From 8ff3dcd271fe9818a19eb25eda87a1e2a8c817a7 Mon Sep 17 00:00:00 2001 From: Silvan Calarco Date: Fri, 5 Jan 2024 22:18:49 +0100 Subject: [PATCH] added patches from Fedora, including pkg-config file fix includes installation directory [release 4.0.0.2496-2mamba;Sun Nov 28 2021] --- firebird-4.0.0.2496-add-pkgconfig-files.patch | 28 + firebird-4.0.0.2496-c++17.patch | 144 + ...-4.0.0.2496-cloop-honour-build-flags.patch | 38 + firebird-4.0.0.2496-no-copy-from-icu.patch | 52 + firebird-4.0.0.2496-noexcept.patch | 664 + firebird-4.0.0.2496-ttmath-abseil-4.0.0.patch | 21255 ++++++++++++++++ firebird.spec | 52 +- 7 files changed, 22223 insertions(+), 10 deletions(-) create mode 100644 firebird-4.0.0.2496-add-pkgconfig-files.patch create mode 100644 firebird-4.0.0.2496-c++17.patch create mode 100644 firebird-4.0.0.2496-cloop-honour-build-flags.patch create mode 100644 firebird-4.0.0.2496-no-copy-from-icu.patch create mode 100644 firebird-4.0.0.2496-noexcept.patch create mode 100644 firebird-4.0.0.2496-ttmath-abseil-4.0.0.patch diff --git a/firebird-4.0.0.2496-add-pkgconfig-files.patch b/firebird-4.0.0.2496-add-pkgconfig-files.patch new file mode 100644 index 0000000..981afe2 --- /dev/null +++ b/firebird-4.0.0.2496-add-pkgconfig-files.patch @@ -0,0 +1,28 @@ +diff --git a/builds/install/arch-specific/linux/misc/fbclient.pc.in b/builds/install/arch-specific/linux/misc/fbclient.pc.in +new file mode 100644 +index 0000000..d49fdc5 +--- /dev/null ++++ b/builds/install/arch-specific/linux/misc/fbclient.pc.in +@@ -0,0 +1,10 @@ ++prefix=@prefix@ ++exec_prefix=@exec_prefix@ ++libdir=@FB_LIBDIR@ ++includedir=@FB_INCDIR@ ++ ++Name: fbclient ++Description: Firebird client library ++Version: @FIREBIRD_VERSION@ ++Cflags: -I${includedir}/firebird ++Libs: -L${libdir} -lfbclient +diff --git a/configure.ac b/configure.ac +index 0a3de36..922c778 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1307,6 +1307,7 @@ case "$PLATFORM" in + gen/install/misc/firebird.init.d.gentoo:builds/install/arch-specific/linux/firebird.init.d.gentoo.in + gen/install/misc/firebird.init.d.slackware:builds/install/arch-specific/linux/firebird.init.d.slackware.in + gen/install/misc/rc.config.firebird:builds/install/arch-specific/linux/rc.config.firebird.in ++ gen/install/misc/fbclient.pc:builds/install/arch-specific/linux/misc/fbclient.pc.in + gen/Release/firebird/bin/linuxLibrary.sh:builds/install/arch-specific/linux/linuxLibrary.sh.in + gen/install/misc/firebird.service:builds/install/arch-specific/linux/firebird.service.in + ], diff --git a/firebird-4.0.0.2496-c++17.patch b/firebird-4.0.0.2496-c++17.patch new file mode 100644 index 0000000..76cd4e2 --- /dev/null +++ b/firebird-4.0.0.2496-c++17.patch @@ -0,0 +1,144 @@ +From ff49d71b0cdbab75f8a22717c4f88343a5961868 Mon Sep 17 00:00:00 2001 +From: Adriano dos Santos Fernandes +Date: Mon, 31 May 2021 08:55:26 -0300 +Subject: [PATCH] Set POSIX build to use C++17. + +--- + CMakeLists.txt | 4 ++-- + builds/posix/make.defaults | 2 +- + builds/posix/prefix.freebsd_amd64 | 2 +- + configure.ac | 2 +- + examples/extauth/Makefile | 2 +- + examples/interfaces/makefile | 2 +- + extern/icu/android/aarch64/config.sh | 2 +- + extern/icu/android/armv7a/config.sh | 4 ++-- + extern/icu/android/linux/config.sh | 2 +- + 9 files changed, 11 insertions(+), 11 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 620fd032af4..5f336efd611 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -206,14 +206,14 @@ if (MINGW) + set(CMAKE_STATIC_LIBRARY_PREFIX) + + add_definitions(-D_WIN32_WINNT=0x0600) +- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4 -std=c++11") ++ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4 -std=c++17") + endif() + + if (UNIX) + set(OS_DIR posix) + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") +- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -msse4 -std=c++11") ++ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -msse4 -std=c++17") + + if (NOT CMAKE_CROSSCOMPILING) + set(LIB_readline readline) +diff --git a/builds/posix/make.defaults b/builds/posix/make.defaults +index d96e89053fa..57bbb006865 100755 +--- a/builds/posix/make.defaults ++++ b/builds/posix/make.defaults +@@ -103,7 +103,7 @@ GLOB_OPTIONS:= + #____________________________________________________________________________ + + # Global c++ flags: firebird needs no RTTI, choose build standard +-PLUSPLUS_FLAGS:= -fno-rtti -std=c++11 ++PLUSPLUS_FLAGS:= -fno-rtti -std=c++17 + + # If this is defined then we use special rules useful for developers only + IsDeveloper = @DEVEL_FLG@ +diff --git a/builds/posix/prefix.freebsd_amd64 b/builds/posix/prefix.freebsd_amd64 +index f27567a2715..0736d87e935 100644 +--- a/builds/posix/prefix.freebsd_amd64 ++++ b/builds/posix/prefix.freebsd_amd64 +@@ -26,4 +26,4 @@ DEV_FLAGS=-ggdb -DFREEBSD -DAMD64 -pipe -MMD -p -fPIC -Wall -Wno-non-virtual-dto + # This file must be compiled with SSE4.2 support + %/CRC32C.o: CXXFLAGS += -msse4 + +-CXXFLAGS := $(CXXFLAGS) -std=c++11 ++CXXFLAGS := $(CXXFLAGS) -std=c++17 +diff --git a/configure.ac b/configure.ac +index 9b40be43101..e4a83cf8d3b 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -899,7 +899,7 @@ dnl if 64-bit mode, then archive tool, ar, needs -X64 option + fi + + XE_SAVE_ENV() +-CXXFLAGS="$CXXFLAGS -std=c++11" ++CXXFLAGS="$CXXFLAGS -std=c++17" + AC_CACHE_CHECK([whether the C++ compiler understands noexcept], [ac_cv_cxx_noexcept], [ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[int f(int x) noexcept { return x + 1; }]], [[]])], + [ac_cv_cxx_noexcept=yes], [ac_cv_cxx_noexcept=no])]) +diff --git a/examples/extauth/Makefile b/examples/extauth/Makefile +index 9da7bbd357f..3c8b878d225 100644 +--- a/examples/extauth/Makefile ++++ b/examples/extauth/Makefile +@@ -61,7 +61,7 @@ KEYGEN_objects=$(INTERMED)/keygen.o + TCWRAP_objects=$(INTERMED)/TcWrapper.o + KEY_AUTH_objects=$(INTERMED)/ExtAuth.o + +-CXXFLAGS=-std=c++11 -pthread -I$(ROOT)/include -fPIC $(TOMCRYPT_COMPILE) ++CXXFLAGS=-std=c++17 -pthread -I$(ROOT)/include -fPIC $(TOMCRYPT_COMPILE) + LDFLAGS=-pthread -L$(LIB) -Wl,-rpath,'$$ORIGIN/../lib' $(TOMCRYPT_LINK) + + LINK_LIBS=-lfbclient -ltomcrypt -ltommath +diff --git a/examples/interfaces/makefile b/examples/interfaces/makefile +index 153c3d558dc..b65dba90a7d 100644 +--- a/examples/interfaces/makefile ++++ b/examples/interfaces/makefile +@@ -33,7 +33,7 @@ FBCLIENT = $(FIREBIRD)/lib/libfbclient.so + # General Compiler and linker Defines for Linux + # --------------------------------------------------------------------- + CXX = c++ +-CXXFLAGS= -c -Wall -g3 -std=c++11 -fno-rtti $(INCLUDE) ++CXXFLAGS= -c -Wall -g3 -std=c++17 -fno-rtti $(INCLUDE) + RM = rm -f + + # +diff --git a/extern/icu/android/aarch64/config.sh b/extern/icu/android/aarch64/config.sh +index 51ef623a3c5..f464d930ec2 100755 +--- a/extern/icu/android/aarch64/config.sh ++++ b/extern/icu/android/aarch64/config.sh +@@ -18,7 +18,7 @@ + --enable-dyload \ + --with-cross-build=$CROSS_BUILD_DIR \ + CFLAGS='-Os' \ +- CXXFLAGS='--std=c++11' \ ++ CXXFLAGS='--std=c++17' \ + LDFLAGS='-static-libstdc++' \ + CC=aarch64-linux-android24-clang \ + CXX=aarch64-linux-android24-clang++ \ +diff --git a/extern/icu/android/armv7a/config.sh b/extern/icu/android/armv7a/config.sh +index fe1bd037456..0e458c690e7 100755 +--- a/extern/icu/android/armv7a/config.sh ++++ b/extern/icu/android/armv7a/config.sh +@@ -18,10 +18,10 @@ + --enable-dyload \ + --with-cross-build=$CROSS_BUILD_DIR \ + CFLAGS='-Os -march=armv7-a -mfloat-abi=softfp -mfpu=neon' \ +- CXXFLAGS='--std=c++11 -march=armv7-a -mfloat-abi=softfp -mfpu=neon' \ ++ CXXFLAGS='--std=c++17 -march=armv7-a -mfloat-abi=softfp -mfpu=neon' \ + LDFLAGS='-static-libstdc++ -march=armv7-a -Wl,--fix-cortex-a8' \ + CC=arm-linux-androideabi-clang \ + CXX=arm-linux-androideabi-clang++ \ + AR=arm-linux-androideabi-ar \ + RANLIB=arm-linux-androideabi-ranlib \ +- --with-data-packaging=archive +\ No newline at end of file ++ --with-data-packaging=archive +diff --git a/extern/icu/android/linux/config.sh b/extern/icu/android/linux/config.sh +index a8b56024aae..6e7d9c5f5c8 100755 +--- a/extern/icu/android/linux/config.sh ++++ b/extern/icu/android/linux/config.sh +@@ -1,7 +1,7 @@ + #!/bin/sh + ../source/runConfigureICU Linux --prefix=$PWD/prebuilt \ + CFLAGS="-Os" \ +- CXXFLAGS="--std=c++11" \ ++ CXXFLAGS="--std=c++17" \ + --enable-static \ + --enable-shared=no \ + --enable-extras=no \ diff --git a/firebird-4.0.0.2496-cloop-honour-build-flags.patch b/firebird-4.0.0.2496-cloop-honour-build-flags.patch new file mode 100644 index 0000000..b854300 --- /dev/null +++ b/firebird-4.0.0.2496-cloop-honour-build-flags.patch @@ -0,0 +1,38 @@ +diff --git a/extern/cloop/Makefile b/extern/cloop/Makefile +index 08516c2..1573dc2 100644 +--- a/extern/cloop/Makefile ++++ b/extern/cloop/Makefile +@@ -6,7 +6,7 @@ TARGET := release + + CC := $(CC) + CXX := $(CXX) +-LD := $(CXX) ++LD := $(CXX) $(LDFLAGS) + + SRC_DIR := src + BUILD_DIR := build +@@ -27,8 +27,9 @@ SRCS_CPP := $(foreach sdir,$(SRC_DIRS),$(wildcard $(sdir)/*.cpp)) + OBJS_C := $(patsubst $(SRC_DIR)/%.c,$(OBJ_DIR)/%.o,$(SRCS_C)) + OBJS_CPP := $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(SRCS_CPP)) + +-C_FLAGS := -ggdb -fPIC -MMD -MP -W -Wall -Wno-unused-parameter +-CXX_FLAGS := $(C_FLAGS) ++COMMON_C_FLAGS := -ggdb -fPIC -MMD -MP -W -Wall -Wno-unused-parameter ++C_FLAGS := $(COMMON_C_FLAGS) $(CFLAGS) $(CPPFLAGS) ++CXX_FLAGS := $(COMMON_C_FLAGS) $(CXXFLAGS) $(CPPFLAGS) + FPC_FLAGS := -Mdelphi + + ifeq ($(shell uname),FreeBSD) +diff --git a/extern/btyacc/Makefile b/extern/btyacc/Makefile +index f432965..52d8443 100644 +--- a/extern/btyacc/Makefile ++++ b/extern/btyacc/Makefile +@@ -12,7 +12,7 @@ HDRS = defs.h mstring.h + # across all of our supported compilers/platforms. + + # Vanilla CFLAGS +-CFLAGS= ++CFLAGS=-fPIE + + # No LDFLAGS + #LDFLAGS= diff --git a/firebird-4.0.0.2496-no-copy-from-icu.patch b/firebird-4.0.0.2496-no-copy-from-icu.patch new file mode 100644 index 0000000..7f84e0b --- /dev/null +++ b/firebird-4.0.0.2496-no-copy-from-icu.patch @@ -0,0 +1,52 @@ +diff --git a/builds/posix/Makefile.in b/builds/posix/Makefile.in +index bb4ceb1..87e75a2 100644 +--- a/builds/posix/Makefile.in ++++ b/builds/posix/Makefile.in +@@ -534,7 +534,7 @@ $(GSTAT): $(GSTAT_Objects) $(COMMON_LIB) + isql: $(ISQL) + + $(ISQL): $(ISQL_Objects) $(COMMON_LIB) +- $(EXE_LINK) $(EXE_LINK_OPTIONS) $^ -o $@ $(FIREBIRD_LIBRARY_LINK) $(LIBEDITLINE) $(TERMLIB) $(LINK_LIBS) $(call LINK_DARWIN_RPATH,..) ++ $(EXE_LINK) $(EXE_LINK_OPTIONS) $^ -o $@ $(FIREBIRD_LIBRARY_LINK) $(LIBEDITLINE) $(TERMLIB) $(LINK_LIBS) $(ICU_LIBS) $(call LINK_DARWIN_RPATH,..) + + nbackup: $(NBACKUP) + +diff --git a/src/isql/isql.epp b/src/isql/isql.epp +index 79da1f7..4554252 100644 +--- a/src/isql/isql.epp ++++ b/src/isql/isql.epp +@@ -173,34 +173,6 @@ const char* UNKNOWN = "*unknown*"; + + namespace IcuUtil + { +- // Duplicate from ICU to not need to link ISQL with it. It's used by U8_NEXT_UNSAFE. +- static const uint8_t utf8_countTrailBytes[256] = { +- 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, +- 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, +- +- 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, +- 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, +- +- 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, +- 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, +- +- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +- +- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, +- 3, 3, 3, 3, 3, +- 3, 3, 3, /* illegal in Unicode */ +- 4, 4, 4, 4, /* illegal in Unicode */ +- 5, 5, /* illegal in Unicode */ +- 0, 0 /* illegal bytes 0xfe and 0xff */ +- }; +- + // Return the number of characters of a string. + static unsigned charLength(SSHORT charset, unsigned len, const char* str) + { diff --git a/firebird-4.0.0.2496-noexcept.patch b/firebird-4.0.0.2496-noexcept.patch new file mode 100644 index 0000000..f1a1f48 --- /dev/null +++ b/firebird-4.0.0.2496-noexcept.patch @@ -0,0 +1,664 @@ +From a999f35f0fad27798fdc88a3f5cdf2e3e9041594 Mon Sep 17 00:00:00 2001 +From: Adriano dos Santos Fernandes +Date: Mon, 31 May 2021 08:55:26 -0300 +Subject: [PATCH] Replace FB_NOTHROW by noexcept and remove FB_THROW. + +--- + src/common/classes/alloc.cpp | 128 +++++++++++++++++------------------ + src/common/classes/alloc.h | 74 ++++++++------------ + 2 files changed, 94 insertions(+), 108 deletions(-) + +diff --git a/src/common/classes/alloc.cpp b/src/common/classes/alloc.cpp +index 1bd6ad4f09d..ee91ab89df8 100644 +--- a/src/common/classes/alloc.cpp ++++ b/src/common/classes/alloc.cpp +@@ -68,19 +68,19 @@ + #define VALGRIND_FIX_IT // overrides suspicious valgrind behavior + #endif // USE_VALGRIND + +-void* operator new(size_t s ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) ++void* operator new(size_t s ALLOC_PARAMS) + { + return MemoryPool::globalAlloc(s ALLOC_PASS_ARGS); + } +-void* operator new[](size_t s ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) ++void* operator new[](size_t s ALLOC_PARAMS) + { + return MemoryPool::globalAlloc(s ALLOC_PASS_ARGS); + } +-void operator delete(void* mem ALLOC_PARAMS) FB_NOTHROW ++void operator delete(void* mem ALLOC_PARAMS) noexcept + { + MemoryPool::globalFree(mem); + } +-void operator delete[](void* mem ALLOC_PARAMS) FB_NOTHROW ++void operator delete[](void* mem ALLOC_PARAMS) noexcept + { + MemoryPool::globalFree(mem); + } +@@ -109,7 +109,7 @@ static const int GUARD_BYTES = 0; + #endif + + template +-T absVal(T n) FB_NOTHROW ++T absVal(T n) noexcept + { + return n < 0 ? -n : n; + } +@@ -160,7 +160,7 @@ struct FailedBlock + FailedBlock* failedList = NULL; + #endif + +-void corrupt(const char* text) FB_NOTHROW ++void corrupt(const char* text) noexcept + { + #ifdef DEV_BUILD + fprintf(stderr, "%s\n", text); +@@ -377,7 +377,7 @@ class MemHeader + + #ifdef MEM_DEBUG + void print_contents(bool used, FILE* file, bool used_only, +- const char* filter_path, const size_t filter_len) FB_NOTHROW ++ const char* filter_path, const size_t filter_len) noexcept + { + if (used || !used_only) + { +@@ -406,7 +406,7 @@ class MemHeader + } + #endif + +- void validate(MemPool* p, StatInt& vUse) FB_NOTHROW ++ void validate(MemPool* p, StatInt& vUse) noexcept + { + if (p == pool && !isExtent()) + vUse += getSize(); +@@ -461,7 +461,7 @@ class MemBaseHunk + } + + public: +- void validate(MemPool* pool, size_t hdr, StatInt& vMap, StatInt& vUse) FB_NOTHROW ++ void validate(MemPool* pool, size_t hdr, StatInt& vMap, StatInt& vUse) noexcept + { + if (length >= DEFAULT_ALLOCATION) + { +@@ -526,7 +526,7 @@ class MemSmallHunk : public MemBaseHunk + + #ifdef MEM_DEBUG + void print_contents(FILE* file, MemPool* pool, bool used_only, +- const char* filter_path, const size_t filter_len) FB_NOTHROW ++ const char* filter_path, const size_t filter_len) noexcept + { + UCHAR* m = ((UCHAR*) this) + hdrSize(); + fprintf(file, "Small hunk %p: memory=[%p:%p) spaceRemaining=%" SIZEFORMAT " length=%" SIZEFORMAT "\n", +@@ -598,7 +598,7 @@ class MemMediumHunk : public MemBaseHunk + + #ifdef MEM_DEBUG + void print_contents(FILE* file, MemPool* pool, bool used_only, +- const char* filter_path, const size_t filter_len) FB_NOTHROW ++ const char* filter_path, const size_t filter_len) noexcept + { + UCHAR* m = ((UCHAR*) this) + hdrSize(); + fprintf(file, "Medium hunk %p: memory=[%p:%p) spaceRemaining=%" SIZEFORMAT " length=%" SIZEFORMAT "\n", +@@ -630,7 +630,7 @@ class MemBigHunk + + #ifdef MEM_DEBUG + void print_contents(FILE* file, MemPool* pool, bool used_only, +- const char* filter_path, const size_t filter_len) FB_NOTHROW ++ const char* filter_path, const size_t filter_len) noexcept + { + fprintf(file, "Big hunk %p: memory=%p length=%" SIZEFORMAT "\n", + this, block, length); +@@ -1647,7 +1647,7 @@ class FreeObjects + + ~FreeObjects(); + +- FreeObjPtr allocateBlock(MemPool* pool, size_t from, size_t& size) FB_THROW (OOM_EXCEPTION) ++ FreeObjPtr allocateBlock(MemPool* pool, size_t from, size_t& size) + { + size_t full_size = size + (from ? 0 : ListBuilder::MEM_OVERHEAD); + if (full_size > Limits::TOP_LIMIT) +@@ -1696,7 +1696,7 @@ class FreeObjects + + #ifdef MEM_DEBUG + void print_contents(FILE* file, MemPool* pool, bool used_only, +- const char* filter_path, const size_t filter_len) FB_NOTHROW ++ const char* filter_path, const size_t filter_len) noexcept + { + for (Extent* ext = currentExtent; ext; ext = ext->next) + ext->print_contents(file, pool, used_only, filter_path, filter_len); +@@ -1717,7 +1717,7 @@ class FreeObjects + ListBuilder listBuilder; + Extent* currentExtent; + +- MemBlock* newBlock(MemPool* pool, unsigned slot) FB_THROW (OOM_EXCEPTION); ++ MemBlock* newBlock(MemPool* pool, unsigned slot); + }; + + +@@ -1799,26 +1799,26 @@ class MemPool + }; + #endif // VALIDATE_POOL + +- MemBlock* alloc(size_t from, size_t& length, bool flagRedirect) FB_THROW (OOM_EXCEPTION); +- void releaseBlock(MemBlock *block, bool flagDecr) FB_NOTHROW; ++ MemBlock* alloc(size_t from, size_t& length, bool flagRedirect); ++ void releaseBlock(MemBlock *block, bool flagDecr) noexcept; + + public: +- void* allocate(size_t size ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION); +- MemBlock* allocate2(size_t from, size_t& size ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION); ++ void* allocate(size_t size ALLOC_PARAMS); ++ MemBlock* allocate2(size_t from, size_t& size ALLOC_PARAMS); + + private: +- virtual void memoryIsExhausted(void) FB_THROW (OOM_EXCEPTION); +- void* allocRaw(size_t length) FB_THROW (OOM_EXCEPTION); +- static void releaseMemory(void* block, bool flagExtent) FB_NOTHROW; +- static void releaseRaw(bool destroying, void *block, size_t size, bool use_cache = true) FB_NOTHROW; +- void* getExtent(size_t from, size_t& to) FB_THROW (OOM_EXCEPTION); ++ virtual void memoryIsExhausted(void); ++ void* allocRaw(size_t length); ++ static void releaseMemory(void* block, bool flagExtent) noexcept; ++ static void releaseRaw(bool destroying, void *block, size_t size, bool use_cache = true) noexcept; ++ void* getExtent(size_t from, size_t& to); + + public: +- static void releaseExtent(bool destroying, void *block, size_t size, MemPool* pool) FB_NOTHROW; ++ static void releaseExtent(bool destroying, void *block, size_t size, MemPool* pool) noexcept; + + // pass desired size, return actual extent size + template +- void newExtent(size_t& size, Extent** linkedList) FB_THROW (OOM_EXCEPTION); ++ void newExtent(size_t& size, Extent** linkedList); + + private: + #ifdef USE_VALGRIND +@@ -1830,9 +1830,9 @@ class MemPool + + public: + static void deletePool(MemPool* pool); +- static void globalFree(void* block) FB_NOTHROW; ++ static void globalFree(void* block) noexcept; + +- static void deallocate(void* block) FB_NOTHROW; ++ static void deallocate(void* block) noexcept; + bool validate(char* buf, FB_SIZE_T size); + + // Create memory pool instance +@@ -1840,7 +1840,7 @@ class MemPool + + // Set statistics group for pool. Usage counters will be decremented from + // previously set group and added to new +- void setStatsGroup(MemoryStats& stats) FB_NOTHROW; ++ void setStatsGroup(MemoryStats& stats) noexcept; + + // Initialize and finalize global memory pool + static MemPool* init() +@@ -1893,25 +1893,25 @@ class MemPool + } + + // Statistics +- void increment_usage(size_t size) FB_NOTHROW ++ void increment_usage(size_t size) noexcept + { + stats->increment_usage(size); + used_memory += size; + } + +- void decrement_usage(size_t size) FB_NOTHROW ++ void decrement_usage(size_t size) noexcept + { + stats->decrement_usage(size); + used_memory -= size; + } + +- void increment_mapping(size_t size) FB_NOTHROW ++ void increment_mapping(size_t size) noexcept + { + stats->increment_mapping(size); + mapped_memory += size; + } + +- void decrement_mapping(size_t size) FB_NOTHROW ++ void decrement_mapping(size_t size) noexcept + { + stats->decrement_mapping(size); + mapped_memory -= size; +@@ -1919,9 +1919,9 @@ class MemPool + + #ifdef MEM_DEBUG + // Print out pool contents. This is debugging routine +- void print_contents(FILE*, unsigned flags, const char* filter_path) FB_NOTHROW; ++ void print_contents(FILE*, unsigned flags, const char* filter_path) noexcept; + // The same routine, but more easily callable from the debugger +- void print_contents(const char* filename, unsigned flags, const char* filter_path) FB_NOTHROW; ++ void print_contents(const char* filename, unsigned flags, const char* filter_path) noexcept; + + private: + MemPool* next; +@@ -1961,7 +1961,7 @@ void DoubleLinkedList::decrUsage(MemMediumHunk* hunk, MemPool* pool) + + + template +-MemBlock* FreeObjects::newBlock(MemPool* pool, unsigned slot) FB_THROW (OOM_EXCEPTION) ++MemBlock* FreeObjects::newBlock(MemPool* pool, unsigned slot) + { + size_t size = Limits::getSize(slot); + +@@ -2170,7 +2170,7 @@ MemPool::~MemPool(void) + } + + template +-void MemPool::newExtent(size_t& size, Extent** linkedList) FB_THROW(OOM_EXCEPTION) ++void MemPool::newExtent(size_t& size, Extent** linkedList) + { + // No large enough block found. We need to extend the pool + void* memory = NULL; +@@ -2214,7 +2214,7 @@ MemoryPool* MemoryPool::createPool(MemoryPool* parentPool, MemoryStats& stats) + return FB_NEW_POOL(*parentPool) MemoryPool(p); + } + +-void MemPool::setStatsGroup(MemoryStats& newStats) FB_NOTHROW ++void MemPool::setStatsGroup(MemoryStats& newStats) noexcept + { + MutexLockGuard guard(mutex, "MemPool::setStatsGroup"); + +@@ -2230,12 +2230,12 @@ void MemPool::setStatsGroup(MemoryStats& newStats) FB_NOTHROW + stats->increment_usage(sav_used_memory); + } + +-void MemoryPool::setStatsGroup(MemoryStats& newStats) FB_NOTHROW ++void MemoryPool::setStatsGroup(MemoryStats& newStats) noexcept + { + pool->setStatsGroup(newStats); + } + +-MemBlock* MemPool::alloc(size_t from, size_t& length, bool flagRedirect) FB_THROW (OOM_EXCEPTION) ++MemBlock* MemPool::alloc(size_t from, size_t& length, bool flagRedirect) + { + MutexEnsureUnlock guard(mutex, "MemPool::alloc"); + guard.enter(); +@@ -2294,7 +2294,7 @@ MemBlock* MemPool::allocate2(size_t from, size_t& size + #ifdef DEBUG_GDS_ALLOC + , const char* fileName, int line + #endif +-) FB_THROW (OOM_EXCEPTION) ++) + { + size_t length = from ? size : ROUNDUP(size + VALGRIND_REDZONE, roundingSize) + GUARD_BYTES; + MemBlock* memory = alloc(from, length, true); +@@ -2324,7 +2324,7 @@ MemBlock* MemPool::allocate2(size_t from, size_t& size + } + + +-void* MemPool::allocate(size_t size ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) ++void* MemPool::allocate(size_t size ALLOC_PARAMS) + { + #ifdef VALIDATE_POOL + MutexLockGuard guard(mutex, "MemPool::allocate"); +@@ -2339,7 +2339,7 @@ void* MemPool::allocate(size_t size ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) + } + + +-void MemPool::releaseMemory(void* object, bool flagExtent) FB_NOTHROW ++void MemPool::releaseMemory(void* object, bool flagExtent) noexcept + { + if (object) + { +@@ -2403,7 +2403,7 @@ void MemPool::releaseMemory(void* object, bool flagExtent) FB_NOTHROW + } + } + +-void MemPool::releaseBlock(MemBlock* block, bool decrUsage) FB_NOTHROW ++void MemPool::releaseBlock(MemBlock* block, bool decrUsage) noexcept + { + if (block->pool != this) + corrupt("bad block released"); +@@ -2464,12 +2464,12 @@ void MemPool::releaseBlock(MemBlock* block, bool decrUsage) FB_NOTHROW + releaseRaw(pool_destroying, hunk, hunk->length, false); + } + +-void MemPool::memoryIsExhausted(void) FB_THROW (OOM_EXCEPTION) ++void MemPool::memoryIsExhausted(void) + { + Firebird::BadAlloc::raise(); + } + +-void* MemPool::allocRaw(size_t size) FB_THROW (OOM_EXCEPTION) ++void* MemPool::allocRaw(size_t size) + { + #ifndef USE_VALGRIND + if (size == DEFAULT_ALLOCATION) +@@ -2549,7 +2549,7 @@ void* MemPool::allocRaw(size_t size) FB_THROW (OOM_EXCEPTION) + } + + +-void* MemPool::getExtent(size_t from, size_t& to) FB_THROW(OOM_EXCEPTION) // pass desired minimum size, return actual extent size ++void* MemPool::getExtent(size_t from, size_t& to) // pass desired minimum size, return actual extent size + { + #ifdef VALIDATE_POOL + MutexLockGuard guard(mutex, "MemPool::getExtent"); +@@ -2560,7 +2560,7 @@ void* MemPool::getExtent(size_t from, size_t& to) FB_THROW(OOM_EXCEPTION) // pa + } + + +-void MemPool::releaseExtent(bool destroying, void* block, size_t size, MemPool* pool) FB_NOTHROW ++void MemPool::releaseExtent(bool destroying, void* block, size_t size, MemPool* pool) noexcept + { + if (size < DEFAULT_ALLOCATION) + releaseMemory(block, true); +@@ -2573,7 +2573,7 @@ void MemPool::releaseExtent(bool destroying, void* block, size_t size, MemPool* + } + + +-void MemPool::releaseRaw(bool destroying, void* block, size_t size, bool use_cache) FB_NOTHROW ++void MemPool::releaseRaw(bool destroying, void* block, size_t size, bool use_cache) noexcept + { + #ifndef USE_VALGRIND + if (use_cache && (size == DEFAULT_ALLOCATION)) +@@ -2666,19 +2666,19 @@ void MemPool::releaseRaw(bool destroying, void* block, size_t size, bool use_cac + } + } + +-void MemPool::globalFree(void* block) FB_NOTHROW ++void MemPool::globalFree(void* block) noexcept + { + deallocate(block); + } + +-void* MemoryPool::calloc(size_t size ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) ++void* MemoryPool::calloc(size_t size ALLOC_PARAMS) + { + void* block = allocate(size ALLOC_PASS_ARGS); + memset(block, 0, size); + return block; + } + +-void MemPool::deallocate(void* block) FB_NOTHROW ++void MemPool::deallocate(void* block) noexcept + { + releaseMemory(block, false); + } +@@ -2720,7 +2720,7 @@ bool MemPool::validate(char* buf, FB_SIZE_T size) + } + + #ifdef MEM_DEBUG +-void MemPool::print_contents(const char* filename, unsigned flags, const char* filter_path) FB_NOTHROW ++void MemPool::print_contents(const char* filename, unsigned flags, const char* filter_path) noexcept + { + FILE* out = os_utils::fopen(filename, "w"); + if (!out) +@@ -2731,7 +2731,7 @@ void MemPool::print_contents(const char* filename, unsigned flags, const char* f + } + + // This member function can't be const because there are calls to the mutex. +-void MemPool::print_contents(FILE* file, unsigned flags, const char* filter_path) FB_NOTHROW ++void MemPool::print_contents(FILE* file, unsigned flags, const char* filter_path) noexcept + { + bool used_only = flags & MemoryPool::PRINT_USED_ONLY; + +@@ -2818,7 +2818,7 @@ MemoryPool& AutoStorage::getAutoMemoryPool() + } + + #ifdef LIBC_CALLS_NEW +-void* MemoryPool::globalAlloc(size_t s ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) ++void* MemoryPool::globalAlloc(size_t s ALLOC_PARAMS) + { + if (!defaultMemoryManager) + { +@@ -2831,17 +2831,17 @@ void* MemoryPool::globalAlloc(size_t s ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) + } + #endif // LIBC_CALLS_NEW + +-void MemoryPool::globalFree(void* block) FB_NOTHROW ++void MemoryPool::globalFree(void* block) noexcept + { + MemPool::globalFree(block); + } + +-void* MemoryPool::allocate(size_t size ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) ++void* MemoryPool::allocate(size_t size ALLOC_PARAMS) + { + return pool->allocate(size ALLOC_PASS_ARGS); + } + +-void MemoryPool::deallocate(void* block) FB_NOTHROW ++void MemoryPool::deallocate(void* block) noexcept + { + pool->deallocate(block); + } +@@ -2870,14 +2870,14 @@ void MemoryPool::deletePool(MemoryPool* pool) + delete pool; + } + +-void MemoryPool::print_contents(FILE* file, unsigned flags, const char* filter_path) FB_NOTHROW ++void MemoryPool::print_contents(FILE* file, unsigned flags, const char* filter_path) noexcept + { + #ifdef MEM_DEBUG + pool->print_contents(file, flags, filter_path); + #endif + } + +-void MemoryPool::print_contents(const char* filename, unsigned flags, const char* filter_path) FB_NOTHROW ++void MemoryPool::print_contents(const char* filename, unsigned flags, const char* filter_path) noexcept + { + #ifdef MEM_DEBUG + pool->print_contents(filename, flags, filter_path); +@@ -2950,21 +2950,21 @@ void AutoStorage::ProbeStack() const + // in a case when we actually need "new" only with file/line information + // this version should be also present as a pair for "delete". + #ifdef DEBUG_GDS_ALLOC +-void* operator new(size_t s) FB_THROW (OOM_EXCEPTION) ++void* operator new(size_t s) + { + return MemoryPool::globalAlloc(s ALLOC_ARGS); + } +-void* operator new[](size_t s) FB_THROW (OOM_EXCEPTION) ++void* operator new[](size_t s) + { + return MemoryPool::globalAlloc(s ALLOC_ARGS); + } + +-void operator delete(void* mem) FB_NOTHROW ++void operator delete(void* mem) noexcept + { + MemoryPool::globalFree(mem); + } + +-void operator delete[](void* mem) FB_NOTHROW ++void operator delete[](void* mem) noexcept + { + MemoryPool::globalFree(mem); + } +diff --git a/src/common/classes/alloc.h b/src/common/classes/alloc.h +index 65f9afbb8a9..44d9e0ea462 100644 +--- a/src/common/classes/alloc.h ++++ b/src/common/classes/alloc.h +@@ -58,20 +58,6 @@ + + #include + +-#define OOM_EXCEPTION std::bad_alloc +- +-#if __cplusplus >= 201103L +-#define FB_NO_THROW_SPECIFIER +-#endif +- +-#ifdef FB_NO_THROW_SPECIFIER +-#define FB_THROW(x) +-#define FB_NOTHROW noexcept +-#else +-#define FB_THROW(x) throw(x) +-#define FB_NOTHROW throw() +-#endif +- + #ifdef DEBUG_GDS_ALLOC + #define FB_NEW new(__FILE__, __LINE__) + #define FB_NEW_POOL(pool) new(pool, __FILE__, __LINE__) +@@ -106,10 +92,10 @@ class MemoryStats + ~MemoryStats() + {} + +- size_t getCurrentUsage() const FB_NOTHROW { return mst_usage.value(); } +- size_t getMaximumUsage() const FB_NOTHROW { return mst_max_usage; } +- size_t getCurrentMapping() const FB_NOTHROW { return mst_mapped.value(); } +- size_t getMaximumMapping() const FB_NOTHROW { return mst_max_mapped; } ++ size_t getCurrentUsage() const noexcept { return mst_usage.value(); } ++ size_t getMaximumUsage() const noexcept { return mst_max_usage; } ++ size_t getCurrentMapping() const noexcept { return mst_mapped.value(); } ++ size_t getMaximumMapping() const noexcept { return mst_max_mapped; } + + private: + // Forbid copying/assignment +@@ -131,7 +117,7 @@ class MemoryStats + size_t mst_max_mapped; + + // These methods are thread-safe due to usage of atomic counters only +- void increment_usage(size_t size) FB_NOTHROW ++ void increment_usage(size_t size) noexcept + { + for (MemoryStats* statistics = this; statistics; statistics = statistics->mst_parent) + { +@@ -141,7 +127,7 @@ class MemoryStats + } + } + +- void decrement_usage(size_t size) FB_NOTHROW ++ void decrement_usage(size_t size) noexcept + { + for (MemoryStats* statistics = this; statistics; statistics = statistics->mst_parent) + { +@@ -149,7 +135,7 @@ class MemoryStats + } + } + +- void increment_mapping(size_t size) FB_NOTHROW ++ void increment_mapping(size_t size) noexcept + { + for (MemoryStats* statistics = this; statistics; statistics = statistics->mst_parent) + { +@@ -159,7 +145,7 @@ class MemoryStats + } + } + +- void decrement_mapping(size_t size) FB_NOTHROW ++ void decrement_mapping(size_t size) noexcept + { + for (MemoryStats* statistics = this; statistics; statistics = statistics->mst_parent) + { +@@ -205,21 +191,21 @@ class MemoryPool + #define ALLOC_PASS_ARGS + #endif // DEBUG_GDS_ALLOC + +- void* calloc(size_t size ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION); ++ void* calloc(size_t size ALLOC_PARAMS); + + #ifdef LIBC_CALLS_NEW +- static void* globalAlloc(size_t s ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION); ++ static void* globalAlloc(size_t s ALLOC_PARAMS); + #else +- static void* globalAlloc(size_t s ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) ++ static void* globalAlloc(size_t s ALLOC_PARAMS) + { + return defaultMemoryManager->allocate(s ALLOC_PASS_ARGS); + } + #endif // LIBC_CALLS_NEW + +- void* allocate(size_t size ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION); ++ void* allocate(size_t size ALLOC_PARAMS); + +- static void globalFree(void* mem) FB_NOTHROW; +- void deallocate(void* mem) FB_NOTHROW; ++ static void globalFree(void* mem) noexcept; ++ void deallocate(void* mem) noexcept; + + // Set context pool for current thread of execution + static MemoryPool* setContextPool(MemoryPool* newPool); +@@ -229,7 +215,7 @@ class MemoryPool + + // Set statistics group for pool. Usage counters will be decremented from + // previously set group and added to new +- void setStatsGroup(MemoryStats& stats) FB_NOTHROW; ++ void setStatsGroup(MemoryStats& stats) noexcept; + + // Initialize and finalize global memory pool + static void init(); +@@ -241,9 +227,9 @@ class MemoryPool + // Print out pool contents. This is debugging routine + static const unsigned PRINT_USED_ONLY = 0x01; + static const unsigned PRINT_RECURSIVE = 0x02; +- void print_contents(FILE*, unsigned flags = 0, const char* filter_path = 0) FB_NOTHROW; ++ void print_contents(FILE*, unsigned flags = 0, const char* filter_path = 0) noexcept; + // The same routine, but more easily callable from the debugger +- void print_contents(const char* filename, unsigned flags = 0, const char* filter_path = 0) FB_NOTHROW; ++ void print_contents(const char* filename, unsigned flags = 0, const char* filter_path = 0) noexcept; + + public: + struct Finalizer +@@ -298,7 +284,7 @@ class MemoryPool + + } // namespace Firebird + +-static inline Firebird::MemoryPool* getDefaultMemoryPool() FB_NOTHROW ++static inline Firebird::MemoryPool* getDefaultMemoryPool() noexcept + { + fb_assert(Firebird::MemoryPool::defaultMemoryManager); + return Firebird::MemoryPool::defaultMemoryManager; +@@ -355,36 +341,36 @@ class SubsystemContextPoolHolder : public ContextPoolHolder + using Firebird::MemoryPool; + + // operators new and delete +-extern void* operator new(size_t s ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION); +-extern void* operator new[](size_t s ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION); +-extern void operator delete(void* mem ALLOC_PARAMS) FB_NOTHROW; +-extern void operator delete[](void* mem ALLOC_PARAMS) FB_NOTHROW; ++extern void* operator new(size_t s ALLOC_PARAMS); ++extern void* operator new[](size_t s ALLOC_PARAMS); ++extern void operator delete(void* mem ALLOC_PARAMS) noexcept; ++extern void operator delete[](void* mem ALLOC_PARAMS) noexcept; + + +-inline void* operator new(size_t s, Firebird::MemoryPool& pool ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) ++inline void* operator new(size_t s, Firebird::MemoryPool& pool ALLOC_PARAMS) + { + return pool.allocate(s ALLOC_PASS_ARGS); + } +-inline void* operator new[](size_t s, Firebird::MemoryPool& pool ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) ++inline void* operator new[](size_t s, Firebird::MemoryPool& pool ALLOC_PARAMS) + { + return pool.allocate(s ALLOC_PASS_ARGS); + } + +-inline void operator delete(void* mem, Firebird::MemoryPool& pool ALLOC_PARAMS) FB_NOTHROW ++inline void operator delete(void* mem, Firebird::MemoryPool& pool ALLOC_PARAMS) noexcept + { + MemoryPool::globalFree(mem); + } +-inline void operator delete[](void* mem, Firebird::MemoryPool& pool ALLOC_PARAMS) FB_NOTHROW ++inline void operator delete[](void* mem, Firebird::MemoryPool& pool ALLOC_PARAMS) noexcept + { + MemoryPool::globalFree(mem); + } + + #if __cplusplus >= 201402L +-inline void operator delete(void* mem, std::size_t s ALLOC_PARAMS) FB_NOTHROW ++inline void operator delete(void* mem, std::size_t s ALLOC_PARAMS) noexcept + { + MemoryPool::globalFree(mem); + } +-inline void operator delete[](void* mem, std::size_t s ALLOC_PARAMS) FB_NOTHROW ++inline void operator delete[](void* mem, std::size_t s ALLOC_PARAMS) noexcept + { + MemoryPool::globalFree(mem); + } +@@ -392,8 +378,8 @@ inline void operator delete[](void* mem, std::size_t s ALLOC_PARAMS) FB_NOTHROW + + #ifdef DEBUG_GDS_ALLOC + +-extern void operator delete(void* mem) FB_NOTHROW; +-extern void operator delete[](void* mem) FB_NOTHROW; ++extern void operator delete(void* mem) noexcept; ++extern void operator delete[](void* mem) noexcept; + + #endif // DEBUG_GDS_ALLOC + diff --git a/firebird-4.0.0.2496-ttmath-abseil-4.0.0.patch b/firebird-4.0.0.2496-ttmath-abseil-4.0.0.patch new file mode 100644 index 0000000..ee98e95 --- /dev/null +++ b/firebird-4.0.0.2496-ttmath-abseil-4.0.0.patch @@ -0,0 +1,21255 @@ +diff --git a/builds/posix/Makefile.in b/builds/posix/Makefile.in +index bb4ceb12fb..dcd2b173ae 100644 +--- a/builds/posix/Makefile.in ++++ b/builds/posix/Makefile.in +@@ -170,6 +170,9 @@ external: + $(MAKE) -C $(ROOT)/extern/decNumber + ln -sf $(ROOT)/extern/decNumber/libdecFloat.a $(LIB) + ++ $(MAKE) -C $(ROOT)/extern/int128/absl/numeric ++ ln -sf $(ROOT)/extern/int128/absl/numeric/libi128.a $(LIB) ++ + CXXFLAGS="-O3 -g -fPIC" $(MAKE) -C $(ROOT)/extern/re2 + ln -sf $(ROOT)/extern/re2/obj/libre2.a $(LIB) + +@@ -328,6 +331,8 @@ cross2: + $(MAKE) re2 + $(MAKE) -C $(ROOT)/extern/decNumber + ln -sf $(ROOT)/extern/decNumber/libdecFloat$(CROSS).a $(LIB) ++ $(MAKE) -C $(ROOT)/extern/int128/absl/numeric ++ ln -sf $(ROOT)/extern/int128/absl/numeric/libi128$(CROSS).a $(LIB) + $(MAKE) yvalve + $(MAKE) engine + $(MAKE) fbintl +@@ -738,12 +743,12 @@ install install-embedded silent_install package packages dist: + # + .PHONY: clean clean_objects clean_dependancies clean_extern_objects clean_build \ + clean_gpre_gen clean_icu clean_dbs clean_examples clean_makefiles \ +- clean_editline clean_all clean_decfloat clean_vers clean_misc ++ clean_editline clean_all clean_decfloat clean_int128 clean_vers clean_misc + + + clean: clean_objects clean_dependancies clean_extern_objects clean_build \ + clean_yacc_gen clean_gpre_gen clean_dbs clean_examples clean_tommath \ +- clean_tomcrypt clean_decfloat clean_vers clean_misc ++ clean_tomcrypt clean_decfloat clean_int128 clean_vers clean_misc + + clean_vers: + $(RM) *.vers +@@ -797,6 +802,9 @@ clean_tomcrypt: + clean_decfloat: + -$(MAKE) -C $(ROOT)/extern/decNumber clean + ++clean_int128: ++ -$(MAKE) -C $(ROOT)/extern/int128/absl/numeric clean ++ + clean_objects: + $(RM) `find $(TMP_ROOT)/ -type f -name '*.o' -print` + $(RM) `find $(TMP_ROOT)/ -type f -name '*.a' -print` +diff --git a/builds/posix/make.android.arm64 b/builds/posix/make.android.arm64 +index 79fbb90c2e..ff0d8d85ff 100644 +--- a/builds/posix/make.android.arm64 ++++ b/builds/posix/make.android.arm64 +@@ -41,7 +41,7 @@ DEV_FLAGS=$(COMMON_FLAGS) $(WARN_FLAGS) + CROSS_CONFIG=android.arm64 + + LDFLAGS += --sysroot=$(CROSS_SYSROOT) -static-libstdc++ +-DroidLibs := -lm -ldl $(DECLIB) $(RE2LIB) ++DroidLibs := -lm -ldl $(DECLIB) $(RE2LIB) $(I128LIB) + + LINK_LIBS = $(DroidLibs) + STATICLINK_LIBS = $(DroidLibs) +diff --git a/builds/posix/make.android.arme b/builds/posix/make.android.arme +index c7233d0191..b6ae33587d 100644 +--- a/builds/posix/make.android.arme ++++ b/builds/posix/make.android.arme +@@ -40,7 +40,7 @@ DEV_FLAGS=$(COMMON_FLAGS) $(WARN_FLAGS) + CROSS_CONFIG=android.arme + + LDFLAGS += --sysroot=$(CROSS_PLATFORM) -static-libstdc++ +-DroidLibs := -lm -ldl $(DECLIB) $(RE2LIB) ++DroidLibs := -lm -ldl $(DECLIB) $(RE2LIB) $(I128LIB) + UDR_SUPPORT_LIBS := + + LINK_LIBS = $(DroidLibs) +diff --git a/builds/posix/make.defaults b/builds/posix/make.defaults +index 6dfd3ab118..9421947a59 100755 +--- a/builds/posix/make.defaults ++++ b/builds/posix/make.defaults +@@ -134,6 +134,7 @@ CAS_OPTIONS=@CAS_OPTIONS@ + # multiple-precision integer library + MATHLIB=@MATHLIB@ + DECLIB=-ldecFloat$(CROSS) ++I128LIB=-li128$(CROSS) + RE2LIB=-lre2 + + # crypt library +@@ -190,8 +191,8 @@ endif + STATICLIB_LINK = $(AR) crus + STATICEXE_LINK = $(CXX) $(GLOB_OPTIONS) $(CXXFLAGS) -static-libstdc++ + +-LINK_LIBS = @LIBS@ $(DECLIB) $(RE2LIB) +-SO_LINK_LIBS = @LIBS@ $(DECLIB) $(RE2LIB) ++LINK_LIBS = @LIBS@ $(DECLIB) $(RE2LIB) $(I128LIB) ++SO_LINK_LIBS = @LIBS@ $(DECLIB) $(RE2LIB) $(I128LIB) + + # Default extensions + +diff --git a/builds/posix/make.rules b/builds/posix/make.rules +index 3afd891141..e725b93067 100644 +--- a/builds/posix/make.rules ++++ b/builds/posix/make.rules +@@ -32,7 +32,7 @@ + + + # Please don't use compiler/platform specific flags here - nmcc 02-Nov-2002 +-WFLAGS =-I$(SRC_ROOT)/include/gen -I$(SRC_ROOT)/include -I$(ROOT)/extern/re2 $(CPPFLAGS) $(LTCSOURCE) ++WFLAGS =-I$(SRC_ROOT)/include/gen -I$(SRC_ROOT)/include -I$(ROOT)/extern/re2 -I$(ROOT)/extern/int128 $(CPPFLAGS) $(LTCSOURCE) + + ifeq ($(TOMMATH_BUILD_FLG),Y) + WFLAGS += -I$(TOMMATH_INC) +diff --git a/builds/posix/prefix.linux_s390x b/builds/posix/prefix.linux_s390x +index ccb2340123..cb0992bb41 100644 +--- a/builds/posix/prefix.linux_s390x ++++ b/builds/posix/prefix.linux_s390x +@@ -18,10 +18,10 @@ + # + # 2 Oct 2002, Nickolay Samofatov - Major cleanup + +-COMMON_FLAGS=-ggdb -DFB_SEND_FLAGS=MSG_NOSIGNAL -DLINUX -pipe -MMD -fPIC -fmessage-length=0 -fsigned-char ++COMMON_FLAGS=-ggdb -DFB_SEND_FLAGS=MSG_NOSIGNAL -DLINUX -pipe -MMD -fPIC -fmessage-length=0 -fsigned-char -Wno-invalid-offsetof + OPTIMIZE_FLAGS=-O3 -fno-omit-frame-pointer -fno-builtin + WARN_FLAGS=-Wall -Wno-switch -Wno-parentheses -Wno-unknown-pragmas -Wno-unused-variable -Wno-non-virtual-dtor + + PROD_FLAGS=$(COMMON_FLAGS) $(OPTIMIZE_FLAGS) +-DEV_FLAGS=-DUSE_VALGRIND -p $(COMMON_FLAGS) $(WARN_FLAGS) +-#DEV_FLAGS=-p $(COMMON_FLAGS) $(WARN_FLAGS) ++#DEV_FLAGS=-DUSE_VALGRIND -p $(COMMON_FLAGS) $(WARN_FLAGS) ++DEV_FLAGS=-p $(COMMON_FLAGS) $(WARN_FLAGS) +diff --git a/extern/int128/absl/base/attributes.h b/extern/int128/absl/base/attributes.h +new file mode 100644 +index 0000000000..52139556f2 +--- /dev/null ++++ b/extern/int128/absl/base/attributes.h +@@ -0,0 +1,721 @@ ++// Copyright 2017 The Abseil Authors. ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// https://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++// ++// This header file defines macros for declaring attributes for functions, ++// types, and variables. ++// ++// These macros are used within Abseil and allow the compiler to optimize, where ++// applicable, certain function calls. ++// ++// Most macros here are exposing GCC or Clang features, and are stubbed out for ++// other compilers. ++// ++// GCC attributes documentation: ++// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html ++// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Variable-Attributes.html ++// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Type-Attributes.html ++// ++// Most attributes in this file are already supported by GCC 4.7. However, some ++// of them are not supported in older version of Clang. Thus, we check ++// `__has_attribute()` first. If the check fails, we check if we are on GCC and ++// assume the attribute exists on GCC (which is verified on GCC 4.7). ++ ++#ifndef ABSL_BASE_ATTRIBUTES_H_ ++#define ABSL_BASE_ATTRIBUTES_H_ ++ ++#include "absl/base/config.h" ++ ++// ABSL_HAVE_ATTRIBUTE ++// ++// A function-like feature checking macro that is a wrapper around ++// `__has_attribute`, which is defined by GCC 5+ and Clang and evaluates to a ++// nonzero constant integer if the attribute is supported or 0 if not. ++// ++// It evaluates to zero if `__has_attribute` is not defined by the compiler. ++// ++// GCC: https://gcc.gnu.org/gcc-5/changes.html ++// Clang: https://clang.llvm.org/docs/LanguageExtensions.html ++#ifdef __has_attribute ++#define ABSL_HAVE_ATTRIBUTE(x) __has_attribute(x) ++#else ++#define ABSL_HAVE_ATTRIBUTE(x) 0 ++#endif ++ ++// ABSL_HAVE_CPP_ATTRIBUTE ++// ++// A function-like feature checking macro that accepts C++11 style attributes. ++// It's a wrapper around `__has_cpp_attribute`, defined by ISO C++ SD-6 ++// (https://en.cppreference.com/w/cpp/experimental/feature_test). If we don't ++// find `__has_cpp_attribute`, will evaluate to 0. ++#if defined(__cplusplus) && defined(__has_cpp_attribute) ++// NOTE: requiring __cplusplus above should not be necessary, but ++// works around https://bugs.llvm.org/show_bug.cgi?id=23435. ++#define ABSL_HAVE_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) ++#else ++#define ABSL_HAVE_CPP_ATTRIBUTE(x) 0 ++#endif ++ ++// ----------------------------------------------------------------------------- ++// Function Attributes ++// ----------------------------------------------------------------------------- ++// ++// GCC: https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html ++// Clang: https://clang.llvm.org/docs/AttributeReference.html ++ ++// ABSL_PRINTF_ATTRIBUTE ++// ABSL_SCANF_ATTRIBUTE ++// ++// Tells the compiler to perform `printf` format string checking if the ++// compiler supports it; see the 'format' attribute in ++// . ++// ++// Note: As the GCC manual states, "[s]ince non-static C++ methods ++// have an implicit 'this' argument, the arguments of such methods ++// should be counted from two, not one." ++#if ABSL_HAVE_ATTRIBUTE(format) || (defined(__GNUC__) && !defined(__clang__)) ++#define ABSL_PRINTF_ATTRIBUTE(string_index, first_to_check) \ ++ __attribute__((__format__(__printf__, string_index, first_to_check))) ++#define ABSL_SCANF_ATTRIBUTE(string_index, first_to_check) \ ++ __attribute__((__format__(__scanf__, string_index, first_to_check))) ++#else ++#define ABSL_PRINTF_ATTRIBUTE(string_index, first_to_check) ++#define ABSL_SCANF_ATTRIBUTE(string_index, first_to_check) ++#endif ++ ++// ABSL_ATTRIBUTE_ALWAYS_INLINE ++// ABSL_ATTRIBUTE_NOINLINE ++// ++// Forces functions to either inline or not inline. Introduced in gcc 3.1. ++#if ABSL_HAVE_ATTRIBUTE(always_inline) || \ ++ (defined(__GNUC__) && !defined(__clang__)) ++#define ABSL_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline)) ++#define ABSL_HAVE_ATTRIBUTE_ALWAYS_INLINE 1 ++#else ++#define ABSL_ATTRIBUTE_ALWAYS_INLINE ++#endif ++ ++#if ABSL_HAVE_ATTRIBUTE(noinline) || (defined(__GNUC__) && !defined(__clang__)) ++#define ABSL_ATTRIBUTE_NOINLINE __attribute__((noinline)) ++#define ABSL_HAVE_ATTRIBUTE_NOINLINE 1 ++#else ++#define ABSL_ATTRIBUTE_NOINLINE ++#endif ++ ++// ABSL_ATTRIBUTE_NO_TAIL_CALL ++// ++// Prevents the compiler from optimizing away stack frames for functions which ++// end in a call to another function. ++#if ABSL_HAVE_ATTRIBUTE(disable_tail_calls) ++#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1 ++#define ABSL_ATTRIBUTE_NO_TAIL_CALL __attribute__((disable_tail_calls)) ++#elif defined(__GNUC__) && !defined(__clang__) && !defined(__e2k__) ++#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1 ++#define ABSL_ATTRIBUTE_NO_TAIL_CALL \ ++ __attribute__((optimize("no-optimize-sibling-calls"))) ++#else ++#define ABSL_ATTRIBUTE_NO_TAIL_CALL ++#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 0 ++#endif ++ ++// ABSL_ATTRIBUTE_WEAK ++// ++// Tags a function as weak for the purposes of compilation and linking. ++// Weak attributes did not work properly in LLVM's Windows backend before ++// 9.0.0, so disable them there. See https://bugs.llvm.org/show_bug.cgi?id=37598 ++// for further information. ++// The MinGW compiler doesn't complain about the weak attribute until the link ++// step, presumably because Windows doesn't use ELF binaries. ++#if (ABSL_HAVE_ATTRIBUTE(weak) || \ ++ (defined(__GNUC__) && !defined(__clang__))) && \ ++ (!defined(_WIN32) || __clang_major__ < 9) && !defined(__MINGW32__) ++#undef ABSL_ATTRIBUTE_WEAK ++#define ABSL_ATTRIBUTE_WEAK __attribute__((weak)) ++#define ABSL_HAVE_ATTRIBUTE_WEAK 1 ++#else ++#define ABSL_ATTRIBUTE_WEAK ++#define ABSL_HAVE_ATTRIBUTE_WEAK 0 ++#endif ++ ++// ABSL_ATTRIBUTE_NONNULL ++// ++// Tells the compiler either (a) that a particular function parameter ++// should be a non-null pointer, or (b) that all pointer arguments should ++// be non-null. ++// ++// Note: As the GCC manual states, "[s]ince non-static C++ methods ++// have an implicit 'this' argument, the arguments of such methods ++// should be counted from two, not one." ++// ++// Args are indexed starting at 1. ++// ++// For non-static class member functions, the implicit `this` argument ++// is arg 1, and the first explicit argument is arg 2. For static class member ++// functions, there is no implicit `this`, and the first explicit argument is ++// arg 1. ++// ++// Example: ++// ++// /* arg_a cannot be null, but arg_b can */ ++// void Function(void* arg_a, void* arg_b) ABSL_ATTRIBUTE_NONNULL(1); ++// ++// class C { ++// /* arg_a cannot be null, but arg_b can */ ++// void Method(void* arg_a, void* arg_b) ABSL_ATTRIBUTE_NONNULL(2); ++// ++// /* arg_a cannot be null, but arg_b can */ ++// static void StaticMethod(void* arg_a, void* arg_b) ++// ABSL_ATTRIBUTE_NONNULL(1); ++// }; ++// ++// If no arguments are provided, then all pointer arguments should be non-null. ++// ++// /* No pointer arguments may be null. */ ++// void Function(void* arg_a, void* arg_b, int arg_c) ABSL_ATTRIBUTE_NONNULL(); ++// ++// NOTE: The GCC nonnull attribute actually accepts a list of arguments, but ++// ABSL_ATTRIBUTE_NONNULL does not. ++#if ABSL_HAVE_ATTRIBUTE(nonnull) || (defined(__GNUC__) && !defined(__clang__)) ++#define ABSL_ATTRIBUTE_NONNULL(arg_index) __attribute__((nonnull(arg_index))) ++#else ++#define ABSL_ATTRIBUTE_NONNULL(...) ++#endif ++ ++// ABSL_ATTRIBUTE_NORETURN ++// ++// Tells the compiler that a given function never returns. ++#if ABSL_HAVE_ATTRIBUTE(noreturn) || (defined(__GNUC__) && !defined(__clang__)) ++#define ABSL_ATTRIBUTE_NORETURN __attribute__((noreturn)) ++#elif defined(_MSC_VER) ++#define ABSL_ATTRIBUTE_NORETURN __declspec(noreturn) ++#else ++#define ABSL_ATTRIBUTE_NORETURN ++#endif ++ ++// ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS ++// ++// Tells the AddressSanitizer (or other memory testing tools) to ignore a given ++// function. Useful for cases when a function reads random locations on stack, ++// calls _exit from a cloned subprocess, deliberately accesses buffer ++// out of bounds or does other scary things with memory. ++// NOTE: GCC supports AddressSanitizer(asan) since 4.8. ++// https://gcc.gnu.org/gcc-4.8/changes.html ++#if ABSL_HAVE_ATTRIBUTE(no_sanitize_address) ++#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) ++#else ++#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS ++#endif ++ ++// ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY ++// ++// Tells the MemorySanitizer to relax the handling of a given function. All "Use ++// of uninitialized value" warnings from such functions will be suppressed, and ++// all values loaded from memory will be considered fully initialized. This ++// attribute is similar to the ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS attribute ++// above, but deals with initialized-ness rather than addressability issues. ++// NOTE: MemorySanitizer(msan) is supported by Clang but not GCC. ++#if ABSL_HAVE_ATTRIBUTE(no_sanitize_memory) ++#define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory)) ++#else ++#define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY ++#endif ++ ++// ABSL_ATTRIBUTE_NO_SANITIZE_THREAD ++// ++// Tells the ThreadSanitizer to not instrument a given function. ++// NOTE: GCC supports ThreadSanitizer(tsan) since 4.8. ++// https://gcc.gnu.org/gcc-4.8/changes.html ++#if ABSL_HAVE_ATTRIBUTE(no_sanitize_thread) ++#define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread)) ++#else ++#define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD ++#endif ++ ++// ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED ++// ++// Tells the UndefinedSanitizer to ignore a given function. Useful for cases ++// where certain behavior (eg. division by zero) is being used intentionally. ++// NOTE: GCC supports UndefinedBehaviorSanitizer(ubsan) since 4.9. ++// https://gcc.gnu.org/gcc-4.9/changes.html ++#if ABSL_HAVE_ATTRIBUTE(no_sanitize_undefined) ++#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \ ++ __attribute__((no_sanitize_undefined)) ++#elif ABSL_HAVE_ATTRIBUTE(no_sanitize) ++#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \ ++ __attribute__((no_sanitize("undefined"))) ++#else ++#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED ++#endif ++ ++// ABSL_ATTRIBUTE_NO_SANITIZE_CFI ++// ++// Tells the ControlFlowIntegrity sanitizer to not instrument a given function. ++// See https://clang.llvm.org/docs/ControlFlowIntegrity.html for details. ++#if ABSL_HAVE_ATTRIBUTE(no_sanitize) ++#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI __attribute__((no_sanitize("cfi"))) ++#else ++#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI ++#endif ++ ++// ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK ++// ++// Tells the SafeStack to not instrument a given function. ++// See https://clang.llvm.org/docs/SafeStack.html for details. ++#if ABSL_HAVE_ATTRIBUTE(no_sanitize) ++#define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK \ ++ __attribute__((no_sanitize("safe-stack"))) ++#else ++#define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK ++#endif ++ ++// ABSL_ATTRIBUTE_RETURNS_NONNULL ++// ++// Tells the compiler that a particular function never returns a null pointer. ++#if ABSL_HAVE_ATTRIBUTE(returns_nonnull) ++#define ABSL_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull)) ++#else ++#define ABSL_ATTRIBUTE_RETURNS_NONNULL ++#endif ++ ++// ABSL_HAVE_ATTRIBUTE_SECTION ++// ++// Indicates whether labeled sections are supported. Weak symbol support is ++// a prerequisite. Labeled sections are not supported on Darwin/iOS. ++#ifdef ABSL_HAVE_ATTRIBUTE_SECTION ++#error ABSL_HAVE_ATTRIBUTE_SECTION cannot be directly set ++#elif (ABSL_HAVE_ATTRIBUTE(section) || \ ++ (defined(__GNUC__) && !defined(__clang__))) && \ ++ !defined(__APPLE__) && ABSL_HAVE_ATTRIBUTE_WEAK ++#define ABSL_HAVE_ATTRIBUTE_SECTION 1 ++ ++// ABSL_ATTRIBUTE_SECTION ++// ++// Tells the compiler/linker to put a given function into a section and define ++// `__start_ ## name` and `__stop_ ## name` symbols to bracket the section. ++// This functionality is supported by GNU linker. Any function annotated with ++// `ABSL_ATTRIBUTE_SECTION` must not be inlined, or it will be placed into ++// whatever section its caller is placed into. ++// ++#ifndef ABSL_ATTRIBUTE_SECTION ++#define ABSL_ATTRIBUTE_SECTION(name) \ ++ __attribute__((section(#name))) __attribute__((noinline)) ++#endif ++ ++ ++// ABSL_ATTRIBUTE_SECTION_VARIABLE ++// ++// Tells the compiler/linker to put a given variable into a section and define ++// `__start_ ## name` and `__stop_ ## name` symbols to bracket the section. ++// This functionality is supported by GNU linker. ++#ifndef ABSL_ATTRIBUTE_SECTION_VARIABLE ++#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) __attribute__((section(#name))) ++#endif ++ ++// ABSL_DECLARE_ATTRIBUTE_SECTION_VARS ++// ++// A weak section declaration to be used as a global declaration ++// for ABSL_ATTRIBUTE_SECTION_START|STOP(name) to compile and link ++// even without functions with ABSL_ATTRIBUTE_SECTION(name). ++// ABSL_DEFINE_ATTRIBUTE_SECTION should be in the exactly one file; it's ++// a no-op on ELF but not on Mach-O. ++// ++#ifndef ABSL_DECLARE_ATTRIBUTE_SECTION_VARS ++#define ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) \ ++ extern char __start_##name[] ABSL_ATTRIBUTE_WEAK; \ ++ extern char __stop_##name[] ABSL_ATTRIBUTE_WEAK ++#endif ++#ifndef ABSL_DEFINE_ATTRIBUTE_SECTION_VARS ++#define ABSL_INIT_ATTRIBUTE_SECTION_VARS(name) ++#define ABSL_DEFINE_ATTRIBUTE_SECTION_VARS(name) ++#endif ++ ++// ABSL_ATTRIBUTE_SECTION_START ++// ++// Returns `void*` pointers to start/end of a section of code with ++// functions having ABSL_ATTRIBUTE_SECTION(name). ++// Returns 0 if no such functions exist. ++// One must ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) for this to compile and ++// link. ++// ++#define ABSL_ATTRIBUTE_SECTION_START(name) \ ++ (reinterpret_cast(__start_##name)) ++#define ABSL_ATTRIBUTE_SECTION_STOP(name) \ ++ (reinterpret_cast(__stop_##name)) ++ ++#else // !ABSL_HAVE_ATTRIBUTE_SECTION ++ ++#define ABSL_HAVE_ATTRIBUTE_SECTION 0 ++ ++// provide dummy definitions ++#define ABSL_ATTRIBUTE_SECTION(name) ++#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) ++#define ABSL_INIT_ATTRIBUTE_SECTION_VARS(name) ++#define ABSL_DEFINE_ATTRIBUTE_SECTION_VARS(name) ++#define ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) ++#define ABSL_ATTRIBUTE_SECTION_START(name) (reinterpret_cast(0)) ++#define ABSL_ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast(0)) ++ ++#endif // ABSL_ATTRIBUTE_SECTION ++ ++// ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC ++// ++// Support for aligning the stack on 32-bit x86. ++#if ABSL_HAVE_ATTRIBUTE(force_align_arg_pointer) || \ ++ (defined(__GNUC__) && !defined(__clang__)) ++#if defined(__i386__) ++#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC \ ++ __attribute__((force_align_arg_pointer)) ++#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) ++#elif defined(__x86_64__) ++#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (1) ++#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC ++#else // !__i386__ && !__x86_64 ++#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) ++#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC ++#endif // __i386__ ++#else ++#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC ++#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) ++#endif ++ ++// ABSL_MUST_USE_RESULT ++// ++// Tells the compiler to warn about unused results. ++// ++// When annotating a function, it must appear as the first part of the ++// declaration or definition. The compiler will warn if the return value from ++// such a function is unused: ++// ++// ABSL_MUST_USE_RESULT Sprocket* AllocateSprocket(); ++// AllocateSprocket(); // Triggers a warning. ++// ++// When annotating a class, it is equivalent to annotating every function which ++// returns an instance. ++// ++// class ABSL_MUST_USE_RESULT Sprocket {}; ++// Sprocket(); // Triggers a warning. ++// ++// Sprocket MakeSprocket(); ++// MakeSprocket(); // Triggers a warning. ++// ++// Note that references and pointers are not instances: ++// ++// Sprocket* SprocketPointer(); ++// SprocketPointer(); // Does *not* trigger a warning. ++// ++// ABSL_MUST_USE_RESULT allows using cast-to-void to suppress the unused result ++// warning. For that, warn_unused_result is used only for clang but not for gcc. ++// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425 ++// ++// Note: past advice was to place the macro after the argument list. ++#if ABSL_HAVE_ATTRIBUTE(nodiscard) ++#define ABSL_MUST_USE_RESULT [[nodiscard]] ++#elif defined(__clang__) && ABSL_HAVE_ATTRIBUTE(warn_unused_result) ++#define ABSL_MUST_USE_RESULT __attribute__((warn_unused_result)) ++#else ++#define ABSL_MUST_USE_RESULT ++#endif ++ ++// ABSL_ATTRIBUTE_HOT, ABSL_ATTRIBUTE_COLD ++// ++// Tells GCC that a function is hot or cold. GCC can use this information to ++// improve static analysis, i.e. a conditional branch to a cold function ++// is likely to be not-taken. ++// This annotation is used for function declarations. ++// ++// Example: ++// ++// int foo() ABSL_ATTRIBUTE_HOT; ++#if ABSL_HAVE_ATTRIBUTE(hot) || (defined(__GNUC__) && !defined(__clang__)) ++#define ABSL_ATTRIBUTE_HOT __attribute__((hot)) ++#else ++#define ABSL_ATTRIBUTE_HOT ++#endif ++ ++#if ABSL_HAVE_ATTRIBUTE(cold) || (defined(__GNUC__) && !defined(__clang__)) ++#define ABSL_ATTRIBUTE_COLD __attribute__((cold)) ++#else ++#define ABSL_ATTRIBUTE_COLD ++#endif ++ ++// ABSL_XRAY_ALWAYS_INSTRUMENT, ABSL_XRAY_NEVER_INSTRUMENT, ABSL_XRAY_LOG_ARGS ++// ++// We define the ABSL_XRAY_ALWAYS_INSTRUMENT and ABSL_XRAY_NEVER_INSTRUMENT ++// macro used as an attribute to mark functions that must always or never be ++// instrumented by XRay. Currently, this is only supported in Clang/LLVM. ++// ++// For reference on the LLVM XRay instrumentation, see ++// http://llvm.org/docs/XRay.html. ++// ++// A function with the XRAY_ALWAYS_INSTRUMENT macro attribute in its declaration ++// will always get the XRay instrumentation sleds. These sleds may introduce ++// some binary size and runtime overhead and must be used sparingly. ++// ++// These attributes only take effect when the following conditions are met: ++// ++// * The file/target is built in at least C++11 mode, with a Clang compiler ++// that supports XRay attributes. ++// * The file/target is built with the -fxray-instrument flag set for the ++// Clang/LLVM compiler. ++// * The function is defined in the translation unit (the compiler honors the ++// attribute in either the definition or the declaration, and must match). ++// ++// There are cases when, even when building with XRay instrumentation, users ++// might want to control specifically which functions are instrumented for a ++// particular build using special-case lists provided to the compiler. These ++// special case lists are provided to Clang via the ++// -fxray-always-instrument=... and -fxray-never-instrument=... flags. The ++// attributes in source take precedence over these special-case lists. ++// ++// To disable the XRay attributes at build-time, users may define ++// ABSL_NO_XRAY_ATTRIBUTES. Do NOT define ABSL_NO_XRAY_ATTRIBUTES on specific ++// packages/targets, as this may lead to conflicting definitions of functions at ++// link-time. ++// ++// XRay isn't currently supported on Android: ++// https://github.com/android/ndk/issues/368 ++#if ABSL_HAVE_CPP_ATTRIBUTE(clang::xray_always_instrument) && \ ++ !defined(ABSL_NO_XRAY_ATTRIBUTES) && !defined(__ANDROID__) ++#define ABSL_XRAY_ALWAYS_INSTRUMENT [[clang::xray_always_instrument]] ++#define ABSL_XRAY_NEVER_INSTRUMENT [[clang::xray_never_instrument]] ++#if ABSL_HAVE_CPP_ATTRIBUTE(clang::xray_log_args) ++#define ABSL_XRAY_LOG_ARGS(N) \ ++ [[clang::xray_always_instrument, clang::xray_log_args(N)]] ++#else ++#define ABSL_XRAY_LOG_ARGS(N) [[clang::xray_always_instrument]] ++#endif ++#else ++#define ABSL_XRAY_ALWAYS_INSTRUMENT ++#define ABSL_XRAY_NEVER_INSTRUMENT ++#define ABSL_XRAY_LOG_ARGS(N) ++#endif ++ ++// ABSL_ATTRIBUTE_REINITIALIZES ++// ++// Indicates that a member function reinitializes the entire object to a known ++// state, independent of the previous state of the object. ++// ++// The clang-tidy check bugprone-use-after-move allows member functions marked ++// with this attribute to be called on objects that have been moved from; ++// without the attribute, this would result in a use-after-move warning. ++#if ABSL_HAVE_CPP_ATTRIBUTE(clang::reinitializes) ++#define ABSL_ATTRIBUTE_REINITIALIZES [[clang::reinitializes]] ++#else ++#define ABSL_ATTRIBUTE_REINITIALIZES ++#endif ++ ++// ----------------------------------------------------------------------------- ++// Variable Attributes ++// ----------------------------------------------------------------------------- ++ ++// ABSL_ATTRIBUTE_UNUSED ++// ++// Prevents the compiler from complaining about variables that appear unused. ++// ++// For code or headers that are assured to only build with C++17 and up, prefer ++// just using the standard '[[maybe_unused]]' directly over this macro. ++// ++// Due to differences in positioning requirements between the old, compiler ++// specific __attribute__ syntax and the now standard [[maybe_unused]], this ++// macro does not attempt to take advantage of '[[maybe_unused]]'. ++#if ABSL_HAVE_ATTRIBUTE(unused) || (defined(__GNUC__) && !defined(__clang__)) ++#undef ABSL_ATTRIBUTE_UNUSED ++#define ABSL_ATTRIBUTE_UNUSED __attribute__((__unused__)) ++#else ++#define ABSL_ATTRIBUTE_UNUSED ++#endif ++ ++// ABSL_ATTRIBUTE_INITIAL_EXEC ++// ++// Tells the compiler to use "initial-exec" mode for a thread-local variable. ++// See http://people.redhat.com/drepper/tls.pdf for the gory details. ++#if ABSL_HAVE_ATTRIBUTE(tls_model) || (defined(__GNUC__) && !defined(__clang__)) ++#define ABSL_ATTRIBUTE_INITIAL_EXEC __attribute__((tls_model("initial-exec"))) ++#else ++#define ABSL_ATTRIBUTE_INITIAL_EXEC ++#endif ++ ++// ABSL_ATTRIBUTE_PACKED ++// ++// Instructs the compiler not to use natural alignment for a tagged data ++// structure, but instead to reduce its alignment to 1. This attribute can ++// either be applied to members of a structure or to a structure in its ++// entirety. Applying this attribute (judiciously) to a structure in its ++// entirety to optimize the memory footprint of very commonly-used structs is ++// fine. Do not apply this attribute to a structure in its entirety if the ++// purpose is to control the offsets of the members in the structure. Instead, ++// apply this attribute only to structure members that need it. ++// ++// When applying ABSL_ATTRIBUTE_PACKED only to specific structure members the ++// natural alignment of structure members not annotated is preserved. Aligned ++// member accesses are faster than non-aligned member accesses even if the ++// targeted microprocessor supports non-aligned accesses. ++#if ABSL_HAVE_ATTRIBUTE(packed) || (defined(__GNUC__) && !defined(__clang__)) ++#define ABSL_ATTRIBUTE_PACKED __attribute__((__packed__)) ++#else ++#define ABSL_ATTRIBUTE_PACKED ++#endif ++ ++// ABSL_ATTRIBUTE_FUNC_ALIGN ++// ++// Tells the compiler to align the function start at least to certain ++// alignment boundary ++#if ABSL_HAVE_ATTRIBUTE(aligned) || (defined(__GNUC__) && !defined(__clang__)) ++#define ABSL_ATTRIBUTE_FUNC_ALIGN(bytes) __attribute__((aligned(bytes))) ++#else ++#define ABSL_ATTRIBUTE_FUNC_ALIGN(bytes) ++#endif ++ ++// ABSL_FALLTHROUGH_INTENDED ++// ++// Annotates implicit fall-through between switch labels, allowing a case to ++// indicate intentional fallthrough and turn off warnings about any lack of a ++// `break` statement. The ABSL_FALLTHROUGH_INTENDED macro should be followed by ++// a semicolon and can be used in most places where `break` can, provided that ++// no statements exist between it and the next switch label. ++// ++// Example: ++// ++// switch (x) { ++// case 40: ++// case 41: ++// if (truth_is_out_there) { ++// ++x; ++// ABSL_FALLTHROUGH_INTENDED; // Use instead of/along with annotations ++// // in comments ++// } else { ++// return x; ++// } ++// case 42: ++// ... ++// ++// Notes: When supported, GCC and Clang can issue a warning on switch labels ++// with unannotated fallthrough using the warning `-Wimplicit-fallthrough`. See ++// clang documentation on language extensions for details: ++// https://clang.llvm.org/docs/AttributeReference.html#fallthrough-clang-fallthrough ++// ++// When used with unsupported compilers, the ABSL_FALLTHROUGH_INTENDED macro has ++// no effect on diagnostics. In any case this macro has no effect on runtime ++// behavior and performance of code. ++ ++#ifdef ABSL_FALLTHROUGH_INTENDED ++#error "ABSL_FALLTHROUGH_INTENDED should not be defined." ++#elif ABSL_HAVE_CPP_ATTRIBUTE(fallthrough) ++#define ABSL_FALLTHROUGH_INTENDED [[fallthrough]] ++#elif ABSL_HAVE_CPP_ATTRIBUTE(clang::fallthrough) ++#define ABSL_FALLTHROUGH_INTENDED [[clang::fallthrough]] ++#elif ABSL_HAVE_CPP_ATTRIBUTE(gnu::fallthrough) ++#define ABSL_FALLTHROUGH_INTENDED [[gnu::fallthrough]] ++#else ++#define ABSL_FALLTHROUGH_INTENDED \ ++ do { \ ++ } while (0) ++#endif ++ ++// ABSL_DEPRECATED() ++// ++// Marks a deprecated class, struct, enum, function, method and variable ++// declarations. The macro argument is used as a custom diagnostic message (e.g. ++// suggestion of a better alternative). ++// ++// Examples: ++// ++// class ABSL_DEPRECATED("Use Bar instead") Foo {...}; ++// ++// ABSL_DEPRECATED("Use Baz() instead") void Bar() {...} ++// ++// template ++// ABSL_DEPRECATED("Use DoThat() instead") ++// void DoThis(); ++// ++// Every usage of a deprecated entity will trigger a warning when compiled with ++// clang's `-Wdeprecated-declarations` option. This option is turned off by ++// default, but the warnings will be reported by clang-tidy. ++#if defined(__clang__) && defined(__cplusplus) && __cplusplus >= 201103L ++#define ABSL_DEPRECATED(message) __attribute__((deprecated(message))) ++#endif ++ ++#ifndef ABSL_DEPRECATED ++#define ABSL_DEPRECATED(message) ++#endif ++ ++// ABSL_CONST_INIT ++// ++// A variable declaration annotated with the `ABSL_CONST_INIT` attribute will ++// not compile (on supported platforms) unless the variable has a constant ++// initializer. This is useful for variables with static and thread storage ++// duration, because it guarantees that they will not suffer from the so-called ++// "static init order fiasco". Prefer to put this attribute on the most visible ++// declaration of the variable, if there's more than one, because code that ++// accesses the variable can then use the attribute for optimization. ++// ++// Example: ++// ++// class MyClass { ++// public: ++// ABSL_CONST_INIT static MyType my_var; ++// }; ++// ++// MyType MyClass::my_var = MakeMyType(...); ++// ++// Note that this attribute is redundant if the variable is declared constexpr. ++#if ABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization) ++#define ABSL_CONST_INIT [[clang::require_constant_initialization]] ++#else ++#define ABSL_CONST_INIT ++#endif // ABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization) ++ ++// ABSL_ATTRIBUTE_PURE_FUNCTION ++// ++// ABSL_ATTRIBUTE_PURE_FUNCTION is used to annotate declarations of "pure" ++// functions. A function is pure if its return value is only a function of its ++// arguments. The pure attribute prohibits a function from modifying the state ++// of the program that is observable by means other than inspecting the ++// function's return value. Declaring such functions with the pure attribute ++// allows the compiler to avoid emitting some calls in repeated invocations of ++// the function with the same argument values. ++// ++// Example: ++// ++// ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Milliseconds(Duration d); ++#if ABSL_HAVE_CPP_ATTRIBUTE(gnu::pure) ++#define ABSL_ATTRIBUTE_PURE_FUNCTION [[gnu::pure]] ++#elif ABSL_HAVE_ATTRIBUTE(pure) ++#define ABSL_ATTRIBUTE_PURE_FUNCTION __attribute__((pure)) ++#else ++#define ABSL_ATTRIBUTE_PURE_FUNCTION ++#endif ++ ++// ABSL_ATTRIBUTE_LIFETIME_BOUND indicates that a resource owned by a function ++// parameter or implicit object parameter is retained by the return value of the ++// annotated function (or, for a parameter of a constructor, in the value of the ++// constructed object). This attribute causes warnings to be produced if a ++// temporary object does not live long enough. ++// ++// When applied to a reference parameter, the referenced object is assumed to be ++// retained by the return value of the function. When applied to a non-reference ++// parameter (for example, a pointer or a class type), all temporaries ++// referenced by the parameter are assumed to be retained by the return value of ++// the function. ++// ++// See also the upstream documentation: ++// https://clang.llvm.org/docs/AttributeReference.html#lifetimebound ++#if ABSL_HAVE_CPP_ATTRIBUTE(clang::lifetimebound) ++#define ABSL_ATTRIBUTE_LIFETIME_BOUND [[clang::lifetimebound]] ++#elif ABSL_HAVE_ATTRIBUTE(lifetimebound) ++#define ABSL_ATTRIBUTE_LIFETIME_BOUND __attribute__((lifetimebound)) ++#else ++#define ABSL_ATTRIBUTE_LIFETIME_BOUND ++#endif ++ ++#endif // ABSL_BASE_ATTRIBUTES_H_ +diff --git a/extern/int128/absl/base/config.h b/extern/int128/absl/base/config.h +new file mode 100644 +index 0000000000..a6e7c86a0c +--- /dev/null ++++ b/extern/int128/absl/base/config.h +@@ -0,0 +1,745 @@ ++// ++// Copyright 2017 The Abseil Authors. ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// https://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++// ++// ----------------------------------------------------------------------------- ++// File: config.h ++// ----------------------------------------------------------------------------- ++// ++// This header file defines a set of macros for checking the presence of ++// important compiler and platform features. Such macros can be used to ++// produce portable code by parameterizing compilation based on the presence or ++// lack of a given feature. ++// ++// We define a "feature" as some interface we wish to program to: for example, ++// a library function or system call. A value of `1` indicates support for ++// that feature; any other value indicates the feature support is undefined. ++// ++// Example: ++// ++// Suppose a programmer wants to write a program that uses the 'mmap()' system ++// call. The Abseil macro for that feature (`ABSL_HAVE_MMAP`) allows you to ++// selectively include the `mmap.h` header and bracket code using that feature ++// in the macro: ++// ++// #include "absl/base/config.h" ++// ++// #ifdef ABSL_HAVE_MMAP ++// #include "sys/mman.h" ++// #endif //ABSL_HAVE_MMAP ++// ++// ... ++// #ifdef ABSL_HAVE_MMAP ++// void *ptr = mmap(...); ++// ... ++// #endif // ABSL_HAVE_MMAP ++ ++#ifndef ABSL_BASE_CONFIG_H_ ++#define ABSL_BASE_CONFIG_H_ ++ ++// Included for the __GLIBC__ macro (or similar macros on other systems). ++#include ++ ++#ifdef __cplusplus ++// Included for __GLIBCXX__, _LIBCPP_VERSION ++#include ++#endif // __cplusplus ++ ++#if defined(__APPLE__) ++// Included for TARGET_OS_IPHONE, __IPHONE_OS_VERSION_MIN_REQUIRED, ++// __IPHONE_8_0. ++#include ++#include ++#endif ++ ++#include "absl/base/options.h" ++#include "absl/base/policy_checks.h" ++ ++// Helper macro to convert a CPP variable to a string literal. ++#define ABSL_INTERNAL_DO_TOKEN_STR(x) #x ++#define ABSL_INTERNAL_TOKEN_STR(x) ABSL_INTERNAL_DO_TOKEN_STR(x) ++ ++// ----------------------------------------------------------------------------- ++// Abseil namespace annotations ++// ----------------------------------------------------------------------------- ++ ++// ABSL_NAMESPACE_BEGIN/ABSL_NAMESPACE_END ++// ++// An annotation placed at the beginning/end of each `namespace absl` scope. ++// This is used to inject an inline namespace. ++// ++// The proper way to write Abseil code in the `absl` namespace is: ++// ++// namespace absl { ++// ABSL_NAMESPACE_BEGIN ++// ++// void Foo(); // absl::Foo(). ++// ++// ABSL_NAMESPACE_END ++// } // namespace absl ++// ++// Users of Abseil should not use these macros, because users of Abseil should ++// not write `namespace absl {` in their own code for any reason. (Abseil does ++// not support forward declarations of its own types, nor does it support ++// user-provided specialization of Abseil templates. Code that violates these ++// rules may be broken without warning.) ++#if !defined(ABSL_OPTION_USE_INLINE_NAMESPACE) || \ ++ !defined(ABSL_OPTION_INLINE_NAMESPACE_NAME) ++#error options.h is misconfigured. ++#endif ++ ++// Check that ABSL_OPTION_INLINE_NAMESPACE_NAME is neither "head" nor "" ++#if defined(__cplusplus) && ABSL_OPTION_USE_INLINE_NAMESPACE == 1 ++ ++#define ABSL_INTERNAL_INLINE_NAMESPACE_STR \ ++ ABSL_INTERNAL_TOKEN_STR(ABSL_OPTION_INLINE_NAMESPACE_NAME) ++ ++static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != '\0', ++ "options.h misconfigured: ABSL_OPTION_INLINE_NAMESPACE_NAME must " ++ "not be empty."); ++static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' || ++ ABSL_INTERNAL_INLINE_NAMESPACE_STR[1] != 'e' || ++ ABSL_INTERNAL_INLINE_NAMESPACE_STR[2] != 'a' || ++ ABSL_INTERNAL_INLINE_NAMESPACE_STR[3] != 'd' || ++ ABSL_INTERNAL_INLINE_NAMESPACE_STR[4] != '\0', ++ "options.h misconfigured: ABSL_OPTION_INLINE_NAMESPACE_NAME must " ++ "be changed to a new, unique identifier name."); ++ ++#endif ++ ++#if ABSL_OPTION_USE_INLINE_NAMESPACE == 0 ++#define ABSL_NAMESPACE_BEGIN ++#define ABSL_NAMESPACE_END ++#define ABSL_INTERNAL_C_SYMBOL(x) x ++#elif ABSL_OPTION_USE_INLINE_NAMESPACE == 1 ++#define ABSL_NAMESPACE_BEGIN \ ++ inline namespace ABSL_OPTION_INLINE_NAMESPACE_NAME { ++#define ABSL_NAMESPACE_END } ++#define ABSL_INTERNAL_C_SYMBOL_HELPER_2(x, v) x##_##v ++#define ABSL_INTERNAL_C_SYMBOL_HELPER_1(x, v) \ ++ ABSL_INTERNAL_C_SYMBOL_HELPER_2(x, v) ++#define ABSL_INTERNAL_C_SYMBOL(x) \ ++ ABSL_INTERNAL_C_SYMBOL_HELPER_1(x, ABSL_OPTION_INLINE_NAMESPACE_NAME) ++#else ++#error options.h is misconfigured. ++#endif ++ ++// ----------------------------------------------------------------------------- ++// Compiler Feature Checks ++// ----------------------------------------------------------------------------- ++ ++// ABSL_HAVE_BUILTIN() ++// ++// Checks whether the compiler supports a Clang Feature Checking Macro, and if ++// so, checks whether it supports the provided builtin function "x" where x ++// is one of the functions noted in ++// https://clang.llvm.org/docs/LanguageExtensions.html ++// ++// Note: Use this macro to avoid an extra level of #ifdef __has_builtin check. ++// http://releases.llvm.org/3.3/tools/clang/docs/LanguageExtensions.html ++#ifdef __has_builtin ++#define ABSL_HAVE_BUILTIN(x) __has_builtin(x) ++#else ++#define ABSL_HAVE_BUILTIN(x) 0 ++#endif ++ ++#if defined(__is_identifier) ++#define ABSL_INTERNAL_HAS_KEYWORD(x) !(__is_identifier(x)) ++#else ++#define ABSL_INTERNAL_HAS_KEYWORD(x) 0 ++#endif ++ ++#ifdef __has_feature ++#define ABSL_HAVE_FEATURE(f) __has_feature(f) ++#else ++#define ABSL_HAVE_FEATURE(f) 0 ++#endif ++ ++// Portable check for GCC minimum version: ++// https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html ++#if defined(__GNUC__) && defined(__GNUC_MINOR__) ++#define ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(x, y) \ ++ (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y)) ++#else ++#define ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(x, y) 0 ++#endif ++ ++#if defined(__clang__) && defined(__clang_major__) && defined(__clang_minor__) ++#define ABSL_INTERNAL_HAVE_MIN_CLANG_VERSION(x, y) \ ++ (__clang_major__ > (x) || __clang_major__ == (x) && __clang_minor__ >= (y)) ++#else ++#define ABSL_INTERNAL_HAVE_MIN_CLANG_VERSION(x, y) 0 ++#endif ++ ++// ABSL_HAVE_TLS is defined to 1 when __thread should be supported. ++// We assume __thread is supported on Linux when compiled with Clang or compiled ++// against libstdc++ with _GLIBCXX_HAVE_TLS defined. ++#ifdef ABSL_HAVE_TLS ++#error ABSL_HAVE_TLS cannot be directly set ++#elif defined(__linux__) && (defined(__clang__) || defined(_GLIBCXX_HAVE_TLS)) ++#define ABSL_HAVE_TLS 1 ++#endif ++ ++// ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE ++// ++// Checks whether `std::is_trivially_destructible` is supported. ++// ++// Notes: All supported compilers using libc++ support this feature, as does ++// gcc >= 4.8.1 using libstdc++, and Visual Studio. ++#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE ++#error ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE cannot be directly set ++#elif defined(_LIBCPP_VERSION) || defined(_MSC_VER) || \ ++ (!defined(__clang__) && defined(__GLIBCXX__) && \ ++ ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(4, 8)) ++#define ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE 1 ++#endif ++ ++// ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE ++// ++// Checks whether `std::is_trivially_default_constructible` and ++// `std::is_trivially_copy_constructible` are supported. ++ ++// ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE ++// ++// Checks whether `std::is_trivially_copy_assignable` is supported. ++ ++// Notes: Clang with libc++ supports these features, as does gcc >= 5.1 with ++// either libc++ or libstdc++, and Visual Studio (but not NVCC). ++#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) ++#error ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE cannot be directly set ++#elif defined(ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE) ++#error ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE cannot directly set ++#elif (defined(__clang__) && defined(_LIBCPP_VERSION)) || \ ++ (!defined(__clang__) && ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(7, 4) && \ ++ (defined(_LIBCPP_VERSION) || defined(__GLIBCXX__))) || \ ++ (defined(_MSC_VER) && !defined(__NVCC__)) ++#define ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE 1 ++#define ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE 1 ++#endif ++ ++// ABSL_HAVE_SOURCE_LOCATION_CURRENT ++// ++// Indicates whether `absl::SourceLocation::current()` will return useful ++// information in some contexts. ++#ifndef ABSL_HAVE_SOURCE_LOCATION_CURRENT ++#if ABSL_INTERNAL_HAS_KEYWORD(__builtin_LINE) && \ ++ ABSL_INTERNAL_HAS_KEYWORD(__builtin_FILE) ++#define ABSL_HAVE_SOURCE_LOCATION_CURRENT 1 ++#elif ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(5, 0) ++#define ABSL_HAVE_SOURCE_LOCATION_CURRENT 1 ++#endif ++#endif ++ ++// ABSL_HAVE_THREAD_LOCAL ++// ++// Checks whether C++11's `thread_local` storage duration specifier is ++// supported. ++#ifdef ABSL_HAVE_THREAD_LOCAL ++#error ABSL_HAVE_THREAD_LOCAL cannot be directly set ++#elif defined(__APPLE__) ++// Notes: ++// * Xcode's clang did not support `thread_local` until version 8, and ++// even then not for all iOS < 9.0. ++// * Xcode 9.3 started disallowing `thread_local` for 32-bit iOS simulator ++// targeting iOS 9.x. ++// * Xcode 10 moves the deployment target check for iOS < 9.0 to link time ++// making ABSL_HAVE_FEATURE unreliable there. ++// ++#if ABSL_HAVE_FEATURE(cxx_thread_local) && \ ++ !(TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0) ++#define ABSL_HAVE_THREAD_LOCAL 1 ++#endif ++#else // !defined(__APPLE__) ++#define ABSL_HAVE_THREAD_LOCAL 1 ++#endif ++ ++// There are platforms for which TLS should not be used even though the compiler ++// makes it seem like it's supported (Android NDK < r12b for example). ++// This is primarily because of linker problems and toolchain misconfiguration: ++// Abseil does not intend to support this indefinitely. Currently, the newest ++// toolchain that we intend to support that requires this behavior is the ++// r11 NDK - allowing for a 5 year support window on that means this option ++// is likely to be removed around June of 2021. ++// TLS isn't supported until NDK r12b per ++// https://developer.android.com/ndk/downloads/revision_history.html ++// Since NDK r16, `__NDK_MAJOR__` and `__NDK_MINOR__` are defined in ++// . For NDK < r16, users should define these macros, ++// e.g. `-D__NDK_MAJOR__=11 -D__NKD_MINOR__=0` for NDK r11. ++#if defined(__ANDROID__) && defined(__clang__) ++#if __has_include() ++#include ++#endif // __has_include() ++#if defined(__ANDROID__) && defined(__clang__) && defined(__NDK_MAJOR__) && \ ++ defined(__NDK_MINOR__) && \ ++ ((__NDK_MAJOR__ < 12) || ((__NDK_MAJOR__ == 12) && (__NDK_MINOR__ < 1))) ++#undef ABSL_HAVE_TLS ++#undef ABSL_HAVE_THREAD_LOCAL ++#endif ++#endif // defined(__ANDROID__) && defined(__clang__) ++ ++// ABSL_HAVE_INTRINSIC_INT128 ++// ++// Checks whether the __int128 compiler extension for a 128-bit integral type is ++// supported. ++// ++// Note: __SIZEOF_INT128__ is defined by Clang and GCC when __int128 is ++// supported, but we avoid using it in certain cases: ++// * On Clang: ++// * Building using Clang for Windows, where the Clang runtime library has ++// 128-bit support only on LP64 architectures, but Windows is LLP64. ++// * On Nvidia's nvcc: ++// * nvcc also defines __GNUC__ and __SIZEOF_INT128__, but not all versions ++// actually support __int128. ++ ++/* Unfortunately FB does not support alignment requirements (16) in ODS ++ ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++#error ABSL_HAVE_INTRINSIC_INT128 cannot be directly set ++#elif defined(__SIZEOF_INT128__) ++#if (defined(__clang__) && !defined(_WIN32)) || \ ++ (defined(__CUDACC__) && __CUDACC_VER_MAJOR__ >= 9) || \ ++ (defined(__GNUC__) && !defined(__clang__) && !defined(__CUDACC__)) ++#define ABSL_HAVE_INTRINSIC_INT128 1 ++#elif defined(__CUDACC__) ++// __CUDACC_VER__ is a full version number before CUDA 9, and is defined to a ++// string explaining that it has been removed starting with CUDA 9. We use ++// nested #ifs because there is no short-circuiting in the preprocessor. ++// NOTE: `__CUDACC__` could be undefined while `__CUDACC_VER__` is defined. ++#if __CUDACC_VER__ >= 70000 ++#define ABSL_HAVE_INTRINSIC_INT128 1 ++#endif // __CUDACC_VER__ >= 70000 ++#endif // defined(__CUDACC__) ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ */ ++#undef ABSL_HAVE_INTRINSIC_INT128 ++ ++// ABSL_HAVE_EXCEPTIONS ++// ++// Checks whether the compiler both supports and enables exceptions. Many ++// compilers support a "no exceptions" mode that disables exceptions. ++// ++// Generally, when ABSL_HAVE_EXCEPTIONS is not defined: ++// ++// * Code using `throw` and `try` may not compile. ++// * The `noexcept` specifier will still compile and behave as normal. ++// * The `noexcept` operator may still return `false`. ++// ++// For further details, consult the compiler's documentation. ++#ifdef ABSL_HAVE_EXCEPTIONS ++#error ABSL_HAVE_EXCEPTIONS cannot be directly set. ++#elif ABSL_INTERNAL_HAVE_MIN_CLANG_VERSION(3, 6) ++// Clang >= 3.6 ++#if ABSL_HAVE_FEATURE(cxx_exceptions) ++#define ABSL_HAVE_EXCEPTIONS 1 ++#endif // ABSL_HAVE_FEATURE(cxx_exceptions) ++#elif defined(__clang__) ++// Clang < 3.6 ++// http://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html#the-exceptions-macro ++#if defined(__EXCEPTIONS) && ABSL_HAVE_FEATURE(cxx_exceptions) ++#define ABSL_HAVE_EXCEPTIONS 1 ++#endif // defined(__EXCEPTIONS) && ABSL_HAVE_FEATURE(cxx_exceptions) ++// Handle remaining special cases and default to exceptions being supported. ++#elif !(defined(__GNUC__) && (__GNUC__ < 5) && !defined(__EXCEPTIONS)) && \ ++ !(ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(5, 0) && \ ++ !defined(__cpp_exceptions)) && \ ++ !(defined(_MSC_VER) && !defined(_CPPUNWIND)) ++#define ABSL_HAVE_EXCEPTIONS 1 ++#endif ++ ++// ----------------------------------------------------------------------------- ++// Platform Feature Checks ++// ----------------------------------------------------------------------------- ++ ++// Currently supported operating systems and associated preprocessor ++// symbols: ++// ++// Linux and Linux-derived __linux__ ++// Android __ANDROID__ (implies __linux__) ++// Linux (non-Android) __linux__ && !__ANDROID__ ++// Darwin (macOS and iOS) __APPLE__ ++// Akaros (http://akaros.org) __ros__ ++// Windows _WIN32 ++// NaCL __native_client__ ++// AsmJS __asmjs__ ++// WebAssembly __wasm__ ++// Fuchsia __Fuchsia__ ++// ++// Note that since Android defines both __ANDROID__ and __linux__, one ++// may probe for either Linux or Android by simply testing for __linux__. ++ ++// ABSL_HAVE_MMAP ++// ++// Checks whether the platform has an mmap(2) implementation as defined in ++// POSIX.1-2001. ++#ifdef ABSL_HAVE_MMAP ++#error ABSL_HAVE_MMAP cannot be directly set ++#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \ ++ defined(__ros__) || defined(__native_client__) || defined(__asmjs__) || \ ++ defined(__wasm__) || defined(__Fuchsia__) || defined(__sun) || \ ++ defined(__ASYLO__) || defined(__myriad2__) ++#define ABSL_HAVE_MMAP 1 ++#endif ++ ++// ABSL_HAVE_PTHREAD_GETSCHEDPARAM ++// ++// Checks whether the platform implements the pthread_(get|set)schedparam(3) ++// functions as defined in POSIX.1-2001. ++#ifdef ABSL_HAVE_PTHREAD_GETSCHEDPARAM ++#error ABSL_HAVE_PTHREAD_GETSCHEDPARAM cannot be directly set ++#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \ ++ defined(__ros__) ++#define ABSL_HAVE_PTHREAD_GETSCHEDPARAM 1 ++#endif ++ ++// ABSL_HAVE_SCHED_GETCPU ++// ++// Checks whether sched_getcpu is available. ++#ifdef ABSL_HAVE_SCHED_GETCPU ++#error ABSL_HAVE_SCHED_GETCPU cannot be directly set ++#elif defined(__linux__) ++#define ABSL_HAVE_SCHED_GETCPU 1 ++#endif ++ ++// ABSL_HAVE_SCHED_YIELD ++// ++// Checks whether the platform implements sched_yield(2) as defined in ++// POSIX.1-2001. ++#ifdef ABSL_HAVE_SCHED_YIELD ++#error ABSL_HAVE_SCHED_YIELD cannot be directly set ++#elif defined(__linux__) || defined(__ros__) || defined(__native_client__) ++#define ABSL_HAVE_SCHED_YIELD 1 ++#endif ++ ++// ABSL_HAVE_SEMAPHORE_H ++// ++// Checks whether the platform supports the header and sem_init(3) ++// family of functions as standardized in POSIX.1-2001. ++// ++// Note: While Apple provides for both iOS and macOS, it is ++// explicitly deprecated and will cause build failures if enabled for those ++// platforms. We side-step the issue by not defining it here for Apple ++// platforms. ++#ifdef ABSL_HAVE_SEMAPHORE_H ++#error ABSL_HAVE_SEMAPHORE_H cannot be directly set ++#elif defined(__linux__) || defined(__ros__) ++#define ABSL_HAVE_SEMAPHORE_H 1 ++#endif ++ ++// ABSL_HAVE_ALARM ++// ++// Checks whether the platform supports the header and alarm(2) ++// function as standardized in POSIX.1-2001. ++#ifdef ABSL_HAVE_ALARM ++#error ABSL_HAVE_ALARM cannot be directly set ++#elif defined(__GOOGLE_GRTE_VERSION__) ++// feature tests for Google's GRTE ++#define ABSL_HAVE_ALARM 1 ++#elif defined(__GLIBC__) ++// feature test for glibc ++#define ABSL_HAVE_ALARM 1 ++#elif defined(_MSC_VER) ++// feature tests for Microsoft's library ++#elif defined(__MINGW32__) ++// mingw32 doesn't provide alarm(2): ++// https://osdn.net/projects/mingw/scm/git/mingw-org-wsl/blobs/5.2-trunk/mingwrt/include/unistd.h ++// mingw-w64 provides a no-op implementation: ++// https://sourceforge.net/p/mingw-w64/mingw-w64/ci/master/tree/mingw-w64-crt/misc/alarm.c ++#elif defined(__EMSCRIPTEN__) ++// emscripten doesn't support signals ++#elif defined(__Fuchsia__) ++// Signals don't exist on fuchsia. ++#elif defined(__native_client__) ++#else ++// other standard libraries ++#define ABSL_HAVE_ALARM 1 ++#endif ++ ++// ABSL_IS_LITTLE_ENDIAN ++// ABSL_IS_BIG_ENDIAN ++// ++// Checks the endianness of the platform. ++// ++// Notes: uses the built in endian macros provided by GCC (since 4.6) and ++// Clang (since 3.2); see ++// https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html. ++// Otherwise, if _WIN32, assume little endian. Otherwise, bail with an error. ++#if defined(ABSL_IS_BIG_ENDIAN) ++#error "ABSL_IS_BIG_ENDIAN cannot be directly set." ++#endif ++#if defined(ABSL_IS_LITTLE_ENDIAN) ++#error "ABSL_IS_LITTLE_ENDIAN cannot be directly set." ++#endif ++ ++#if (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \ ++ __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) ++#define ABSL_IS_LITTLE_ENDIAN 1 ++#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \ ++ __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ++#define ABSL_IS_BIG_ENDIAN 1 ++#elif defined(_WIN32) ++#define ABSL_IS_LITTLE_ENDIAN 1 ++#else ++#error "absl endian detection needs to be set up for your compiler" ++#endif ++ ++// macOS 10.13 and iOS 10.11 don't let you use , , or ++// even though the headers exist and are publicly noted to work. See ++// https://github.com/abseil/abseil-cpp/issues/207 and ++// https://developer.apple.com/documentation/xcode_release_notes/xcode_10_release_notes ++// libc++ spells out the availability requirements in the file ++// llvm-project/libcxx/include/__config via the #define ++// _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS. ++#if defined(__APPLE__) && defined(_LIBCPP_VERSION) && \ ++ ((defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \ ++ __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101400) || \ ++ (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && \ ++ __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 120000) || \ ++ (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && \ ++ __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 50000) || \ ++ (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && \ ++ __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 120000)) ++#define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 1 ++#else ++#define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 0 ++#endif ++ ++// ABSL_HAVE_STD_ANY ++// ++// Checks whether C++17 std::any is available by checking whether exists. ++#ifdef ABSL_HAVE_STD_ANY ++#error "ABSL_HAVE_STD_ANY cannot be directly set." ++#endif ++ ++#ifdef __has_include ++#if __has_include() && defined(__cplusplus) && __cplusplus >= 201703L && \ ++ !ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE ++#define ABSL_HAVE_STD_ANY 1 ++#endif ++#endif ++ ++// ABSL_HAVE_STD_OPTIONAL ++// ++// Checks whether C++17 std::optional is available. ++#ifdef ABSL_HAVE_STD_OPTIONAL ++#error "ABSL_HAVE_STD_OPTIONAL cannot be directly set." ++#endif ++ ++#ifdef __has_include ++#if __has_include() && defined(__cplusplus) && \ ++ __cplusplus >= 201703L && !ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE ++#define ABSL_HAVE_STD_OPTIONAL 1 ++#endif ++#endif ++ ++// ABSL_HAVE_STD_VARIANT ++// ++// Checks whether C++17 std::variant is available. ++#ifdef ABSL_HAVE_STD_VARIANT ++#error "ABSL_HAVE_STD_VARIANT cannot be directly set." ++#endif ++ ++#ifdef __has_include ++#if __has_include() && defined(__cplusplus) && \ ++ __cplusplus >= 201703L && !ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE ++#define ABSL_HAVE_STD_VARIANT 1 ++#endif ++#endif ++ ++// ABSL_HAVE_STD_STRING_VIEW ++// ++// Checks whether C++17 std::string_view is available. ++#ifdef ABSL_HAVE_STD_STRING_VIEW ++#error "ABSL_HAVE_STD_STRING_VIEW cannot be directly set." ++#endif ++ ++#ifdef __has_include ++#if __has_include() && defined(__cplusplus) && \ ++ __cplusplus >= 201703L ++#define ABSL_HAVE_STD_STRING_VIEW 1 ++#endif ++#endif ++ ++// For MSVC, `__has_include` is supported in VS 2017 15.3, which is later than ++// the support for , , , . So we use ++// _MSC_VER to check whether we have VS 2017 RTM (when , , ++// , is implemented) or higher. Also, `__cplusplus` is ++// not correctly set by MSVC, so we use `_MSVC_LANG` to check the language ++// version. ++// TODO(zhangxy): fix tests before enabling aliasing for `std::any`. ++#if defined(_MSC_VER) && _MSC_VER >= 1910 && \ ++ ((defined(_MSVC_LANG) && _MSVC_LANG > 201402) || \ ++ (defined(__cplusplus) && __cplusplus > 201402)) ++// #define ABSL_HAVE_STD_ANY 1 ++#define ABSL_HAVE_STD_OPTIONAL 1 ++#define ABSL_HAVE_STD_VARIANT 1 ++#define ABSL_HAVE_STD_STRING_VIEW 1 ++#endif ++ ++// ABSL_USES_STD_ANY ++// ++// Indicates whether absl::any is an alias for std::any. ++#if !defined(ABSL_OPTION_USE_STD_ANY) ++#error options.h is misconfigured. ++#elif ABSL_OPTION_USE_STD_ANY == 0 || \ ++ (ABSL_OPTION_USE_STD_ANY == 2 && !defined(ABSL_HAVE_STD_ANY)) ++#undef ABSL_USES_STD_ANY ++#elif ABSL_OPTION_USE_STD_ANY == 1 || \ ++ (ABSL_OPTION_USE_STD_ANY == 2 && defined(ABSL_HAVE_STD_ANY)) ++#define ABSL_USES_STD_ANY 1 ++#else ++#error options.h is misconfigured. ++#endif ++ ++// ABSL_USES_STD_OPTIONAL ++// ++// Indicates whether absl::optional is an alias for std::optional. ++#if !defined(ABSL_OPTION_USE_STD_OPTIONAL) ++#error options.h is misconfigured. ++#elif ABSL_OPTION_USE_STD_OPTIONAL == 0 || \ ++ (ABSL_OPTION_USE_STD_OPTIONAL == 2 && !defined(ABSL_HAVE_STD_OPTIONAL)) ++#undef ABSL_USES_STD_OPTIONAL ++#elif ABSL_OPTION_USE_STD_OPTIONAL == 1 || \ ++ (ABSL_OPTION_USE_STD_OPTIONAL == 2 && defined(ABSL_HAVE_STD_OPTIONAL)) ++#define ABSL_USES_STD_OPTIONAL 1 ++#else ++#error options.h is misconfigured. ++#endif ++ ++// ABSL_USES_STD_VARIANT ++// ++// Indicates whether absl::variant is an alias for std::variant. ++#if !defined(ABSL_OPTION_USE_STD_VARIANT) ++#error options.h is misconfigured. ++#elif ABSL_OPTION_USE_STD_VARIANT == 0 || \ ++ (ABSL_OPTION_USE_STD_VARIANT == 2 && !defined(ABSL_HAVE_STD_VARIANT)) ++#undef ABSL_USES_STD_VARIANT ++#elif ABSL_OPTION_USE_STD_VARIANT == 1 || \ ++ (ABSL_OPTION_USE_STD_VARIANT == 2 && defined(ABSL_HAVE_STD_VARIANT)) ++#define ABSL_USES_STD_VARIANT 1 ++#else ++#error options.h is misconfigured. ++#endif ++ ++// ABSL_USES_STD_STRING_VIEW ++// ++// Indicates whether absl::string_view is an alias for std::string_view. ++#if !defined(ABSL_OPTION_USE_STD_STRING_VIEW) ++#error options.h is misconfigured. ++#elif ABSL_OPTION_USE_STD_STRING_VIEW == 0 || \ ++ (ABSL_OPTION_USE_STD_STRING_VIEW == 2 && \ ++ !defined(ABSL_HAVE_STD_STRING_VIEW)) ++#undef ABSL_USES_STD_STRING_VIEW ++#elif ABSL_OPTION_USE_STD_STRING_VIEW == 1 || \ ++ (ABSL_OPTION_USE_STD_STRING_VIEW == 2 && \ ++ defined(ABSL_HAVE_STD_STRING_VIEW)) ++#define ABSL_USES_STD_STRING_VIEW 1 ++#else ++#error options.h is misconfigured. ++#endif ++ ++// In debug mode, MSVC 2017's std::variant throws a EXCEPTION_ACCESS_VIOLATION ++// SEH exception from emplace for variant when constructing the ++// struct can throw. This defeats some of variant_test and ++// variant_exception_safety_test. ++#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_DEBUG) ++#define ABSL_INTERNAL_MSVC_2017_DBG_MODE ++#endif ++ ++// ABSL_INTERNAL_MANGLED_NS ++// ABSL_INTERNAL_MANGLED_BACKREFERENCE ++// ++// Internal macros for building up mangled names in our internal fork of CCTZ. ++// This implementation detail is only needed and provided for the MSVC build. ++// ++// These macros both expand to string literals. ABSL_INTERNAL_MANGLED_NS is ++// the mangled spelling of the `absl` namespace, and ++// ABSL_INTERNAL_MANGLED_BACKREFERENCE is a back-reference integer representing ++// the proper count to skip past the CCTZ fork namespace names. (This number ++// is one larger when there is an inline namespace name to skip.) ++#if defined(_MSC_VER) ++#if ABSL_OPTION_USE_INLINE_NAMESPACE == 0 ++#define ABSL_INTERNAL_MANGLED_NS "absl" ++#define ABSL_INTERNAL_MANGLED_BACKREFERENCE "5" ++#else ++#define ABSL_INTERNAL_MANGLED_NS \ ++ ABSL_INTERNAL_TOKEN_STR(ABSL_OPTION_INLINE_NAMESPACE_NAME) "@absl" ++#define ABSL_INTERNAL_MANGLED_BACKREFERENCE "6" ++#endif ++#endif ++ ++#undef ABSL_INTERNAL_HAS_KEYWORD ++ ++// ABSL_DLL ++// ++// When building Abseil as a DLL, this macro expands to `__declspec(dllexport)` ++// so we can annotate symbols appropriately as being exported. When used in ++// headers consuming a DLL, this macro expands to `__declspec(dllimport)` so ++// that consumers know the symbol is defined inside the DLL. In all other cases, ++// the macro expands to nothing. ++#if defined(_MSC_VER) ++#if defined(ABSL_BUILD_DLL) ++#define ABSL_DLL __declspec(dllexport) ++#elif defined(ABSL_CONSUME_DLL) ++#define ABSL_DLL __declspec(dllimport) ++#else ++#define ABSL_DLL ++#endif ++#else ++#define ABSL_DLL ++#endif // defined(_MSC_VER) ++ ++// ABSL_HAVE_MEMORY_SANITIZER ++// ++// MemorySanitizer (MSan) is a detector of uninitialized reads. It consists of ++// a compiler instrumentation module and a run-time library. ++#ifdef ABSL_HAVE_MEMORY_SANITIZER ++#error "ABSL_HAVE_MEMORY_SANITIZER cannot be directly set." ++#elif defined(__SANITIZE_MEMORY__) ++#define ABSL_HAVE_MEMORY_SANITIZER 1 ++#elif !defined(__native_client__) && ABSL_HAVE_FEATURE(memory_sanitizer) ++#define ABSL_HAVE_MEMORY_SANITIZER 1 ++#endif ++ ++// ABSL_HAVE_THREAD_SANITIZER ++// ++// ThreadSanitizer (TSan) is a fast data race detector. ++#ifdef ABSL_HAVE_THREAD_SANITIZER ++#error "ABSL_HAVE_THREAD_SANITIZER cannot be directly set." ++#elif defined(__SANITIZE_THREAD__) ++#define ABSL_HAVE_THREAD_SANITIZER 1 ++#elif ABSL_HAVE_FEATURE(thread_sanitizer) ++#define ABSL_HAVE_THREAD_SANITIZER 1 ++#endif ++ ++// ABSL_HAVE_ADDRESS_SANITIZER ++// ++// AddressSanitizer (ASan) is a fast memory error detector. ++#ifdef ABSL_HAVE_ADDRESS_SANITIZER ++#error "ABSL_HAVE_ADDRESS_SANITIZER cannot be directly set." ++#elif defined(__SANITIZE_ADDRESS__) ++#define ABSL_HAVE_ADDRESS_SANITIZER 1 ++#elif ABSL_HAVE_FEATURE(address_sanitizer) ++#define ABSL_HAVE_ADDRESS_SANITIZER 1 ++#endif ++ ++// ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION ++// ++// Class template argument deduction is a language feature added in C++17. ++#ifdef ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION ++#error "ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION cannot be directly set." ++#elif defined(__cpp_deduction_guides) ++#define ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION 1 ++#endif ++ ++#endif // ABSL_BASE_CONFIG_H_ +diff --git a/extern/int128/absl/base/macros.h b/extern/int128/absl/base/macros.h +new file mode 100644 +index 0000000000..3e085a916b +--- /dev/null ++++ b/extern/int128/absl/base/macros.h +@@ -0,0 +1,158 @@ ++// ++// Copyright 2017 The Abseil Authors. ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// https://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++// ++// ----------------------------------------------------------------------------- ++// File: macros.h ++// ----------------------------------------------------------------------------- ++// ++// This header file defines the set of language macros used within Abseil code. ++// For the set of macros used to determine supported compilers and platforms, ++// see absl/base/config.h instead. ++// ++// This code is compiled directly on many platforms, including client ++// platforms like Windows, Mac, and embedded systems. Before making ++// any changes here, make sure that you're not breaking any platforms. ++ ++#ifndef ABSL_BASE_MACROS_H_ ++#define ABSL_BASE_MACROS_H_ ++ ++#include ++#include ++ ++#include "absl/base/attributes.h" ++#include "absl/base/config.h" ++#include "absl/base/optimization.h" ++#include "absl/base/port.h" ++ ++// ABSL_ARRAYSIZE() ++// ++// Returns the number of elements in an array as a compile-time constant, which ++// can be used in defining new arrays. If you use this macro on a pointer by ++// mistake, you will get a compile-time error. ++#define ABSL_ARRAYSIZE(array) \ ++ (sizeof(::absl::macros_internal::ArraySizeHelper(array))) ++ ++namespace absl { ++ABSL_NAMESPACE_BEGIN ++namespace macros_internal { ++// Note: this internal template function declaration is used by ABSL_ARRAYSIZE. ++// The function doesn't need a definition, as we only use its type. ++template ++auto ArraySizeHelper(const T (&array)[N]) -> char (&)[N]; ++} // namespace macros_internal ++ABSL_NAMESPACE_END ++} // namespace absl ++ ++// ABSL_BAD_CALL_IF() ++// ++// Used on a function overload to trap bad calls: any call that matches the ++// overload will cause a compile-time error. This macro uses a clang-specific ++// "enable_if" attribute, as described at ++// https://clang.llvm.org/docs/AttributeReference.html#enable-if ++// ++// Overloads which use this macro should be bracketed by ++// `#ifdef ABSL_BAD_CALL_IF`. ++// ++// Example: ++// ++// int isdigit(int c); ++// #ifdef ABSL_BAD_CALL_IF ++// int isdigit(int c) ++// ABSL_BAD_CALL_IF(c <= -1 || c > 255, ++// "'c' must have the value of an unsigned char or EOF"); ++// #endif // ABSL_BAD_CALL_IF ++#if ABSL_HAVE_ATTRIBUTE(enable_if) ++#define ABSL_BAD_CALL_IF(expr, msg) \ ++ __attribute__((enable_if(expr, "Bad call trap"), unavailable(msg))) ++#endif ++ ++// ABSL_ASSERT() ++// ++// In C++11, `assert` can't be used portably within constexpr functions. ++// ABSL_ASSERT functions as a runtime assert but works in C++11 constexpr ++// functions. Example: ++// ++// constexpr double Divide(double a, double b) { ++// return ABSL_ASSERT(b != 0), a / b; ++// } ++// ++// This macro is inspired by ++// https://akrzemi1.wordpress.com/2017/05/18/asserts-in-constexpr-functions/ ++#if defined(NDEBUG) ++#define ABSL_ASSERT(expr) \ ++ (false ? static_cast(expr) : static_cast(0)) ++#else ++#define ABSL_ASSERT(expr) \ ++ (ABSL_PREDICT_TRUE((expr)) ? static_cast(0) \ ++ : [] { assert(false && #expr); }()) // NOLINT ++#endif ++ ++// `ABSL_INTERNAL_HARDENING_ABORT()` controls how `ABSL_HARDENING_ASSERT()` ++// aborts the program in release mode (when NDEBUG is defined). The ++// implementation should abort the program as quickly as possible and ideally it ++// should not be possible to ignore the abort request. ++#if (ABSL_HAVE_BUILTIN(__builtin_trap) && \ ++ ABSL_HAVE_BUILTIN(__builtin_unreachable)) || \ ++ (defined(__GNUC__) && !defined(__clang__)) ++#define ABSL_INTERNAL_HARDENING_ABORT() \ ++ do { \ ++ __builtin_trap(); \ ++ __builtin_unreachable(); \ ++ } while (false) ++#else ++#define ABSL_INTERNAL_HARDENING_ABORT() abort() ++#endif ++ ++// ABSL_HARDENING_ASSERT() ++// ++// `ABSL_HARDENING_ASSERT()` is like `ABSL_ASSERT()`, but used to implement ++// runtime assertions that should be enabled in hardened builds even when ++// `NDEBUG` is defined. ++// ++// When `NDEBUG` is not defined, `ABSL_HARDENING_ASSERT()` is identical to ++// `ABSL_ASSERT()`. ++// ++// See `ABSL_OPTION_HARDENED` in `absl/base/options.h` for more information on ++// hardened mode. ++#if ABSL_OPTION_HARDENED == 1 && defined(NDEBUG) ++#define ABSL_HARDENING_ASSERT(expr) \ ++ (ABSL_PREDICT_TRUE((expr)) ? static_cast(0) \ ++ : [] { ABSL_INTERNAL_HARDENING_ABORT(); }()) ++#else ++#define ABSL_HARDENING_ASSERT(expr) ABSL_ASSERT(expr) ++#endif ++ ++#ifdef ABSL_HAVE_EXCEPTIONS ++#define ABSL_INTERNAL_TRY try ++#define ABSL_INTERNAL_CATCH_ANY catch (...) ++#define ABSL_INTERNAL_RETHROW do { throw; } while (false) ++#else // ABSL_HAVE_EXCEPTIONS ++#define ABSL_INTERNAL_TRY if (true) ++#define ABSL_INTERNAL_CATCH_ANY else if (false) ++#define ABSL_INTERNAL_RETHROW do {} while (false) ++#endif // ABSL_HAVE_EXCEPTIONS ++ ++// `ABSL_INTERNAL_UNREACHABLE` is an unreachable statement. A program which ++// reaches one has undefined behavior, and the compiler may optimize ++// accordingly. ++#if defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable) ++#define ABSL_INTERNAL_UNREACHABLE __builtin_unreachable() ++#elif defined(_MSC_VER) ++#define ABSL_INTERNAL_UNREACHABLE __assume(0) ++#else ++#define ABSL_INTERNAL_UNREACHABLE ++#endif ++ ++#endif // ABSL_BASE_MACROS_H_ +diff --git a/extern/int128/absl/base/optimization.h b/extern/int128/absl/base/optimization.h +new file mode 100644 +index 0000000000..d090be1286 +--- /dev/null ++++ b/extern/int128/absl/base/optimization.h +@@ -0,0 +1,244 @@ ++// ++// Copyright 2017 The Abseil Authors. ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// https://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++// ++// ----------------------------------------------------------------------------- ++// File: optimization.h ++// ----------------------------------------------------------------------------- ++// ++// This header file defines portable macros for performance optimization. ++ ++#ifndef ABSL_BASE_OPTIMIZATION_H_ ++#define ABSL_BASE_OPTIMIZATION_H_ ++ ++#include ++ ++#include "absl/base/config.h" ++ ++// ABSL_BLOCK_TAIL_CALL_OPTIMIZATION ++// ++// Instructs the compiler to avoid optimizing tail-call recursion. This macro is ++// useful when you wish to preserve the existing function order within a stack ++// trace for logging, debugging, or profiling purposes. ++// ++// Example: ++// ++// int f() { ++// int result = g(); ++// ABSL_BLOCK_TAIL_CALL_OPTIMIZATION(); ++// return result; ++// } ++#if defined(__pnacl__) ++#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() if (volatile int x = 0) { (void)x; } ++#elif defined(__clang__) ++// Clang will not tail call given inline volatile assembly. ++#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() __asm__ __volatile__("") ++#elif defined(__GNUC__) ++// GCC will not tail call given inline volatile assembly. ++#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() __asm__ __volatile__("") ++#elif defined(_MSC_VER) ++#include ++// The __nop() intrinsic blocks the optimisation. ++#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() __nop() ++#else ++#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() if (volatile int x = 0) { (void)x; } ++#endif ++ ++// ABSL_CACHELINE_SIZE ++// ++// Explicitly defines the size of the L1 cache for purposes of alignment. ++// Setting the cacheline size allows you to specify that certain objects be ++// aligned on a cacheline boundary with `ABSL_CACHELINE_ALIGNED` declarations. ++// (See below.) ++// ++// NOTE: this macro should be replaced with the following C++17 features, when ++// those are generally available: ++// ++// * `std::hardware_constructive_interference_size` ++// * `std::hardware_destructive_interference_size` ++// ++// See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0154r1.html ++// for more information. ++#if defined(__GNUC__) ++// Cache line alignment ++#if defined(__i386__) || defined(__x86_64__) ++#define ABSL_CACHELINE_SIZE 64 ++#elif defined(__powerpc64__) ++#define ABSL_CACHELINE_SIZE 128 ++#elif defined(__aarch64__) ++// We would need to read special register ctr_el0 to find out L1 dcache size. ++// This value is a good estimate based on a real aarch64 machine. ++#define ABSL_CACHELINE_SIZE 64 ++#elif defined(__arm__) ++// Cache line sizes for ARM: These values are not strictly correct since ++// cache line sizes depend on implementations, not architectures. There ++// are even implementations with cache line sizes configurable at boot ++// time. ++#if defined(__ARM_ARCH_5T__) ++#define ABSL_CACHELINE_SIZE 32 ++#elif defined(__ARM_ARCH_7A__) ++#define ABSL_CACHELINE_SIZE 64 ++#endif ++#endif ++ ++#ifndef ABSL_CACHELINE_SIZE ++// A reasonable default guess. Note that overestimates tend to waste more ++// space, while underestimates tend to waste more time. ++#define ABSL_CACHELINE_SIZE 64 ++#endif ++ ++// ABSL_CACHELINE_ALIGNED ++// ++// Indicates that the declared object be cache aligned using ++// `ABSL_CACHELINE_SIZE` (see above). Cacheline aligning objects allows you to ++// load a set of related objects in the L1 cache for performance improvements. ++// Cacheline aligning objects properly allows constructive memory sharing and ++// prevents destructive (or "false") memory sharing. ++// ++// NOTE: callers should replace uses of this macro with `alignas()` using ++// `std::hardware_constructive_interference_size` and/or ++// `std::hardware_destructive_interference_size` when C++17 becomes available to ++// them. ++// ++// See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0154r1.html ++// for more information. ++// ++// On some compilers, `ABSL_CACHELINE_ALIGNED` expands to an `__attribute__` ++// or `__declspec` attribute. For compilers where this is not known to work, ++// the macro expands to nothing. ++// ++// No further guarantees are made here. The result of applying the macro ++// to variables and types is always implementation-defined. ++// ++// WARNING: It is easy to use this attribute incorrectly, even to the point ++// of causing bugs that are difficult to diagnose, crash, etc. It does not ++// of itself guarantee that objects are aligned to a cache line. ++// ++// NOTE: Some compilers are picky about the locations of annotations such as ++// this attribute, so prefer to put it at the beginning of your declaration. ++// For example, ++// ++// ABSL_CACHELINE_ALIGNED static Foo* foo = ... ++// ++// class ABSL_CACHELINE_ALIGNED Bar { ... ++// ++// Recommendations: ++// ++// 1) Consult compiler documentation; this comment is not kept in sync as ++// toolchains evolve. ++// 2) Verify your use has the intended effect. This often requires inspecting ++// the generated machine code. ++// 3) Prefer applying this attribute to individual variables. Avoid ++// applying it to types. This tends to localize the effect. ++#define ABSL_CACHELINE_ALIGNED __attribute__((aligned(ABSL_CACHELINE_SIZE))) ++#elif defined(_MSC_VER) ++#define ABSL_CACHELINE_SIZE 64 ++#define ABSL_CACHELINE_ALIGNED __declspec(align(ABSL_CACHELINE_SIZE)) ++#else ++#define ABSL_CACHELINE_SIZE 64 ++#define ABSL_CACHELINE_ALIGNED ++#endif ++ ++// ABSL_PREDICT_TRUE, ABSL_PREDICT_FALSE ++// ++// Enables the compiler to prioritize compilation using static analysis for ++// likely paths within a boolean branch. ++// ++// Example: ++// ++// if (ABSL_PREDICT_TRUE(expression)) { ++// return result; // Faster if more likely ++// } else { ++// return 0; ++// } ++// ++// Compilers can use the information that a certain branch is not likely to be ++// taken (for instance, a CHECK failure) to optimize for the common case in ++// the absence of better information (ie. compiling gcc with `-fprofile-arcs`). ++// ++// Recommendation: Modern CPUs dynamically predict branch execution paths, ++// typically with accuracy greater than 97%. As a result, annotating every ++// branch in a codebase is likely counterproductive; however, annotating ++// specific branches that are both hot and consistently mispredicted is likely ++// to yield performance improvements. ++#if ABSL_HAVE_BUILTIN(__builtin_expect) || \ ++ (defined(__GNUC__) && !defined(__clang__)) ++#define ABSL_PREDICT_FALSE(x) (__builtin_expect(false || (x), false)) ++#define ABSL_PREDICT_TRUE(x) (__builtin_expect(false || (x), true)) ++#else ++#define ABSL_PREDICT_FALSE(x) (x) ++#define ABSL_PREDICT_TRUE(x) (x) ++#endif ++ ++// ABSL_INTERNAL_ASSUME(cond) ++// Informs the compiler that a condition is always true and that it can assume ++// it to be true for optimization purposes. The call has undefined behavior if ++// the condition is false. ++// In !NDEBUG mode, the condition is checked with an assert(). ++// NOTE: The expression must not have side effects, as it will only be evaluated ++// in some compilation modes and not others. ++// ++// Example: ++// ++// int x = ...; ++// ABSL_INTERNAL_ASSUME(x >= 0); ++// // The compiler can optimize the division to a simple right shift using the ++// // assumption specified above. ++// int y = x / 16; ++// ++#if !defined(NDEBUG) ++#define ABSL_INTERNAL_ASSUME(cond) assert(cond) ++#elif ABSL_HAVE_BUILTIN(__builtin_assume) ++#define ABSL_INTERNAL_ASSUME(cond) __builtin_assume(cond) ++#elif defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable) ++#define ABSL_INTERNAL_ASSUME(cond) \ ++ do { \ ++ if (!(cond)) __builtin_unreachable(); \ ++ } while (0) ++#elif defined(_MSC_VER) ++#define ABSL_INTERNAL_ASSUME(cond) __assume(cond) ++#else ++#define ABSL_INTERNAL_ASSUME(cond) \ ++ do { \ ++ static_cast(false && (cond)); \ ++ } while (0) ++#endif ++ ++// ABSL_INTERNAL_UNIQUE_SMALL_NAME(cond) ++// This macro forces small unique name on a static file level symbols like ++// static local variables or static functions. This is intended to be used in ++// macro definitions to optimize the cost of generated code. Do NOT use it on ++// symbols exported from translation unit since it may cause a link time ++// conflict. ++// ++// Example: ++// ++// #define MY_MACRO(txt) ++// namespace { ++// char VeryVeryLongVarName[] ABSL_INTERNAL_UNIQUE_SMALL_NAME() = txt; ++// const char* VeryVeryLongFuncName() ABSL_INTERNAL_UNIQUE_SMALL_NAME(); ++// const char* VeryVeryLongFuncName() { return txt; } ++// } ++// ++ ++#if defined(__GNUC__) ++#define ABSL_INTERNAL_UNIQUE_SMALL_NAME2(x) #x ++#define ABSL_INTERNAL_UNIQUE_SMALL_NAME1(x) ABSL_INTERNAL_UNIQUE_SMALL_NAME2(x) ++#define ABSL_INTERNAL_UNIQUE_SMALL_NAME() \ ++ asm(ABSL_INTERNAL_UNIQUE_SMALL_NAME1(.absl.__COUNTER__)) ++#else ++#define ABSL_INTERNAL_UNIQUE_SMALL_NAME() ++#endif ++ ++#endif // ABSL_BASE_OPTIMIZATION_H_ +diff --git a/extern/int128/absl/base/options.h b/extern/int128/absl/base/options.h +new file mode 100644 +index 0000000000..230bf1eecc +--- /dev/null ++++ b/extern/int128/absl/base/options.h +@@ -0,0 +1,238 @@ ++// Copyright 2019 The Abseil Authors. ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// https://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++// ++// ----------------------------------------------------------------------------- ++// File: options.h ++// ----------------------------------------------------------------------------- ++// ++// This file contains Abseil configuration options for setting specific ++// implementations instead of letting Abseil determine which implementation to ++// use at compile-time. Setting these options may be useful for package or build ++// managers who wish to guarantee ABI stability within binary builds (which are ++// otherwise difficult to enforce). ++// ++// *** IMPORTANT NOTICE FOR PACKAGE MANAGERS: It is important that ++// maintainers of package managers who wish to package Abseil read and ++// understand this file! *** ++// ++// Abseil contains a number of possible configuration endpoints, based on ++// parameters such as the detected platform, language version, or command-line ++// flags used to invoke the underlying binary. As is the case with all ++// libraries, binaries which contain Abseil code must ensure that separate ++// packages use the same compiled copy of Abseil to avoid a diamond dependency ++// problem, which can occur if two packages built with different Abseil ++// configuration settings are linked together. Diamond dependency problems in ++// C++ may manifest as violations to the One Definition Rule (ODR) (resulting in ++// linker errors), or undefined behavior (resulting in crashes). ++// ++// Diamond dependency problems can be avoided if all packages utilize the same ++// exact version of Abseil. Building from source code with the same compilation ++// parameters is the easiest way to avoid such dependency problems. However, for ++// package managers who cannot control such compilation parameters, we are ++// providing the file to allow you to inject ABI (Application Binary Interface) ++// stability across builds. Settings options in this file will neither change ++// API nor ABI, providing a stable copy of Abseil between packages. ++// ++// Care must be taken to keep options within these configurations isolated ++// from any other dynamic settings, such as command-line flags which could alter ++// these options. This file is provided specifically to help build and package ++// managers provide a stable copy of Abseil within their libraries and binaries; ++// other developers should not have need to alter the contents of this file. ++// ++// ----------------------------------------------------------------------------- ++// Usage ++// ----------------------------------------------------------------------------- ++// ++// For any particular package release, set the appropriate definitions within ++// this file to whatever value makes the most sense for your package(s). Note ++// that, by default, most of these options, at the moment, affect the ++// implementation of types; future options may affect other implementation ++// details. ++// ++// NOTE: the defaults within this file all assume that Abseil can select the ++// proper Abseil implementation at compile-time, which will not be sufficient ++// to guarantee ABI stability to package managers. ++ ++#ifndef ABSL_BASE_OPTIONS_H_ ++#define ABSL_BASE_OPTIONS_H_ ++ ++// Include a standard library header to allow configuration based on the ++// standard library in use. ++#ifdef __cplusplus ++#include ++#endif ++ ++// ----------------------------------------------------------------------------- ++// Type Compatibility Options ++// ----------------------------------------------------------------------------- ++// ++// ABSL_OPTION_USE_STD_ANY ++// ++// This option controls whether absl::any is implemented as an alias to ++// std::any, or as an independent implementation. ++// ++// A value of 0 means to use Abseil's implementation. This requires only C++11 ++// support, and is expected to work on every toolchain we support. ++// ++// A value of 1 means to use an alias to std::any. This requires that all code ++// using Abseil is built in C++17 mode or later. ++// ++// A value of 2 means to detect the C++ version being used to compile Abseil, ++// and use an alias only if a working std::any is available. This option is ++// useful when you are building your entire program, including all of its ++// dependencies, from source. It should not be used otherwise -- for example, ++// if you are distributing Abseil in a binary package manager -- since in ++// mode 2, absl::any will name a different type, with a different mangled name ++// and binary layout, depending on the compiler flags passed by the end user. ++// For more info, see https://abseil.io/about/design/dropin-types. ++// ++// User code should not inspect this macro. To check in the preprocessor if ++// absl::any is a typedef of std::any, use the feature macro ABSL_USES_STD_ANY. ++ ++#define ABSL_OPTION_USE_STD_ANY 2 ++ ++ ++// ABSL_OPTION_USE_STD_OPTIONAL ++// ++// This option controls whether absl::optional is implemented as an alias to ++// std::optional, or as an independent implementation. ++// ++// A value of 0 means to use Abseil's implementation. This requires only C++11 ++// support, and is expected to work on every toolchain we support. ++// ++// A value of 1 means to use an alias to std::optional. This requires that all ++// code using Abseil is built in C++17 mode or later. ++// ++// A value of 2 means to detect the C++ version being used to compile Abseil, ++// and use an alias only if a working std::optional is available. This option ++// is useful when you are building your program from source. It should not be ++// used otherwise -- for example, if you are distributing Abseil in a binary ++// package manager -- since in mode 2, absl::optional will name a different ++// type, with a different mangled name and binary layout, depending on the ++// compiler flags passed by the end user. For more info, see ++// https://abseil.io/about/design/dropin-types. ++ ++// User code should not inspect this macro. To check in the preprocessor if ++// absl::optional is a typedef of std::optional, use the feature macro ++// ABSL_USES_STD_OPTIONAL. ++ ++#define ABSL_OPTION_USE_STD_OPTIONAL 2 ++ ++ ++// ABSL_OPTION_USE_STD_STRING_VIEW ++// ++// This option controls whether absl::string_view is implemented as an alias to ++// std::string_view, or as an independent implementation. ++// ++// A value of 0 means to use Abseil's implementation. This requires only C++11 ++// support, and is expected to work on every toolchain we support. ++// ++// A value of 1 means to use an alias to std::string_view. This requires that ++// all code using Abseil is built in C++17 mode or later. ++// ++// A value of 2 means to detect the C++ version being used to compile Abseil, ++// and use an alias only if a working std::string_view is available. This ++// option is useful when you are building your program from source. It should ++// not be used otherwise -- for example, if you are distributing Abseil in a ++// binary package manager -- since in mode 2, absl::string_view will name a ++// different type, with a different mangled name and binary layout, depending on ++// the compiler flags passed by the end user. For more info, see ++// https://abseil.io/about/design/dropin-types. ++// ++// User code should not inspect this macro. To check in the preprocessor if ++// absl::string_view is a typedef of std::string_view, use the feature macro ++// ABSL_USES_STD_STRING_VIEW. ++ ++#define ABSL_OPTION_USE_STD_STRING_VIEW 2 ++ ++// ABSL_OPTION_USE_STD_VARIANT ++// ++// This option controls whether absl::variant is implemented as an alias to ++// std::variant, or as an independent implementation. ++// ++// A value of 0 means to use Abseil's implementation. This requires only C++11 ++// support, and is expected to work on every toolchain we support. ++// ++// A value of 1 means to use an alias to std::variant. This requires that all ++// code using Abseil is built in C++17 mode or later. ++// ++// A value of 2 means to detect the C++ version being used to compile Abseil, ++// and use an alias only if a working std::variant is available. This option ++// is useful when you are building your program from source. It should not be ++// used otherwise -- for example, if you are distributing Abseil in a binary ++// package manager -- since in mode 2, absl::variant will name a different ++// type, with a different mangled name and binary layout, depending on the ++// compiler flags passed by the end user. For more info, see ++// https://abseil.io/about/design/dropin-types. ++// ++// User code should not inspect this macro. To check in the preprocessor if ++// absl::variant is a typedef of std::variant, use the feature macro ++// ABSL_USES_STD_VARIANT. ++ ++#define ABSL_OPTION_USE_STD_VARIANT 2 ++ ++ ++// ABSL_OPTION_USE_INLINE_NAMESPACE ++// ABSL_OPTION_INLINE_NAMESPACE_NAME ++// ++// These options controls whether all entities in the absl namespace are ++// contained within an inner inline namespace. This does not affect the ++// user-visible API of Abseil, but it changes the mangled names of all symbols. ++// ++// This can be useful as a version tag if you are distributing Abseil in ++// precompiled form. This will prevent a binary library build of Abseil with ++// one inline namespace being used with headers configured with a different ++// inline namespace name. Binary packagers are reminded that Abseil does not ++// guarantee any ABI stability in Abseil, so any update of Abseil or ++// configuration change in such a binary package should be combined with a ++// new, unique value for the inline namespace name. ++// ++// A value of 0 means not to use inline namespaces. ++// ++// A value of 1 means to use an inline namespace with the given name inside ++// namespace absl. If this is set, ABSL_OPTION_INLINE_NAMESPACE_NAME must also ++// be changed to a new, unique identifier name. In particular "head" is not ++// allowed. ++ ++#define ABSL_OPTION_USE_INLINE_NAMESPACE 0 ++#define ABSL_OPTION_INLINE_NAMESPACE_NAME head ++ ++// ABSL_OPTION_HARDENED ++// ++// This option enables a "hardened" build in release mode (in this context, ++// release mode is defined as a build where the `NDEBUG` macro is defined). ++// ++// A value of 0 means that "hardened" mode is not enabled. ++// ++// A value of 1 means that "hardened" mode is enabled. ++// ++// Hardened builds have additional security checks enabled when `NDEBUG` is ++// defined. Defining `NDEBUG` is normally used to turn `assert()` macro into a ++// no-op, as well as disabling other bespoke program consistency checks. By ++// defining ABSL_OPTION_HARDENED to 1, a select set of checks remain enabled in ++// release mode. These checks guard against programming errors that may lead to ++// security vulnerabilities. In release mode, when one of these programming ++// errors is encountered, the program will immediately abort, possibly without ++// any attempt at logging. ++// ++// The checks enabled by this option are not free; they do incur runtime cost. ++// ++// The checks enabled by this option are always active when `NDEBUG` is not ++// defined, even in the case when ABSL_OPTION_HARDENED is defined to 0. The ++// checks enabled by this option may abort the program in a different way and ++// log additional information when `NDEBUG` is not defined. ++ ++#define ABSL_OPTION_HARDENED 0 ++ ++#endif // ABSL_BASE_OPTIONS_H_ +diff --git a/extern/int128/absl/base/policy_checks.h b/extern/int128/absl/base/policy_checks.h +new file mode 100644 +index 0000000000..06b3243916 +--- /dev/null ++++ b/extern/int128/absl/base/policy_checks.h +@@ -0,0 +1,111 @@ ++// Copyright 2017 The Abseil Authors. ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// https://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++// ++// ----------------------------------------------------------------------------- ++// File: policy_checks.h ++// ----------------------------------------------------------------------------- ++// ++// This header enforces a minimum set of policies at build time, such as the ++// supported compiler and library versions. Unsupported configurations are ++// reported with `#error`. This enforcement is best effort, so successfully ++// compiling this header does not guarantee a supported configuration. ++ ++#ifndef ABSL_BASE_POLICY_CHECKS_H_ ++#define ABSL_BASE_POLICY_CHECKS_H_ ++ ++// Included for the __GLIBC_PREREQ macro used below. ++#include ++ ++// Included for the _STLPORT_VERSION macro used below. ++#if defined(__cplusplus) ++#include ++#endif ++ ++// ----------------------------------------------------------------------------- ++// Operating System Check ++// ----------------------------------------------------------------------------- ++ ++#if defined(__CYGWIN__) ++#error "Cygwin is not supported." ++#endif ++ ++// ----------------------------------------------------------------------------- ++// Toolchain Check ++// ----------------------------------------------------------------------------- ++ ++// We support MSVC++ 14.0 update 2 and later. ++// This minimum will go up. ++#if defined(_MSC_FULL_VER) && _MSC_FULL_VER < 190023918 && !defined(__clang__) ++#error "This package requires Visual Studio 2015 Update 2 or higher." ++#endif ++ ++// We support gcc 4.7 and later. ++// This minimum will go up. ++#if defined(__GNUC__) && !defined(__clang__) ++#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7) ++#error "This package requires gcc 4.7 or higher." ++#endif ++#endif ++ ++// We support Apple Xcode clang 4.2.1 (version 421.11.65) and later. ++// This corresponds to Apple Xcode version 4.5. ++// This minimum will go up. ++#if defined(__apple_build_version__) && __apple_build_version__ < 4211165 ++#error "This package requires __apple_build_version__ of 4211165 or higher." ++#endif ++ ++// ----------------------------------------------------------------------------- ++// C++ Version Check ++// ----------------------------------------------------------------------------- ++ ++// Enforce C++11 as the minimum. Note that Visual Studio has not ++// advanced __cplusplus despite being good enough for our purposes, so ++// so we exempt it from the check. ++#if defined(__cplusplus) && !defined(_MSC_VER) ++#if __cplusplus < 201103L ++#error "C++ versions less than C++11 are not supported." ++#endif ++#endif ++ ++// ----------------------------------------------------------------------------- ++// Standard Library Check ++// ----------------------------------------------------------------------------- ++ ++#if defined(_STLPORT_VERSION) ++#error "STLPort is not supported." ++#endif ++ ++// ----------------------------------------------------------------------------- ++// `char` Size Check ++// ----------------------------------------------------------------------------- ++ ++// Abseil currently assumes CHAR_BIT == 8. If you would like to use Abseil on a ++// platform where this is not the case, please provide us with the details about ++// your platform so we can consider relaxing this requirement. ++#if CHAR_BIT != 8 ++#error "Abseil assumes CHAR_BIT == 8." ++#endif ++ ++// ----------------------------------------------------------------------------- ++// `int` Size Check ++// ----------------------------------------------------------------------------- ++ ++// Abseil currently assumes that an int is 4 bytes. If you would like to use ++// Abseil on a platform where this is not the case, please provide us with the ++// details about your platform so we can consider relaxing this requirement. ++#if INT_MAX < 2147483647 ++#error "Abseil assumes that int is at least 4 bytes. " ++#endif ++ ++#endif // ABSL_BASE_POLICY_CHECKS_H_ +diff --git a/extern/int128/absl/base/port.h b/extern/int128/absl/base/port.h +new file mode 100644 +index 0000000000..5bc4d6cd95 +--- /dev/null ++++ b/extern/int128/absl/base/port.h +@@ -0,0 +1,25 @@ ++// Copyright 2017 The Abseil Authors. ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// https://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++// ++// This files is a forwarding header for other headers containing various ++// portability macros and functions. ++ ++#ifndef ABSL_BASE_PORT_H_ ++#define ABSL_BASE_PORT_H_ ++ ++#include "absl/base/attributes.h" ++#include "absl/base/config.h" ++#include "absl/base/optimization.h" ++ ++#endif // ABSL_BASE_PORT_H_ +diff --git a/extern/int128/absl/numeric/Makefile b/extern/int128/absl/numeric/Makefile +new file mode 100644 +index 0000000000..396e95d063 +--- /dev/null ++++ b/extern/int128/absl/numeric/Makefile +@@ -0,0 +1,11 @@ ++LIBRARY=libi128$(CROSS).a ++ ++$(LIBRARY): $(wildcard *.cc) $(wildcard *.h) $(wildcard internal/*.h) $(wildcard ../base/*.h) $(wildcard *.inc) Makefile ++ $(RM) -f *.o ++ $(CXX) $(CROSS_FLAGS) -I../.. -c -O3 -fPIC int128.cc ++ $(AR) crs $(LIBRARY) *.o ++ $(RM) -f *.o ++ ++.PHONY: clean ++clean: ++ $(RM) -f *.o *.a +diff --git a/extern/int128/absl/numeric/bits.h b/extern/int128/absl/numeric/bits.h +new file mode 100644 +index 0000000000..52013ad49b +--- /dev/null ++++ b/extern/int128/absl/numeric/bits.h +@@ -0,0 +1,177 @@ ++// Copyright 2020 The Abseil Authors ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// https://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++// ++// ----------------------------------------------------------------------------- ++// File: bits.h ++// ----------------------------------------------------------------------------- ++// ++// This file contains implementations of C++20's bitwise math functions, as ++// defined by: ++// ++// P0553R4: ++// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0553r4.html ++// P0556R3: ++// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0556r3.html ++// P1355R2: ++// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1355r2.html ++// P1956R1: ++// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1956r1.pdf ++// ++// When using a standard library that implements these functions, we use the ++// standard library's implementation. ++ ++#ifndef ABSL_NUMERIC_BITS_H_ ++#define ABSL_NUMERIC_BITS_H_ ++ ++#include ++#include ++#include ++ ++#if (defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L) || \ ++ (defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L) ++#include ++#endif ++ ++#include "absl/base/attributes.h" ++#include "absl/base/config.h" ++#include "absl/numeric/internal/bits.h" ++ ++namespace absl { ++ABSL_NAMESPACE_BEGIN ++ ++#if !(defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L) ++// rotating ++template ++ABSL_MUST_USE_RESULT constexpr ++ typename std::enable_if::value, T>::type ++ rotl(T x, int s) noexcept { ++ return numeric_internal::RotateLeft(x, s); ++} ++ ++template ++ABSL_MUST_USE_RESULT constexpr ++ typename std::enable_if::value, T>::type ++ rotr(T x, int s) noexcept { ++ return numeric_internal::RotateRight(x, s); ++} ++ ++// Counting functions ++// ++// While these functions are typically constexpr, on some platforms, they may ++// not be marked as constexpr due to constraints of the compiler/available ++// intrinsics. ++template ++ABSL_INTERNAL_CONSTEXPR_CLZ inline ++ typename std::enable_if::value, int>::type ++ countl_zero(T x) noexcept { ++ return numeric_internal::CountLeadingZeroes(x); ++} ++ ++template ++ABSL_INTERNAL_CONSTEXPR_CLZ inline ++ typename std::enable_if::value, int>::type ++ countl_one(T x) noexcept { ++ // Avoid integer promotion to a wider type ++ return countl_zero(static_cast(~x)); ++} ++ ++template ++ABSL_INTERNAL_CONSTEXPR_CTZ inline ++ typename std::enable_if::value, int>::type ++ countr_zero(T x) noexcept { ++ return numeric_internal::CountTrailingZeroes(x); ++} ++ ++template ++ABSL_INTERNAL_CONSTEXPR_CTZ inline ++ typename std::enable_if::value, int>::type ++ countr_one(T x) noexcept { ++ // Avoid integer promotion to a wider type ++ return countr_zero(static_cast(~x)); ++} ++ ++template ++ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline ++ typename std::enable_if::value, int>::type ++ popcount(T x) noexcept { ++ return numeric_internal::Popcount(x); ++} ++#else // defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L ++ ++using std::countl_one; ++using std::countl_zero; ++using std::countr_one; ++using std::countr_zero; ++using std::popcount; ++using std::rotl; ++using std::rotr; ++ ++#endif ++ ++#if !(defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L) ++// Returns: true if x is an integral power of two; false otherwise. ++template ++constexpr inline typename std::enable_if::value, bool>::type ++has_single_bit(T x) noexcept { ++ return x != 0 && (x & (x - 1)) == 0; ++} ++ ++// Returns: If x == 0, 0; otherwise one plus the base-2 logarithm of x, with any ++// fractional part discarded. ++template ++ABSL_INTERNAL_CONSTEXPR_CLZ inline ++ typename std::enable_if::value, T>::type ++ bit_width(T x) noexcept { ++ return std::numeric_limits::digits - countl_zero(x); ++} ++ ++// Returns: If x == 0, 0; otherwise the maximal value y such that ++// has_single_bit(y) is true and y <= x. ++template ++ABSL_INTERNAL_CONSTEXPR_CLZ inline ++ typename std::enable_if::value, T>::type ++ bit_floor(T x) noexcept { ++ return x == 0 ? 0 : T{1} << (bit_width(x) - 1); ++} ++ ++// Returns: N, where N is the smallest power of 2 greater than or equal to x. ++// ++// Preconditions: N is representable as a value of type T. ++template ++ABSL_INTERNAL_CONSTEXPR_CLZ inline ++ typename std::enable_if::value, T>::type ++ bit_ceil(T x) { ++ // If T is narrower than unsigned, T{1} << bit_width will be promoted. We ++ // want to force it to wraparound so that bit_ceil of an invalid value are not ++ // core constant expressions. ++ // ++ // BitCeilNonPowerOf2 triggers an overflow in constexpr contexts if we would ++ // undergo promotion to unsigned but not fit the result into T without ++ // truncation. ++ return has_single_bit(x) ? T{1} << (bit_width(x) - 1) ++ : numeric_internal::BitCeilNonPowerOf2(x); ++} ++#else // defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L ++ ++using std::bit_ceil; ++using std::bit_floor; ++using std::bit_width; ++using std::has_single_bit; ++ ++#endif ++ ++ABSL_NAMESPACE_END ++} // namespace absl ++ ++#endif // ABSL_NUMERIC_BITS_H_ +diff --git a/extern/int128/absl/numeric/int128.cc b/extern/int128/absl/numeric/int128.cc +new file mode 100644 +index 0000000000..17d88744ae +--- /dev/null ++++ b/extern/int128/absl/numeric/int128.cc +@@ -0,0 +1,383 @@ ++// Copyright 2017 The Abseil Authors. ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// https://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++#include "absl/numeric/int128.h" ++ ++#include ++ ++#include ++#include ++#include // NOLINT(readability/streams) ++#include ++#include ++#include ++ ++#include "absl/base/optimization.h" ++#include "absl/numeric/bits.h" ++ ++namespace absl { ++ABSL_NAMESPACE_BEGIN ++ ++ABSL_DLL const uint128 kuint128max = MakeUint128( ++ std::numeric_limits::max(), std::numeric_limits::max()); ++ ++namespace { ++ ++// Returns the 0-based position of the last set bit (i.e., most significant bit) ++// in the given uint128. The argument is not 0. ++// ++// For example: ++// Given: 5 (decimal) == 101 (binary) ++// Returns: 2 ++inline ABSL_ATTRIBUTE_ALWAYS_INLINE int Fls128(uint128 n) { ++ if (uint64_t hi = Uint128High64(n)) { ++ ABSL_INTERNAL_ASSUME(hi != 0); ++ return 127 - countl_zero(hi); ++ } ++ const uint64_t low = Uint128Low64(n); ++ ABSL_INTERNAL_ASSUME(low != 0); ++ return 63 - countl_zero(low); ++} ++ ++// Long division/modulo for uint128 implemented using the shift-subtract ++// division algorithm adapted from: ++// https://stackoverflow.com/questions/5386377/division-without-using ++inline void DivModImpl(uint128 dividend, uint128 divisor, uint128* quotient_ret, ++ uint128* remainder_ret) { ++ assert(divisor != 0); ++ ++ if (divisor > dividend) { ++ *quotient_ret = 0; ++ *remainder_ret = dividend; ++ return; ++ } ++ ++ if (divisor == dividend) { ++ *quotient_ret = 1; ++ *remainder_ret = 0; ++ return; ++ } ++ ++ uint128 denominator = divisor; ++ uint128 quotient = 0; ++ ++ // Left aligns the MSB of the denominator and the dividend. ++ const int shift = Fls128(dividend) - Fls128(denominator); ++ denominator <<= shift; ++ ++ // Uses shift-subtract algorithm to divide dividend by denominator. The ++ // remainder will be left in dividend. ++ for (int i = 0; i <= shift; ++i) { ++ quotient <<= 1; ++ if (dividend >= denominator) { ++ dividend -= denominator; ++ quotient |= 1; ++ } ++ denominator >>= 1; ++ } ++ ++ *quotient_ret = quotient; ++ *remainder_ret = dividend; ++} ++ ++template ++uint128 MakeUint128FromFloat(T v) { ++ static_assert(std::is_floating_point::value, ""); ++ ++ // Rounding behavior is towards zero, same as for built-in types. ++ ++ // Undefined behavior if v is NaN or cannot fit into uint128. ++ assert(std::isfinite(v) && v > -1 && ++ (std::numeric_limits::max_exponent <= 128 || ++ v < std::ldexp(static_cast(1), 128))); ++ ++ if (v >= std::ldexp(static_cast(1), 64)) { ++ uint64_t hi = static_cast(std::ldexp(v, -64)); ++ uint64_t lo = static_cast(v - std::ldexp(static_cast(hi), 64)); ++ return MakeUint128(hi, lo); ++ } ++ ++ return MakeUint128(0, static_cast(v)); ++} ++ ++#if defined(__clang__) && !defined(__SSE3__) ++// Workaround for clang bug: https://bugs.llvm.org/show_bug.cgi?id=38289 ++// Casting from long double to uint64_t is miscompiled and drops bits. ++// It is more work, so only use when we need the workaround. ++uint128 MakeUint128FromFloat(long double v) { ++ // Go 50 bits at a time, that fits in a double ++ static_assert(std::numeric_limits::digits >= 50, ""); ++ static_assert(std::numeric_limits::digits <= 150, ""); ++ // Undefined behavior if v is not finite or cannot fit into uint128. ++ assert(std::isfinite(v) && v > -1 && v < std::ldexp(1.0L, 128)); ++ ++ v = std::ldexp(v, -100); ++ uint64_t w0 = static_cast(static_cast(std::trunc(v))); ++ v = std::ldexp(v - static_cast(w0), 50); ++ uint64_t w1 = static_cast(static_cast(std::trunc(v))); ++ v = std::ldexp(v - static_cast(w1), 50); ++ uint64_t w2 = static_cast(static_cast(std::trunc(v))); ++ return (static_cast(w0) << 100) | (static_cast(w1) << 50) | ++ static_cast(w2); ++} ++#endif // __clang__ && !__SSE3__ ++} // namespace ++ ++uint128::uint128(float v) : uint128(MakeUint128FromFloat(v)) {} ++uint128::uint128(double v) : uint128(MakeUint128FromFloat(v)) {} ++uint128::uint128(long double v) : uint128(MakeUint128FromFloat(v)) {} ++ ++#if !defined(ABSL_HAVE_INTRINSIC_INT128) ++uint128 operator/(uint128 lhs, uint128 rhs) { ++ uint128 quotient = 0; ++ uint128 remainder = 0; ++ DivModImpl(lhs, rhs, "ient, &remainder); ++ return quotient; ++} ++ ++uint128 operator%(uint128 lhs, uint128 rhs) { ++ uint128 quotient = 0; ++ uint128 remainder = 0; ++ DivModImpl(lhs, rhs, "ient, &remainder); ++ return remainder; ++} ++#endif // !defined(ABSL_HAVE_INTRINSIC_INT128) ++ ++namespace { ++ ++std::string Uint128ToFormattedString(uint128 v, std::ios_base::fmtflags flags) { ++ // Select a divisor which is the largest power of the base < 2^64. ++ uint128 div; ++ int div_base_log; ++ switch (flags & std::ios::basefield) { ++ case std::ios::hex: ++ div = 0x1000000000000000; // 16^15 ++ div_base_log = 15; ++ break; ++ case std::ios::oct: ++ div = 01000000000000000000000; // 8^21 ++ div_base_log = 21; ++ break; ++ default: // std::ios::dec ++ div = 10000000000000000000u; // 10^19 ++ div_base_log = 19; ++ break; ++ } ++ ++ // Now piece together the uint128 representation from three chunks of the ++ // original value, each less than "div" and therefore representable as a ++ // uint64_t. ++ std::ostringstream os; ++ std::ios_base::fmtflags copy_mask = ++ std::ios::basefield | std::ios::showbase | std::ios::uppercase; ++ os.setf(flags & copy_mask, copy_mask); ++ uint128 high = v; ++ uint128 low; ++ DivModImpl(high, div, &high, &low); ++ uint128 mid; ++ DivModImpl(high, div, &high, &mid); ++ if (Uint128Low64(high) != 0) { ++ os << Uint128Low64(high); ++ os << std::noshowbase << std::setfill('0') << std::setw(div_base_log); ++ os << Uint128Low64(mid); ++ os << std::setw(div_base_log); ++ } else if (Uint128Low64(mid) != 0) { ++ os << Uint128Low64(mid); ++ os << std::noshowbase << std::setfill('0') << std::setw(div_base_log); ++ } ++ os << Uint128Low64(low); ++ return os.str(); ++} ++ ++} // namespace ++ ++std::ostream& operator<<(std::ostream& os, uint128 v) { ++ std::ios_base::fmtflags flags = os.flags(); ++ std::string rep = Uint128ToFormattedString(v, flags); ++ ++ // Add the requisite padding. ++ std::streamsize width = os.width(0); ++ if (static_cast(width) > rep.size()) { ++ std::ios::fmtflags adjustfield = flags & std::ios::adjustfield; ++ if (adjustfield == std::ios::left) { ++ rep.append(width - rep.size(), os.fill()); ++ } else if (adjustfield == std::ios::internal && ++ (flags & std::ios::showbase) && ++ (flags & std::ios::basefield) == std::ios::hex && v != 0) { ++ rep.insert(2, width - rep.size(), os.fill()); ++ } else { ++ rep.insert(0, width - rep.size(), os.fill()); ++ } ++ } ++ ++ return os << rep; ++} ++ ++namespace { ++ ++uint128 UnsignedAbsoluteValue(int128 v) { ++ // Cast to uint128 before possibly negating because -Int128Min() is undefined. ++ return Int128High64(v) < 0 ? -uint128(v) : uint128(v); ++} ++ ++} // namespace ++ ++#if !defined(ABSL_HAVE_INTRINSIC_INT128) ++namespace { ++ ++template ++int128 MakeInt128FromFloat(T v) { ++ // Conversion when v is NaN or cannot fit into int128 would be undefined ++ // behavior if using an intrinsic 128-bit integer. ++ assert(std::isfinite(v) && (std::numeric_limits::max_exponent <= 127 || ++ (v >= -std::ldexp(static_cast(1), 127) && ++ v < std::ldexp(static_cast(1), 127)))); ++ ++ // We must convert the absolute value and then negate as needed, because ++ // floating point types are typically sign-magnitude. Otherwise, the ++ // difference between the high and low 64 bits when interpreted as two's ++ // complement overwhelms the precision of the mantissa. ++ uint128 result = v < 0 ? -MakeUint128FromFloat(-v) : MakeUint128FromFloat(v); ++ return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(result)), ++ Uint128Low64(result)); ++} ++ ++} // namespace ++ ++int128::int128(float v) : int128(MakeInt128FromFloat(v)) {} ++int128::int128(double v) : int128(MakeInt128FromFloat(v)) {} ++int128::int128(long double v) : int128(MakeInt128FromFloat(v)) {} ++ ++int128 operator/(int128 lhs, int128 rhs) { ++ assert(lhs != Int128Min() || rhs != -1); // UB on two's complement. ++ ++ uint128 quotient = 0; ++ uint128 remainder = 0; ++ DivModImpl(UnsignedAbsoluteValue(lhs), UnsignedAbsoluteValue(rhs), ++ "ient, &remainder); ++ if ((Int128High64(lhs) < 0) != (Int128High64(rhs) < 0)) quotient = -quotient; ++ return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(quotient)), ++ Uint128Low64(quotient)); ++} ++ ++int128 operator%(int128 lhs, int128 rhs) { ++ assert(lhs != Int128Min() || rhs != -1); // UB on two's complement. ++ ++ uint128 quotient = 0; ++ uint128 remainder = 0; ++ DivModImpl(UnsignedAbsoluteValue(lhs), UnsignedAbsoluteValue(rhs), ++ "ient, &remainder); ++ if (Int128High64(lhs) < 0) remainder = -remainder; ++ return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(remainder)), ++ Uint128Low64(remainder)); ++} ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ ++std::ostream& operator<<(std::ostream& os, int128 v) { ++ std::ios_base::fmtflags flags = os.flags(); ++ std::string rep; ++ ++ // Add the sign if needed. ++ bool print_as_decimal = ++ (flags & std::ios::basefield) == std::ios::dec || ++ (flags & std::ios::basefield) == std::ios_base::fmtflags(); ++ if (print_as_decimal) { ++ if (Int128High64(v) < 0) { ++ rep = "-"; ++ } else if (flags & std::ios::showpos) { ++ rep = "+"; ++ } ++ } ++ ++ rep.append(Uint128ToFormattedString( ++ print_as_decimal ? UnsignedAbsoluteValue(v) : uint128(v), os.flags())); ++ ++ // Add the requisite padding. ++ std::streamsize width = os.width(0); ++ if (static_cast(width) > rep.size()) { ++ switch (flags & std::ios::adjustfield) { ++ case std::ios::left: ++ rep.append(width - rep.size(), os.fill()); ++ break; ++ case std::ios::internal: ++ if (print_as_decimal && (rep[0] == '+' || rep[0] == '-')) { ++ rep.insert(1, width - rep.size(), os.fill()); ++ } else if ((flags & std::ios::basefield) == std::ios::hex && ++ (flags & std::ios::showbase) && v != 0) { ++ rep.insert(2, width - rep.size(), os.fill()); ++ } else { ++ rep.insert(0, width - rep.size(), os.fill()); ++ } ++ break; ++ default: // std::ios::right ++ rep.insert(0, width - rep.size(), os.fill()); ++ break; ++ } ++ } ++ ++ return os << rep; ++} ++ ++ABSL_NAMESPACE_END ++} // namespace absl ++ ++namespace std { ++constexpr bool numeric_limits::is_specialized; ++constexpr bool numeric_limits::is_signed; ++constexpr bool numeric_limits::is_integer; ++constexpr bool numeric_limits::is_exact; ++constexpr bool numeric_limits::has_infinity; ++constexpr bool numeric_limits::has_quiet_NaN; ++constexpr bool numeric_limits::has_signaling_NaN; ++constexpr float_denorm_style numeric_limits::has_denorm; ++constexpr bool numeric_limits::has_denorm_loss; ++constexpr float_round_style numeric_limits::round_style; ++constexpr bool numeric_limits::is_iec559; ++constexpr bool numeric_limits::is_bounded; ++constexpr bool numeric_limits::is_modulo; ++constexpr int numeric_limits::digits; ++constexpr int numeric_limits::digits10; ++constexpr int numeric_limits::max_digits10; ++constexpr int numeric_limits::radix; ++constexpr int numeric_limits::min_exponent; ++constexpr int numeric_limits::min_exponent10; ++constexpr int numeric_limits::max_exponent; ++constexpr int numeric_limits::max_exponent10; ++constexpr bool numeric_limits::traps; ++constexpr bool numeric_limits::tinyness_before; ++ ++constexpr bool numeric_limits::is_specialized; ++constexpr bool numeric_limits::is_signed; ++constexpr bool numeric_limits::is_integer; ++constexpr bool numeric_limits::is_exact; ++constexpr bool numeric_limits::has_infinity; ++constexpr bool numeric_limits::has_quiet_NaN; ++constexpr bool numeric_limits::has_signaling_NaN; ++constexpr float_denorm_style numeric_limits::has_denorm; ++constexpr bool numeric_limits::has_denorm_loss; ++constexpr float_round_style numeric_limits::round_style; ++constexpr bool numeric_limits::is_iec559; ++constexpr bool numeric_limits::is_bounded; ++constexpr bool numeric_limits::is_modulo; ++constexpr int numeric_limits::digits; ++constexpr int numeric_limits::digits10; ++constexpr int numeric_limits::max_digits10; ++constexpr int numeric_limits::radix; ++constexpr int numeric_limits::min_exponent; ++constexpr int numeric_limits::min_exponent10; ++constexpr int numeric_limits::max_exponent; ++constexpr int numeric_limits::max_exponent10; ++constexpr bool numeric_limits::traps; ++constexpr bool numeric_limits::tinyness_before; ++} // namespace std +diff --git a/extern/int128/absl/numeric/int128.h b/extern/int128/absl/numeric/int128.h +new file mode 100644 +index 0000000000..a9cbe489dd +--- /dev/null ++++ b/extern/int128/absl/numeric/int128.h +@@ -0,0 +1,1155 @@ ++// ++// Copyright 2017 The Abseil Authors. ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// https://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++// ++// ----------------------------------------------------------------------------- ++// File: int128.h ++// ----------------------------------------------------------------------------- ++// ++// This header file defines 128-bit integer types, `uint128` and `int128`. ++// ++// TODO(absl-team): This module is inconsistent as many inline `uint128` methods ++// are defined in this file, while many inline `int128` methods are defined in ++// the `int128_*_intrinsic.inc` files. ++ ++#ifndef ABSL_NUMERIC_INT128_H_ ++#define ABSL_NUMERIC_INT128_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "absl/base/config.h" ++#include "absl/base/macros.h" ++#include "absl/base/port.h" ++ ++#if defined(_MSC_VER) ++// In very old versions of MSVC and when the /Zc:wchar_t flag is off, wchar_t is ++// a typedef for unsigned short. Otherwise wchar_t is mapped to the __wchar_t ++// builtin type. We need to make sure not to define operator wchar_t() ++// alongside operator unsigned short() in these instances. ++#define ABSL_INTERNAL_WCHAR_T __wchar_t ++#if defined(_M_X64) ++#include ++#pragma intrinsic(_umul128) ++#endif // defined(_M_X64) ++#else // defined(_MSC_VER) ++#define ABSL_INTERNAL_WCHAR_T wchar_t ++#endif // defined(_MSC_VER) ++ ++namespace absl { ++ABSL_NAMESPACE_BEGIN ++ ++class int128; ++ ++// uint128 ++// ++// An unsigned 128-bit integer type. The API is meant to mimic an intrinsic type ++// as closely as is practical, including exhibiting undefined behavior in ++// analogous cases (e.g. division by zero). This type is intended to be a ++// drop-in replacement once C++ supports an intrinsic `uint128_t` type; when ++// that occurs, existing well-behaved uses of `uint128` will continue to work ++// using that new type. ++// ++// Note: code written with this type will continue to compile once `uint128_t` ++// is introduced, provided the replacement helper functions ++// `Uint128(Low|High)64()` and `MakeUint128()` are made. ++// ++// A `uint128` supports the following: ++// ++// * Implicit construction from integral types ++// * Explicit conversion to integral types ++// ++// Additionally, if your compiler supports `__int128`, `uint128` is ++// interoperable with that type. (Abseil checks for this compatibility through ++// the `ABSL_HAVE_INTRINSIC_INT128` macro.) ++// ++// However, a `uint128` differs from intrinsic integral types in the following ++// ways: ++// ++// * Errors on implicit conversions that do not preserve value (such as ++// loss of precision when converting to float values). ++// * Requires explicit construction from and conversion to floating point ++// types. ++// * Conversion to integral types requires an explicit static_cast() to ++// mimic use of the `-Wnarrowing` compiler flag. ++// * The alignment requirement of `uint128` may differ from that of an ++// intrinsic 128-bit integer type depending on platform and build ++// configuration. ++// ++// Example: ++// ++// float y = absl::Uint128Max(); // Error. uint128 cannot be implicitly ++// // converted to float. ++// ++// absl::uint128 v; ++// uint64_t i = v; // Error ++// uint64_t i = static_cast(v); // OK ++// ++class ++#if defined(ABSL_HAVE_INTRINSIC_INT128) ++ alignas(unsigned __int128) ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ uint128 { ++ public: ++ uint128() = default; ++ ++ // Constructors from arithmetic types ++ constexpr uint128(int v); // NOLINT(runtime/explicit) ++ constexpr uint128(unsigned int v); // NOLINT(runtime/explicit) ++ constexpr uint128(long v); // NOLINT(runtime/int) ++ constexpr uint128(unsigned long v); // NOLINT(runtime/int) ++ constexpr uint128(long long v); // NOLINT(runtime/int) ++ constexpr uint128(unsigned long long v); // NOLINT(runtime/int) ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++ constexpr uint128(__int128 v); // NOLINT(runtime/explicit) ++ constexpr uint128(unsigned __int128 v); // NOLINT(runtime/explicit) ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ constexpr uint128(int128 v); // NOLINT(runtime/explicit) ++ explicit uint128(float v); ++ explicit uint128(double v); ++ explicit uint128(long double v); ++ ++ // Assignment operators from arithmetic types ++ uint128& operator=(int v); ++ uint128& operator=(unsigned int v); ++ uint128& operator=(long v); // NOLINT(runtime/int) ++ uint128& operator=(unsigned long v); // NOLINT(runtime/int) ++ uint128& operator=(long long v); // NOLINT(runtime/int) ++ uint128& operator=(unsigned long long v); // NOLINT(runtime/int) ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++ uint128& operator=(__int128 v); ++ uint128& operator=(unsigned __int128 v); ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ uint128& operator=(int128 v); ++ ++ // Conversion operators to other arithmetic types ++ constexpr explicit operator bool() const; ++ constexpr explicit operator char() const; ++ constexpr explicit operator signed char() const; ++ constexpr explicit operator unsigned char() const; ++ constexpr explicit operator char16_t() const; ++ constexpr explicit operator char32_t() const; ++ constexpr explicit operator ABSL_INTERNAL_WCHAR_T() const; ++ constexpr explicit operator short() const; // NOLINT(runtime/int) ++ // NOLINTNEXTLINE(runtime/int) ++ constexpr explicit operator unsigned short() const; ++ constexpr explicit operator int() const; ++ constexpr explicit operator unsigned int() const; ++ constexpr explicit operator long() const; // NOLINT(runtime/int) ++ // NOLINTNEXTLINE(runtime/int) ++ constexpr explicit operator unsigned long() const; ++ // NOLINTNEXTLINE(runtime/int) ++ constexpr explicit operator long long() const; ++ // NOLINTNEXTLINE(runtime/int) ++ constexpr explicit operator unsigned long long() const; ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++ constexpr explicit operator __int128() const; ++ constexpr explicit operator unsigned __int128() const; ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ explicit operator float() const; ++ explicit operator double() const; ++ explicit operator long double() const; ++ ++ // Trivial copy constructor, assignment operator and destructor. ++ ++ // Arithmetic operators. ++ uint128& operator+=(uint128 other); ++ uint128& operator-=(uint128 other); ++ uint128& operator*=(uint128 other); ++ // Long division/modulo for uint128. ++ uint128& operator/=(uint128 other); ++ uint128& operator%=(uint128 other); ++ uint128 operator++(int); ++ uint128 operator--(int); ++ uint128& operator<<=(int); ++ uint128& operator>>=(int); ++ uint128& operator&=(uint128 other); ++ uint128& operator|=(uint128 other); ++ uint128& operator^=(uint128 other); ++ uint128& operator++(); ++ uint128& operator--(); ++ ++ // Uint128Low64() ++ // ++ // Returns the lower 64-bit value of a `uint128` value. ++ friend constexpr uint64_t Uint128Low64(uint128 v); ++ ++ // Uint128High64() ++ // ++ // Returns the higher 64-bit value of a `uint128` value. ++ friend constexpr uint64_t Uint128High64(uint128 v); ++ ++ // MakeUInt128() ++ // ++ // Constructs a `uint128` numeric value from two 64-bit unsigned integers. ++ // Note that this factory function is the only way to construct a `uint128` ++ // from integer values greater than 2^64. ++ // ++ // Example: ++ // ++ // absl::uint128 big = absl::MakeUint128(1, 0); ++ friend constexpr uint128 MakeUint128(uint64_t high, uint64_t low); ++ ++ // Uint128Max() ++ // ++ // Returns the highest value for a 128-bit unsigned integer. ++ friend constexpr uint128 Uint128Max(); ++ ++ // Support for absl::Hash. ++ template ++ friend H AbslHashValue(H h, uint128 v) { ++ return H::combine(std::move(h), Uint128High64(v), Uint128Low64(v)); ++ } ++ ++ private: ++ constexpr uint128(uint64_t high, uint64_t low); ++ ++ // TODO(strel) Update implementation to use __int128 once all users of ++ // uint128 are fixed to not depend on alignof(uint128) == 8. Also add ++ // alignas(16) to class definition to keep alignment consistent across ++ // platforms. ++#if defined(ABSL_IS_LITTLE_ENDIAN) ++ uint64_t lo_; ++ uint64_t hi_; ++#elif defined(ABSL_IS_BIG_ENDIAN) ++ uint64_t hi_; ++ uint64_t lo_; ++#else // byte order ++#error "Unsupported byte order: must be little-endian or big-endian." ++#endif // byte order ++}; ++ ++// Prefer to use the constexpr `Uint128Max()`. ++// ++// TODO(absl-team) deprecate kuint128max once migration tool is released. ++ABSL_DLL extern const uint128 kuint128max; ++ ++// allow uint128 to be logged ++std::ostream& operator<<(std::ostream& os, uint128 v); ++ ++// TODO(strel) add operator>>(std::istream&, uint128) ++ ++constexpr uint128 Uint128Max() { ++ return uint128((std::numeric_limits::max)(), ++ (std::numeric_limits::max)()); ++} ++ ++ABSL_NAMESPACE_END ++} // namespace absl ++ ++// Specialized numeric_limits for uint128. ++namespace std { ++template <> ++class numeric_limits { ++ public: ++ 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 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 float_round_style round_style = round_toward_zero; ++ static constexpr bool is_iec559 = false; ++ static constexpr bool is_bounded = true; ++ static constexpr bool is_modulo = true; ++ static constexpr int digits = 128; ++ static constexpr int digits10 = 38; ++ static constexpr int max_digits10 = 0; ++ static constexpr int radix = 2; ++ static constexpr int min_exponent = 0; ++ static constexpr int min_exponent10 = 0; ++ static constexpr int max_exponent = 0; ++ static constexpr int max_exponent10 = 0; ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++ static constexpr bool traps = numeric_limits::traps; ++#else // ABSL_HAVE_INTRINSIC_INT128 ++ static constexpr bool traps = numeric_limits::traps; ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ static constexpr bool tinyness_before = false; ++ ++ static constexpr absl::uint128 (min)() { return 0; } ++ static constexpr absl::uint128 lowest() { return 0; } ++ static constexpr absl::uint128 (max)() { return absl::Uint128Max(); } ++ static constexpr absl::uint128 epsilon() { return 0; } ++ static constexpr absl::uint128 round_error() { return 0; } ++ static constexpr absl::uint128 infinity() { return 0; } ++ static constexpr absl::uint128 quiet_NaN() { return 0; } ++ static constexpr absl::uint128 signaling_NaN() { return 0; } ++ static constexpr absl::uint128 denorm_min() { return 0; } ++}; ++} // namespace std ++ ++namespace absl { ++ABSL_NAMESPACE_BEGIN ++ ++// int128 ++// ++// A signed 128-bit integer type. The API is meant to mimic an intrinsic ++// integral type as closely as is practical, including exhibiting undefined ++// behavior in analogous cases (e.g. division by zero). ++// ++// An `int128` supports the following: ++// ++// * Implicit construction from integral types ++// * Explicit conversion to integral types ++// ++// However, an `int128` differs from intrinsic integral types in the following ++// ways: ++// ++// * It is not implicitly convertible to other integral types. ++// * Requires explicit construction from and conversion to floating point ++// types. ++ ++// Additionally, if your compiler supports `__int128`, `int128` is ++// interoperable with that type. (Abseil checks for this compatibility through ++// the `ABSL_HAVE_INTRINSIC_INT128` macro.) ++// ++// The design goal for `int128` is that it will be compatible with a future ++// `int128_t`, if that type becomes a part of the standard. ++// ++// Example: ++// ++// float y = absl::int128(17); // Error. int128 cannot be implicitly ++// // converted to float. ++// ++// absl::int128 v; ++// int64_t i = v; // Error ++// int64_t i = static_cast(v); // OK ++// ++class int128 { ++ public: ++ int128() = default; ++ ++ // Constructors from arithmetic types ++ constexpr int128(int v); // NOLINT(runtime/explicit) ++ constexpr int128(unsigned int v); // NOLINT(runtime/explicit) ++ constexpr int128(long v); // NOLINT(runtime/int) ++ constexpr int128(unsigned long v); // NOLINT(runtime/int) ++ constexpr int128(long long v); // NOLINT(runtime/int) ++ constexpr int128(unsigned long long v); // NOLINT(runtime/int) ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++ constexpr int128(__int128 v); // NOLINT(runtime/explicit) ++ constexpr explicit int128(unsigned __int128 v); ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ constexpr explicit int128(uint128 v); ++ explicit int128(float v); ++ explicit int128(double v); ++ explicit int128(long double v); ++ ++ // Assignment operators from arithmetic types ++ int128& operator=(int v); ++ int128& operator=(unsigned int v); ++ int128& operator=(long v); // NOLINT(runtime/int) ++ int128& operator=(unsigned long v); // NOLINT(runtime/int) ++ int128& operator=(long long v); // NOLINT(runtime/int) ++ int128& operator=(unsigned long long v); // NOLINT(runtime/int) ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++ int128& operator=(__int128 v); ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ ++ // Conversion operators to other arithmetic types ++ constexpr explicit operator bool() const; ++ constexpr explicit operator char() const; ++ constexpr explicit operator signed char() const; ++ constexpr explicit operator unsigned char() const; ++ constexpr explicit operator char16_t() const; ++ constexpr explicit operator char32_t() const; ++ constexpr explicit operator ABSL_INTERNAL_WCHAR_T() const; ++ constexpr explicit operator short() const; // NOLINT(runtime/int) ++ // NOLINTNEXTLINE(runtime/int) ++ constexpr explicit operator unsigned short() const; ++ constexpr explicit operator int() const; ++ constexpr explicit operator unsigned int() const; ++ constexpr explicit operator long() const; // NOLINT(runtime/int) ++ // NOLINTNEXTLINE(runtime/int) ++ constexpr explicit operator unsigned long() const; ++ // NOLINTNEXTLINE(runtime/int) ++ constexpr explicit operator long long() const; ++ // NOLINTNEXTLINE(runtime/int) ++ constexpr explicit operator unsigned long long() const; ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++ constexpr explicit operator __int128() const; ++ constexpr explicit operator unsigned __int128() const; ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ explicit operator float() const; ++ explicit operator double() const; ++ explicit operator long double() const; ++ ++ // Trivial copy constructor, assignment operator and destructor. ++ ++ // Arithmetic operators ++ int128& operator+=(int128 other); ++ int128& operator-=(int128 other); ++ int128& operator*=(int128 other); ++ int128& operator/=(int128 other); ++ int128& operator%=(int128 other); ++ int128 operator++(int); // postfix increment: i++ ++ int128 operator--(int); // postfix decrement: i-- ++ int128& operator++(); // prefix increment: ++i ++ int128& operator--(); // prefix decrement: --i ++ int128& operator&=(int128 other); ++ int128& operator|=(int128 other); ++ int128& operator^=(int128 other); ++ int128& operator<<=(int amount); ++ int128& operator>>=(int amount); ++ ++ // Int128Low64() ++ // ++ // Returns the lower 64-bit value of a `int128` value. ++ friend constexpr uint64_t Int128Low64(int128 v); ++ ++ // Int128High64() ++ // ++ // Returns the higher 64-bit value of a `int128` value. ++ friend constexpr int64_t Int128High64(int128 v); ++ ++ // MakeInt128() ++ // ++ // Constructs a `int128` numeric value from two 64-bit integers. Note that ++ // signedness is conveyed in the upper `high` value. ++ // ++ // (absl::int128(1) << 64) * high + low ++ // ++ // Note that this factory function is the only way to construct a `int128` ++ // from integer values greater than 2^64 or less than -2^64. ++ // ++ // Example: ++ // ++ // absl::int128 big = absl::MakeInt128(1, 0); ++ // absl::int128 big_n = absl::MakeInt128(-1, 0); ++ friend constexpr int128 MakeInt128(int64_t high, uint64_t low); ++ ++ // Int128Max() ++ // ++ // Returns the maximum value for a 128-bit signed integer. ++ friend constexpr int128 Int128Max(); ++ ++ // Int128Min() ++ // ++ // Returns the minimum value for a 128-bit signed integer. ++ friend constexpr int128 Int128Min(); ++ ++ // Support for absl::Hash. ++ template ++ friend H AbslHashValue(H h, int128 v) { ++ return H::combine(std::move(h), Int128High64(v), Int128Low64(v)); ++ } ++ ++ private: ++ constexpr int128(int64_t high, uint64_t low); ++ ++#if defined(ABSL_HAVE_INTRINSIC_INT128) ++ __int128 v_; ++#else // ABSL_HAVE_INTRINSIC_INT128 ++#if defined(ABSL_IS_LITTLE_ENDIAN) ++ uint64_t lo_; ++ int64_t hi_; ++#elif defined(ABSL_IS_BIG_ENDIAN) ++ int64_t hi_; ++ uint64_t lo_; ++#else // byte order ++#error "Unsupported byte order: must be little-endian or big-endian." ++#endif // byte order ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++}; ++ ++std::ostream& operator<<(std::ostream& os, int128 v); ++ ++// TODO(absl-team) add operator>>(std::istream&, int128) ++ ++constexpr int128 Int128Max() { ++ return int128((std::numeric_limits::max)(), ++ (std::numeric_limits::max)()); ++} ++ ++constexpr int128 Int128Min() { ++ return int128((std::numeric_limits::min)(), 0); ++} ++ ++ABSL_NAMESPACE_END ++} // namespace absl ++ ++// Specialized numeric_limits for int128. ++namespace std { ++template <> ++class numeric_limits { ++ public: ++ 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 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 float_round_style round_style = round_toward_zero; ++ static constexpr bool is_iec559 = false; ++ static constexpr bool is_bounded = true; ++ static constexpr bool is_modulo = false; ++ static constexpr int digits = 127; ++ static constexpr int digits10 = 38; ++ static constexpr int max_digits10 = 0; ++ static constexpr int radix = 2; ++ static constexpr int min_exponent = 0; ++ static constexpr int min_exponent10 = 0; ++ static constexpr int max_exponent = 0; ++ static constexpr int max_exponent10 = 0; ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++ static constexpr bool traps = numeric_limits<__int128>::traps; ++#else // ABSL_HAVE_INTRINSIC_INT128 ++ static constexpr bool traps = numeric_limits::traps; ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ static constexpr bool tinyness_before = false; ++ ++ static constexpr absl::int128 (min)() { return absl::Int128Min(); } ++ static constexpr absl::int128 lowest() { return absl::Int128Min(); } ++ static constexpr absl::int128 (max)() { return absl::Int128Max(); } ++ static constexpr absl::int128 epsilon() { return 0; } ++ static constexpr absl::int128 round_error() { return 0; } ++ static constexpr absl::int128 infinity() { return 0; } ++ static constexpr absl::int128 quiet_NaN() { return 0; } ++ static constexpr absl::int128 signaling_NaN() { return 0; } ++ static constexpr absl::int128 denorm_min() { return 0; } ++}; ++} // namespace std ++ ++// -------------------------------------------------------------------------- ++// Implementation details follow ++// -------------------------------------------------------------------------- ++namespace absl { ++ABSL_NAMESPACE_BEGIN ++ ++constexpr uint128 MakeUint128(uint64_t high, uint64_t low) { ++ return uint128(high, low); ++} ++ ++// Assignment from integer types. ++ ++inline uint128& uint128::operator=(int v) { return *this = uint128(v); } ++ ++inline uint128& uint128::operator=(unsigned int v) { ++ return *this = uint128(v); ++} ++ ++inline uint128& uint128::operator=(long v) { // NOLINT(runtime/int) ++ return *this = uint128(v); ++} ++ ++// NOLINTNEXTLINE(runtime/int) ++inline uint128& uint128::operator=(unsigned long v) { ++ return *this = uint128(v); ++} ++ ++// NOLINTNEXTLINE(runtime/int) ++inline uint128& uint128::operator=(long long v) { ++ return *this = uint128(v); ++} ++ ++// NOLINTNEXTLINE(runtime/int) ++inline uint128& uint128::operator=(unsigned long long v) { ++ return *this = uint128(v); ++} ++ ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++inline uint128& uint128::operator=(__int128 v) { ++ return *this = uint128(v); ++} ++ ++inline uint128& uint128::operator=(unsigned __int128 v) { ++ return *this = uint128(v); ++} ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ ++inline uint128& uint128::operator=(int128 v) { ++ return *this = uint128(v); ++} ++ ++// Arithmetic operators. ++ ++uint128 operator<<(uint128 lhs, int amount); ++uint128 operator>>(uint128 lhs, int amount); ++uint128 operator+(uint128 lhs, uint128 rhs); ++uint128 operator-(uint128 lhs, uint128 rhs); ++uint128 operator*(uint128 lhs, uint128 rhs); ++uint128 operator/(uint128 lhs, uint128 rhs); ++uint128 operator%(uint128 lhs, uint128 rhs); ++ ++inline uint128& uint128::operator<<=(int amount) { ++ *this = *this << amount; ++ return *this; ++} ++ ++inline uint128& uint128::operator>>=(int amount) { ++ *this = *this >> amount; ++ return *this; ++} ++ ++inline uint128& uint128::operator+=(uint128 other) { ++ *this = *this + other; ++ return *this; ++} ++ ++inline uint128& uint128::operator-=(uint128 other) { ++ *this = *this - other; ++ return *this; ++} ++ ++inline uint128& uint128::operator*=(uint128 other) { ++ *this = *this * other; ++ return *this; ++} ++ ++inline uint128& uint128::operator/=(uint128 other) { ++ *this = *this / other; ++ return *this; ++} ++ ++inline uint128& uint128::operator%=(uint128 other) { ++ *this = *this % other; ++ return *this; ++} ++ ++constexpr uint64_t Uint128Low64(uint128 v) { return v.lo_; } ++ ++constexpr uint64_t Uint128High64(uint128 v) { return v.hi_; } ++ ++// Constructors from integer types. ++ ++#if defined(ABSL_IS_LITTLE_ENDIAN) ++ ++constexpr uint128::uint128(uint64_t high, uint64_t low) ++ : lo_{low}, hi_{high} {} ++ ++constexpr uint128::uint128(int v) ++ : lo_{static_cast(v)}, ++ hi_{v < 0 ? (std::numeric_limits::max)() : 0} {} ++constexpr uint128::uint128(long v) // NOLINT(runtime/int) ++ : lo_{static_cast(v)}, ++ hi_{v < 0 ? (std::numeric_limits::max)() : 0} {} ++constexpr uint128::uint128(long long v) // NOLINT(runtime/int) ++ : lo_{static_cast(v)}, ++ hi_{v < 0 ? (std::numeric_limits::max)() : 0} {} ++ ++constexpr uint128::uint128(unsigned int v) : lo_{v}, hi_{0} {} ++// NOLINTNEXTLINE(runtime/int) ++constexpr uint128::uint128(unsigned long v) : lo_{v}, hi_{0} {} ++// NOLINTNEXTLINE(runtime/int) ++constexpr uint128::uint128(unsigned long long v) : lo_{v}, hi_{0} {} ++ ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++constexpr uint128::uint128(__int128 v) ++ : lo_{static_cast(v & ~uint64_t{0})}, ++ hi_{static_cast(static_cast(v) >> 64)} {} ++constexpr uint128::uint128(unsigned __int128 v) ++ : lo_{static_cast(v & ~uint64_t{0})}, ++ hi_{static_cast(v >> 64)} {} ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ ++constexpr uint128::uint128(int128 v) ++ : lo_{Int128Low64(v)}, hi_{static_cast(Int128High64(v))} {} ++ ++#elif defined(ABSL_IS_BIG_ENDIAN) ++ ++constexpr uint128::uint128(uint64_t high, uint64_t low) ++ : hi_{high}, lo_{low} {} ++ ++constexpr uint128::uint128(int v) ++ : hi_{v < 0 ? (std::numeric_limits::max)() : 0}, ++ lo_{static_cast(v)} {} ++constexpr uint128::uint128(long v) // NOLINT(runtime/int) ++ : hi_{v < 0 ? (std::numeric_limits::max)() : 0}, ++ lo_{static_cast(v)} {} ++constexpr uint128::uint128(long long v) // NOLINT(runtime/int) ++ : hi_{v < 0 ? (std::numeric_limits::max)() : 0}, ++ lo_{static_cast(v)} {} ++ ++constexpr uint128::uint128(unsigned int v) : hi_{0}, lo_{v} {} ++// NOLINTNEXTLINE(runtime/int) ++constexpr uint128::uint128(unsigned long v) : hi_{0}, lo_{v} {} ++// NOLINTNEXTLINE(runtime/int) ++constexpr uint128::uint128(unsigned long long v) : hi_{0}, lo_{v} {} ++ ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++constexpr uint128::uint128(__int128 v) ++ : hi_{static_cast(static_cast(v) >> 64)}, ++ lo_{static_cast(v & ~uint64_t{0})} {} ++constexpr uint128::uint128(unsigned __int128 v) ++ : hi_{static_cast(v >> 64)}, ++ lo_{static_cast(v & ~uint64_t{0})} {} ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ ++constexpr uint128::uint128(int128 v) ++ : hi_{static_cast(Int128High64(v))}, lo_{Int128Low64(v)} {} ++ ++#else // byte order ++#error "Unsupported byte order: must be little-endian or big-endian." ++#endif // byte order ++ ++// Conversion operators to integer types. ++ ++constexpr uint128::operator bool() const { return lo_ || hi_; } ++ ++constexpr uint128::operator char() const { return static_cast(lo_); } ++ ++constexpr uint128::operator signed char() const { ++ return static_cast(lo_); ++} ++ ++constexpr uint128::operator unsigned char() const { ++ return static_cast(lo_); ++} ++ ++constexpr uint128::operator char16_t() const { ++ return static_cast(lo_); ++} ++ ++constexpr uint128::operator char32_t() const { ++ return static_cast(lo_); ++} ++ ++constexpr uint128::operator ABSL_INTERNAL_WCHAR_T() const { ++ return static_cast(lo_); ++} ++ ++// NOLINTNEXTLINE(runtime/int) ++constexpr uint128::operator short() const { return static_cast(lo_); } ++ ++constexpr uint128::operator unsigned short() const { // NOLINT(runtime/int) ++ return static_cast(lo_); // NOLINT(runtime/int) ++} ++ ++constexpr uint128::operator int() const { return static_cast(lo_); } ++ ++constexpr uint128::operator unsigned int() const { ++ return static_cast(lo_); ++} ++ ++// NOLINTNEXTLINE(runtime/int) ++constexpr uint128::operator long() const { return static_cast(lo_); } ++ ++constexpr uint128::operator unsigned long() const { // NOLINT(runtime/int) ++ return static_cast(lo_); // NOLINT(runtime/int) ++} ++ ++constexpr uint128::operator long long() const { // NOLINT(runtime/int) ++ return static_cast(lo_); // NOLINT(runtime/int) ++} ++ ++constexpr uint128::operator unsigned long long() const { // NOLINT(runtime/int) ++ return static_cast(lo_); // NOLINT(runtime/int) ++} ++ ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++constexpr uint128::operator __int128() const { ++ return (static_cast<__int128>(hi_) << 64) + lo_; ++} ++ ++constexpr uint128::operator unsigned __int128() const { ++ return (static_cast(hi_) << 64) + lo_; ++} ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ ++// Conversion operators to floating point types. ++ ++inline uint128::operator float() const { ++ return static_cast(lo_) + std::ldexp(static_cast(hi_), 64); ++} ++ ++inline uint128::operator double() const { ++ return static_cast(lo_) + std::ldexp(static_cast(hi_), 64); ++} ++ ++inline uint128::operator long double() const { ++ return static_cast(lo_) + ++ std::ldexp(static_cast(hi_), 64); ++} ++ ++// Comparison operators. ++ ++inline bool operator==(uint128 lhs, uint128 rhs) { ++#if defined(ABSL_HAVE_INTRINSIC_INT128) ++ return static_cast(lhs) == ++ static_cast(rhs); ++#else ++ return (Uint128Low64(lhs) == Uint128Low64(rhs) && ++ Uint128High64(lhs) == Uint128High64(rhs)); ++#endif ++} ++ ++inline bool operator!=(uint128 lhs, uint128 rhs) { ++ return !(lhs == rhs); ++} ++ ++inline bool operator<(uint128 lhs, uint128 rhs) { ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++ return static_cast(lhs) < ++ static_cast(rhs); ++#else ++ return (Uint128High64(lhs) == Uint128High64(rhs)) ++ ? (Uint128Low64(lhs) < Uint128Low64(rhs)) ++ : (Uint128High64(lhs) < Uint128High64(rhs)); ++#endif ++} ++ ++inline bool operator>(uint128 lhs, uint128 rhs) { return rhs < lhs; } ++ ++inline bool operator<=(uint128 lhs, uint128 rhs) { return !(rhs < lhs); } ++ ++inline bool operator>=(uint128 lhs, uint128 rhs) { return !(lhs < rhs); } ++ ++// Unary operators. ++ ++constexpr inline uint128 operator+(uint128 val) { ++ return val; ++} ++ ++constexpr inline int128 operator+(int128 val) { ++ return val; ++} ++ ++inline uint128 operator-(uint128 val) { ++#if defined(ABSL_HAVE_INTRINSIC_INT128) ++ return -static_cast(val); ++#else ++ uint64_t hi = ~Uint128High64(val); ++ uint64_t lo = ~Uint128Low64(val) + 1; ++ if (lo == 0) ++hi; // carry ++ return MakeUint128(hi, lo); ++#endif ++} ++ ++constexpr inline bool operator!(uint128 val) { ++#if defined(ABSL_HAVE_INTRINSIC_INT128) ++ return !static_cast(val); ++#else ++ return !Uint128High64(val) && !Uint128Low64(val); ++#endif ++} ++ ++// Logical operators. ++ ++constexpr inline uint128 operator~(uint128 val) { ++#if defined(ABSL_HAVE_INTRINSIC_INT128) ++ return ~static_cast(val); ++#else ++ return MakeUint128(~Uint128High64(val), ~Uint128Low64(val)); ++#endif ++} ++ ++constexpr inline uint128 operator|(uint128 lhs, uint128 rhs) { ++#if defined(ABSL_HAVE_INTRINSIC_INT128) ++ return static_cast(lhs) | ++ static_cast(rhs); ++#else ++ return MakeUint128(Uint128High64(lhs) | Uint128High64(rhs), ++ Uint128Low64(lhs) | Uint128Low64(rhs)); ++#endif ++} ++ ++constexpr inline uint128 operator&(uint128 lhs, uint128 rhs) { ++#if defined(ABSL_HAVE_INTRINSIC_INT128) ++ return static_cast(lhs) & ++ static_cast(rhs); ++#else ++ return MakeUint128(Uint128High64(lhs) & Uint128High64(rhs), ++ Uint128Low64(lhs) & Uint128Low64(rhs)); ++#endif ++} ++ ++constexpr inline uint128 operator^(uint128 lhs, uint128 rhs) { ++#if defined(ABSL_HAVE_INTRINSIC_INT128) ++ return static_cast(lhs) ^ ++ static_cast(rhs); ++#else ++ return MakeUint128(Uint128High64(lhs) ^ Uint128High64(rhs), ++ Uint128Low64(lhs) ^ Uint128Low64(rhs)); ++#endif ++} ++ ++inline uint128& uint128::operator|=(uint128 other) { ++ *this = *this | other; ++ return *this; ++} ++ ++inline uint128& uint128::operator&=(uint128 other) { ++ *this = *this & other; ++ return *this; ++} ++ ++inline uint128& uint128::operator^=(uint128 other) { ++ *this = *this ^ other; ++ return *this; ++} ++ ++// Arithmetic operators. ++ ++inline uint128 operator<<(uint128 lhs, int amount) { ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++ return static_cast(lhs) << amount; ++#else ++ // uint64_t shifts of >= 64 are undefined, so we will need some ++ // special-casing. ++ if (amount < 64) { ++ if (amount != 0) { ++ return MakeUint128( ++ (Uint128High64(lhs) << amount) | (Uint128Low64(lhs) >> (64 - amount)), ++ Uint128Low64(lhs) << amount); ++ } ++ return lhs; ++ } ++ return MakeUint128(Uint128Low64(lhs) << (amount - 64), 0); ++#endif ++} ++ ++inline uint128 operator>>(uint128 lhs, int amount) { ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++ return static_cast(lhs) >> amount; ++#else ++ // uint64_t shifts of >= 64 are undefined, so we will need some ++ // special-casing. ++ if (amount < 64) { ++ if (amount != 0) { ++ return MakeUint128(Uint128High64(lhs) >> amount, ++ (Uint128Low64(lhs) >> amount) | ++ (Uint128High64(lhs) << (64 - amount))); ++ } ++ return lhs; ++ } ++ return MakeUint128(0, Uint128High64(lhs) >> (amount - 64)); ++#endif ++} ++ ++inline uint128 operator+(uint128 lhs, uint128 rhs) { ++#if defined(ABSL_HAVE_INTRINSIC_INT128) ++ return static_cast(lhs) + ++ static_cast(rhs); ++#else ++ uint128 result = MakeUint128(Uint128High64(lhs) + Uint128High64(rhs), ++ Uint128Low64(lhs) + Uint128Low64(rhs)); ++ if (Uint128Low64(result) < Uint128Low64(lhs)) { // check for carry ++ return MakeUint128(Uint128High64(result) + 1, Uint128Low64(result)); ++ } ++ return result; ++#endif ++} ++ ++inline uint128 operator-(uint128 lhs, uint128 rhs) { ++#if defined(ABSL_HAVE_INTRINSIC_INT128) ++ return static_cast(lhs) - ++ static_cast(rhs); ++#else ++ uint128 result = MakeUint128(Uint128High64(lhs) - Uint128High64(rhs), ++ Uint128Low64(lhs) - Uint128Low64(rhs)); ++ if (Uint128Low64(lhs) < Uint128Low64(rhs)) { // check for carry ++ return MakeUint128(Uint128High64(result) - 1, Uint128Low64(result)); ++ } ++ return result; ++#endif ++} ++ ++inline uint128 operator*(uint128 lhs, uint128 rhs) { ++#if defined(ABSL_HAVE_INTRINSIC_INT128) ++ // TODO(strel) Remove once alignment issues are resolved and unsigned __int128 ++ // can be used for uint128 storage. ++ return static_cast(lhs) * ++ static_cast(rhs); ++#elif defined(_MSC_VER) && defined(_M_X64) ++ uint64_t carry; ++ uint64_t low = _umul128(Uint128Low64(lhs), Uint128Low64(rhs), &carry); ++ return MakeUint128(Uint128Low64(lhs) * Uint128High64(rhs) + ++ Uint128High64(lhs) * Uint128Low64(rhs) + carry, ++ low); ++#else // ABSL_HAVE_INTRINSIC128 ++ uint64_t a32 = Uint128Low64(lhs) >> 32; ++ uint64_t a00 = Uint128Low64(lhs) & 0xffffffff; ++ uint64_t b32 = Uint128Low64(rhs) >> 32; ++ uint64_t b00 = Uint128Low64(rhs) & 0xffffffff; ++ uint128 result = ++ MakeUint128(Uint128High64(lhs) * Uint128Low64(rhs) + ++ Uint128Low64(lhs) * Uint128High64(rhs) + a32 * b32, ++ a00 * b00); ++ result += uint128(a32 * b00) << 32; ++ result += uint128(a00 * b32) << 32; ++ return result; ++#endif // ABSL_HAVE_INTRINSIC128 ++} ++ ++#if defined(ABSL_HAVE_INTRINSIC_INT128) ++inline uint128 operator/(uint128 lhs, uint128 rhs) { ++ return static_cast(lhs) / ++ static_cast(rhs); ++} ++ ++inline uint128 operator%(uint128 lhs, uint128 rhs) { ++ return static_cast(lhs) % ++ static_cast(rhs); ++} ++#endif ++ ++// Increment/decrement operators. ++ ++inline uint128 uint128::operator++(int) { ++ uint128 tmp(*this); ++ *this += 1; ++ return tmp; ++} ++ ++inline uint128 uint128::operator--(int) { ++ uint128 tmp(*this); ++ *this -= 1; ++ return tmp; ++} ++ ++inline uint128& uint128::operator++() { ++ *this += 1; ++ return *this; ++} ++ ++inline uint128& uint128::operator--() { ++ *this -= 1; ++ return *this; ++} ++ ++constexpr int128 MakeInt128(int64_t high, uint64_t low) { ++ return int128(high, low); ++} ++ ++// Assignment from integer types. ++inline int128& int128::operator=(int v) { ++ return *this = int128(v); ++} ++ ++inline int128& int128::operator=(unsigned int v) { ++ return *this = int128(v); ++} ++ ++inline int128& int128::operator=(long v) { // NOLINT(runtime/int) ++ return *this = int128(v); ++} ++ ++// NOLINTNEXTLINE(runtime/int) ++inline int128& int128::operator=(unsigned long v) { ++ return *this = int128(v); ++} ++ ++// NOLINTNEXTLINE(runtime/int) ++inline int128& int128::operator=(long long v) { ++ return *this = int128(v); ++} ++ ++// NOLINTNEXTLINE(runtime/int) ++inline int128& int128::operator=(unsigned long long v) { ++ return *this = int128(v); ++} ++ ++// Arithmetic operators. ++ ++int128 operator+(int128 lhs, int128 rhs); ++int128 operator-(int128 lhs, int128 rhs); ++int128 operator*(int128 lhs, int128 rhs); ++int128 operator/(int128 lhs, int128 rhs); ++int128 operator%(int128 lhs, int128 rhs); ++int128 operator|(int128 lhs, int128 rhs); ++int128 operator&(int128 lhs, int128 rhs); ++int128 operator^(int128 lhs, int128 rhs); ++int128 operator<<(int128 lhs, int amount); ++int128 operator>>(int128 lhs, int amount); ++ ++inline int128& int128::operator+=(int128 other) { ++ *this = *this + other; ++ return *this; ++} ++ ++inline int128& int128::operator-=(int128 other) { ++ *this = *this - other; ++ return *this; ++} ++ ++inline int128& int128::operator*=(int128 other) { ++ *this = *this * other; ++ return *this; ++} ++ ++inline int128& int128::operator/=(int128 other) { ++ *this = *this / other; ++ return *this; ++} ++ ++inline int128& int128::operator%=(int128 other) { ++ *this = *this % other; ++ return *this; ++} ++ ++inline int128& int128::operator|=(int128 other) { ++ *this = *this | other; ++ return *this; ++} ++ ++inline int128& int128::operator&=(int128 other) { ++ *this = *this & other; ++ return *this; ++} ++ ++inline int128& int128::operator^=(int128 other) { ++ *this = *this ^ other; ++ return *this; ++} ++ ++inline int128& int128::operator<<=(int amount) { ++ *this = *this << amount; ++ return *this; ++} ++ ++inline int128& int128::operator>>=(int amount) { ++ *this = *this >> amount; ++ return *this; ++} ++ ++namespace int128_internal { ++ ++// Casts from unsigned to signed while preserving the underlying binary ++// representation. ++constexpr int64_t BitCastToSigned(uint64_t v) { ++ // Casting an unsigned integer to a signed integer of the same ++ // width is implementation defined behavior if the source value would not fit ++ // in the destination type. We step around it with a roundtrip bitwise not ++ // operation to make sure this function remains constexpr. Clang, GCC, and ++ // MSVC optimize this to a no-op on x86-64. ++ return v & (uint64_t{1} << 63) ? ~static_cast(~v) ++ : static_cast(v); ++} ++ ++} // namespace int128_internal ++ ++#if defined(ABSL_HAVE_INTRINSIC_INT128) ++#include "absl/numeric/int128_have_intrinsic.inc" // IWYU pragma: export ++#else // ABSL_HAVE_INTRINSIC_INT128 ++#include "absl/numeric/int128_no_intrinsic.inc" // IWYU pragma: export ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ ++ABSL_NAMESPACE_END ++} // namespace absl ++ ++#undef ABSL_INTERNAL_WCHAR_T ++ ++#endif // ABSL_NUMERIC_INT128_H_ +diff --git a/extern/int128/absl/numeric/int128_have_intrinsic.inc b/extern/int128/absl/numeric/int128_have_intrinsic.inc +new file mode 100644 +index 0000000000..d6c76dd320 +--- /dev/null ++++ b/extern/int128/absl/numeric/int128_have_intrinsic.inc +@@ -0,0 +1,302 @@ ++// ++// Copyright 2017 The Abseil Authors. ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// https://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++// This file contains :int128 implementation details that depend on internal ++// representation when ABSL_HAVE_INTRINSIC_INT128 is defined. This file is ++// included by int128.h and relies on ABSL_INTERNAL_WCHAR_T being defined. ++ ++namespace int128_internal { ++ ++// Casts from unsigned to signed while preserving the underlying binary ++// representation. ++constexpr __int128 BitCastToSigned(unsigned __int128 v) { ++ // Casting an unsigned integer to a signed integer of the same ++ // width is implementation defined behavior if the source value would not fit ++ // in the destination type. We step around it with a roundtrip bitwise not ++ // operation to make sure this function remains constexpr. Clang and GCC ++ // optimize this to a no-op on x86-64. ++ return v & (static_cast(1) << 127) ++ ? ~static_cast<__int128>(~v) ++ : static_cast<__int128>(v); ++} ++ ++} // namespace int128_internal ++ ++inline int128& int128::operator=(__int128 v) { ++ v_ = v; ++ return *this; ++} ++ ++constexpr uint64_t Int128Low64(int128 v) { ++ return static_cast(v.v_ & ~uint64_t{0}); ++} ++ ++constexpr int64_t Int128High64(int128 v) { ++ // Initially cast to unsigned to prevent a right shift on a negative value. ++ return int128_internal::BitCastToSigned( ++ static_cast(static_cast(v.v_) >> 64)); ++} ++ ++constexpr int128::int128(int64_t high, uint64_t low) ++ // Initially cast to unsigned to prevent a left shift that overflows. ++ : v_(int128_internal::BitCastToSigned(static_cast(high) ++ << 64) | ++ low) {} ++ ++ ++constexpr int128::int128(int v) : v_{v} {} ++ ++constexpr int128::int128(long v) : v_{v} {} // NOLINT(runtime/int) ++ ++constexpr int128::int128(long long v) : v_{v} {} // NOLINT(runtime/int) ++ ++constexpr int128::int128(__int128 v) : v_{v} {} ++ ++constexpr int128::int128(unsigned int v) : v_{v} {} ++ ++constexpr int128::int128(unsigned long v) : v_{v} {} // NOLINT(runtime/int) ++ ++// NOLINTNEXTLINE(runtime/int) ++constexpr int128::int128(unsigned long long v) : v_{v} {} ++ ++constexpr int128::int128(unsigned __int128 v) : v_{static_cast<__int128>(v)} {} ++ ++inline int128::int128(float v) { ++ v_ = static_cast<__int128>(v); ++} ++ ++inline int128::int128(double v) { ++ v_ = static_cast<__int128>(v); ++} ++ ++inline int128::int128(long double v) { ++ v_ = static_cast<__int128>(v); ++} ++ ++constexpr int128::int128(uint128 v) : v_{static_cast<__int128>(v)} {} ++ ++constexpr int128::operator bool() const { return static_cast(v_); } ++ ++constexpr int128::operator char() const { return static_cast(v_); } ++ ++constexpr int128::operator signed char() const { ++ return static_cast(v_); ++} ++ ++constexpr int128::operator unsigned char() const { ++ return static_cast(v_); ++} ++ ++constexpr int128::operator char16_t() const { ++ return static_cast(v_); ++} ++ ++constexpr int128::operator char32_t() const { ++ return static_cast(v_); ++} ++ ++constexpr int128::operator ABSL_INTERNAL_WCHAR_T() const { ++ return static_cast(v_); ++} ++ ++constexpr int128::operator short() const { // NOLINT(runtime/int) ++ return static_cast(v_); // NOLINT(runtime/int) ++} ++ ++constexpr int128::operator unsigned short() const { // NOLINT(runtime/int) ++ return static_cast(v_); // NOLINT(runtime/int) ++} ++ ++constexpr int128::operator int() const { ++ return static_cast(v_); ++} ++ ++constexpr int128::operator unsigned int() const { ++ return static_cast(v_); ++} ++ ++constexpr int128::operator long() const { // NOLINT(runtime/int) ++ return static_cast(v_); // NOLINT(runtime/int) ++} ++ ++constexpr int128::operator unsigned long() const { // NOLINT(runtime/int) ++ return static_cast(v_); // NOLINT(runtime/int) ++} ++ ++constexpr int128::operator long long() const { // NOLINT(runtime/int) ++ return static_cast(v_); // NOLINT(runtime/int) ++} ++ ++constexpr int128::operator unsigned long long() const { // NOLINT(runtime/int) ++ return static_cast(v_); // NOLINT(runtime/int) ++} ++ ++constexpr int128::operator __int128() const { return v_; } ++ ++constexpr int128::operator unsigned __int128() const { ++ return static_cast(v_); ++} ++ ++// Clang on PowerPC sometimes produces incorrect __int128 to floating point ++// conversions. In that case, we do the conversion with a similar implementation ++// to the conversion operators in int128_no_intrinsic.inc. ++#if defined(__clang__) && !defined(__ppc64__) ++inline int128::operator float() const { return static_cast(v_); } ++ ++inline int128::operator double () const { return static_cast(v_); } ++ ++inline int128::operator long double() const { ++ return static_cast(v_); ++} ++ ++#else // Clang on PowerPC ++// Forward declaration for conversion operators to floating point types. ++int128 operator-(int128 v); ++bool operator!=(int128 lhs, int128 rhs); ++ ++inline int128::operator float() const { ++ // We must convert the absolute value and then negate as needed, because ++ // floating point types are typically sign-magnitude. Otherwise, the ++ // difference between the high and low 64 bits when interpreted as two's ++ // complement overwhelms the precision of the mantissa. ++ // ++ // Also check to make sure we don't negate Int128Min() ++ return v_ < 0 && *this != Int128Min() ++ ? -static_cast(-*this) ++ : static_cast(Int128Low64(*this)) + ++ std::ldexp(static_cast(Int128High64(*this)), 64); ++} ++ ++inline int128::operator double() const { ++ // See comment in int128::operator float() above. ++ return v_ < 0 && *this != Int128Min() ++ ? -static_cast(-*this) ++ : static_cast(Int128Low64(*this)) + ++ std::ldexp(static_cast(Int128High64(*this)), 64); ++} ++ ++inline int128::operator long double() const { ++ // See comment in int128::operator float() above. ++ return v_ < 0 && *this != Int128Min() ++ ? -static_cast(-*this) ++ : static_cast(Int128Low64(*this)) + ++ std::ldexp(static_cast(Int128High64(*this)), ++ 64); ++} ++#endif // Clang on PowerPC ++ ++// Comparison operators. ++ ++inline bool operator==(int128 lhs, int128 rhs) { ++ return static_cast<__int128>(lhs) == static_cast<__int128>(rhs); ++} ++ ++inline bool operator!=(int128 lhs, int128 rhs) { ++ return static_cast<__int128>(lhs) != static_cast<__int128>(rhs); ++} ++ ++inline bool operator<(int128 lhs, int128 rhs) { ++ return static_cast<__int128>(lhs) < static_cast<__int128>(rhs); ++} ++ ++inline bool operator>(int128 lhs, int128 rhs) { ++ return static_cast<__int128>(lhs) > static_cast<__int128>(rhs); ++} ++ ++inline bool operator<=(int128 lhs, int128 rhs) { ++ return static_cast<__int128>(lhs) <= static_cast<__int128>(rhs); ++} ++ ++inline bool operator>=(int128 lhs, int128 rhs) { ++ return static_cast<__int128>(lhs) >= static_cast<__int128>(rhs); ++} ++ ++// Unary operators. ++ ++inline int128 operator-(int128 v) { ++ return -static_cast<__int128>(v); ++} ++ ++inline bool operator!(int128 v) { ++ return !static_cast<__int128>(v); ++} ++ ++inline int128 operator~(int128 val) { ++ return ~static_cast<__int128>(val); ++} ++ ++// Arithmetic operators. ++ ++inline int128 operator+(int128 lhs, int128 rhs) { ++ return static_cast<__int128>(lhs) + static_cast<__int128>(rhs); ++} ++ ++inline int128 operator-(int128 lhs, int128 rhs) { ++ return static_cast<__int128>(lhs) - static_cast<__int128>(rhs); ++} ++ ++inline int128 operator*(int128 lhs, int128 rhs) { ++ return static_cast<__int128>(lhs) * static_cast<__int128>(rhs); ++} ++ ++inline int128 operator/(int128 lhs, int128 rhs) { ++ return static_cast<__int128>(lhs) / static_cast<__int128>(rhs); ++} ++ ++inline int128 operator%(int128 lhs, int128 rhs) { ++ return static_cast<__int128>(lhs) % static_cast<__int128>(rhs); ++} ++ ++inline int128 int128::operator++(int) { ++ int128 tmp(*this); ++ ++v_; ++ return tmp; ++} ++ ++inline int128 int128::operator--(int) { ++ int128 tmp(*this); ++ --v_; ++ return tmp; ++} ++ ++inline int128& int128::operator++() { ++ ++v_; ++ return *this; ++} ++ ++inline int128& int128::operator--() { ++ --v_; ++ return *this; ++} ++ ++inline int128 operator|(int128 lhs, int128 rhs) { ++ return static_cast<__int128>(lhs) | static_cast<__int128>(rhs); ++} ++ ++inline int128 operator&(int128 lhs, int128 rhs) { ++ return static_cast<__int128>(lhs) & static_cast<__int128>(rhs); ++} ++ ++inline int128 operator^(int128 lhs, int128 rhs) { ++ return static_cast<__int128>(lhs) ^ static_cast<__int128>(rhs); ++} ++ ++inline int128 operator<<(int128 lhs, int amount) { ++ return static_cast<__int128>(lhs) << amount; ++} ++ ++inline int128 operator>>(int128 lhs, int amount) { ++ return static_cast<__int128>(lhs) >> amount; ++} +diff --git a/extern/int128/absl/numeric/int128_no_intrinsic.inc b/extern/int128/absl/numeric/int128_no_intrinsic.inc +new file mode 100644 +index 0000000000..c753771ae7 +--- /dev/null ++++ b/extern/int128/absl/numeric/int128_no_intrinsic.inc +@@ -0,0 +1,308 @@ ++// ++// Copyright 2017 The Abseil Authors. ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// https://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++// This file contains :int128 implementation details that depend on internal ++// representation when ABSL_HAVE_INTRINSIC_INT128 is *not* defined. This file ++// is included by int128.h and relies on ABSL_INTERNAL_WCHAR_T being defined. ++ ++constexpr uint64_t Int128Low64(int128 v) { return v.lo_; } ++ ++constexpr int64_t Int128High64(int128 v) { return v.hi_; } ++ ++#if defined(ABSL_IS_LITTLE_ENDIAN) ++ ++constexpr int128::int128(int64_t high, uint64_t low) : ++ lo_(low), hi_(high) {} ++ ++constexpr int128::int128(int v) ++ : lo_{static_cast(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {} ++constexpr int128::int128(long v) // NOLINT(runtime/int) ++ : lo_{static_cast(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {} ++constexpr int128::int128(long long v) // NOLINT(runtime/int) ++ : lo_{static_cast(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {} ++ ++constexpr int128::int128(unsigned int v) : lo_{v}, hi_{0} {} ++// NOLINTNEXTLINE(runtime/int) ++constexpr int128::int128(unsigned long v) : lo_{v}, hi_{0} {} ++// NOLINTNEXTLINE(runtime/int) ++constexpr int128::int128(unsigned long long v) : lo_{v}, hi_{0} {} ++ ++constexpr int128::int128(uint128 v) ++ : lo_{Uint128Low64(v)}, hi_{static_cast(Uint128High64(v))} {} ++ ++#elif defined(ABSL_IS_BIG_ENDIAN) ++ ++constexpr int128::int128(int64_t high, uint64_t low) : ++ hi_{high}, lo_{low} {} ++ ++constexpr int128::int128(int v) ++ : hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast(v)} {} ++constexpr int128::int128(long v) // NOLINT(runtime/int) ++ : hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast(v)} {} ++constexpr int128::int128(long long v) // NOLINT(runtime/int) ++ : hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast(v)} {} ++ ++constexpr int128::int128(unsigned int v) : hi_{0}, lo_{v} {} ++// NOLINTNEXTLINE(runtime/int) ++constexpr int128::int128(unsigned long v) : hi_{0}, lo_{v} {} ++// NOLINTNEXTLINE(runtime/int) ++constexpr int128::int128(unsigned long long v) : hi_{0}, lo_{v} {} ++ ++constexpr int128::int128(uint128 v) ++ : hi_{static_cast(Uint128High64(v))}, lo_{Uint128Low64(v)} {} ++ ++#else // byte order ++#error "Unsupported byte order: must be little-endian or big-endian." ++#endif // byte order ++ ++constexpr int128::operator bool() const { return lo_ || hi_; } ++ ++constexpr int128::operator char() const { ++ // NOLINTNEXTLINE(runtime/int) ++ return static_cast(static_cast(*this)); ++} ++ ++constexpr int128::operator signed char() const { ++ // NOLINTNEXTLINE(runtime/int) ++ return static_cast(static_cast(*this)); ++} ++ ++constexpr int128::operator unsigned char() const { ++ return static_cast(lo_); ++} ++ ++constexpr int128::operator char16_t() const { ++ return static_cast(lo_); ++} ++ ++constexpr int128::operator char32_t() const { ++ return static_cast(lo_); ++} ++ ++constexpr int128::operator ABSL_INTERNAL_WCHAR_T() const { ++ // NOLINTNEXTLINE(runtime/int) ++ return static_cast(static_cast(*this)); ++} ++ ++constexpr int128::operator short() const { // NOLINT(runtime/int) ++ // NOLINTNEXTLINE(runtime/int) ++ return static_cast(static_cast(*this)); ++} ++ ++constexpr int128::operator unsigned short() const { // NOLINT(runtime/int) ++ return static_cast(lo_); // NOLINT(runtime/int) ++} ++ ++constexpr int128::operator int() const { ++ // NOLINTNEXTLINE(runtime/int) ++ return static_cast(static_cast(*this)); ++} ++ ++constexpr int128::operator unsigned int() const { ++ return static_cast(lo_); ++} ++ ++constexpr int128::operator long() const { // NOLINT(runtime/int) ++ // NOLINTNEXTLINE(runtime/int) ++ return static_cast(static_cast(*this)); ++} ++ ++constexpr int128::operator unsigned long() const { // NOLINT(runtime/int) ++ return static_cast(lo_); // NOLINT(runtime/int) ++} ++ ++constexpr int128::operator long long() const { // NOLINT(runtime/int) ++ // We don't bother checking the value of hi_. If *this < 0, lo_'s high bit ++ // must be set in order for the value to fit into a long long. Conversely, if ++ // lo_'s high bit is set, *this must be < 0 for the value to fit. ++ return int128_internal::BitCastToSigned(lo_); ++} ++ ++constexpr int128::operator unsigned long long() const { // NOLINT(runtime/int) ++ return static_cast(lo_); // NOLINT(runtime/int) ++} ++ ++// Forward declaration for conversion operators to floating point types. ++int128 operator-(int128 v); ++bool operator!=(int128 lhs, int128 rhs); ++ ++inline int128::operator float() const { ++ // We must convert the absolute value and then negate as needed, because ++ // floating point types are typically sign-magnitude. Otherwise, the ++ // difference between the high and low 64 bits when interpreted as two's ++ // complement overwhelms the precision of the mantissa. ++ // ++ // Also check to make sure we don't negate Int128Min() ++ return hi_ < 0 && *this != Int128Min() ++ ? -static_cast(-*this) ++ : static_cast(lo_) + ++ std::ldexp(static_cast(hi_), 64); ++} ++ ++inline int128::operator double() const { ++ // See comment in int128::operator float() above. ++ return hi_ < 0 && *this != Int128Min() ++ ? -static_cast(-*this) ++ : static_cast(lo_) + ++ std::ldexp(static_cast(hi_), 64); ++} ++ ++inline int128::operator long double() const { ++ // See comment in int128::operator float() above. ++ return hi_ < 0 && *this != Int128Min() ++ ? -static_cast(-*this) ++ : static_cast(lo_) + ++ std::ldexp(static_cast(hi_), 64); ++} ++ ++// Comparison operators. ++ ++inline bool operator==(int128 lhs, int128 rhs) { ++ return (Int128Low64(lhs) == Int128Low64(rhs) && ++ Int128High64(lhs) == Int128High64(rhs)); ++} ++ ++inline bool operator!=(int128 lhs, int128 rhs) { ++ return !(lhs == rhs); ++} ++ ++inline bool operator<(int128 lhs, int128 rhs) { ++ return (Int128High64(lhs) == Int128High64(rhs)) ++ ? (Int128Low64(lhs) < Int128Low64(rhs)) ++ : (Int128High64(lhs) < Int128High64(rhs)); ++} ++ ++inline bool operator>(int128 lhs, int128 rhs) { ++ return (Int128High64(lhs) == Int128High64(rhs)) ++ ? (Int128Low64(lhs) > Int128Low64(rhs)) ++ : (Int128High64(lhs) > Int128High64(rhs)); ++} ++ ++inline bool operator<=(int128 lhs, int128 rhs) { ++ return !(lhs > rhs); ++} ++ ++inline bool operator>=(int128 lhs, int128 rhs) { ++ return !(lhs < rhs); ++} ++ ++// Unary operators. ++ ++inline int128 operator-(int128 v) { ++ int64_t hi = ~Int128High64(v); ++ uint64_t lo = ~Int128Low64(v) + 1; ++ if (lo == 0) ++hi; // carry ++ return MakeInt128(hi, lo); ++} ++ ++inline bool operator!(int128 v) { ++ return !Int128Low64(v) && !Int128High64(v); ++} ++ ++inline int128 operator~(int128 val) { ++ return MakeInt128(~Int128High64(val), ~Int128Low64(val)); ++} ++ ++// Arithmetic operators. ++ ++inline int128 operator+(int128 lhs, int128 rhs) { ++ int128 result = MakeInt128(Int128High64(lhs) + Int128High64(rhs), ++ Int128Low64(lhs) + Int128Low64(rhs)); ++ if (Int128Low64(result) < Int128Low64(lhs)) { // check for carry ++ return MakeInt128(Int128High64(result) + 1, Int128Low64(result)); ++ } ++ return result; ++} ++ ++inline int128 operator-(int128 lhs, int128 rhs) { ++ int128 result = MakeInt128(Int128High64(lhs) - Int128High64(rhs), ++ Int128Low64(lhs) - Int128Low64(rhs)); ++ if (Int128Low64(lhs) < Int128Low64(rhs)) { // check for carry ++ return MakeInt128(Int128High64(result) - 1, Int128Low64(result)); ++ } ++ return result; ++} ++ ++inline int128 operator*(int128 lhs, int128 rhs) { ++ uint128 result = uint128(lhs) * rhs; ++ return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(result)), ++ Uint128Low64(result)); ++} ++ ++inline int128 int128::operator++(int) { ++ int128 tmp(*this); ++ *this += 1; ++ return tmp; ++} ++ ++inline int128 int128::operator--(int) { ++ int128 tmp(*this); ++ *this -= 1; ++ return tmp; ++} ++ ++inline int128& int128::operator++() { ++ *this += 1; ++ return *this; ++} ++ ++inline int128& int128::operator--() { ++ *this -= 1; ++ return *this; ++} ++ ++inline int128 operator|(int128 lhs, int128 rhs) { ++ return MakeInt128(Int128High64(lhs) | Int128High64(rhs), ++ Int128Low64(lhs) | Int128Low64(rhs)); ++} ++ ++inline int128 operator&(int128 lhs, int128 rhs) { ++ return MakeInt128(Int128High64(lhs) & Int128High64(rhs), ++ Int128Low64(lhs) & Int128Low64(rhs)); ++} ++ ++inline int128 operator^(int128 lhs, int128 rhs) { ++ return MakeInt128(Int128High64(lhs) ^ Int128High64(rhs), ++ Int128Low64(lhs) ^ Int128Low64(rhs)); ++} ++ ++inline int128 operator<<(int128 lhs, int amount) { ++ // uint64_t shifts of >= 64 are undefined, so we need some special-casing. ++ if (amount < 64) { ++ if (amount != 0) { ++ return MakeInt128( ++ (Int128High64(lhs) << amount) | ++ static_cast(Int128Low64(lhs) >> (64 - amount)), ++ Int128Low64(lhs) << amount); ++ } ++ return lhs; ++ } ++ return MakeInt128(static_cast(Int128Low64(lhs) << (amount - 64)), 0); ++} ++ ++inline int128 operator>>(int128 lhs, int amount) { ++ // uint64_t shifts of >= 64 are undefined, so we need some special-casing. ++ if (amount < 64) { ++ if (amount != 0) { ++ return MakeInt128( ++ Int128High64(lhs) >> amount, ++ (Int128Low64(lhs) >> amount) | ++ (static_cast(Int128High64(lhs)) << (64 - amount))); ++ } ++ return lhs; ++ } ++ return MakeInt128(0, ++ static_cast(Int128High64(lhs) >> (amount - 64))); ++} +diff --git a/extern/int128/absl/numeric/internal/bits.h b/extern/int128/absl/numeric/internal/bits.h +new file mode 100644 +index 0000000000..bfef06bce1 +--- /dev/null ++++ b/extern/int128/absl/numeric/internal/bits.h +@@ -0,0 +1,358 @@ ++// Copyright 2020 The Abseil Authors ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// https://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++#ifndef ABSL_NUMERIC_INTERNAL_BITS_H_ ++#define ABSL_NUMERIC_INTERNAL_BITS_H_ ++ ++#include ++#include ++#include ++ ++// Clang on Windows has __builtin_clzll; otherwise we need to use the ++// windows intrinsic functions. ++#if defined(_MSC_VER) && !defined(__clang__) ++#include ++#endif ++ ++#include "absl/base/attributes.h" ++#include "absl/base/config.h" ++ ++#if defined(__GNUC__) && !defined(__clang__) ++// GCC ++#define ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(x) 1 ++#else ++#define ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(x) ABSL_HAVE_BUILTIN(x) ++#endif ++ ++#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcountl) && \ ++ ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcountll) ++#define ABSL_INTERNAL_CONSTEXPR_POPCOUNT constexpr ++#define ABSL_INTERNAL_HAS_CONSTEXPR_POPCOUNT 1 ++#else ++#define ABSL_INTERNAL_CONSTEXPR_POPCOUNT ++#define ABSL_INTERNAL_HAS_CONSTEXPR_POPCOUNT 0 ++#endif ++ ++#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clz) && \ ++ ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clzll) ++#define ABSL_INTERNAL_CONSTEXPR_CLZ constexpr ++#define ABSL_INTERNAL_HAS_CONSTEXPR_CLZ 1 ++#else ++#define ABSL_INTERNAL_CONSTEXPR_CLZ ++#define ABSL_INTERNAL_HAS_CONSTEXPR_CLZ 0 ++#endif ++ ++#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctz) && \ ++ ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctzll) ++#define ABSL_INTERNAL_CONSTEXPR_CTZ constexpr ++#define ABSL_INTERNAL_HAS_CONSTEXPR_CTZ 1 ++#else ++#define ABSL_INTERNAL_CONSTEXPR_CTZ ++#define ABSL_INTERNAL_HAS_CONSTEXPR_CTZ 0 ++#endif ++ ++namespace absl { ++ABSL_NAMESPACE_BEGIN ++namespace numeric_internal { ++ ++constexpr bool IsPowerOf2(unsigned int x) noexcept { ++ return x != 0 && (x & (x - 1)) == 0; ++} ++ ++template ++ABSL_MUST_USE_RESULT ABSL_ATTRIBUTE_ALWAYS_INLINE constexpr T RotateRight( ++ T x, int s) noexcept { ++ static_assert(std::is_unsigned::value, "T must be unsigned"); ++ static_assert(IsPowerOf2(std::numeric_limits::digits), ++ "T must have a power-of-2 size"); ++ ++ return static_cast(x >> (s & (std::numeric_limits::digits - 1))) | ++ static_cast(x << ((-s) & (std::numeric_limits::digits - 1))); ++} ++ ++template ++ABSL_MUST_USE_RESULT ABSL_ATTRIBUTE_ALWAYS_INLINE constexpr T RotateLeft( ++ T x, int s) noexcept { ++ static_assert(std::is_unsigned::value, "T must be unsigned"); ++ static_assert(IsPowerOf2(std::numeric_limits::digits), ++ "T must have a power-of-2 size"); ++ ++ return static_cast(x << (s & (std::numeric_limits::digits - 1))) | ++ static_cast(x >> ((-s) & (std::numeric_limits::digits - 1))); ++} ++ ++ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline int ++Popcount32(uint32_t x) noexcept { ++#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcount) ++ static_assert(sizeof(unsigned int) == sizeof(x), ++ "__builtin_popcount does not take 32-bit arg"); ++ return __builtin_popcount(x); ++#else ++ x -= ((x >> 1) & 0x55555555); ++ x = ((x >> 2) & 0x33333333) + (x & 0x33333333); ++ return static_cast((((x + (x >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24); ++#endif ++} ++ ++ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline int ++Popcount64(uint64_t x) noexcept { ++#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcountll) ++ static_assert(sizeof(unsigned long long) == sizeof(x), // NOLINT(runtime/int) ++ "__builtin_popcount does not take 64-bit arg"); ++ return __builtin_popcountll(x); ++#else ++ x -= (x >> 1) & 0x5555555555555555ULL; ++ x = ((x >> 2) & 0x3333333333333333ULL) + (x & 0x3333333333333333ULL); ++ return static_cast( ++ (((x + (x >> 4)) & 0xF0F0F0F0F0F0F0FULL) * 0x101010101010101ULL) >> 56); ++#endif ++} ++ ++template ++ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline int ++Popcount(T x) noexcept { ++ static_assert(std::is_unsigned::value, "T must be unsigned"); ++ static_assert(IsPowerOf2(std::numeric_limits::digits), ++ "T must have a power-of-2 size"); ++ static_assert(sizeof(x) <= sizeof(uint64_t), "T is too large"); ++ return sizeof(x) <= sizeof(uint32_t) ? Popcount32(x) : Popcount64(x); ++} ++ ++ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int ++CountLeadingZeroes32(uint32_t x) { ++#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clz) ++ // Use __builtin_clz, which uses the following instructions: ++ // x86: bsr, lzcnt ++ // ARM64: clz ++ // PPC: cntlzd ++ ++ static_assert(sizeof(unsigned int) == sizeof(x), ++ "__builtin_clz does not take 32-bit arg"); ++ // Handle 0 as a special case because __builtin_clz(0) is undefined. ++ return x == 0 ? 32 : __builtin_clz(x); ++#elif defined(_MSC_VER) && !defined(__clang__) ++ unsigned long result = 0; // NOLINT(runtime/int) ++ if (_BitScanReverse(&result, x)) { ++ return 31 - result; ++ } ++ return 32; ++#else ++ int zeroes = 28; ++ if (x >> 16) { ++ zeroes -= 16; ++ x >>= 16; ++ } ++ if (x >> 8) { ++ zeroes -= 8; ++ x >>= 8; ++ } ++ if (x >> 4) { ++ zeroes -= 4; ++ x >>= 4; ++ } ++ return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[x] + zeroes; ++#endif ++} ++ ++ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int ++CountLeadingZeroes16(uint16_t x) { ++#if ABSL_HAVE_BUILTIN(__builtin_clzs) ++ static_assert(sizeof(unsigned short) == sizeof(x), // NOLINT(runtime/int) ++ "__builtin_clzs does not take 16-bit arg"); ++ return x == 0 ? 16 : __builtin_clzs(x); ++#else ++ return CountLeadingZeroes32(x) - 16; ++#endif ++} ++ ++ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int ++CountLeadingZeroes64(uint64_t x) { ++#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clzll) ++ // Use __builtin_clzll, which uses the following instructions: ++ // x86: bsr, lzcnt ++ // ARM64: clz ++ // PPC: cntlzd ++ static_assert(sizeof(unsigned long long) == sizeof(x), // NOLINT(runtime/int) ++ "__builtin_clzll does not take 64-bit arg"); ++ ++ // Handle 0 as a special case because __builtin_clzll(0) is undefined. ++ return x == 0 ? 64 : __builtin_clzll(x); ++#elif defined(_MSC_VER) && !defined(__clang__) && \ ++ (defined(_M_X64) || defined(_M_ARM64)) ++ // MSVC does not have __buitin_clzll. Use _BitScanReverse64. ++ unsigned long result = 0; // NOLINT(runtime/int) ++ if (_BitScanReverse64(&result, x)) { ++ return 63 - result; ++ } ++ return 64; ++#elif defined(_MSC_VER) && !defined(__clang__) ++ // MSVC does not have __buitin_clzll. Compose two calls to _BitScanReverse ++ unsigned long result = 0; // NOLINT(runtime/int) ++ if ((x >> 32) && ++ _BitScanReverse(&result, static_cast(x >> 32))) { ++ return 31 - result; ++ } ++ if (_BitScanReverse(&result, static_cast(x))) { ++ return 63 - result; ++ } ++ return 64; ++#else ++ int zeroes = 60; ++ if (x >> 32) { ++ zeroes -= 32; ++ x >>= 32; ++ } ++ if (x >> 16) { ++ zeroes -= 16; ++ x >>= 16; ++ } ++ if (x >> 8) { ++ zeroes -= 8; ++ x >>= 8; ++ } ++ if (x >> 4) { ++ zeroes -= 4; ++ x >>= 4; ++ } ++ return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[x] + zeroes; ++#endif ++} ++ ++template ++ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int ++CountLeadingZeroes(T x) { ++ static_assert(std::is_unsigned::value, "T must be unsigned"); ++ static_assert(IsPowerOf2(std::numeric_limits::digits), ++ "T must have a power-of-2 size"); ++ static_assert(sizeof(T) <= sizeof(uint64_t), "T too large"); ++ return sizeof(T) <= sizeof(uint16_t) ++ ? CountLeadingZeroes16(static_cast(x)) - ++ (std::numeric_limits::digits - ++ std::numeric_limits::digits) ++ : (sizeof(T) <= sizeof(uint32_t) ++ ? CountLeadingZeroes32(static_cast(x)) - ++ (std::numeric_limits::digits - ++ std::numeric_limits::digits) ++ : CountLeadingZeroes64(x)); ++} ++ ++ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int ++CountTrailingZeroesNonzero32(uint32_t x) { ++#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctz) ++ static_assert(sizeof(unsigned int) == sizeof(x), ++ "__builtin_ctz does not take 32-bit arg"); ++ return __builtin_ctz(x); ++#elif defined(_MSC_VER) && !defined(__clang__) ++ unsigned long result = 0; // NOLINT(runtime/int) ++ _BitScanForward(&result, x); ++ return result; ++#else ++ int c = 31; ++ x &= ~x + 1; ++ if (x & 0x0000FFFF) c -= 16; ++ if (x & 0x00FF00FF) c -= 8; ++ if (x & 0x0F0F0F0F) c -= 4; ++ if (x & 0x33333333) c -= 2; ++ if (x & 0x55555555) c -= 1; ++ return c; ++#endif ++} ++ ++ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int ++CountTrailingZeroesNonzero64(uint64_t x) { ++#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctzll) ++ static_assert(sizeof(unsigned long long) == sizeof(x), // NOLINT(runtime/int) ++ "__builtin_ctzll does not take 64-bit arg"); ++ return __builtin_ctzll(x); ++#elif defined(_MSC_VER) && !defined(__clang__) && \ ++ (defined(_M_X64) || defined(_M_ARM64)) ++ unsigned long result = 0; // NOLINT(runtime/int) ++ _BitScanForward64(&result, x); ++ return result; ++#elif defined(_MSC_VER) && !defined(__clang__) ++ unsigned long result = 0; // NOLINT(runtime/int) ++ if (static_cast(x) == 0) { ++ _BitScanForward(&result, static_cast(x >> 32)); ++ return result + 32; ++ } ++ _BitScanForward(&result, static_cast(x)); ++ return result; ++#else ++ int c = 63; ++ x &= ~x + 1; ++ if (x & 0x00000000FFFFFFFF) c -= 32; ++ if (x & 0x0000FFFF0000FFFF) c -= 16; ++ if (x & 0x00FF00FF00FF00FF) c -= 8; ++ if (x & 0x0F0F0F0F0F0F0F0F) c -= 4; ++ if (x & 0x3333333333333333) c -= 2; ++ if (x & 0x5555555555555555) c -= 1; ++ return c; ++#endif ++} ++ ++ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int ++CountTrailingZeroesNonzero16(uint16_t x) { ++#if ABSL_HAVE_BUILTIN(__builtin_ctzs) ++ static_assert(sizeof(unsigned short) == sizeof(x), // NOLINT(runtime/int) ++ "__builtin_ctzs does not take 16-bit arg"); ++ return __builtin_ctzs(x); ++#else ++ return CountTrailingZeroesNonzero32(x); ++#endif ++} ++ ++template ++ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int ++CountTrailingZeroes(T x) noexcept { ++ static_assert(std::is_unsigned::value, "T must be unsigned"); ++ static_assert(IsPowerOf2(std::numeric_limits::digits), ++ "T must have a power-of-2 size"); ++ static_assert(sizeof(T) <= sizeof(uint64_t), "T too large"); ++ return x == 0 ? std::numeric_limits::digits ++ : (sizeof(T) <= sizeof(uint16_t) ++ ? CountTrailingZeroesNonzero16(static_cast(x)) ++ : (sizeof(T) <= sizeof(uint32_t) ++ ? CountTrailingZeroesNonzero32( ++ static_cast(x)) ++ : CountTrailingZeroesNonzero64(x))); ++} ++ ++// If T is narrower than unsigned, T{1} << bit_width will be promoted. We ++// want to force it to wraparound so that bit_ceil of an invalid value are not ++// core constant expressions. ++template ++ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline ++ typename std::enable_if::value, T>::type ++ BitCeilPromotionHelper(T x, T promotion) { ++ return (T{1} << (x + promotion)) >> promotion; ++} ++ ++template ++ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline ++ typename std::enable_if::value, T>::type ++ BitCeilNonPowerOf2(T x) { ++ // If T is narrower than unsigned, it undergoes promotion to unsigned when we ++ // shift. We calculate the number of bits added by the wider type. ++ return BitCeilPromotionHelper( ++ static_cast(std::numeric_limits::digits - CountLeadingZeroes(x)), ++ T{sizeof(T) >= sizeof(unsigned) ? 0 ++ : std::numeric_limits::digits - ++ std::numeric_limits::digits}); ++} ++ ++} // namespace numeric_internal ++ABSL_NAMESPACE_END ++} // namespace absl ++ ++#endif // ABSL_NUMERIC_INTERNAL_BITS_H_ +diff --git a/extern/int128/absl/numeric/internal/representation.h b/extern/int128/absl/numeric/internal/representation.h +new file mode 100644 +index 0000000000..82d332fdde +--- /dev/null ++++ b/extern/int128/absl/numeric/internal/representation.h +@@ -0,0 +1,55 @@ ++// Copyright 2021 The Abseil Authors ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// https://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++#ifndef ABSL_NUMERIC_INTERNAL_REPRESENTATION_H_ ++#define ABSL_NUMERIC_INTERNAL_REPRESENTATION_H_ ++ ++#include ++ ++#include "absl/base/config.h" ++ ++namespace absl { ++ABSL_NAMESPACE_BEGIN ++namespace numeric_internal { ++ ++// Returns true iff long double is represented as a pair of doubles added ++// together. ++inline constexpr bool IsDoubleDouble() { ++ // A double-double value always has exactly twice the precision of a double ++ // value--one double carries the high digits and one double carries the low ++ // digits. This property is not shared with any other common floating-point ++ // representation, so this test won't trigger false positives. For reference, ++ // this table gives the number of bits of precision of each common ++ // floating-point representation: ++ // ++ // type precision ++ // IEEE single 24 b ++ // IEEE double 53 ++ // x86 long double 64 ++ // double-double 106 ++ // IEEE quadruple 113 ++ // ++ // Note in particular that a quadruple-precision float has greater precision ++ // than a double-double float despite taking up the same amount of memory; the ++ // quad has more of its bits allocated to the mantissa than the double-double ++ // has. ++ return std::numeric_limits::digits == ++ 2 * std::numeric_limits::digits; ++} ++ ++} // namespace numeric_internal ++ABSL_NAMESPACE_END ++} // namespace absl ++ ++#endif // ABSL_NUMERIC_INTERNAL_REPRESENTATION_H_ +diff --git a/extern/ttmath/ttmath.h b/extern/ttmath/ttmath.h +deleted file mode 100644 +index 9b9e8ee6e5..0000000000 +--- a/extern/ttmath/ttmath.h ++++ /dev/null +@@ -1,2843 +0,0 @@ +-/* +- * This file is a part of TTMath Bignum Library +- * and is distributed under the (new) BSD licence. +- * Author: Tomasz Sowa +- */ +- +-/* +- * Copyright (c) 2006-2012, Tomasz Sowa +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * +- * * Redistributions of source code must retain the above copyright notice, +- * this list of conditions and the following disclaimer. +- * +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * +- * * Neither the name Tomasz Sowa nor the names of contributors to this +- * project may be used to endorse or promote products derived +- * from this software without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +- * THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +- +- +-#ifndef headerfilettmathmathtt +-#define headerfilettmathmathtt +- +-/*! +- \file ttmath.h +- \brief Mathematics functions. +-*/ +- +-#ifdef _MSC_VER +-//warning C4127: conditional expression is constant +-#pragma warning( disable: 4127 ) +-//warning C4702: unreachable code +-#pragma warning( disable: 4702 ) +-//warning C4800: forcing value to bool 'true' or 'false' (performance warning) +-#pragma warning( disable: 4800 ) +-#endif +- +-#define TTMATH_DONT_USE_WCHAR +- +-#include "ttmathint.h" +-#include "ttmathobjects.h" +- +- +-namespace ttmath +-{ +- /* +- * +- * functions defined here are used only with Big<> types +- * +- * +- */ +- +- +- /* +- * +- * functions for rounding +- * +- * +- */ +- +- +- /*! +- this function skips the fraction from x +- e.g 2.2 = 2 +- 2.7 = 2 +- -2.2 = 2 +- -2.7 = 2 +- */ +- template +- ValueType SkipFraction(const ValueType & x) +- { +- ValueType result( x ); +- result.SkipFraction(); +- +- return result; +- } +- +- +- /*! +- this function rounds to the nearest integer value +- e.g 2.2 = 2 +- 2.7 = 3 +- -2.2 = -2 +- -2.7 = -3 +- */ +- template +- ValueType Round(const ValueType & x, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; // NaN +- } +- +- ValueType result( x ); +- uint c = result.Round(); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return result; +- } +- +- +- +- /*! +- this function returns a value representing the smallest integer +- that is greater than or equal to x +- +- Ceil(-3.7) = -3 +- Ceil(-3.1) = -3 +- Ceil(-3.0) = -3 +- Ceil(4.0) = 4 +- Ceil(4.2) = 5 +- Ceil(4.8) = 5 +- */ +- template +- ValueType Ceil(const ValueType & x, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; // NaN +- } +- +- ValueType result(x); +- uint c = 0; +- +- result.SkipFraction(); +- +- if( result != x ) +- { +- // x is with fraction +- // if x is negative we don't have to do anything +- if( !x.IsSign() ) +- { +- ValueType one; +- one.SetOne(); +- +- c += result.Add(one); +- } +- } +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return result; +- } +- +- +- /*! +- this function returns a value representing the largest integer +- that is less than or equal to x +- +- Floor(-3.6) = -4 +- Floor(-3.1) = -4 +- Floor(-3) = -3 +- Floor(2) = 2 +- Floor(2.3) = 2 +- Floor(2.8) = 2 +- */ +- template +- ValueType Floor(const ValueType & x, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; // NaN +- } +- +- ValueType result(x); +- uint c = 0; +- +- result.SkipFraction(); +- +- if( result != x ) +- { +- // x is with fraction +- // if x is positive we don't have to do anything +- if( x.IsSign() ) +- { +- ValueType one; +- one.SetOne(); +- +- c += result.Sub(one); +- } +- } +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return result; +- } +- +- +- +- /* +- * +- * logarithms and the exponent +- * +- * +- */ +- +- +- /*! +- this function calculates the natural logarithm (logarithm with the base 'e') +- */ +- template +- ValueType Ln(const ValueType & x, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; // NaN +- } +- +- ValueType result; +- uint state = result.Ln(x); +- +- if( err ) +- { +- switch( state ) +- { +- case 0: +- *err = err_ok; +- break; +- case 1: +- *err = err_overflow; +- break; +- case 2: +- *err = err_improper_argument; +- break; +- default: +- *err = err_internal_error; +- break; +- } +- } +- +- +- return result; +- } +- +- +- /*! +- this function calculates the logarithm +- */ +- template +- ValueType Log(const ValueType & x, const ValueType & base, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) *err = err_improper_argument; +- return x; +- } +- +- if( base.IsNan() ) +- { +- if( err ) *err = err_improper_argument; +- return base; +- } +- +- ValueType result; +- uint state = result.Log(x, base); +- +- if( err ) +- { +- switch( state ) +- { +- case 0: +- *err = err_ok; +- break; +- case 1: +- *err = err_overflow; +- break; +- case 2: +- case 3: +- *err = err_improper_argument; +- break; +- default: +- *err = err_internal_error; +- break; +- } +- } +- +- return result; +- } +- +- +- /*! +- this function calculates the expression e^x +- */ +- template +- ValueType Exp(const ValueType & x, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; // NaN +- } +- +- ValueType result; +- uint c = result.Exp(x); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return result; +- } +- +- +- /*! +- * +- * trigonometric functions +- * +- */ +- +- +- /* +- this namespace consists of auxiliary functions +- (something like 'private' in a class) +- */ +- namespace auxiliaryfunctions +- { +- +- /*! +- an auxiliary function for calculating the Sine +- (you don't have to call this function) +- */ +- template +- uint PrepareSin(ValueType & x, bool & change_sign) +- { +- ValueType temp; +- +- change_sign = false; +- +- if( x.IsSign() ) +- { +- // we're using the formula 'sin(-x) = -sin(x)' +- change_sign = !change_sign; +- x.ChangeSign(); +- } +- +- // we're reducing the period 2*PI +- // (for big values there'll always be zero) +- temp.Set2Pi(); +- +- if( x.Mod(temp) ) +- return 1; +- +- +- // we're setting 'x' as being in the range of <0, 0.5PI> +- +- temp.SetPi(); +- +- if( x > temp ) +- { +- // x is in (pi, 2*pi> +- x.Sub( temp ); +- change_sign = !change_sign; +- } +- +- temp.Set05Pi(); +- +- if( x > temp ) +- { +- // x is in (0.5pi, pi> +- x.Sub( temp ); +- x = temp - x; +- } +- +- return 0; +- } +- +- +- /*! +- an auxiliary function for calculating the Sine +- (you don't have to call this function) +- +- it returns Sin(x) where 'x' is from <0, PI/2> +- we're calculating the Sin with using Taylor series in zero or PI/2 +- (depending on which point of these two points is nearer to the 'x') +- +- Taylor series: +- sin(x) = sin(a) + cos(a)*(x-a)/(1!) +- - sin(a)*((x-a)^2)/(2!) - cos(a)*((x-a)^3)/(3!) +- + sin(a)*((x-a)^4)/(4!) + ... +- +- when a=0 it'll be: +- sin(x) = (x)/(1!) - (x^3)/(3!) + (x^5)/(5!) - (x^7)/(7!) + (x^9)/(9!) ... +- +- and when a=PI/2: +- sin(x) = 1 - ((x-PI/2)^2)/(2!) + ((x-PI/2)^4)/(4!) - ((x-PI/2)^6)/(6!) ... +- */ +- template +- ValueType Sin0pi05(const ValueType & x) +- { +- ValueType result; +- ValueType numerator, denominator; +- ValueType d_numerator, d_denominator; +- ValueType one, temp, old_result; +- +- // temp = pi/4 +- temp.Set05Pi(); +- temp.exponent.SubOne(); +- +- one.SetOne(); +- +- if( x < temp ) +- { +- // we're using the Taylor series with a=0 +- result = x; +- numerator = x; +- denominator = one; +- +- // d_numerator = x^2 +- d_numerator = x; +- d_numerator.Mul(x); +- +- d_denominator = 2; +- } +- else +- { +- // we're using the Taylor series with a=PI/2 +- result = one; +- numerator = one; +- denominator = one; +- +- // d_numerator = (x-pi/2)^2 +- ValueType pi05; +- pi05.Set05Pi(); +- +- temp = x; +- temp.Sub( pi05 ); +- d_numerator = temp; +- d_numerator.Mul( temp ); +- +- d_denominator = one; +- } +- +- uint c = 0; +- bool addition = false; +- +- old_result = result; +- for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) +- { +- // we're starting from a second part of the formula +- c += numerator. Mul( d_numerator ); +- c += denominator. Mul( d_denominator ); +- c += d_denominator.Add( one ); +- c += denominator. Mul( d_denominator ); +- c += d_denominator.Add( one ); +- temp = numerator; +- c += temp.Div(denominator); +- +- if( c ) +- // Sin is from <-1,1> and cannot make an overflow +- // but the carry can be from the Taylor series +- // (then we only break our calculations) +- break; +- +- if( addition ) +- result.Add( temp ); +- else +- result.Sub( temp ); +- +- +- addition = !addition; +- +- // we're testing whether the result has changed after adding +- // the next part of the Taylor formula, if not we end the loop +- // (it means 'x' is zero or 'x' is PI/2 or this part of the formula +- // is too small) +- if( result == old_result ) +- break; +- +- old_result = result; +- } +- +- return result; +- } +- +- } // namespace auxiliaryfunctions +- +- +- +- /*! +- this function calculates the Sine +- */ +- template +- ValueType Sin(ValueType x, ErrorCode * err = 0) +- { +- using namespace auxiliaryfunctions; +- +- ValueType one, result; +- bool change_sign; +- +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; +- } +- +- if( err ) +- *err = err_ok; +- +- if( PrepareSin( x, change_sign ) ) +- { +- // x is too big, we cannnot reduce the 2*PI period +- // prior to version 0.8.5 the result was zero +- +- // result has NaN flag set by default +- +- if( err ) +- *err = err_overflow; // maybe another error code? err_improper_argument? +- +- return result; // NaN is set by default +- } +- +- result = Sin0pi05( x ); +- +- one.SetOne(); +- +- // after calculations there can be small distortions in the result +- if( result > one ) +- result = one; +- else +- if( result.IsSign() ) +- // we've calculated the sin from <0, pi/2> and the result +- // should be positive +- result.SetZero(); +- +- if( change_sign ) +- result.ChangeSign(); +- +- return result; +- } +- +- +- /*! +- this function calulates the Cosine +- we're using the formula cos(x) = sin(x + PI/2) +- */ +- template +- ValueType Cos(ValueType x, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; // NaN +- } +- +- ValueType pi05; +- pi05.Set05Pi(); +- +- uint c = x.Add( pi05 ); +- +- if( c ) +- { +- if( err ) +- *err = err_overflow; +- +- return ValueType(); // result is undefined (NaN is set by default) +- } +- +- return Sin(x, err); +- } +- +- +- /*! +- this function calulates the Tangent +- we're using the formula tan(x) = sin(x) / cos(x) +- +- it takes more time than calculating the Tan directly +- from for example Taylor series but should be a bit preciser +- because Tan receives its values from -infinity to +infinity +- and when we calculate it from any series then we can make +- a greater mistake than calculating 'sin/cos' +- */ +- template +- ValueType Tan(const ValueType & x, ErrorCode * err = 0) +- { +- ValueType result = Cos(x, err); +- +- if( err && *err != err_ok ) +- return result; +- +- if( result.IsZero() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- result.SetNan(); +- +- return result; +- } +- +- return Sin(x, err) / result; +- } +- +- +- /*! +- this function calulates the Tangent +- look at the description of Tan(...) +- +- (the abbreviation of Tangent can be 'tg' as well) +- */ +- template +- ValueType Tg(const ValueType & x, ErrorCode * err = 0) +- { +- return Tan(x, err); +- } +- +- +- /*! +- this function calulates the Cotangent +- we're using the formula tan(x) = cos(x) / sin(x) +- +- (why do we make it in this way? +- look at information in Tan() function) +- */ +- template +- ValueType Cot(const ValueType & x, ErrorCode * err = 0) +- { +- ValueType result = Sin(x, err); +- +- if( err && *err != err_ok ) +- return result; +- +- if( result.IsZero() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- result.SetNan(); +- +- return result; +- } +- +- return Cos(x, err) / result; +- } +- +- +- /*! +- this function calulates the Cotangent +- look at the description of Cot(...) +- +- (the abbreviation of Cotangent can be 'ctg' as well) +- */ +- template +- ValueType Ctg(const ValueType & x, ErrorCode * err = 0) +- { +- return Cot(x, err); +- } +- +- +- /* +- * +- * inverse trigonometric functions +- * +- * +- */ +- +- namespace auxiliaryfunctions +- { +- +- /*! +- an auxiliary function for calculating the Arc Sine +- +- we're calculating asin from the following formula: +- asin(x) = x + (1*x^3)/(2*3) + (1*3*x^5)/(2*4*5) + (1*3*5*x^7)/(2*4*6*7) + ... +- where abs(x) <= 1 +- +- we're using this formula when x is from <0, 1/2> +- */ +- template +- ValueType ASin_0(const ValueType & x) +- { +- ValueType nominator, denominator, nominator_add, nominator_x, denominator_add, denominator_x; +- ValueType two, result(x), x2(x); +- ValueType nominator_temp, denominator_temp, old_result = result; +- uint c = 0; +- +- x2.Mul(x); +- two = 2; +- +- nominator.SetOne(); +- denominator = two; +- nominator_add = nominator; +- denominator_add = denominator; +- nominator_x = x; +- denominator_x = 3; +- +- for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) +- { +- c += nominator_x.Mul(x2); +- nominator_temp = nominator_x; +- c += nominator_temp.Mul(nominator); +- denominator_temp = denominator; +- c += denominator_temp.Mul(denominator_x); +- c += nominator_temp.Div(denominator_temp); +- +- // if there is a carry somewhere we only break the calculating +- // the result should be ok -- it's from <-pi/2, pi/2> +- if( c ) +- break; +- +- result.Add(nominator_temp); +- +- if( result == old_result ) +- // there's no sense to calculate more +- break; +- +- old_result = result; +- +- +- c += nominator_add.Add(two); +- c += denominator_add.Add(two); +- c += nominator.Mul(nominator_add); +- c += denominator.Mul(denominator_add); +- c += denominator_x.Add(two); +- } +- +- return result; +- } +- +- +- +- /*! +- an auxiliary function for calculating the Arc Sine +- +- we're calculating asin from the following formula: +- asin(x) = pi/2 - sqrt(2)*sqrt(1-x) * asin_temp +- asin_temp = 1 + (1*(1-x))/((2*3)*(2)) + (1*3*(1-x)^2)/((2*4*5)*(4)) + (1*3*5*(1-x)^3)/((2*4*6*7)*(8)) + ... +- +- where abs(x) <= 1 +- +- we're using this formula when x is from (1/2, 1> +- */ +- template +- ValueType ASin_1(const ValueType & x) +- { +- ValueType nominator, denominator, nominator_add, nominator_x, nominator_x_add, denominator_add, denominator_x; +- ValueType denominator2; +- ValueType one, two, result; +- ValueType nominator_temp, denominator_temp, old_result; +- uint c = 0; +- +- two = 2; +- +- one.SetOne(); +- nominator = one; +- result = one; +- old_result = result; +- denominator = two; +- nominator_add = nominator; +- denominator_add = denominator; +- nominator_x = one; +- nominator_x.Sub(x); +- nominator_x_add = nominator_x; +- denominator_x = 3; +- denominator2 = two; +- +- +- for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) +- { +- nominator_temp = nominator_x; +- c += nominator_temp.Mul(nominator); +- denominator_temp = denominator; +- c += denominator_temp.Mul(denominator_x); +- c += denominator_temp.Mul(denominator2); +- c += nominator_temp.Div(denominator_temp); +- +- // if there is a carry somewhere we only break the calculating +- // the result should be ok -- it's from <-pi/2, pi/2> +- if( c ) +- break; +- +- result.Add(nominator_temp); +- +- if( result == old_result ) +- // there's no sense to calculate more +- break; +- +- old_result = result; +- +- c += nominator_x.Mul(nominator_x_add); +- c += nominator_add.Add(two); +- c += denominator_add.Add(two); +- c += nominator.Mul(nominator_add); +- c += denominator.Mul(denominator_add); +- c += denominator_x.Add(two); +- c += denominator2.Mul(two); +- } +- +- +- nominator_x_add.exponent.AddOne(); // *2 +- one.exponent.SubOne(); // =0.5 +- nominator_x_add.Pow(one); // =sqrt(nominator_x_add) +- result.Mul(nominator_x_add); +- +- one.Set05Pi(); +- one.Sub(result); +- +- return one; +- } +- +- +- } // namespace auxiliaryfunctions +- +- +- /*! +- this function calculates the Arc Sine +- x is from <-1,1> +- */ +- template +- ValueType ASin(ValueType x, ErrorCode * err = 0) +- { +- using namespace auxiliaryfunctions; +- +- ValueType result, one; +- one.SetOne(); +- bool change_sign = false; +- +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; +- } +- +- if( x.GreaterWithoutSignThan(one) ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return result; // NaN is set by default +- } +- +- if( x.IsSign() ) +- { +- change_sign = true; +- x.Abs(); +- } +- +- one.exponent.SubOne(); // =0.5 +- +- // asin(-x) = -asin(x) +- if( x.GreaterWithoutSignThan(one) ) +- result = ASin_1(x); +- else +- result = ASin_0(x); +- +- if( change_sign ) +- result.ChangeSign(); +- +- if( err ) +- *err = err_ok; +- +- return result; +- } +- +- +- /*! +- this function calculates the Arc Cosine +- +- we're using the formula: +- acos(x) = pi/2 - asin(x) +- */ +- template +- ValueType ACos(const ValueType & x, ErrorCode * err = 0) +- { +- ValueType temp; +- +- temp.Set05Pi(); +- temp.Sub(ASin(x, err)); +- +- return temp; +- } +- +- +- +- namespace auxiliaryfunctions +- { +- +- /*! +- an auxiliary function for calculating the Arc Tangent +- +- arc tan (x) where x is in <0; 0.5) +- (x can be in (-0.5 ; 0.5) too) +- +- we're using the Taylor series expanded in zero: +- atan(x) = x - (x^3)/3 + (x^5)/5 - (x^7)/7 + ... +- */ +- template +- ValueType ATan0(const ValueType & x) +- { +- ValueType nominator, denominator, nominator_add, denominator_add, temp; +- ValueType result, old_result; +- bool adding = false; +- uint c = 0; +- +- result = x; +- old_result = result; +- nominator = x; +- nominator_add = x; +- nominator_add.Mul(x); +- +- denominator.SetOne(); +- denominator_add = 2; +- +- for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) +- { +- c += nominator.Mul(nominator_add); +- c += denominator.Add(denominator_add); +- +- temp = nominator; +- c += temp.Div(denominator); +- +- if( c ) +- // the result should be ok +- break; +- +- if( adding ) +- result.Add(temp); +- else +- result.Sub(temp); +- +- if( result == old_result ) +- // there's no sense to calculate more +- break; +- +- old_result = result; +- adding = !adding; +- } +- +- return result; +- } +- +- +- /*! +- an auxiliary function for calculating the Arc Tangent +- +- where x is in <0 ; 1> +- */ +- template +- ValueType ATan01(const ValueType & x) +- { +- ValueType half; +- half.Set05(); +- +- /* +- it would be better if we chose about sqrt(2)-1=0.41... instead of 0.5 here +- +- because as you can see below: +- when x = sqrt(2)-1 +- abs(x) = abs( (x-1)/(1+x) ) +- so when we're calculating values around x +- then they will be better converged to each other +- +- for example if we have x=0.4999 then during calculating ATan0(0.4999) +- we have to make about 141 iterations but when we have x=0.5 +- then during calculating ATan0( (x-1)/(1+x) ) we have to make +- only about 89 iterations (both for Big<3,9>) +- +- in the future this 0.5 can be changed +- */ +- if( x.SmallerWithoutSignThan(half) ) +- return ATan0(x); +- +- +- /* +- x>=0.5 and x<=1 +- (x can be even smaller than 0.5) +- +- y = atac(x) +- x = tan(y) +- +- tan(y-b) = (tan(y)-tab(b)) / (1+tan(y)*tan(b)) +- y-b = atan( (tan(y)-tab(b)) / (1+tan(y)*tan(b)) ) +- y = b + atan( (x-tab(b)) / (1+x*tan(b)) ) +- +- let b = pi/4 +- tan(b) = tan(pi/4) = 1 +- y = pi/4 + atan( (x-1)/(1+x) ) +- +- so +- atac(x) = pi/4 + atan( (x-1)/(1+x) ) +- when x->1 (x converges to 1) the (x-1)/(1+x) -> 0 +- and we can use ATan0() function here +- */ +- +- ValueType n(x),d(x),one,result; +- +- one.SetOne(); +- n.Sub(one); +- d.Add(one); +- n.Div(d); +- +- result = ATan0(n); +- +- n.Set05Pi(); +- n.exponent.SubOne(); // =pi/4 +- result.Add(n); +- +- return result; +- } +- +- +- /*! +- an auxiliary function for calculating the Arc Tangent +- where x > 1 +- +- we're using the formula: +- atan(x) = pi/2 - atan(1/x) for x>0 +- */ +- template +- ValueType ATanGreaterThanPlusOne(const ValueType & x) +- { +- ValueType temp, atan; +- +- temp.SetOne(); +- +- if( temp.Div(x) ) +- { +- // if there was a carry here that means x is very big +- // and atan(1/x) fast converged to 0 +- atan.SetZero(); +- } +- else +- atan = ATan01(temp); +- +- temp.Set05Pi(); +- temp.Sub(atan); +- +- return temp; +- } +- +- } // namespace auxiliaryfunctions +- +- +- /*! +- this function calculates the Arc Tangent +- */ +- template +- ValueType ATan(ValueType x) +- { +- using namespace auxiliaryfunctions; +- +- ValueType one, result; +- one.SetOne(); +- bool change_sign = false; +- +- if( x.IsNan() ) +- return x; +- +- // if x is negative we're using the formula: +- // atan(-x) = -atan(x) +- if( x.IsSign() ) +- { +- change_sign = true; +- x.Abs(); +- } +- +- if( x.GreaterWithoutSignThan(one) ) +- result = ATanGreaterThanPlusOne(x); +- else +- result = ATan01(x); +- +- if( change_sign ) +- result.ChangeSign(); +- +- return result; +- } +- +- +- /*! +- this function calculates the Arc Tangent +- look at the description of ATan(...) +- +- (the abbreviation of Arc Tangent can be 'atg' as well) +- */ +- template +- ValueType ATg(const ValueType & x) +- { +- return ATan(x); +- } +- +- +- /*! +- this function calculates the Arc Cotangent +- +- we're using the formula: +- actan(x) = pi/2 - atan(x) +- */ +- template +- ValueType ACot(const ValueType & x) +- { +- ValueType result; +- +- result.Set05Pi(); +- result.Sub(ATan(x)); +- +- return result; +- } +- +- +- /*! +- this function calculates the Arc Cotangent +- look at the description of ACot(...) +- +- (the abbreviation of Arc Cotangent can be 'actg' as well) +- */ +- template +- ValueType ACtg(const ValueType & x) +- { +- return ACot(x); +- } +- +- +- /* +- * +- * hyperbolic functions +- * +- * +- */ +- +- +- /*! +- this function calculates the Hyperbolic Sine +- +- we're using the formula sinh(x)= ( e^x - e^(-x) ) / 2 +- */ +- template +- ValueType Sinh(const ValueType & x, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; // NaN +- } +- +- ValueType ex, emx; +- uint c = 0; +- +- c += ex.Exp(x); +- c += emx.Exp(-x); +- +- c += ex.Sub(emx); +- c += ex.exponent.SubOne(); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return ex; +- } +- +- +- /*! +- this function calculates the Hyperbolic Cosine +- +- we're using the formula cosh(x)= ( e^x + e^(-x) ) / 2 +- */ +- template +- ValueType Cosh(const ValueType & x, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; // NaN +- } +- +- ValueType ex, emx; +- uint c = 0; +- +- c += ex.Exp(x); +- c += emx.Exp(-x); +- +- c += ex.Add(emx); +- c += ex.exponent.SubOne(); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return ex; +- } +- +- +- /*! +- this function calculates the Hyperbolic Tangent +- +- we're using the formula tanh(x)= ( e^x - e^(-x) ) / ( e^x + e^(-x) ) +- */ +- template +- ValueType Tanh(const ValueType & x, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; // NaN +- } +- +- ValueType ex, emx, nominator, denominator; +- uint c = 0; +- +- c += ex.Exp(x); +- c += emx.Exp(-x); +- +- nominator = ex; +- c += nominator.Sub(emx); +- denominator = ex; +- c += denominator.Add(emx); +- +- c += nominator.Div(denominator); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return nominator; +- } +- +- +- /*! +- this function calculates the Hyperbolic Tangent +- look at the description of Tanh(...) +- +- (the abbreviation of Hyperbolic Tangent can be 'tgh' as well) +- */ +- template +- ValueType Tgh(const ValueType & x, ErrorCode * err = 0) +- { +- return Tanh(x, err); +- } +- +- /*! +- this function calculates the Hyperbolic Cotangent +- +- we're using the formula coth(x)= ( e^x + e^(-x) ) / ( e^x - e^(-x) ) +- */ +- template +- ValueType Coth(const ValueType & x, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; // NaN +- } +- +- if( x.IsZero() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return ValueType(); // NaN is set by default +- } +- +- ValueType ex, emx, nominator, denominator; +- uint c = 0; +- +- c += ex.Exp(x); +- c += emx.Exp(-x); +- +- nominator = ex; +- c += nominator.Add(emx); +- denominator = ex; +- c += denominator.Sub(emx); +- +- c += nominator.Div(denominator); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return nominator; +- } +- +- +- /*! +- this function calculates the Hyperbolic Cotangent +- look at the description of Coth(...) +- +- (the abbreviation of Hyperbolic Cotangent can be 'ctgh' as well) +- */ +- template +- ValueType Ctgh(const ValueType & x, ErrorCode * err = 0) +- { +- return Coth(x, err); +- } +- +- +- /* +- * +- * inverse hyperbolic functions +- * +- * +- */ +- +- +- /*! +- inverse hyperbolic sine +- +- asinh(x) = ln( x + sqrt(x^2 + 1) ) +- */ +- template +- ValueType ASinh(const ValueType & x, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; // NaN +- } +- +- ValueType xx(x), one, result; +- uint c = 0; +- one.SetOne(); +- +- c += xx.Mul(x); +- c += xx.Add(one); +- one.exponent.SubOne(); // one=0.5 +- // xx is >= 1 +- c += xx.PowFrac(one); // xx=sqrt(xx) +- c += xx.Add(x); +- c += result.Ln(xx); // xx > 0 +- +- // here can only be a carry +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return result; +- } +- +- +- /*! +- inverse hyperbolic cosine +- +- acosh(x) = ln( x + sqrt(x^2 - 1) ) x in <1, infinity) +- */ +- template +- ValueType ACosh(const ValueType & x, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; // NaN +- } +- +- ValueType xx(x), one, result; +- uint c = 0; +- one.SetOne(); +- +- if( x < one ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return result; // NaN is set by default +- } +- +- c += xx.Mul(x); +- c += xx.Sub(one); +- // xx is >= 0 +- // we can't call a PowFrac when the 'x' is zero +- // if x is 0 the sqrt(0) is 0 +- if( !xx.IsZero() ) +- { +- one.exponent.SubOne(); // one=0.5 +- c += xx.PowFrac(one); // xx=sqrt(xx) +- } +- c += xx.Add(x); +- c += result.Ln(xx); // xx >= 1 +- +- // here can only be a carry +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return result; +- } +- +- +- /*! +- inverse hyperbolic tangent +- +- atanh(x) = 0.5 * ln( (1+x) / (1-x) ) x in (-1, 1) +- */ +- template +- ValueType ATanh(const ValueType & x, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; // NaN +- } +- +- ValueType nominator(x), denominator, one, result; +- uint c = 0; +- one.SetOne(); +- +- if( !x.SmallerWithoutSignThan(one) ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return result; // NaN is set by default +- } +- +- c += nominator.Add(one); +- denominator = one; +- c += denominator.Sub(x); +- c += nominator.Div(denominator); +- c += result.Ln(nominator); +- c += result.exponent.SubOne(); +- +- // here can only be a carry +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return result; +- } +- +- +- /*! +- inverse hyperbolic tantent +- */ +- template +- ValueType ATgh(const ValueType & x, ErrorCode * err = 0) +- { +- return ATanh(x, err); +- } +- +- +- /*! +- inverse hyperbolic cotangent +- +- acoth(x) = 0.5 * ln( (x+1) / (x-1) ) x in (-infinity, -1) or (1, infinity) +- */ +- template +- ValueType ACoth(const ValueType & x, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; // NaN +- } +- +- ValueType nominator(x), denominator(x), one, result; +- uint c = 0; +- one.SetOne(); +- +- if( !x.GreaterWithoutSignThan(one) ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return result; // NaN is set by default +- } +- +- c += nominator.Add(one); +- c += denominator.Sub(one); +- c += nominator.Div(denominator); +- c += result.Ln(nominator); +- c += result.exponent.SubOne(); +- +- // here can only be a carry +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return result; +- } +- +- +- /*! +- inverse hyperbolic cotantent +- */ +- template +- ValueType ACtgh(const ValueType & x, ErrorCode * err = 0) +- { +- return ACoth(x, err); +- } +- +- +- +- +- +- /* +- * +- * functions for converting between degrees, radians and gradians +- * +- * +- */ +- +- +- /*! +- this function converts degrees to radians +- +- it returns: x * pi / 180 +- */ +- template +- ValueType DegToRad(const ValueType & x, ErrorCode * err = 0) +- { +- ValueType result, temp; +- uint c = 0; +- +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; +- } +- +- result = x; +- +- // it is better to make division first and then multiplication +- // the result is more accurate especially when x is: 90,180,270 or 360 +- temp = 180; +- c += result.Div(temp); +- +- temp.SetPi(); +- c += result.Mul(temp); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return result; +- } +- +- +- /*! +- this function converts radians to degrees +- +- it returns: x * 180 / pi +- */ +- template +- ValueType RadToDeg(const ValueType & x, ErrorCode * err = 0) +- { +- ValueType result, delimiter; +- uint c = 0; +- +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; +- } +- +- result = 180; +- c += result.Mul(x); +- +- delimiter.SetPi(); +- c += result.Div(delimiter); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return result; +- } +- +- +- /*! +- this function converts degrees in the long format into one value +- +- long format: (degrees, minutes, seconds) +- minutes and seconds must be greater than or equal zero +- +- result: +- if d>=0 : result= d + ((s/60)+m)/60 +- if d<0 : result= d - ((s/60)+m)/60 +- +- ((s/60)+m)/60 = (s+60*m)/3600 (second version is faster because +- there's only one division) +- +- for example: +- DegToDeg(10, 30, 0) = 10.5 +- DegToDeg(10, 24, 35.6)=10.4098(8) +- */ +- template +- ValueType DegToDeg( const ValueType & d, const ValueType & m, const ValueType & s, +- ErrorCode * err = 0) +- { +- ValueType delimiter, multipler; +- uint c = 0; +- +- if( d.IsNan() || m.IsNan() || s.IsNan() || m.IsSign() || s.IsSign() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- delimiter.SetZeroNan(); // not needed, only to get rid of GCC warning about an uninitialized variable +- +- return delimiter; +- } +- +- multipler = 60; +- delimiter = 3600; +- +- c += multipler.Mul(m); +- c += multipler.Add(s); +- c += multipler.Div(delimiter); +- +- if( d.IsSign() ) +- multipler.ChangeSign(); +- +- c += multipler.Add(d); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return multipler; +- } +- +- +- /*! +- this function converts degrees in the long format to radians +- */ +- template +- ValueType DegToRad( const ValueType & d, const ValueType & m, const ValueType & s, +- ErrorCode * err = 0) +- { +- ValueType temp_deg = DegToDeg(d,m,s,err); +- +- if( err && *err!=err_ok ) +- return temp_deg; +- +- return DegToRad(temp_deg, err); +- } +- +- +- /*! +- this function converts gradians to radians +- +- it returns: x * pi / 200 +- */ +- template +- ValueType GradToRad(const ValueType & x, ErrorCode * err = 0) +- { +- ValueType result, temp; +- uint c = 0; +- +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; +- } +- +- result = x; +- +- // it is better to make division first and then multiplication +- // the result is more accurate especially when x is: 100,200,300 or 400 +- temp = 200; +- c += result.Div(temp); +- +- temp.SetPi(); +- c += result.Mul(temp); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return result; +- } +- +- +- /*! +- this function converts radians to gradians +- +- it returns: x * 200 / pi +- */ +- template +- ValueType RadToGrad(const ValueType & x, ErrorCode * err = 0) +- { +- ValueType result, delimiter; +- uint c = 0; +- +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; +- } +- +- result = 200; +- c += result.Mul(x); +- +- delimiter.SetPi(); +- c += result.Div(delimiter); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return result; +- } +- +- +- /*! +- this function converts degrees to gradians +- +- it returns: x * 200 / 180 +- */ +- template +- ValueType DegToGrad(const ValueType & x, ErrorCode * err = 0) +- { +- ValueType result, temp; +- uint c = 0; +- +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; +- } +- +- result = x; +- +- temp = 200; +- c += result.Mul(temp); +- +- temp = 180; +- c += result.Div(temp); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return result; +- } +- +- +- /*! +- this function converts degrees in the long format to gradians +- */ +- template +- ValueType DegToGrad( const ValueType & d, const ValueType & m, const ValueType & s, +- ErrorCode * err = 0) +- { +- ValueType temp_deg = DegToDeg(d,m,s,err); +- +- if( err && *err!=err_ok ) +- return temp_deg; +- +- return DegToGrad(temp_deg, err); +- } +- +- +- /*! +- this function converts degrees to gradians +- +- it returns: x * 180 / 200 +- */ +- template +- ValueType GradToDeg(const ValueType & x, ErrorCode * err = 0) +- { +- ValueType result, temp; +- uint c = 0; +- +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; +- } +- +- result = x; +- +- temp = 180; +- c += result.Mul(temp); +- +- temp = 200; +- c += result.Div(temp); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return result; +- } +- +- +- +- +- /* +- * +- * another functions +- * +- * +- */ +- +- +- /*! +- this function calculates the square root +- +- Sqrt(9) = 3 +- */ +- template +- ValueType Sqrt(ValueType x, ErrorCode * err = 0) +- { +- if( x.IsNan() || x.IsSign() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- x.SetNan(); +- +- return x; +- } +- +- uint c = x.Sqrt(); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return x; +- } +- +- +- +- namespace auxiliaryfunctions +- { +- +- template +- bool RootCheckIndexSign(ValueType & x, const ValueType & index, ErrorCode * err) +- { +- if( index.IsSign() ) +- { +- // index cannot be negative +- if( err ) +- *err = err_improper_argument; +- +- x.SetNan(); +- +- return true; +- } +- +- return false; +- } +- +- +- template +- bool RootCheckIndexZero(ValueType & x, const ValueType & index, ErrorCode * err) +- { +- if( index.IsZero() ) +- { +- if( x.IsZero() ) +- { +- // there isn't root(0;0) - we assume it's not defined +- if( err ) +- *err = err_improper_argument; +- +- x.SetNan(); +- +- return true; +- } +- +- // root(x;0) is 1 (if x!=0) +- x.SetOne(); +- +- if( err ) +- *err = err_ok; +- +- return true; +- } +- +- return false; +- } +- +- +- template +- bool RootCheckIndexOne(const ValueType & index, ErrorCode * err) +- { +- ValueType one; +- one.SetOne(); +- +- if( index == one ) +- { +- //root(x;1) is x +- // we do it because if we used the PowFrac function +- // we would lose the precision +- if( err ) +- *err = err_ok; +- +- return true; +- } +- +- return false; +- } +- +- +- template +- bool RootCheckIndexTwo(ValueType & x, const ValueType & index, ErrorCode * err) +- { +- if( index == 2 ) +- { +- x = Sqrt(x, err); +- +- return true; +- } +- +- return false; +- } +- +- +- template +- bool RootCheckIndexFrac(ValueType & x, const ValueType & index, ErrorCode * err) +- { +- if( !index.IsInteger() ) +- { +- // index must be integer +- if( err ) +- *err = err_improper_argument; +- +- x.SetNan(); +- +- return true; +- } +- +- return false; +- } +- +- +- template +- bool RootCheckXZero(ValueType & x, ErrorCode * err) +- { +- if( x.IsZero() ) +- { +- // root(0;index) is zero (if index!=0) +- // RootCheckIndexZero() must be called beforehand +- x.SetZero(); +- +- if( err ) +- *err = err_ok; +- +- return true; +- } +- +- return false; +- } +- +- +- template +- bool RootCheckIndex(ValueType & x, const ValueType & index, ErrorCode * err, bool * change_sign) +- { +- *change_sign = false; +- +- if( index.Mod2() ) +- { +- // index is odd (1,3,5...) +- if( x.IsSign() ) +- { +- *change_sign = true; +- x.Abs(); +- } +- } +- else +- { +- // index is even +- // x cannot be negative +- if( x.IsSign() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- x.SetNan(); +- +- return true; +- } +- } +- +- return false; +- } +- +- +- template +- uint RootCorrectInteger(ValueType & old_x, ValueType & x, const ValueType & index) +- { +- if( !old_x.IsInteger() || x.IsInteger() || !index.exponent.IsSign() ) +- return 0; +- +- // old_x is integer, +- // x is not integer, +- // index is relatively small (index.exponent<0 or index.exponent<=0) +- // (because we're using a special powering algorithm Big::PowUInt()) +- +- uint c = 0; +- +- ValueType temp(x); +- c += temp.Round(); +- +- ValueType temp_round(temp); +- c += temp.PowUInt(index); +- +- if( temp == old_x ) +- x = temp_round; +- +- return (c==0)? 0 : 1; +- } +- +- +- +- } // namespace auxiliaryfunctions +- +- +- +- /*! +- indexth Root of x +- index must be integer and not negative <0;1;2;3....) +- +- if index==0 the result is one +- if x==0 the result is zero and we assume root(0;0) is not defined +- +- if index is even (2;4;6...) the result is x^(1/index) and x>0 +- if index is odd (1;2;3;...) the result is either +- -(abs(x)^(1/index)) if x<0 or +- x^(1/index)) if x>0 +- +- (for index==1 the result is equal x) +- */ +- template +- ValueType Root(ValueType x, const ValueType & index, ErrorCode * err = 0) +- { +- using namespace auxiliaryfunctions; +- +- if( x.IsNan() || index.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- x.SetNan(); +- +- return x; +- } +- +- if( RootCheckIndexSign(x, index, err) ) return x; +- if( RootCheckIndexZero(x, index, err) ) return x; +- if( RootCheckIndexOne ( index, err) ) return x; +- if( RootCheckIndexTwo (x, index, err) ) return x; +- if( RootCheckIndexFrac(x, index, err) ) return x; +- if( RootCheckXZero (x, err) ) return x; +- +- // index integer and index!=0 +- // x!=0 +- +- ValueType old_x(x); +- bool change_sign; +- +- if( RootCheckIndex(x, index, err, &change_sign ) ) return x; +- +- ValueType temp; +- uint c = 0; +- +- // we're using the formula: root(x ; n) = exp( ln(x) / n ) +- c += temp.Ln(x); +- c += temp.Div(index); +- c += x.Exp(temp); +- +- if( change_sign ) +- { +- // x is different from zero +- x.SetSign(); +- } +- +- c += RootCorrectInteger(old_x, x, index); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return x; +- } +- +- +- +- /*! +- absolute value of x +- e.g. -2 = 2 +- 2 = 2 +- */ +- template +- ValueType Abs(const ValueType & x) +- { +- ValueType result( x ); +- result.Abs(); +- +- return result; +- } +- +- +- /*! +- it returns the sign of the value +- e.g. -2 = -1 +- 0 = 0 +- 10 = 1 +- */ +- template +- ValueType Sgn(ValueType x) +- { +- x.Sgn(); +- +- return x; +- } +- +- +- /*! +- the remainder from a division +- +- e.g. +- mod( 12.6 ; 3) = 0.6 because 12.6 = 3*4 + 0.6 +- mod(-12.6 ; 3) = -0.6 bacause -12.6 = 3*(-4) + (-0.6) +- mod( 12.6 ; -3) = 0.6 +- mod(-12.6 ; -3) = -0.6 +- */ +- template +- ValueType Mod(ValueType a, const ValueType & b, ErrorCode * err = 0) +- { +- if( a.IsNan() || b.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- a.SetNan(); +- +- return a; +- } +- +- uint c = a.Mod(b); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return a; +- } +- +- +- +- namespace auxiliaryfunctions +- { +- +- /*! +- this function is used to store factorials in a given container +- 'more' means how many values should be added at the end +- +- e.g. +- std::vector fact; +- SetFactorialSequence(fact, 3); +- // now the container has three values: 1 1 2 +- +- SetFactorialSequence(fact, 2); +- // now the container has five values: 1 1 2 6 24 +- */ +- template +- void SetFactorialSequence(std::vector & fact, uint more = 20) +- { +- if( more == 0 ) +- more = 1; +- +- uint start = static_cast(fact.size()); +- fact.resize(fact.size() + more); +- +- if( start == 0 ) +- { +- fact[0] = 1; +- ++start; +- } +- +- for(uint i=start ; i +- ValueType SetBernoulliNumbersSum(CGamma & cgamma, const ValueType & n_, uint m, +- const volatile StopCalculating * stop = 0) +- { +- ValueType k_, temp, temp2, temp3, sum; +- +- sum.SetZero(); +- +- for(uint k=0 ; kWasStopSignal() ) +- return ValueType(); // NaN +- +- if( k>1 && (k & 1) == 1 ) // for that k the Bernoulli number is zero +- continue; +- +- k_ = k; +- +- temp = n_; // n_ is equal 2 +- temp.Pow(k_); +- // temp = 2^k +- +- temp2 = cgamma.fact[m]; +- temp3 = cgamma.fact[k]; +- temp3.Mul(cgamma.fact[m-k]); +- temp2.Div(temp3); +- // temp2 = (m k) = m! / ( k! * (m-k)! ) +- +- temp.Mul(temp2); +- temp.Mul(cgamma.bern[k]); +- +- sum.Add(temp); +- // sum += 2^k * (m k) * B(k) +- +- if( sum.IsNan() ) +- break; +- } +- +- return sum; +- } +- +- +- /*! +- an auxiliary function used to calculate Bernoulli numbers +- start is >= 2 +- +- we use the recurrence formula: +- B(m) = 1 / (2*(1 - 2^m)) * sum(m) +- where sum(m) is calculated by SetBernoulliNumbersSum() +- */ +- template +- bool SetBernoulliNumbersMore(CGamma & cgamma, uint start, const volatile StopCalculating * stop = 0) +- { +- ValueType denominator, temp, temp2, temp3, m_, sum, sum2, n_, k_; +- +- const uint n = 2; +- n_ = n; +- +- // start is >= 2 +- for(uint m=start ; mWasStopSignal() ) +- { +- cgamma.bern.resize(m); // valid numbers are in [0, m-1] +- return false; +- } +- +- cgamma.bern[m].Div(denominator); +- } +- } +- +- return true; +- } +- +- +- /*! +- this function is used to calculate Bernoulli numbers, +- returns false if there was a stop signal, +- 'more' means how many values should be added at the end +- +- e.g. +- typedef Big<1,2> MyBig; +- CGamma cgamma; +- SetBernoulliNumbers(cgamma, 3); +- // now we have three first Bernoulli numbers: 1 -0.5 0.16667 +- +- SetBernoulliNumbers(cgamma, 4); +- // now we have 7 Bernoulli numbers: 1 -0.5 0.16667 0 -0.0333 0 0.0238 +- */ +- template +- bool SetBernoulliNumbers(CGamma & cgamma, uint more = 20, const volatile StopCalculating * stop = 0) +- { +- if( more == 0 ) +- more = 1; +- +- uint start = static_cast(cgamma.bern.size()); +- cgamma.bern.resize(cgamma.bern.size() + more); +- +- if( start == 0 ) +- { +- cgamma.bern[0].SetOne(); +- ++start; +- } +- +- if( cgamma.bern.size() == 1 ) +- return true; +- +- if( start == 1 ) +- { +- cgamma.bern[1].Set05(); +- cgamma.bern[1].ChangeSign(); +- ++start; +- } +- +- // we should have sufficient factorials in cgamma.fact +- if( cgamma.fact.size() < cgamma.bern.size() ) +- SetFactorialSequence(cgamma.fact, static_cast(cgamma.bern.size() - cgamma.fact.size())); +- +- +- return SetBernoulliNumbersMore(cgamma, start, stop); +- } +- +- +- /*! +- an auxiliary function used to calculate the Gamma() function +- +- we calculate a sum: +- sum(n) = sum_{m=2} { B(m) / ( (m^2 - m) * n^(m-1) ) } = 1/(12*n) - 1/(360*n^3) + 1/(1260*n^5) + ... +- B(m) means a mth Bernoulli number +- the sum starts from m=2, we calculate as long as the value will not change after adding a next part +- */ +- template +- ValueType GammaFactorialHighSum(const ValueType & n, CGamma & cgamma, ErrorCode & err, +- const volatile StopCalculating * stop) +- { +- ValueType temp, temp2, denominator, sum, oldsum; +- +- sum.SetZero(); +- +- for(uint m=2 ; mWasStopSignal() ) +- { +- err = err_interrupt; +- return ValueType(); // NaN +- } +- +- temp = (m-1); +- denominator = n; +- denominator.Pow(temp); +- // denominator = n ^ (m-1) +- +- temp = m; +- temp2 = temp; +- temp.Mul(temp2); +- temp.Sub(temp2); +- // temp = m^2 - m +- +- denominator.Mul(temp); +- // denominator = (m^2 - m) * n ^ (m-1) +- +- if( m >= cgamma.bern.size() ) +- { +- if( !SetBernoulliNumbers(cgamma, m - cgamma.bern.size() + 1 + 3, stop) ) // 3 more than needed +- { +- // there was the stop signal +- err = err_interrupt; +- return ValueType(); // NaN +- } +- } +- +- temp = cgamma.bern[m]; +- temp.Div(denominator); +- +- oldsum = sum; +- sum.Add(temp); +- +- if( sum.IsNan() || oldsum==sum ) +- break; +- } +- +- return sum; +- } +- +- +- /*! +- an auxiliary function used to calculate the Gamma() function +- +- we calculate a helper function GammaFactorialHigh() by using Stirling's series: +- n! = (n/e)^n * sqrt(2*pi*n) * exp( sum(n) ) +- where n is a real number (not only an integer) and is sufficient large (greater than TTMATH_GAMMA_BOUNDARY) +- and sum(n) is calculated by GammaFactorialHighSum() +- */ +- template +- ValueType GammaFactorialHigh(const ValueType & n, CGamma & cgamma, ErrorCode & err, +- const volatile StopCalculating * stop) +- { +- ValueType temp, temp2, temp3, denominator, sum; +- +- temp.Set2Pi(); +- temp.Mul(n); +- temp2 = Sqrt(temp); +- // temp2 = sqrt(2*pi*n) +- +- temp = n; +- temp3.SetE(); +- temp.Div(temp3); +- temp.Pow(n); +- // temp = (n/e)^n +- +- sum = GammaFactorialHighSum(n, cgamma, err, stop); +- temp3.Exp(sum); +- // temp3 = exp(sum) +- +- temp.Mul(temp2); +- temp.Mul(temp3); +- +- return temp; +- } +- +- +- /*! +- an auxiliary function used to calculate the Gamma() function +- +- Gamma(x) = GammaFactorialHigh(x-1) +- */ +- template +- ValueType GammaPlusHigh(ValueType n, CGamma & cgamma, ErrorCode & err, const volatile StopCalculating * stop) +- { +- ValueType one; +- +- one.SetOne(); +- n.Sub(one); +- +- return GammaFactorialHigh(n, cgamma, err, stop); +- } +- +- +- /*! +- an auxiliary function used to calculate the Gamma() function +- +- we use this function when n is integer and a small value (from 0 to TTMATH_GAMMA_BOUNDARY] +- we use the formula: +- gamma(n) = (n-1)! = 1 * 2 * 3 * ... * (n-1) +- */ +- template +- ValueType GammaPlusLowIntegerInt(uint n, CGamma & cgamma) +- { +- TTMATH_ASSERT( n > 0 ) +- +- if( n - 1 < static_cast(cgamma.fact.size()) ) +- return cgamma.fact[n - 1]; +- +- ValueType res; +- uint start = 2; +- +- if( cgamma.fact.size() < 2 ) +- { +- res.SetOne(); +- } +- else +- { +- start = static_cast(cgamma.fact.size()); +- res = cgamma.fact[start-1]; +- } +- +- for(uint i=start ; i +- ValueType GammaPlusLowInteger(const ValueType & n, CGamma & cgamma) +- { +- sint n_; +- +- n.ToInt(n_); +- +- return GammaPlusLowIntegerInt(n_, cgamma); +- } +- +- +- /*! +- an auxiliary function used to calculate the Gamma() function +- +- we use this function when n is a small value (from 0 to TTMATH_GAMMA_BOUNDARY] +- we use a recurrence formula: +- gamma(z+1) = z * gamma(z) +- then: gamma(z) = gamma(z+1) / z +- +- e.g. +- gamma(3.89) = gamma(2001.89) / ( 3.89 * 4.89 * 5.89 * ... * 1999.89 * 2000.89 ) +- */ +- template +- ValueType GammaPlusLow(ValueType n, CGamma & cgamma, ErrorCode & err, const volatile StopCalculating * stop) +- { +- ValueType one, denominator, temp, boundary; +- +- if( n.IsInteger() ) +- return GammaPlusLowInteger(n, cgamma); +- +- one.SetOne(); +- denominator = n; +- boundary = TTMATH_GAMMA_BOUNDARY; +- +- while( n < boundary ) +- { +- n.Add(one); +- denominator.Mul(n); +- } +- +- n.Add(one); +- +- // now n is sufficient big +- temp = GammaPlusHigh(n, cgamma, err, stop); +- temp.Div(denominator); +- +- return temp; +- } +- +- +- /*! +- an auxiliary function used to calculate the Gamma() function +- */ +- template +- ValueType GammaPlus(const ValueType & n, CGamma & cgamma, ErrorCode & err, const volatile StopCalculating * stop) +- { +- if( n > TTMATH_GAMMA_BOUNDARY ) +- return GammaPlusHigh(n, cgamma, err, stop); +- +- return GammaPlusLow(n, cgamma, err, stop); +- } +- +- +- /*! +- an auxiliary function used to calculate the Gamma() function +- +- this function is used when n is negative +- we use the reflection formula: +- gamma(1-z) * gamma(z) = pi / sin(pi*z) +- then: gamma(z) = pi / (sin(pi*z) * gamma(1-z)) +- +- */ +- template +- ValueType GammaMinus(const ValueType & n, CGamma & cgamma, ErrorCode & err, const volatile StopCalculating * stop) +- { +- ValueType pi, denominator, temp, temp2; +- +- if( n.IsInteger() ) +- { +- // gamma function is not defined when n is negative and integer +- err = err_improper_argument; +- return temp; // NaN +- } +- +- pi.SetPi(); +- +- temp = pi; +- temp.Mul(n); +- temp2 = Sin(temp); +- // temp2 = sin(pi * n) +- +- temp.SetOne(); +- temp.Sub(n); +- temp = GammaPlus(temp, cgamma, err, stop); +- // temp = gamma(1 - n) +- +- temp.Mul(temp2); +- pi.Div(temp); +- +- return pi; +- } +- +- } // namespace auxiliaryfunctions +- +- +- +- /*! +- this function calculates the Gamma function +- +- it's multithread safe, you should create a CGamma<> object and use it whenever you call the Gamma() +- e.g. +- typedef Big<1,2> MyBig; +- MyBig x=234, y=345.53; +- CGamma cgamma; +- std::cout << Gamma(x, cgamma) << std::endl; +- std::cout << Gamma(y, cgamma) << std::endl; +- in the CGamma<> object the function stores some coefficients (factorials, Bernoulli numbers), +- and they will be reused in next calls to the function +- +- each thread should have its own CGamma<> object, and you can use these objects with Factorial() function too +- */ +- template +- ValueType Gamma(const ValueType & n, CGamma & cgamma, ErrorCode * err = 0, +- const volatile StopCalculating * stop = 0) +- { +- using namespace auxiliaryfunctions; +- +- ValueType result; +- ErrorCode err_tmp; +- +- if( n.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return n; +- } +- +- if( cgamma.history.Get(n, result, err_tmp) ) +- { +- if( err ) +- *err = err_tmp; +- +- return result; +- } +- +- err_tmp = err_ok; +- +- if( n.IsSign() ) +- { +- result = GammaMinus(n, cgamma, err_tmp, stop); +- } +- else +- if( n.IsZero() ) +- { +- err_tmp = err_improper_argument; +- result.SetNan(); +- } +- else +- { +- result = GammaPlus(n, cgamma, err_tmp, stop); +- } +- +- if( result.IsNan() && err_tmp==err_ok ) +- err_tmp = err_overflow; +- +- if( err ) +- *err = err_tmp; +- +- if( stop && !stop->WasStopSignal() ) +- cgamma.history.Add(n, result, err_tmp); +- +- return result; +- } +- +- +- /*! +- this function calculates the Gamma function +- +- note: this function should be used only in a single-thread environment +- */ +- template +- ValueType Gamma(const ValueType & n, ErrorCode * err = 0) +- { +- // warning: this static object is not thread safe +- static CGamma cgamma; +- +- return Gamma(n, cgamma, err); +- } +- +- +- +- namespace auxiliaryfunctions +- { +- +- /*! +- an auxiliary function for calculating the factorial function +- +- we use the formula: +- x! = gamma(x+1) +- */ +- template +- ValueType Factorial2(ValueType x, +- CGamma * cgamma = 0, +- ErrorCode * err = 0, +- const volatile StopCalculating * stop = 0) +- { +- ValueType result, one; +- +- if( x.IsNan() || x.IsSign() || !x.IsInteger() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- x.SetNan(); +- +- return x; +- } +- +- one.SetOne(); +- x.Add(one); +- +- if( cgamma ) +- return Gamma(x, *cgamma, err, stop); +- +- return Gamma(x, err); +- } +- +- } // namespace auxiliaryfunctions +- +- +- +- /*! +- the factorial from given 'x' +- e.g. +- Factorial(4) = 4! = 1*2*3*4 +- +- it's multithread safe, you should create a CGamma<> object and use it whenever you call the Factorial() +- e.g. +- typedef Big<1,2> MyBig; +- MyBig x=234, y=54345; +- CGamma cgamma; +- std::cout << Factorial(x, cgamma) << std::endl; +- std::cout << Factorial(y, cgamma) << std::endl; +- in the CGamma<> object the function stores some coefficients (factorials, Bernoulli numbers), +- and they will be reused in next calls to the function +- +- each thread should have its own CGamma<> object, and you can use these objects with Gamma() function too +- */ +- template +- ValueType Factorial(const ValueType & x, CGamma & cgamma, ErrorCode * err = 0, +- const volatile StopCalculating * stop = 0) +- { +- return auxiliaryfunctions::Factorial2(x, &cgamma, err, stop); +- } +- +- +- /*! +- the factorial from given 'x' +- e.g. +- Factorial(4) = 4! = 1*2*3*4 +- +- note: this function should be used only in a single-thread environment +- */ +- template +- ValueType Factorial(const ValueType & x, ErrorCode * err = 0) +- { +- return auxiliaryfunctions::Factorial2(x, (CGamma*)0, err, 0); +- } +- +- +- /*! +- this method prepares some coefficients: factorials and Bernoulli numbers +- stored in 'fact' and 'bern' objects +- +- we're defining the method here because we're using Gamma() function which +- is not available in ttmathobjects.h +- +- read the doc info in ttmathobjects.h file where CGamma<> struct is declared +- */ +- template +- void CGamma::InitAll() +- { +- ValueType x = TTMATH_GAMMA_BOUNDARY + 1; +- +- // history.Remove(x) removes only one object +- // we must be sure that there are not others objects with the key 'x' +- while( history.Remove(x) ) +- { +- } +- +- // the simplest way to initialize is to call the Gamma function with (TTMATH_GAMMA_BOUNDARY + 1) +- // when x is larger then fewer coefficients we need +- Gamma(x, *this); +- } +- +- +- +-} // namespace +- +- +-#ifdef _MSC_VER +-//warning C4127: conditional expression is constant +-#pragma warning( default: 4127 ) +-//warning C4702: unreachable code +-#pragma warning( default: 4702 ) +-//warning C4800: forcing value to bool 'true' or 'false' (performance warning) +-#pragma warning( default: 4800 ) +-#endif +- +-#endif +diff --git a/extern/ttmath/ttmathint.h b/extern/ttmath/ttmathint.h +deleted file mode 100644 +index 8ad0189f93..0000000000 +--- a/extern/ttmath/ttmathint.h ++++ /dev/null +@@ -1,1917 +0,0 @@ +-/* +- * This file is a part of TTMath Bignum Library +- * and is distributed under the (new) BSD licence. +- * Author: Tomasz Sowa +- */ +- +-/* +- * Copyright (c) 2006-2011, Tomasz Sowa +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * +- * * Redistributions of source code must retain the above copyright notice, +- * this list of conditions and the following disclaimer. +- * +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * +- * * Neither the name Tomasz Sowa nor the names of contributors to this +- * project may be used to endorse or promote products derived +- * from this software without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +- * THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +- +- +-#ifndef headerfilettmathint +-#define headerfilettmathint +- +-/*! +- \file ttmathint.h +- \brief template class Int +-*/ +- +-#include "ttmathuint.h" +- +-namespace ttmath +-{ +- +- +-/*! +- \brief Int implements a big integer value with a sign +- +- value_size - how many bytes specify our value +- on 32bit platforms: value_size=1 -> 4 bytes -> 32 bits +- on 64bit platforms: value_size=1 -> 8 bytes -> 64 bits +- value_size = 1,2,3,4,5,6.... +-*/ +-template +-class Int : public UInt +-{ +-public: +- +- /*! +- this method sets the max value which this class can hold +- (all bits will be one besides the last one) +- */ +- void SetMax() +- { +- UInt::SetMax(); +- UInt::table[value_size-1] = ~ TTMATH_UINT_HIGHEST_BIT; +- } +- +- +- /*! +- this method sets the min value which this class can hold +- (all bits will be zero besides the last one which is one) +- */ +- void SetMin() +- { +- UInt::SetZero(); +- UInt::table[value_size-1] = TTMATH_UINT_HIGHEST_BIT; +- } +- +- +- /*! +- this method sets -1 as the value +- (-1 is equal the max value in an unsigned type) +- */ +- void SetSignOne() +- { +- UInt::SetMax(); +- } +- +- +- /*! +- we change the sign of the value +- +- if it isn't possible to change the sign this method returns 1 +- else return 0 and changing the sign +- */ +- uint ChangeSign() +- { +- /* +- if the value is equal that one which has been returned from SetMin +- (only the highest bit is set) that means we can't change sign +- because the value is too big (bigger about one) +- +- e.g. when value_size = 1 and value is -2147483648 we can't change it to the +- 2147483648 because the max value which can be held is 2147483647 +- +- we don't change the value and we're using this fact somewhere in some methods +- (if we look on our value without the sign we get the correct value +- eg. -2147483648 in Int<1> will be 2147483648 on the UInt<1> type) +- */ +- if( UInt::IsOnlyTheHighestBitSet() ) +- return 1; +- +- UInt temp(*this); +- UInt::SetZero(); +- UInt::Sub(temp); +- +- return 0; +- } +- +- +- +- /*! +- this method sets the sign +- +- e.g. 1 -> -1 +- -2 -> -2 +- +- from a positive value we make a negative value, +- if the value is negative we do nothing +- */ +- void SetSign() +- { +- if( IsSign() ) +- return; +- +- ChangeSign(); +- } +- +- +- +- /*! +- this method returns true if there's the sign +- +- (the highest bit will be converted to the bool) +- */ +- bool IsSign() const +- { +- return UInt::IsTheHighestBitSet(); +- } +- +- +- +- /*! +- it sets an absolute value +- +- it can return carry (1) (look on ChangeSign() for details) +- */ +- uint Abs() +- { +- if( !IsSign() ) +- return 0; +- +- return ChangeSign(); +- } +- +- +- +- +- /*! +- * +- * basic mathematic functions +- * +- */ +- +-private: +- +- uint CorrectCarryAfterAdding(bool p1_is_sign, bool p2_is_sign) +- { +- if( !p1_is_sign && !p2_is_sign ) +- { +- if( UInt::IsTheHighestBitSet() ) +- return 1; +- } +- +- if( p1_is_sign && p2_is_sign ) +- { +- if( ! UInt::IsTheHighestBitSet() ) +- return 1; +- } +- +- return 0; +- } +- +- +-public: +- +- /*! +- this method adds two value with a sign and returns a carry +- +- we're using methods from the base class because values are stored with U2 +- we must only make the carry correction +- +- this = p1(=this) + p2 +- +- when p1>=0 i p2>=0 carry is set when the highest bit of value is set +- when p1<0 i p2<0 carry is set when the highest bit of value is clear +- when p1>=0 i p2<0 carry will never be set +- when p1<0 i p2>=0 carry will never be set +- */ +- uint Add(const Int & ss2) +- { +- bool p1_is_sign = IsSign(); +- bool p2_is_sign = ss2.IsSign(); +- +- UInt::Add(ss2); +- +- return CorrectCarryAfterAdding(p1_is_sign, p2_is_sign); +- } +- +- +- /*! +- this method adds one *unsigned* word (at a specific position) +- and returns a carry (if it was) +- +- look at a description in UInt<>::AddInt(...) +- */ +- uint AddInt(uint value, uint index = 0) +- { +- bool p1_is_sign = IsSign(); +- +- UInt::AddInt(value, index); +- +- return CorrectCarryAfterAdding(p1_is_sign, false); +- } +- +- +- /*! +- this method adds two *unsigned* words to the existing value +- and these words begin on the 'index' position +- +- index should be equal or smaller than value_size-2 (index <= value_size-2) +- x1 - lower word, x2 - higher word +- +- look at a description in UInt<>::AddTwoInts(...) +- */ +- uint AddTwoInts(uint x2, uint x1, uint index) +- { +- bool p1_is_sign = IsSign(); +- +- UInt::AddTwoInts(x2, x1, index); +- +- return CorrectCarryAfterAdding(p1_is_sign, false); +- } +- +-private: +- +- uint CorrectCarryAfterSubtracting(bool p1_is_sign, bool p2_is_sign) +- { +- if( !p1_is_sign && p2_is_sign ) +- { +- if( UInt::IsTheHighestBitSet() ) +- return 1; +- } +- +- if( p1_is_sign && !p2_is_sign ) +- { +- if( ! UInt::IsTheHighestBitSet() ) +- return 1; +- } +- +- return 0; +- } +- +-public: +- +- /*! +- this method subtracts two values with a sign +- +- we don't use the previous Add because the method ChangeSign can +- sometimes return carry +- +- this = p1(=this) - p2 +- +- when p1>=0 i p2>=0 carry will never be set +- when p1<0 i p2<0 carry will never be set +- when p1>=0 i p2<0 carry is set when the highest bit of value is set +- when p1<0 i p2>=0 carry is set when the highest bit of value is clear +- */ +- uint Sub(const Int & ss2) +- { +- bool p1_is_sign = IsSign(); +- bool p2_is_sign = ss2.IsSign(); +- +- UInt::Sub(ss2); +- +- return CorrectCarryAfterSubtracting(p1_is_sign, p2_is_sign); +- } +- +- +- /*! +- this method subtracts one *unsigned* word (at a specific position) +- and returns a carry (if it was) +- */ +- uint SubInt(uint value, uint index = 0) +- { +- bool p1_is_sign = IsSign(); +- +- UInt::SubInt(value, index); +- +- return CorrectCarryAfterSubtracting(p1_is_sign, false); +- } +- +- +- /*! +- this method adds one to the value and returns carry +- */ +- uint AddOne() +- { +- bool p1_is_sign = IsSign(); +- +- UInt::AddOne(); +- +- return CorrectCarryAfterAdding(p1_is_sign, false); +- } +- +- +- /*! +- this method subtracts one from the value and returns carry +- */ +- uint SubOne() +- { +- bool p1_is_sign = IsSign(); +- +- UInt::SubOne(); +- +- return CorrectCarryAfterSubtracting(p1_is_sign, false); +- } +- +- +-private: +- +- +- uint CheckMinCarry(bool ss1_is_sign, bool ss2_is_sign) +- { +- /* +- we have to examine the sign of the result now +- but if the result is with the sign then: +- 1. if the signs were the same that means the result is too big +- (the result must be without a sign) +- 2. if the signs were different that means if the result +- is different from that one which has been returned from SetMin() +- that is carry (result too big) but if the result is equal SetMin() +- there'll be ok (and the next SetSign will has no effect because +- the value is actually negative -- look at description of that case +- in ChangeSign()) +- */ +- if( IsSign() ) +- { +- if( ss1_is_sign != ss2_is_sign ) +- { +- /* +- there can be one case where signs are different and +- the result will be equal the value from SetMin() (only the highest bit is set) +- (this situation is ok) +- */ +- if( !UInt::IsOnlyTheHighestBitSet() ) +- return 1; +- } +- else +- { +- // signs were the same +- return 1; +- } +- } +- +- return 0; +- } +- +- +-public: +- +- +- /*! +- multiplication: this = this * ss2 +- +- it can return a carry +- */ +- uint MulInt(sint ss2) +- { +- bool ss1_is_sign, ss2_is_sign; +- uint c; +- +- ss1_is_sign = IsSign(); +- +- /* +- we don't have to check the carry from Abs (values will be correct +- because next we're using the method MulInt from the base class UInt +- which is without a sign) +- */ +- Abs(); +- +- if( ss2 < 0 ) +- { +- ss2 = -ss2; +- ss2_is_sign = true; +- } +- else +- { +- ss2_is_sign = false; +- } +- +- c = UInt::MulInt((uint)ss2); +- c += CheckMinCarry(ss1_is_sign, ss2_is_sign); +- +- if( ss1_is_sign != ss2_is_sign ) +- SetSign(); +- +- return c; +- } +- +- +- +- /*! +- multiplication this = this * ss2 +- +- it returns carry if the result is too big +- (we're using the method from the base class but we have to make +- one correction in account of signs) +- */ +- uint Mul(Int ss2) +- { +- bool ss1_is_sign, ss2_is_sign; +- uint c; +- +- ss1_is_sign = IsSign(); +- ss2_is_sign = ss2.IsSign(); +- +- /* +- we don't have to check the carry from Abs (values will be correct +- because next we're using the method Mul from the base class UInt +- which is without a sign) +- */ +- Abs(); +- ss2.Abs(); +- +- c = UInt::Mul(ss2); +- c += CheckMinCarry(ss1_is_sign, ss2_is_sign); +- +- if( ss1_is_sign != ss2_is_sign ) +- SetSign(); +- +- return c; +- } +- +- +- /*! +- division this = this / ss2 +- returned values: +- 0 - ok +- 1 - division by zero +- +- for example: (result means 'this') +- 20 / 3 --> result: 6 remainder: 2 +- -20 / 3 --> result: -6 remainder: -2 +- 20 / -3 --> result: -6 remainder: 2 +- -20 / -3 --> result: 6 remainder: -2 +- +- in other words: this(old) = ss2 * this(new)(result) + remainder +- */ +- uint Div(Int ss2, Int * remainder = 0) +- { +- bool ss1_is_sign, ss2_is_sign; +- +- ss1_is_sign = IsSign(); +- ss2_is_sign = ss2.IsSign(); +- +- /* +- we don't have to test the carry from Abs as well as in Mul +- */ +- Abs(); +- ss2.Abs(); +- +- uint c = UInt::Div(ss2, remainder); +- +- if( ss1_is_sign != ss2_is_sign ) +- SetSign(); +- +- if( ss1_is_sign && remainder ) +- remainder->SetSign(); +- +- return c; +- } +- +- uint Div(const Int & ss2, Int & remainder) +- { +- return Div(ss2, &remainder); +- } +- +- +- /*! +- division this = this / ss2 (ss2 is int) +- returned values: +- 0 - ok +- 1 - division by zero +- +- for example: (result means 'this') +- 20 / 3 --> result: 6 remainder: 2 +- -20 / 3 --> result: -6 remainder: -2 +- 20 / -3 --> result: -6 remainder: 2 +- -20 / -3 --> result: 6 remainder: -2 +- +- in other words: this(old) = ss2 * this(new)(result) + remainder +- */ +- uint DivInt(sint ss2, sint * remainder = 0) +- { +- bool ss1_is_sign, ss2_is_sign; +- +- ss1_is_sign = IsSign(); +- +- /* +- we don't have to test the carry from Abs as well as in Mul +- */ +- Abs(); +- +- if( ss2 < 0 ) +- { +- ss2 = -ss2; +- ss2_is_sign = true; +- } +- else +- { +- ss2_is_sign = false; +- } +- +- uint rem; +- uint c = UInt::DivInt((uint)ss2, &rem); +- +- if( ss1_is_sign != ss2_is_sign ) +- SetSign(); +- +- if( remainder ) +- { +- if( ss1_is_sign ) +- *remainder = -sint(rem); +- else +- *remainder = sint(rem); +- } +- +- return c; +- } +- +- +- uint DivInt(sint ss2, sint & remainder) +- { +- return DivInt(ss2, &remainder); +- } +- +- +-private: +- +- +- /*! +- power this = this ^ pow +- this can be negative +- pow is >= 0 +- */ +- uint Pow2(const Int & pow) +- { +- bool was_sign = IsSign(); +- uint c = 0; +- +- if( was_sign ) +- c += Abs(); +- +- uint c_temp = UInt::Pow(pow); +- if( c_temp > 0 ) +- return c_temp; // c_temp can be: 0, 1 or 2 +- +- if( was_sign && (pow.table[0] & 1) == 1 ) +- // negative value to the power of odd number is negative +- c += ChangeSign(); +- +- return (c==0)? 0 : 1; +- } +- +- +-public: +- +- +- /*! +- power this = this ^ pow +- +- return values: +- 0 - ok +- 1 - carry +- 2 - incorrect arguments 0^0 or 0^(-something) +- */ +- uint Pow(Int pow) +- { +- if( !pow.IsSign() ) +- return Pow2(pow); +- +- if( UInt::IsZero() ) +- // if 'pow' is negative then +- // 'this' must be different from zero +- return 2; +- +- if( pow.ChangeSign() ) +- return 1; +- +- Int t(*this); +- uint c_temp = t.Pow2(pow); +- if( c_temp > 0 ) +- return c_temp; +- +- UInt::SetOne(); +- if( Div(t) ) +- return 1; +- +- return 0; +- } +- +- +- +- /*! +- * +- * convertion methods +- * +- */ +-private: +- +- +- /*! +- an auxiliary method for converting both from UInt and Int +- */ +- template +- uint FromUIntOrInt(const UInt & p, bool UInt_type) +- { +- uint min_size = (value_size < argument_size)? value_size : argument_size; +- uint i; +- +- for(i=0 ; i::table[i] = p.table[i]; +- +- +- if( value_size > argument_size ) +- { +- uint fill; +- +- if( UInt_type ) +- fill = 0; +- else +- fill = (p.table[argument_size-1] & TTMATH_UINT_HIGHEST_BIT)? +- TTMATH_UINT_MAX_VALUE : 0; +- +- // 'this' is longer than 'p' +- for( ; i::table[i] = fill; +- } +- else +- { +- uint test = (UInt::table[value_size-1] & TTMATH_UINT_HIGHEST_BIT)? +- TTMATH_UINT_MAX_VALUE : 0; +- +- if( UInt_type && test!=0 ) +- return 1; +- +- for( ; i type into this class +- +- this operation has mainly sense if the value from p +- can be held in this type +- +- it returns a carry if the value 'p' is too big +- */ +- template +- uint FromInt(const Int & p) +- { +- return FromUIntOrInt(p, false); +- } +- +- +- /*! +- this method converts the sint type into this class +- */ +- uint FromInt(sint value) +- { +- uint fill = ( value<0 ) ? TTMATH_UINT_MAX_VALUE : 0; +- +- for(uint i=1 ; i::table[i] = fill; +- +- UInt::table[0] = uint(value); +- +- // there'll never be a carry here +- return 0; +- } +- +- +- /*! +- this method converts UInt into this class +- */ +- template +- uint FromUInt(const UInt & p) +- { +- return FromUIntOrInt(p, true); +- } +- +- +- /*! +- this method converts UInt into this class +- */ +- template +- uint FromInt(const UInt & p) +- { +- return FromUIntOrInt(p, true); +- } +- +- +- /*! +- this method converts the uint type into this class +- */ +- uint FromUInt(uint value) +- { +- for(uint i=1 ; i::table[i] = 0; +- +- UInt::table[0] = value; +- +- // there can be a carry here when the size of this value is equal one word +- // and the 'value' has the highest bit set +- if( value_size==1 && (value & TTMATH_UINT_HIGHEST_BIT)!=0 ) +- return 1; +- +- return 0; +- } +- +- +- /*! +- this method converts the uint type into this class +- */ +- uint FromInt(uint value) +- { +- return FromUInt(value); +- } +- +- +- /*! +- the default assignment operator +- */ +-/* Int & operator=(const Int & p) +- { +- FromInt(p); +- +- return *this; +- } +- */ +- +- /*! +- this operator converts an Int type to this class +- +- it doesn't return a carry +- */ +-/* template +- Int & operator=(const Int & p) +- { +- FromInt(p); +- +- return *this; +- } +- */ +- +- /*! +- this method converts the sint type to this class +- */ +- Int & operator=(sint i) +- { +- FromInt(i); +- +- return *this; +- } +- +- +- /*! +- a constructor for converting the uint to this class +- */ +-/* Int(sint i) +- { +- FromInt(i); +- } +-*/ +- +- /*! +- a copy constructor +- */ +-/* Int(const Int & u) +- { +- FromInt(u); +- } +-*/ +- +- /*! +- a constructor for copying from another types +- */ +-/* template +- Int(const Int & u) +- { +- // look that 'size' we still set as 'value_size' and not as u.value_size +- FromInt(u); +- } +-*/ +- +- +- /*! +- this operator converts an UInt type to this class +- +- it doesn't return a carry +- */ +- template +- Int & operator=(const UInt & p) +- { +- FromUInt(p); +- +- return *this; +- } +- +- +- /*! +- this method converts the Uint type to this class +- */ +- Int & operator=(uint i) +- { +- FromUInt(i); +- +- return *this; +- } +- +- +- /*! +- a constructor for converting the uint to this class +- */ +-/* Int(uint i) +- { +- FromUInt(i); +- } +-*/ +- +- /*! +- a constructor for copying from another types +- */ +-/* template +- Int(const UInt & u) +- { +- // look that 'size' we still set as 'value_size' and not as u.value_size +- FromUInt(u); +- } +-*/ +- +- +-#ifdef TTMATH_PLATFORM32 +- +- +- /*! +- this method converts unsigned 64 bit int type to this class +- ***this method is created only on a 32bit platform*** +- */ +- uint FromUInt(ulint n) +- { +- uint c = UInt::FromUInt(n); +- +- if( c ) +- return 1; +- +- if( value_size == 1 ) +- return ((UInt::table[0] & TTMATH_UINT_HIGHEST_BIT) == 0) ? 0 : 1; +- +- if( value_size == 2 ) +- return ((UInt::table[1] & TTMATH_UINT_HIGHEST_BIT) == 0) ? 0 : 1; +- +- return 0; +- } +- +- +- /*! +- this method converts unsigned 64 bit int type to this class +- ***this method is created only on a 32bit platform*** +- */ +- uint FromInt(ulint n) +- { +- return FromUInt(n); +- } +- +- +- /*! +- this method converts signed 64 bit int type to this class +- ***this method is created only on a 32bit platform*** +- */ +- uint FromInt(slint n) +- { +- uint mask = (n < 0) ? TTMATH_UINT_MAX_VALUE : 0; +- +- UInt::table[0] = (uint)(ulint)n; +- +- if( value_size == 1 ) +- { +- if( uint(ulint(n) >> 32) != mask ) +- return 1; +- +- return ((UInt::table[0] & TTMATH_UINT_HIGHEST_BIT) == (mask & TTMATH_UINT_HIGHEST_BIT)) ? 0 : 1; +- } +- +- UInt::table[1] = (uint)(ulint(n) >> 32); +- +- for(uint i=2 ; i::table[i] = mask; +- +- return 0; +- } +- +- +- /*! +- this operator converts unsigned 64 bit int type to this class +- ***this operator is created only on a 32bit platform*** +- */ +- Int & operator=(ulint n) +- { +- FromUInt(n); +- +- return *this; +- } +- +- +- /*! +- a constructor for converting unsigned 64 bit int to this class +- ***this constructor is created only on a 32bit platform*** +- */ +-/* Int(ulint n) +- { +- FromUInt(n); +- } +-*/ +- +- /*! +- this operator converts signed 64 bit int type to this class +- ***this operator is created only on a 32bit platform*** +- */ +- Int & operator=(slint n) +- { +- FromInt(n); +- +- return *this; +- } +- +- +- /*! +- a constructor for converting signed 64 bit int to this class +- ***this constructor is created only on a 32bit platform*** +- */ +-/* Int(slint n) +- { +- FromInt(n); +- } +-*/ +-#endif +- +- +- +- +-#ifdef TTMATH_PLATFORM64 +- +- /*! +- this method converts 32 bit unsigned int type to this class +- ***this operator is created only on a 64bit platform*** +- */ +- uint FromUInt(unsigned int i) +- { +- return FromUInt(uint(i)); +- } +- +- +- /*! +- this method converts 32 bit unsigned int type to this class +- ***this operator is created only on a 64bit platform*** +- */ +- uint FromInt(unsigned int i) +- { +- return FromUInt(i); +- } +- +- +- /*! +- this method converts 32 bit signed int type to this class +- ***this operator is created only on a 64bit platform*** +- */ +- uint FromInt(signed int i) +- { +- return FromInt(sint(i)); +- } +- +- +- /*! +- this method converts 32 bit unsigned int type to this class +- ***this operator is created only on a 64bit platform*** +- */ +- Int & operator=(unsigned int i) +- { +- FromUInt(i); +- +- return *this; +- } +- +- +- /*! +- a constructor for converting 32 bit unsigned int to this class +- ***this constructor is created only on a 64bit platform*** +- */ +-/* Int(unsigned int i) +- { +- FromUInt(i); +- } +-*/ +- +- /*! +- this operator converts 32 bit signed int type to this class +- ***this operator is created only on a 64bit platform*** +- */ +- Int & operator=(signed int i) +- { +- FromInt(i); +- +- return *this; +- } +- +- +- /*! +- a constructor for converting 32 bit signed int to this class +- ***this constructor is created only on a 64bit platform*** +- */ +-/* Int(signed int i) +- { +- FromInt(i); +- } +-*/ +-#endif +- +- +- +- /*! +- a constructor for converting string to this class (with the base=10) +- */ +-/* Int(const char * s) +- { +- FromString(s); +- } +-*/ +- +- /*! +- a constructor for converting a string to this class (with the base=10) +- */ +-/* Int(const std::string & s) +- { +- FromString( s.c_str() ); +- } +-*/ +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- /*! +- a constructor for converting string to this class (with the base=10) +- */ +- Int(const wchar_t * s) +- { +- FromString(s); +- } +- +- +- /*! +- a constructor for converting a string to this class (with the base=10) +- */ +- Int(const std::wstring & s) +- { +- FromString( s.c_str() ); +- } +- +-#endif +- +- +- /*! +- a default constructor +- +- we don't clear table etc. +- */ +-/* Int() +- { +- } +-*/ +- +- /*! +- the destructor +- */ +-/* ~Int() +- { +- } +-*/ +- +- /*! +- this method returns the lowest value from table with a sign +- +- we must be sure when we using this method whether the value +- will hold in an sint type or not (the rest value from table must be zero or -1) +- */ +- sint ToInt() const +- { +- return sint( UInt::table[0] ); +- } +- +- +- /*! +- this method converts the value to uint type +- can return a carry if the value is too long to store it in uint type +- */ +- uint ToUInt(uint & result) const +- { +- uint c = UInt::ToUInt(result); +- +- if( value_size == 1 ) +- return (result & TTMATH_UINT_HIGHEST_BIT) == 0 ? 0 : 1; +- +- return c; +- } +- +- +- /*! +- this method converts the value to uint type +- can return a carry if the value is too long to store it in uint type +- */ +- uint ToInt(uint & result) const +- { +- return ToUInt(result); +- } +- +- +- /*! +- this method converts the value to sint type +- can return a carry if the value is too long to store it in sint type +- */ +- uint ToInt(sint & result) const +- { +- result = sint( UInt::table[0] ); +- uint mask = IsSign() ? TTMATH_UINT_MAX_VALUE : 0; +- +- if( (result & TTMATH_UINT_HIGHEST_BIT) != (mask & TTMATH_UINT_HIGHEST_BIT) ) +- return 1; +- +- for(uint i=1 ; i::table[i] != mask ) +- return 1; +- +- return 0; +- } +- +- +-#ifdef TTMATH_PLATFORM32 +- +- /*! +- this method converts the value to ulint type (64 bit unsigned integer) +- can return a carry if the value is too long to store it in ulint type +- *** this method is created only on a 32 bit platform *** +- */ +- uint ToUInt(ulint & result) const +- { +- uint c = UInt::ToUInt(result); +- +- if( value_size == 1 ) +- return (UInt::table[0] & TTMATH_UINT_HIGHEST_BIT) == 0 ? 0 : 1; +- +- if( value_size == 2 ) +- return (UInt::table[1] & TTMATH_UINT_HIGHEST_BIT) == 0 ? 0 : 1; +- +- return c; +- } +- +- +- /*! +- this method converts the value to ulint type (64 bit unsigned integer) +- can return a carry if the value is too long to store it in ulint type +- *** this method is created only on a 32 bit platform *** +- */ +- uint ToInt(ulint & result) const +- { +- return ToUInt(result); +- } +- +- +- /*! +- this method converts the value to slint type (64 bit signed integer) +- can return a carry if the value is too long to store it in slint type +- *** this method is created only on a 32 bit platform *** +- */ +- uint ToInt(slint & result) const +- { +- if( value_size == 1 ) +- { +- result = slint(sint(UInt::table[0])); +- } +- else +- { +- uint low = UInt::table[0]; +- uint high = UInt::table[1]; +- +- result = low; +- result |= (ulint(high) << TTMATH_BITS_PER_UINT); +- +- uint mask = IsSign() ? TTMATH_UINT_MAX_VALUE : 0; +- +- if( (high & TTMATH_UINT_HIGHEST_BIT) != (mask & TTMATH_UINT_HIGHEST_BIT) ) +- return 1; +- +- for(uint i=2 ; i::table[i] != mask ) +- return 1; +- } +- +- return 0; +- } +- +-#endif +- +- +- +-#ifdef TTMATH_PLATFORM64 +- +- /*! +- this method converts the value to a 32 bit unsigned integer +- can return a carry if the value is too long to store it in this type +- *** this method is created only on a 64 bit platform *** +- */ +- uint ToUInt(unsigned int & result) const +- { +- uint c = UInt::ToUInt(result); +- +- if( c || IsSign() ) +- return 1; +- +- return 0; +- } +- +- +- /*! +- this method converts the value to a 32 bit unsigned integer +- can return a carry if the value is too long to store it in this type +- *** this method is created only on a 64 bit platform *** +- */ +- uint ToInt(unsigned int & result) const +- { +- return ToUInt(result); +- } +- +- +- /*! +- this method converts the value to a 32 bit signed integer +- can return a carry if the value is too long to store it in this type +- *** this method is created only on a 64 bit platform *** +- */ +- uint ToInt(int & result) const +- { +- uint first = UInt::table[0]; +- +- result = int(first); +- uint mask = IsSign() ? TTMATH_UINT_MAX_VALUE : 0; +- +- if( (first >> 31) != (mask >> 31) ) +- return 1; +- +- for(uint i=1 ; i::table[i] != mask ) +- return 1; +- +- return 0; +- } +- +-#endif +- +- +- +- /*! +- an auxiliary method for converting to a string +- */ +- template +- void ToStringBase(string_type & result, uint b = 10) const +- { +- if( IsSign() ) +- { +- Int temp(*this); +- temp.Abs(); +- temp.UInt::ToStringBase(result, b, true); +- } +- else +- { +- UInt::ToStringBase(result, b, false); +- } +- } +- +- /*! +- this method converts the value to a string with a base equal 'b' +- */ +- void ToString(std::string & result, uint b = 10) const +- { +- return ToStringBase(result, b); +- } +- +- +- /*! +- this method converts the value to a string with a base equal 'b' +- */ +- std::string ToString(uint b = 10) const +- { +- std::string result; +- ToStringBase(result, b); +- +- return result; +- } +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- /*! +- this method converts the value to a string with a base equal 'b' +- */ +- void ToString(std::wstring & result, uint b = 10) const +- { +- return ToStringBase(result, b); +- } +- +- +- /*! +- this method converts the value to a string with a base equal 'b' +- */ +- std::wstring ToWString(uint b = 10) const +- { +- std::wstring result; +- ToStringBase(result, b); +- +- return result; +- } +- +-#endif +- +- +- +-private: +- +- /*! +- an auxiliary method for converting from a string +- */ +- template +- uint FromStringBase(const char_type * s, uint b = 10, const char_type ** after_source = 0, bool * value_read = 0) +- { +- bool is_sign = false; +- +- Misc::SkipWhiteCharacters(s); +- +- if( *s == '-' ) +- { +- is_sign = true; +- Misc::SkipWhiteCharacters(++s); +- } +- else +- if( *s == '+' ) +- { +- Misc::SkipWhiteCharacters(++s); +- } +- +- if( UInt::FromString(s,b,after_source,value_read) ) +- return 1; +- +- if( is_sign ) +- { +- Int mmin; +- +- mmin.SetMin(); +- +- /* +- the reference to mmin will be automatically converted to the reference +- to UInt type +- (this value can be equal mmin -- look at a description in ChangeSign()) +- */ +- if( UInt::operator>( mmin ) ) +- return 1; +- +- /* +- if the value is equal mmin the method ChangeSign() does nothing (only returns 1 but we ignore it) +- */ +- ChangeSign(); +- } +- else +- { +- Int mmax; +- +- mmax.SetMax(); +- +- if( UInt::operator>( mmax ) ) +- return 1; +- } +- +- return 0; +- } +- +- +-public: +- +- /*! +- this method converts a string into its value +- it returns carry=1 if the value will be too big or an incorrect base 'b' is given +- +- string is ended with a non-digit value, for example: +- "-12" will be translated to -12 +- as well as: +- "- 12foo" will be translated to -12 too +- +- existing first white characters will be ommited +- (between '-' and a first digit can be white characters too) +- +- after_source (if exists) is pointing at the end of the parsed string +- +- value_read (if exists) tells whether something has actually been read (at least one digit) +- */ +- uint FromString(const char * s, uint b = 10, const char ** after_source = 0, bool * value_read = 0) +- { +- return FromStringBase(s, b, after_source, value_read); +- } +- +- +- /*! +- this method converts a string into its value +- */ +- uint FromString(const wchar_t * s, uint b = 10, const wchar_t ** after_source = 0, bool * value_read = 0) +- { +- return FromStringBase(s, b, after_source, value_read); +- } +- +- +- /*! +- this method converts a string into its value +- it returns carry=1 if the value will be too big or an incorrect base 'b' is given +- */ +- uint FromString(const std::string & s, uint b = 10) +- { +- return FromString( s.c_str(), b ); +- } +- +- +- /*! +- this operator converts a string into its value (with base = 10) +- */ +- Int & operator=(const char * s) +- { +- FromString(s); +- +- return *this; +- } +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- +- /*! +- this method converts a string into its value +- it returns carry=1 if the value will be too big or an incorrect base 'b' is given +- */ +- uint FromString(const std::wstring & s, uint b = 10) +- { +- return FromString( s.c_str(), b ); +- } +- +- +- /*! +- this operator converts a string into its value (with base = 10) +- */ +- Int & operator=(const wchar_t * s) +- { +- FromString(s); +- +- return *this; +- } +- +- +- /*! +- this operator converts a string into its value (with base = 10) +- */ +- Int & operator=(const std::wstring & s) +- { +- FromString( s.c_str() ); +- +- return *this; +- } +- +-#endif +- +- +- /*! +- this operator converts a string into its value (with base = 10) +- */ +- Int & operator=(const std::string & s) +- { +- FromString( s.c_str() ); +- +- return *this; +- } +- +- +- +- /*! +- * +- * methods for comparing +- * +- * +- */ +- +- bool operator==(const Int & l) const +- { +- return UInt::operator==(l); +- } +- +- bool operator!=(const Int & l) const +- { +- return UInt::operator!=(l); +- } +- +- bool operator<(const Int & l) const +- { +- sint i=value_size-1; +- +- sint a1 = sint(UInt::table[i]); +- sint a2 = sint(l.table[i]); +- +- if( a1 != a2 ) +- return a1 < a2; +- +- +- for(--i ; i>=0 ; --i) +- { +- if( UInt::table[i] != l.table[i] ) +- // comparison as unsigned int +- return UInt::table[i] < l.table[i]; +- } +- +- // they're equal +- return false; +- } +- +- +- bool operator>(const Int & l) const +- { +- sint i=value_size-1; +- +- sint a1 = sint(UInt::table[i]); +- sint a2 = sint(l.table[i]); +- +- if( a1 != a2 ) +- return a1 > a2; +- +- +- for(--i ; i>=0 ; --i) +- { +- if( UInt::table[i] != l.table[i] ) +- // comparison as unsigned int +- return UInt::table[i] > l.table[i]; +- } +- +- // they're equal +- return false; +- } +- +- +- bool operator<=(const Int & l) const +- { +- sint i=value_size-1; +- +- sint a1 = sint(UInt::table[i]); +- sint a2 = sint(l.table[i]); +- +- if( a1 != a2 ) +- return a1 < a2; +- +- +- for(--i ; i>=0 ; --i) +- { +- if( UInt::table[i] != l.table[i] ) +- // comparison as unsigned int +- return UInt::table[i] < l.table[i]; +- } +- +- // they're equal +- return true; +- } +- +- +- bool operator>=(const Int & l) const +- { +- sint i=value_size-1; +- +- sint a1 = sint(UInt::table[i]); +- sint a2 = sint(l.table[i]); +- +- if( a1 != a2 ) +- return a1 > a2; +- +- +- for(--i ; i>=0 ; --i) +- { +- if( UInt::table[i] != l.table[i] ) +- // comparison as unsigned int +- return UInt::table[i] > l.table[i]; +- } +- +- // they're equal +- return true; +- } +- +- +- +- /*! +- * +- * standard mathematical operators +- * +- */ +- +- +- /*! +- an operator for changing the sign +- +- it's not changing 'this' but the changed value will be returned +- */ +- Int operator-() const +- { +- Int temp(*this); +- +- temp.ChangeSign(); +- +- return temp; +- } +- +- +- Int operator-(const Int & p2) const +- { +- Int temp(*this); +- +- temp.Sub(p2); +- +- return temp; +- } +- +- +- Int & operator-=(const Int & p2) +- { +- Sub(p2); +- +- return *this; +- } +- +- +- Int operator+(const Int & p2) const +- { +- Int temp(*this); +- +- temp.Add(p2); +- +- return temp; +- } +- +- +- Int & operator+=(const Int & p2) +- { +- Add(p2); +- +- return *this; +- } +- +- +- Int operator*(const Int & p2) const +- { +- Int temp(*this); +- +- temp.Mul(p2); +- +- return temp; +- } +- +- +- Int & operator*=(const Int & p2) +- { +- Mul(p2); +- +- return *this; +- } +- +- +- Int operator/(const Int & p2) const +- { +- Int temp(*this); +- +- temp.Div(p2); +- +- return temp; +- } +- +- +- Int & operator/=(const Int & p2) +- { +- Div(p2); +- +- return *this; +- } +- +- +- Int operator%(const Int & p2) const +- { +- Int temp(*this); +- Int remainder; +- +- temp.Div(p2, remainder); +- +- return remainder; +- } +- +- +- Int & operator%=(const Int & p2) +- { +- Int remainder; +- +- Div(p2, remainder); +- operator=(remainder); +- +- return *this; +- } +- +- +- /*! +- Prefix operator e.g. ++variable +- */ +- UInt & operator++() +- { +- AddOne(); +- +- return *this; +- } +- +- +- /*! +- Postfix operator e.g. variable++ +- */ +- UInt operator++(int) +- { +- UInt temp( *this ); +- +- AddOne(); +- +- return temp; +- } +- +- +- UInt & operator--() +- { +- SubOne(); +- +- return *this; +- } +- +- +- UInt operator--(int) +- { +- UInt temp( *this ); +- +- SubOne(); +- +- return temp; +- } +- +- +- +- /*! +- * +- * input/output operators for standard streams +- * +- */ +- +-private: +- +- /*! +- an auxiliary method for outputing to standard streams +- */ +- template +- static ostream_type & OutputToStream(ostream_type & s, const Int & l) +- { +- string_type ss; +- +- l.ToString(ss); +- s << ss; +- +- return s; +- } +- +- +- +-public: +- +- +- /*! +- output to standard streams +- */ +- friend std::ostream & operator<<(std::ostream & s, const Int & l) +- { +- return OutputToStream(s, l); +- } +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- /*! +- output to standard streams +- */ +- friend std::wostream & operator<<(std::wostream & s, const Int & l) +- { +- return OutputToStream(s, l); +- } +- +-#endif +- +- +- +-private: +- +- /*! +- an auxiliary method for converting from a string +- */ +- template +- static istream_type & InputFromStream(istream_type & s, Int & l) +- { +- string_type ss; +- +- // char or wchar_t for operator>> +- char_type z; +- +- // operator>> omits white characters if they're set for ommiting +- s >> z; +- +- if( z=='-' || z=='+' ) +- { +- ss += z; +- s >> z; // we're reading a next character (white characters can be ommited) +- } +- +- // we're reading only digits (base=10) +- while( s.good() && Misc::CharToDigit(z, 10)>=0 ) +- { +- ss += z; +- z = static_cast(s.get()); +- } +- +- // we're leaving the last readed character +- // (it's not belonging to the value) +- s.unget(); +- +- l.FromString(ss); +- +- return s; +- } +- +- +-public: +- +- /*! +- input from standard streams +- */ +- friend std::istream & operator>>(std::istream & s, Int & l) +- { +- return InputFromStream(s, l); +- } +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- /*! +- input from standard streams +- */ +- friend std::wistream & operator>>(std::wistream & s, Int & l) +- { +- return InputFromStream(s, l); +- } +-#endif +- +- +-}; +- +-} // namespace +- +-#endif +diff --git a/extern/ttmath/ttmathmisc.h b/extern/ttmath/ttmathmisc.h +deleted file mode 100644 +index 330a43a468..0000000000 +--- a/extern/ttmath/ttmathmisc.h ++++ /dev/null +@@ -1,250 +0,0 @@ +-/* +- * This file is a part of TTMath Bignum Library +- * and is distributed under the (new) BSD licence. +- * Author: Tomasz Sowa +- */ +- +-/* +- * Copyright (c) 2006-2010, Tomasz Sowa +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * +- * * Redistributions of source code must retain the above copyright notice, +- * this list of conditions and the following disclaimer. +- * +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * +- * * Neither the name Tomasz Sowa nor the names of contributors to this +- * project may be used to endorse or promote products derived +- * from this software without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +- * THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +-#ifndef headerfilettmathmisc +-#define headerfilettmathmisc +- +- +-/*! +- \file ttmathmisc.h +- \brief some helpful functions +-*/ +- +- +-#include +- +- +-namespace ttmath +-{ +- +-/*! +- some helpful functions +-*/ +-class Misc +-{ +-public: +- +- +-/* +- * +- * AssignString(result, str) +- * result = str +- * +- */ +- +-/*! +- result = str +-*/ +-static void AssignString(std::string & result, const char * str) +-{ +- result = str; +-} +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +-/*! +- result = str +-*/ +-static void AssignString(std::wstring & result, const char * str) +-{ +- result.clear(); +- +- for( ; *str ; ++str ) +- result += *str; +-} +- +- +-/*! +- result = str +-*/ +-static void AssignString(std::wstring & result, const std::string & str) +-{ +- return AssignString(result, str.c_str()); +-} +- +- +-/*! +- result = str +-*/ +-static void AssignString(std::string & result, const wchar_t * str) +-{ +- result.clear(); +- +- for( ; *str ; ++str ) +- result += static_cast(*str); +-} +- +- +-/*! +- result = str +-*/ +-static void AssignString(std::string & result, const std::wstring & str) +-{ +- return AssignString(result, str.c_str()); +-} +- +-#endif +- +- +-/* +- * +- * AddString(result, str) +- * result += str +- * +- */ +- +- +-/*! +- result += str +-*/ +-static void AddString(std::string & result, const char * str) +-{ +- result += str; +-} +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +-/*! +- result += str +-*/ +-static void AddString(std::wstring & result, const char * str) +-{ +- for( ; *str ; ++str ) +- result += *str; +-} +- +-#endif +- +- +-/* +- this method omits any white characters from the string +- char_type is char or wchar_t +-*/ +-template +-static void SkipWhiteCharacters(const char_type * & c) +-{ +- // 13 is at the end in a DOS text file (\r\n) +- while( (*c==' ' ) || (*c=='\t') || (*c==13 ) || (*c=='\n') ) +- ++c; +-} +- +- +- +- +-/*! +- this static method converts one character into its value +- +- for example: +- 1 -> 1 +- 8 -> 8 +- A -> 10 +- f -> 15 +- +- this method don't check whether c is correct or not +-*/ +-static uint CharToDigit(uint c) +-{ +- if(c>='0' && c<='9') +- return c-'0'; +- +- if(c>='a' && c<='z') +- return c-'a'+10; +- +-return c-'A'+10; +-} +- +- +-/*! +- this method changes a character 'c' into its value +- (if there can't be a correct value it returns -1) +- +- for example: +- c=2, base=10 -> function returns 2 +- c=A, base=10 -> function returns -1 +- c=A, base=16 -> function returns 10 +-*/ +-static sint CharToDigit(uint c, uint base) +-{ +- if( c>='0' && c<='9' ) +- c=c-'0'; +- else +- if( c>='a' && c<='z' ) +- c=c-'a'+10; +- else +- if( c>='A' && c<='Z' ) +- c=c-'A'+10; +- else +- return -1; +- +- +- if( c >= base ) +- return -1; +- +- +-return sint(c); +-} +- +- +- +-/*! +- this method converts a digit into a char +- digit should be from <0,F> +- (we don't have to get a base) +- +- for example: +- 1 -> 1 +- 8 -> 8 +- 10 -> A +- 15 -> F +-*/ +-static uint DigitToChar(uint digit) +-{ +- if( digit < 10 ) +- return digit + '0'; +- +-return digit - 10 + 'A'; +-} +- +- +-}; // struct Misc +- +-} +- +- +-#endif +diff --git a/extern/ttmath/ttmathobjects.h b/extern/ttmath/ttmathobjects.h +deleted file mode 100644 +index c35026bbd0..0000000000 +--- a/extern/ttmath/ttmathobjects.h ++++ /dev/null +@@ -1,809 +0,0 @@ +-/* +- * This file is a part of TTMath Mathematical Library +- * and is distributed under the (new) BSD licence. +- * Author: Tomasz Sowa +- */ +- +-/* +- * Copyright (c) 2006-2010, Tomasz Sowa +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * +- * * Redistributions of source code must retain the above copyright notice, +- * this list of conditions and the following disclaimer. +- * +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * +- * * Neither the name Tomasz Sowa nor the names of contributors to this +- * project may be used to endorse or promote products derived +- * from this software without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +- * THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +- +-#ifndef headerfilettmathobject +-#define headerfilettmathobject +- +-/*! +- \file ttmathobjects.h +- \brief Mathematic functions. +-*/ +- +-#include +-#include +-#include +-#include +- +-#include "ttmathtypes.h" +-#include "ttmathmisc.h" +- +- +-namespace ttmath +-{ +- +-/*! +- objects of this class are used with the mathematical parser +- they hold variables or functions defined by a user +- +- each object has its own table in which we're keeping variables or functions +-*/ +-class Objects +-{ +-public: +- +- +- /*! +- one item (variable or function) +- 'items' will be on the table +- */ +- struct Item +- { +- // name of a variable of a function +- // internally we store variables and funcions as std::string (not std::wstring even when wide characters are used) +- std::string value; +- +- // number of parameters required by the function +- // (if there's a variable this 'param' is ignored) +- int param; +- +- Item() {} +- Item(const std::string & v, int p) : value(v), param(p) {} +- }; +- +- // 'Table' is the type of our table +- typedef std::map Table; +- typedef Table::iterator Iterator; +- typedef Table::const_iterator CIterator; +- +- +- +- /*! +- this method returns true if a character 'c' is a character +- which can be in a name +- +- if 'can_be_digit' is true that means when the 'c' is a digit this +- method returns true otherwise it returns false +- */ +- static bool CorrectCharacter(int c, bool can_be_digit) +- { +- if( (c>='a' && c<='z') || (c>='A' && c<='Z') ) +- return true; +- +- if( can_be_digit && ((c>='0' && c<='9') || c=='_') ) +- return true; +- +- return false; +- } +- +- +- /*! +- this method returns true if the name can be as a name of an object +- */ +- template +- static bool IsNameCorrect(const string_type & name) +- { +- if( name.empty() ) +- return false; +- +- if( !CorrectCharacter(name[0], false) ) +- return false; +- +- typename string_type::const_iterator i = name.begin(); +- +- for(++i ; i!=name.end() ; ++i) +- if( !CorrectCharacter(*i, true) ) +- return false; +- +- return true; +- } +- +- +- /*! +- this method returns true if such an object is defined (name exists) +- */ +- bool IsDefined(const std::string & name) +- { +- Iterator i = table.find(name); +- +- if( i != table.end() ) +- // we have this object in our table +- return true; +- +- return false; +- } +- +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- /*! +- this method returns true if such an object is defined (name exists) +- */ +- bool IsDefined(const std::wstring & name) +- { +- // we should check whether the name (in wide characters) are correct +- // before calling AssignString() function +- if( !IsNameCorrect(name) ) +- return false; +- +- Misc::AssignString(str_tmp1, name); +- +- return IsDefined(str_tmp1); +- } +- +-#endif +- +- +- /*! +- this method adds one object (variable of function) into the table +- */ +- ErrorCode Add(const std::string & name, const std::string & value, int param = 0) +- { +- if( !IsNameCorrect(name) ) +- return err_incorrect_name; +- +- Iterator i = table.find(name); +- +- if( i != table.end() ) +- // we have this object in our table +- return err_object_exists; +- +- table.insert( std::make_pair(name, Item(value, param)) ); +- +- return err_ok; +- } +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- /*! +- this method adds one object (variable of function) into the table +- */ +- ErrorCode Add(const std::wstring & name, const std::wstring & value, int param = 0) +- { +- // we should check whether the name (in wide characters) are correct +- // before calling AssignString() function +- if( !IsNameCorrect(name) ) +- return err_incorrect_name; +- +- Misc::AssignString(str_tmp1, name); +- Misc::AssignString(str_tmp2, value); +- +- return Add(str_tmp1, str_tmp2, param); +- } +- +-#endif +- +- +- /*! +- this method returns 'true' if the table is empty +- */ +- bool Empty() const +- { +- return table.empty(); +- } +- +- +- /*! +- this method clears the table +- */ +- void Clear() +- { +- return table.clear(); +- } +- +- +- /*! +- this method returns 'const_iterator' on the first item on the table +- */ +- CIterator Begin() const +- { +- return table.begin(); +- } +- +- +- /*! +- this method returns 'const_iterator' pointing at the space after last item +- (returns table.end()) +- */ +- CIterator End() const +- { +- return table.end(); +- } +- +- +- /*! +- this method changes the value and the number of parameters for a specific object +- */ +- ErrorCode EditValue(const std::string & name, const std::string & value, int param = 0) +- { +- if( !IsNameCorrect(name) ) +- return err_incorrect_name; +- +- Iterator i = table.find(name); +- +- if( i == table.end() ) +- return err_unknown_object; +- +- i->second.value = value; +- i->second.param = param; +- +- return err_ok; +- } +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- +- /*! +- this method changes the value and the number of parameters for a specific object +- */ +- ErrorCode EditValue(const std::wstring & name, const std::wstring & value, int param = 0) +- { +- // we should check whether the name (in wide characters) are correct +- // before calling AssignString() function +- if( !IsNameCorrect(name) ) +- return err_incorrect_name; +- +- Misc::AssignString(str_tmp1, name); +- Misc::AssignString(str_tmp2, value); +- +- return EditValue(str_tmp1, str_tmp2, param); +- } +- +-#endif +- +- +- /*! +- this method changes the name of a specific object +- */ +- ErrorCode EditName(const std::string & old_name, const std::string & new_name) +- { +- if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) ) +- return err_incorrect_name; +- +- Iterator old_i = table.find(old_name); +- if( old_i == table.end() ) +- return err_unknown_object; +- +- if( old_name == new_name ) +- // the new name is the same as the old one +- // we treat it as a normal situation +- return err_ok; +- +- ErrorCode err = Add(new_name, old_i->second.value, old_i->second.param); +- +- if( err == err_ok ) +- { +- old_i = table.find(old_name); +- TTMATH_ASSERT( old_i != table.end() ) +- +- table.erase(old_i); +- } +- +- return err; +- } +- +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- +- /*! +- this method changes the name of a specific object +- */ +- ErrorCode EditName(const std::wstring & old_name, const std::wstring & new_name) +- { +- // we should check whether the name (in wide characters) are correct +- // before calling AssignString() function +- if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) ) +- return err_incorrect_name; +- +- Misc::AssignString(str_tmp1, old_name); +- Misc::AssignString(str_tmp2, new_name); +- +- return EditName(str_tmp1, str_tmp2); +- } +- +-#endif +- +- +- /*! +- this method deletes an object +- */ +- ErrorCode Delete(const std::string & name) +- { +- if( !IsNameCorrect(name) ) +- return err_incorrect_name; +- +- Iterator i = table.find(name); +- +- if( i == table.end() ) +- return err_unknown_object; +- +- table.erase( i ); +- +- return err_ok; +- } +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- +- /*! +- this method deletes an object +- */ +- ErrorCode Delete(const std::wstring & name) +- { +- // we should check whether the name (in wide characters) are correct +- // before calling AssignString() function +- if( !IsNameCorrect(name) ) +- return err_incorrect_name; +- +- Misc::AssignString(str_tmp1, name); +- +- return Delete(str_tmp1); +- } +- +-#endif +- +- +- /*! +- this method gets the value of a specific object +- */ +- ErrorCode GetValue(const std::string & name, std::string & value) const +- { +- if( !IsNameCorrect(name) ) +- return err_incorrect_name; +- +- CIterator i = table.find(name); +- +- if( i == table.end() ) +- { +- value.clear(); +- return err_unknown_object; +- } +- +- value = i->second.value; +- +- return err_ok; +- } +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- /*! +- this method gets the value of a specific object +- */ +- ErrorCode GetValue(const std::wstring & name, std::wstring & value) +- { +- // we should check whether the name (in wide characters) are correct +- // before calling AssignString() function +- if( !IsNameCorrect(name) ) +- return err_incorrect_name; +- +- Misc::AssignString(str_tmp1, name); +- ErrorCode err = GetValue(str_tmp1, str_tmp2); +- Misc::AssignString(value, str_tmp2); +- +- return err; +- } +- +-#endif +- +- +- /*! +- this method gets the value of a specific object +- (this version is used for not copying the whole string) +- */ +- ErrorCode GetValue(const std::string & name, const char ** value) const +- { +- if( !IsNameCorrect(name) ) +- return err_incorrect_name; +- +- CIterator i = table.find(name); +- +- if( i == table.end() ) +- { +- *value = 0; +- return err_unknown_object; +- } +- +- *value = i->second.value.c_str(); +- +- return err_ok; +- } +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- /*! +- this method gets the value of a specific object +- (this version is used for not copying the whole string) +- */ +- ErrorCode GetValue(const std::wstring & name, const char ** value) +- { +- // we should check whether the name (in wide characters) are correct +- // before calling AssignString() function +- if( !IsNameCorrect(name) ) +- return err_incorrect_name; +- +- Misc::AssignString(str_tmp1, name); +- +- return GetValue(str_tmp1, value); +- } +- +-#endif +- +- +- /*! +- this method gets the value and the number of parameters +- of a specific object +- */ +- ErrorCode GetValueAndParam(const std::string & name, std::string & value, int * param) const +- { +- if( !IsNameCorrect(name) ) +- return err_incorrect_name; +- +- CIterator i = table.find(name); +- +- if( i == table.end() ) +- { +- value.empty(); +- *param = 0; +- return err_unknown_object; +- } +- +- value = i->second.value; +- *param = i->second.param; +- +- return err_ok; +- } +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- /*! +- this method gets the value and the number of parameters +- of a specific object +- */ +- ErrorCode GetValueAndParam(const std::wstring & name, std::wstring & value, int * param) +- { +- // we should check whether the name (in wide characters) are correct +- // before calling AssignString() function +- if( !IsNameCorrect(name) ) +- return err_incorrect_name; +- +- Misc::AssignString(str_tmp1, name); +- ErrorCode err = GetValueAndParam(str_tmp1, str_tmp2, param); +- Misc::AssignString(value, str_tmp2); +- +- return err; +- } +- +-#endif +- +- +- /*! +- this method sets the value and the number of parameters +- of a specific object +- (this version is used for not copying the whole string) +- */ +- ErrorCode GetValueAndParam(const std::string & name, const char ** value, int * param) const +- { +- if( !IsNameCorrect(name) ) +- return err_incorrect_name; +- +- CIterator i = table.find(name); +- +- if( i == table.end() ) +- { +- *value = 0; +- *param = 0; +- return err_unknown_object; +- } +- +- *value = i->second.value.c_str(); +- *param = i->second.param; +- +- return err_ok; +- } +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- +- /*! +- this method sets the value and the number of parameters +- of a specific object +- (this version is used for not copying the whole string +- but in fact we make one copying during AssignString()) +- */ +- ErrorCode GetValueAndParam(const std::wstring & name, const char ** value, int * param) +- { +- // we should check whether the name (in wide characters) are correct +- // before calling AssignString() function +- if( !IsNameCorrect(name) ) +- return err_incorrect_name; +- +- Misc::AssignString(str_tmp1, name); +- +- return GetValueAndParam(str_tmp1, value, param); +- } +- +- +-#endif +- +- +- /*! +- this method returns a pointer into the table +- */ +- Table * GetTable() +- { +- return &table; +- } +- +- +-private: +- +- Table table; +- std::string str_tmp1, str_tmp2; +- +-}; // end of class Objects +- +- +- +- +- +- +- +-/*! +- objects of the class History are used to keep values in functions +- which take a lot of time during calculating, for instance in the +- function Factorial(x) +- +- it means that when we're calculating e.g. Factorial(1000) and the +- Factorial finds that we have calculated it before, the value (result) +- is taken from the history +-*/ +-template +-class History +-{ +- /*! +- one item in the History's object holds a key, a value for the key +- and a corresponding error code +- */ +- struct Item +- { +- ValueType key, value; +- ErrorCode err; +- }; +- +- +- /*! +- we use std::list for simply deleting the first item +- but because we're searching through the whole container +- (in the method Get) the container should not be too big +- (linear time of searching) +- */ +- typedef std::list buffer_type; +- buffer_type buffer; +- typename buffer_type::size_type buffer_max_size; +- +-public: +- +- /*! +- default constructor +- default max size of the History's container is 15 items +- */ +- History() +- { +- buffer_max_size = 15; +- } +- +- +- /*! +- a constructor which takes another value of the max size +- of the History's container +- */ +- History(typename buffer_type::size_type new_size) +- { +- buffer_max_size = new_size; +- } +- +- +- /*! +- this method adds one item into the History +- if the size of the container is greater than buffer_max_size +- the first item will be removed +- */ +- void Add(const ValueType & key, const ValueType & value, ErrorCode err) +- { +- Item item; +- item.key = key; +- item.value = value; +- item.err = err; +- +- buffer.insert( buffer.end(), item ); +- +- if( buffer.size() > buffer_max_size ) +- buffer.erase(buffer.begin()); +- } +- +- +- /*! +- this method checks whether we have an item which has the key equal 'key' +- +- if there's such item the method sets the 'value' and the 'err' +- and returns true otherwise it returns false and 'value' and 'err' +- remain unchanged +- */ +- bool Get(const ValueType & key, ValueType & value, ErrorCode & err) +- { +- typename buffer_type::iterator i = buffer.begin(); +- +- for( ; i != buffer.end() ; ++i ) +- { +- if( i->key == key ) +- { +- value = i->value; +- err = i->err; +- return true; +- } +- } +- +- return false; +- } +- +- +- /*! +- this methods deletes an item +- +- we assume that there is only one item with the 'key' +- (this methods removes the first one) +- */ +- bool Remove(const ValueType & key) +- { +- typename buffer_type::iterator i = buffer.begin(); +- +- for( ; i != buffer.end() ; ++i ) +- { +- if( i->key == key ) +- { +- buffer.erase(i); +- return true; +- } +- } +- +- return false; +- } +- +- +-}; // end of class History +- +- +- +-/*! +- this is an auxiliary class used when calculating Gamma() or Factorial() +- +- in multithreaded environment you can provide an object of this class to +- the Gamma() or Factorial() function, e.g; +- typedef Big<1, 3> MyBig; +- MyBig x = 123456; +- CGamma cgamma; +- std::cout << Gamma(x, cgamma); +- each thread should have its own CGamma<> object +- +- in a single-thread environment a CGamma<> object is a static variable +- in a second version of Gamma() and you don't have to explicitly use it, e.g. +- typedef Big<1, 3> MyBig; +- MyBig x = 123456; +- std::cout << Gamma(x); +-*/ +-template +-struct CGamma +-{ +- /*! +- this table holds factorials +- 1 +- 1 +- 2 +- 6 +- 24 +- 120 +- 720 +- ....... +- */ +- std::vector fact; +- +- +- /*! +- this table holds Bernoulli numbers +- 1 +- -0.5 +- 0.166666666666666666666666667 +- 0 +- -0.0333333333333333333333333333 +- 0 +- 0.0238095238095238095238095238 +- 0 +- -0.0333333333333333333333333333 +- 0 +- 0.075757575757575757575757576 +- ..... +- */ +- std::vector bern; +- +- +- /*! +- here we store some calculated values +- (this is for speeding up, if the next argument of Gamma() or Factorial() +- is in the 'history' then the result we are not calculating but simply +- return from the 'history' object) +- */ +- History history; +- +- +- /*! +- this method prepares some coefficients: factorials and Bernoulli numbers +- stored in 'fact' and 'bern' objects +- +- how many values should be depends on the size of the mantissa - if +- the mantissa is larger then we must calculate more values +- for a mantissa which consists of 256 bits (8 words on a 32bit platform) +- we have to calculate about 30 values (the size of fact and bern will be 30), +- and for a 2048 bits mantissa we have to calculate 306 coefficients +- +- you don't have to call this method, these coefficients will be automatically calculated +- when they are needed +- +- you must note that calculating these coefficients is a little time-consuming operation, +- (especially when the mantissa is large) and first call to Gamma() or Factorial() +- can take more time than next calls, and in the end this is the point when InitAll() +- comes in handy: you can call this method somewhere at the beginning of your program +- */ +- void InitAll(); +- // definition is in ttmath.h +-}; +- +- +- +- +-} // namespace +- +-#endif +diff --git a/extern/ttmath/ttmaththreads.h b/extern/ttmath/ttmaththreads.h +deleted file mode 100644 +index 586227f2fc..0000000000 +--- a/extern/ttmath/ttmaththreads.h ++++ /dev/null +@@ -1,250 +0,0 @@ +-/* +- * This file is a part of TTMath Bignum Library +- * and is distributed under the (new) BSD licence. +- * Author: Tomasz Sowa +- */ +- +-/* +- * Copyright (c) 2006-2009, Tomasz Sowa +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * +- * * Redistributions of source code must retain the above copyright notice, +- * this list of conditions and the following disclaimer. +- * +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * +- * * Neither the name Tomasz Sowa nor the names of contributors to this +- * project may be used to endorse or promote products derived +- * from this software without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +- * THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +- +- +-#ifndef headerfilettmaththreads +-#define headerfilettmaththreads +- +-#include "ttmathtypes.h" +- +-#ifdef TTMATH_WIN32_THREADS +-#include +-#include +-#endif +- +-#ifdef TTMATH_POSIX_THREADS +-#include +-#endif +- +- +- +-/*! +- \file ttmaththreads.h +- \brief Some objects used in multithreads environment +-*/ +- +- +-/* +- this is a simple skeleton of a program in multithreads environment: +- +- #define TTMATH_MULTITHREADS +- #include +- +- TTMATH_MULTITHREADS_HELPER +- +- int main() +- { +- [...] +- } +- +- make sure that macro TTMATH_MULTITHREADS is defined and (somewhere in *.cpp file) +- use TTMATH_MULTITHREADS_HELPER macro (outside of any classes/functions/namespaces scope) +-*/ +- +- +-namespace ttmath +-{ +- +- +-#ifdef TTMATH_WIN32_THREADS +- +- /* +- we use win32 threads +- */ +- +- +- /*! +- in multithreads environment you should use TTMATH_MULTITHREADS_HELPER macro +- somewhere in *.cpp file +- +- (at the moment in win32 this macro does nothing) +- */ +- #define TTMATH_MULTITHREADS_HELPER +- +- +- /*! +- objects of this class are used to synchronize +- */ +- class ThreadLock +- { +- HANDLE mutex_handle; +- +- +- void CreateName(char * buffer) const +- { +- #ifdef _MSC_VER +- #pragma warning (disable : 4996) +- // warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. +- #endif +- +- sprintf(buffer, "TTMATH_LOCK_%ul", (unsigned long)GetCurrentProcessId()); +- +- #ifdef _MSC_VER +- #pragma warning (default : 4996) +- #endif +- } +- +- +- public: +- +- bool Lock() +- { +- char buffer[50]; +- +- CreateName(buffer); +- mutex_handle = CreateMutexA(0, false, buffer); +- +- if( mutex_handle == 0 ) +- return false; +- +- WaitForSingleObject(mutex_handle, INFINITE); +- +- return true; +- } +- +- +- ThreadLock() +- { +- mutex_handle = 0; +- } +- +- +- ~ThreadLock() +- { +- if( mutex_handle != 0 ) +- { +- ReleaseMutex(mutex_handle); +- CloseHandle(mutex_handle); +- } +- } +- }; +- +-#endif // #ifdef TTMATH_WIN32_THREADS +- +- +- +- +- +-#ifdef TTMATH_POSIX_THREADS +- +- /* +- we use posix threads +- */ +- +- +- /*! +- in multithreads environment you should use TTMATH_MULTITHREADS_HELPER macro +- somewhere in *.cpp file +- (this macro defines a pthread_mutex_t object used by TTMath library) +- */ +- #define TTMATH_MULTITHREADS_HELPER \ +- namespace ttmath \ +- { \ +- pthread_mutex_t ttmath_mutex = PTHREAD_MUTEX_INITIALIZER; \ +- } +- +- +- /*! +- ttmath_mutex will be defined by TTMATH_MULTITHREADS_HELPER macro +- */ +- extern pthread_mutex_t ttmath_mutex; +- +- +- /*! +- objects of this class are used to synchronize +- */ +- class ThreadLock +- { +- public: +- +- bool Lock() +- { +- if( pthread_mutex_lock(&ttmath_mutex) != 0 ) +- return false; +- +- return true; +- } +- +- +- ~ThreadLock() +- { +- pthread_mutex_unlock(&ttmath_mutex); +- } +- }; +- +-#endif // #ifdef TTMATH_POSIX_THREADS +- +- +- +- +-#if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS) +- +- /*! +- we don't use win32 and pthreads +- */ +- +- /*! +- */ +- #define TTMATH_MULTITHREADS_HELPER +- +- +- /*! +- objects of this class are used to synchronize +- actually we don't synchronize, the method Lock() returns always 'false' +- */ +- class ThreadLock +- { +- public: +- +- bool Lock() +- { +- return false; +- } +- }; +- +- +-#endif // #if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS) +- +- +- +- +- +-} // namespace +- +-#endif +- +diff --git a/extern/ttmath/ttmathtypes.h b/extern/ttmath/ttmathtypes.h +deleted file mode 100644 +index 3d9ddbe7b0..0000000000 +--- a/extern/ttmath/ttmathtypes.h ++++ /dev/null +@@ -1,676 +0,0 @@ +-/* +- * This file is a part of TTMath Bignum Library +- * and is distributed under the (new) BSD licence. +- * Author: Tomasz Sowa +- */ +- +-/* +- * Copyright (c) 2006-2012, Tomasz Sowa +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * +- * * Redistributions of source code must retain the above copyright notice, +- * this list of conditions and the following disclaimer. +- * +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * +- * * Neither the name Tomasz Sowa nor the names of contributors to this +- * project may be used to endorse or promote products derived +- * from this software without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +- * THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +- +-#ifndef headerfilettmathtypes +-#define headerfilettmathtypes +- +-/*! +- \file ttmathtypes.h +- \brief constants used in the library +- +- As our library is written in header files (templates) we cannot use +- constants like 'const int' etc. because we should have some source files +- *.cpp to define this variables. Only what we can have are constants +- defined by #define preprocessor macros. +- +- All macros are preceded by TTMATH_ prefix +-*/ +- +- +-#include +-#include +-#include +- +-#ifndef _MSC_VER +-#include +-// for uint64_t and int64_t on a 32 bit platform +-#endif +- +- +- +-/*! +- the version of the library +- +- TTMATH_PRERELEASE_VER is either zero or one +- zero means that this is the release version of the library +- (one means something like beta) +-*/ +-#define TTMATH_MAJOR_VER 0 +-#define TTMATH_MINOR_VER 9 +-#define TTMATH_REVISION_VER 3 +- +-#define TTMATH_PRERELEASE_VER 0 +- +- +- +-/*! +- you can define a platform explicitly by defining either +- TTMATH_PLATFORM32 or TTMATH_PLATFORM64 macro +-*/ +-#if !defined TTMATH_PLATFORM32 && !defined TTMATH_PLATFORM64 +- +- #if !defined _M_X64 && !defined __x86_64__ +- +- /* +- other platforms than x86 and amd64 are not recognized at the moment +- so you should set TTMATH_PLATFORMxx manually +- */ +- +- // we're using a 32bit platform +- #define TTMATH_PLATFORM32 +- +- #else +- +- // we're using a 64bit platform +- #define TTMATH_PLATFORM64 +- +- #endif +- +-#endif +- +- +-/*! +- asm version of the library is available by default only for: +- x86 and amd64 platforms and for Microsoft Visual and GCC compilers +- +- but you can force using asm version (the same asm as for Microsoft Visual) +- by defining TTMATH_FORCEASM macro +- you have to be sure that your compiler accept such an asm format +-*/ +-#ifndef TTMATH_FORCEASM +- +- #if !defined __i386__ && !defined _X86_ && !defined _M_IX86 && !defined __x86_64__ && !defined _M_X64 +- /*! +- x86 architecture: +- __i386__ defined by GNU C +- _X86_ defined by MinGW32 +- _M_IX86 defined by Visual Studio, Intel C/C++, Digital Mars and Watcom C/C++ +- +- amd64 architecture: +- __x86_64__ defined by GNU C, CLANG (LLVM) and Sun Studio +- _M_X64 defined by Visual Studio +- +- asm version is available only for x86 or amd64 platforms +- */ +- #define TTMATH_NOASM +- #endif +- +- +- +- #if !defined _MSC_VER && !defined __GNUC__ +- /*! +- another compilers than MS VC or GCC or CLANG (LLVM) by default use no asm version +- (CLANG defines __GNUC__ too) +- */ +- #define TTMATH_NOASM +- #endif +- +-#endif +- +- +-namespace ttmath +-{ +- +- +-#ifdef TTMATH_PLATFORM32 +- +- /*! +- on 32bit platforms one word (uint, sint) will be equal 32bits +- */ +- typedef unsigned int uint; +- typedef signed int sint; +- +- /*! +- on 32 bit platform ulint and slint will be equal 64 bits +- */ +- #ifdef _MSC_VER +- // long long on MS Windows (Visual and GCC mingw compilers) have 64 bits +- // stdint.h is not available on Visual Studio prior to VS 2010 version +- typedef unsigned long long int ulint; +- typedef signed long long int slint; +- #else +- // we do not use 'long' here because there is a difference in unix and windows +- // environments: in unix 'long' has 64 bits but in windows it has only 32 bits +- typedef uint64_t ulint; +- typedef int64_t slint; +- #endif +- +- /*! +- how many bits there are in the uint type +- */ +- #define TTMATH_BITS_PER_UINT 32u +- +- /*! +- the mask for the highest bit in the unsigned 32bit word (2^31) +- */ +- #define TTMATH_UINT_HIGHEST_BIT 2147483648u +- +- /*! +- the max value of the unsigned 32bit word (2^32 - 1) +- (all bits equal one) +- */ +- #define TTMATH_UINT_MAX_VALUE 4294967295u +- +- /*! +- the number of words (32bit words on 32bit platform) +- which are kept in built-in variables for a Big<> type +- (these variables are defined in ttmathbig.h) +- */ +- #define TTMATH_BUILTIN_VARIABLES_SIZE 256u +- +- /*! +- this macro returns the number of machine words +- capable to hold min_bits bits +- e.g. TTMATH_BITS(128) returns 4 +- */ +- #define TTMATH_BITS(min_bits) ((min_bits-1)/32 + 1) +- +-#else +- +- /*! +- on 64bit platforms one word (uint, sint) will be equal 64bits +- */ +- #ifdef _MSC_VER +- /* in VC 'long' type has 32 bits, __int64 is VC extension */ +- typedef unsigned __int64 uint; +- typedef signed __int64 sint; +- #else +- typedef unsigned long uint; +- typedef signed long sint; +- #endif +- +- /*! +- on 64bit platforms we do not define ulint and slint +- */ +- +- /*! +- how many bits there are in the uint type +- */ +- #define TTMATH_BITS_PER_UINT 64ul +- +- /*! +- the mask for the highest bit in the unsigned 64bit word (2^63) +- */ +- #define TTMATH_UINT_HIGHEST_BIT 9223372036854775808ul +- +- /*! +- the max value of the unsigned 64bit word (2^64 - 1) +- (all bits equal one) +- */ +- #define TTMATH_UINT_MAX_VALUE 18446744073709551615ul +- +- /*! +- the number of words (64bit words on 64bit platforms) +- which are kept in built-in variables for a Big<> type +- (these variables are defined in ttmathbig.h) +- */ +- #define TTMATH_BUILTIN_VARIABLES_SIZE 128ul +- +- /*! +- this macro returns the number of machine words +- capable to hold min_bits bits +- e.g. TTMATH_BITS(128) returns 2 +- */ +- #define TTMATH_BITS(min_bits) ((min_bits-1)/64 + 1) +- +-#endif +-} +- +- +-#if defined(TTMATH_MULTITHREADS) && !defined(TTMATH_MULTITHREADS_NOSYNC) +- #if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS) +- +- #if defined(_WIN32) +- #define TTMATH_WIN32_THREADS +- #elif defined(unix) || defined(__unix__) || defined(__unix) +- #define TTMATH_POSIX_THREADS +- #endif +- +- #endif +-#endif +- +- +- +-/*! +- this variable defines how many iterations are performed +- during some kind of calculating when we're making any long formulas +- (for example Taylor series) +- +- it's used in ExpSurrounding0(...), LnSurrounding1(...), Sin0pi05(...), etc. +- +- note! there'll not be so many iterations, iterations are stopped when +- there is no sense to continue calculating (for example when the result +- still remains unchanged after adding next series and we know that the next +- series are smaller than previous ones) +-*/ +-#define TTMATH_ARITHMETIC_MAX_LOOP 10000 +- +- +- +-/*! +- this is a limit when calculating Karatsuba multiplication +- if the size of a vector is smaller than TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE +- the Karatsuba algorithm will use standard schoolbook multiplication +-*/ +-#ifdef TTMATH_DEBUG_LOG +- // if TTMATH_DEBUG_LOG is defined then we should use the same size regardless of the compiler +- #define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 3 +-#else +- #ifdef __GNUC__ +- #define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 3 +- #else +- #define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 5 +- #endif +-#endif +- +- +-/*! +- this is a special value used when calculating the Gamma(x) function +- if x is greater than this value then the Gamma(x) will be calculated using +- some kind of series +- +- don't use smaller values than about 100 +-*/ +-#define TTMATH_GAMMA_BOUNDARY 2000 +- +- +- +- +- +-namespace ttmath +-{ +- +- /*! +- lib type codes: +- asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits) +- asm_gcc_32 - with asm code designed for GCC (32 bits) +- asm_vc_64 - with asm for VC (64 bit) +- asm_gcc_64 - with asm for GCC (64 bit) +- no_asm_32 - pure C++ version (32 bit) - without any asm code +- no_asm_64 - pure C++ version (64 bit) - without any asm code +- */ +- enum LibTypeCode +- { +- asm_vc_32 = 0, +- asm_gcc_32, +- asm_vc_64, +- asm_gcc_64, +- no_asm_32, +- no_asm_64 +- }; +- +- +- /*! +- error codes +- */ +- enum ErrorCode +- { +- err_ok = 0, +- err_nothing_has_read, +- err_unknown_character, +- err_unexpected_final_bracket, +- err_stack_not_clear, +- err_unknown_variable, +- err_division_by_zero, +- err_interrupt, +- err_overflow, +- err_unknown_function, +- err_unknown_operator, +- err_unexpected_semicolon_operator, +- err_improper_amount_of_arguments, +- err_improper_argument, +- err_unexpected_end, +- err_internal_error, +- err_incorrect_name, +- err_incorrect_value, +- err_variable_exists, +- err_variable_loop, +- err_functions_loop, +- err_must_be_only_one_value, +- err_object_exists, +- err_unknown_object, +- err_still_calculating, +- err_in_short_form_used_function, +- err_percent_from +- }; +- +- +- /*! +- this struct is used when converting to/from a string +- /temporarily only in Big::ToString() and Big::FromString()/ +- */ +- struct Conv +- { +- /*! +- base (radix) on which the value will be shown (or read) +- default: 10 +- */ +- uint base; +- +- +- /*! +- used only in Big::ToString() +- if true the value will be always shown in the scientific mode, e.g: 123e+30 +- default: false +- */ +- bool scient; +- +- +- /*! +- used only in Big::ToString() +- if scient is false then the value will be printed in the scientific mode +- only if the exponent is greater than scien_from +- default: 15 +- */ +- sint scient_from; +- +- +- /*! +- if 'base_round' is true and 'base' is different from 2, 4, 8, or 16 +- and the result value is not an integer then we make an additional rounding +- (after converting the last digit from the result is skipped) +- default: true +- +- e.g. +- Conv c; +- c.base_round = false; +- Big<1, 1> a = "0.1"; // decimal input +- std::cout << a.ToString(c) << std::endl; // the result is: 0.099999999 +- */ +- bool base_round; +- +- +- /*! +- used only in Big::ToString() +- tells how many digits after comma are possible +- default: -1 which means all digits are printed +- +- set it to zero if you want integer value only +- +- for example when the value is: +- 12.345678 and 'round' is 4 +- then the result will be +- 12.3457 (the last digit was rounded) +- */ +- sint round; +- +- +- /*! +- if true that not mattered digits in the mantissa will be cut off +- (zero characters at the end -- after the comma operator) +- e.g. 1234,78000 will be: 1234,78 +- default: true +- */ +- bool trim_zeroes; +- +- +- /*! +- the main comma operator (used when reading and writing) +- default is a dot '.' +- */ +- uint comma; +- +- +- /*! +- additional comma operator (used only when reading) +- if you don't want it just set it to zero +- default is a comma ',' +- +- this allowes you to convert from a value: +- 123.45 as well as from 123,45 +- */ +- uint comma2; +- +- +- /*! +- it sets the character which is used for grouping +- if group=' ' then: 1234,56789 will be printed as: 1 234,567 89 +- +- if you don't want grouping just set it to zero (which is default) +- */ +- uint group; +- +- +- /*! +- how many digits should be grouped (it is used if 'group' is non zero) +- default: 3 +- */ +- uint group_digits; +- +- +- /*! +- */ +- uint group_exp; // not implemented yet +- +- +- +- +- Conv() +- { +- // default values +- base = 10; +- scient = false; +- scient_from = 15; +- base_round = true; +- round = -1; +- trim_zeroes = true; +- comma = '.'; +- comma2 = ','; +- group = 0; +- group_digits = 3; +- group_exp = 0; +- } +- }; +- +- +- +- /*! +- this simple class can be used in multithreading model +- (you can write your own class derived from this one) +- +- for example: in some functions like Factorial() +- /at the moment only Factorial/ you can give a pointer to +- the 'stop object', if the method WasStopSignal() of this +- object returns true that means we should break the calculating +- and return +- */ +- class StopCalculating +- { +- public: +- virtual bool WasStopSignal() const volatile { return false; } +- virtual ~StopCalculating(){} +- }; +- +- +- /*! +- a small class which is useful when compiling with gcc +- +- object of this type holds the name and the line of a file +- in which the macro TTMATH_ASSERT or TTMATH_REFERENCE_ASSERT was used +- */ +- class ExceptionInfo +- { +- const char * file; +- int line; +- +- public: +- ExceptionInfo() : file(0), line(0) {} +- ExceptionInfo(const char * f, int l) : file(f), line(l) {} +- +- std::string Where() const +- { +- if( !file ) +- return "unknown"; +- +- std::ostringstream result; +- result << file << ":" << line; +- +- return result.str(); +- } +- }; +- +- +- /*! +- A small class used for reporting 'reference' errors +- +- In the library is used macro TTMATH_REFERENCE_ASSERT which +- can throw an exception of this type +- +- ** from version 0.9.2 this macro is removed from all methods +- in public interface so you don't have to worry about it ** +- +- If you compile with gcc you can get a small benefit +- from using method Where() (it returns std::string) with +- the name and the line of a file where the macro TTMATH_REFERENCE_ASSERT +- was used) +- */ +- class ReferenceError : public std::logic_error, public ExceptionInfo +- { +- public: +- +- ReferenceError() : std::logic_error("reference error") +- { +- } +- +- ReferenceError(const char * f, int l) : +- std::logic_error("reference error"), ExceptionInfo(f,l) +- { +- } +- +- std::string Where() const +- { +- return ExceptionInfo::Where(); +- } +- }; +- +- +- /*! +- a small class used for reporting errors +- +- in the library is used macro TTMATH_ASSERT which +- (if the condition in it is false) throw an exception +- of this type +- +- if you compile with gcc you can get a small benefit +- from using method Where() (it returns std::string) with +- the name and the line of a file where the macro TTMATH_ASSERT +- was used) +- */ +- class RuntimeError : public std::runtime_error, public ExceptionInfo +- { +- public: +- +- RuntimeError() : std::runtime_error("internal error") +- { +- } +- +- RuntimeError(const char * f, int l) : +- std::runtime_error("internal error"), ExceptionInfo(f,l) +- { +- } +- +- std::string Where() const +- { +- return ExceptionInfo::Where(); +- } +- }; +- +- +- +- /*! +- TTMATH_DEBUG +- this macro enables further testing during writing your code +- you don't have to define it in a release mode +- +- if this macro is set then macros TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT +- are set as well and these macros can throw an exception if a condition in it +- is not fulfilled (look at the definition of TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT) +- +- TTMATH_DEBUG is set automatically if DEBUG or _DEBUG are defined +- */ +- #if defined DEBUG || defined _DEBUG +- #define TTMATH_DEBUG +- #endif +- +- +- #ifdef TTMATH_DEBUG +- +- #if defined(__FILE__) && defined(__LINE__) +- +- #define TTMATH_REFERENCE_ASSERT(expression) \ +- if( &(expression) == this ) throw ttmath::ReferenceError(__FILE__, __LINE__); +- +- #define TTMATH_ASSERT(expression) \ +- if( !(expression) ) throw ttmath::RuntimeError(__FILE__, __LINE__); +- +- #else +- +- #define TTMATH_REFERENCE_ASSERT(expression) \ +- if( &(expression) == this ) throw ReferenceError(); +- +- #define TTMATH_ASSERT(expression) \ +- if( !(expression) ) throw RuntimeError(); +- #endif +- +- #else +- #define TTMATH_REFERENCE_ASSERT(expression) +- #define TTMATH_ASSERT(expression) +- #endif +- +- +- +- #ifdef TTMATH_DEBUG_LOG +- #define TTMATH_LOG(msg) PrintLog(msg, std::cout); +- #define TTMATH_LOGC(msg, carry) PrintLog(msg, carry, std::cout); +- #define TTMATH_VECTOR_LOG(msg, vector, len) PrintVectorLog(msg, std::cout, vector, len); +- #define TTMATH_VECTOR_LOGC(msg, carry, vector, len) PrintVectorLog(msg, carry, std::cout, vector, len); +- #else +- #define TTMATH_LOG(msg) +- #define TTMATH_LOGC(msg, carry) +- #define TTMATH_VECTOR_LOG(msg, vector, len) +- #define TTMATH_VECTOR_LOGC(msg, carry, vector, len) +- #endif +- +- +- +- +-} // namespace +- +- +-#endif +- +diff --git a/extern/ttmath/ttmathuint.h b/extern/ttmath/ttmathuint.h +deleted file mode 100644 +index b9cf67cd11..0000000000 +--- a/extern/ttmath/ttmathuint.h ++++ /dev/null +@@ -1,4126 +0,0 @@ +-/* +- * This file is a part of TTMath Bignum Library +- * and is distributed under the (new) BSD licence. +- * Author: Tomasz Sowa +- */ +- +-/* +- * Copyright (c) 2006-2011, Tomasz Sowa +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * +- * * Redistributions of source code must retain the above copyright notice, +- * this list of conditions and the following disclaimer. +- * +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * +- * * Neither the name Tomasz Sowa nor the names of contributors to this +- * project may be used to endorse or promote products derived +- * from this software without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +- * THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +- +- +-#ifndef headerfilettmathuint +-#define headerfilettmathuint +- +- +-/*! +- \file ttmathuint.h +- \brief template class UInt +-*/ +- +-#include +-#include +- +- +-#include "ttmathtypes.h" +-#include "ttmathmisc.h" +- +- +- +-/*! +- \brief a namespace for the TTMath library +-*/ +-namespace ttmath +-{ +- +-/*! +- \brief UInt implements a big integer value without a sign +- +- value_size - how many bytes specify our value +- on 32bit platforms: value_size=1 -> 4 bytes -> 32 bits +- on 64bit platforms: value_size=1 -> 8 bytes -> 64 bits +- value_size = 1,2,3,4,5,6.... +-*/ +-template +-class UInt +-{ +-public: +- +- /*! +- buffer for the integer value +- table[0] - the lowest word of the value +- */ +- uint table[value_size]; +- +- +- +- /*! +- some methods used for debugging purposes +- */ +- +- +- /*! +- this method is used when macro TTMATH_DEBUG_LOG is defined +- */ +- template +- static void PrintVectorLog(const char_type * msg, ostream_type & output, const uint * vector, uint vector_len) +- { +- output << msg << std::endl; +- +- for(uint i=0 ; i +- static void PrintVectorLog(const char_type * msg, uint carry, ostream_type & output, const uint * vector, uint vector_len) +- { +- PrintVectorLog(msg, output, vector, vector_len); +- output << " carry: " << carry << std::endl; +- } +- +- +- /*! +- this method is used when macro TTMATH_DEBUG_LOG is defined +- */ +- template +- void PrintLog(const char_type * msg, ostream_type & output) const +- { +- PrintVectorLog(msg, output, table, value_size); +- } +- +- +- /*! +- this method is used when macro TTMATH_DEBUG_LOG is defined +- */ +- template +- void PrintLog(const char_type * msg, uint carry, ostream_type & output) const +- { +- PrintVectorLog(msg, output, table, value_size); +- output << " carry: " << carry << std::endl; +- } +- +- +- /*! +- this method returns the size of the table +- */ +- uint Size() const +- { +- return value_size; +- } +- +- +- /*! +- this method sets zero +- */ +- void SetZero() +- { +- // in the future here can be 'memset' +- +- for(uint i=0 ; i & ss2) +- { +- for(uint i=0 ; i=0 && temp_table_index=0 ; --i) +- table[i] = 0; +- +- +- TTMATH_LOG("UInt::SetFromTable") +- } +- +-#endif +- +- +-#ifdef TTMATH_PLATFORM64 +- /*! +- this method copies the value stored in an another table +- (warning: first values in temp_table are the highest words -- it's different +- from our table) +- +- ***this method is created only on a 64bit platform*** +- +- we copy as many words as it is possible +- +- if temp_table_len is bigger than value_size we'll try to round +- the lowest word from table depending on the last not used bit in temp_table +- (this rounding isn't a perfect rounding -- look at the description below) +- +- and if temp_table_len is smaller than value_size we'll clear the rest words +- in the table +- +- warning: we're using 'temp_table' as a pointer at 32bit words +- */ +- void SetFromTable(const unsigned int * temp_table, uint temp_table_len) +- { +- uint temp_table_index = 0; +- sint i; // 'i' with a sign +- +- for(i=value_size-1 ; i>=0 && temp_table_index= 0 ; --i) +- table[i] = 0; +- +- TTMATH_LOG("UInt::SetFromTable") +- } +- +-#endif +- +- +- +- +- +- /*! +- * +- * basic mathematic functions +- * +- */ +- +- +- +- +- /*! +- this method adds one to the existing value +- */ +- uint AddOne() +- { +- return AddInt(1); +- } +- +- +- /*! +- this method subtracts one from the existing value +- */ +- uint SubOne() +- { +- return SubInt(1); +- } +- +- +-private: +- +- +- /*! +- an auxiliary method for moving bits into the left hand side +- +- this method moves only words +- */ +- void RclMoveAllWords(uint & rest_bits, uint & last_c, uint bits, uint c) +- { +- rest_bits = bits % TTMATH_BITS_PER_UINT; +- uint all_words = bits / TTMATH_BITS_PER_UINT; +- uint mask = ( c ) ? TTMATH_UINT_MAX_VALUE : 0; +- +- +- if( all_words >= value_size ) +- { +- if( all_words == value_size && rest_bits == 0 ) +- last_c = table[0] & 1; +- // else: last_c is default set to 0 +- +- // clearing +- for(uint i = 0 ; i 0 ) +- { +- // 0 < all_words < value_size +- +- sint first, second; +- last_c = table[value_size - all_words] & 1; // all_words is greater than 0 +- +- // copying the first part of the value +- for(first = value_size-1, second=first-all_words ; second>=0 ; --first, --second) +- table[first] = table[second]; +- +- // setting the rest to 'c' +- for( ; first>=0 ; --first ) +- table[first] = mask; +- } +- +- TTMATH_LOG("UInt::RclMoveAllWords") +- } +- +-public: +- +- /*! +- moving all bits into the left side 'bits' times +- return value <- this <- C +- +- bits is from a range of <0, man * TTMATH_BITS_PER_UINT> +- or it can be even bigger then all bits will be set to 'c' +- +- the value c will be set into the lowest bits +- and the method returns state of the last moved bit +- */ +- uint Rcl(uint bits, uint c=0) +- { +- uint last_c = 0; +- uint rest_bits = bits; +- +- if( bits == 0 ) +- return 0; +- +- if( bits >= TTMATH_BITS_PER_UINT ) +- RclMoveAllWords(rest_bits, last_c, bits, c); +- +- if( rest_bits == 0 ) +- { +- TTMATH_LOG("UInt::Rcl") +- return last_c; +- } +- +- // rest_bits is from 1 to TTMATH_BITS_PER_UINT-1 now +- if( rest_bits == 1 ) +- { +- last_c = Rcl2_one(c); +- } +- else if( rest_bits == 2 ) +- { +- // performance tests showed that for rest_bits==2 it's better to use Rcl2_one twice instead of Rcl2(2,c) +- Rcl2_one(c); +- last_c = Rcl2_one(c); +- } +- else +- { +- last_c = Rcl2(rest_bits, c); +- } +- +- TTMATH_LOGC("UInt::Rcl", last_c) +- +- return last_c; +- } +- +-private: +- +- /*! +- an auxiliary method for moving bits into the right hand side +- +- this method moves only words +- */ +- void RcrMoveAllWords(uint & rest_bits, uint & last_c, uint bits, uint c) +- { +- rest_bits = bits % TTMATH_BITS_PER_UINT; +- uint all_words = bits / TTMATH_BITS_PER_UINT; +- uint mask = ( c ) ? TTMATH_UINT_MAX_VALUE : 0; +- +- +- if( all_words >= value_size ) +- { +- if( all_words == value_size && rest_bits == 0 ) +- last_c = (table[value_size-1] & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0; +- // else: last_c is default set to 0 +- +- // clearing +- for(uint i = 0 ; i 0 ) +- { +- // 0 < all_words < value_size +- +- uint first, second; +- last_c = (table[all_words - 1] & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0; // all_words is > 0 +- +- // copying the first part of the value +- for(first=0, second=all_words ; second this -> return value +- +- bits is from a range of <0, man * TTMATH_BITS_PER_UINT> +- or it can be even bigger then all bits will be set to 'c' +- +- the value c will be set into the highest bits +- and the method returns state of the last moved bit +- */ +- uint Rcr(uint bits, uint c=0) +- { +- uint last_c = 0; +- uint rest_bits = bits; +- +- if( bits == 0 ) +- return 0; +- +- if( bits >= TTMATH_BITS_PER_UINT ) +- RcrMoveAllWords(rest_bits, last_c, bits, c); +- +- if( rest_bits == 0 ) +- { +- TTMATH_LOG("UInt::Rcr") +- return last_c; +- } +- +- // rest_bits is from 1 to TTMATH_BITS_PER_UINT-1 now +- if( rest_bits == 1 ) +- { +- last_c = Rcr2_one(c); +- } +- else if( rest_bits == 2 ) +- { +- // performance tests showed that for rest_bits==2 it's better to use Rcr2_one twice instead of Rcr2(2,c) +- Rcr2_one(c); +- last_c = Rcr2_one(c); +- } +- else +- { +- last_c = Rcr2(rest_bits, c); +- } +- +- TTMATH_LOGC("UInt::Rcr", last_c) +- +- return last_c; +- } +- +- +- /*! +- this method moves all bits into the left side +- (it returns value how many bits have been moved) +- */ +- uint CompensationToLeft() +- { +- uint moving = 0; +- +- // a - index a last word which is different from zero +- sint a; +- for(a=value_size-1 ; a>=0 && table[a]==0 ; --a); +- +- if( a < 0 ) +- return moving; // all words in table have zero +- +- if( a != value_size-1 ) +- { +- moving += ( value_size-1 - a ) * TTMATH_BITS_PER_UINT; +- +- // moving all words +- sint i; +- for(i=value_size-1 ; a>=0 ; --i, --a) +- table[i] = table[a]; +- +- // setting the rest word to zero +- for(; i>=0 ; --i) +- table[i] = 0; +- } +- +- uint moving2 = FindLeadingBitInWord( table[value_size-1] ); +- // moving2 is different from -1 because the value table[value_size-1] +- // is not zero +- +- moving2 = TTMATH_BITS_PER_UINT - moving2 - 1; +- Rcl(moving2); +- +- TTMATH_LOG("UInt::CompensationToLeft") +- +- return moving + moving2; +- } +- +- +- /*! +- this method looks for the highest set bit +- +- result: +- if 'this' is not zero: +- return value - true +- 'table_id' - the index of a word <0..value_size-1> +- 'index' - the index of this set bit in the word <0..TTMATH_BITS_PER_UINT) +- +- if 'this' is zero: +- return value - false +- both 'table_id' and 'index' are zero +- */ +- bool FindLeadingBit(uint & table_id, uint & index) const +- { +- for(table_id=value_size-1 ; table_id!=0 && table[table_id]==0 ; --table_id); +- +- if( table_id==0 && table[table_id]==0 ) +- { +- // is zero +- index = 0; +- +- return false; +- } +- +- // table[table_id] is different from 0 +- index = FindLeadingBitInWord( table[table_id] ); +- +- return true; +- } +- +- +- /*! +- this method looks for the smallest set bit +- +- result: +- if 'this' is not zero: +- return value - true +- 'table_id' - the index of a word <0..value_size-1> +- 'index' - the index of this set bit in the word <0..TTMATH_BITS_PER_UINT) +- +- if 'this' is zero: +- return value - false +- both 'table_id' and 'index' are zero +- */ +- bool FindLowestBit(uint & table_id, uint & index) const +- { +- for(table_id=0 ; table_id= value_size ) +- { +- // is zero +- index = 0; +- table_id = 0; +- +- return false; +- } +- +- // table[table_id] is different from 0 +- index = FindLowestBitInWord( table[table_id] ); +- +- return true; +- } +- +- +- /*! +- getting the 'bit_index' bit +- +- bit_index bigger or equal zero +- */ +- uint GetBit(uint bit_index) const +- { +- TTMATH_ASSERT( bit_index < value_size * TTMATH_BITS_PER_UINT ) +- +- uint index = bit_index / TTMATH_BITS_PER_UINT; +- uint bit = bit_index % TTMATH_BITS_PER_UINT; +- +- uint temp = table[index]; +- uint res = SetBitInWord(temp, bit); +- +- return res; +- } +- +- +- /*! +- setting the 'bit_index' bit +- and returning the last state of the bit +- +- bit_index bigger or equal zero +- */ +- uint SetBit(uint bit_index) +- { +- TTMATH_ASSERT( bit_index < value_size * TTMATH_BITS_PER_UINT ) +- +- uint index = bit_index / TTMATH_BITS_PER_UINT; +- uint bit = bit_index % TTMATH_BITS_PER_UINT; +- uint res = SetBitInWord(table[index], bit); +- +- TTMATH_LOG("UInt::SetBit") +- +- return res; +- } +- +- +- /*! +- this method performs a bitwise operation AND +- */ +- void BitAnd(const UInt & ss2) +- { +- for(uint x=0 ; x & ss2) +- { +- for(uint x=0 ; x & ss2) +- { +- for(uint x=0 ; x +- +- for example: +- BitNot2(8) = BitNot2( 1000(bin) ) = 111(bin) = 7 +- */ +- void BitNot2() +- { +- uint table_id, index; +- +- if( FindLeadingBit(table_id, index) ) +- { +- for(uint x=0 ; x>= shift; +- +- table[table_id] ^= mask; +- } +- else +- table[0] = 1; +- +- +- TTMATH_LOG("UInt::BitNot2") +- } +- +- +- +- /*! +- * +- * Multiplication +- * +- * +- */ +- +-public: +- +- /*! +- multiplication: this = this * ss2 +- +- it can return a carry +- */ +- uint MulInt(uint ss2) +- { +- uint r1, r2, x1; +- uint c = 0; +- +- UInt u(*this); +- SetZero(); +- +- if( ss2 == 0 ) +- { +- TTMATH_LOGC("UInt::MulInt(uint)", 0) +- return 0; +- } +- +- for(x1=0 ; x1 +- void MulInt(uint ss2, UInt & result) const +- { +- TTMATH_ASSERT( result_size > value_size ) +- +- uint r2,r1; +- uint x1size=value_size; +- uint x1start=0; +- +- result.SetZero(); +- +- if( ss2 == 0 ) +- { +- TTMATH_VECTOR_LOG("UInt::MulInt(uint, UInt<>)", result.table, result_size) +- return; +- } +- +- if( value_size > 2 ) +- { +- // if the value_size is smaller than or equal to 2 +- // there is no sense to set x1size and x1start to another values +- +- for(x1size=value_size ; x1size>0 && table[x1size-1]==0 ; --x1size); +- +- if( x1size == 0 ) +- { +- TTMATH_VECTOR_LOG("UInt::MulInt(uint, UInt<>)", result.table, result_size) +- return; +- } +- +- for(x1start=0 ; x1start)", result.table, result_size) +- +- return; +- } +- +- +- +- /*! +- the multiplication 'this' = 'this' * ss2 +- +- algorithm: 100 - means automatically choose the fastest algorithm +- */ +- uint Mul(const UInt & ss2, uint algorithm = 100) +- { +- switch( algorithm ) +- { +- case 1: +- return Mul1(ss2); +- +- case 2: +- return Mul2(ss2); +- +- case 3: +- return Mul3(ss2); +- +- case 100: +- default: +- return MulFastest(ss2); +- } +- } +- +- +- /*! +- the multiplication 'result' = 'this' * ss2 +- +- since the 'result' is twice bigger than 'this' and 'ss2' +- this method never returns a carry +- +- algorithm: 100 - means automatically choose the fastest algorithm +- */ +- void MulBig(const UInt & ss2, +- UInt & result, +- uint algorithm = 100) +- { +- switch( algorithm ) +- { +- case 1: +- return Mul1Big(ss2, result); +- +- case 2: +- return Mul2Big(ss2, result); +- +- case 3: +- return Mul3Big(ss2, result); +- +- case 100: +- default: +- return MulFastestBig(ss2, result); +- } +- } +- +- +- +- /*! +- the first version of the multiplication algorithm +- */ +- +-private: +- +- /*! +- multiplication: this = this * ss2 +- +- it returns carry if it has been +- */ +- uint Mul1Ref(const UInt & ss2) +- { +- TTMATH_REFERENCE_ASSERT( ss2 ) +- +- UInt ss1( *this ); +- SetZero(); +- +- for(uint i=0; i < value_size*TTMATH_BITS_PER_UINT ; ++i) +- { +- if( Add(*this) ) +- { +- TTMATH_LOGC("UInt::Mul1", 1) +- return 1; +- } +- +- if( ss1.Rcl(1) ) +- if( Add(ss2) ) +- { +- TTMATH_LOGC("UInt::Mul1", 1) +- return 1; +- } +- } +- +- TTMATH_LOGC("UInt::Mul1", 0) +- +- return 0; +- } +- +- +-public: +- +- /*! +- multiplication: this = this * ss2 +- can return carry +- */ +- uint Mul1(const UInt & ss2) +- { +- if( this == &ss2 ) +- { +- UInt copy_ss2(ss2); +- return Mul1Ref(copy_ss2); +- } +- else +- { +- return Mul1Ref(ss2); +- } +- } +- +- +- /*! +- multiplication: result = this * ss2 +- +- result is twice bigger than 'this' and 'ss2' +- this method never returns carry +- */ +- void Mul1Big(const UInt & ss2_, UInt & result) +- { +- UInt ss2; +- uint i; +- +- // copying *this into result and ss2_ into ss2 +- for(i=0 ; i & ss2) +- { +- UInt result; +- uint i, c = 0; +- +- Mul2Big(ss2, result); +- +- // copying result +- for(i=0 ; i & ss2, UInt & result) +- { +- Mul2Big2(table, ss2.table, result); +- +- TTMATH_LOG("UInt::Mul2Big") +- } +- +- +-private: +- +- /*! +- an auxiliary method for calculating the multiplication +- +- arguments we're taking as pointers (this is to improve the Mul3Big2()- avoiding +- unnecessary copying objects), the result should be taken as a pointer too, +- but at the moment there is no method AddTwoInts() which can operate on pointers +- */ +- template +- void Mul2Big2(const uint * ss1, const uint * ss2, UInt & result) +- { +- uint x1size = ss_size, x2size = ss_size; +- uint x1start = 0, x2start = 0; +- +- if( ss_size > 2 ) +- { +- // if the ss_size is smaller than or equal to 2 +- // there is no sense to set x1size (and others) to another values +- +- for(x1size=ss_size ; x1size>0 && ss1[x1size-1]==0 ; --x1size); +- for(x2size=ss_size ; x2size>0 && ss2[x2size-1]==0 ; --x2size); +- +- for(x1start=0 ; x1start(ss1, ss2, result, x1start, x1size, x2start, x2size); +- } +- +- +- +- /*! +- an auxiliary method for calculating the multiplication +- */ +- template +- void Mul2Big3(const uint * ss1, const uint * ss2, UInt & result, uint x1start, uint x1size, uint x2start, uint x2size) +- { +- uint r2, r1; +- +- result.SetZero(); +- +- if( x1size==0 || x2size==0 ) +- return; +- +- for(uint x1=x1start ; x1 & ss2) +- { +- UInt result; +- uint i, c = 0; +- +- Mul3Big(ss2, result); +- +- // copying result +- for(i=0 ; i & ss2, UInt & result) +- { +- Mul3Big2(table, ss2.table, result.table); +- +- TTMATH_LOG("UInt::Mul3Big") +- } +- +- +- +-private: +- +- /*! +- an auxiliary method for calculating the Karatsuba multiplication +- +- result_size is equal ss_size*2 +- */ +- template +- void Mul3Big2(const uint * ss1, const uint * ss2, uint * result) +- { +- const uint * x1, * x0, * y1, * y0; +- +- +- if( ss_size>1 && ss_size res; +- Mul2Big2(ss1, ss2, res); +- +-#ifdef __clang__ +-#pragma clang diagnostic push +-#pragma clang diagnostic ignored "-Wtautological-compare" +-#endif +- +- for(uint i=0 ; i(x1, x0, y1, y0, result); +- } +- else +- { +- // ss_size is even +- x0 = ss1; +- y0 = ss2; +- x1 = ss1 + ss_size / 2; +- y1 = ss2 + ss_size / 2; +- +- // all four vectors (x0 x1 y0 y1) are equal in size +- Mul3Big3(x1, x0, y1, y0, result); +- } +- } +- +- +- +-#ifdef _MSC_VER +-#pragma warning (disable : 4717) +-//warning C4717: recursive on all control paths, function will cause runtime stack overflow +-//we have the stop point in Mul3Big2() method +-#endif +- +- +- /*! +- an auxiliary method for calculating the Karatsuba multiplication +- +- x = x1*B^m + x0 +- y = y1*B^m + y0 +- +- first_size - is the size of vectors: x0 and y0 +- second_size - is the size of vectors: x1 and y1 (can be either equal first_size or smaller about one from first_size) +- +- x*y = (x1*B^m + x0)(y1*B^m + y0) = z2*B^(2m) + z1*B^m + z0 +- where +- z0 = x0*y0 +- z2 = x1*y1 +- z1 = (x1 + x0)*(y1 + y0) - z2 - z0 +- */ +- template +- uint Mul3Big3(const uint * x1, const uint * x0, const uint * y1, const uint * y0, uint * result) +- { +- uint i, c, xc, yc; +- +- UInt temp, temp2; +- UInt z1; +- +- // z0 and z2 we store directly in the result (we don't use any temporary variables) +- Mul3Big2(x0, y0, result); // z0 +- Mul3Big2(x1, y1, result+first_size*2); // z2 +- +- // now we calculate z1 +- // temp = (x0 + x1) +- // temp2 = (y0 + y1) +- // we're using temp and temp2 with UInt, although there can be a carry but +- // we simple remember it in xc and yc (xc and yc can be either 0 or 1), +- // and (x0 + x1)*(y0 + y1) we calculate in this way (schoolbook algorithm): +- // +- // xc | temp +- // yc | temp2 +- // -------------------- +- // (temp * temp2) +- // xc*temp2 | +- // yc*temp | +- // xc*yc | +- // ---------- z1 -------- +- // +- // and the result is never larger in size than 3*first_size +- +- xc = AddVector(x0, x1, first_size, second_size, temp.table); +- yc = AddVector(y0, y1, first_size, second_size, temp2.table); +- +- Mul3Big2(temp.table, temp2.table, z1.table); +- +-#ifdef __clang__ +-#pragma clang diagnostic push +-#pragma clang diagnostic ignored "-Wtautological-compare" +-#endif +- +- // clearing the rest of z1 +- for(i=first_size*2 ; i second_size ) +- { +- uint z1_size = result_size - first_size; +- TTMATH_ASSERT( z1_size <= first_size*3 ) +- +-#ifdef __clang__ +-#pragma clang diagnostic push +-#pragma clang diagnostic ignored "-Wtautological-compare" +-#endif +- +- for(i=z1_size ; i & ss2) +- { +- UInt result; +- uint i, c = 0; +- +- MulFastestBig(ss2, result); +- +- // copying result +- for(i=0 ; i & ss2, UInt & result) +- { +- if( value_size < TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE ) +- return Mul2Big(ss2, result); +- +- uint x1size = value_size, x2size = value_size; +- uint x1start = 0, x2start = 0; +- +- for(x1size=value_size ; x1size>0 && table[x1size-1]==0 ; --x1size); +- for(x2size=value_size ; x2size>0 && ss2.table[x2size-1]==0 ; --x2size); +- +- if( x1size==0 || x2size==0 ) +- { +- // either 'this' or 'ss2' is equal zero - the result is zero too +- result.SetZero(); +- return; +- } +- +- for(x1start=0 ; x1start(table, ss2.table, result, x1start, x1size, x2start, x2size); +- +- +- // Karatsuba multiplication +- Mul3Big(ss2, result); +- +- TTMATH_LOG("UInt::MulFastestBig") +- } +- +- +- /*! +- * +- * Division +- * +- * +- */ +- +-public: +- +- +- /*! +- division by one unsigned word +- +- returns 1 when divisor is zero +- */ +- uint DivInt(uint divisor, uint * remainder = 0) +- { +- if( divisor == 0 ) +- { +- if( remainder ) +- *remainder = 0; // this is for convenience, without it the compiler can report that 'remainder' is uninitialized +- +- TTMATH_LOG("UInt::DivInt") +- +- return 1; +- } +- +- if( divisor == 1 ) +- { +- if( remainder ) +- *remainder = 0; +- +- TTMATH_LOG("UInt::DivInt") +- +- return 0; +- } +- +- UInt dividend(*this); +- SetZero(); +- +- sint i; // i must be with a sign +- uint r = 0; +- +- // we're looking for the last word in ss1 +- for(i=value_size-1 ; i>0 && dividend.table[i]==0 ; --i); +- +- for( ; i>=0 ; --i) +- DivTwoWords(r, dividend.table[i], divisor, &table[i], &r); +- +- if( remainder ) +- *remainder = r; +- +- TTMATH_LOG("UInt::DivInt") +- +- return 0; +- } +- +- uint DivInt(uint divisor, uint & remainder) +- { +- return DivInt(divisor, &remainder); +- } +- +- +- +- /*! +- division this = this / ss2 +- +- return values: +- 0 - ok +- 1 - division by zero +- 'this' will be the quotient +- 'remainder' - remainder +- */ +- uint Div( const UInt & divisor, +- UInt * remainder = 0, +- uint algorithm = 3) +- { +- switch( algorithm ) +- { +- case 1: +- return Div1(divisor, remainder); +- +- case 2: +- return Div2(divisor, remainder); +- +- case 3: +- default: +- return Div3(divisor, remainder); +- } +- } +- +- uint Div(const UInt & divisor, UInt & remainder, uint algorithm = 3) +- { +- return Div(divisor, &remainder, algorithm); +- } +- +- +- +-private: +- +- /*! +- return values: +- 0 - none has to be done +- 1 - division by zero +- 2 - division should be made +- */ +- uint Div_StandardTest( const UInt & v, +- uint & m, uint & n, +- UInt * remainder = 0) +- { +- switch( Div_CalculatingSize(v, m, n) ) +- { +- case 4: // 'this' is equal v +- if( remainder ) +- remainder->SetZero(); +- +- SetOne(); +- TTMATH_LOG("UInt::Div_StandardTest") +- return 0; +- +- case 3: // 'this' is smaller than v +- if( remainder ) +- *remainder = *this; +- +- SetZero(); +- TTMATH_LOG("UInt::Div_StandardTest") +- return 0; +- +- case 2: // 'this' is zero +- if( remainder ) +- remainder->SetZero(); +- +- SetZero(); +- TTMATH_LOG("UInt::Div_StandardTest") +- return 0; +- +- case 1: // v is zero +- TTMATH_LOG("UInt::Div_StandardTest") +- return 1; +- } +- +- TTMATH_LOG("UInt::Div_StandardTest") +- +- return 2; +- } +- +- +- +- /*! +- return values: +- 0 - ok +- 'm' - is the index (from 0) of last non-zero word in table ('this') +- 'n' - is the index (from 0) of last non-zero word in v.table +- 1 - v is zero +- 2 - 'this' is zero +- 3 - 'this' is smaller than v +- 4 - 'this' is equal v +- +- if the return value is different than zero the 'm' and 'n' are undefined +- */ +- uint Div_CalculatingSize(const UInt & v, uint & m, uint & n) +- { +- m = n = value_size-1; +- +- for( ; n!=0 && v.table[n]==0 ; --n); +- +- if( n==0 && v.table[n]==0 ) +- return 1; +- +- for( ; m!=0 && table[m]==0 ; --m); +- +- if( m==0 && table[m]==0 ) +- return 2; +- +- if( m < n ) +- return 3; +- else +- if( m == n ) +- { +- uint i; +- for(i = n ; i!=0 && table[i]==v.table[i] ; --i); +- +- if( table[i] < v.table[i] ) +- return 3; +- else +- if (table[i] == v.table[i] ) +- return 4; +- } +- +- return 0; +- } +- +- +-public: +- +- /*! +- the first division algorithm +- radix 2 +- */ +- uint Div1(const UInt & divisor, UInt * remainder = 0) +- { +- uint m,n, test; +- +- test = Div_StandardTest(divisor, m, n, remainder); +- if( test < 2 ) +- return test; +- +- if( !remainder ) +- { +- UInt rem; +- +- return Div1_Calculate(divisor, rem); +- } +- +- return Div1_Calculate(divisor, *remainder); +- } +- +- +- /*! +- the first division algorithm +- radix 2 +- */ +- uint Div1(const UInt & divisor, UInt & remainder) +- { +- return Div1(divisor, &remainder); +- } +- +- +-private: +- +- uint Div1_Calculate(const UInt & divisor, UInt & rest) +- { +- if( this == &divisor ) +- { +- UInt divisor_copy(divisor); +- return Div1_CalculateRef(divisor_copy, rest); +- } +- else +- { +- return Div1_CalculateRef(divisor, rest); +- } +- } +- +- +- uint Div1_CalculateRef(const UInt & divisor, UInt & rest) +- { +- TTMATH_REFERENCE_ASSERT( divisor ) +- +- sint loop; +- sint c; +- +- rest.SetZero(); +- loop = value_size * TTMATH_BITS_PER_UINT; +- c = 0; +- +- +- div_a: +- c = Rcl(1, c); +- c = rest.Add(rest,c); +- c = rest.Sub(divisor,c); +- +- c = !c; +- +- if(!c) +- goto div_d; +- +- +- div_b: +- --loop; +- if(loop) +- goto div_a; +- +- c = Rcl(1, c); +- TTMATH_LOG("UInt::Div1_Calculate") +- return 0; +- +- +- div_c: +- c = Rcl(1, c); +- c = rest.Add(rest,c); +- c = rest.Add(divisor); +- +- if(c) +- goto div_b; +- +- +- div_d: +- --loop; +- if(loop) +- goto div_c; +- +- c = Rcl(1, c); +- c = rest.Add(divisor); +- +- TTMATH_LOG("UInt::Div1_Calculate") +- +- return 0; +- } +- +- +-public: +- +- /*! +- the second division algorithm +- +- return values: +- 0 - ok +- 1 - division by zero +- */ +- uint Div2(const UInt & divisor, UInt * remainder = 0) +- { +- if( this == &divisor ) +- { +- UInt divisor_copy(divisor); +- return Div2Ref(divisor_copy, remainder); +- } +- else +- { +- return Div2Ref(divisor, remainder); +- } +- } +- +- +- /*! +- the second division algorithm +- +- return values: +- 0 - ok +- 1 - division by zero +- */ +- uint Div2(const UInt & divisor, UInt & remainder) +- { +- return Div2(divisor, &remainder); +- } +- +- +-private: +- +- /*! +- the second division algorithm +- +- return values: +- 0 - ok +- 1 - division by zero +- */ +- uint Div2Ref(const UInt & divisor, UInt * remainder = 0) +- { +- uint bits_diff; +- uint status = Div2_Calculate(divisor, remainder, bits_diff); +- if( status < 2 ) +- return status; +- +- if( CmpBiggerEqual(divisor) ) +- { +- Div2(divisor, remainder); +- SetBit(bits_diff); +- } +- else +- { +- if( remainder ) +- *remainder = *this; +- +- SetZero(); +- SetBit(bits_diff); +- } +- +- TTMATH_LOG("UInt::Div2") +- +- return 0; +- } +- +- +- /*! +- return values: +- 0 - we've calculated the division +- 1 - division by zero +- 2 - we have to still calculate +- +- */ +- uint Div2_Calculate(const UInt & divisor, UInt * remainder, +- uint & bits_diff) +- { +- uint table_id, index; +- uint divisor_table_id, divisor_index; +- +- uint status = Div2_FindLeadingBitsAndCheck( divisor, remainder, +- table_id, index, +- divisor_table_id, divisor_index); +- +- if( status < 2 ) +- { +- TTMATH_LOG("UInt::Div2_Calculate") +- return status; +- } +- +- // here we know that 'this' is greater than divisor +- // then 'index' is greater or equal 'divisor_index' +- bits_diff = index - divisor_index; +- +- UInt divisor_copy(divisor); +- divisor_copy.Rcl(bits_diff, 0); +- +- if( CmpSmaller(divisor_copy, table_id) ) +- { +- divisor_copy.Rcr(1); +- --bits_diff; +- } +- +- Sub(divisor_copy, 0); +- +- TTMATH_LOG("UInt::Div2_Calculate") +- +- return 2; +- } +- +- +- /*! +- return values: +- 0 - we've calculated the division +- 1 - division by zero +- 2 - we have to still calculate +- */ +- uint Div2_FindLeadingBitsAndCheck( const UInt & divisor, +- UInt * remainder, +- uint & table_id, uint & index, +- uint & divisor_table_id, uint & divisor_index) +- { +- if( !divisor.FindLeadingBit(divisor_table_id, divisor_index) ) +- { +- // division by zero +- TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck") +- return 1; +- } +- +- if( !FindLeadingBit(table_id, index) ) +- { +- // zero is divided by something +- +- SetZero(); +- +- if( remainder ) +- remainder->SetZero(); +- +- TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck") +- +- return 0; +- } +- +- divisor_index += divisor_table_id * TTMATH_BITS_PER_UINT; +- index += table_id * TTMATH_BITS_PER_UINT; +- +- if( divisor_table_id == 0 ) +- { +- // dividor has only one 32-bit word +- +- uint r; +- DivInt(divisor.table[0], &r); +- +- if( remainder ) +- { +- remainder->SetZero(); +- remainder->table[0] = r; +- } +- +- TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck") +- +- return 0; +- } +- +- +- if( Div2_DivisorGreaterOrEqual( divisor, remainder, +- table_id, index, +- divisor_index) ) +- { +- TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck") +- return 0; +- } +- +- +- TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck") +- +- return 2; +- } +- +- +- /*! +- return values: +- true if divisor is equal or greater than 'this' +- */ +- bool Div2_DivisorGreaterOrEqual( const UInt & divisor, +- UInt * remainder, +- uint table_id, uint index, +- uint divisor_index ) +- { +- if( divisor_index > index ) +- { +- // divisor is greater than this +- +- if( remainder ) +- *remainder = *this; +- +- SetZero(); +- +- TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual") +- +- return true; +- } +- +- if( divisor_index == index ) +- { +- // table_id == divisor_table_id as well +- +- uint i; +- for(i = table_id ; i!=0 && table[i]==divisor.table[i] ; --i); +- +- if( table[i] < divisor.table[i] ) +- { +- // divisor is greater than 'this' +- +- if( remainder ) +- *remainder = *this; +- +- SetZero(); +- +- TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual") +- +- return true; +- } +- else +- if( table[i] == divisor.table[i] ) +- { +- // divisor is equal 'this' +- +- if( remainder ) +- remainder->SetZero(); +- +- SetOne(); +- +- TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual") +- +- return true; +- } +- } +- +- TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual") +- +- return false; +- } +- +- +-public: +- +- /*! +- the third division algorithm +- */ +- uint Div3(const UInt & ss2, UInt * remainder = 0) +- { +- if( this == &ss2 ) +- { +- UInt copy_ss2(ss2); +- return Div3Ref(copy_ss2, remainder); +- } +- else +- { +- return Div3Ref(ss2, remainder); +- } +- } +- +- +- /*! +- the third division algorithm +- */ +- uint Div3(const UInt & ss2, UInt & remainder) +- { +- return Div3(ss2, &remainder); +- } +- +- +-private: +- +- /*! +- the third division algorithm +- +- this algorithm is described in the following book: +- "The art of computer programming 2" (4.3.1 page 272) +- Donald E. Knuth +- !! give the description here (from the book) +- */ +- uint Div3Ref(const UInt & v, UInt * remainder = 0) +- { +- uint m,n, test; +- +- test = Div_StandardTest(v, m, n, remainder); +- if( test < 2 ) +- return test; +- +- if( n == 0 ) +- { +- uint r; +- DivInt( v.table[0], &r ); +- +- if( remainder ) +- { +- remainder->SetZero(); +- remainder->table[0] = r; +- } +- +- TTMATH_LOG("UInt::Div3") +- +- return 0; +- } +- +- +- // we can only use the third division algorithm when +- // the divisor is greater or equal 2^32 (has more than one 32-bit word) +- ++m; +- ++n; +- m = m - n; +- Div3_Division(v, remainder, m, n); +- +- TTMATH_LOG("UInt::Div3") +- +- return 0; +- } +- +- +- +-private: +- +- +- void Div3_Division(UInt v, UInt * remainder, uint m, uint n) +- { +- TTMATH_ASSERT( n>=2 ) +- +- UInt uu, vv; +- UInt q; +- uint d, u_value_size, u0, u1, u2, v1, v0, j=m; +- +- u_value_size = Div3_Normalize(v, n, d); +- +- if( j+n == value_size ) +- u2 = u_value_size; +- else +- u2 = table[j+n]; +- +- Div3_MakeBiggerV(v, vv); +- +- for(uint i = j+1 ; i & uu, uint j, uint n, uint u_max) +- { +- uint i; +- +- for(i=0 ; i so and 'i' is from <0..value_size> +- // then table[i] is always correct (look at the declaration of 'uu') +- uu.table[i] = u_max; +- +- for( ++i ; i & uu, uint j, uint n) +- { +- uint i; +- +- for(i=0 ; i & v, UInt & vv) +- { +- for(uint i=0 ; i & v, uint n, uint & d) +- { +- // v.table[n-1] is != 0 +- +- uint bit = (uint)FindLeadingBitInWord(v.table[n-1]); +- uint move = (TTMATH_BITS_PER_UINT - bit - 1); +- uint res = table[value_size-1]; +- d = move; +- +- if( move > 0 ) +- { +- v.Rcl(move, 0); +- Rcl(move, 0); +- res = res >> (bit + 1); +- } +- else +- { +- res = 0; +- } +- +- TTMATH_LOG("UInt::Div3_Normalize") +- +- return res; +- } +- +- +- void Div3_Unnormalize(UInt * remainder, uint n, uint d) +- { +- for(uint i=n ; i u_temp; +- uint rp; +- bool next_test; +- +- TTMATH_ASSERT( v1 != 0 ) +- +- u_temp.table[1] = u2; +- u_temp.table[0] = u1; +- u_temp.DivInt(v1, &rp); +- +- TTMATH_ASSERT( u_temp.table[1]==0 || u_temp.table[1]==1 ) +- +- do +- { +- bool decrease = false; +- +- if( u_temp.table[1] == 1 ) +- decrease = true; +- else +- { +- UInt<2> temp1, temp2; +- +- UInt<2>::MulTwoWords(u_temp.table[0], v0, temp1.table+1, temp1.table); +- temp2.table[1] = rp; +- temp2.table[0] = u0; +- +- if( temp1 > temp2 ) +- decrease = true; +- } +- +- next_test = false; +- +- if( decrease ) +- { +- u_temp.SubOne(); +- +- rp += v1; +- +- if( rp >= v1 ) // it means that there wasn't a carry (r & uu, +- const UInt & vv, uint & qp) +- { +- // D4 (in the book) +- +- UInt vv_temp(vv); +- vv_temp.MulInt(qp); +- +- if( uu.Sub(vv_temp) ) +- { +- // there was a carry +- +- // +- // !!! this part of code was not tested +- // +- +- --qp; +- uu.Add(vv); +- +- // can be a carry from this additions but it should be ignored +- // because it cancels with the borrow from uu.Sub(vv_temp) +- } +- +- TTMATH_LOG("UInt::Div3_MultiplySubtract") +- } +- +- +- +- +- +- +-public: +- +- +- /*! +- power this = this ^ pow +- binary algorithm (r-to-l) +- +- return values: +- 0 - ok +- 1 - carry +- 2 - incorrect argument (0^0) +- */ +- uint Pow(UInt pow) +- { +- if(pow.IsZero() && IsZero()) +- // we don't define zero^zero +- return 2; +- +- UInt start(*this); +- UInt result; +- result.SetOne(); +- uint c = 0; +- +- while( !c ) +- { +- if( pow.table[0] & 1 ) +- c += result.Mul(start); +- +- pow.Rcr2_one(0); +- if( pow.IsZero() ) +- break; +- +- c += start.Mul(start); +- } +- +- *this = result; +- +- TTMATH_LOGC("UInt::Pow(UInt<>)", c) +- +- return (c==0)? 0 : 1; +- } +- +- +- /*! +- square root +- e.g. Sqrt(9) = 3 +- ('digit-by-digit' algorithm) +- */ +- void Sqrt() +- { +- UInt bit, temp; +- +- if( IsZero() ) +- return; +- +- UInt value(*this); +- +- SetZero(); +- bit.SetZero(); +- bit.table[value_size-1] = (TTMATH_UINT_HIGHEST_BIT >> 1); +- +- while( bit > value ) +- bit.Rcr(2); +- +- while( !bit.IsZero() ) +- { +- temp = *this; +- temp.Add(bit); +- +- if( value >= temp ) +- { +- value.Sub(temp); +- Rcr(1); +- Add(bit); +- } +- else +- { +- Rcr(1); +- } +- +- bit.Rcr(2); +- } +- +- TTMATH_LOG("UInt::Sqrt") +- } +- +- +- +- /*! +- this method sets n first bits to value zero +- +- For example: +- let n=2 then if there's a value 111 (bin) there'll be '100' (bin) +- */ +- void ClearFirstBits(uint n) +- { +- if( n >= value_size*TTMATH_BITS_PER_UINT ) +- { +- SetZero(); +- TTMATH_LOG("UInt::ClearFirstBits") +- return; +- } +- +- uint * p = table; +- +- // first we're clearing the whole words +- while( n >= TTMATH_BITS_PER_UINT ) +- { +- *p++ = 0; +- n -= TTMATH_BITS_PER_UINT; +- } +- +- if( n == 0 ) +- { +- TTMATH_LOG("UInt::ClearFirstBits") +- return; +- } +- +- // and then we're clearing one word which has left +- // mask -- all bits are set to one +- uint mask = TTMATH_UINT_MAX_VALUE; +- +- mask = mask << n; +- +- (*p) &= mask; +- +- TTMATH_LOG("UInt::ClearFirstBits") +- } +- +- +- /*! +- this method returns true if the highest bit of the value is set +- */ +- bool IsTheHighestBitSet() const +- { +- return (table[value_size-1] & TTMATH_UINT_HIGHEST_BIT) != 0; +- } +- +- +- /*! +- this method returns true if the lowest bit of the value is set +- */ +- bool IsTheLowestBitSet() const +- { +- return (*table & 1) != 0; +- } +- +- +- /*! +- returning true if only the highest bit is set +- */ +- bool IsOnlyTheHighestBitSet() const +- { +-#ifdef __clang__ +-#pragma clang diagnostic push +-#pragma clang diagnostic ignored "-Wtautological-compare" +-#endif +- +- for(uint i=0 ; i> (TTMATH_BITS_PER_UINT - rest); +- +- return (table[i] & mask) == 0; +- } +- +- +- +- /*! +- * +- * conversion methods +- * +- */ +- +- +- +- /*! +- this method converts an UInt type to this class +- +- this operation has mainly sense if the value from p is +- equal or smaller than that one which is returned from UInt::SetMax() +- +- it returns a carry if the value 'p' is too big +- */ +- template +- uint FromUInt(const UInt & p) +- { +- uint min_size = (value_size < argument_size)? value_size : argument_size; +- uint i; +- +- for(i=0 ; i argument_size ) +- { +- // 'this' is longer than 'p' +- +- for( ; i)", 1) +- return 1; +- } +- } +- +- TTMATH_LOGC("UInt::FromUInt(UInt<>)", 0) +- +- return 0; +- } +- +- +- /*! +- this method converts an UInt type to this class +- +- this operation has mainly sense if the value from p is +- equal or smaller than that one which is returned from UInt::SetMax() +- +- it returns a carry if the value 'p' is too big +- */ +- template +- uint FromInt(const UInt & p) +- { +- return FromUInt(p); +- } +- +- +- /*! +- this method converts the uint type to this class +- */ +- uint FromUInt(uint value) +- { +- for(uint i=1 ; i type to this class +- +- it doesn't return a carry +- */ +-/* template +- UInt & operator=(const UInt & p) +- { +- FromUInt(p); +- +- return *this; +- } +-*/ +- +- /*! +- the assignment operator +- */ +-/* UInt & operator=(const UInt & p) +- { +- for(uint i=0 ; i)") +- +- return *this; +- } +-*/ +- +- /*! +- this method converts the uint type to this class +- */ +- UInt & operator=(uint i) +- { +- FromUInt(i); +- +- return *this; +- } +- +- +- /*! +- a constructor for converting the uint to this class +- */ +-/* UInt(uint i) +- { +- FromUInt(i); +- } +-*/ +- +- /*! +- this method converts the sint type to this class +- */ +- UInt & operator=(sint i) +- { +- FromInt(i); +- +- return *this; +- } +- +- +- /*! +- a constructor for converting the sint to this class +- +- look at the description of UInt::operator=(sint) +- */ +-/* UInt(sint i) +- { +- FromInt(i); +- } +-*/ +- +-#ifdef TTMATH_PLATFORM32 +- +- +- /*! +- this method converts unsigned 64 bit int type to this class +- ***this method is created only on a 32bit platform*** +- */ +- uint FromUInt(ulint n) +- { +- table[0] = (uint)n; +- +- if( value_size == 1 ) +- { +- uint c = ((n >> TTMATH_BITS_PER_UINT) == 0) ? 0 : 1; +- +- TTMATH_LOGC("UInt::FromUInt(ulint)", c) +- return c; +- } +- +- table[1] = (uint)(n >> TTMATH_BITS_PER_UINT); +- +- for(uint i=2 ; i & operator=(ulint n) +- { +- FromUInt(n); +- +- return *this; +- } +- +- +- /*! +- a constructor for converting unsigned 64 bit int to this class +- ***this constructor is created only on a 32bit platform*** +- */ +-/* UInt(ulint n) +- { +- FromUInt(n); +- } +-*/ +- +- /*! +- this operator converts signed 64 bit int type to this class +- ***this operator is created only on a 32bit platform*** +- */ +- UInt & operator=(slint n) +- { +- FromInt(n); +- +- return *this; +- } +- +- +- /*! +- a constructor for converting signed 64 bit int to this class +- ***this constructor is created only on a 32bit platform*** +- */ +-/* UInt(slint n) +- { +- FromInt(n); +- } +-*/ +-#endif +- +- +- +-#ifdef TTMATH_PLATFORM64 +- +- +- /*! +- this method converts 32 bit unsigned int type to this class +- ***this operator is created only on a 64bit platform*** +- */ +- uint FromUInt(unsigned int i) +- { +- return FromUInt(uint(i)); +- } +- +- /*! +- this method converts 32 bit unsigned int type to this class +- ***this operator is created only on a 64bit platform*** +- */ +- uint FromInt(unsigned int i) +- { +- return FromUInt(uint(i)); +- } +- +- +- /*! +- this method converts 32 bit signed int type to this class +- ***this operator is created only on a 64bit platform*** +- */ +- uint FromInt(signed int i) +- { +- return FromInt(sint(i)); +- } +- +- +- /*! +- this operator converts 32 bit unsigned int type to this class +- ***this operator is created only on a 64bit platform*** +- */ +- UInt & operator=(unsigned int i) +- { +- FromUInt(i); +- +- return *this; +- } +- +- +- /*! +- a constructor for converting 32 bit unsigned int to this class +- ***this constructor is created only on a 64bit platform*** +- */ +-/* UInt(unsigned int i) +- { +- FromUInt(i); +- } +-*/ +- +- /*! +- an operator for converting 32 bit signed int to this class +- ***this constructor is created only on a 64bit platform*** +- */ +- UInt & operator=(signed int i) +- { +- FromInt(i); +- +- return *this; +- } +- +- +- /*! +- a constructor for converting 32 bit signed int to this class +- ***this constructor is created only on a 64bit platform*** +- */ +-/* UInt(signed int i) +- { +- FromInt(i); +- } +-*/ +- +-#endif +- +- +- +- +- +- /*! +- a constructor for converting a string to this class (with the base=10) +- */ +-/* UInt(const char * s) +- { +- FromString(s); +- } +-*/ +- +- /*! +- a constructor for converting a string to this class (with the base=10) +- */ +-/* UInt(const std::string & s) +- { +- FromString( s.c_str() ); +- } +-*/ +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- /*! +- a constructor for converting a string to this class (with the base=10) +- */ +- UInt(const wchar_t * s) +- { +- FromString(s); +- } +- +- +- /*! +- a constructor for converting a string to this class (with the base=10) +- */ +- UInt(const std::wstring & s) +- { +- FromString( s.c_str() ); +- } +- +-#endif +- +- +- +- +- /*! +- a default constructor +- +- we don't clear the table +- */ +-/* UInt() +- { +- // when macro TTMATH_DEBUG_LOG is defined +- // we set special values to the table +- // in order to be everywhere the same value of the UInt object +- // without this it would be difficult to analyse the log file +- #ifdef TTMATH_DEBUG_LOG +- #ifdef TTMATH_PLATFORM32 +- for(uint i=0 ; i & u) +- { +- for(uint i=0 ; i)") +- } +-*/ +- +- +- /*! +- a template for producting constructors for copying from another types +- */ +-/* template +- UInt(const UInt & u) +- { +- // look that 'size' we still set as 'value_size' and not as u.value_size +- FromUInt(u); +- } +-*/ +- +- +- +- /*! +- a destructor +- */ +-/* ~UInt() +- { +- } +-*/ +- +- /*! +- this method returns the lowest value from table +- +- we must be sure when we using this method whether the value +- will hold in an uint type or not (the rest value from the table must be zero) +- */ +- uint ToUInt() const +- { +- return table[0]; +- } +- +- +- /*! +- this method converts the value to uint type +- can return a carry if the value is too long to store it in uint type +- */ +- uint ToUInt(uint & result) const +- { +- result = table[0]; +- +- for(uint i=1 ; i> 32) != 0 ) +- return 1; +- +- for(uint i=1 ; i +- */ +- double ToStringLog2(uint x) const +- { +- static double log_tab[] = { +- 1.000000000000000000, +- 0.630929753571457437, +- 0.500000000000000000, +- 0.430676558073393050, +- 0.386852807234541586, +- 0.356207187108022176, +- 0.333333333333333333, +- 0.315464876785728718, +- 0.301029995663981195, +- 0.289064826317887859, +- 0.278942945651129843, +- 0.270238154427319741, +- 0.262649535037193547, +- 0.255958024809815489, +- 0.250000000000000000 +- }; +- +- if( x<2 || x>16 ) +- return 0; +- +- return log_tab[x-2]; +- } +- +- +-public: +- +- +- /*! +- an auxiliary method for converting to a string +- it's used from Int::ToString() too (negative is set true then) +- */ +- template +- void ToStringBase(string_type & result, uint b = 10, bool negative = false) const +- { +- UInt temp(*this); +- uint rest, table_id, index, digits; +- double digits_d; +- char character; +- +- result.clear(); +- +- if( b<2 || b>16 ) +- return; +- +- if( !FindLeadingBit(table_id, index) ) +- { +- result = '0'; +- return; +- } +- +- if( negative ) +- result = '-'; +- +- digits_d = table_id; // for not making an overflow in uint type +- digits_d *= TTMATH_BITS_PER_UINT; +- digits_d += index + 1; +- digits_d *= ToStringLog2(b); +- digits = static_cast(digits_d) + 3; // plus some epsilon +- +- if( result.capacity() < digits ) +- result.reserve(digits); +- +- do +- { +- temp.DivInt(b, &rest); +- character = static_cast(Misc::DigitToChar(rest)); +- result.insert(result.end(), character); +- } +- while( !temp.IsZero() ); +- +- size_t i1 = negative ? 1 : 0; // the first is a hyphen (when negative is true) +- size_t i2 = result.size() - 1; +- +- for( ; i1 < i2 ; ++i1, --i2 ) +- { +- char tempc = static_cast(result[i1]); +- result[i1] = result[i2]; +- result[i2] = tempc; +- } +- } +- +- +- +- /*! +- this method converts the value to a string with a base equal 'b' +- */ +- void ToString(std::string & result, uint b = 10) const +- { +- return ToStringBase(result, b); +- } +- +- +- std::string ToString(uint b = 10) const +- { +- std::string result; +- ToStringBase(result, b); +- +- return result; +- } +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- void ToString(std::wstring & result, uint b = 10) const +- { +- return ToStringBase(result, b); +- } +- +- std::wstring ToWString(uint b = 10) const +- { +- std::wstring result; +- ToStringBase(result, b); +- +- return result; +- } +- +-#endif +- +- +- +-private: +- +- /*! +- an auxiliary method for converting from a string +- */ +- template +- uint FromStringBase(const char_type * s, uint b = 10, const char_type ** after_source = 0, bool * value_read = 0) +- { +- UInt base; +- base.FromUInt( b ); +- UInt temp; +- sint z; +- uint c = 0; +- +- SetZero(); +- temp.SetZero(); +- Misc::SkipWhiteCharacters(s); +- +- if( after_source ) +- *after_source = s; +- +- if( value_read ) +- *value_read = false; +- +- if( b<2 || b>16 ) +- return 1; +- +- +- for( ; (z=Misc::CharToDigit(*s, b)) != -1 ; ++s) +- { +- if( value_read ) +- *value_read = true; +- +- if( c == 0 ) +- { +- temp.table[0] = z; +- +- c += Mul(base); // !! IMPROVE ME: there can be used MulInt here +- c += Add(temp); +- } +- } +- +- if( after_source ) +- *after_source = s; +- +- TTMATH_LOGC("UInt::FromString", c) +- +- return (c==0)? 0 : 1; +- } +- +- +-public: +- +- +- /*! +- this method converts a string into its value +- it returns carry=1 if the value will be too big or an incorrect base 'b' is given +- +- string is ended with a non-digit value, for example: +- "12" will be translated to 12 +- as well as: +- "12foo" will be translated to 12 too +- +- existing first white characters will be ommited +- +- if the value from s is too large the rest digits will be skipped +- +- after_source (if exists) is pointing at the end of the parsed string +- +- value_read (if exists) tells whether something has actually been read (at least one digit) +- */ +- uint FromString(const char * s, uint b = 10, const char ** after_source = 0, bool * value_read = 0) +- { +- return FromStringBase(s, b, after_source, value_read); +- } +- +- +- /*! +- this method converts a string into its value +- +- (it returns carry=1 if the value will be too big or an incorrect base 'b' is given) +- */ +- uint FromString(const std::string & s, uint b = 10) +- { +- return FromString( s.c_str(), b ); +- } +- +- +- /*! +- this operator converts a string into its value (with base = 10) +- */ +- UInt & operator=(const char * s) +- { +- FromString(s); +- +- return *this; +- } +- +- +- /*! +- this operator converts a string into its value (with base = 10) +- */ +- UInt & operator=(const std::string & s) +- { +- FromString( s.c_str() ); +- +- return *this; +- } +- +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- /*! +- this method converts a string into its value +- */ +- uint FromString(const wchar_t * s, uint b = 10, const wchar_t ** after_source = 0, bool * value_read = 0) +- { +- return FromStringBase(s, b, after_source, value_read); +- } +- +- +- /*! +- this method converts a string into its value +- +- (it returns carry=1 if the value will be too big or an incorrect base 'b' is given) +- */ +- uint FromString(const std::wstring & s, uint b = 10) +- { +- return FromString( s.c_str(), b ); +- } +- +- +- /*! +- this operator converts a string into its value (with base = 10) +- */ +- UInt & operator=(const wchar_t * s) +- { +- FromString(s); +- +- return *this; +- } +- +- +- /*! +- this operator converts a string into its value (with base = 10) +- */ +- UInt & operator=(const std::wstring & s) +- { +- FromString( s.c_str() ); +- +- return *this; +- } +- +-#endif +- +- +- /*! +- * +- * methods for comparing +- * +- */ +- +- +- /*! +- this method returns true if 'this' is smaller than 'l' +- +- 'index' is an index of the first word from will be the comparison performed +- (note: we start the comparison from back - from the last word, when index is -1 /default/ +- it is automatically set into the last word) +- I introduced it for some kind of optimization made in the second division algorithm (Div2) +- */ +- bool CmpSmaller(const UInt & l, sint index = -1) const +- { +- sint i; +- +- if( index==-1 || index>=sint(value_size) ) +- i = value_size - 1; +- else +- i = index; +- +- +- for( ; i>=0 ; --i) +- { +- if( table[i] != l.table[i] ) +- return table[i] < l.table[i]; +- } +- +- // they're equal +- return false; +- } +- +- +- +- /*! +- this method returns true if 'this' is bigger than 'l' +- +- 'index' is an index of the first word from will be the comparison performed +- (note: we start the comparison from back - from the last word, when index is -1 /default/ +- it is automatically set into the last word) +- +- I introduced it for some kind of optimization made in the second division algorithm (Div2) +- */ +- bool CmpBigger(const UInt & l, sint index = -1) const +- { +- sint i; +- +- if( index==-1 || index>=sint(value_size) ) +- i = value_size - 1; +- else +- i = index; +- +- +- for( ; i>=0 ; --i) +- { +- if( table[i] != l.table[i] ) +- return table[i] > l.table[i]; +- } +- +- // they're equal +- return false; +- } +- +- +- /*! +- this method returns true if 'this' is equal 'l' +- +- 'index' is an index of the first word from will be the comparison performed +- (note: we start the comparison from back - from the last word, when index is -1 /default/ +- it is automatically set into the last word) +- */ +- bool CmpEqual(const UInt & l, sint index = -1) const +- { +- sint i; +- +- if( index==-1 || index>=sint(value_size) ) +- i = value_size - 1; +- else +- i = index; +- +- +- for( ; i>=0 ; --i) +- if( table[i] != l.table[i] ) +- return false; +- +- return true; +- } +- +- +- +- /*! +- this method returns true if 'this' is smaller than or equal 'l' +- +- 'index' is an index of the first word from will be the comparison performed +- (note: we start the comparison from back - from the last word, when index is -1 /default/ +- it is automatically set into the last word) +- */ +- bool CmpSmallerEqual(const UInt & l, sint index=-1) const +- { +- sint i; +- +- if( index==-1 || index>=sint(value_size) ) +- i = value_size - 1; +- else +- i = index; +- +- +- for( ; i>=0 ; --i) +- { +- if( table[i] != l.table[i] ) +- return table[i] < l.table[i]; +- } +- +- // they're equal +- return true; +- } +- +- +- +- /*! +- this method returns true if 'this' is bigger than or equal 'l' +- +- 'index' is an index of the first word from will be the comparison performed +- (note: we start the comparison from back - from the last word, when index is -1 /default/ +- it is automatically set into the last word) +- */ +- bool CmpBiggerEqual(const UInt & l, sint index=-1) const +- { +- sint i; +- +- if( index==-1 || index>=sint(value_size) ) +- i = value_size - 1; +- else +- i = index; +- +- +- for( ; i>=0 ; --i) +- { +- if( table[i] != l.table[i] ) +- return table[i] > l.table[i]; +- } +- +- // they're equal +- return true; +- } +- +- +- /* +- operators for comparising +- */ +- +- bool operator<(const UInt & l) const +- { +- return CmpSmaller(l); +- } +- +- +- bool operator>(const UInt & l) const +- { +- return CmpBigger(l); +- } +- +- +- bool operator==(const UInt & l) const +- { +- return CmpEqual(l); +- } +- +- +- bool operator!=(const UInt & l) const +- { +- return !operator==(l); +- } +- +- +- bool operator<=(const UInt & l) const +- { +- return CmpSmallerEqual(l); +- } +- +- bool operator>=(const UInt & l) const +- { +- return CmpBiggerEqual(l); +- } +- +- +- /*! +- * +- * standard mathematical operators +- * +- */ +- +- UInt operator-(const UInt & p2) const +- { +- UInt temp(*this); +- +- temp.Sub(p2); +- +- return temp; +- } +- +- UInt & operator-=(const UInt & p2) +- { +- Sub(p2); +- +- return *this; +- } +- +- UInt operator+(const UInt & p2) const +- { +- UInt temp(*this); +- +- temp.Add(p2); +- +- return temp; +- } +- +- UInt & operator+=(const UInt & p2) +- { +- Add(p2); +- +- return *this; +- } +- +- +- UInt operator*(const UInt & p2) const +- { +- UInt temp(*this); +- +- temp.Mul(p2); +- +- return temp; +- } +- +- +- UInt & operator*=(const UInt & p2) +- { +- Mul(p2); +- +- return *this; +- } +- +- +- UInt operator/(const UInt & p2) const +- { +- UInt temp(*this); +- +- temp.Div(p2); +- +- return temp; +- } +- +- +- UInt & operator/=(const UInt & p2) +- { +- Div(p2); +- +- return *this; +- } +- +- +- UInt operator%(const UInt & p2) const +- { +- UInt temp(*this); +- UInt remainder; +- +- temp.Div( p2, remainder ); +- +- return remainder; +- } +- +- +- UInt & operator%=(const UInt & p2) +- { +- UInt remainder; +- +- Div( p2, remainder ); +- operator=(remainder); +- +- return *this; +- } +- +- +- /*! +- Prefix operator e.g ++variable +- */ +- UInt & operator++() +- { +- AddOne(); +- +- return *this; +- } +- +- +- /*! +- Postfix operator e.g variable++ +- */ +- UInt operator++(int) +- { +- UInt temp( *this ); +- +- AddOne(); +- +- return temp; +- } +- +- +- UInt & operator--() +- { +- SubOne(); +- +- return *this; +- } +- +- +- UInt operator--(int) +- { +- UInt temp( *this ); +- +- SubOne(); +- +- return temp; +- } +- +- +- +- /*! +- * +- * bitwise operators +- * +- */ +- +- UInt operator~() const +- { +- UInt temp( *this ); +- +- temp.BitNot(); +- +- return temp; +- } +- +- +- UInt operator&(const UInt & p2) const +- { +- UInt temp( *this ); +- +- temp.BitAnd(p2); +- +- return temp; +- } +- +- +- UInt & operator&=(const UInt & p2) +- { +- BitAnd(p2); +- +- return *this; +- } +- +- +- UInt operator|(const UInt & p2) const +- { +- UInt temp( *this ); +- +- temp.BitOr(p2); +- +- return temp; +- } +- +- +- UInt & operator|=(const UInt & p2) +- { +- BitOr(p2); +- +- return *this; +- } +- +- +- UInt operator^(const UInt & p2) const +- { +- UInt temp( *this ); +- +- temp.BitXor(p2); +- +- return temp; +- } +- +- +- UInt & operator^=(const UInt & p2) +- { +- BitXor(p2); +- +- return *this; +- } +- +- +- UInt operator>>(int move) const +- { +- UInt temp( *this ); +- +- temp.Rcr(move); +- +- return temp; +- } +- +- +- UInt & operator>>=(int move) +- { +- Rcr(move); +- +- return *this; +- } +- +- +- UInt operator<<(int move) const +- { +- UInt temp( *this ); +- +- temp.Rcl(move); +- +- return temp; +- } +- +- +- UInt & operator<<=(int move) +- { +- Rcl(move); +- +- return *this; +- } +- +- +- /*! +- * +- * input/output operators for standard streams +- * +- * (they are very simple, in the future they should be changed) +- * +- */ +- +- +-private: +- +- +- /*! +- an auxiliary method for outputing to standard streams +- */ +- template +- static ostream_type & OutputToStream(ostream_type & s, const UInt & l) +- { +- string_type ss; +- +- l.ToString(ss); +- s << ss; +- +- return s; +- } +- +- +-public: +- +- +- /*! +- output to standard streams +- */ +- friend std::ostream & operator<<(std::ostream & s, const UInt & l) +- { +- return OutputToStream(s, l); +- } +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- /*! +- output to standard streams +- */ +- friend std::wostream & operator<<(std::wostream & s, const UInt & l) +- { +- return OutputToStream(s, l); +- } +- +-#endif +- +- +- +-private: +- +- /*! +- an auxiliary method for reading from standard streams +- */ +- template +- static istream_type & InputFromStream(istream_type & s, UInt & l) +- { +- string_type ss; +- +- // char or wchar_t for operator>> +- char_type z; +- +- // operator>> omits white characters if they're set for ommiting +- s >> z; +- +- // we're reading only digits (base=10) +- while( s.good() && Misc::CharToDigit(z, 10)>=0 ) +- { +- ss += z; +- z = static_cast(s.get()); +- } +- +- // we're leaving the last read character +- // (it's not belonging to the value) +- s.unget(); +- +- l.FromString(ss); +- +- return s; +- } +- +-public: +- +- +- /*! +- input from standard streams +- */ +- friend std::istream & operator>>(std::istream & s, UInt & l) +- { +- return InputFromStream(s, l); +- } +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- /*! +- input from standard streams +- */ +- friend std::wistream & operator>>(std::wistream & s, UInt & l) +- { +- return InputFromStream(s, l); +- } +- +-#endif +- +- +- /* +- Following methods are defined in: +- ttmathuint_x86.h +- ttmathuint_x86_64.h +- ttmathuint_noasm.h +- */ +- +-#ifdef TTMATH_NOASM +- static uint AddTwoWords(uint a, uint b, uint carry, uint * result); +- static uint SubTwoWords(uint a, uint b, uint carry, uint * result); +- +-#ifdef TTMATH_PLATFORM64 +- +- union uint_ +- { +- struct +- { +- unsigned int low; // 32 bit +- unsigned int high; // 32 bit +- } u_; +- +- uint u; // 64 bit +- }; +- +- +- static void DivTwoWords2(uint a,uint b, uint c, uint * r, uint * rest); +- static uint DivTwoWordsNormalize(uint_ & a_, uint_ & b_, uint_ & c_); +- static uint DivTwoWordsUnnormalize(uint u, uint d); +- static unsigned int DivTwoWordsCalculate(uint_ u_, unsigned int u3, uint_ v_); +- static void MultiplySubtract(uint_ & u_, unsigned int & u3, unsigned int & q, uint_ v_); +- +-#endif // TTMATH_PLATFORM64 +-#endif // TTMATH_NOASM +- +- +-private: +- uint Rcl2_one(uint c); +- uint Rcr2_one(uint c); +- uint Rcl2(uint bits, uint c); +- uint Rcr2(uint bits, uint c); +- +-public: +- static const char * LibTypeStr(); +- static LibTypeCode LibType(); +- uint Add(const UInt & ss2, uint c=0); +- uint AddInt(uint value, uint index = 0); +- uint AddTwoInts(uint x2, uint x1, uint index); +- static uint AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result); +- uint Sub(const UInt & ss2, uint c=0); +- uint SubInt(uint value, uint index = 0); +- static uint SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result); +- static sint FindLeadingBitInWord(uint x); +- static sint FindLowestBitInWord(uint x); +- static uint SetBitInWord(uint & value, uint bit); +- static void MulTwoWords(uint a, uint b, uint * result_high, uint * result_low); +- static void DivTwoWords(uint a,uint b, uint c, uint * r, uint * rest); +- +-}; +- +- +- +-/*! +- this specialization is needed in order to not confused the compiler "error: ISO C++ forbids zero-size array" +- when compiling Mul3Big2() method +-*/ +-template<> +-class UInt<0> +-{ +-public: +- uint table[1]; +- +- void Mul2Big(const UInt<0> &, UInt<0> &) { TTMATH_ASSERT(false) }; +- void SetZero() { TTMATH_ASSERT(false) }; +- uint AddTwoInts(uint, uint, uint) { TTMATH_ASSERT(false) return 0; }; +-}; +- +- +-} //namespace +- +- +-#include "ttmathuint_x86.h" +-#include "ttmathuint_x86_64.h" +-#include "ttmathuint_noasm.h" +- +-#endif +diff --git a/extern/ttmath/ttmathuint_noasm.h b/extern/ttmath/ttmathuint_noasm.h +deleted file mode 100644 +index 07c73fc499..0000000000 +--- a/extern/ttmath/ttmathuint_noasm.h ++++ /dev/null +@@ -1,1017 +0,0 @@ +-/* +- * This file is a part of TTMath Bignum Library +- * and is distributed under the (new) BSD licence. +- * Author: Tomasz Sowa +- */ +- +-/* +- * Copyright (c) 2006-2010, Tomasz Sowa +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * +- * * Redistributions of source code must retain the above copyright notice, +- * this list of conditions and the following disclaimer. +- * +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * +- * * Neither the name Tomasz Sowa nor the names of contributors to this +- * project may be used to endorse or promote products derived +- * from this software without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +- * THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +-#ifndef headerfilettmathuint_noasm +-#define headerfilettmathuint_noasm +- +- +-#ifdef TTMATH_NOASM +- +-/*! +- \file ttmathuint_noasm.h +- \brief template class UInt with methods without any assembler code +- +- this file is included at the end of ttmathuint.h +-*/ +- +- +-namespace ttmath +-{ +- +- /*! +- returning the string represents the currect type of the library +- we have following types: +- asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits) +- asm_gcc_32 - with asm code designed for GCC (32 bits) +- asm_vc_64 - with asm for VC (64 bit) +- asm_gcc_64 - with asm for GCC (64 bit) +- no_asm_32 - pure C++ version (32 bit) - without any asm code +- no_asm_64 - pure C++ version (64 bit) - without any asm code +- */ +- template +- const char * UInt::LibTypeStr() +- { +- #ifdef TTMATH_PLATFORM32 +- static const char info[] = "no_asm_32"; +- #endif +- +- #ifdef TTMATH_PLATFORM64 +- static const char info[] = "no_asm_64"; +- #endif +- +- return info; +- } +- +- +- /*! +- returning the currect type of the library +- */ +- template +- LibTypeCode UInt::LibType() +- { +- #ifdef TTMATH_PLATFORM32 +- LibTypeCode info = no_asm_32; +- #endif +- +- #ifdef TTMATH_PLATFORM64 +- LibTypeCode info = no_asm_64; +- #endif +- +- return info; +- } +- +- +- /*! +- this method adds two words together +- returns carry +- +- this method is created only when TTMATH_NOASM macro is defined +- */ +- template +- uint UInt::AddTwoWords(uint a, uint b, uint carry, uint * result) +- { +- uint temp; +- +- if( carry == 0 ) +- { +- temp = a + b; +- +- if( temp < a ) +- carry = 1; +- } +- else +- { +- carry = 1; +- temp = a + b + carry; +- +- if( temp > a ) // !(temp<=a) +- carry = 0; +- } +- +- *result = temp; +- +- return carry; +- } +- +- +- +- /*! +- this method adding ss2 to the this and adding carry if it's defined +- (this = this + ss2 + c) +- +- c must be zero or one (might be a bigger value than 1) +- function returns carry (1) (if it was) +- */ +- +- template +- uint UInt::Add(const UInt & ss2, uint c) +- { +- uint i; +- +- for(i=0 ; i +- uint UInt::AddInt(uint value, uint index) +- { +- uint i, c; +- +- TTMATH_ASSERT( index < value_size ) +- +- +- c = AddTwoWords(table[index], value, 0, &table[index]); +- +- for(i=index+1 ; i +- uint UInt::AddTwoInts(uint x2, uint x1, uint index) +- { +- uint i, c; +- +- TTMATH_ASSERT( index < value_size - 1 ) +- +- +- c = AddTwoWords(table[index], x1, 0, &table[index]); +- c = AddTwoWords(table[index+1], x2, c, &table[index+1]); +- +- for(i=index+2 ; i +- uint UInt::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) +- { +- uint i, c = 0; +- +- TTMATH_ASSERT( ss1_size >= ss2_size ) +- +- for(i=0 ; i +- uint UInt::SubTwoWords(uint a, uint b, uint carry, uint * result) +- { +- if( carry == 0 ) +- { +- *result = a - b; +- +- if( a < b ) +- carry = 1; +- } +- else +- { +- carry = 1; +- *result = a - b - carry; +- +- if( a > b ) // !(a <= b ) +- carry = 0; +- } +- +- return carry; +- } +- +- +- +- +- /*! +- this method's subtracting ss2 from the 'this' and subtracting +- carry if it has been defined +- (this = this - ss2 - c) +- +- c must be zero or one (might be a bigger value than 1) +- function returns carry (1) (if it was) +- */ +- template +- uint UInt::Sub(const UInt & ss2, uint c) +- { +- uint i; +- +- for(i=0 ; i +- uint UInt::SubInt(uint value, uint index) +- { +- uint i, c; +- +- TTMATH_ASSERT( index < value_size ) +- +- +- c = SubTwoWords(table[index], value, 0, &table[index]); +- +- for(i=index+1 ; i +- uint UInt::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) +- { +- uint i, c = 0; +- +- TTMATH_ASSERT( ss1_size >= ss2_size ) +- +- for(i=0 ; i +- uint UInt::Rcl2_one(uint c) +- { +- uint i, new_c; +- +- if( c != 0 ) +- c = 1; +- +- for(i=0 ; i this -> return value +- +- the highest *bit* will be held the 'c' and +- the state of one additional bit (on the right hand side) +- will be returned +- +- for example: +- let this is 000000010 +- after Rcr2_one(1) there'll be 100000001 and Rcr2_one returns 0 +- */ +- template +- uint UInt::Rcr2_one(uint c) +- { +- sint i; // signed i +- uint new_c; +- +- if( c != 0 ) +- c = TTMATH_UINT_HIGHEST_BIT; +- +- for(i=sint(value_size)-1 ; i>=0 ; --i) +- { +- new_c = (table[i] & 1) ? TTMATH_UINT_HIGHEST_BIT : 0; +- table[i] = (table[i] >> 1) | c; +- c = new_c; +- } +- +- c = (c != 0)? 1 : 0; +- +- TTMATH_LOGC("UInt::Rcr2_one", c) +- +- return c; +- } +- +- +- +- +- /*! +- this method moves all bits into the left hand side +- return value <- this <- c +- +- the lowest *bits* will be held the 'c' and +- the state of one additional bit (on the left hand side) +- will be returned +- +- for example: +- let this is 001010000 +- after Rcl2(3, 1) there'll be 010000111 and Rcl2 returns 1 +- */ +- template +- uint UInt::Rcl2(uint bits, uint c) +- { +- TTMATH_ASSERT( bits>0 && bits> move; +- +- for(i=0 ; i> move; +- table[i] = (table[i] << bits) | c; +- c = new_c; +- } +- +- TTMATH_LOGC("UInt::Rcl2", (c & 1)) +- +- return (c & 1); +- } +- +- +- +- +- /*! +- this method moves all bits into the right hand side +- C -> this -> return value +- +- the highest *bits* will be held the 'c' and +- the state of one additional bit (on the right hand side) +- will be returned +- +- for example: +- let this is 000000010 +- after Rcr2(2, 1) there'll be 110000000 and Rcr2 returns 1 +- */ +- template +- uint UInt::Rcr2(uint bits, uint c) +- { +- TTMATH_ASSERT( bits>0 && bits=0 ; --i) +- { +- new_c = table[i] << move; +- table[i] = (table[i] >> bits) | c; +- c = new_c; +- } +- +- c = (c & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0; +- +- TTMATH_LOGC("UInt::Rcr2", c) +- +- return c; +- } +- +- +- +- +- /*! +- this method returns the number of the highest set bit in x +- if the 'x' is zero this method returns '-1' +- */ +- template +- sint UInt::FindLeadingBitInWord(uint x) +- { +- if( x == 0 ) +- return -1; +- +- uint bit = TTMATH_BITS_PER_UINT - 1; +- +- while( (x & TTMATH_UINT_HIGHEST_BIT) == 0 ) +- { +- x = x << 1; +- --bit; +- } +- +- return bit; +- } +- +- +- +- /*! +- this method returns the number of the highest set bit in x +- if the 'x' is zero this method returns '-1' +- */ +- template +- sint UInt::FindLowestBitInWord(uint x) +- { +- if( x == 0 ) +- return -1; +- +- uint bit = 0; +- +- while( (x & 1) == 0 ) +- { +- x = x >> 1; +- ++bit; +- } +- +- return bit; +- } +- +- +- +- /*! +- this method sets a special bit in the 'value' +- and returns the last state of the bit (zero or one) +- +- bit is from <0,TTMATH_BITS_PER_UINT-1> +- +- e.g. +- uint x = 100; +- uint bit = SetBitInWord(x, 3); +- now: x = 108 and bit = 0 +- */ +- template +- uint UInt::SetBitInWord(uint & value, uint bit) +- { +- TTMATH_ASSERT( bit < TTMATH_BITS_PER_UINT ) +- +- uint mask = 1; +- +- if( bit > 0 ) +- mask = mask << bit; +- +- uint last = value & mask; +- value = value | mask; +- +- return (last != 0) ? 1 : 0; +- } +- +- +- +- +- +- +- /*! +- * +- * Multiplication +- * +- * +- */ +- +- +- /*! +- multiplication: result_high:result_low = a * b +- result_high - higher word of the result +- result_low - lower word of the result +- +- this methos never returns a carry +- this method is used in the second version of the multiplication algorithms +- */ +- template +- void UInt::MulTwoWords(uint a, uint b, uint * result_high, uint * result_low) +- { +- #ifdef TTMATH_PLATFORM32 +- +- /* +- on 32bit platforms we have defined 'unsigned long long int' type known as 'ulint' in ttmath namespace +- this type has 64 bits, then we're using only one multiplication: 32bit * 32bit = 64bit +- */ +- +- union uint_ +- { +- struct +- { +- uint low; // 32 bits +- uint high; // 32 bits +- } u_; +- +- ulint u; // 64 bits +- } res; +- +- res.u = ulint(a) * ulint(b); // multiply two 32bit words, the result has 64 bits +- +- *result_high = res.u_.high; +- *result_low = res.u_.low; +- +- #else +- +- /* +- 64 bits platforms +- +- we don't have a native type which has 128 bits +- then we're splitting 'a' and 'b' to 4 parts (high and low halves) +- and using 4 multiplications (with additions and carry correctness) +- */ +- +- uint_ a_; +- uint_ b_; +- uint_ res_high1, res_high2; +- uint_ res_low1, res_low2; +- +- a_.u = a; +- b_.u = b; +- +- /* +- the multiplication is as follows (schoolbook algorithm with O(n^2) ): +- +- 32 bits 32 bits +- +- +--------------------------------+ +- | a_.u_.high | a_.u_.low | +- +--------------------------------+ +- | b_.u_.high | b_.u_.low | +- +--------------------------------+--------------------------------+ +- | res_high1.u | res_low1.u | +- +--------------------------------+--------------------------------+ +- | res_high2.u | res_low2.u | +- +--------------------------------+--------------------------------+ +- +- 64 bits 64 bits +- */ +- +- +- uint_ temp; +- +- res_low1.u = uint(b_.u_.low) * uint(a_.u_.low); +- +- temp.u = uint(res_low1.u_.high) + uint(b_.u_.low) * uint(a_.u_.high); +- res_low1.u_.high = temp.u_.low; +- res_high1.u_.low = temp.u_.high; +- res_high1.u_.high = 0; +- +- res_low2.u_.low = 0; +- temp.u = uint(b_.u_.high) * uint(a_.u_.low); +- res_low2.u_.high = temp.u_.low; +- +- res_high2.u = uint(b_.u_.high) * uint(a_.u_.high) + uint(temp.u_.high); +- +- uint c = AddTwoWords(res_low1.u, res_low2.u, 0, &res_low2.u); +- AddTwoWords(res_high1.u, res_high2.u, c, &res_high2.u); // there is no carry from here +- +- *result_high = res_high2.u; +- *result_low = res_low2.u; +- +- #endif +- } +- +- +- +- +- /*! +- * +- * Division +- * +- * +- */ +- +- +- /*! +- this method calculates 64bits word a:b / 32bits c (a higher, b lower word) +- r = a:b / c and rest - remainder +- +- * +- * WARNING: +- * the c has to be suitably large for the result being keeped in one word, +- * if c is equal zero there'll be a hardware interruption (0) +- * and probably the end of your program +- * +- */ +- template +- void UInt::DivTwoWords(uint a, uint b, uint c, uint * r, uint * rest) +- { +- // (a < c ) for the result to be one word +- TTMATH_ASSERT( c != 0 && a < c ) +- +- #ifdef TTMATH_PLATFORM32 +- +- union +- { +- struct +- { +- uint low; // 32 bits +- uint high; // 32 bits +- } u_; +- +- ulint u; // 64 bits +- } ab; +- +- ab.u_.high = a; +- ab.u_.low = b; +- +- *r = uint(ab.u / c); +- *rest = uint(ab.u % c); +- +- #else +- +- uint_ c_; +- c_.u = c; +- +- +- if( a == 0 ) +- { +- *r = b / c; +- *rest = b % c; +- } +- else +- if( c_.u_.high == 0 ) +- { +- // higher half of 'c' is zero +- // then higher half of 'a' is zero too (look at the asserts at the beginning - 'a' is smaller than 'c') +- uint_ a_, b_, res_, temp1, temp2; +- +- a_.u = a; +- b_.u = b; +- +- temp1.u_.high = a_.u_.low; +- temp1.u_.low = b_.u_.high; +- +- res_.u_.high = (unsigned int)(temp1.u / c); +- temp2.u_.high = (unsigned int)(temp1.u % c); +- temp2.u_.low = b_.u_.low; +- +- res_.u_.low = (unsigned int)(temp2.u / c); +- *rest = temp2.u % c; +- +- *r = res_.u; +- } +- else +- { +- return DivTwoWords2(a, b, c, r, rest); +- } +- +- #endif +- } +- +- +-#ifdef TTMATH_PLATFORM64 +- +- +- /*! +- this method is available only on 64bit platforms +- +- the same algorithm like the third division algorithm in ttmathuint.h +- but now with the radix=2^32 +- */ +- template +- void UInt::DivTwoWords2(uint a, uint b, uint c, uint * r, uint * rest) +- { +- // a is not zero +- // c_.u_.high is not zero +- +- uint_ a_, b_, c_, u_, q_; +- unsigned int u3; // 32 bit +- +- a_.u = a; +- b_.u = b; +- c_.u = c; +- +- // normalizing +- uint d = DivTwoWordsNormalize(a_, b_, c_); +- +- // loop from j=1 to j=0 +- // the first step (for j=2) is skipped because our result is only in one word, +- // (first 'q' were 0 and nothing would be changed) +- u_.u_.high = a_.u_.high; +- u_.u_.low = a_.u_.low; +- u3 = b_.u_.high; +- q_.u_.high = DivTwoWordsCalculate(u_, u3, c_); +- MultiplySubtract(u_, u3, q_.u_.high, c_); +- +- u_.u_.high = u_.u_.low; +- u_.u_.low = u3; +- u3 = b_.u_.low; +- q_.u_.low = DivTwoWordsCalculate(u_, u3, c_); +- MultiplySubtract(u_, u3, q_.u_.low, c_); +- +- *r = q_.u; +- +- // unnormalizing for the remainder +- u_.u_.high = u_.u_.low; +- u_.u_.low = u3; +- *rest = DivTwoWordsUnnormalize(u_.u, d); +- } +- +- +- +- +- template +- uint UInt::DivTwoWordsNormalize(uint_ & a_, uint_ & b_, uint_ & c_) +- { +- uint d = 0; +- +- for( ; (c_.u & TTMATH_UINT_HIGHEST_BIT) == 0 ; ++d ) +- { +- c_.u = c_.u << 1; +- +- uint bc = b_.u & TTMATH_UINT_HIGHEST_BIT; // carry from 'b' +- +- b_.u = b_.u << 1; +- a_.u = a_.u << 1; // carry bits from 'a' are simply skipped +- +- if( bc ) +- a_.u = a_.u | 1; +- } +- +- return d; +- } +- +- +- template +- uint UInt::DivTwoWordsUnnormalize(uint u, uint d) +- { +- if( d == 0 ) +- return u; +- +- u = u >> d; +- +- return u; +- } +- +- +- template +- unsigned int UInt::DivTwoWordsCalculate(uint_ u_, unsigned int u3, uint_ v_) +- { +- bool next_test; +- uint_ qp_, rp_, temp_; +- +- qp_.u = u_.u / uint(v_.u_.high); +- rp_.u = u_.u % uint(v_.u_.high); +- +- TTMATH_ASSERT( qp_.u_.high==0 || qp_.u_.high==1 ) +- +- do +- { +- bool decrease = false; +- +- if( qp_.u_.high == 1 ) +- decrease = true; +- else +- { +- temp_.u_.high = rp_.u_.low; +- temp_.u_.low = u3; +- +- if( qp_.u * uint(v_.u_.low) > temp_.u ) +- decrease = true; +- } +- +- next_test = false; +- +- if( decrease ) +- { +- --qp_.u; +- rp_.u += v_.u_.high; +- +- if( rp_.u_.high == 0 ) +- next_test = true; +- } +- } +- while( next_test ); +- +- return qp_.u_.low; +- } +- +- +- template +- void UInt::MultiplySubtract(uint_ & u_, unsigned int & u3, unsigned int & q, uint_ v_) +- { +- uint_ temp_; +- +- uint res_high; +- uint res_low; +- +- MulTwoWords(v_.u, q, &res_high, &res_low); +- +- uint_ sub_res_high_; +- uint_ sub_res_low_; +- +- temp_.u_.high = u_.u_.low; +- temp_.u_.low = u3; +- +- uint c = SubTwoWords(temp_.u, res_low, 0, &sub_res_low_.u); +- +- temp_.u_.high = 0; +- temp_.u_.low = u_.u_.high; +- c = SubTwoWords(temp_.u, res_high, c, &sub_res_high_.u); +- +- if( c ) +- { +- --q; +- +- c = AddTwoWords(sub_res_low_.u, v_.u, 0, &sub_res_low_.u); +- AddTwoWords(sub_res_high_.u, 0, c, &sub_res_high_.u); +- } +- +- u_.u_.high = sub_res_high_.u_.low; +- u_.u_.low = sub_res_low_.u_.high; +- u3 = sub_res_low_.u_.low; +- } +- +-#endif // #ifdef TTMATH_PLATFORM64 +- +- +- +-} //namespace +- +- +-#endif //ifdef TTMATH_NOASM +-#endif +- +- +- +- +diff --git a/extern/ttmath/ttmathuint_x86.h b/extern/ttmath/ttmathuint_x86.h +deleted file mode 100644 +index 1dd087f524..0000000000 +--- a/extern/ttmath/ttmathuint_x86.h ++++ /dev/null +@@ -1,1602 +0,0 @@ +-/* +- * This file is a part of TTMath Bignum Library +- * and is distributed under the (new) BSD licence. +- * Author: Tomasz Sowa +- */ +- +-/* +- * Copyright (c) 2006-2009, Tomasz Sowa +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * +- * * Redistributions of source code must retain the above copyright notice, +- * this list of conditions and the following disclaimer. +- * +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * +- * * Neither the name Tomasz Sowa nor the names of contributors to this +- * project may be used to endorse or promote products derived +- * from this software without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +- * THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +- +- +-#ifndef headerfilettmathuint_x86 +-#define headerfilettmathuint_x86 +- +- +-#ifndef TTMATH_NOASM +-#ifdef TTMATH_PLATFORM32 +- +- +-/*! +- \file ttmathuint_x86.h +- \brief template class UInt with assembler code for 32bit x86 processors +- +- this file is included at the end of ttmathuint.h +-*/ +- +- +- +-/*! +- \brief a namespace for the TTMath library +-*/ +-namespace ttmath +-{ +- +- /*! +- returning the string represents the currect type of the library +- we have following types: +- asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits) +- asm_gcc_32 - with asm code designed for GCC (32 bits) +- asm_vc_64 - with asm for VC (64 bit) +- asm_gcc_64 - with asm for GCC (64 bit) +- no_asm_32 - pure C++ version (32 bit) - without any asm code +- no_asm_64 - pure C++ version (64 bit) - without any asm code +- */ +- template +- const char * UInt::LibTypeStr() +- { +- #ifndef __GNUC__ +- static const char info[] = "asm_vc_32"; +- #endif +- +- #ifdef __GNUC__ +- static const char info[] = "asm_gcc_32"; +- #endif +- +- return info; +- } +- +- +- /*! +- returning the currect type of the library +- */ +- template +- LibTypeCode UInt::LibType() +- { +- #ifndef __GNUC__ +- LibTypeCode info = asm_vc_32; +- #endif +- +- #ifdef __GNUC__ +- LibTypeCode info = asm_gcc_32; +- #endif +- +- return info; +- } +- +- +- +- /*! +- * +- * basic mathematic functions +- * +- */ +- +- +- /*! +- adding ss2 to the this and adding carry if it's defined +- (this = this + ss2 + c) +- +- c must be zero or one (might be a bigger value than 1) +- function returns carry (1) (if it has been) +- */ +- template +- uint UInt::Add(const UInt & ss2, uint c) +- { +- uint b = value_size; +- uint * p1 = table; +- uint * p2 = const_cast(ss2.table); +- +- // we don't have to use TTMATH_REFERENCE_ASSERT here +- // this algorithm doesn't require it +- +- #ifndef __GNUC__ +- +- // this part might be compiled with for example visual c +- +- __asm +- { +- push eax +- push ebx +- push ecx +- push edx +- push esi +- +- mov ecx,[b] +- +- mov ebx,[p1] +- mov esi,[p2] +- +- xor edx,edx // edx=0 +- mov eax,[c] +- neg eax // CF=1 if rax!=0 , CF=0 if rax==0 +- +- ttmath_loop: +- mov eax,[esi+edx*4] +- adc [ebx+edx*4],eax +- +- inc edx +- dec ecx +- jnz ttmath_loop +- +- adc ecx, ecx +- mov [c], ecx +- +- pop esi +- pop edx +- pop ecx +- pop ebx +- pop eax +- } +- +- +- +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy, dummy2; +- // this part should be compiled with gcc +- +- __asm__ __volatile__( +- +- "xorl %%edx, %%edx \n" +- "negl %%eax \n" // CF=1 if rax!=0 , CF=0 if rax==0 +- +- "1: \n" +- "movl (%%esi,%%edx,4), %%eax \n" +- "adcl %%eax, (%%ebx,%%edx,4) \n" +- +- "incl %%edx \n" +- "decl %%ecx \n" +- "jnz 1b \n" +- +- "adc %%ecx, %%ecx \n" +- +- : "=c" (c), "=a" (dummy), "=d" (dummy2) +- : "0" (b), "1" (c), "b" (p1), "S" (p2) +- : "cc", "memory" ); +- #endif +- +- TTMATH_LOGC("UInt::Add", c) +- +- return c; +- } +- +- +- +- /*! +- adding one word (at a specific position) +- and returning a carry (if it has been) +- +- e.g. +- +- if we've got (value_size=3): +- table[0] = 10; +- table[1] = 30; +- table[2] = 5; +- and we call: +- AddInt(2,1) +- then it'll be: +- table[0] = 10; +- table[1] = 30 + 2; +- table[2] = 5; +- +- of course if there was a carry from table[2] it would be returned +- */ +- template +- uint UInt::AddInt(uint value, uint index) +- { +- uint b = value_size; +- uint * p1 = table; +- uint c; +- +- TTMATH_ASSERT( index < value_size ) +- +- #ifndef __GNUC__ +- +- __asm +- { +- push eax +- push ebx +- push ecx +- push edx +- +- mov ecx, [b] +- sub ecx, [index] +- +- mov edx, [index] +- mov ebx, [p1] +- +- mov eax, [value] +- +- ttmath_loop: +- add [ebx+edx*4], eax +- jnc ttmath_end +- +- mov eax, 1 +- inc edx +- dec ecx +- jnz ttmath_loop +- +- ttmath_end: +- setc al +- movzx edx, al +- mov [c], edx +- +- pop edx +- pop ecx +- pop ebx +- pop eax +- } +- +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy, dummy2; +- +- __asm__ __volatile__( +- +- "subl %%edx, %%ecx \n" +- +- "1: \n" +- "addl %%eax, (%%ebx,%%edx,4) \n" +- "jnc 2f \n" +- +- "movl $1, %%eax \n" +- "incl %%edx \n" +- "decl %%ecx \n" +- "jnz 1b \n" +- +- "2: \n" +- "setc %%al \n" +- "movzx %%al, %%edx \n" +- +- : "=d" (c), "=a" (dummy), "=c" (dummy2) +- : "0" (index), "1" (value), "2" (b), "b" (p1) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_LOGC("UInt::AddInt", c) +- +- return c; +- } +- +- +- +- +- /*! +- adding only two unsigned words to the existing value +- and these words begin on the 'index' position +- (it's used in the multiplication algorithm 2) +- +- index should be equal or smaller than value_size-2 (index <= value_size-2) +- x1 - lower word, x2 - higher word +- +- for example if we've got value_size equal 4 and: +- table[0] = 3 +- table[1] = 4 +- table[2] = 5 +- table[3] = 6 +- then let +- x1 = 10 +- x2 = 20 +- and +- index = 1 +- +- the result of this method will be: +- table[0] = 3 +- table[1] = 4 + x1 = 14 +- table[2] = 5 + x2 = 25 +- table[3] = 6 +- +- and no carry at the end of table[3] +- +- (of course if there was a carry in table[2](5+20) then +- this carry would be passed to the table[3] etc.) +- */ +- template +- uint UInt::AddTwoInts(uint x2, uint x1, uint index) +- { +- uint b = value_size; +- uint * p1 = table; +- uint c; +- +- TTMATH_ASSERT( index < value_size - 1 ) +- +- #ifndef __GNUC__ +- __asm +- { +- push eax +- push ebx +- push ecx +- push edx +- +- mov ecx, [b] +- sub ecx, [index] +- +- mov ebx, [p1] +- mov edx, [index] +- +- mov eax, [x1] +- add [ebx+edx*4], eax +- inc edx +- dec ecx +- +- mov eax, [x2] +- +- ttmath_loop: +- adc [ebx+edx*4], eax +- jnc ttmath_end +- +- mov eax, 0 +- inc edx +- dec ecx +- jnz ttmath_loop +- +- ttmath_end: +- setc al +- movzx edx, al +- mov [c], edx +- +- pop edx +- pop ecx +- pop ebx +- pop eax +- +- } +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy, dummy2; +- +- __asm__ __volatile__( +- +- "subl %%edx, %%ecx \n" +- +- "addl %%esi, (%%ebx,%%edx,4) \n" +- "incl %%edx \n" +- "decl %%ecx \n" +- +- "1: \n" +- "adcl %%eax, (%%ebx,%%edx,4) \n" +- "jnc 2f \n" +- +- "mov $0, %%eax \n" +- "incl %%edx \n" +- "decl %%ecx \n" +- "jnz 1b \n" +- +- "2: \n" +- "setc %%al \n" +- "movzx %%al, %%eax \n" +- +- : "=a" (c), "=c" (dummy), "=d" (dummy2) +- : "0" (x2), "1" (b), "2" (index), "b" (p1), "S" (x1) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_LOGC("UInt::AddTwoInts", c) +- +- return c; +- } +- +- +- +- /*! +- this static method addes one vector to the other +- 'ss1' is larger in size or equal to 'ss2' +- +- ss1 points to the first (larger) vector +- ss2 points to the second vector +- ss1_size - size of the ss1 (and size of the result too) +- ss2_size - size of the ss2 +- result - is the result vector (which has size the same as ss1: ss1_size) +- +- Example: ss1_size is 5, ss2_size is 3 +- ss1: ss2: result (output): +- 5 1 5+1 +- 4 3 4+3 +- 2 7 2+7 +- 6 6 +- 9 9 +- of course the carry is propagated and will be returned from the last item +- (this method is used by the Karatsuba multiplication algorithm) +- */ +- template +- uint UInt::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) +- { +- TTMATH_ASSERT( ss1_size >= ss2_size ) +- +- uint rest = ss1_size - ss2_size; +- uint c; +- +- #ifndef __GNUC__ +- +- // this part might be compiled with for example visual c +- __asm +- { +- pushad +- +- mov ecx, [ss2_size] +- xor edx, edx // edx = 0, cf = 0 +- +- mov esi, [ss1] +- mov ebx, [ss2] +- mov edi, [result] +- +- ttmath_loop: +- mov eax, [esi+edx*4] +- adc eax, [ebx+edx*4] +- mov [edi+edx*4], eax +- +- inc edx +- dec ecx +- jnz ttmath_loop +- +- adc ecx, ecx // ecx has the cf state +- +- mov ebx, [rest] +- or ebx, ebx +- jz ttmath_end +- +- xor ebx, ebx // ebx = 0 +- neg ecx // setting cf from ecx +- mov ecx, [rest] // ecx is != 0 +- +- ttmath_loop2: +- mov eax, [esi+edx*4] +- adc eax, ebx +- mov [edi+edx*4], eax +- +- inc edx +- dec ecx +- jnz ttmath_loop2 +- +- adc ecx, ecx +- +- ttmath_end: +- mov [c], ecx +- +- popad +- } +- +- #endif +- +- +- #ifdef __GNUC__ +- +- // this part should be compiled with gcc +- uint dummy1, dummy2, dummy3; +- +- __asm__ __volatile__( +- "push %%edx \n" +- "xor %%edx, %%edx \n" // edx = 0, cf = 0 +- "1: \n" +- "mov (%%esi,%%edx,4), %%eax \n" +- "adc (%%ebx,%%edx,4), %%eax \n" +- "mov %%eax, (%%edi,%%edx,4) \n" +- +- "inc %%edx \n" +- "dec %%ecx \n" +- "jnz 1b \n" +- +- "adc %%ecx, %%ecx \n" // ecx has the cf state +- "pop %%eax \n" // eax = rest +- +- "or %%eax, %%eax \n" +- "jz 3f \n" +- +- "xor %%ebx, %%ebx \n" // ebx = 0 +- "neg %%ecx \n" // setting cf from ecx +- "mov %%eax, %%ecx \n" // ecx=rest and is != 0 +- "2: \n" +- "mov (%%esi, %%edx, 4), %%eax \n" +- "adc %%ebx, %%eax \n" +- "mov %%eax, (%%edi, %%edx, 4) \n" +- +- "inc %%edx \n" +- "dec %%ecx \n" +- "jnz 2b \n" +- +- "adc %%ecx, %%ecx \n" +- "3: \n" +- +- : "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3) +- : "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_VECTOR_LOGC("UInt::AddVector", c, result, ss1_size) +- +- return c; +- } +- +- +- /*! +- subtracting ss2 from the 'this' and subtracting +- carry if it has been defined +- (this = this - ss2 - c) +- +- c must be zero or one (might be a bigger value than 1) +- function returns carry (1) (if it has been) +- */ +- template +- uint UInt::Sub(const UInt & ss2, uint c) +- { +- uint b = value_size; +- uint * p1 = table; +- uint * p2 = const_cast(ss2.table); +- +- // we don't have to use TTMATH_REFERENCE_ASSERT here +- // this algorithm doesn't require it +- +- #ifndef __GNUC__ +- +- __asm +- { +- push eax +- push ebx +- push ecx +- push edx +- push esi +- +- mov ecx,[b] +- +- mov ebx,[p1] +- mov esi,[p2] +- +- xor edx,edx // edx=0 +- mov eax,[c] +- neg eax // CF=1 if rax!=0 , CF=0 if rax==0 +- +- ttmath_loop: +- mov eax,[esi+edx*4] +- sbb [ebx+edx*4],eax +- +- inc edx +- dec ecx +- jnz ttmath_loop +- +- adc ecx, ecx +- mov [c], ecx +- +- pop esi +- pop edx +- pop ecx +- pop ebx +- pop eax +- } +- +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy, dummy2; +- +- __asm__ __volatile__( +- +- "xorl %%edx, %%edx \n" +- "negl %%eax \n" // CF=1 if rax!=0 , CF=0 if rax==0 +- +- "1: \n" +- "movl (%%esi,%%edx,4), %%eax \n" +- "sbbl %%eax, (%%ebx,%%edx,4) \n" +- +- "incl %%edx \n" +- "decl %%ecx \n" +- "jnz 1b \n" +- +- "adc %%ecx, %%ecx \n" +- +- : "=c" (c), "=a" (dummy), "=d" (dummy2) +- : "0" (b), "1" (c), "b" (p1), "S" (p2) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_LOGC("UInt::Sub", c) +- +- return c; +- } +- +- +- +- +- /*! +- this method subtracts one word (at a specific position) +- and returns a carry (if it was) +- +- e.g. +- +- if we've got (value_size=3): +- table[0] = 10; +- table[1] = 30; +- table[2] = 5; +- and we call: +- SubInt(2,1) +- then it'll be: +- table[0] = 10; +- table[1] = 30 - 2; +- table[2] = 5; +- +- of course if there was a carry from table[2] it would be returned +- */ +- template +- uint UInt::SubInt(uint value, uint index) +- { +- uint b = value_size; +- uint * p1 = table; +- uint c; +- +- TTMATH_ASSERT( index < value_size ) +- +- #ifndef __GNUC__ +- +- __asm +- { +- push eax +- push ebx +- push ecx +- push edx +- +- mov ecx, [b] +- sub ecx, [index] +- +- mov edx, [index] +- mov ebx, [p1] +- +- mov eax, [value] +- +- ttmath_loop: +- sub [ebx+edx*4], eax +- jnc ttmath_end +- +- mov eax, 1 +- inc edx +- dec ecx +- jnz ttmath_loop +- +- ttmath_end: +- setc al +- movzx edx, al +- mov [c], edx +- +- pop edx +- pop ecx +- pop ebx +- pop eax +- } +- +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy, dummy2; +- +- __asm__ __volatile__( +- +- "subl %%edx, %%ecx \n" +- +- "1: \n" +- "subl %%eax, (%%ebx,%%edx,4) \n" +- "jnc 2f \n" +- +- "movl $1, %%eax \n" +- "incl %%edx \n" +- "decl %%ecx \n" +- "jnz 1b \n" +- +- "2: \n" +- "setc %%al \n" +- "movzx %%al, %%edx \n" +- +- : "=d" (c), "=a" (dummy), "=c" (dummy2) +- : "0" (index), "1" (value), "2" (b), "b" (p1) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_LOGC("UInt::SubInt", c) +- +- return c; +- } +- +- +- +- /*! +- this static method subtractes one vector from the other +- 'ss1' is larger in size or equal to 'ss2' +- +- ss1 points to the first (larger) vector +- ss2 points to the second vector +- ss1_size - size of the ss1 (and size of the result too) +- ss2_size - size of the ss2 +- result - is the result vector (which has size the same as ss1: ss1_size) +- +- Example: ss1_size is 5, ss2_size is 3 +- ss1: ss2: result (output): +- 5 1 5-1 +- 4 3 4-3 +- 2 7 2-7 +- 6 6-1 (the borrow from previous item) +- 9 9 +- return (carry): 0 +- of course the carry (borrow) is propagated and will be returned from the last item +- (this method is used by the Karatsuba multiplication algorithm) +- */ +- template +- uint UInt::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) +- { +- TTMATH_ASSERT( ss1_size >= ss2_size ) +- +- uint rest = ss1_size - ss2_size; +- uint c; +- +- #ifndef __GNUC__ +- +- // this part might be compiled with for example visual c +- +- /* +- the asm code is nearly the same as in AddVector +- only two instructions 'adc' are changed to 'sbb' +- */ +- __asm +- { +- pushad +- +- mov ecx, [ss2_size] +- xor edx, edx // edx = 0, cf = 0 +- +- mov esi, [ss1] +- mov ebx, [ss2] +- mov edi, [result] +- +- ttmath_loop: +- mov eax, [esi+edx*4] +- sbb eax, [ebx+edx*4] +- mov [edi+edx*4], eax +- +- inc edx +- dec ecx +- jnz ttmath_loop +- +- adc ecx, ecx // ecx has the cf state +- +- mov ebx, [rest] +- or ebx, ebx +- jz ttmath_end +- +- xor ebx, ebx // ebx = 0 +- neg ecx // setting cf from ecx +- mov ecx, [rest] // ecx is != 0 +- +- ttmath_loop2: +- mov eax, [esi+edx*4] +- sbb eax, ebx +- mov [edi+edx*4], eax +- +- inc edx +- dec ecx +- jnz ttmath_loop2 +- +- adc ecx, ecx +- +- ttmath_end: +- mov [c], ecx +- +- popad +- } +- +- #endif +- +- +- #ifdef __GNUC__ +- +- // this part should be compiled with gcc +- uint dummy1, dummy2, dummy3; +- +- __asm__ __volatile__( +- "push %%edx \n" +- "xor %%edx, %%edx \n" // edx = 0, cf = 0 +- "1: \n" +- "mov (%%esi,%%edx,4), %%eax \n" +- "sbb (%%ebx,%%edx,4), %%eax \n" +- "mov %%eax, (%%edi,%%edx,4) \n" +- +- "inc %%edx \n" +- "dec %%ecx \n" +- "jnz 1b \n" +- +- "adc %%ecx, %%ecx \n" // ecx has the cf state +- "pop %%eax \n" // eax = rest +- +- "or %%eax, %%eax \n" +- "jz 3f \n" +- +- "xor %%ebx, %%ebx \n" // ebx = 0 +- "neg %%ecx \n" // setting cf from ecx +- "mov %%eax, %%ecx \n" // ecx=rest and is != 0 +- "2: \n" +- "mov (%%esi, %%edx, 4), %%eax \n" +- "sbb %%ebx, %%eax \n" +- "mov %%eax, (%%edi, %%edx, 4) \n" +- +- "inc %%edx \n" +- "dec %%ecx \n" +- "jnz 2b \n" +- +- "adc %%ecx, %%ecx \n" +- "3: \n" +- +- : "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3) +- : "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_VECTOR_LOGC("UInt::SubVector", c, result, ss1_size) +- +- return c; +- } +- +- +- +- /*! +- this method moves all bits into the left hand side +- return value <- this <- c +- +- the lowest *bit* will be held the 'c' and +- the state of one additional bit (on the left hand side) +- will be returned +- +- for example: +- let this is 001010000 +- after Rcl2_one(1) there'll be 010100001 and Rcl2_one returns 0 +- */ +- template +- uint UInt::Rcl2_one(uint c) +- { +- uint b = value_size; +- uint * p1 = table; +- +- #ifndef __GNUC__ +- __asm +- { +- push ebx +- push ecx +- push edx +- +- mov ebx, [p1] +- xor edx, edx +- mov ecx, [c] +- neg ecx +- mov ecx, [b] +- +- ttmath_loop: +- rcl dword ptr [ebx+edx*4], 1 +- +- inc edx +- dec ecx +- jnz ttmath_loop +- +- adc ecx, ecx +- mov [c], ecx +- +- pop edx +- pop ecx +- pop ebx +- } +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy, dummy2; +- +- __asm__ __volatile__( +- +- "xorl %%edx, %%edx \n" // edx=0 +- "negl %%eax \n" // CF=1 if eax!=0 , CF=0 if eax==0 +- +- "1: \n" +- "rcll $1, (%%ebx, %%edx, 4) \n" +- +- "incl %%edx \n" +- "decl %%ecx \n" +- "jnz 1b \n" +- +- "adcl %%ecx, %%ecx \n" +- +- : "=c" (c), "=a" (dummy), "=d" (dummy2) +- : "0" (b), "1" (c), "b" (p1) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_LOGC("UInt::Rcl2_one", c) +- +- return c; +- } +- +- +- +- /*! +- this method moves all bits into the right hand side +- c -> this -> return value +- +- the highest *bit* will be held the 'c' and +- the state of one additional bit (on the right hand side) +- will be returned +- +- for example: +- let this is 000000010 +- after Rcr2_one(1) there'll be 100000001 and Rcr2_one returns 0 +- */ +- template +- uint UInt::Rcr2_one(uint c) +- { +- uint b = value_size; +- uint * p1 = table; +- +- #ifndef __GNUC__ +- __asm +- { +- push ebx +- push ecx +- +- mov ebx, [p1] +- mov ecx, [c] +- neg ecx +- mov ecx, [b] +- +- ttmath_loop: +- rcr dword ptr [ebx+ecx*4-4], 1 +- +- dec ecx +- jnz ttmath_loop +- +- adc ecx, ecx +- mov [c], ecx +- +- pop ecx +- pop ebx +- } +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy; +- +- __asm__ __volatile__( +- +- "negl %%eax \n" // CF=1 if eax!=0 , CF=0 if eax==0 +- +- "1: \n" +- "rcrl $1, -4(%%ebx, %%ecx, 4) \n" +- +- "decl %%ecx \n" +- "jnz 1b \n" +- +- "adcl %%ecx, %%ecx \n" +- +- : "=c" (c), "=a" (dummy) +- : "0" (b), "1" (c), "b" (p1) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_LOGC("UInt::Rcr2_one", c) +- +- return c; +- } +- +- +- +-#ifdef _MSC_VER +-#pragma warning (disable : 4731) +-//warning C4731: frame pointer register 'ebp' modified by inline assembly code +-#endif +- +- +- +- /*! +- this method moves all bits into the left hand side +- return value <- this <- c +- +- the lowest *bits* will be held the 'c' and +- the state of one additional bit (on the left hand side) +- will be returned +- +- for example: +- let this is 001010000 +- after Rcl2(3, 1) there'll be 010000111 and Rcl2 returns 1 +- */ +- template +- uint UInt::Rcl2(uint bits, uint c) +- { +- TTMATH_ASSERT( bits>0 && bits edx -> cf) (cl times) +- "movl %%edx, %%ebp \n" // ebp = edx = mask +- "movl %%esi, %%ecx \n" +- +- "xorl %%edx, %%edx \n" +- "movl %%edx, %%esi \n" +- "orl %%eax, %%eax \n" +- "cmovnz %%ebp, %%esi \n" // if(c) esi=mask else esi=0 +- +- "1: \n" +- "roll %%cl, (%%ebx,%%edx,4) \n" +- +- "movl (%%ebx,%%edx,4), %%eax \n" +- "andl %%ebp, %%eax \n" +- "xorl %%eax, (%%ebx,%%edx,4) \n" +- "orl %%esi, (%%ebx,%%edx,4) \n" +- "movl %%eax, %%esi \n" +- +- "incl %%edx \n" +- "decl %%edi \n" +- "jnz 1b \n" +- +- "and $1, %%eax \n" +- +- "pop %%ebp \n" +- +- : "=a" (c), "=D" (dummy), "=S" (dummy2), "=d" (dummy3) +- : "0" (c), "1" (b), "b" (p1), "c" (bits) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_LOGC("UInt::Rcl2", c) +- +- return c; +- } +- +- +- +- +- /*! +- this method moves all bits into the right hand side +- C -> this -> return value +- +- the highest *bits* will be held the 'c' and +- the state of one additional bit (on the right hand side) +- will be returned +- +- for example: +- let this is 000000010 +- after Rcr2(2, 1) there'll be 110000000 and Rcr2 returns 1 +- */ +- template +- uint UInt::Rcr2(uint bits, uint c) +- { +- TTMATH_ASSERT( bits>0 && bits +- sint UInt::FindLeadingBitInWord(uint x) +- { +- sint result; +- +- #ifndef __GNUC__ +- __asm +- { +- push eax +- push edx +- +- mov edx,-1 +- bsr eax,[x] +- cmovz eax,edx +- mov [result], eax +- +- pop edx +- pop eax +- } +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy; +- +- __asm__ ( +- +- "movl $-1, %1 \n" +- "bsrl %2, %0 \n" +- "cmovz %1, %0 \n" +- +- : "=r" (result), "=&r" (dummy) +- : "r" (x) +- : "cc" ); +- +- #endif +- +- return result; +- } +- +- +- +- /* +- this method returns the number of the smallest set bit in one 32-bit word +- if the 'x' is zero this method returns '-1' +- */ +- template +- sint UInt::FindLowestBitInWord(uint x) +- { +- sint result; +- +- #ifndef __GNUC__ +- __asm +- { +- push eax +- push edx +- +- mov edx,-1 +- bsf eax,[x] +- cmovz eax,edx +- mov [result], eax +- +- pop edx +- pop eax +- } +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy; +- +- __asm__ ( +- +- "movl $-1, %1 \n" +- "bsfl %2, %0 \n" +- "cmovz %1, %0 \n" +- +- : "=r" (result), "=&r" (dummy) +- : "r" (x) +- : "cc" ); +- +- #endif +- +- return result; +- } +- +- +- +- /*! +- this method sets a special bit in the 'value' +- and returns the last state of the bit (zero or one) +- +- bit is from <0,31> +- e.g. +- uint x = 100; +- uint bit = SetBitInWord(x, 3); +- now: x = 108 and bit = 0 +- */ +- template +- uint UInt::SetBitInWord(uint & value, uint bit) +- { +- TTMATH_ASSERT( bit < TTMATH_BITS_PER_UINT ) +- +- uint old_bit; +- uint v = value; +- +- #ifndef __GNUC__ +- __asm +- { +- push ebx +- push eax +- +- mov eax, [v] +- mov ebx, [bit] +- bts eax, ebx +- mov [v], eax +- +- setc bl +- movzx ebx, bl +- mov [old_bit], ebx +- +- pop eax +- pop ebx +- } +- #endif +- +- +- #ifdef __GNUC__ +- __asm__ ( +- +- "btsl %%ebx, %%eax \n" +- "setc %%bl \n" +- "movzx %%bl, %%ebx \n" +- +- : "=a" (v), "=b" (old_bit) +- : "0" (v), "1" (bit) +- : "cc" ); +- +- #endif +- +- value = v; +- +- return old_bit; +- } +- +- +- +- +- /*! +- multiplication: result_high:result_low = a * b +- result_high - higher word of the result +- result_low - lower word of the result +- +- this methos never returns a carry +- this method is used in the second version of the multiplication algorithms +- */ +- template +- void UInt::MulTwoWords(uint a, uint b, uint * result_high, uint * result_low) +- { +- /* +- we must use these temporary variables in order to inform the compilator +- that value pointed with result1 and result2 has changed +- +- this has no effect in visual studio but it's useful when +- using gcc and options like -Ox +- */ +- uint result1_; +- uint result2_; +- +- #ifndef __GNUC__ +- +- __asm +- { +- push eax +- push edx +- +- mov eax, [a] +- mul dword ptr [b] +- +- mov [result2_], edx +- mov [result1_], eax +- +- pop edx +- pop eax +- } +- +- #endif +- +- +- #ifdef __GNUC__ +- +- __asm__ ( +- +- "mull %%edx \n" +- +- : "=a" (result1_), "=d" (result2_) +- : "0" (a), "1" (b) +- : "cc" ); +- +- #endif +- +- +- *result_low = result1_; +- *result_high = result2_; +- } +- +- +- +- +- +- /*! +- * +- * Division +- * +- * +- */ +- +- +- +- +- /*! +- this method calculates 64bits word a:b / 32bits c (a higher, b lower word) +- r = a:b / c and rest - remainder +- +- * +- * WARNING: +- * if r (one word) is too small for the result or c is equal zero +- * there'll be a hardware interruption (0) +- * and probably the end of your program +- * +- */ +- template +- void UInt::DivTwoWords(uint a, uint b, uint c, uint * r, uint * rest) +- { +- uint r_; +- uint rest_; +- /* +- these variables have similar meaning like those in +- the multiplication algorithm MulTwoWords +- */ +- +- TTMATH_ASSERT( c != 0 ) +- +- #ifndef __GNUC__ +- __asm +- { +- push eax +- push edx +- +- mov edx, [a] +- mov eax, [b] +- div dword ptr [c] +- +- mov [r_], eax +- mov [rest_], edx +- +- pop edx +- pop eax +- } +- #endif +- +- +- #ifdef __GNUC__ +- +- __asm__ ( +- +- "divl %%ecx \n" +- +- : "=a" (r_), "=d" (rest_) +- : "0" (b), "1" (a), "c" (c) +- : "cc" ); +- +- #endif +- +- +- *r = r_; +- *rest = rest_; +- +- } +- +- +- +-} //namespace +- +- +- +-#endif //ifdef TTMATH_PLATFORM32 +-#endif //ifndef TTMATH_NOASM +-#endif +diff --git a/extern/ttmath/ttmathuint_x86_64.h b/extern/ttmath/ttmathuint_x86_64.h +deleted file mode 100644 +index 188fc5e7bd..0000000000 +--- a/extern/ttmath/ttmathuint_x86_64.h ++++ /dev/null +@@ -1,1146 +0,0 @@ +-/* +- * This file is a part of TTMath Bignum Library +- * and is distributed under the (new) BSD licence. +- * Author: Tomasz Sowa +- */ +- +-/* +- * Copyright (c) 2006-2010, Tomasz Sowa +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * +- * * Redistributions of source code must retain the above copyright notice, +- * this list of conditions and the following disclaimer. +- * +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * +- * * Neither the name Tomasz Sowa nor the names of contributors to this +- * project may be used to endorse or promote products derived +- * from this software without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +- * THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +- +-#ifndef headerfilettmathuint_x86_64 +-#define headerfilettmathuint_x86_64 +- +- +-#ifndef TTMATH_NOASM +-#ifdef TTMATH_PLATFORM64 +- +- +-/*! +- \file ttmathuint_x86_64.h +- \brief template class UInt with assembler code for 64bit x86_64 processors +- +- this file is included at the end of ttmathuint.h +-*/ +- +-#ifndef __GNUC__ +-#include +-#endif +- +- +-namespace ttmath +-{ +- +- #ifndef __GNUC__ +- +- extern "C" +- { +- uint __fastcall ttmath_adc_x64(uint* p1, const uint* p2, uint nSize, uint c); +- uint __fastcall ttmath_addindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue); +- uint __fastcall ttmath_addindexed2_x64(uint* p1, uint nSize, uint nPos, uint nValue1, uint nValue2); +- uint __fastcall ttmath_addvector_x64(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result); +- uint __fastcall ttmath_sbb_x64(uint* p1, const uint* p2, uint nSize, uint c); +- uint __fastcall ttmath_subindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue); +- uint __fastcall ttmath_subvector_x64(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result); +- uint __fastcall ttmath_rcl_x64(uint* p1, uint nSize, uint nLowestBit); +- uint __fastcall ttmath_rcr_x64(uint* p1, uint nSize, uint nLowestBit); +- uint __fastcall ttmath_div_x64(uint* pnValHi, uint* pnValLo, uint nDiv); +- uint __fastcall ttmath_rcl2_x64(uint* p1, uint nSize, uint nBits, uint c); +- uint __fastcall ttmath_rcr2_x64(uint* p1, uint nSize, uint nBits, uint c); +- }; +- #endif +- +- +- /*! +- returning the string represents the currect type of the library +- we have following types: +- asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits) +- asm_gcc_32 - with asm code designed for GCC (32 bits) +- asm_vc_64 - with asm for VC (64 bit) +- asm_gcc_64 - with asm for GCC (64 bit) +- no_asm_32 - pure C++ version (32 bit) - without any asm code +- no_asm_64 - pure C++ version (64 bit) - without any asm code +- */ +- template +- const char * UInt::LibTypeStr() +- { +- #ifndef __GNUC__ +- static const char info[] = "asm_vc_64"; +- #endif +- +- #ifdef __GNUC__ +- static const char info[] = "asm_gcc_64"; +- #endif +- +- return info; +- } +- +- +- /*! +- returning the currect type of the library +- */ +- template +- LibTypeCode UInt::LibType() +- { +- #ifndef __GNUC__ +- LibTypeCode info = asm_vc_64; +- #endif +- +- #ifdef __GNUC__ +- LibTypeCode info = asm_gcc_64; +- #endif +- +- return info; +- } +- +- +- /*! +- * +- * basic mathematic functions +- * +- */ +- +- +- +- /*! +- this method adding ss2 to the this and adding carry if it's defined +- (this = this + ss2 + c) +- +- ***this method is created only on a 64bit platform*** +- +- c must be zero or one (might be a bigger value than 1) +- function returns carry (1) (if it was) +- */ +- template +- uint UInt::Add(const UInt & ss2, uint c) +- { +- uint b = value_size; +- uint * p1 = table; +- const uint * p2 = ss2.table; +- +- // we don't have to use TTMATH_REFERENCE_ASSERT here +- // this algorithm doesn't require it +- +- #ifndef __GNUC__ +- c = ttmath_adc_x64(p1,p2,b,c); +- #endif +- +- #ifdef __GNUC__ +- uint dummy, dummy2; +- +- /* +- this part should be compiled with gcc +- */ +- __asm__ __volatile__( +- +- "xorq %%rdx, %%rdx \n" +- "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 +- +- "1: \n" +- "movq (%%rsi,%%rdx,8), %%rax \n" +- "adcq %%rax, (%%rbx,%%rdx,8) \n" +- +- "incq %%rdx \n" +- "decq %%rcx \n" +- "jnz 1b \n" +- +- "adcq %%rcx, %%rcx \n" +- +- : "=c" (c), "=a" (dummy), "=d" (dummy2) +- : "0" (b), "1" (c), "b" (p1), "S" (p2) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_LOGC("UInt::Add", c) +- +- return c; +- } +- +- +- +- /*! +- this method adds one word (at a specific position) +- and returns a carry (if it was) +- +- ***this method is created only on a 64bit platform*** +- +- +- if we've got (value_size=3): +- table[0] = 10; +- table[1] = 30; +- table[2] = 5; +- and we call: +- AddInt(2,1) +- then it'll be: +- table[0] = 10; +- table[1] = 30 + 2; +- table[2] = 5; +- +- of course if there was a carry from table[2] it would be returned +- */ +- template +- uint UInt::AddInt(uint value, uint index) +- { +- uint b = value_size; +- uint * p1 = table; +- uint c; +- +- TTMATH_ASSERT( index < value_size ) +- +- #ifndef __GNUC__ +- c = ttmath_addindexed_x64(p1,b,index,value); +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy, dummy2; +- +- __asm__ __volatile__( +- +- "subq %%rdx, %%rcx \n" +- +- "1: \n" +- "addq %%rax, (%%rbx,%%rdx,8) \n" +- "jnc 2f \n" +- +- "movq $1, %%rax \n" +- "incq %%rdx \n" +- "decq %%rcx \n" +- "jnz 1b \n" +- +- "2: \n" +- "setc %%al \n" +- "movzx %%al, %%rdx \n" +- +- : "=d" (c), "=a" (dummy), "=c" (dummy2) +- : "0" (index), "1" (value), "2" (b), "b" (p1) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_LOGC("UInt::AddInt", c) +- +- return c; +- } +- +- +- +- /*! +- this method adds only two unsigned words to the existing value +- and these words begin on the 'index' position +- (it's used in the multiplication algorithm 2) +- +- ***this method is created only on a 64bit platform*** +- +- index should be equal or smaller than value_size-2 (index <= value_size-2) +- x1 - lower word, x2 - higher word +- +- for example if we've got value_size equal 4 and: +- table[0] = 3 +- table[1] = 4 +- table[2] = 5 +- table[3] = 6 +- then let +- x1 = 10 +- x2 = 20 +- and +- index = 1 +- +- the result of this method will be: +- table[0] = 3 +- table[1] = 4 + x1 = 14 +- table[2] = 5 + x2 = 25 +- table[3] = 6 +- +- and no carry at the end of table[3] +- +- (of course if there was a carry in table[2](5+20) then +- this carry would be passed to the table[3] etc.) +- */ +- template +- uint UInt::AddTwoInts(uint x2, uint x1, uint index) +- { +- uint b = value_size; +- uint * p1 = table; +- uint c; +- +- TTMATH_ASSERT( index < value_size - 1 ) +- +- #ifndef __GNUC__ +- c = ttmath_addindexed2_x64(p1,b,index,x1,x2); +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy, dummy2; +- +- __asm__ __volatile__( +- +- "subq %%rdx, %%rcx \n" +- +- "addq %%rsi, (%%rbx,%%rdx,8) \n" +- "incq %%rdx \n" +- "decq %%rcx \n" +- +- "1: \n" +- "adcq %%rax, (%%rbx,%%rdx,8) \n" +- "jnc 2f \n" +- +- "mov $0, %%rax \n" +- "incq %%rdx \n" +- "decq %%rcx \n" +- "jnz 1b \n" +- +- "2: \n" +- "setc %%al \n" +- "movzx %%al, %%rax \n" +- +- : "=a" (c), "=c" (dummy), "=d" (dummy2) +- : "0" (x2), "1" (b), "2" (index), "b" (p1), "S" (x1) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_LOGC("UInt::AddTwoInts", c) +- +- return c; +- } +- +- +- +- /*! +- this static method addes one vector to the other +- 'ss1' is larger in size or equal to 'ss2' +- +- ss1 points to the first (larger) vector +- ss2 points to the second vector +- ss1_size - size of the ss1 (and size of the result too) +- ss2_size - size of the ss2 +- result - is the result vector (which has size the same as ss1: ss1_size) +- +- Example: ss1_size is 5, ss2_size is 3 +- ss1: ss2: result (output): +- 5 1 5+1 +- 4 3 4+3 +- 2 7 2+7 +- 6 6 +- 9 9 +- of course the carry is propagated and will be returned from the last item +- (this method is used by the Karatsuba multiplication algorithm) +- */ +- template +- uint UInt::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) +- { +- TTMATH_ASSERT( ss1_size >= ss2_size ) +- +- uint c; +- +- #ifndef __GNUC__ +- c = ttmath_addvector_x64(ss1, ss2, ss1_size, ss2_size, result); +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy1, dummy2, dummy3; +- uint rest = ss1_size - ss2_size; +- +- // this part should be compiled with gcc +- +- __asm__ __volatile__( +- "mov %%rdx, %%r8 \n" +- "xor %%rdx, %%rdx \n" // rdx = 0, cf = 0 +- "1: \n" +- "mov (%%rsi,%%rdx,8), %%rax \n" +- "adc (%%rbx,%%rdx,8), %%rax \n" +- "mov %%rax, (%%rdi,%%rdx,8) \n" +- +- "inc %%rdx \n" +- "dec %%rcx \n" +- "jnz 1b \n" +- +- "adc %%rcx, %%rcx \n" // rcx has the cf state +- +- "or %%r8, %%r8 \n" +- "jz 3f \n" +- +- "xor %%rbx, %%rbx \n" // ebx = 0 +- "neg %%rcx \n" // setting cf from rcx +- "mov %%r8, %%rcx \n" // rcx=rest and is != 0 +- "2: \n" +- "mov (%%rsi, %%rdx, 8), %%rax \n" +- "adc %%rbx, %%rax \n" +- "mov %%rax, (%%rdi, %%rdx, 8) \n" +- +- "inc %%rdx \n" +- "dec %%rcx \n" +- "jnz 2b \n" +- +- "adc %%rcx, %%rcx \n" +- "3: \n" +- +- : "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3) +- : "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result) +- : "%r8", "cc", "memory" ); +- +- #endif +- +- TTMATH_VECTOR_LOGC("UInt::AddVector", c, result, ss1_size) +- +- return c; +- } +- +- +- +- /*! +- this method's subtracting ss2 from the 'this' and subtracting +- carry if it has been defined +- (this = this - ss2 - c) +- +- ***this method is created only on a 64bit platform*** +- +- c must be zero or one (might be a bigger value than 1) +- function returns carry (1) (if it was) +- */ +- template +- uint UInt::Sub(const UInt & ss2, uint c) +- { +- uint b = value_size; +- uint * p1 = table; +- const uint * p2 = ss2.table; +- +- // we don't have to use TTMATH_REFERENCE_ASSERT here +- // this algorithm doesn't require it +- +- #ifndef __GNUC__ +- c = ttmath_sbb_x64(p1,p2,b,c); +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy, dummy2; +- +- __asm__ __volatile__( +- +- "xorq %%rdx, %%rdx \n" +- "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 +- +- "1: \n" +- "movq (%%rsi,%%rdx,8), %%rax \n" +- "sbbq %%rax, (%%rbx,%%rdx,8) \n" +- +- "incq %%rdx \n" +- "decq %%rcx \n" +- "jnz 1b \n" +- +- "adcq %%rcx, %%rcx \n" +- +- : "=c" (c), "=a" (dummy), "=d" (dummy2) +- : "0" (b), "1" (c), "b" (p1), "S" (p2) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_LOGC("UInt::Sub", c) +- +- return c; +- } +- +- +- +- /*! +- this method subtracts one word (at a specific position) +- and returns a carry (if it was) +- +- ***this method is created only on a 64bit platform*** +- +- if we've got (value_size=3): +- table[0] = 10; +- table[1] = 30; +- table[2] = 5; +- and we call: +- SubInt(2,1) +- then it'll be: +- table[0] = 10; +- table[1] = 30 - 2; +- table[2] = 5; +- +- of course if there was a carry from table[2] it would be returned +- */ +- template +- uint UInt::SubInt(uint value, uint index) +- { +- uint b = value_size; +- uint * p1 = table; +- uint c; +- +- TTMATH_ASSERT( index < value_size ) +- +- #ifndef __GNUC__ +- c = ttmath_subindexed_x64(p1,b,index,value); +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy, dummy2; +- +- __asm__ __volatile__( +- +- "subq %%rdx, %%rcx \n" +- +- "1: \n" +- "subq %%rax, (%%rbx,%%rdx,8) \n" +- "jnc 2f \n" +- +- "movq $1, %%rax \n" +- "incq %%rdx \n" +- "decq %%rcx \n" +- "jnz 1b \n" +- +- "2: \n" +- "setc %%al \n" +- "movzx %%al, %%rdx \n" +- +- : "=d" (c), "=a" (dummy), "=c" (dummy2) +- : "0" (index), "1" (value), "2" (b), "b" (p1) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_LOGC("UInt::SubInt", c) +- +- return c; +- } +- +- +- /*! +- this static method subtractes one vector from the other +- 'ss1' is larger in size or equal to 'ss2' +- +- ss1 points to the first (larger) vector +- ss2 points to the second vector +- ss1_size - size of the ss1 (and size of the result too) +- ss2_size - size of the ss2 +- result - is the result vector (which has size the same as ss1: ss1_size) +- +- Example: ss1_size is 5, ss2_size is 3 +- ss1: ss2: result (output): +- 5 1 5-1 +- 4 3 4-3 +- 2 7 2-7 +- 6 6-1 (the borrow from previous item) +- 9 9 +- return (carry): 0 +- of course the carry (borrow) is propagated and will be returned from the last item +- (this method is used by the Karatsuba multiplication algorithm) +- */ +- template +- uint UInt::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) +- { +- TTMATH_ASSERT( ss1_size >= ss2_size ) +- +- uint c; +- +- #ifndef __GNUC__ +- c = ttmath_subvector_x64(ss1, ss2, ss1_size, ss2_size, result); +- #endif +- +- +- #ifdef __GNUC__ +- +- // the asm code is nearly the same as in AddVector +- // only two instructions 'adc' are changed to 'sbb' +- +- uint dummy1, dummy2, dummy3; +- uint rest = ss1_size - ss2_size; +- +- __asm__ __volatile__( +- "mov %%rdx, %%r8 \n" +- "xor %%rdx, %%rdx \n" // rdx = 0, cf = 0 +- "1: \n" +- "mov (%%rsi,%%rdx,8), %%rax \n" +- "sbb (%%rbx,%%rdx,8), %%rax \n" +- "mov %%rax, (%%rdi,%%rdx,8) \n" +- +- "inc %%rdx \n" +- "dec %%rcx \n" +- "jnz 1b \n" +- +- "adc %%rcx, %%rcx \n" // rcx has the cf state +- +- "or %%r8, %%r8 \n" +- "jz 3f \n" +- +- "xor %%rbx, %%rbx \n" // ebx = 0 +- "neg %%rcx \n" // setting cf from rcx +- "mov %%r8, %%rcx \n" // rcx=rest and is != 0 +- "2: \n" +- "mov (%%rsi, %%rdx, 8), %%rax \n" +- "sbb %%rbx, %%rax \n" +- "mov %%rax, (%%rdi, %%rdx, 8) \n" +- +- "inc %%rdx \n" +- "dec %%rcx \n" +- "jnz 2b \n" +- +- "adc %%rcx, %%rcx \n" +- "3: \n" +- +- : "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3) +- : "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result) +- : "%r8", "cc", "memory" ); +- +- #endif +- +- TTMATH_VECTOR_LOGC("UInt::SubVector", c, result, ss1_size) +- +- return c; +- } +- +- +- /*! +- this method moves all bits into the left hand side +- return value <- this <- c +- +- the lowest *bit* will be held the 'c' and +- the state of one additional bit (on the left hand side) +- will be returned +- +- for example: +- let this is 001010000 +- after Rcl2_one(1) there'll be 010100001 and Rcl2_one returns 0 +- +- ***this method is created only on a 64bit platform*** +- */ +- template +- uint UInt::Rcl2_one(uint c) +- { +- sint b = value_size; +- uint * p1 = table; +- +- +- #ifndef __GNUC__ +- c = ttmath_rcl_x64(p1,b,c); +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy, dummy2; +- +- __asm__ __volatile__( +- +- "xorq %%rdx, %%rdx \n" // rdx=0 +- "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 +- +- "1: \n" +- "rclq $1, (%%rbx, %%rdx, 8) \n" +- +- "incq %%rdx \n" +- "decq %%rcx \n" +- "jnz 1b \n" +- +- "adcq %%rcx, %%rcx \n" +- +- : "=c" (c), "=a" (dummy), "=d" (dummy2) +- : "0" (b), "1" (c), "b" (p1) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_LOGC("UInt::Rcl2_one", c) +- +- return c; +- } +- +- +- /*! +- this method moves all bits into the right hand side +- c -> this -> return value +- +- the highest *bit* will be held the 'c' and +- the state of one additional bit (on the right hand side) +- will be returned +- +- for example: +- let this is 000000010 +- after Rcr2_one(1) there'll be 100000001 and Rcr2_one returns 0 +- +- ***this method is created only on a 64bit platform*** +- */ +- template +- uint UInt::Rcr2_one(uint c) +- { +- sint b = value_size; +- uint * p1 = table; +- +- +- #ifndef __GNUC__ +- c = ttmath_rcr_x64(p1,b,c); +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy; +- +- __asm__ __volatile__( +- +- "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 +- +- "1: \n" +- "rcrq $1, -8(%%rbx, %%rcx, 8) \n" +- +- "decq %%rcx \n" +- "jnz 1b \n" +- +- "adcq %%rcx, %%rcx \n" +- +- : "=c" (c), "=a" (dummy) +- : "0" (b), "1" (c), "b" (p1) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_LOGC("UInt::Rcr2_one", c) +- +- return c; +- } +- +- +- +- /*! +- this method moves all bits into the left hand side +- return value <- this <- c +- +- the lowest *bits* will be held the 'c' and +- the state of one additional bit (on the left hand side) +- will be returned +- +- for example: +- let this is 001010000 +- after Rcl2(3, 1) there'll be 010000111 and Rcl2 returns 1 +- +- ***this method is created only on a 64bit platform*** +- */ +- template +- uint UInt::Rcl2(uint bits, uint c) +- { +- TTMATH_ASSERT( bits>0 && bits this -> return value +- +- the highest *bits* will be held the 'c' and +- the state of one additional bit (on the right hand side) +- will be returned +- +- for example: +- let this is 000000010 +- after Rcr2(2, 1) there'll be 110000000 and Rcr2 returns 1 +- +- ***this method is created only on a 64bit platform*** +- */ +- template +- uint UInt::Rcr2(uint bits, uint c) +- { +- TTMATH_ASSERT( bits>0 && bits +- sint UInt::FindLeadingBitInWord(uint x) +- { +- sint result; +- +- +- #ifndef __GNUC__ +- +- unsigned long nIndex = 0; +- +- if( _BitScanReverse64(&nIndex,x) == 0 ) +- result = -1; +- else +- result = nIndex; +- +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy; +- +- __asm__ ( +- +- "movq $-1, %1 \n" +- "bsrq %2, %0 \n" +- "cmovz %1, %0 \n" +- +- : "=r" (result), "=&r" (dummy) +- : "r" (x) +- : "cc" ); +- +- #endif +- +- +- return result; +- } +- +- +- /* +- this method returns the number of the highest set bit in one 64-bit word +- if the 'x' is zero this method returns '-1' +- +- ***this method is created only on a 64bit platform*** +- */ +- template +- sint UInt::FindLowestBitInWord(uint x) +- { +- sint result; +- +- +- #ifndef __GNUC__ +- +- unsigned long nIndex = 0; +- +- if( _BitScanForward64(&nIndex,x) == 0 ) +- result = -1; +- else +- result = nIndex; +- +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy; +- +- __asm__ ( +- +- "movq $-1, %1 \n" +- "bsfq %2, %0 \n" +- "cmovz %1, %0 \n" +- +- : "=r" (result), "=&r" (dummy) +- : "r" (x) +- : "cc" ); +- +- #endif +- +- +- return result; +- } +- +- +- /*! +- this method sets a special bit in the 'value' +- and returns the last state of the bit (zero or one) +- +- ***this method is created only on a 64bit platform*** +- +- bit is from <0,63> +- +- e.g. +- uint x = 100; +- uint bit = SetBitInWord(x, 3); +- now: x = 108 and bit = 0 +- */ +- template +- uint UInt::SetBitInWord(uint & value, uint bit) +- { +- TTMATH_ASSERT( bit < TTMATH_BITS_PER_UINT ) +- +- uint old_bit; +- uint v = value; +- +- +- #ifndef __GNUC__ +- old_bit = _bittestandset64((__int64*)&value,bit) != 0; +- #endif +- +- +- #ifdef __GNUC__ +- +- __asm__ ( +- +- "btsq %%rbx, %%rax \n" +- "setc %%bl \n" +- "movzx %%bl, %%rbx \n" +- +- : "=a" (v), "=b" (old_bit) +- : "0" (v), "1" (bit) +- : "cc" ); +- +- #endif +- +- value = v; +- +- return old_bit; +- } +- +- +- /*! +- * +- * Multiplication +- * +- * +- */ +- +- +- /*! +- multiplication: result_high:result_low = a * b +- result_high - higher word of the result +- result_low - lower word of the result +- +- this methos never returns a carry +- this method is used in the second version of the multiplication algorithms +- +- ***this method is created only on a 64bit platform*** +- */ +- template +- void UInt::MulTwoWords(uint a, uint b, uint * result_high, uint * result_low) +- { +- /* +- we must use these temporary variables in order to inform the compilator +- that value pointed with result1 and result2 has changed +- +- this has no effect in visual studio but it's usefull when +- using gcc and options like -O +- */ +- uint result1_; +- uint result2_; +- +- +- #ifndef __GNUC__ +- result1_ = _umul128(a,b,&result2_); +- #endif +- +- +- #ifdef __GNUC__ +- +- __asm__ ( +- +- "mulq %%rdx \n" +- +- : "=a" (result1_), "=d" (result2_) +- : "0" (a), "1" (b) +- : "cc" ); +- +- #endif +- +- +- *result_low = result1_; +- *result_high = result2_; +- } +- +- +- +- +- /*! +- * +- * Division +- * +- * +- */ +- +- +- /*! +- this method calculates 64bits word a:b / 32bits c (a higher, b lower word) +- r = a:b / c and rest - remainder +- +- ***this method is created only on a 64bit platform*** +- +- * +- * WARNING: +- * if r (one word) is too small for the result or c is equal zero +- * there'll be a hardware interruption (0) +- * and probably the end of your program +- * +- */ +- template +- void UInt::DivTwoWords(uint a,uint b, uint c, uint * r, uint * rest) +- { +- uint r_; +- uint rest_; +- /* +- these variables have similar meaning like those in +- the multiplication algorithm MulTwoWords +- */ +- +- TTMATH_ASSERT( c != 0 ) +- +- +- #ifndef __GNUC__ +- +- ttmath_div_x64(&a,&b,c); +- r_ = a; +- rest_ = b; +- +- #endif +- +- +- #ifdef __GNUC__ +- +- __asm__ ( +- +- "divq %%rcx \n" +- +- : "=a" (r_), "=d" (rest_) +- : "d" (a), "a" (b), "c" (c) +- : "cc" ); +- +- #endif +- +- +- *r = r_; +- *rest = rest_; +- } +- +-} //namespace +- +- +-#endif //ifdef TTMATH_PLATFORM64 +-#endif //ifndef TTMATH_NOASM +-#endif +- +- +diff --git a/extern/ttmath/ttmathuint_x86_64_msvc.asm b/extern/ttmath/ttmathuint_x86_64_msvc.asm +deleted file mode 100644 +index aae113f636..0000000000 +--- a/extern/ttmath/ttmathuint_x86_64_msvc.asm ++++ /dev/null +@@ -1,548 +0,0 @@ +-; +-; This file is a part of TTMath Bignum Library +-; and is distributed under the (new) BSD licence. +-; Author: Christian Kaiser +-; +- +-; +-; Copyright (c) 2009, Christian Kaiser +-; All rights reserved. +-; +-; Redistribution and use in source and binary forms, with or without +-; modification, are permitted provided that the following conditions are met: +-; +-; * Redistributions of source code must retain the above copyright notice, +-; this list of conditions and the following disclaimer. +-; +-; * Redistributions in binary form must reproduce the above copyright +-; notice, this list of conditions and the following disclaimer in the +-; documentation and/or other materials provided with the distribution. +-; +-; * Neither the name Christian Kaiser nor the names of contributors to this +-; project may be used to endorse or promote products derived +-; from this software without specific prior written permission. +-; +-; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +-; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +-; ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +-; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +-; THE POSSIBILITY OF SUCH DAMAGE. +-; +- +-; +-; compile with debug info: ml64.exe /c /Zd /Zi ttmathuint_x86_64_msvc.asm +-; compile without debug info: ml64.exe /c ttmathuint_x86_64_msvc.asm +-; this creates ttmathuint_x86_64_msvc.obj file which can be linked with your program +-; +- +-PUBLIC ttmath_adc_x64 +-PUBLIC ttmath_addindexed_x64 +-PUBLIC ttmath_addindexed2_x64 +-PUBLIC ttmath_addvector_x64 +- +-PUBLIC ttmath_sbb_x64 +-PUBLIC ttmath_subindexed_x64 +-PUBLIC ttmath_subvector_x64 +- +-PUBLIC ttmath_rcl_x64 +-PUBLIC ttmath_rcr_x64 +- +-PUBLIC ttmath_rcl2_x64 +-PUBLIC ttmath_rcr2_x64 +- +-PUBLIC ttmath_div_x64 +- +-; +-; Microsoft x86_64 convention: http://msdn.microsoft.com/en-us/library/9b372w95.aspx +-; +-; "rax, rcx, rdx, r8-r11 are volatile." +-; "rbx, rbp, rdi, rsi, r12-r15 are nonvolatile." +-; +- +- +-.CODE +- +- +- ALIGN 8 +- +-;---------------------------------------- +- +-ttmath_adc_x64 PROC +- ; rcx = p1 +- ; rdx = p2 +- ; r8 = nSize +- ; r9 = nCarry +- +- xor rax, rax +- xor r11, r11 +- sub rax, r9 ; sets CARRY if r9 != 0 +- +- ALIGN 16 +- loop1: +- mov rax,qword ptr [rdx + r11 * 8] +- adc qword ptr [rcx + r11 * 8], rax +- lea r11, [r11+1] +- dec r8 +- jnz loop1 +- +- setc al +- movzx rax, al +- +- ret +- +-ttmath_adc_x64 ENDP +- +-;---------------------------------------- +- +- ALIGN 8 +- +-;---------------------------------------- +- +-ttmath_addindexed_x64 PROC +- +- ; rcx = p1 +- ; rdx = nSize +- ; r8 = nPos +- ; r9 = nValue +- +- xor rax, rax ; rax = result +- sub rdx, r8 ; rdx = remaining count of uints +- +- add qword ptr [rcx + r8 * 8], r9 +- jc next1 +- +- ret +- +-next1: +- mov r9, 1 +- +- ALIGN 16 +-loop1: +- dec rdx +- jz done_with_cy +- lea r8, [r8+1] +- add qword ptr [rcx + r8 * 8], r9 +- jc loop1 +- +- ret +- +-done_with_cy: +- lea rax, [rax+1] ; rax = 1 +- +- ret +- +-ttmath_addindexed_x64 ENDP +- +-;---------------------------------------- +- +- ALIGN 8 +- +-;---------------------------------------- +- +-ttmath_addindexed2_x64 PROC +- +- ; rcx = p1 (pointer) +- ; rdx = b (value size) +- ; r8 = nPos +- ; r9 = nValue1 +- ; [rsp+0x28] = nValue2 +- +- xor rax, rax ; return value +- mov r11, rcx ; table +- sub rdx, r8 ; rdx = remaining count of uints +- mov r10, [rsp+028h] ; r10 = nValue2 +- +- add qword ptr [r11 + r8 * 8], r9 +- lea r8, [r8+1] +- lea rdx, [rdx-1] +- adc qword ptr [r11 + r8 * 8], r10 +- jc next +- ret +- +- ALIGN 16 +-loop1: +- lea r8, [r8+1] +- add qword ptr [r11 + r8 * 8], 1 +- jc next +- ret +- +-next: +- dec rdx ; does not modify CY too... +- jnz loop1 +- lea rax, [rax+1] +- ret +- +-ttmath_addindexed2_x64 ENDP +- +- +- +-;---------------------------------------- +- +- ALIGN 8 +- +-;---------------------------------------- +- +- +-ttmath_addvector_x64 PROC +- ; rcx = ss1 +- ; rdx = ss2 +- ; r8 = ss1_size +- ; r9 = ss2_size +- ; [rsp+0x28] = result +- +- mov r10, [rsp+028h] +- sub r8, r9 +- xor r11, r11 ; r11=0, cf=0 +- +- ALIGN 16 +- loop1: +- mov rax, qword ptr [rcx + r11 * 8] +- adc rax, qword ptr [rdx + r11 * 8] +- mov qword ptr [r10 + r11 * 8], rax +- inc r11 +- dec r9 +- jnz loop1 +- +- adc r9, r9 ; r9 has the cf state +- +- or r8, r8 +- jz done +- +- neg r9 ; setting cf from r9 +- mov r9, 0 ; don't use xor here (cf is used) +- loop2: +- mov rax, qword ptr [rcx + r11 * 8] +- adc rax, r9 +- mov qword ptr [r10 + r11 * 8], rax +- inc r11 +- dec r8 +- jnz loop2 +- +- adc r8, r8 +- mov rax, r8 +- +- ret +- +-done: +- mov rax, r9 +- ret +- +-ttmath_addvector_x64 ENDP +- +- +-;---------------------------------------- +- +- ALIGN 8 +- +-;---------------------------------------- +- +-ttmath_sbb_x64 PROC +- +- ; rcx = p1 +- ; rdx = p2 +- ; r8 = nCount +- ; r9 = nCarry +- +- xor rax, rax +- xor r11, r11 +- sub rax, r9 ; sets CARRY if r9 != 0 +- +- ALIGN 16 +- loop1: +- mov rax,qword ptr [rdx + r11 * 8] +- sbb qword ptr [rcx + r11 * 8], rax +- lea r11, [r11+1] +- dec r8 +- jnz loop1 +- +- setc al +- movzx rax, al +- +- ret +- +-ttmath_sbb_x64 ENDP +- +-;---------------------------------------- +- +- ALIGN 8 +- +-;---------------------------------------- +- +-ttmath_subindexed_x64 PROC +- ; rcx = p1 +- ; rdx = nSize +- ; r8 = nPos +- ; r9 = nValue +- +- sub rdx, r8 ; rdx = remaining count of uints +- +- ALIGN 16 +-loop1: +- sub qword ptr [rcx + r8 * 8], r9 +- jnc done +- +- lea r8, [r8+1] +- mov r9, 1 +- dec rdx +- jnz loop1 +- +- mov rax, 1 +- ret +- +-done: +- xor rax, rax +- ret +- +-ttmath_subindexed_x64 ENDP +- +- +- +-;---------------------------------------- +- +- ALIGN 8 +- +-;---------------------------------------- +- +-; the same asm code as in addvector_x64 only two instructions 'adc' changed to 'sbb' +- +-ttmath_subvector_x64 PROC +- ; rcx = ss1 +- ; rdx = ss2 +- ; r8 = ss1_size +- ; r9 = ss2_size +- ; [rsp+0x28] = result +- +- mov r10, [rsp+028h] +- sub r8, r9 +- xor r11, r11 ; r11=0, cf=0 +- +- ALIGN 16 +- loop1: +- mov rax, qword ptr [rcx + r11 * 8] +- sbb rax, qword ptr [rdx + r11 * 8] +- mov qword ptr [r10 + r11 * 8], rax +- inc r11 +- dec r9 +- jnz loop1 +- +- adc r9, r9 ; r9 has the cf state +- +- or r8, r8 +- jz done +- +- neg r9 ; setting cf from r9 +- mov r9, 0 ; don't use xor here (cf is used) +- loop2: +- mov rax, qword ptr [rcx + r11 * 8] +- sbb rax, r9 +- mov qword ptr [r10 + r11 * 8], rax +- inc r11 +- dec r8 +- jnz loop2 +- +- adc r8, r8 +- mov rax, r8 +- +- ret +- +-done: +- mov rax, r9 +- ret +- +-ttmath_subvector_x64 ENDP +- +- +- +- +-;---------------------------------------- +- +- ALIGN 8 +- +-;---------------------------------------- +- +-ttmath_rcl_x64 PROC +- ; rcx = p1 +- ; rdx = b +- ; r8 = nLowestBit +- +- mov r11, rcx ; table +- xor r10, r10 +- neg r8 ; CY set if r8 <> 0 +- +- ALIGN 16 +-loop1: +- rcl qword ptr [r11 + r10 * 8], 1 +- lea r10, [r10+1] +- dec rdx +- jnz loop1 +- +- setc al +- movzx rax, al +- +- ret +- +-ttmath_rcl_x64 ENDP +- +-;---------------------------------------- +- +- ALIGN 8 +- +-;---------------------------------------- +- +-ttmath_rcr_x64 PROC +- ; rcx = p1 +- ; rdx = nSize +- ; r8 = nLowestBit +- +- xor r10, r10 +- neg r8 ; CY set if r8 <> 0 +- +- ALIGN 16 +-loop1: +- rcr qword ptr -8[rcx + rdx * 8], 1 +- dec rdx +- jnz loop1 +- +- setc al +- movzx rax, al +- +- ret +- +-ttmath_rcr_x64 ENDP +- +-;---------------------------------------- +- +- ALIGN 8 +- +-;---------------------------------------- +- +-ttmath_div_x64 PROC +- +- ; rcx = &Hi +- ; rdx = &Lo +- ; r8 = nDiv +- +- mov r11, rcx +- mov r10, rdx +- +- mov rdx, qword ptr [r11] +- mov rax, qword ptr [r10] +- div r8 +- mov qword ptr [r10], rdx ; remainder +- mov qword ptr [r11], rax ; value +- +- ret +- +-ttmath_div_x64 ENDP +- +-;---------------------------------------- +- +- ALIGN 8 +- +-;---------------------------------------- +- +-ttmath_rcl2_x64 PROC +- ; rcx = p1 +- ; rdx = nSize +- ; r8 = bits +- ; r9 = c +- +- push rbx +- +- mov r10, rcx ; r10 = p1 +- xor rax, rax +- +- mov rcx, 64 +- sub rcx, r8 +- +- mov r11, -1 +- shr r11, cl ; r11 = mask +- +- mov rcx, r8 ; rcx = count of bits +- +- mov rbx, rax ; rbx = old value = 0 +- or r9, r9 +- cmovnz rbx, r11 ; if (c) then old value = mask +- +- mov r9, rax ; r9 = index (0..nSize-1) +- +- ALIGN 16 +-loop1: +- rol qword ptr [r10+r9*8], cl +- mov rax, qword ptr [r10+r9*8] +- and rax, r11 +- xor qword ptr [r10+r9*8], rax +- or qword ptr [r10+r9*8], rbx +- mov rbx, rax +- +- lea r9, [r9+1] +- dec rdx +- +- jnz loop1 +- +- and rax, 1 +- pop rbx +- ret +- +-ttmath_rcl2_x64 ENDP +- +-;---------------------------------------- +- +- ALIGN 8 +- +-;---------------------------------------- +- +-ttmath_rcr2_x64 PROC +- ; rcx = p1 +- ; rdx = nSize +- ; r8 = bits +- ; r9 = c +- +- push rbx +- mov r10, rcx ; r10 = p1 +- xor rax, rax +- +- mov rcx, 64 +- sub rcx, r8 +- +- mov r11, -1 +- shl r11, cl ; r11 = mask +- +- mov rcx, r8 ; rcx = count of bits +- +- mov rbx, rax ; rbx = old value = 0 +- or r9, r9 +- cmovnz rbx, r11 ; if (c) then old value = mask +- +- mov r9, rdx ; r9 = index (0..nSize-1) +- lea r9, [r9-1] +- +- ALIGN 16 +-loop1: +- ror qword ptr [r10+r9*8], cl +- mov rax, qword ptr [r10+r9*8] +- and rax, r11 +- xor qword ptr [r10+r9*8], rax +- or qword ptr [r10+r9*8], rbx +- mov rbx, rax +- +- lea r9, [r9-1] +- dec rdx +- +- jnz loop1 +- +- rol rax, 1 +- and rax, 1 +- pop rbx +- +- ret +- +-ttmath_rcr2_x64 ENDP +- +-END +diff --git a/src/common/Int128.cpp b/src/common/Int128.cpp +index d3158dddeb..88414b041d 100644 +--- a/src/common/Int128.cpp ++++ b/src/common/Int128.cpp +@@ -56,60 +56,18 @@ const CInt128 minus1(-1); + + namespace Firebird { + +-Int128 Int128::set(SLONG value, int scale) +-{ +- v = ttmath::sint(value); +- setScale(scale); +- return *this; +-} +- +-Int128 Int128::set(SINT64 value, int scale) +-{ +-#ifdef TTMATH_PLATFORM32 +- v = ttmath::slint(value); +-#else +- v = ttmath::sint(value); +-#endif +- setScale(scale); +- return *this; +-} +- + Int128 Int128::set(const char* value) + { + // This is simplified method - it does not perform all what's needed for CVT_decompose +- v.FromString(value); +- return *this; +-} +- +-Int128 Int128::set(double value) +-{ +- bool sgn = false; +- if (value < 0.0) +- { +- value = -value; +- sgn = true; +- } +- +- double parts[4]; +- for (int i = 0; i < 4; ++i) ++ for (v = 0; ; ++value) + { +- parts[i] = value; +- value /= p2_32; +- } +- fb_assert(value < 1.0); ++ if (*value < '0' or *value > '9') ++ break; + +- unsigned dwords[4]; +- value = 0.0; +- for (int i = 4; i--;) +- { +- dwords[i] = (parts[i] - value); +- value += p2_32 * dwords[i]; ++ v *= 10; ++ v += (*value - '0'); + } + +- setTable32(dwords); +- if (sgn) +- v.ChangeSign(); +- + return *this; + } + +@@ -122,14 +80,14 @@ Int128 Int128::set(DecimalStatus decSt, Decimal128 value) + value.getBcd(&bcd); + fb_assert(bcd.exp == 0); + +- v.SetZero(); ++ v = 0; + for (unsigned b = 0; b < sizeof(bcd.bcd); ++b) + { +- v.MulInt(10); +- v.AddInt(bcd.bcd[b]); ++ v *= 10; ++ v += bcd.bcd[b]; + } + if (bcd.sign < 0) +- v.ChangeSign(); ++ v = -v; + + return *this; + } +@@ -138,9 +96,13 @@ void Int128::setScale(int scale) + { + if (scale > 0) + { +- ttmath::sint rem = 0; ++ int rem = 0; + while (scale--) +- v.DivInt(10, scale == 0 ? &rem : nullptr); ++ { ++ if (scale == 0) ++ rem = int(v % 10); ++ v /= 10; ++ } + + if (rem > 4) + v++; +@@ -152,21 +114,11 @@ void Int128::setScale(int scale) + while (scale++) { + if (v > i128limit.v || v < -i128limit.v) + (Arg::Gds(isc_arith_except) << Arg::Gds(isc_numeric_out_of_range)).raise(); +- v.MulInt(10); ++ v *= 10; + } + } + } + +-int Int128::toInteger(int scale) const +-{ +- Int128 tmp(*this); +- tmp.setScale(scale); +- int rc; +- if (tmp.v.ToInt(rc)) +- overflow(); +- return rc; +-} +- + void Int128::toString(int scale, unsigned length, char* to) const + { + string buffer; +@@ -181,10 +133,22 @@ void Int128::toString(int scale, unsigned length, char* to) const + + void Int128::toString(int scale, string& to) const + { +- v.ToStringBase(to); +- bool sgn = to[0] == '-'; ++ to.erase(); ++ absl::int128 vv = v; ++ ++ bool sgn = (vv < 0); + if (sgn) +- to.erase(0, 1); ++ vv = -vv; ++ ++ while (vv > 0) ++ { ++ int dig = int(vv % 10); ++ to.insert(string::size_type(0), string::size_type(1), char(dig + '0')); ++ vv /= 10; ++ } ++ ++ if (to.isEmpty()) ++ to = "0"; + + if (scale) + { +@@ -220,78 +184,23 @@ void Int128::toString(int scale, string& to) const + to.insert(0, "-"); + } + +-SINT64 Int128::toInt64(int scale) const +-{ +- Int128 tmp(*this); +- tmp.setScale(scale); +- if (tmp.v < i64min.v || tmp.v > i64max.v) +- overflow(); +- +- unsigned dwords[4]; +- tmp.getTable32(dwords); +- SINT64 rc = int(dwords[1]); +- rc <<= 32; +- rc += dwords[0]; +- +- return rc; +-} +- +-double Int128::toDouble() const +-{ +- unsigned dwords[4]; +- getTable32(dwords); +- double rc = int(dwords[3]); +- for (int i = 3; i--;) +- { +- rc *= p2_32; +- rc += dwords[i]; +- } +- +- return rc; +-} +- +-int Int128::compare(Int128 tgt) const +-{ +- return v < tgt.v ? -1 : v > tgt.v ? 1 : 0; +-} +- + Int128 Int128::abs() const + { +- Int128 rc(*this); +- if (rc.v.Abs()) ++ if (compare(MIN_Int128) == 0) + overflow(); +- return rc; +-} + +-Int128 Int128::neg() const +-{ +- Int128 rc(*this); +- if (rc.v.ChangeSign()) +- overflow(); +- return rc; +-} +- +-Int128 Int128::add(Int128 op2) const +-{ +- Int128 rc(*this); +- if (rc.v.Add(op2.v)) +- overflow(); ++ Int128 rc; ++ rc.v = v < 0 ? -v : v; + return rc; + } + +-Int128 Int128::sub(Int128 op2) const ++Int128 Int128::neg() const + { +- Int128 rc(*this); +- if (rc.v.Sub(op2.v)) ++ if (compare(MIN_Int128) == 0) + overflow(); +- return rc; +-} + +-Int128 Int128::mul(Int128 op2) const +-{ +- Int128 rc(*this); +- if (rc.v.Mul(op2.v)) +- overflow(); ++ Int128 rc; ++ rc.v = -v; + return rc; + } + +@@ -300,210 +209,37 @@ Int128 Int128::div(Int128 op2, int scale) const + if (compare(MIN_Int128) == 0 && op2.compare(minus1) == 0) + Arg::Gds(isc_exception_integer_overflow).raise(); + ++ if (op2.v == 0) ++ zerodivide(); ++ + static const CInt128 MIN_BY10(MIN_Int128 / 10); + static const CInt128 MAX_BY10(MAX_Int128 / 10); + + // Scale op1 by as many of the needed powers of 10 as possible without an overflow. +- CInt128 op1(*this); ++ Int128 op1(*this); + int sign1 = op1.sign(); + while ((scale < 0) && (sign1 >= 0 ? op1.compare(MAX_BY10) <= 0 : op1.compare(MIN_BY10) >= 0)) + { +- op1 *= 10; ++ op1.v *= 10; + ++scale; + } + + // Scale op2 shifting it to the right as long as only zeroes are thrown away. +- CInt128 tmp(op2); + while (scale < 0) + { +- ttmath::sint rem = 0; +- tmp.v.DivInt(10, &rem); ++ int rem = int(v % 10); + if (rem) + break; +- op2 = tmp; ++ op2.v /= 10; + ++scale; + } + +- if (op1.v.Div(op2.v)) +- zerodivide(); ++ op1.v /= op2.v; + + op1.setScale(scale); + return op1; + } + +-Int128 Int128::mod(Int128 op2) const +-{ +- Int128 tmp(*this); +- Int128 rc; +- if (tmp.v.Div(op2.v, rc.v)) +- zerodivide(); +- return rc; +-} +- +-int Int128::sign() const +-{ +- return v.IsSign() ? -1 : v.IsZero() ? 0 : 1; +-} +- +-UCHAR* Int128::getBytes() +-{ +- return (UCHAR*)(v.table); +-} +- +-void Int128::getTable32(unsigned* dwords) const +-{ +- static_assert((sizeof(v.table[0]) == 4) || (sizeof(v.table[0]) == 8), +- "Unsupported size of integer in ttmath"); +- +- if (sizeof(v.table[0]) == 4) +- { +- for (int i = 0; i < 4; ++i) +- dwords[i] = v.table[i]; +- } +- else if (sizeof(v.table[0]) == 8) +- { +- for (int i = 0; i < 2; ++i) +- { +- dwords[i * 2] = v.table[i] & 0xFFFFFFFF; +- dwords[i * 2 + 1] = (v.table[i] >> 32) & 0xFFFFFFFF; +- } +- } +-} +- +-void Int128::setTable32(const unsigned* dwords) +-{ +- static_assert((sizeof(v.table[0]) == 4) || (sizeof(v.table[0]) == 8), +- "Unsupported size of integer in ttmath"); +- +- if (sizeof(v.table[0]) == 4) +- { +- for (int i = 0; i < 4; ++i) +- v.table[i] = dwords[i]; +- } +- else if (sizeof(v.table[0]) == 8) +- { +- for (int i = 0; i < 2; ++i) +- { +- v.table[i] = dwords[i * 2 + 1]; +- v.table[i] <<= 32; +- v.table[i] += dwords[i * 2]; +- } +- } +-} +- +-Int128 Int128::operator&=(FB_UINT64 mask) +-{ +- v.table[0] &= mask; +- unsigned i = 1; +- if (sizeof(v.table[0]) == 4) +- { +- i = 2; +- v.table[1] &= (mask >> 32); +- } +- +- for (; i < FB_NELEM(v.table); ++i) +- v.table[i] = 0; +- return *this; +-} +- +-Int128 Int128::operator&=(ULONG mask) +-{ +- v.table[0] &= mask; +- +- for (unsigned i = 1; i < FB_NELEM(v.table); ++i) +- v.table[i] = 0; +- return *this; +-} +- +-Int128 Int128::operator/(unsigned value) const +-{ +- Int128 rc(*this); +- rc.v.DivInt(value); +- return rc; +-} +- +-Int128 Int128::operator<<(int value) const +-{ +- Int128 rc(*this); +- rc.v <<= value; +- return rc; +-} +- +-Int128 Int128::operator>>(int value) const +-{ +- Int128 rc(*this); +- rc.v >>= value; +- return rc; +-} +- +-Int128 Int128::operator&=(Int128 value) +-{ +- v &= value.v; +- return *this; +-} +- +-Int128 Int128::operator|=(Int128 value) +-{ +- v |= value.v; +- return *this; +-} +- +-Int128 Int128::operator^=(Int128 value) +-{ +- v ^= value.v; +- return *this; +-} +- +-Int128 Int128::operator~() const +-{ +- Int128 rc(*this); +- rc.v.BitNot(); +- return rc; +-} +- +-Int128 Int128::operator-() const +-{ +- return neg(); +-} +- +-Int128 Int128::operator+=(unsigned value) +-{ +- v.AddInt(value); +- return *this; +-} +- +-Int128 Int128::operator-=(unsigned value) +-{ +- v.SubInt(value); +- return *this; +-} +- +-Int128 Int128::operator*=(unsigned value) +-{ +- v.MulInt(value); +- return *this; +-} +- +-bool Int128::operator>(Int128 value) const +-{ +- return v > value.v; +-} +- +-bool Int128::operator>=(Int128 value) const +-{ +- return v >= value.v; +-} +- +-bool Int128::operator==(Int128 value) const +-{ +- return v == value.v; +-} +- +-bool Int128::operator!=(Int128 value) const +-{ +- return v != value.v; +-} +- + void Int128::zerodivide() + { + (Arg::Gds(isc_arith_except) << Arg::Gds(isc_exception_integer_divide_by_zero)).raise(); +@@ -533,10 +269,10 @@ CInt128::CInt128(minmax mm) + switch(mm) + { + case MkMax: +- v.SetMax(); ++ v = absl::Int128Max(); + break; + case MkMin: +- v.SetMin(); ++ v = absl::Int128Min(); + break; + } + } +diff --git a/src/common/Int128.h b/src/common/Int128.h +index 5fde931ff9..432023d176 100644 +--- a/src/common/Int128.h ++++ b/src/common/Int128.h +@@ -36,7 +36,7 @@ + + #include "classes/fb_string.h" + +-#include "../../extern/ttmath/ttmath.h" ++#include "absl/numeric/int128.h" + + namespace Firebird { + +@@ -53,10 +53,29 @@ public: + return set(SLONG(value), scale); + } + #endif +- Int128 set(SLONG value, int scale); +- Int128 set(SINT64 value, int scale); +- Int128 set(double value); ++ ++ Int128 set(SLONG value, int scale) ++ { ++ v = value; ++ setScale(scale); ++ return *this; ++ } ++ ++ Int128 set(SINT64 value, int scale) ++ { ++ v = value; ++ setScale(scale); ++ return *this; ++ } ++ ++ Int128 set(double value) ++ { ++ v = absl::int128(value); ++ return *this; ++ } ++ + Int128 set(DecimalStatus decSt, Decimal128 value); ++ + Int128 set(Int128 value) + { + v = value.v; +@@ -73,49 +92,217 @@ public: + const char* show(); + #endif + +- int toInteger(int scale) const; +- SINT64 toInt64(int scale) const; ++ int toInteger(int scale) const ++ { ++ Int128 tmp(*this); ++ tmp.setScale(scale); ++ int rc = int(tmp.v); ++ if (tmp.v != rc) ++ overflow(); ++ return rc; ++ } ++ ++ SINT64 toInt64(int scale) const ++ { ++ Int128 tmp(*this); ++ tmp.setScale(scale); ++ SINT64 rc = SINT64(tmp.v); ++ if (tmp.v != rc) ++ overflow(); ++ return rc; ++ } ++ + void toString(int scale, unsigned length, char* to) const; + void toString(int scale, string& to) const; +- double toDouble() const; +- +- Int128 operator&=(FB_UINT64 mask); +- Int128 operator&=(ULONG mask); +- Int128 operator-() const; +- Int128 operator/(unsigned value) const; +- Int128 operator+=(unsigned value); +- Int128 operator-=(unsigned value); +- Int128 operator*=(unsigned value); +- +- Int128 operator<<(int value) const; +- Int128 operator>>(int value) const; +- +- int compare(Int128 tgt) const; +- bool operator>(Int128 value) const; +- bool operator>=(Int128 value) const; +- bool operator==(Int128 value) const; +- bool operator!=(Int128 value) const; +- Int128 operator&=(Int128 value); +- Int128 operator|=(Int128 value); +- Int128 operator^=(Int128 value); +- Int128 operator~() const; +- int sign() const; ++ ++ double toDouble() const ++ { ++ return double(v); ++ } ++ ++ Int128 operator&=(FB_UINT64 mask) ++ { ++ v &= mask; ++ return *this; ++ } ++ ++ Int128 operator&=(ULONG mask) ++ { ++ v &= mask; ++ return *this; ++ } ++ ++ Int128 operator-() const ++ { ++ Int128 rc; ++ rc.v = -v; ++ return rc; ++ } ++ ++ Int128 operator/(unsigned value) const ++ { ++ Int128 rc; ++ rc.v = v / value; ++ return rc; ++ } ++ ++ Int128 operator+=(unsigned value) ++ { ++ v += value; ++ return *this; ++ } ++ ++ Int128 operator-=(unsigned value) ++ { ++ v -= value; ++ return *this; ++ } ++ ++ Int128 operator*=(unsigned value) ++ { ++ v *= value; ++ return *this; ++ } ++ ++ Int128 operator<<(int value) const ++ { ++ Int128 rc; ++ rc.v = v << value; ++ return rc; ++ } ++ ++ Int128 operator>>(int value) const ++ { ++ Int128 rc; ++ rc.v = v >> value; ++ return rc; ++ } ++ ++ int compare(Int128 tgt) const ++ { ++ return v < tgt.v ? -1 : v > tgt.v ? 1 : 0; ++ } ++ ++ bool operator>(Int128 value) const ++ { ++ return v > value.v; ++ } ++ ++ bool operator>=(Int128 value) const ++ { ++ return v >= value.v; ++ } ++ ++ bool operator==(Int128 value) const ++ { ++ return v == value.v; ++ } ++ ++ bool operator!=(Int128 value) const ++ { ++ return v != value.v; ++ } ++ ++ Int128 operator&=(Int128 value) ++ { ++ v &= value.v; ++ return *this; ++ } ++ ++ Int128 operator|=(Int128 value) ++ { ++ v |= value.v; ++ return *this; ++ } ++ ++ Int128 operator^=(Int128 value) ++ { ++ v ^= value.v; ++ return *this; ++ } ++ ++ Int128 operator~() const ++ { ++ Int128 rc; ++ rc.v = ~v; ++ return rc; ++ } ++ ++ int sign() const ++ { ++ return v < 0 ? -1 : v == 0 ? 0 : 1; ++ } + + Int128 abs() const; + Int128 neg() const; +- Int128 add(Int128 op2) const; +- Int128 sub(Int128 op2) const; +- Int128 mul(Int128 op2) const; ++ ++ Int128 add(Int128 op2) const ++ { ++ Int128 rc; ++ rc.v = v + op2.v; ++ ++ // see comment ArithmeticNode::add2() ++ if (sign() == op2.sign() && op2.sign() != rc.sign()) ++ overflow(); ++ ++ return rc; ++ } ++ ++ Int128 sub(Int128 op2) const ++ { ++ Int128 rc; ++ rc.v = v - op2.v; ++ ++ // see comment ArithmeticNode::add2() ++ if (sign() != op2.sign() && op2.sign() == rc.sign()) ++ overflow(); ++ ++ return rc; ++ } ++ ++ Int128 mul(Int128 op2) const ++ { ++ Int128 rc; ++ rc.v = v * op2.v; ++ ++ if (rc.v / v != op2.v) ++ overflow(); ++ ++ return rc; ++ } ++ + Int128 div(Int128 op2, int scale) const; +- Int128 mod(Int128 op2) const; + +- void getTable32(unsigned* dwords) const; // internal data in per-32bit form +- void setTable32(const unsigned* dwords); ++ Int128 mod(Int128 op2) const ++ { ++ if (op2.v == 0) ++ zerodivide(); ++ ++ Int128 rc; ++ rc.v = v % op2.v; ++ return rc; ++ } ++ ++ // returns internal data in per-32bit form ++ void getTable32(unsigned* dwords) const ++ { ++ absl::int128 vv = v; ++ for (int i = 0; i < 4; ++i) ++ { ++ dwords[i] = unsigned(vv); ++ vv >>= 32; ++ } ++ } ++ + void setScale(int scale); +- UCHAR* getBytes(); ++ ++ UCHAR* getBytes() ++ { ++ return (UCHAR*)(&v); ++ } + + protected: +- ttmath::Int v; ++ absl::int128 v; + + static void overflow(); + static void zerodivide(); +@@ -143,10 +330,10 @@ class I128limit : public Int128 + public: + I128limit() + { +- v.SetOne(); ++ v = 1; + for (int i = 0; i < 126; ++i) +- v.MulInt(2); +- v.DivInt(5); ++ v *= 2; ++ v *= 5; + } + }; + +diff --git a/src/jrd/align.h b/src/jrd/align.h +index aa4631488d..c94f0f4da3 100644 +--- a/src/jrd/align.h ++++ b/src/jrd/align.h +@@ -114,7 +114,7 @@ static const USHORT type_alignments[DTYPE_TYPE_MAX] = + sizeof(UCHAR), /* dtype_boolean */ + sizeof(Firebird::Decimal64),/* dtype_dec64 */ + sizeof(Firebird::Decimal64),/* dtype_dec128 */ +- sizeof(Firebird::Decimal64),/* dtype_int128 */ ++ sizeof(SINT64), /* dtype_int128 */ + sizeof(GDS_TIME), /* dtype_sql_time_tz */ + sizeof(GDS_DATE), /* dtype_timestamp_tz */ + sizeof(GDS_TIME), /* dtype_ex_time_tz */ diff --git a/firebird.spec b/firebird.spec index 491ee97..55b7fae 100644 --- a/firebird.spec +++ b/firebird.spec @@ -6,7 +6,7 @@ %define majver %(echo %version | cut -d. -f 1-2) Name: firebird Version: 4.0.0.2496 -Release: 1mamba +Release: 3mamba Summary: SQL Relational Database Group: Applications/Databases Vendor: openmamba @@ -21,6 +21,12 @@ Source4: firebird.service Source5: firebird-tmpfiles.conf Source6: firebird-sysusers.conf Source7: firebird-default.password +Patch0: firebird-4.0.0.2496-add-pkgconfig-files.patch +Patch1: firebird-4.0.0.2496-no-copy-from-icu.patch +Patch2: firebird-4.0.0.2496-cloop-honour-build-flags.patch +Patch3: firebird-4.0.0.2496-c++17.patch +Patch4: firebird-4.0.0.2496-noexcept.patch +Patch5: firebird-4.0.0.2496-ttmath-abseil-4.0.0.patch License: MPL 1.1 ## AUTOBUILDREQ-BEGIN BuildRequires: glibc-devel @@ -92,31 +98,45 @@ This package contains multi-threaded, non-local client libraries for Firebird SQ %setup -q -n Firebird-%{version}-0 #-D -T #:<< __EOF +%patch0 -p1 +%patch1 -p1 -b .no-copy-from-icu +%patch2 -p1 -b .cloop-honour-build-flags +%patch3 -p1 -b .c++17 +%patch4 -p1 -b .noexcept +%patch5 -p1 -b .ttmath-abseil-4.0.0 + NOCONFIGURE=1 ./autogen.sh %build #:<< __EOF +export CFLAGS="%{optflags} -fno-strict-aliasing" +export CXXFLAGS="${CFLAGS} -fno-delete-null-pointer-checks" + %configure \ --disable-rpath \ - --with-fbconf=%{_sysconfdir}/firebird \ - --with-fbinclude=%{_includedir}/firebird \ + --with-system-editline \ + --with-fbinclude=%{_includedir} \ + --with-fbsbin=%{_libdir}/firebird/bin \ --with-fbbin=%{_bindir} \ + --with-fbconf=%{_sysconfdir}/firebird \ + --with-fblib=%{_libdir} \ --with-fbdoc=%{_docdir}/firebird \ + --with-fbsample=%{_defaultdocdir}/firebird/sample \ + --with-fbsample-db=%{_localstatedir}/lib/firebird/data \ --with-fbhelp=%{_docdir}/firebird/help \ --with-fbintl=%{_libdir}/firebird/intl \ - --with-fbsbin=%{_libdir}/firebird/bin \ - --with-fblib=%{_libdir} \ + --with-fbmisc=%{_datadir}/firebird/misc \ --with-fbsecure-db=/var/lib/firebird/system \ --with-fbmsg=%{_libdir}/firebird/msg \ --with-fblog=/var/log/firebird \ --with-fbglock=/run/firebird \ --with-fbplugins=%{_libdir}/firebird/plugins \ - --with-fbtzdata=%{_localstatedir}/lib/%{name}/tzdata \ - --with-system-editline \ - --without-fbmisc \ - --without-fbsample \ - --without-fbsample-db + --with-fbtzdata=%{_localstatedir}/lib/%{name}/tzdata + +# --without-fbmisc \ +# --without-fbsample \ +# --without-fbsample-db %make @@ -130,6 +150,9 @@ cd gen cd .. install -d -m0755 %{buildroot} cp -av gen/buildroot/* %{buildroot}/ + +mkdir -p %{buildroot}%{_libdir}/pkgconfig +cp -v gen/install/misc/*.pc %{buildroot}%{_libdir}/pkgconfig/ install -Dm644 %{SOURCE4} %{buildroot}%{_unitdir}/firebird.service install -Dm644 %{SOURCE5} %{buildroot}%{_tmpfilesdir}/firebird.conf @@ -222,8 +245,12 @@ fi %dir %{_libdir}/firebird/bin %{_libdir}/firebird/bin/* %dir %{_localstatedir}/lib/firebird +%dir %{_localstatedir}/lib/firebird/data +%{_localstatedir}/lib/firebird/data/* %dir %{_localstatedir}/lib/firebird/tzdata %{_localstatedir}/lib/firebird/tzdata/* +%dir %{_datadir}/firebird/misc +%{_datadir}/firebird/misc/* %doc doc/license/IDPL.txt %doc doc/license/README.license.usage.txt @@ -235,6 +262,7 @@ fi %{_includedir}/firebird/* %{_libdir}/libfbclient.so %{_libdir}/libib_util.so +%{_libdir}/pkgconfig/fbclient.pc %files -n libfbclient %defattr(-,root,root) @@ -250,6 +278,10 @@ fi %{_datadir}/doc/firebird/* %changelog +* Sun Nov 28 2021 Silvan Calarco 4.0.0.2496-2mamba +- added patches from Fedora, including pkg-config file +- fix includes installation directory + * Thu Jun 17 2021 Silvan Calarco 4.0.0.2496-1mamba - update to 4.0.0.2496