You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
firebird/ttmath-abseil.4.0.0.patch

21256 lines
510 KiB

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
+// <https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html>.
+//
+// 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<void *>(__start_##name))
+#define ABSL_ATTRIBUTE_SECTION_STOP(name) \
+ (reinterpret_cast<void *>(__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<void *>(0))
+#define ABSL_ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast<void *>(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 <typename T>
+// 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 <limits.h>
+
+#ifdef __cplusplus
+// Included for __GLIBCXX__, _LIBCPP_VERSION
+#include <cstddef>
+#endif // __cplusplus
+
+#if defined(__APPLE__)
+// Included for TARGET_OS_IPHONE, __IPHONE_OS_VERSION_MIN_REQUIRED,
+// __IPHONE_8_0.
+#include <Availability.h>
+#include <TargetConditionals.h>
+#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<T>` 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<T>` and
+// `std::is_trivially_copy_constructible<T>` are supported.
+
+// ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
+//
+// Checks whether `std::is_trivially_copy_assignable<T>` 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
+// <android/ndk-version.h>. 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(<android/ndk-version.h>)
+#include <android/ndk-version.h>
+#endif // __has_include(<android/ndk-version.h>)
+#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 <semaphore.h> header and sem_init(3)
+// family of functions as standardized in POSIX.1-2001.
+//
+// Note: While Apple provides <semaphore.h> 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 <signal.h> 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 <any>, <optional>, or <variant>
+// 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 <any> exists.
+#ifdef ABSL_HAVE_STD_ANY
+#error "ABSL_HAVE_STD_ANY cannot be directly set."
+#endif
+
+#ifdef __has_include
+#if __has_include(<any>) && 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(<optional>) && 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(<variant>) && 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(<string_view>) && 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 <optional>, <any>, <string_view>, <variant>. So we use
+// _MSC_VER to check whether we have VS 2017 RTM (when <optional>, <any>,
+// <string_view>, <variant> 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<SomeStruct> 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 <cassert>
+#include <cstddef>
+
+#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 <typename T, size_t N>
+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<void>(expr) : static_cast<void>(0))
+#else
+#define ABSL_ASSERT(expr) \
+ (ABSL_PREDICT_TRUE((expr)) ? static_cast<void>(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<void>(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 <assert.h>
+
+#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 <intrin.h>
+// 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<void>(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 <ciso646>
+#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 <limits.h>
+
+// Included for the _STLPORT_VERSION macro used below.
+#if defined(__cplusplus)
+#include <cstddef>
+#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 <cstdint>
+#include <limits>
+#include <type_traits>
+
+#if (defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L) || \
+ (defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L)
+#include <bit>
+#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 <class T>
+ABSL_MUST_USE_RESULT constexpr
+ typename std::enable_if<std::is_unsigned<T>::value, T>::type
+ rotl(T x, int s) noexcept {
+ return numeric_internal::RotateLeft(x, s);
+}
+
+template <class T>
+ABSL_MUST_USE_RESULT constexpr
+ typename std::enable_if<std::is_unsigned<T>::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 <class T>
+ABSL_INTERNAL_CONSTEXPR_CLZ inline
+ typename std::enable_if<std::is_unsigned<T>::value, int>::type
+ countl_zero(T x) noexcept {
+ return numeric_internal::CountLeadingZeroes(x);
+}
+
+template <class T>
+ABSL_INTERNAL_CONSTEXPR_CLZ inline
+ typename std::enable_if<std::is_unsigned<T>::value, int>::type
+ countl_one(T x) noexcept {
+ // Avoid integer promotion to a wider type
+ return countl_zero(static_cast<T>(~x));
+}
+
+template <class T>
+ABSL_INTERNAL_CONSTEXPR_CTZ inline
+ typename std::enable_if<std::is_unsigned<T>::value, int>::type
+ countr_zero(T x) noexcept {
+ return numeric_internal::CountTrailingZeroes(x);
+}
+
+template <class T>
+ABSL_INTERNAL_CONSTEXPR_CTZ inline
+ typename std::enable_if<std::is_unsigned<T>::value, int>::type
+ countr_one(T x) noexcept {
+ // Avoid integer promotion to a wider type
+ return countr_zero(static_cast<T>(~x));
+}
+
+template <class T>
+ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline
+ typename std::enable_if<std::is_unsigned<T>::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 <class T>
+constexpr inline typename std::enable_if<std::is_unsigned<T>::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 <class T>
+ABSL_INTERNAL_CONSTEXPR_CLZ inline
+ typename std::enable_if<std::is_unsigned<T>::value, T>::type
+ bit_width(T x) noexcept {
+ return std::numeric_limits<T>::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 <class T>
+ABSL_INTERNAL_CONSTEXPR_CLZ inline
+ typename std::enable_if<std::is_unsigned<T>::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 <class T>
+ABSL_INTERNAL_CONSTEXPR_CLZ inline
+ typename std::enable_if<std::is_unsigned<T>::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 <stddef.h>
+
+#include <cassert>
+#include <iomanip>
+#include <ostream> // NOLINT(readability/streams)
+#include <sstream>
+#include <string>
+#include <type_traits>
+
+#include "absl/base/optimization.h"
+#include "absl/numeric/bits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+ABSL_DLL const uint128 kuint128max = MakeUint128(
+ std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::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 <typename T>
+uint128 MakeUint128FromFloat(T v) {
+ static_assert(std::is_floating_point<T>::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<T>::max_exponent <= 128 ||
+ v < std::ldexp(static_cast<T>(1), 128)));
+
+ if (v >= std::ldexp(static_cast<T>(1), 64)) {
+ uint64_t hi = static_cast<uint64_t>(std::ldexp(v, -64));
+ uint64_t lo = static_cast<uint64_t>(v - std::ldexp(static_cast<T>(hi), 64));
+ return MakeUint128(hi, lo);
+ }
+
+ return MakeUint128(0, static_cast<uint64_t>(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<double>::digits >= 50, "");
+ static_assert(std::numeric_limits<long double>::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<uint64_t>(static_cast<double>(std::trunc(v)));
+ v = std::ldexp(v - static_cast<double>(w0), 50);
+ uint64_t w1 = static_cast<uint64_t>(static_cast<double>(std::trunc(v)));
+ v = std::ldexp(v - static_cast<double>(w1), 50);
+ uint64_t w2 = static_cast<uint64_t>(static_cast<double>(std::trunc(v)));
+ return (static_cast<uint128>(w0) << 100) | (static_cast<uint128>(w1) << 50) |
+ static_cast<uint128>(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, &quotient, &remainder);
+ return quotient;
+}
+
+uint128 operator%(uint128 lhs, uint128 rhs) {
+ uint128 quotient = 0;
+ uint128 remainder = 0;
+ DivModImpl(lhs, rhs, &quotient, &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<size_t>(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 <typename T>
+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<T>::max_exponent <= 127 ||
+ (v >= -std::ldexp(static_cast<T>(1), 127) &&
+ v < std::ldexp(static_cast<T>(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),
+ &quotient, &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),
+ &quotient, &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<size_t>(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<absl::uint128>::is_specialized;
+constexpr bool numeric_limits<absl::uint128>::is_signed;
+constexpr bool numeric_limits<absl::uint128>::is_integer;
+constexpr bool numeric_limits<absl::uint128>::is_exact;
+constexpr bool numeric_limits<absl::uint128>::has_infinity;
+constexpr bool numeric_limits<absl::uint128>::has_quiet_NaN;
+constexpr bool numeric_limits<absl::uint128>::has_signaling_NaN;
+constexpr float_denorm_style numeric_limits<absl::uint128>::has_denorm;
+constexpr bool numeric_limits<absl::uint128>::has_denorm_loss;
+constexpr float_round_style numeric_limits<absl::uint128>::round_style;
+constexpr bool numeric_limits<absl::uint128>::is_iec559;
+constexpr bool numeric_limits<absl::uint128>::is_bounded;
+constexpr bool numeric_limits<absl::uint128>::is_modulo;
+constexpr int numeric_limits<absl::uint128>::digits;
+constexpr int numeric_limits<absl::uint128>::digits10;
+constexpr int numeric_limits<absl::uint128>::max_digits10;
+constexpr int numeric_limits<absl::uint128>::radix;
+constexpr int numeric_limits<absl::uint128>::min_exponent;
+constexpr int numeric_limits<absl::uint128>::min_exponent10;
+constexpr int numeric_limits<absl::uint128>::max_exponent;
+constexpr int numeric_limits<absl::uint128>::max_exponent10;
+constexpr bool numeric_limits<absl::uint128>::traps;
+constexpr bool numeric_limits<absl::uint128>::tinyness_before;
+
+constexpr bool numeric_limits<absl::int128>::is_specialized;
+constexpr bool numeric_limits<absl::int128>::is_signed;
+constexpr bool numeric_limits<absl::int128>::is_integer;
+constexpr bool numeric_limits<absl::int128>::is_exact;
+constexpr bool numeric_limits<absl::int128>::has_infinity;
+constexpr bool numeric_limits<absl::int128>::has_quiet_NaN;
+constexpr bool numeric_limits<absl::int128>::has_signaling_NaN;
+constexpr float_denorm_style numeric_limits<absl::int128>::has_denorm;
+constexpr bool numeric_limits<absl::int128>::has_denorm_loss;
+constexpr float_round_style numeric_limits<absl::int128>::round_style;
+constexpr bool numeric_limits<absl::int128>::is_iec559;
+constexpr bool numeric_limits<absl::int128>::is_bounded;
+constexpr bool numeric_limits<absl::int128>::is_modulo;
+constexpr int numeric_limits<absl::int128>::digits;
+constexpr int numeric_limits<absl::int128>::digits10;
+constexpr int numeric_limits<absl::int128>::max_digits10;
+constexpr int numeric_limits<absl::int128>::radix;
+constexpr int numeric_limits<absl::int128>::min_exponent;
+constexpr int numeric_limits<absl::int128>::min_exponent10;
+constexpr int numeric_limits<absl::int128>::max_exponent;
+constexpr int numeric_limits<absl::int128>::max_exponent10;
+constexpr bool numeric_limits<absl::int128>::traps;
+constexpr bool numeric_limits<absl::int128>::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 <cassert>
+#include <cmath>
+#include <cstdint>
+#include <cstring>
+#include <iosfwd>
+#include <limits>
+#include <utility>
+
+#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 <intrin.h>
+#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<uint64_t>(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 <typename H>
+ 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<uint64_t>::max)(),
+ (std::numeric_limits<uint64_t>::max)());
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+// Specialized numeric_limits for uint128.
+namespace std {
+template <>
+class numeric_limits<absl::uint128> {
+ 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<unsigned __int128>::traps;
+#else // ABSL_HAVE_INTRINSIC_INT128
+ static constexpr bool traps = numeric_limits<uint64_t>::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<int64_t>(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 <typename H>
+ 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<int64_t>::max)(),
+ (std::numeric_limits<uint64_t>::max)());
+}
+
+constexpr int128 Int128Min() {
+ return int128((std::numeric_limits<int64_t>::min)(), 0);
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+// Specialized numeric_limits for int128.
+namespace std {
+template <>
+class numeric_limits<absl::int128> {
+ 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<uint64_t>::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<uint64_t>(v)},
+ hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {}
+constexpr uint128::uint128(long v) // NOLINT(runtime/int)
+ : lo_{static_cast<uint64_t>(v)},
+ hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {}
+constexpr uint128::uint128(long long v) // NOLINT(runtime/int)
+ : lo_{static_cast<uint64_t>(v)},
+ hi_{v < 0 ? (std::numeric_limits<uint64_t>::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<uint64_t>(v & ~uint64_t{0})},
+ hi_{static_cast<uint64_t>(static_cast<unsigned __int128>(v) >> 64)} {}
+constexpr uint128::uint128(unsigned __int128 v)
+ : lo_{static_cast<uint64_t>(v & ~uint64_t{0})},
+ hi_{static_cast<uint64_t>(v >> 64)} {}
+#endif // ABSL_HAVE_INTRINSIC_INT128
+
+constexpr uint128::uint128(int128 v)
+ : lo_{Int128Low64(v)}, hi_{static_cast<uint64_t>(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<uint64_t>::max)() : 0},
+ lo_{static_cast<uint64_t>(v)} {}
+constexpr uint128::uint128(long v) // NOLINT(runtime/int)
+ : hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0},
+ lo_{static_cast<uint64_t>(v)} {}
+constexpr uint128::uint128(long long v) // NOLINT(runtime/int)
+ : hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0},
+ lo_{static_cast<uint64_t>(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<uint64_t>(static_cast<unsigned __int128>(v) >> 64)},
+ lo_{static_cast<uint64_t>(v & ~uint64_t{0})} {}
+constexpr uint128::uint128(unsigned __int128 v)
+ : hi_{static_cast<uint64_t>(v >> 64)},
+ lo_{static_cast<uint64_t>(v & ~uint64_t{0})} {}
+#endif // ABSL_HAVE_INTRINSIC_INT128
+
+constexpr uint128::uint128(int128 v)
+ : hi_{static_cast<uint64_t>(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<char>(lo_); }
+
+constexpr uint128::operator signed char() const {
+ return static_cast<signed char>(lo_);
+}
+
+constexpr uint128::operator unsigned char() const {
+ return static_cast<unsigned char>(lo_);
+}
+
+constexpr uint128::operator char16_t() const {
+ return static_cast<char16_t>(lo_);
+}
+
+constexpr uint128::operator char32_t() const {
+ return static_cast<char32_t>(lo_);
+}
+
+constexpr uint128::operator ABSL_INTERNAL_WCHAR_T() const {
+ return static_cast<ABSL_INTERNAL_WCHAR_T>(lo_);
+}
+
+// NOLINTNEXTLINE(runtime/int)
+constexpr uint128::operator short() const { return static_cast<short>(lo_); }
+
+constexpr uint128::operator unsigned short() const { // NOLINT(runtime/int)
+ return static_cast<unsigned short>(lo_); // NOLINT(runtime/int)
+}
+
+constexpr uint128::operator int() const { return static_cast<int>(lo_); }
+
+constexpr uint128::operator unsigned int() const {
+ return static_cast<unsigned int>(lo_);
+}
+
+// NOLINTNEXTLINE(runtime/int)
+constexpr uint128::operator long() const { return static_cast<long>(lo_); }
+
+constexpr uint128::operator unsigned long() const { // NOLINT(runtime/int)
+ return static_cast<unsigned long>(lo_); // NOLINT(runtime/int)
+}
+
+constexpr uint128::operator long long() const { // NOLINT(runtime/int)
+ return static_cast<long long>(lo_); // NOLINT(runtime/int)
+}
+
+constexpr uint128::operator unsigned long long() const { // NOLINT(runtime/int)
+ return static_cast<unsigned long long>(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<unsigned __int128>(hi_) << 64) + lo_;
+}
+#endif // ABSL_HAVE_INTRINSIC_INT128
+
+// Conversion operators to floating point types.
+
+inline uint128::operator float() const {
+ return static_cast<float>(lo_) + std::ldexp(static_cast<float>(hi_), 64);
+}
+
+inline uint128::operator double() const {
+ return static_cast<double>(lo_) + std::ldexp(static_cast<double>(hi_), 64);
+}
+
+inline uint128::operator long double() const {
+ return static_cast<long double>(lo_) +
+ std::ldexp(static_cast<long double>(hi_), 64);
+}
+
+// Comparison operators.
+
+inline bool operator==(uint128 lhs, uint128 rhs) {
+#if defined(ABSL_HAVE_INTRINSIC_INT128)
+ return static_cast<unsigned __int128>(lhs) ==
+ static_cast<unsigned __int128>(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<unsigned __int128>(lhs) <
+ static_cast<unsigned __int128>(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<unsigned __int128>(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<unsigned __int128>(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<unsigned __int128>(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<unsigned __int128>(lhs) |
+ static_cast<unsigned __int128>(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<unsigned __int128>(lhs) &
+ static_cast<unsigned __int128>(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<unsigned __int128>(lhs) ^
+ static_cast<unsigned __int128>(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<unsigned __int128>(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<unsigned __int128>(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<unsigned __int128>(lhs) +
+ static_cast<unsigned __int128>(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<unsigned __int128>(lhs) -
+ static_cast<unsigned __int128>(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<unsigned __int128>(lhs) *
+ static_cast<unsigned __int128>(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<unsigned __int128>(lhs) /
+ static_cast<unsigned __int128>(rhs);
+}
+
+inline uint128 operator%(uint128 lhs, uint128 rhs) {
+ return static_cast<unsigned __int128>(lhs) %
+ static_cast<unsigned __int128>(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<int64_t>(~v)
+ : static_cast<int64_t>(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<unsigned __int128>(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<uint64_t>(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<uint64_t>(static_cast<unsigned __int128>(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<unsigned __int128>(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<bool>(v_); }
+
+constexpr int128::operator char() const { return static_cast<char>(v_); }
+
+constexpr int128::operator signed char() const {
+ return static_cast<signed char>(v_);
+}
+
+constexpr int128::operator unsigned char() const {
+ return static_cast<unsigned char>(v_);
+}
+
+constexpr int128::operator char16_t() const {
+ return static_cast<char16_t>(v_);
+}
+
+constexpr int128::operator char32_t() const {
+ return static_cast<char32_t>(v_);
+}
+
+constexpr int128::operator ABSL_INTERNAL_WCHAR_T() const {
+ return static_cast<ABSL_INTERNAL_WCHAR_T>(v_);
+}
+
+constexpr int128::operator short() const { // NOLINT(runtime/int)
+ return static_cast<short>(v_); // NOLINT(runtime/int)
+}
+
+constexpr int128::operator unsigned short() const { // NOLINT(runtime/int)
+ return static_cast<unsigned short>(v_); // NOLINT(runtime/int)
+}
+
+constexpr int128::operator int() const {
+ return static_cast<int>(v_);
+}
+
+constexpr int128::operator unsigned int() const {
+ return static_cast<unsigned int>(v_);
+}
+
+constexpr int128::operator long() const { // NOLINT(runtime/int)
+ return static_cast<long>(v_); // NOLINT(runtime/int)
+}
+
+constexpr int128::operator unsigned long() const { // NOLINT(runtime/int)
+ return static_cast<unsigned long>(v_); // NOLINT(runtime/int)
+}
+
+constexpr int128::operator long long() const { // NOLINT(runtime/int)
+ return static_cast<long long>(v_); // NOLINT(runtime/int)
+}
+
+constexpr int128::operator unsigned long long() const { // NOLINT(runtime/int)
+ return static_cast<unsigned long long>(v_); // NOLINT(runtime/int)
+}
+
+constexpr int128::operator __int128() const { return v_; }
+
+constexpr int128::operator unsigned __int128() const {
+ return static_cast<unsigned __int128>(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<float>(v_); }
+
+inline int128::operator double () const { return static_cast<double>(v_); }
+
+inline int128::operator long double() const {
+ return static_cast<long double>(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<float>(-*this)
+ : static_cast<float>(Int128Low64(*this)) +
+ std::ldexp(static_cast<float>(Int128High64(*this)), 64);
+}
+
+inline int128::operator double() const {
+ // See comment in int128::operator float() above.
+ return v_ < 0 && *this != Int128Min()
+ ? -static_cast<double>(-*this)
+ : static_cast<double>(Int128Low64(*this)) +
+ std::ldexp(static_cast<double>(Int128High64(*this)), 64);
+}
+
+inline int128::operator long double() const {
+ // See comment in int128::operator float() above.
+ return v_ < 0 && *this != Int128Min()
+ ? -static_cast<long double>(-*this)
+ : static_cast<long double>(Int128Low64(*this)) +
+ std::ldexp(static_cast<long double>(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<uint64_t>(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {}
+constexpr int128::int128(long v) // NOLINT(runtime/int)
+ : lo_{static_cast<uint64_t>(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {}
+constexpr int128::int128(long long v) // NOLINT(runtime/int)
+ : lo_{static_cast<uint64_t>(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<int64_t>(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<uint64_t>(v)} {}
+constexpr int128::int128(long v) // NOLINT(runtime/int)
+ : hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast<uint64_t>(v)} {}
+constexpr int128::int128(long long v) // NOLINT(runtime/int)
+ : hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast<uint64_t>(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<int64_t>(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<char>(static_cast<long long>(*this));
+}
+
+constexpr int128::operator signed char() const {
+ // NOLINTNEXTLINE(runtime/int)
+ return static_cast<signed char>(static_cast<long long>(*this));
+}
+
+constexpr int128::operator unsigned char() const {
+ return static_cast<unsigned char>(lo_);
+}
+
+constexpr int128::operator char16_t() const {
+ return static_cast<char16_t>(lo_);
+}
+
+constexpr int128::operator char32_t() const {
+ return static_cast<char32_t>(lo_);
+}
+
+constexpr int128::operator ABSL_INTERNAL_WCHAR_T() const {
+ // NOLINTNEXTLINE(runtime/int)
+ return static_cast<ABSL_INTERNAL_WCHAR_T>(static_cast<long long>(*this));
+}
+
+constexpr int128::operator short() const { // NOLINT(runtime/int)
+ // NOLINTNEXTLINE(runtime/int)
+ return static_cast<short>(static_cast<long long>(*this));
+}
+
+constexpr int128::operator unsigned short() const { // NOLINT(runtime/int)
+ return static_cast<unsigned short>(lo_); // NOLINT(runtime/int)
+}
+
+constexpr int128::operator int() const {
+ // NOLINTNEXTLINE(runtime/int)
+ return static_cast<int>(static_cast<long long>(*this));
+}
+
+constexpr int128::operator unsigned int() const {
+ return static_cast<unsigned int>(lo_);
+}
+
+constexpr int128::operator long() const { // NOLINT(runtime/int)
+ // NOLINTNEXTLINE(runtime/int)
+ return static_cast<long>(static_cast<long long>(*this));
+}
+
+constexpr int128::operator unsigned long() const { // NOLINT(runtime/int)
+ return static_cast<unsigned long>(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<unsigned long long>(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<float>(-*this)
+ : static_cast<float>(lo_) +
+ std::ldexp(static_cast<float>(hi_), 64);
+}
+
+inline int128::operator double() const {
+ // See comment in int128::operator float() above.
+ return hi_ < 0 && *this != Int128Min()
+ ? -static_cast<double>(-*this)
+ : static_cast<double>(lo_) +
+ std::ldexp(static_cast<double>(hi_), 64);
+}
+
+inline int128::operator long double() const {
+ // See comment in int128::operator float() above.
+ return hi_ < 0 && *this != Int128Min()
+ ? -static_cast<long double>(-*this)
+ : static_cast<long double>(lo_) +
+ std::ldexp(static_cast<long double>(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<int64_t>(Int128Low64(lhs) >> (64 - amount)),
+ Int128Low64(lhs) << amount);
+ }
+ return lhs;
+ }
+ return MakeInt128(static_cast<int64_t>(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<uint64_t>(Int128High64(lhs)) << (64 - amount)));
+ }
+ return lhs;
+ }
+ return MakeInt128(0,
+ static_cast<uint64_t>(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 <cstdint>
+#include <limits>
+#include <type_traits>
+
+// Clang on Windows has __builtin_clzll; otherwise we need to use the
+// windows intrinsic functions.
+#if defined(_MSC_VER) && !defined(__clang__)
+#include <intrin.h>
+#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 <class T>
+ABSL_MUST_USE_RESULT ABSL_ATTRIBUTE_ALWAYS_INLINE constexpr T RotateRight(
+ T x, int s) noexcept {
+ static_assert(std::is_unsigned<T>::value, "T must be unsigned");
+ static_assert(IsPowerOf2(std::numeric_limits<T>::digits),
+ "T must have a power-of-2 size");
+
+ return static_cast<T>(x >> (s & (std::numeric_limits<T>::digits - 1))) |
+ static_cast<T>(x << ((-s) & (std::numeric_limits<T>::digits - 1)));
+}
+
+template <class T>
+ABSL_MUST_USE_RESULT ABSL_ATTRIBUTE_ALWAYS_INLINE constexpr T RotateLeft(
+ T x, int s) noexcept {
+ static_assert(std::is_unsigned<T>::value, "T must be unsigned");
+ static_assert(IsPowerOf2(std::numeric_limits<T>::digits),
+ "T must have a power-of-2 size");
+
+ return static_cast<T>(x << (s & (std::numeric_limits<T>::digits - 1))) |
+ static_cast<T>(x >> ((-s) & (std::numeric_limits<T>::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<int>((((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<int>(
+ (((x + (x >> 4)) & 0xF0F0F0F0F0F0F0FULL) * 0x101010101010101ULL) >> 56);
+#endif
+}
+
+template <class T>
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline int
+Popcount(T x) noexcept {
+ static_assert(std::is_unsigned<T>::value, "T must be unsigned");
+ static_assert(IsPowerOf2(std::numeric_limits<T>::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<unsigned long>(x >> 32))) {
+ return 31 - result;
+ }
+ if (_BitScanReverse(&result, static_cast<unsigned long>(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 <typename T>
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int
+CountLeadingZeroes(T x) {
+ static_assert(std::is_unsigned<T>::value, "T must be unsigned");
+ static_assert(IsPowerOf2(std::numeric_limits<T>::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<uint16_t>(x)) -
+ (std::numeric_limits<uint16_t>::digits -
+ std::numeric_limits<T>::digits)
+ : (sizeof(T) <= sizeof(uint32_t)
+ ? CountLeadingZeroes32(static_cast<uint32_t>(x)) -
+ (std::numeric_limits<uint32_t>::digits -
+ std::numeric_limits<T>::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<uint32_t>(x) == 0) {
+ _BitScanForward(&result, static_cast<unsigned long>(x >> 32));
+ return result + 32;
+ }
+ _BitScanForward(&result, static_cast<unsigned long>(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 <class T>
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int
+CountTrailingZeroes(T x) noexcept {
+ static_assert(std::is_unsigned<T>::value, "T must be unsigned");
+ static_assert(IsPowerOf2(std::numeric_limits<T>::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<T>::digits
+ : (sizeof(T) <= sizeof(uint16_t)
+ ? CountTrailingZeroesNonzero16(static_cast<uint16_t>(x))
+ : (sizeof(T) <= sizeof(uint32_t)
+ ? CountTrailingZeroesNonzero32(
+ static_cast<uint32_t>(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 <class T>
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline
+ typename std::enable_if<std::is_unsigned<T>::value, T>::type
+ BitCeilPromotionHelper(T x, T promotion) {
+ return (T{1} << (x + promotion)) >> promotion;
+}
+
+template <class T>
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline
+ typename std::enable_if<std::is_unsigned<T>::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<T>(std::numeric_limits<T>::digits - CountLeadingZeroes(x)),
+ T{sizeof(T) >= sizeof(unsigned) ? 0
+ : std::numeric_limits<unsigned>::digits -
+ std::numeric_limits<T>::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 <limits>
+
+#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<long double>::digits ==
+ 2 * std::numeric_limits<double>::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 <t.sowa@ttmath.org>
- */
-
-/*
- * 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- bool RootCheckIndexTwo(ValueType & x, const ValueType & index, ErrorCode * err)
- {
- if( index == 2 )
- {
- x = Sqrt(x, err);
-
- return true;
- }
-
- return false;
- }
-
-
- template<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<class ValueType>
- 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<ValueType> 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<class ValueType>
- void SetFactorialSequence(std::vector<ValueType> & fact, uint more = 20)
- {
- if( more == 0 )
- more = 1;
-
- uint start = static_cast<uint>(fact.size());
- fact.resize(fact.size() + more);
-
- if( start == 0 )
- {
- fact[0] = 1;
- ++start;
- }
-
- for(uint i=start ; i<fact.size() ; ++i)
- {
- fact[i] = fact[i-1];
- fact[i].MulInt(i);
- }
- }
-
-
- /*!
- an auxiliary function used to calculate Bernoulli numbers
-
- this function returns a sum:
- sum(m) = sum_{k=0}^{m-1} {2^k * (m k) * B(k)} k in [0, m-1] (m k) means binomial coefficient = (m! / (k! * (m-k)!))
-
- you should have sufficient factorials in cgamma.fact
- (cgamma.fact should have at least m items)
-
- n_ should be equal 2
- */
- template<class ValueType>
- ValueType SetBernoulliNumbersSum(CGamma<ValueType> & cgamma, const ValueType & n_, uint m,
- const volatile StopCalculating * stop = 0)
- {
- ValueType k_, temp, temp2, temp3, sum;
-
- sum.SetZero();
-
- for(uint k=0 ; k<m ; ++k) // k<m means k<=m-1
- {
- if( stop && (k & 15)==0 ) // means: k % 16 == 0
- if( stop->WasStopSignal() )
- 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<class ValueType>
- bool SetBernoulliNumbersMore(CGamma<ValueType> & 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 ; m<cgamma.bern.size() ; ++m)
- {
- if( (m & 1) == 1 )
- {
- cgamma.bern[m].SetZero();
- }
- else
- {
- m_ = m;
-
- temp = n_; // n_ = 2
- temp.Pow(m_);
- // temp = 2^m
-
- denominator.SetOne();
- denominator.Sub(temp);
- if( denominator.exponent.AddOne() ) // it means: denominator.MulInt(2)
- denominator.SetNan();
-
- // denominator = 2 * (1 - 2^m)
-
- cgamma.bern[m] = SetBernoulliNumbersSum(cgamma, n_, m, stop);
-
- if( stop && stop->WasStopSignal() )
- {
- 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<MyBig> 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<class ValueType>
- bool SetBernoulliNumbers(CGamma<ValueType> & cgamma, uint more = 20, const volatile StopCalculating * stop = 0)
- {
- if( more == 0 )
- more = 1;
-
- uint start = static_cast<uint>(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<uint>(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<class ValueType>
- ValueType GammaFactorialHighSum(const ValueType & n, CGamma<ValueType> & cgamma, ErrorCode & err,
- const volatile StopCalculating * stop)
- {
- ValueType temp, temp2, denominator, sum, oldsum;
-
- sum.SetZero();
-
- for(uint m=2 ; m<TTMATH_ARITHMETIC_MAX_LOOP ; m+=2)
- {
- if( stop && (m & 3)==0 ) // (m & 3)==0 means: (m % 4)==0
- if( stop->WasStopSignal() )
- {
- 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<class ValueType>
- ValueType GammaFactorialHigh(const ValueType & n, CGamma<ValueType> & 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<class ValueType>
- ValueType GammaPlusHigh(ValueType n, CGamma<ValueType> & 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<class ValueType>
- ValueType GammaPlusLowIntegerInt(uint n, CGamma<ValueType> & cgamma)
- {
- TTMATH_ASSERT( n > 0 )
-
- if( n - 1 < static_cast<uint>(cgamma.fact.size()) )
- return cgamma.fact[n - 1];
-
- ValueType res;
- uint start = 2;
-
- if( cgamma.fact.size() < 2 )
- {
- res.SetOne();
- }
- else
- {
- start = static_cast<uint>(cgamma.fact.size());
- res = cgamma.fact[start-1];
- }
-
- for(uint i=start ; i<n ; ++i)
- res.MulInt(i);
-
- return res;
- }
-
-
- /*!
- 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]
- */
- template<class ValueType>
- ValueType GammaPlusLowInteger(const ValueType & n, CGamma<ValueType> & 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<class ValueType>
- ValueType GammaPlusLow(ValueType n, CGamma<ValueType> & 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<class ValueType>
- ValueType GammaPlus(const ValueType & n, CGamma<ValueType> & 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<class ValueType>
- ValueType GammaMinus(const ValueType & n, CGamma<ValueType> & 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<MyBig> 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<class ValueType>
- ValueType Gamma(const ValueType & n, CGamma<ValueType> & 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<class ValueType>
- ValueType Gamma(const ValueType & n, ErrorCode * err = 0)
- {
- // warning: this static object is not thread safe
- static CGamma<ValueType> 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<class ValueType>
- ValueType Factorial2(ValueType x,
- CGamma<ValueType> * 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<MyBig> 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<class ValueType>
- ValueType Factorial(const ValueType & x, CGamma<ValueType> & 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<class ValueType>
- ValueType Factorial(const ValueType & x, ErrorCode * err = 0)
- {
- return auxiliaryfunctions::Factorial2(x, (CGamma<ValueType>*)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<class ValueType>
- void CGamma<ValueType>::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 <t.sowa@ttmath.org>
- */
-
-/*
- * 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<uint>
-*/
-
-#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<uint value_size>
-class Int : public UInt<value_size>
-{
-public:
-
- /*!
- this method sets the max value which this class can hold
- (all bits will be one besides the last one)
- */
- void SetMax()
- {
- UInt<value_size>::SetMax();
- UInt<value_size>::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<value_size>::SetZero();
- UInt<value_size>::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<value_size>::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<value_size>::IsOnlyTheHighestBitSet() )
- return 1;
-
- UInt<value_size> temp(*this);
- UInt<value_size>::SetZero();
- UInt<value_size>::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<value_size>::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<value_size>::IsTheHighestBitSet() )
- return 1;
- }
-
- if( p1_is_sign && p2_is_sign )
- {
- if( ! UInt<value_size>::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<value_size> & ss2)
- {
- bool p1_is_sign = IsSign();
- bool p2_is_sign = ss2.IsSign();
-
- UInt<value_size>::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<value_size>::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<value_size>::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<value_size>::IsTheHighestBitSet() )
- return 1;
- }
-
- if( p1_is_sign && !p2_is_sign )
- {
- if( ! UInt<value_size>::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<value_size> & ss2)
- {
- bool p1_is_sign = IsSign();
- bool p2_is_sign = ss2.IsSign();
-
- UInt<value_size>::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<value_size>::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<value_size>::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<value_size>::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<value_size>::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<value_size>::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<value_size> 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<value_size>::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<value_size> ss2, Int<value_size> * 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<value_size>::Div(ss2, remainder);
-
- if( ss1_is_sign != ss2_is_sign )
- SetSign();
-
- if( ss1_is_sign && remainder )
- remainder->SetSign();
-
- return c;
- }
-
- uint Div(const Int<value_size> & ss2, Int<value_size> & 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<value_size>::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<value_size> & pow)
- {
- bool was_sign = IsSign();
- uint c = 0;
-
- if( was_sign )
- c += Abs();
-
- uint c_temp = UInt<value_size>::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<value_size> pow)
- {
- if( !pow.IsSign() )
- return Pow2(pow);
-
- if( UInt<value_size>::IsZero() )
- // if 'pow' is negative then
- // 'this' must be different from zero
- return 2;
-
- if( pow.ChangeSign() )
- return 1;
-
- Int<value_size> t(*this);
- uint c_temp = t.Pow2(pow);
- if( c_temp > 0 )
- return c_temp;
-
- UInt<value_size>::SetOne();
- if( Div(t) )
- return 1;
-
- return 0;
- }
-
-
-
- /*!
- *
- * convertion methods
- *
- */
-private:
-
-
- /*!
- an auxiliary method for converting both from UInt and Int
- */
- template<uint argument_size>
- uint FromUIntOrInt(const UInt<argument_size> & p, bool UInt_type)
- {
- uint min_size = (value_size < argument_size)? value_size : argument_size;
- uint i;
-
- for(i=0 ; i<min_size ; ++i)
- UInt<value_size>::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<value_size ; ++i)
- UInt<value_size>::table[i] = fill;
- }
- else
- {
- uint test = (UInt<value_size>::table[value_size-1] & TTMATH_UINT_HIGHEST_BIT)?
- TTMATH_UINT_MAX_VALUE : 0;
-
- if( UInt_type && test!=0 )
- return 1;
-
- for( ; i<argument_size ; ++i)
- if( p.table[i] != test )
- return 1;
- }
-
- return 0;
- }
-
-public:
-
- /*!
- this method converts an Int<another_size> 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 argument_size>
- uint FromInt(const Int<argument_size> & 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<value_size ; ++i)
- UInt<value_size>::table[i] = fill;
-
- UInt<value_size>::table[0] = uint(value);
-
- // there'll never be a carry here
- return 0;
- }
-
-
- /*!
- this method converts UInt<another_size> into this class
- */
- template<uint argument_size>
- uint FromUInt(const UInt<argument_size> & p)
- {
- return FromUIntOrInt(p, true);
- }
-
-
- /*!
- this method converts UInt<another_size> into this class
- */
- template<uint argument_size>
- uint FromInt(const UInt<argument_size> & p)
- {
- return FromUIntOrInt(p, true);
- }
-
-
- /*!
- this method converts the uint type into this class
- */
- uint FromUInt(uint value)
- {
- for(uint i=1 ; i<value_size ; ++i)
- UInt<value_size>::table[i] = 0;
-
- UInt<value_size>::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<value_size> & operator=(const Int<value_size> & p)
- {
- FromInt(p);
-
- return *this;
- }
- */
-
- /*!
- this operator converts an Int<another_size> type to this class
-
- it doesn't return a carry
- */
-/* template<uint argument_size>
- Int<value_size> & operator=(const Int<argument_size> & p)
- {
- FromInt(p);
-
- return *this;
- }
- */
-
- /*!
- this method converts the sint type to this class
- */
- Int<value_size> & 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<value_size> & u)
- {
- FromInt(u);
- }
-*/
-
- /*!
- a constructor for copying from another types
- */
-/* template<uint argument_size>
- Int(const Int<argument_size> & u)
- {
- // look that 'size' we still set as 'value_size' and not as u.value_size
- FromInt(u);
- }
-*/
-
-
- /*!
- this operator converts an UInt<another_size> type to this class
-
- it doesn't return a carry
- */
- template<uint argument_size>
- Int<value_size> & operator=(const UInt<argument_size> & p)
- {
- FromUInt(p);
-
- return *this;
- }
-
-
- /*!
- this method converts the Uint type to this class
- */
- Int<value_size> & 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<uint argument_size>
- Int(const UInt<argument_size> & 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<value_size>::FromUInt(n);
-
- if( c )
- return 1;
-
- if( value_size == 1 )
- return ((UInt<value_size>::table[0] & TTMATH_UINT_HIGHEST_BIT) == 0) ? 0 : 1;
-
- if( value_size == 2 )
- return ((UInt<value_size>::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<value_size>::table[0] = (uint)(ulint)n;
-
- if( value_size == 1 )
- {
- if( uint(ulint(n) >> 32) != mask )
- return 1;
-
- return ((UInt<value_size>::table[0] & TTMATH_UINT_HIGHEST_BIT) == (mask & TTMATH_UINT_HIGHEST_BIT)) ? 0 : 1;
- }
-
- UInt<value_size>::table[1] = (uint)(ulint(n) >> 32);
-
- for(uint i=2 ; i<value_size ; ++i)
- UInt<value_size>::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<value_size> & 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<value_size> & 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<value_size> & 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<value_size> & 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<value_size>::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<value_size>::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<value_size>::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<value_size ; ++i)
- if( UInt<value_size>::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<value_size>::ToUInt(result);
-
- if( value_size == 1 )
- return (UInt<value_size>::table[0] & TTMATH_UINT_HIGHEST_BIT) == 0 ? 0 : 1;
-
- if( value_size == 2 )
- return (UInt<value_size>::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<value_size>::table[0]));
- }
- else
- {
- uint low = UInt<value_size>::table[0];
- uint high = UInt<value_size>::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<value_size ; ++i)
- if( UInt<value_size>::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<value_size>::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<value_size>::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<value_size ; ++i)
- if( UInt<value_size>::table[i] != mask )
- return 1;
-
- return 0;
- }
-
-#endif
-
-
-
- /*!
- an auxiliary method for converting to a string
- */
- template<class string_type>
- void ToStringBase(string_type & result, uint b = 10) const
- {
- if( IsSign() )
- {
- Int<value_size> temp(*this);
- temp.Abs();
- temp.UInt<value_size>::ToStringBase(result, b, true);
- }
- else
- {
- UInt<value_size>::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<class char_type>
- 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<value_size>::FromString(s,b,after_source,value_read) )
- return 1;
-
- if( is_sign )
- {
- Int<value_size> 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<value_size>::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<value_size> mmax;
-
- mmax.SetMax();
-
- if( UInt<value_size>::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<value_size> & 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<value_size> & operator=(const wchar_t * s)
- {
- FromString(s);
-
- return *this;
- }
-
-
- /*!
- this operator converts a string into its value (with base = 10)
- */
- Int<value_size> & operator=(const std::wstring & s)
- {
- FromString( s.c_str() );
-
- return *this;
- }
-
-#endif
-
-
- /*!
- this operator converts a string into its value (with base = 10)
- */
- Int<value_size> & operator=(const std::string & s)
- {
- FromString( s.c_str() );
-
- return *this;
- }
-
-
-
- /*!
- *
- * methods for comparing
- *
- *
- */
-
- bool operator==(const Int<value_size> & l) const
- {
- return UInt<value_size>::operator==(l);
- }
-
- bool operator!=(const Int<value_size> & l) const
- {
- return UInt<value_size>::operator!=(l);
- }
-
- bool operator<(const Int<value_size> & l) const
- {
- sint i=value_size-1;
-
- sint a1 = sint(UInt<value_size>::table[i]);
- sint a2 = sint(l.table[i]);
-
- if( a1 != a2 )
- return a1 < a2;
-
-
- for(--i ; i>=0 ; --i)
- {
- if( UInt<value_size>::table[i] != l.table[i] )
- // comparison as unsigned int
- return UInt<value_size>::table[i] < l.table[i];
- }
-
- // they're equal
- return false;
- }
-
-
- bool operator>(const Int<value_size> & l) const
- {
- sint i=value_size-1;
-
- sint a1 = sint(UInt<value_size>::table[i]);
- sint a2 = sint(l.table[i]);
-
- if( a1 != a2 )
- return a1 > a2;
-
-
- for(--i ; i>=0 ; --i)
- {
- if( UInt<value_size>::table[i] != l.table[i] )
- // comparison as unsigned int
- return UInt<value_size>::table[i] > l.table[i];
- }
-
- // they're equal
- return false;
- }
-
-
- bool operator<=(const Int<value_size> & l) const
- {
- sint i=value_size-1;
-
- sint a1 = sint(UInt<value_size>::table[i]);
- sint a2 = sint(l.table[i]);
-
- if( a1 != a2 )
- return a1 < a2;
-
-
- for(--i ; i>=0 ; --i)
- {
- if( UInt<value_size>::table[i] != l.table[i] )
- // comparison as unsigned int
- return UInt<value_size>::table[i] < l.table[i];
- }
-
- // they're equal
- return true;
- }
-
-
- bool operator>=(const Int<value_size> & l) const
- {
- sint i=value_size-1;
-
- sint a1 = sint(UInt<value_size>::table[i]);
- sint a2 = sint(l.table[i]);
-
- if( a1 != a2 )
- return a1 > a2;
-
-
- for(--i ; i>=0 ; --i)
- {
- if( UInt<value_size>::table[i] != l.table[i] )
- // comparison as unsigned int
- return UInt<value_size>::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<value_size> operator-() const
- {
- Int<value_size> temp(*this);
-
- temp.ChangeSign();
-
- return temp;
- }
-
-
- Int<value_size> operator-(const Int<value_size> & p2) const
- {
- Int<value_size> temp(*this);
-
- temp.Sub(p2);
-
- return temp;
- }
-
-
- Int<value_size> & operator-=(const Int<value_size> & p2)
- {
- Sub(p2);
-
- return *this;
- }
-
-
- Int<value_size> operator+(const Int<value_size> & p2) const
- {
- Int<value_size> temp(*this);
-
- temp.Add(p2);
-
- return temp;
- }
-
-
- Int<value_size> & operator+=(const Int<value_size> & p2)
- {
- Add(p2);
-
- return *this;
- }
-
-
- Int<value_size> operator*(const Int<value_size> & p2) const
- {
- Int<value_size> temp(*this);
-
- temp.Mul(p2);
-
- return temp;
- }
-
-
- Int<value_size> & operator*=(const Int<value_size> & p2)
- {
- Mul(p2);
-
- return *this;
- }
-
-
- Int<value_size> operator/(const Int<value_size> & p2) const
- {
- Int<value_size> temp(*this);
-
- temp.Div(p2);
-
- return temp;
- }
-
-
- Int<value_size> & operator/=(const Int<value_size> & p2)
- {
- Div(p2);
-
- return *this;
- }
-
-
- Int<value_size> operator%(const Int<value_size> & p2) const
- {
- Int<value_size> temp(*this);
- Int<value_size> remainder;
-
- temp.Div(p2, remainder);
-
- return remainder;
- }
-
-
- Int<value_size> & operator%=(const Int<value_size> & p2)
- {
- Int<value_size> remainder;
-
- Div(p2, remainder);
- operator=(remainder);
-
- return *this;
- }
-
-
- /*!
- Prefix operator e.g. ++variable
- */
- UInt<value_size> & operator++()
- {
- AddOne();
-
- return *this;
- }
-
-
- /*!
- Postfix operator e.g. variable++
- */
- UInt<value_size> operator++(int)
- {
- UInt<value_size> temp( *this );
-
- AddOne();
-
- return temp;
- }
-
-
- UInt<value_size> & operator--()
- {
- SubOne();
-
- return *this;
- }
-
-
- UInt<value_size> operator--(int)
- {
- UInt<value_size> temp( *this );
-
- SubOne();
-
- return temp;
- }
-
-
-
- /*!
- *
- * input/output operators for standard streams
- *
- */
-
-private:
-
- /*!
- an auxiliary method for outputing to standard streams
- */
- template<class ostream_type, class string_type>
- static ostream_type & OutputToStream(ostream_type & s, const Int<value_size> & 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<value_size> & l)
- {
- return OutputToStream<std::ostream, std::string>(s, l);
- }
-
-
-#ifndef TTMATH_DONT_USE_WCHAR
-
- /*!
- output to standard streams
- */
- friend std::wostream & operator<<(std::wostream & s, const Int<value_size> & l)
- {
- return OutputToStream<std::wostream, std::wstring>(s, l);
- }
-
-#endif
-
-
-
-private:
-
- /*!
- an auxiliary method for converting from a string
- */
- template<class istream_type, class string_type, class char_type>
- static istream_type & InputFromStream(istream_type & s, Int<value_size> & 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<char_type>(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<value_size> & l)
- {
- return InputFromStream<std::istream, std::string, char>(s, l);
- }
-
-
-#ifndef TTMATH_DONT_USE_WCHAR
-
- /*!
- input from standard streams
- */
- friend std::wistream & operator>>(std::wistream & s, Int<value_size> & l)
- {
- return InputFromStream<std::wistream, std::wstring, wchar_t>(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 <t.sowa@ttmath.org>
- */
-
-/*
- * 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 <string>
-
-
-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<char>(*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<class char_type>
-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 <t.sowa@ttmath.org>
- */
-
-/*
- * 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 <string>
-#include <vector>
-#include <list>
-#include <map>
-
-#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<std::string, Item> 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<class string_type>
- 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 ValueType>
-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<Item> 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<MyBig> 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<class ValueType>
-struct CGamma
-{
- /*!
- this table holds factorials
- 1
- 1
- 2
- 6
- 24
- 120
- 720
- .......
- */
- std::vector<ValueType> 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<ValueType> 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<ValueType> 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 <t.sowa@ttmath.org>
- */
-
-/*
- * 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 <windows.h>
-#include <cstdio>
-#endif
-
-#ifdef TTMATH_POSIX_THREADS
-#include <pthread.h>
-#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/ttmath.h>
-
- 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 <t.sowa@ttmath.org>
- */
-
-/*
- * 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 <stdexcept>
-#include <sstream>
-#include <vector>
-
-#ifndef _MSC_VER
-#include <stdint.h>
-// 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 <t.sowa@ttmath.org>
- */
-
-/*
- * 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<uint>
-*/
-
-#include <iostream>
-#include <iomanip>
-
-
-#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<uint value_size>
-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<class char_type, class ostream_type>
- 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<vector_len ; ++i)
- output << " table[" << i << "]: " << vector[i] << std::endl;
- }
-
-
- /*!
- this method is used when macro TTMATH_DEBUG_LOG is defined
- */
- template<class char_type, class ostream_type>
- 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<class char_type, class ostream_type>
- 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<class char_type, class ostream_type>
- 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<value_size ; ++i)
- table[i] = 0;
-
- TTMATH_LOG("UInt::SetZero")
- }
-
-
- /*!
- this method sets one
- */
- void SetOne()
- {
- SetZero();
- table[0] = 1;
-
- TTMATH_LOG("UInt::SetOne")
- }
-
-
- /*!
- this method sets the max value which this class can hold
- (all bits will be one)
- */
- void SetMax()
- {
- for(uint i=0 ; i<value_size ; ++i)
- table[i] = TTMATH_UINT_MAX_VALUE;
-
- TTMATH_LOG("UInt::SetMax")
- }
-
-
- /*!
- this method sets the min value which this class can hold
- (for an unsigned integer value the zero is the smallest value)
- */
- void SetMin()
- {
- SetZero();
-
- TTMATH_LOG("UInt::SetMin")
- }
-
-
- /*!
- this method swappes this for an argument
- */
- void Swap(UInt<value_size> & ss2)
- {
- for(uint i=0 ; i<value_size ; ++i)
- {
- uint temp = table[i];
- table[i] = ss2.table[i];
- ss2.table[i] = temp;
- }
- }
-
-
-#ifdef TTMATH_PLATFORM32
-
- /*!
- 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)
-
- 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
- */
- void SetFromTable(const uint * 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<temp_table_len; --i, ++temp_table_index)
- table[i] = temp_table[ temp_table_index ];
-
-
- // rounding mantissa
- if( temp_table_index < temp_table_len )
- {
- if( (temp_table[temp_table_index] & TTMATH_UINT_HIGHEST_BIT) != 0 )
- {
- /*
- very simply rounding
- if the bit from not used last word from temp_table is set to one
- we're rouding the lowest word in the table
-
- in fact there should be a normal addition but
- we don't use Add() or AddTwoInts() because these methods
- can set a carry and then there'll be a small problem
- for optimization
- */
- if( table[0] != TTMATH_UINT_MAX_VALUE )
- ++table[0];
- }
- }
-
- // cleaning the rest of the mantissa
- for( ; i>=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<temp_table_len; --i, ++temp_table_index)
- {
- table[i] = uint(temp_table[ temp_table_index ]) << 32;
-
- ++temp_table_index;
-
- if( temp_table_index<temp_table_len )
- table[i] |= temp_table[ temp_table_index ];
- }
-
-
- // rounding mantissa
- if( temp_table_index < temp_table_len )
- {
- if( (temp_table[temp_table_index] & TTMATH_UINT_HIGHEST_BIT) != 0 )
- {
- /*
- very simply rounding
- if the bit from not used last word from temp_table is set to one
- we're rouding the lowest word in the table
-
- in fact there should be a normal addition but
- we don't use Add() or AddTwoInts() because these methods
- can set a carry and then there'll be a small problem
- for optimization
- */
- if( table[0] != TTMATH_UINT_MAX_VALUE )
- ++table[0];
- }
- }
-
- // cleaning the rest of the mantissa
- for( ; i >= 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<value_size ; ++i)
- table[i] = mask;
-
- rest_bits = 0;
- }
- else
- if( all_words > 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<value_size ; ++i)
- table[i] = mask;
-
- rest_bits = 0;
- }
- else if( all_words > 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<value_size ; ++first, ++second)
- table[first] = table[second];
-
- // setting the rest to 'c'
- for( ; first<value_size ; ++first )
- table[first] = mask;
- }
-
- TTMATH_LOG("UInt::RcrMoveAllWords")
- }
-
-public:
-
- /*!
- moving all bits into the right side 'bits' times
- c -> 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 && table[table_id]==0 ; ++table_id);
-
- if( 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<value_size> & ss2)
- {
- for(uint x=0 ; x<value_size ; ++x)
- table[x] &= ss2.table[x];
-
- TTMATH_LOG("UInt::BitAnd")
- }
-
-
- /*!
- this method performs a bitwise operation OR
- */
- void BitOr(const UInt<value_size> & ss2)
- {
- for(uint x=0 ; x<value_size ; ++x)
- table[x] |= ss2.table[x];
-
- TTMATH_LOG("UInt::BitOr")
- }
-
-
- /*!
- this method performs a bitwise operation XOR
- */
- void BitXor(const UInt<value_size> & ss2)
- {
- for(uint x=0 ; x<value_size ; ++x)
- table[x] ^= ss2.table[x];
-
- TTMATH_LOG("UInt::BitXor")
- }
-
-
- /*!
- this method performs a bitwise operation NOT
- */
- void BitNot()
- {
- for(uint x=0 ; x<value_size ; ++x)
- table[x] = ~table[x];
-
- TTMATH_LOG("UInt::BitNot")
- }
-
-
- /*!
- this method performs a bitwise operation NOT but only
- on the range of <0, leading_bit>
-
- 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<table_id ; ++x)
- table[x] = ~table[x];
-
- uint mask = TTMATH_UINT_MAX_VALUE;
- uint shift = TTMATH_BITS_PER_UINT - index - 1;
-
- if(shift)
- mask >>= 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<value_size> u(*this);
- SetZero();
-
- if( ss2 == 0 )
- {
- TTMATH_LOGC("UInt::MulInt(uint)", 0)
- return 0;
- }
-
- for(x1=0 ; x1<value_size-1 ; ++x1)
- {
- MulTwoWords(u.table[x1], ss2, &r2, &r1);
- c += AddTwoInts(r2,r1,x1);
- }
-
- // x1 = value_size-1 (last word)
- MulTwoWords(u.table[x1], ss2, &r2, &r1);
- c += (r2!=0) ? 1 : 0;
- c += AddInt(r1, x1);
-
- TTMATH_LOGC("UInt::MulInt(uint)", c)
-
- return (c==0)? 0 : 1;
- }
-
-
- /*!
- multiplication: result = this * ss2
-
- we're using this method only when result_size is greater than value_size
- if so there will not be a carry
- */
- template<uint result_size>
- void MulInt(uint ss2, UInt<result_size> & 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<x1size && table[x1start]==0 ; ++x1start);
- }
-
- for(uint x1=x1start ; x1<x1size ; ++x1)
- {
- MulTwoWords(table[x1], ss2, &r2, &r1 );
- result.AddTwoInts(r2,r1,x1);
- }
-
- TTMATH_VECTOR_LOG("UInt::MulInt(uint, UInt<>)", result.table, result_size)
-
- return;
- }
-
-
-
- /*!
- the multiplication 'this' = 'this' * ss2
-
- algorithm: 100 - means automatically choose the fastest algorithm
- */
- uint Mul(const UInt<value_size> & 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<value_size> & ss2,
- UInt<value_size*2> & 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<value_size> & ss2)
- {
- TTMATH_REFERENCE_ASSERT( ss2 )
-
- UInt<value_size> 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<value_size> & ss2)
- {
- if( this == &ss2 )
- {
- UInt<value_size> 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<value_size> & ss2_, UInt<value_size*2> & result)
- {
- UInt<value_size*2> ss2;
- uint i;
-
- // copying *this into result and ss2_ into ss2
- for(i=0 ; i<value_size ; ++i)
- {
- result.table[i] = table[i];
- ss2.table[i] = ss2_.table[i];
- }
-
- // cleaning the highest bytes in result and ss2
- for( ; i < value_size*2 ; ++i)
- {
- result.table[i] = 0;
- ss2.table[i] = 0;
- }
-
- // multiply
- // (there will not be a carry)
- result.Mul1( ss2 );
-
- TTMATH_LOG("UInt::Mul1Big")
- }
-
-
-
- /*!
- the second version of the multiplication algorithm
-
- this algorithm is similar to the 'schoolbook method' which is done by hand
- */
-
- /*!
- multiplication: this = this * ss2
-
- it returns carry if it has been
- */
- uint Mul2(const UInt<value_size> & ss2)
- {
- UInt<value_size*2> result;
- uint i, c = 0;
-
- Mul2Big(ss2, result);
-
- // copying result
- for(i=0 ; i<value_size ; ++i)
- table[i] = result.table[i];
-
- // testing carry
- for( ; i<value_size*2 ; ++i)
- if( result.table[i] != 0 )
- {
- c = 1;
- break;
- }
-
- TTMATH_LOGC("UInt::Mul2", c)
-
- return c;
- }
-
-
- /*!
- multiplication: result = this * ss2
-
- result is twice bigger than this and ss2
- this method never returns carry
- */
- void Mul2Big(const UInt<value_size> & ss2, UInt<value_size*2> & result)
- {
- Mul2Big2<value_size>(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<uint ss_size>
- void Mul2Big2(const uint * ss1, const uint * ss2, UInt<ss_size*2> & 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<x1size && ss1[x1start]==0 ; ++x1start);
- for(x2start=0 ; x2start<x2size && ss2[x2start]==0 ; ++x2start);
- }
-
- Mul2Big3<ss_size>(ss1, ss2, result, x1start, x1size, x2start, x2size);
- }
-
-
-
- /*!
- an auxiliary method for calculating the multiplication
- */
- template<uint ss_size>
- void Mul2Big3(const uint * ss1, const uint * ss2, UInt<ss_size*2> & 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<x1size ; ++x1)
- {
- for(uint x2=x2start ; x2<x2size ; ++x2)
- {
- MulTwoWords(ss1[x1], ss2[x2], &r2, &r1);
- result.AddTwoInts(r2, r1, x2+x1);
- // here will never be a carry
- }
- }
- }
-
-
-public:
-
-
- /*!
- multiplication: this = this * ss2
-
- This is Karatsuba Multiplication algorithm, we're using it when value_size is greater than
- or equal to TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE macro (defined in ttmathuint.h).
- If value_size is smaller then we're using Mul2Big() instead.
-
- Karatsuba multiplication:
- Assume we have:
- this = x = x1*B^m + x0
- ss2 = y = y1*B^m + y0
- where x0 and y0 are less than B^m
- the product from multiplication we can show as:
- x*y = (x1*B^m + x0)(y1*B^m + y0) = z2*B^(2m) + z1*B^m + z0
- where
- z2 = x1*y1
- z1 = x1*y0 + x0*y1
- z0 = x0*y0
- this is standard schoolbook algorithm with O(n^2), Karatsuba observed that z1 can be given in other form:
- z1 = (x1 + x0)*(y1 + y0) - z2 - z0 / z1 = (x1*y1 + x1*y0 + x0*y1 + x0*y0) - x1*y1 - x0*y0 = x1*y0 + x0*y1 /
- and to calculate the multiplication we need only three multiplications (with some additions and subtractions)
-
- Our objects 'this' and 'ss2' we divide into two parts and by using recurrence we calculate the multiplication.
- Karatsuba multiplication has O( n^(ln(3)/ln(2)) )
- */
- uint Mul3(const UInt<value_size> & ss2)
- {
- UInt<value_size*2> result;
- uint i, c = 0;
-
- Mul3Big(ss2, result);
-
- // copying result
- for(i=0 ; i<value_size ; ++i)
- table[i] = result.table[i];
-
- // testing carry
- for( ; i<value_size*2 ; ++i)
- if( result.table[i] != 0 )
- {
- c = 1;
- break;
- }
-
- TTMATH_LOGC("UInt::Mul3", c)
-
- return c;
- }
-
-
-
- /*!
- multiplication: result = this * ss2
-
- result is twice bigger than this and ss2,
- this method never returns carry,
- (Karatsuba multiplication)
- */
- void Mul3Big(const UInt<value_size> & ss2, UInt<value_size*2> & result)
- {
- Mul3Big2<value_size>(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<uint ss_size>
- void Mul3Big2(const uint * ss1, const uint * ss2, uint * result)
- {
- const uint * x1, * x0, * y1, * y0;
-
-
- if( ss_size>1 && ss_size<TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE )
- {
- UInt<ss_size*2> res;
- Mul2Big2<ss_size>(ss1, ss2, res);
-
-#ifdef __clang__
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wtautological-compare"
-#endif
-
- for(uint i=0 ; i<ss_size*2 ; ++i)
- result[i] = res.table[i];
-
-#ifdef __clang__
-#pragma clang diagnostic pop
-#endif
-
- return;
- }
- else
- if( ss_size == 1 )
- {
- return MulTwoWords(*ss1, *ss2, &result[1], &result[0]);
- }
-
-
- if( (ss_size & 1) == 1 )
- {
- // ss_size is odd
- x0 = ss1;
- y0 = ss2;
- x1 = ss1 + ss_size / 2 + 1;
- y1 = ss2 + ss_size / 2 + 1;
-
- // the second vectors (x1 and y1) are smaller about one from the first ones (x0 and y0)
- Mul3Big3<ss_size/2 + 1, ss_size/2, ss_size*2>(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<ss_size/2, ss_size/2, ss_size*2>(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 first_size, uint second_size, uint result_size>
- uint Mul3Big3(const uint * x1, const uint * x0, const uint * y1, const uint * y0, uint * result)
- {
- uint i, c, xc, yc;
-
- UInt<first_size> temp, temp2;
- UInt<first_size*3> z1;
-
- // z0 and z2 we store directly in the result (we don't use any temporary variables)
- Mul3Big2<first_size>(x0, y0, result); // z0
- Mul3Big2<second_size>(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<first_size>, 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<first_size>(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<first_size*3 ; ++i)
- z1.table[i] = 0;
-
-#ifdef __clang__
-#pragma clang diagnostic pop
-#endif
-
- if( xc )
- {
- c = AddVector(z1.table+first_size, temp2.table, first_size*3-first_size, first_size, z1.table+first_size);
- TTMATH_ASSERT( c==0 )
- }
-
- if( yc )
- {
- c = AddVector(z1.table+first_size, temp.table, first_size*3-first_size, first_size, z1.table+first_size);
- TTMATH_ASSERT( c==0 )
- }
-
-
- if( xc && yc )
- {
-#ifdef __clang__
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wtautological-compare"
-#endif
-
- for( i=first_size*2 ; i<first_size*3 ; ++i )
- if( ++z1.table[i] != 0 )
- break; // break if there was no carry
-
-#ifdef __clang__
-#pragma clang diagnostic pop
-#endif
- }
-
- // z1 = z1 - z2
- c = SubVector(z1.table, result+first_size*2, first_size*3, second_size*2, z1.table);
- TTMATH_ASSERT(c==0)
-
- // z1 = z1 - z0
- c = SubVector(z1.table, result, first_size*3, first_size*2, z1.table);
- TTMATH_ASSERT(c==0)
-
- // here we've calculated the z1
- // now we're adding it to the result
-
- if( first_size > 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<first_size*3 ; ++i)
- {
- TTMATH_ASSERT( z1.table[i] == 0 )
- }
-
-#ifdef __clang__
-#pragma clang diagnostic pop
-#endif
-
- c = AddVector(result+first_size, z1.table, result_size-first_size, z1_size, result+first_size);
- TTMATH_ASSERT(c==0)
- }
- else
- {
- c = AddVector(result+first_size, z1.table, result_size-first_size, first_size*3, result+first_size);
- TTMATH_ASSERT(c==0)
- }
- return c;
- }
-
-
-
-#ifdef _MSC_VER
-#pragma warning (default : 4717)
-#endif
-
-
-public:
-
-
- /*!
- multiplication this = this * ss2
- */
- uint MulFastest(const UInt<value_size> & ss2)
- {
- UInt<value_size*2> result;
- uint i, c = 0;
-
- MulFastestBig(ss2, result);
-
- // copying result
- for(i=0 ; i<value_size ; ++i)
- table[i] = result.table[i];
-
- // testing carry
- for( ; i<value_size*2 ; ++i)
- if( result.table[i] != 0 )
- {
- c = 1;
- break;
- }
-
- TTMATH_LOGC("UInt::MulFastest", c)
-
- return c;
- }
-
-
- /*!
- multiplication result = this * ss2
-
- this method is trying to select the fastest algorithm
- (in the future this method can be improved)
- */
- void MulFastestBig(const UInt<value_size> & ss2, UInt<value_size*2> & 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<x1size && table[x1start]==0 ; ++x1start);
- for(x2start=0 ; x2start<x2size && ss2.table[x2start]==0 ; ++x2start);
-
- uint distancex1 = x1size - x1start;
- uint distancex2 = x2size - x2start;
-
- if( distancex1 < 3 || distancex2 < 3 )
- // either 'this' or 'ss2' have only 2 (or 1) items different from zero (side by side)
- // (this condition in the future can be improved)
- return Mul2Big3<value_size>(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<value_size> 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<value_size> & divisor,
- UInt<value_size> * 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<value_size> & divisor, UInt<value_size> & 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<value_size> & v,
- uint & m, uint & n,
- UInt<value_size> * 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<value_size> & 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<value_size> & divisor, UInt<value_size> * remainder = 0)
- {
- uint m,n, test;
-
- test = Div_StandardTest(divisor, m, n, remainder);
- if( test < 2 )
- return test;
-
- if( !remainder )
- {
- UInt<value_size> rem;
-
- return Div1_Calculate(divisor, rem);
- }
-
- return Div1_Calculate(divisor, *remainder);
- }
-
-
- /*!
- the first division algorithm
- radix 2
- */
- uint Div1(const UInt<value_size> & divisor, UInt<value_size> & remainder)
- {
- return Div1(divisor, &remainder);
- }
-
-
-private:
-
- uint Div1_Calculate(const UInt<value_size> & divisor, UInt<value_size> & rest)
- {
- if( this == &divisor )
- {
- UInt<value_size> divisor_copy(divisor);
- return Div1_CalculateRef(divisor_copy, rest);
- }
- else
- {
- return Div1_CalculateRef(divisor, rest);
- }
- }
-
-
- uint Div1_CalculateRef(const UInt<value_size> & divisor, UInt<value_size> & 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<value_size> & divisor, UInt<value_size> * remainder = 0)
- {
- if( this == &divisor )
- {
- UInt<value_size> 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<value_size> & divisor, UInt<value_size> & remainder)
- {
- return Div2(divisor, &remainder);
- }
-
-
-private:
-
- /*!
- the second division algorithm
-
- return values:
- 0 - ok
- 1 - division by zero
- */
- uint Div2Ref(const UInt<value_size> & divisor, UInt<value_size> * 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<value_size> & divisor, UInt<value_size> * 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<value_size> 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<value_size> & divisor,
- UInt<value_size> * 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<value_size> & divisor,
- UInt<value_size> * 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<value_size> & ss2, UInt<value_size> * remainder = 0)
- {
- if( this == &ss2 )
- {
- UInt<value_size> copy_ss2(ss2);
- return Div3Ref(copy_ss2, remainder);
- }
- else
- {
- return Div3Ref(ss2, remainder);
- }
- }
-
-
- /*!
- the third division algorithm
- */
- uint Div3(const UInt<value_size> & ss2, UInt<value_size> & 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<value_size> & v, UInt<value_size> * 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<value_size> v, UInt<value_size> * remainder, uint m, uint n)
- {
- TTMATH_ASSERT( n>=2 )
-
- UInt<value_size+1> uu, vv;
- UInt<value_size> 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<value_size ; ++i)
- q.table[i] = 0;
-
- while( true )
- {
- u1 = table[j+n-1];
- u0 = table[j+n-2];
- v1 = v.table[n-1];
- v0 = v.table[n-2];
-
- uint qp = Div3_Calculate(u2,u1,u0, v1,v0);
-
- Div3_MakeNewU(uu, j, n, u2);
- Div3_MultiplySubtract(uu, vv, qp);
- Div3_CopyNewU(uu, j, n);
-
- q.table[j] = qp;
-
- // the next loop
- if( j-- == 0 )
- break;
-
- u2 = table[j+n];
- }
-
- if( remainder )
- Div3_Unnormalize(remainder, n, d);
-
- *this = q;
-
- TTMATH_LOG("UInt::Div3_Division")
- }
-
-
- void Div3_MakeNewU(UInt<value_size+1> & uu, uint j, uint n, uint u_max)
- {
- uint i;
-
- for(i=0 ; i<n ; ++i, ++j)
- uu.table[i] = table[j];
-
- // 'n' is from <1..value_size> 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<value_size+1 ; ++i)
- uu.table[i] = 0;
-
- TTMATH_LOG("UInt::Div3_MakeNewU")
- }
-
-
- void Div3_CopyNewU(const UInt<value_size+1> & uu, uint j, uint n)
- {
- uint i;
-
- for(i=0 ; i<n ; ++i)
- table[i+j] = uu.table[i];
-
- if( i+j < value_size )
- table[i+j] = uu.table[i];
-
- TTMATH_LOG("UInt::Div3_CopyNewU")
- }
-
-
- /*!
- we're making the new 'vv'
- the value is actually the same but the 'table' is bigger (value_size+1)
- */
- void Div3_MakeBiggerV(const UInt<value_size> & v, UInt<value_size+1> & vv)
- {
- for(uint i=0 ; i<value_size ; ++i)
- vv.table[i] = v.table[i];
-
- vv.table[value_size] = 0;
-
- TTMATH_LOG("UInt::Div3_MakeBiggerV")
- }
-
-
- /*!
- we're moving all bits from 'v' into the left side of the n-1 word
- (the highest bit at v.table[n-1] will be equal one,
- the bits from 'this' we're moving the same times as 'v')
-
- return values:
- d - how many times we've moved
- return - the next-left value from 'this' (that after table[value_size-1])
- */
- uint Div3_Normalize(UInt<value_size> & 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<value_size> * remainder, uint n, uint d)
- {
- for(uint i=n ; i<value_size ; ++i)
- table[i] = 0;
-
- Rcr(d,0);
-
- *remainder = *this;
-
- TTMATH_LOG("UInt::Div3_Unnormalize")
- }
-
-
- uint Div3_Calculate(uint u2, uint u1, uint u0, uint v1, uint v0)
- {
- UInt<2> 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<b from the book)
- next_test = true;
- }
- }
- while( next_test );
-
- TTMATH_LOG("UInt::Div3_Calculate")
-
- return u_temp.table[0];
- }
-
-
-
- void Div3_MultiplySubtract( UInt<value_size+1> & uu,
- const UInt<value_size+1> & vv, uint & qp)
- {
- // D4 (in the book)
-
- UInt<value_size+1> 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<value_size> pow)
- {
- if(pow.IsZero() && IsZero())
- // we don't define zero^zero
- return 2;
-
- UInt<value_size> start(*this);
- UInt<value_size> 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<value_size> bit, temp;
-
- if( IsZero() )
- return;
-
- UInt<value_size> 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<value_size-1 ; ++i)
- if( table[i] != 0 )
- return false;
-
-#ifdef __clang__
-#pragma clang diagnostic pop
-#endif
- if( table[value_size-1] != TTMATH_UINT_HIGHEST_BIT )
- return false;
-
- return true;
- }
-
-
- /*!
- returning true if only the lowest bit is set
- */
- bool IsOnlyTheLowestBitSet() const
- {
- if( table[0] != 1 )
- return false;
-
- for(uint i=1 ; i<value_size ; ++i)
- if( table[i] != 0 )
- return false;
-
- return true;
- }
-
-
- /*!
- this method returns true if the value is equal zero
- */
- bool IsZero() const
- {
- for(uint i=0 ; i<value_size ; ++i)
- if(table[i] != 0)
- return false;
-
- return true;
- }
-
-
- /*!
- returning true if first 'bits' bits are equal zero
- */
- bool AreFirstBitsZero(uint bits) const
- {
- TTMATH_ASSERT( bits <= value_size * TTMATH_BITS_PER_UINT )
-
- uint index = bits / TTMATH_BITS_PER_UINT;
- uint rest = bits % TTMATH_BITS_PER_UINT;
- uint i;
-
- for(i=0 ; i<index ; ++i)
- if(table[i] != 0 )
- return false;
-
- if( rest == 0 )
- return true;
-
- uint mask = TTMATH_UINT_MAX_VALUE >> (TTMATH_BITS_PER_UINT - rest);
-
- return (table[i] & mask) == 0;
- }
-
-
-
- /*!
- *
- * conversion methods
- *
- */
-
-
-
- /*!
- this method converts an UInt<another_size> 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<value_size>::SetMax()
-
- it returns a carry if the value 'p' is too big
- */
- template<uint argument_size>
- uint FromUInt(const UInt<argument_size> & p)
- {
- uint min_size = (value_size < argument_size)? value_size : argument_size;
- uint i;
-
- for(i=0 ; i<min_size ; ++i)
- table[i] = p.table[i];
-
-
- if( value_size > argument_size )
- {
- // 'this' is longer than 'p'
-
- for( ; i<value_size ; ++i)
- table[i] = 0;
- }
- else
- {
- for( ; i<argument_size ; ++i)
- if( p.table[i] != 0 )
- {
- TTMATH_LOGC("UInt::FromUInt(UInt<>)", 1)
- return 1;
- }
- }
-
- TTMATH_LOGC("UInt::FromUInt(UInt<>)", 0)
-
- return 0;
- }
-
-
- /*!
- this method converts an UInt<another_size> 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<value_size>::SetMax()
-
- it returns a carry if the value 'p' is too big
- */
- template<uint argument_size>
- uint FromInt(const UInt<argument_size> & p)
- {
- return FromUInt(p);
- }
-
-
- /*!
- this method converts the uint type to this class
- */
- uint FromUInt(uint value)
- {
- for(uint i=1 ; i<value_size ; ++i)
- table[i] = 0;
-
- table[0] = value;
-
- TTMATH_LOG("UInt::FromUInt(uint)")
-
- // there'll never be a carry here
- return 0;
- }
-
-
- /*!
- this method converts the uint type to this class
- */
- uint FromInt(uint value)
- {
- return FromUInt(value);
- }
-
-
- /*!
- this method converts the sint type to this class
- */
- uint FromInt(sint value)
- {
- uint c = FromUInt(uint(value));
-
- if( c || value < 0 )
- return 1;
-
- return 0;
- }
-
-
- /*!
- this operator converts an UInt<another_size> type to this class
-
- it doesn't return a carry
- */
-/* template<uint argument_size>
- UInt<value_size> & operator=(const UInt<argument_size> & p)
- {
- FromUInt(p);
-
- return *this;
- }
-*/
-
- /*!
- the assignment operator
- */
-/* UInt<value_size> & operator=(const UInt<value_size> & p)
- {
- for(uint i=0 ; i<value_size ; ++i)
- table[i] = p.table[i];
-
- TTMATH_LOG("UInt::operator=(UInt<>)")
-
- return *this;
- }
-*/
-
- /*!
- this method converts the uint type to this class
- */
- UInt<value_size> & 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<value_size> & 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<value_size ; ++i)
- table[i] = 0;
-
- TTMATH_LOG("UInt::FromUInt(ulint)")
-
- 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 c = FromUInt(ulint(n));
-
- if( c || n < 0 )
- return 1;
-
- return 0;
- }
-
-
- /*!
- this operator converts unsigned 64 bit int type to this class
- ***this operator is created only on a 32bit platform***
- */
- UInt<value_size> & 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<value_size> & 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<value_size> & 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<value_size> & 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<value_size ; ++i)
- table[i] = 0xc1c1c1c1;
- #else
- for(uint i=0 ; i<value_size ; ++i)
- table[i] = 0xc1c1c1c1c1c1c1c1;
- #endif
- #endif
- }
-*/
-
- /*!
- a copy constructor
- */
-/* UInt(const UInt<value_size> & u)
- {
- for(uint i=0 ; i<value_size ; ++i)
- table[i] = u.table[i];
-
- TTMATH_LOG("UInt::UInt(UInt<>)")
- }
-*/
-
-
- /*!
- a template for producting constructors for copying from another types
- */
-/* template<uint argument_size>
- UInt(const UInt<argument_size> & 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<value_size ; ++i)
- if( table[i] != 0 )
- return 1;
-
- return 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 ToInt(uint & result) const
- {
- return ToUInt(result);
- }
-
-
- /*!
- this method converts the value to sint type (signed integer)
- can return a carry if the value is too long to store it in sint type
- */
- uint ToInt(sint & result) const
- {
- result = sint(table[0]);
-
- if( (result & TTMATH_UINT_HIGHEST_BIT) != 0 )
- return 1;
-
- for(uint i=1 ; i<value_size ; ++i)
- if( table[i] != 0 )
- 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
- {
- if( value_size == 1 )
- {
- result = table[0];
- }
- else
- {
- uint low = table[0];
- uint high = table[1];
-
- result = low;
- result |= (ulint(high) << TTMATH_BITS_PER_UINT);
-
- for(uint i=2 ; i<value_size ; ++i)
- if( table[i] != 0 )
- return 1;
- }
-
- return 0;
- }
-
-
- /*!
- 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
- {
- ulint temp;
-
- uint c = ToUInt(temp);
- result = slint(temp);
-
- if( c || result < 0 )
- return 1;
-
- return 0;
- }
-
-#endif
-
-
-
-#ifdef TTMATH_PLATFORM64
-
- /*!
- this method converts the value to a 32 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
- {
- result = (unsigned int)table[0];
-
- if( (table[0] >> 32) != 0 )
- return 1;
-
- for(uint i=1 ; i<value_size ; ++i)
- if( table[i] != 0 )
- return 1;
-
- return 0;
- }
-
-
- /*!
- this method converts the value to a 32 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 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
- {
- unsigned int temp;
-
- uint c = ToUInt(temp);
- result = int(temp);
-
- if( c || result < 0 )
- return 1;
-
- return 0;
- }
-
-
-#endif
-
-
-
-
-protected:
-
- /*!
- an auxiliary method for converting into the string
- it returns the log (with the base 2) from x
- where x is in <2;16>
- */
- 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<class string_type>
- void ToStringBase(string_type & result, uint b = 10, bool negative = false) const
- {
- UInt<value_size> 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<uint>(digits_d) + 3; // plus some epsilon
-
- if( result.capacity() < digits )
- result.reserve(digits);
-
- do
- {
- temp.DivInt(b, &rest);
- character = static_cast<char>(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<char>(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<class char_type>
- uint FromStringBase(const char_type * s, uint b = 10, const char_type ** after_source = 0, bool * value_read = 0)
- {
- UInt<value_size> base;
- base.FromUInt( b );
- UInt<value_size> 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<value_size> & operator=(const char * s)
- {
- FromString(s);
-
- return *this;
- }
-
-
- /*!
- this operator converts a string into its value (with base = 10)
- */
- UInt<value_size> & 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<value_size> & operator=(const wchar_t * s)
- {
- FromString(s);
-
- return *this;
- }
-
-
- /*!
- this operator converts a string into its value (with base = 10)
- */
- UInt<value_size> & 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<value_size> & 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<value_size> & 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<value_size> & 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<value_size> & 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<value_size> & 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<value_size> & l) const
- {
- return CmpSmaller(l);
- }
-
-
- bool operator>(const UInt<value_size> & l) const
- {
- return CmpBigger(l);
- }
-
-
- bool operator==(const UInt<value_size> & l) const
- {
- return CmpEqual(l);
- }
-
-
- bool operator!=(const UInt<value_size> & l) const
- {
- return !operator==(l);
- }
-
-
- bool operator<=(const UInt<value_size> & l) const
- {
- return CmpSmallerEqual(l);
- }
-
- bool operator>=(const UInt<value_size> & l) const
- {
- return CmpBiggerEqual(l);
- }
-
-
- /*!
- *
- * standard mathematical operators
- *
- */
-
- UInt<value_size> operator-(const UInt<value_size> & p2) const
- {
- UInt<value_size> temp(*this);
-
- temp.Sub(p2);
-
- return temp;
- }
-
- UInt<value_size> & operator-=(const UInt<value_size> & p2)
- {
- Sub(p2);
-
- return *this;
- }
-
- UInt<value_size> operator+(const UInt<value_size> & p2) const
- {
- UInt<value_size> temp(*this);
-
- temp.Add(p2);
-
- return temp;
- }
-
- UInt<value_size> & operator+=(const UInt<value_size> & p2)
- {
- Add(p2);
-
- return *this;
- }
-
-
- UInt<value_size> operator*(const UInt<value_size> & p2) const
- {
- UInt<value_size> temp(*this);
-
- temp.Mul(p2);
-
- return temp;
- }
-
-
- UInt<value_size> & operator*=(const UInt<value_size> & p2)
- {
- Mul(p2);
-
- return *this;
- }
-
-
- UInt<value_size> operator/(const UInt<value_size> & p2) const
- {
- UInt<value_size> temp(*this);
-
- temp.Div(p2);
-
- return temp;
- }
-
-
- UInt<value_size> & operator/=(const UInt<value_size> & p2)
- {
- Div(p2);
-
- return *this;
- }
-
-
- UInt<value_size> operator%(const UInt<value_size> & p2) const
- {
- UInt<value_size> temp(*this);
- UInt<value_size> remainder;
-
- temp.Div( p2, remainder );
-
- return remainder;
- }
-
-
- UInt<value_size> & operator%=(const UInt<value_size> & p2)
- {
- UInt<value_size> remainder;
-
- Div( p2, remainder );
- operator=(remainder);
-
- return *this;
- }
-
-
- /*!
- Prefix operator e.g ++variable
- */
- UInt<value_size> & operator++()
- {
- AddOne();
-
- return *this;
- }
-
-
- /*!
- Postfix operator e.g variable++
- */
- UInt<value_size> operator++(int)
- {
- UInt<value_size> temp( *this );
-
- AddOne();
-
- return temp;
- }
-
-
- UInt<value_size> & operator--()
- {
- SubOne();
-
- return *this;
- }
-
-
- UInt<value_size> operator--(int)
- {
- UInt<value_size> temp( *this );
-
- SubOne();
-
- return temp;
- }
-
-
-
- /*!
- *
- * bitwise operators
- *
- */
-
- UInt<value_size> operator~() const
- {
- UInt<value_size> temp( *this );
-
- temp.BitNot();
-
- return temp;
- }
-
-
- UInt<value_size> operator&(const UInt<value_size> & p2) const
- {
- UInt<value_size> temp( *this );
-
- temp.BitAnd(p2);
-
- return temp;
- }
-
-
- UInt<value_size> & operator&=(const UInt<value_size> & p2)
- {
- BitAnd(p2);
-
- return *this;
- }
-
-
- UInt<value_size> operator|(const UInt<value_size> & p2) const
- {
- UInt<value_size> temp( *this );
-
- temp.BitOr(p2);
-
- return temp;
- }
-
-
- UInt<value_size> & operator|=(const UInt<value_size> & p2)
- {
- BitOr(p2);
-
- return *this;
- }
-
-
- UInt<value_size> operator^(const UInt<value_size> & p2) const
- {
- UInt<value_size> temp( *this );
-
- temp.BitXor(p2);
-
- return temp;
- }
-
-
- UInt<value_size> & operator^=(const UInt<value_size> & p2)
- {
- BitXor(p2);
-
- return *this;
- }
-
-
- UInt<value_size> operator>>(int move) const
- {
- UInt<value_size> temp( *this );
-
- temp.Rcr(move);
-
- return temp;
- }
-
-
- UInt<value_size> & operator>>=(int move)
- {
- Rcr(move);
-
- return *this;
- }
-
-
- UInt<value_size> operator<<(int move) const
- {
- UInt<value_size> temp( *this );
-
- temp.Rcl(move);
-
- return temp;
- }
-
-
- UInt<value_size> & 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<class ostream_type, class string_type>
- static ostream_type & OutputToStream(ostream_type & s, const UInt<value_size> & 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<value_size> & l)
- {
- return OutputToStream<std::ostream, std::string>(s, l);
- }
-
-
-#ifndef TTMATH_DONT_USE_WCHAR
-
- /*!
- output to standard streams
- */
- friend std::wostream & operator<<(std::wostream & s, const UInt<value_size> & l)
- {
- return OutputToStream<std::wostream, std::wstring>(s, l);
- }
-
-#endif
-
-
-
-private:
-
- /*!
- an auxiliary method for reading from standard streams
- */
- template<class istream_type, class string_type, class char_type>
- static istream_type & InputFromStream(istream_type & s, UInt<value_size> & 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<char_type>(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<value_size> & l)
- {
- return InputFromStream<std::istream, std::string, char>(s, l);
- }
-
-
-#ifndef TTMATH_DONT_USE_WCHAR
-
- /*!
- input from standard streams
- */
- friend std::wistream & operator>>(std::wistream & s, UInt<value_size> & l)
- {
- return InputFromStream<std::wistream, std::wstring, wchar_t>(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<value_size> & 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<value_size> & 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 <t.sowa@ttmath.org>
- */
-
-/*
- * 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<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<uint value_size>
- const char * UInt<value_size>::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<uint value_size>
- LibTypeCode UInt<value_size>::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 value_size>
- uint UInt<value_size>::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 value_size>
- uint UInt<value_size>::Add(const UInt<value_size> & ss2, uint c)
- {
- uint i;
-
- for(i=0 ; i<value_size ; ++i)
- c = AddTwoWords(table[i], ss2.table[i], c, &table[i]);
-
- TTMATH_LOGC("UInt::Add", c)
-
- return c;
- }
-
-
- /*!
- this method adds one word (at a specific position)
- and returns a carry (if it was)
-
- 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 value_size>
- uint UInt<value_size>::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<value_size && c ; ++i)
- c = AddTwoWords(table[i], 0, c, &table[i]);
-
- 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)
-
- 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 value_size>
- uint UInt<value_size>::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<value_size && c ; ++i)
- c = AddTwoWords(table[i], 0, c, &table[i]);
-
- 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 value_size>
- uint UInt<value_size>::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<ss2_size ; ++i)
- c = AddTwoWords(ss1[i], ss2[i], c, &result[i]);
-
- for( ; i<ss1_size ; ++i)
- c = AddTwoWords(ss1[i], 0, c, &result[i]);
-
- TTMATH_VECTOR_LOGC("UInt::AddVector", c, result, ss1_size)
-
- return c;
- }
-
-
-
-
- /*!
- this method subtractes one word from the other
- returns carry
-
- this method is created only when TTMATH_NOASM macro is defined
- */
- template<uint value_size>
- uint UInt<value_size>::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 value_size>
- uint UInt<value_size>::Sub(const UInt<value_size> & ss2, uint c)
- {
- uint i;
-
- for(i=0 ; i<value_size ; ++i)
- c = SubTwoWords(table[i], ss2.table[i], c, &table[i]);
-
- TTMATH_LOGC("UInt::Sub", c)
-
- return c;
- }
-
-
-
-
- /*!
- this method subtracts one word (at a specific position)
- and returns a carry (if it was)
-
- 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 value_size>
- uint UInt<value_size>::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<value_size && c ; ++i)
- c = SubTwoWords(table[i], 0, c, &table[i]);
-
- 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 value_size>
- uint UInt<value_size>::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<ss2_size ; ++i)
- c = SubTwoWords(ss1[i], ss2[i], c, &result[i]);
-
- for( ; i<ss1_size ; ++i)
- c = SubTwoWords(ss1[i], 0, c, &result[i]);
-
- 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 value_size>
- uint UInt<value_size>::Rcl2_one(uint c)
- {
- uint i, new_c;
-
- if( c != 0 )
- c = 1;
-
- for(i=0 ; i<value_size ; ++i)
- {
- new_c = (table[i] & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0;
- table[i] = (table[i] << 1) | c;
- c = new_c;
- }
-
- 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 value_size>
- uint UInt<value_size>::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 value_size>
- uint UInt<value_size>::Rcl2(uint bits, uint c)
- {
- TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
-
- uint move = TTMATH_BITS_PER_UINT - bits;
- uint i, new_c;
-
- if( c != 0 )
- c = TTMATH_UINT_MAX_VALUE >> move;
-
- for(i=0 ; i<value_size ; ++i)
- {
- new_c = table[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 value_size>
- uint UInt<value_size>::Rcr2(uint bits, uint c)
- {
- TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
-
- uint move = TTMATH_BITS_PER_UINT - bits;
- sint i; // signed
- uint new_c;
-
- if( c != 0 )
- c = TTMATH_UINT_MAX_VALUE << move;
-
- for(i=value_size-1 ; i>=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<uint value_size>
- sint UInt<value_size>::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<uint value_size>
- sint UInt<value_size>::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 value_size>
- uint UInt<value_size>::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<uint value_size>
- void UInt<value_size>::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<uint value_size>
- void UInt<value_size>::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<uint value_size>
- void UInt<value_size>::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 value_size>
- uint UInt<value_size>::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 value_size>
- uint UInt<value_size>::DivTwoWordsUnnormalize(uint u, uint d)
- {
- if( d == 0 )
- return u;
-
- u = u >> d;
-
- return u;
- }
-
-
- template<uint value_size>
- unsigned int UInt<value_size>::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<uint value_size>
- void UInt<value_size>::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 <t.sowa@ttmath.org>
- */
-
-/*
- * 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<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<uint value_size>
- const char * UInt<value_size>::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<uint value_size>
- LibTypeCode UInt<value_size>::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 value_size>
- uint UInt<value_size>::Add(const UInt<value_size> & ss2, uint c)
- {
- uint b = value_size;
- uint * p1 = table;
- uint * p2 = const_cast<uint*>(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 value_size>
- uint UInt<value_size>::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 value_size>
- uint UInt<value_size>::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 value_size>
- uint UInt<value_size>::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 value_size>
- uint UInt<value_size>::Sub(const UInt<value_size> & ss2, uint c)
- {
- uint b = value_size;
- uint * p1 = table;
- uint * p2 = const_cast<uint*>(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 value_size>
- uint UInt<value_size>::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 value_size>
- uint UInt<value_size>::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 value_size>
- uint UInt<value_size>::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 value_size>
- uint UInt<value_size>::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 value_size>
- uint UInt<value_size>::Rcl2(uint bits, uint c)
- {
- TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
-
- uint b = value_size;
- uint * p1 = table;
-
- #ifndef __GNUC__
- __asm
- {
- push eax
- push ebx
- push ecx
- push edx
- push esi
- push edi
- push ebp
-
- mov edi, [b]
-
- mov ecx, 32
- sub ecx, [bits]
- mov edx, -1
- shr edx, cl
-
- mov ecx, [bits]
- mov ebx, [p1]
- mov eax, [c]
-
- mov ebp, edx // ebp = mask (modified ebp - don't read/write to variables)
-
- xor edx, edx // edx = 0
- mov esi, edx
- or eax, eax
- cmovnz esi, ebp // if(c) esi=mask else esi=0
-
- ttmath_loop:
- rol dword ptr [ebx+edx*4], cl
-
- mov eax, [ebx+edx*4]
- and eax, ebp
- xor [ebx+edx*4], eax // clearing bits
- or [ebx+edx*4], esi // saving old value
- mov esi, eax
-
- inc edx
- dec edi
- jnz ttmath_loop
-
- pop ebp // restoring ebp
-
- and eax, 1
- mov [c], eax
-
- pop edi
- pop esi
- pop edx
- pop ecx
- pop ebx
- pop eax
- }
- #endif
-
-
- #ifdef __GNUC__
- uint dummy, dummy2, dummy3;
-
- __asm__ __volatile__(
-
- "push %%ebp \n"
-
- "movl %%ecx, %%esi \n"
- "movl $32, %%ecx \n"
- "subl %%esi, %%ecx \n" // ecx = 32 - bits
- "movl $-1, %%edx \n" // edx = -1 (all bits set to one)
- "shrl %%cl, %%edx \n" // shifting (0 -> 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 value_size>
- uint UInt<value_size>::Rcr2(uint bits, uint c)
- {
- TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
-
- uint b = value_size;
- uint * p1 = table;
-
- #ifndef __GNUC__
- __asm
- {
- push eax
- push ebx
- push ecx
- push edx
- push esi
- push edi
- push ebp
-
- mov edi, [b]
-
- mov ecx, 32
- sub ecx, [bits]
- mov edx, -1
- shl edx, cl
-
- mov ecx, [bits]
- mov ebx, [p1]
- mov eax, [c]
-
- mov ebp, edx // ebp = mask (modified ebp - don't read/write to variables)
-
- xor edx, edx // edx = 0
- mov esi, edx
- add edx, edi
- dec edx // edx is pointing at the end of the table (on last word)
- or eax, eax
- cmovnz esi, ebp // if(c) esi=mask else esi=0
-
- ttmath_loop:
- ror dword ptr [ebx+edx*4], cl
-
- mov eax, [ebx+edx*4]
- and eax, ebp
- xor [ebx+edx*4], eax // clearing bits
- or [ebx+edx*4], esi // saving old value
- mov esi, eax
-
- dec edx
- dec edi
- jnz ttmath_loop
-
- pop ebp // restoring ebp
-
- rol eax, 1 // 31bit will be first
- and eax, 1
- mov [c], eax
-
- pop edi
- pop esi
- pop edx
- pop ecx
- pop ebx
- pop eax
- }
- #endif
-
-
- #ifdef __GNUC__
- uint dummy, dummy2, dummy3;
-
- __asm__ __volatile__(
-
- "push %%ebp \n"
-
- "movl %%ecx, %%esi \n"
- "movl $32, %%ecx \n"
- "subl %%esi, %%ecx \n" // ecx = 32 - bits
- "movl $-1, %%edx \n" // edx = -1 (all bits set to one)
- "shll %%cl, %%edx \n" // shifting (cf <- edx <- 0) (cl times)
- "movl %%edx, %%ebp \n" // ebp = edx = mask
- "movl %%esi, %%ecx \n"
-
- "xorl %%edx, %%edx \n"
- "movl %%edx, %%esi \n"
- "addl %%edi, %%edx \n"
- "decl %%edx \n" // edx is pointing at the end of the table (on last word)
- "orl %%eax, %%eax \n"
- "cmovnz %%ebp, %%esi \n" // if(c) esi=mask else esi=0
-
- "1: \n"
- "rorl %%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"
-
- "decl %%edx \n"
- "decl %%edi \n"
- "jnz 1b \n"
-
- "roll $1, %%eax \n"
- "andl $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::Rcr2", c)
-
- return c;
- }
-
-
-#ifdef _MSC_VER
-#pragma warning (default : 4731)
-#endif
-
-
- /*
- this method returns the number of the highest set bit in one 32-bit word
- if the 'x' is zero this method returns '-1'
- */
- template<uint value_size>
- sint UInt<value_size>::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<uint value_size>
- sint UInt<value_size>::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 value_size>
- uint UInt<value_size>::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<uint value_size>
- void UInt<value_size>::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<uint value_size>
- void UInt<value_size>::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 <t.sowa@ttmath.org>
- */
-
-/*
- * 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<uint> with assembler code for 64bit x86_64 processors
-
- this file is included at the end of ttmathuint.h
-*/
-
-#ifndef __GNUC__
-#include <intrin.h>
-#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<uint value_size>
- const char * UInt<value_size>::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<uint value_size>
- LibTypeCode UInt<value_size>::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 value_size>
- uint UInt<value_size>::Add(const UInt<value_size> & 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 value_size>
- uint UInt<value_size>::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 value_size>
- uint UInt<value_size>::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 value_size>
- uint UInt<value_size>::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 value_size>
- uint UInt<value_size>::Sub(const UInt<value_size> & 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 value_size>
- uint UInt<value_size>::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 value_size>
- uint UInt<value_size>::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 value_size>
- uint UInt<value_size>::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 value_size>
- uint UInt<value_size>::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 value_size>
- uint UInt<value_size>::Rcl2(uint bits, uint c)
- {
- TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
-
- uint b = value_size;
- uint * p1 = table;
-
-
- #ifndef __GNUC__
- c = ttmath_rcl2_x64(p1,b,bits,c);
- #endif
-
-
- #ifdef __GNUC__
- uint dummy, dummy2, dummy3;
-
- __asm__ __volatile__(
-
- "movq %%rcx, %%rsi \n"
- "movq $64, %%rcx \n"
- "subq %%rsi, %%rcx \n"
- "movq $-1, %%rdx \n"
- "shrq %%cl, %%rdx \n"
- "movq %%rdx, %%r8 \n"
- "movq %%rsi, %%rcx \n"
-
- "xorq %%rdx, %%rdx \n"
- "movq %%rdx, %%rsi \n"
- "orq %%rax, %%rax \n"
- "cmovnz %%r8, %%rsi \n"
-
- "1: \n"
- "rolq %%cl, (%%rbx,%%rdx,8) \n"
-
- "movq (%%rbx,%%rdx,8), %%rax \n"
- "andq %%r8, %%rax \n"
- "xorq %%rax, (%%rbx,%%rdx,8) \n"
- "orq %%rsi, (%%rbx,%%rdx,8) \n"
- "movq %%rax, %%rsi \n"
-
- "incq %%rdx \n"
- "decq %%rdi \n"
- "jnz 1b \n"
-
- "and $1, %%rax \n"
-
- : "=a" (c), "=D" (dummy), "=S" (dummy2), "=d" (dummy3)
- : "0" (c), "1" (b), "b" (p1), "c" (bits)
- : "%r8", "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
-
- ***this method is created only on a 64bit platform***
- */
- template<uint value_size>
- uint UInt<value_size>::Rcr2(uint bits, uint c)
- {
- TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
-
- sint b = value_size;
- uint * p1 = table;
-
-
- #ifndef __GNUC__
- c = ttmath_rcr2_x64(p1,b,bits,c);
- #endif
-
-
- #ifdef __GNUC__
- uint dummy, dummy2, dummy3;
-
- __asm__ __volatile__(
-
- "movq %%rcx, %%rsi \n"
- "movq $64, %%rcx \n"
- "subq %%rsi, %%rcx \n"
- "movq $-1, %%rdx \n"
- "shlq %%cl, %%rdx \n"
- "movq %%rdx, %%R8 \n"
- "movq %%rsi, %%rcx \n"
-
- "xorq %%rdx, %%rdx \n"
- "movq %%rdx, %%rsi \n"
- "addq %%rdi, %%rdx \n"
- "decq %%rdx \n"
- "orq %%rax, %%rax \n"
- "cmovnz %%R8, %%rsi \n"
-
- "1: \n"
- "rorq %%cl, (%%rbx,%%rdx,8) \n"
-
- "movq (%%rbx,%%rdx,8), %%rax \n"
- "andq %%R8, %%rax \n"
- "xorq %%rax, (%%rbx,%%rdx,8) \n"
- "orq %%rsi, (%%rbx,%%rdx,8) \n"
- "movq %%rax, %%rsi \n"
-
- "decq %%rdx \n"
- "decq %%rdi \n"
- "jnz 1b \n"
-
- "rolq $1, %%rax \n"
- "andq $1, %%rax \n"
-
- : "=a" (c), "=D" (dummy), "=S" (dummy2), "=d" (dummy3)
- : "0" (c), "1" (b), "b" (p1), "c" (bits)
- : "%r8", "cc", "memory" );
-
- #endif
-
- TTMATH_LOGC("UInt::Rcr2", c)
-
- return c;
- }
-
-
- /*
- 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<uint value_size>
- sint UInt<value_size>::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<uint value_size>
- sint UInt<value_size>::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 value_size>
- uint UInt<value_size>::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<uint value_size>
- void UInt<value_size>::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<uint value_size>
- void UInt<value_size>::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 <chk@online.de>
-;
-
-;
-; 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<TTMATH_BITS(128)> 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 */