diff --git a/builds/posix/Makefile.in b/builds/posix/Makefile.in index bb4ceb12fb..dcd2b173ae 100644 --- a/builds/posix/Makefile.in +++ b/builds/posix/Makefile.in @@ -170,6 +170,9 @@ external: $(MAKE) -C $(ROOT)/extern/decNumber ln -sf $(ROOT)/extern/decNumber/libdecFloat.a $(LIB) + $(MAKE) -C $(ROOT)/extern/int128/absl/numeric + ln -sf $(ROOT)/extern/int128/absl/numeric/libi128.a $(LIB) + CXXFLAGS="-O3 -g -fPIC" $(MAKE) -C $(ROOT)/extern/re2 ln -sf $(ROOT)/extern/re2/obj/libre2.a $(LIB) @@ -328,6 +331,8 @@ cross2: $(MAKE) re2 $(MAKE) -C $(ROOT)/extern/decNumber ln -sf $(ROOT)/extern/decNumber/libdecFloat$(CROSS).a $(LIB) + $(MAKE) -C $(ROOT)/extern/int128/absl/numeric + ln -sf $(ROOT)/extern/int128/absl/numeric/libi128$(CROSS).a $(LIB) $(MAKE) yvalve $(MAKE) engine $(MAKE) fbintl @@ -738,12 +743,12 @@ install install-embedded silent_install package packages dist: # .PHONY: clean clean_objects clean_dependancies clean_extern_objects clean_build \ clean_gpre_gen clean_icu clean_dbs clean_examples clean_makefiles \ - clean_editline clean_all clean_decfloat clean_vers clean_misc + clean_editline clean_all clean_decfloat clean_int128 clean_vers clean_misc clean: clean_objects clean_dependancies clean_extern_objects clean_build \ clean_yacc_gen clean_gpre_gen clean_dbs clean_examples clean_tommath \ - clean_tomcrypt clean_decfloat clean_vers clean_misc + clean_tomcrypt clean_decfloat clean_int128 clean_vers clean_misc clean_vers: $(RM) *.vers @@ -797,6 +802,9 @@ clean_tomcrypt: clean_decfloat: -$(MAKE) -C $(ROOT)/extern/decNumber clean +clean_int128: + -$(MAKE) -C $(ROOT)/extern/int128/absl/numeric clean + clean_objects: $(RM) `find $(TMP_ROOT)/ -type f -name '*.o' -print` $(RM) `find $(TMP_ROOT)/ -type f -name '*.a' -print` diff --git a/builds/posix/make.android.arm64 b/builds/posix/make.android.arm64 index 79fbb90c2e..ff0d8d85ff 100644 --- a/builds/posix/make.android.arm64 +++ b/builds/posix/make.android.arm64 @@ -41,7 +41,7 @@ DEV_FLAGS=$(COMMON_FLAGS) $(WARN_FLAGS) CROSS_CONFIG=android.arm64 LDFLAGS += --sysroot=$(CROSS_SYSROOT) -static-libstdc++ -DroidLibs := -lm -ldl $(DECLIB) $(RE2LIB) +DroidLibs := -lm -ldl $(DECLIB) $(RE2LIB) $(I128LIB) LINK_LIBS = $(DroidLibs) STATICLINK_LIBS = $(DroidLibs) diff --git a/builds/posix/make.android.arme b/builds/posix/make.android.arme index c7233d0191..b6ae33587d 100644 --- a/builds/posix/make.android.arme +++ b/builds/posix/make.android.arme @@ -40,7 +40,7 @@ DEV_FLAGS=$(COMMON_FLAGS) $(WARN_FLAGS) CROSS_CONFIG=android.arme LDFLAGS += --sysroot=$(CROSS_PLATFORM) -static-libstdc++ -DroidLibs := -lm -ldl $(DECLIB) $(RE2LIB) +DroidLibs := -lm -ldl $(DECLIB) $(RE2LIB) $(I128LIB) UDR_SUPPORT_LIBS := LINK_LIBS = $(DroidLibs) diff --git a/builds/posix/make.defaults b/builds/posix/make.defaults index 6dfd3ab118..9421947a59 100755 --- a/builds/posix/make.defaults +++ b/builds/posix/make.defaults @@ -134,6 +134,7 @@ CAS_OPTIONS=@CAS_OPTIONS@ # multiple-precision integer library MATHLIB=@MATHLIB@ DECLIB=-ldecFloat$(CROSS) +I128LIB=-li128$(CROSS) RE2LIB=-lre2 # crypt library @@ -190,8 +191,8 @@ endif STATICLIB_LINK = $(AR) crus STATICEXE_LINK = $(CXX) $(GLOB_OPTIONS) $(CXXFLAGS) -static-libstdc++ -LINK_LIBS = @LIBS@ $(DECLIB) $(RE2LIB) -SO_LINK_LIBS = @LIBS@ $(DECLIB) $(RE2LIB) +LINK_LIBS = @LIBS@ $(DECLIB) $(RE2LIB) $(I128LIB) +SO_LINK_LIBS = @LIBS@ $(DECLIB) $(RE2LIB) $(I128LIB) # Default extensions diff --git a/builds/posix/make.rules b/builds/posix/make.rules index 3afd891141..e725b93067 100644 --- a/builds/posix/make.rules +++ b/builds/posix/make.rules @@ -32,7 +32,7 @@ # Please don't use compiler/platform specific flags here - nmcc 02-Nov-2002 -WFLAGS =-I$(SRC_ROOT)/include/gen -I$(SRC_ROOT)/include -I$(ROOT)/extern/re2 $(CPPFLAGS) $(LTCSOURCE) +WFLAGS =-I$(SRC_ROOT)/include/gen -I$(SRC_ROOT)/include -I$(ROOT)/extern/re2 -I$(ROOT)/extern/int128 $(CPPFLAGS) $(LTCSOURCE) ifeq ($(TOMMATH_BUILD_FLG),Y) WFLAGS += -I$(TOMMATH_INC) diff --git a/builds/posix/prefix.linux_s390x b/builds/posix/prefix.linux_s390x index ccb2340123..cb0992bb41 100644 --- a/builds/posix/prefix.linux_s390x +++ b/builds/posix/prefix.linux_s390x @@ -18,10 +18,10 @@ # # 2 Oct 2002, Nickolay Samofatov - Major cleanup -COMMON_FLAGS=-ggdb -DFB_SEND_FLAGS=MSG_NOSIGNAL -DLINUX -pipe -MMD -fPIC -fmessage-length=0 -fsigned-char +COMMON_FLAGS=-ggdb -DFB_SEND_FLAGS=MSG_NOSIGNAL -DLINUX -pipe -MMD -fPIC -fmessage-length=0 -fsigned-char -Wno-invalid-offsetof OPTIMIZE_FLAGS=-O3 -fno-omit-frame-pointer -fno-builtin WARN_FLAGS=-Wall -Wno-switch -Wno-parentheses -Wno-unknown-pragmas -Wno-unused-variable -Wno-non-virtual-dtor PROD_FLAGS=$(COMMON_FLAGS) $(OPTIMIZE_FLAGS) -DEV_FLAGS=-DUSE_VALGRIND -p $(COMMON_FLAGS) $(WARN_FLAGS) -#DEV_FLAGS=-p $(COMMON_FLAGS) $(WARN_FLAGS) +#DEV_FLAGS=-DUSE_VALGRIND -p $(COMMON_FLAGS) $(WARN_FLAGS) +DEV_FLAGS=-p $(COMMON_FLAGS) $(WARN_FLAGS) diff --git a/extern/int128/absl/base/attributes.h b/extern/int128/absl/base/attributes.h new file mode 100644 index 0000000000..52139556f2 --- /dev/null +++ b/extern/int128/absl/base/attributes.h @@ -0,0 +1,721 @@ +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// This header file defines macros for declaring attributes for functions, +// types, and variables. +// +// These macros are used within Abseil and allow the compiler to optimize, where +// applicable, certain function calls. +// +// Most macros here are exposing GCC or Clang features, and are stubbed out for +// other compilers. +// +// GCC attributes documentation: +// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html +// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Variable-Attributes.html +// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Type-Attributes.html +// +// Most attributes in this file are already supported by GCC 4.7. However, some +// of them are not supported in older version of Clang. Thus, we check +// `__has_attribute()` first. If the check fails, we check if we are on GCC and +// assume the attribute exists on GCC (which is verified on GCC 4.7). + +#ifndef ABSL_BASE_ATTRIBUTES_H_ +#define ABSL_BASE_ATTRIBUTES_H_ + +#include "absl/base/config.h" + +// ABSL_HAVE_ATTRIBUTE +// +// A function-like feature checking macro that is a wrapper around +// `__has_attribute`, which is defined by GCC 5+ and Clang and evaluates to a +// nonzero constant integer if the attribute is supported or 0 if not. +// +// It evaluates to zero if `__has_attribute` is not defined by the compiler. +// +// GCC: https://gcc.gnu.org/gcc-5/changes.html +// Clang: https://clang.llvm.org/docs/LanguageExtensions.html +#ifdef __has_attribute +#define ABSL_HAVE_ATTRIBUTE(x) __has_attribute(x) +#else +#define ABSL_HAVE_ATTRIBUTE(x) 0 +#endif + +// ABSL_HAVE_CPP_ATTRIBUTE +// +// A function-like feature checking macro that accepts C++11 style attributes. +// It's a wrapper around `__has_cpp_attribute`, defined by ISO C++ SD-6 +// (https://en.cppreference.com/w/cpp/experimental/feature_test). If we don't +// find `__has_cpp_attribute`, will evaluate to 0. +#if defined(__cplusplus) && defined(__has_cpp_attribute) +// NOTE: requiring __cplusplus above should not be necessary, but +// works around https://bugs.llvm.org/show_bug.cgi?id=23435. +#define ABSL_HAVE_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) +#else +#define ABSL_HAVE_CPP_ATTRIBUTE(x) 0 +#endif + +// ----------------------------------------------------------------------------- +// Function Attributes +// ----------------------------------------------------------------------------- +// +// GCC: https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html +// Clang: https://clang.llvm.org/docs/AttributeReference.html + +// ABSL_PRINTF_ATTRIBUTE +// ABSL_SCANF_ATTRIBUTE +// +// Tells the compiler to perform `printf` format string checking if the +// compiler supports it; see the 'format' attribute in +// . +// +// Note: As the GCC manual states, "[s]ince non-static C++ methods +// have an implicit 'this' argument, the arguments of such methods +// should be counted from two, not one." +#if ABSL_HAVE_ATTRIBUTE(format) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_PRINTF_ATTRIBUTE(string_index, first_to_check) \ + __attribute__((__format__(__printf__, string_index, first_to_check))) +#define ABSL_SCANF_ATTRIBUTE(string_index, first_to_check) \ + __attribute__((__format__(__scanf__, string_index, first_to_check))) +#else +#define ABSL_PRINTF_ATTRIBUTE(string_index, first_to_check) +#define ABSL_SCANF_ATTRIBUTE(string_index, first_to_check) +#endif + +// ABSL_ATTRIBUTE_ALWAYS_INLINE +// ABSL_ATTRIBUTE_NOINLINE +// +// Forces functions to either inline or not inline. Introduced in gcc 3.1. +#if ABSL_HAVE_ATTRIBUTE(always_inline) || \ + (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline)) +#define ABSL_HAVE_ATTRIBUTE_ALWAYS_INLINE 1 +#else +#define ABSL_ATTRIBUTE_ALWAYS_INLINE +#endif + +#if ABSL_HAVE_ATTRIBUTE(noinline) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_NOINLINE __attribute__((noinline)) +#define ABSL_HAVE_ATTRIBUTE_NOINLINE 1 +#else +#define ABSL_ATTRIBUTE_NOINLINE +#endif + +// ABSL_ATTRIBUTE_NO_TAIL_CALL +// +// Prevents the compiler from optimizing away stack frames for functions which +// end in a call to another function. +#if ABSL_HAVE_ATTRIBUTE(disable_tail_calls) +#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1 +#define ABSL_ATTRIBUTE_NO_TAIL_CALL __attribute__((disable_tail_calls)) +#elif defined(__GNUC__) && !defined(__clang__) && !defined(__e2k__) +#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1 +#define ABSL_ATTRIBUTE_NO_TAIL_CALL \ + __attribute__((optimize("no-optimize-sibling-calls"))) +#else +#define ABSL_ATTRIBUTE_NO_TAIL_CALL +#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 0 +#endif + +// ABSL_ATTRIBUTE_WEAK +// +// Tags a function as weak for the purposes of compilation and linking. +// Weak attributes did not work properly in LLVM's Windows backend before +// 9.0.0, so disable them there. See https://bugs.llvm.org/show_bug.cgi?id=37598 +// for further information. +// The MinGW compiler doesn't complain about the weak attribute until the link +// step, presumably because Windows doesn't use ELF binaries. +#if (ABSL_HAVE_ATTRIBUTE(weak) || \ + (defined(__GNUC__) && !defined(__clang__))) && \ + (!defined(_WIN32) || __clang_major__ < 9) && !defined(__MINGW32__) +#undef ABSL_ATTRIBUTE_WEAK +#define ABSL_ATTRIBUTE_WEAK __attribute__((weak)) +#define ABSL_HAVE_ATTRIBUTE_WEAK 1 +#else +#define ABSL_ATTRIBUTE_WEAK +#define ABSL_HAVE_ATTRIBUTE_WEAK 0 +#endif + +// ABSL_ATTRIBUTE_NONNULL +// +// Tells the compiler either (a) that a particular function parameter +// should be a non-null pointer, or (b) that all pointer arguments should +// be non-null. +// +// Note: As the GCC manual states, "[s]ince non-static C++ methods +// have an implicit 'this' argument, the arguments of such methods +// should be counted from two, not one." +// +// Args are indexed starting at 1. +// +// For non-static class member functions, the implicit `this` argument +// is arg 1, and the first explicit argument is arg 2. For static class member +// functions, there is no implicit `this`, and the first explicit argument is +// arg 1. +// +// Example: +// +// /* arg_a cannot be null, but arg_b can */ +// void Function(void* arg_a, void* arg_b) ABSL_ATTRIBUTE_NONNULL(1); +// +// class C { +// /* arg_a cannot be null, but arg_b can */ +// void Method(void* arg_a, void* arg_b) ABSL_ATTRIBUTE_NONNULL(2); +// +// /* arg_a cannot be null, but arg_b can */ +// static void StaticMethod(void* arg_a, void* arg_b) +// ABSL_ATTRIBUTE_NONNULL(1); +// }; +// +// If no arguments are provided, then all pointer arguments should be non-null. +// +// /* No pointer arguments may be null. */ +// void Function(void* arg_a, void* arg_b, int arg_c) ABSL_ATTRIBUTE_NONNULL(); +// +// NOTE: The GCC nonnull attribute actually accepts a list of arguments, but +// ABSL_ATTRIBUTE_NONNULL does not. +#if ABSL_HAVE_ATTRIBUTE(nonnull) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_NONNULL(arg_index) __attribute__((nonnull(arg_index))) +#else +#define ABSL_ATTRIBUTE_NONNULL(...) +#endif + +// ABSL_ATTRIBUTE_NORETURN +// +// Tells the compiler that a given function never returns. +#if ABSL_HAVE_ATTRIBUTE(noreturn) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_NORETURN __attribute__((noreturn)) +#elif defined(_MSC_VER) +#define ABSL_ATTRIBUTE_NORETURN __declspec(noreturn) +#else +#define ABSL_ATTRIBUTE_NORETURN +#endif + +// ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS +// +// Tells the AddressSanitizer (or other memory testing tools) to ignore a given +// function. Useful for cases when a function reads random locations on stack, +// calls _exit from a cloned subprocess, deliberately accesses buffer +// out of bounds or does other scary things with memory. +// NOTE: GCC supports AddressSanitizer(asan) since 4.8. +// https://gcc.gnu.org/gcc-4.8/changes.html +#if ABSL_HAVE_ATTRIBUTE(no_sanitize_address) +#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) +#else +#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS +#endif + +// ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY +// +// Tells the MemorySanitizer to relax the handling of a given function. All "Use +// of uninitialized value" warnings from such functions will be suppressed, and +// all values loaded from memory will be considered fully initialized. This +// attribute is similar to the ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS attribute +// above, but deals with initialized-ness rather than addressability issues. +// NOTE: MemorySanitizer(msan) is supported by Clang but not GCC. +#if ABSL_HAVE_ATTRIBUTE(no_sanitize_memory) +#define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory)) +#else +#define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY +#endif + +// ABSL_ATTRIBUTE_NO_SANITIZE_THREAD +// +// Tells the ThreadSanitizer to not instrument a given function. +// NOTE: GCC supports ThreadSanitizer(tsan) since 4.8. +// https://gcc.gnu.org/gcc-4.8/changes.html +#if ABSL_HAVE_ATTRIBUTE(no_sanitize_thread) +#define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread)) +#else +#define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD +#endif + +// ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED +// +// Tells the UndefinedSanitizer to ignore a given function. Useful for cases +// where certain behavior (eg. division by zero) is being used intentionally. +// NOTE: GCC supports UndefinedBehaviorSanitizer(ubsan) since 4.9. +// https://gcc.gnu.org/gcc-4.9/changes.html +#if ABSL_HAVE_ATTRIBUTE(no_sanitize_undefined) +#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \ + __attribute__((no_sanitize_undefined)) +#elif ABSL_HAVE_ATTRIBUTE(no_sanitize) +#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \ + __attribute__((no_sanitize("undefined"))) +#else +#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED +#endif + +// ABSL_ATTRIBUTE_NO_SANITIZE_CFI +// +// Tells the ControlFlowIntegrity sanitizer to not instrument a given function. +// See https://clang.llvm.org/docs/ControlFlowIntegrity.html for details. +#if ABSL_HAVE_ATTRIBUTE(no_sanitize) +#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI __attribute__((no_sanitize("cfi"))) +#else +#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI +#endif + +// ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK +// +// Tells the SafeStack to not instrument a given function. +// See https://clang.llvm.org/docs/SafeStack.html for details. +#if ABSL_HAVE_ATTRIBUTE(no_sanitize) +#define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK \ + __attribute__((no_sanitize("safe-stack"))) +#else +#define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK +#endif + +// ABSL_ATTRIBUTE_RETURNS_NONNULL +// +// Tells the compiler that a particular function never returns a null pointer. +#if ABSL_HAVE_ATTRIBUTE(returns_nonnull) +#define ABSL_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull)) +#else +#define ABSL_ATTRIBUTE_RETURNS_NONNULL +#endif + +// ABSL_HAVE_ATTRIBUTE_SECTION +// +// Indicates whether labeled sections are supported. Weak symbol support is +// a prerequisite. Labeled sections are not supported on Darwin/iOS. +#ifdef ABSL_HAVE_ATTRIBUTE_SECTION +#error ABSL_HAVE_ATTRIBUTE_SECTION cannot be directly set +#elif (ABSL_HAVE_ATTRIBUTE(section) || \ + (defined(__GNUC__) && !defined(__clang__))) && \ + !defined(__APPLE__) && ABSL_HAVE_ATTRIBUTE_WEAK +#define ABSL_HAVE_ATTRIBUTE_SECTION 1 + +// ABSL_ATTRIBUTE_SECTION +// +// Tells the compiler/linker to put a given function into a section and define +// `__start_ ## name` and `__stop_ ## name` symbols to bracket the section. +// This functionality is supported by GNU linker. Any function annotated with +// `ABSL_ATTRIBUTE_SECTION` must not be inlined, or it will be placed into +// whatever section its caller is placed into. +// +#ifndef ABSL_ATTRIBUTE_SECTION +#define ABSL_ATTRIBUTE_SECTION(name) \ + __attribute__((section(#name))) __attribute__((noinline)) +#endif + + +// ABSL_ATTRIBUTE_SECTION_VARIABLE +// +// Tells the compiler/linker to put a given variable into a section and define +// `__start_ ## name` and `__stop_ ## name` symbols to bracket the section. +// This functionality is supported by GNU linker. +#ifndef ABSL_ATTRIBUTE_SECTION_VARIABLE +#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) __attribute__((section(#name))) +#endif + +// ABSL_DECLARE_ATTRIBUTE_SECTION_VARS +// +// A weak section declaration to be used as a global declaration +// for ABSL_ATTRIBUTE_SECTION_START|STOP(name) to compile and link +// even without functions with ABSL_ATTRIBUTE_SECTION(name). +// ABSL_DEFINE_ATTRIBUTE_SECTION should be in the exactly one file; it's +// a no-op on ELF but not on Mach-O. +// +#ifndef ABSL_DECLARE_ATTRIBUTE_SECTION_VARS +#define ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) \ + extern char __start_##name[] ABSL_ATTRIBUTE_WEAK; \ + extern char __stop_##name[] ABSL_ATTRIBUTE_WEAK +#endif +#ifndef ABSL_DEFINE_ATTRIBUTE_SECTION_VARS +#define ABSL_INIT_ATTRIBUTE_SECTION_VARS(name) +#define ABSL_DEFINE_ATTRIBUTE_SECTION_VARS(name) +#endif + +// ABSL_ATTRIBUTE_SECTION_START +// +// Returns `void*` pointers to start/end of a section of code with +// functions having ABSL_ATTRIBUTE_SECTION(name). +// Returns 0 if no such functions exist. +// One must ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) for this to compile and +// link. +// +#define ABSL_ATTRIBUTE_SECTION_START(name) \ + (reinterpret_cast(__start_##name)) +#define ABSL_ATTRIBUTE_SECTION_STOP(name) \ + (reinterpret_cast(__stop_##name)) + +#else // !ABSL_HAVE_ATTRIBUTE_SECTION + +#define ABSL_HAVE_ATTRIBUTE_SECTION 0 + +// provide dummy definitions +#define ABSL_ATTRIBUTE_SECTION(name) +#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) +#define ABSL_INIT_ATTRIBUTE_SECTION_VARS(name) +#define ABSL_DEFINE_ATTRIBUTE_SECTION_VARS(name) +#define ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) +#define ABSL_ATTRIBUTE_SECTION_START(name) (reinterpret_cast(0)) +#define ABSL_ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast(0)) + +#endif // ABSL_ATTRIBUTE_SECTION + +// ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC +// +// Support for aligning the stack on 32-bit x86. +#if ABSL_HAVE_ATTRIBUTE(force_align_arg_pointer) || \ + (defined(__GNUC__) && !defined(__clang__)) +#if defined(__i386__) +#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC \ + __attribute__((force_align_arg_pointer)) +#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) +#elif defined(__x86_64__) +#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (1) +#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC +#else // !__i386__ && !__x86_64 +#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) +#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC +#endif // __i386__ +#else +#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC +#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) +#endif + +// ABSL_MUST_USE_RESULT +// +// Tells the compiler to warn about unused results. +// +// When annotating a function, it must appear as the first part of the +// declaration or definition. The compiler will warn if the return value from +// such a function is unused: +// +// ABSL_MUST_USE_RESULT Sprocket* AllocateSprocket(); +// AllocateSprocket(); // Triggers a warning. +// +// When annotating a class, it is equivalent to annotating every function which +// returns an instance. +// +// class ABSL_MUST_USE_RESULT Sprocket {}; +// Sprocket(); // Triggers a warning. +// +// Sprocket MakeSprocket(); +// MakeSprocket(); // Triggers a warning. +// +// Note that references and pointers are not instances: +// +// Sprocket* SprocketPointer(); +// SprocketPointer(); // Does *not* trigger a warning. +// +// ABSL_MUST_USE_RESULT allows using cast-to-void to suppress the unused result +// warning. For that, warn_unused_result is used only for clang but not for gcc. +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425 +// +// Note: past advice was to place the macro after the argument list. +#if ABSL_HAVE_ATTRIBUTE(nodiscard) +#define ABSL_MUST_USE_RESULT [[nodiscard]] +#elif defined(__clang__) && ABSL_HAVE_ATTRIBUTE(warn_unused_result) +#define ABSL_MUST_USE_RESULT __attribute__((warn_unused_result)) +#else +#define ABSL_MUST_USE_RESULT +#endif + +// ABSL_ATTRIBUTE_HOT, ABSL_ATTRIBUTE_COLD +// +// Tells GCC that a function is hot or cold. GCC can use this information to +// improve static analysis, i.e. a conditional branch to a cold function +// is likely to be not-taken. +// This annotation is used for function declarations. +// +// Example: +// +// int foo() ABSL_ATTRIBUTE_HOT; +#if ABSL_HAVE_ATTRIBUTE(hot) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_HOT __attribute__((hot)) +#else +#define ABSL_ATTRIBUTE_HOT +#endif + +#if ABSL_HAVE_ATTRIBUTE(cold) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_COLD __attribute__((cold)) +#else +#define ABSL_ATTRIBUTE_COLD +#endif + +// ABSL_XRAY_ALWAYS_INSTRUMENT, ABSL_XRAY_NEVER_INSTRUMENT, ABSL_XRAY_LOG_ARGS +// +// We define the ABSL_XRAY_ALWAYS_INSTRUMENT and ABSL_XRAY_NEVER_INSTRUMENT +// macro used as an attribute to mark functions that must always or never be +// instrumented by XRay. Currently, this is only supported in Clang/LLVM. +// +// For reference on the LLVM XRay instrumentation, see +// http://llvm.org/docs/XRay.html. +// +// A function with the XRAY_ALWAYS_INSTRUMENT macro attribute in its declaration +// will always get the XRay instrumentation sleds. These sleds may introduce +// some binary size and runtime overhead and must be used sparingly. +// +// These attributes only take effect when the following conditions are met: +// +// * The file/target is built in at least C++11 mode, with a Clang compiler +// that supports XRay attributes. +// * The file/target is built with the -fxray-instrument flag set for the +// Clang/LLVM compiler. +// * The function is defined in the translation unit (the compiler honors the +// attribute in either the definition or the declaration, and must match). +// +// There are cases when, even when building with XRay instrumentation, users +// might want to control specifically which functions are instrumented for a +// particular build using special-case lists provided to the compiler. These +// special case lists are provided to Clang via the +// -fxray-always-instrument=... and -fxray-never-instrument=... flags. The +// attributes in source take precedence over these special-case lists. +// +// To disable the XRay attributes at build-time, users may define +// ABSL_NO_XRAY_ATTRIBUTES. Do NOT define ABSL_NO_XRAY_ATTRIBUTES on specific +// packages/targets, as this may lead to conflicting definitions of functions at +// link-time. +// +// XRay isn't currently supported on Android: +// https://github.com/android/ndk/issues/368 +#if ABSL_HAVE_CPP_ATTRIBUTE(clang::xray_always_instrument) && \ + !defined(ABSL_NO_XRAY_ATTRIBUTES) && !defined(__ANDROID__) +#define ABSL_XRAY_ALWAYS_INSTRUMENT [[clang::xray_always_instrument]] +#define ABSL_XRAY_NEVER_INSTRUMENT [[clang::xray_never_instrument]] +#if ABSL_HAVE_CPP_ATTRIBUTE(clang::xray_log_args) +#define ABSL_XRAY_LOG_ARGS(N) \ + [[clang::xray_always_instrument, clang::xray_log_args(N)]] +#else +#define ABSL_XRAY_LOG_ARGS(N) [[clang::xray_always_instrument]] +#endif +#else +#define ABSL_XRAY_ALWAYS_INSTRUMENT +#define ABSL_XRAY_NEVER_INSTRUMENT +#define ABSL_XRAY_LOG_ARGS(N) +#endif + +// ABSL_ATTRIBUTE_REINITIALIZES +// +// Indicates that a member function reinitializes the entire object to a known +// state, independent of the previous state of the object. +// +// The clang-tidy check bugprone-use-after-move allows member functions marked +// with this attribute to be called on objects that have been moved from; +// without the attribute, this would result in a use-after-move warning. +#if ABSL_HAVE_CPP_ATTRIBUTE(clang::reinitializes) +#define ABSL_ATTRIBUTE_REINITIALIZES [[clang::reinitializes]] +#else +#define ABSL_ATTRIBUTE_REINITIALIZES +#endif + +// ----------------------------------------------------------------------------- +// Variable Attributes +// ----------------------------------------------------------------------------- + +// ABSL_ATTRIBUTE_UNUSED +// +// Prevents the compiler from complaining about variables that appear unused. +// +// For code or headers that are assured to only build with C++17 and up, prefer +// just using the standard '[[maybe_unused]]' directly over this macro. +// +// Due to differences in positioning requirements between the old, compiler +// specific __attribute__ syntax and the now standard [[maybe_unused]], this +// macro does not attempt to take advantage of '[[maybe_unused]]'. +#if ABSL_HAVE_ATTRIBUTE(unused) || (defined(__GNUC__) && !defined(__clang__)) +#undef ABSL_ATTRIBUTE_UNUSED +#define ABSL_ATTRIBUTE_UNUSED __attribute__((__unused__)) +#else +#define ABSL_ATTRIBUTE_UNUSED +#endif + +// ABSL_ATTRIBUTE_INITIAL_EXEC +// +// Tells the compiler to use "initial-exec" mode for a thread-local variable. +// See http://people.redhat.com/drepper/tls.pdf for the gory details. +#if ABSL_HAVE_ATTRIBUTE(tls_model) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_INITIAL_EXEC __attribute__((tls_model("initial-exec"))) +#else +#define ABSL_ATTRIBUTE_INITIAL_EXEC +#endif + +// ABSL_ATTRIBUTE_PACKED +// +// Instructs the compiler not to use natural alignment for a tagged data +// structure, but instead to reduce its alignment to 1. This attribute can +// either be applied to members of a structure or to a structure in its +// entirety. Applying this attribute (judiciously) to a structure in its +// entirety to optimize the memory footprint of very commonly-used structs is +// fine. Do not apply this attribute to a structure in its entirety if the +// purpose is to control the offsets of the members in the structure. Instead, +// apply this attribute only to structure members that need it. +// +// When applying ABSL_ATTRIBUTE_PACKED only to specific structure members the +// natural alignment of structure members not annotated is preserved. Aligned +// member accesses are faster than non-aligned member accesses even if the +// targeted microprocessor supports non-aligned accesses. +#if ABSL_HAVE_ATTRIBUTE(packed) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_PACKED __attribute__((__packed__)) +#else +#define ABSL_ATTRIBUTE_PACKED +#endif + +// ABSL_ATTRIBUTE_FUNC_ALIGN +// +// Tells the compiler to align the function start at least to certain +// alignment boundary +#if ABSL_HAVE_ATTRIBUTE(aligned) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_FUNC_ALIGN(bytes) __attribute__((aligned(bytes))) +#else +#define ABSL_ATTRIBUTE_FUNC_ALIGN(bytes) +#endif + +// ABSL_FALLTHROUGH_INTENDED +// +// Annotates implicit fall-through between switch labels, allowing a case to +// indicate intentional fallthrough and turn off warnings about any lack of a +// `break` statement. The ABSL_FALLTHROUGH_INTENDED macro should be followed by +// a semicolon and can be used in most places where `break` can, provided that +// no statements exist between it and the next switch label. +// +// Example: +// +// switch (x) { +// case 40: +// case 41: +// if (truth_is_out_there) { +// ++x; +// ABSL_FALLTHROUGH_INTENDED; // Use instead of/along with annotations +// // in comments +// } else { +// return x; +// } +// case 42: +// ... +// +// Notes: When supported, GCC and Clang can issue a warning on switch labels +// with unannotated fallthrough using the warning `-Wimplicit-fallthrough`. See +// clang documentation on language extensions for details: +// https://clang.llvm.org/docs/AttributeReference.html#fallthrough-clang-fallthrough +// +// When used with unsupported compilers, the ABSL_FALLTHROUGH_INTENDED macro has +// no effect on diagnostics. In any case this macro has no effect on runtime +// behavior and performance of code. + +#ifdef ABSL_FALLTHROUGH_INTENDED +#error "ABSL_FALLTHROUGH_INTENDED should not be defined." +#elif ABSL_HAVE_CPP_ATTRIBUTE(fallthrough) +#define ABSL_FALLTHROUGH_INTENDED [[fallthrough]] +#elif ABSL_HAVE_CPP_ATTRIBUTE(clang::fallthrough) +#define ABSL_FALLTHROUGH_INTENDED [[clang::fallthrough]] +#elif ABSL_HAVE_CPP_ATTRIBUTE(gnu::fallthrough) +#define ABSL_FALLTHROUGH_INTENDED [[gnu::fallthrough]] +#else +#define ABSL_FALLTHROUGH_INTENDED \ + do { \ + } while (0) +#endif + +// ABSL_DEPRECATED() +// +// Marks a deprecated class, struct, enum, function, method and variable +// declarations. The macro argument is used as a custom diagnostic message (e.g. +// suggestion of a better alternative). +// +// Examples: +// +// class ABSL_DEPRECATED("Use Bar instead") Foo {...}; +// +// ABSL_DEPRECATED("Use Baz() instead") void Bar() {...} +// +// template +// ABSL_DEPRECATED("Use DoThat() instead") +// void DoThis(); +// +// Every usage of a deprecated entity will trigger a warning when compiled with +// clang's `-Wdeprecated-declarations` option. This option is turned off by +// default, but the warnings will be reported by clang-tidy. +#if defined(__clang__) && defined(__cplusplus) && __cplusplus >= 201103L +#define ABSL_DEPRECATED(message) __attribute__((deprecated(message))) +#endif + +#ifndef ABSL_DEPRECATED +#define ABSL_DEPRECATED(message) +#endif + +// ABSL_CONST_INIT +// +// A variable declaration annotated with the `ABSL_CONST_INIT` attribute will +// not compile (on supported platforms) unless the variable has a constant +// initializer. This is useful for variables with static and thread storage +// duration, because it guarantees that they will not suffer from the so-called +// "static init order fiasco". Prefer to put this attribute on the most visible +// declaration of the variable, if there's more than one, because code that +// accesses the variable can then use the attribute for optimization. +// +// Example: +// +// class MyClass { +// public: +// ABSL_CONST_INIT static MyType my_var; +// }; +// +// MyType MyClass::my_var = MakeMyType(...); +// +// Note that this attribute is redundant if the variable is declared constexpr. +#if ABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization) +#define ABSL_CONST_INIT [[clang::require_constant_initialization]] +#else +#define ABSL_CONST_INIT +#endif // ABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization) + +// ABSL_ATTRIBUTE_PURE_FUNCTION +// +// ABSL_ATTRIBUTE_PURE_FUNCTION is used to annotate declarations of "pure" +// functions. A function is pure if its return value is only a function of its +// arguments. The pure attribute prohibits a function from modifying the state +// of the program that is observable by means other than inspecting the +// function's return value. Declaring such functions with the pure attribute +// allows the compiler to avoid emitting some calls in repeated invocations of +// the function with the same argument values. +// +// Example: +// +// ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Milliseconds(Duration d); +#if ABSL_HAVE_CPP_ATTRIBUTE(gnu::pure) +#define ABSL_ATTRIBUTE_PURE_FUNCTION [[gnu::pure]] +#elif ABSL_HAVE_ATTRIBUTE(pure) +#define ABSL_ATTRIBUTE_PURE_FUNCTION __attribute__((pure)) +#else +#define ABSL_ATTRIBUTE_PURE_FUNCTION +#endif + +// ABSL_ATTRIBUTE_LIFETIME_BOUND indicates that a resource owned by a function +// parameter or implicit object parameter is retained by the return value of the +// annotated function (or, for a parameter of a constructor, in the value of the +// constructed object). This attribute causes warnings to be produced if a +// temporary object does not live long enough. +// +// When applied to a reference parameter, the referenced object is assumed to be +// retained by the return value of the function. When applied to a non-reference +// parameter (for example, a pointer or a class type), all temporaries +// referenced by the parameter are assumed to be retained by the return value of +// the function. +// +// See also the upstream documentation: +// https://clang.llvm.org/docs/AttributeReference.html#lifetimebound +#if ABSL_HAVE_CPP_ATTRIBUTE(clang::lifetimebound) +#define ABSL_ATTRIBUTE_LIFETIME_BOUND [[clang::lifetimebound]] +#elif ABSL_HAVE_ATTRIBUTE(lifetimebound) +#define ABSL_ATTRIBUTE_LIFETIME_BOUND __attribute__((lifetimebound)) +#else +#define ABSL_ATTRIBUTE_LIFETIME_BOUND +#endif + +#endif // ABSL_BASE_ATTRIBUTES_H_ diff --git a/extern/int128/absl/base/config.h b/extern/int128/absl/base/config.h new file mode 100644 index 0000000000..a6e7c86a0c --- /dev/null +++ b/extern/int128/absl/base/config.h @@ -0,0 +1,745 @@ +// +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ----------------------------------------------------------------------------- +// File: config.h +// ----------------------------------------------------------------------------- +// +// This header file defines a set of macros for checking the presence of +// important compiler and platform features. Such macros can be used to +// produce portable code by parameterizing compilation based on the presence or +// lack of a given feature. +// +// We define a "feature" as some interface we wish to program to: for example, +// a library function or system call. A value of `1` indicates support for +// that feature; any other value indicates the feature support is undefined. +// +// Example: +// +// Suppose a programmer wants to write a program that uses the 'mmap()' system +// call. The Abseil macro for that feature (`ABSL_HAVE_MMAP`) allows you to +// selectively include the `mmap.h` header and bracket code using that feature +// in the macro: +// +// #include "absl/base/config.h" +// +// #ifdef ABSL_HAVE_MMAP +// #include "sys/mman.h" +// #endif //ABSL_HAVE_MMAP +// +// ... +// #ifdef ABSL_HAVE_MMAP +// void *ptr = mmap(...); +// ... +// #endif // ABSL_HAVE_MMAP + +#ifndef ABSL_BASE_CONFIG_H_ +#define ABSL_BASE_CONFIG_H_ + +// Included for the __GLIBC__ macro (or similar macros on other systems). +#include + +#ifdef __cplusplus +// Included for __GLIBCXX__, _LIBCPP_VERSION +#include +#endif // __cplusplus + +#if defined(__APPLE__) +// Included for TARGET_OS_IPHONE, __IPHONE_OS_VERSION_MIN_REQUIRED, +// __IPHONE_8_0. +#include +#include +#endif + +#include "absl/base/options.h" +#include "absl/base/policy_checks.h" + +// Helper macro to convert a CPP variable to a string literal. +#define ABSL_INTERNAL_DO_TOKEN_STR(x) #x +#define ABSL_INTERNAL_TOKEN_STR(x) ABSL_INTERNAL_DO_TOKEN_STR(x) + +// ----------------------------------------------------------------------------- +// Abseil namespace annotations +// ----------------------------------------------------------------------------- + +// ABSL_NAMESPACE_BEGIN/ABSL_NAMESPACE_END +// +// An annotation placed at the beginning/end of each `namespace absl` scope. +// This is used to inject an inline namespace. +// +// The proper way to write Abseil code in the `absl` namespace is: +// +// namespace absl { +// ABSL_NAMESPACE_BEGIN +// +// void Foo(); // absl::Foo(). +// +// ABSL_NAMESPACE_END +// } // namespace absl +// +// Users of Abseil should not use these macros, because users of Abseil should +// not write `namespace absl {` in their own code for any reason. (Abseil does +// not support forward declarations of its own types, nor does it support +// user-provided specialization of Abseil templates. Code that violates these +// rules may be broken without warning.) +#if !defined(ABSL_OPTION_USE_INLINE_NAMESPACE) || \ + !defined(ABSL_OPTION_INLINE_NAMESPACE_NAME) +#error options.h is misconfigured. +#endif + +// Check that ABSL_OPTION_INLINE_NAMESPACE_NAME is neither "head" nor "" +#if defined(__cplusplus) && ABSL_OPTION_USE_INLINE_NAMESPACE == 1 + +#define ABSL_INTERNAL_INLINE_NAMESPACE_STR \ + ABSL_INTERNAL_TOKEN_STR(ABSL_OPTION_INLINE_NAMESPACE_NAME) + +static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != '\0', + "options.h misconfigured: ABSL_OPTION_INLINE_NAMESPACE_NAME must " + "not be empty."); +static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' || + ABSL_INTERNAL_INLINE_NAMESPACE_STR[1] != 'e' || + ABSL_INTERNAL_INLINE_NAMESPACE_STR[2] != 'a' || + ABSL_INTERNAL_INLINE_NAMESPACE_STR[3] != 'd' || + ABSL_INTERNAL_INLINE_NAMESPACE_STR[4] != '\0', + "options.h misconfigured: ABSL_OPTION_INLINE_NAMESPACE_NAME must " + "be changed to a new, unique identifier name."); + +#endif + +#if ABSL_OPTION_USE_INLINE_NAMESPACE == 0 +#define ABSL_NAMESPACE_BEGIN +#define ABSL_NAMESPACE_END +#define ABSL_INTERNAL_C_SYMBOL(x) x +#elif ABSL_OPTION_USE_INLINE_NAMESPACE == 1 +#define ABSL_NAMESPACE_BEGIN \ + inline namespace ABSL_OPTION_INLINE_NAMESPACE_NAME { +#define ABSL_NAMESPACE_END } +#define ABSL_INTERNAL_C_SYMBOL_HELPER_2(x, v) x##_##v +#define ABSL_INTERNAL_C_SYMBOL_HELPER_1(x, v) \ + ABSL_INTERNAL_C_SYMBOL_HELPER_2(x, v) +#define ABSL_INTERNAL_C_SYMBOL(x) \ + ABSL_INTERNAL_C_SYMBOL_HELPER_1(x, ABSL_OPTION_INLINE_NAMESPACE_NAME) +#else +#error options.h is misconfigured. +#endif + +// ----------------------------------------------------------------------------- +// Compiler Feature Checks +// ----------------------------------------------------------------------------- + +// ABSL_HAVE_BUILTIN() +// +// Checks whether the compiler supports a Clang Feature Checking Macro, and if +// so, checks whether it supports the provided builtin function "x" where x +// is one of the functions noted in +// https://clang.llvm.org/docs/LanguageExtensions.html +// +// Note: Use this macro to avoid an extra level of #ifdef __has_builtin check. +// http://releases.llvm.org/3.3/tools/clang/docs/LanguageExtensions.html +#ifdef __has_builtin +#define ABSL_HAVE_BUILTIN(x) __has_builtin(x) +#else +#define ABSL_HAVE_BUILTIN(x) 0 +#endif + +#if defined(__is_identifier) +#define ABSL_INTERNAL_HAS_KEYWORD(x) !(__is_identifier(x)) +#else +#define ABSL_INTERNAL_HAS_KEYWORD(x) 0 +#endif + +#ifdef __has_feature +#define ABSL_HAVE_FEATURE(f) __has_feature(f) +#else +#define ABSL_HAVE_FEATURE(f) 0 +#endif + +// Portable check for GCC minimum version: +// https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html +#if defined(__GNUC__) && defined(__GNUC_MINOR__) +#define ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(x, y) \ + (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y)) +#else +#define ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(x, y) 0 +#endif + +#if defined(__clang__) && defined(__clang_major__) && defined(__clang_minor__) +#define ABSL_INTERNAL_HAVE_MIN_CLANG_VERSION(x, y) \ + (__clang_major__ > (x) || __clang_major__ == (x) && __clang_minor__ >= (y)) +#else +#define ABSL_INTERNAL_HAVE_MIN_CLANG_VERSION(x, y) 0 +#endif + +// ABSL_HAVE_TLS is defined to 1 when __thread should be supported. +// We assume __thread is supported on Linux when compiled with Clang or compiled +// against libstdc++ with _GLIBCXX_HAVE_TLS defined. +#ifdef ABSL_HAVE_TLS +#error ABSL_HAVE_TLS cannot be directly set +#elif defined(__linux__) && (defined(__clang__) || defined(_GLIBCXX_HAVE_TLS)) +#define ABSL_HAVE_TLS 1 +#endif + +// ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE +// +// Checks whether `std::is_trivially_destructible` is supported. +// +// Notes: All supported compilers using libc++ support this feature, as does +// gcc >= 4.8.1 using libstdc++, and Visual Studio. +#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE +#error ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE cannot be directly set +#elif defined(_LIBCPP_VERSION) || defined(_MSC_VER) || \ + (!defined(__clang__) && defined(__GLIBCXX__) && \ + ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(4, 8)) +#define ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE 1 +#endif + +// ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE +// +// Checks whether `std::is_trivially_default_constructible` and +// `std::is_trivially_copy_constructible` are supported. + +// ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE +// +// Checks whether `std::is_trivially_copy_assignable` is supported. + +// Notes: Clang with libc++ supports these features, as does gcc >= 5.1 with +// either libc++ or libstdc++, and Visual Studio (but not NVCC). +#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) +#error ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE cannot be directly set +#elif defined(ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE) +#error ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE cannot directly set +#elif (defined(__clang__) && defined(_LIBCPP_VERSION)) || \ + (!defined(__clang__) && ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(7, 4) && \ + (defined(_LIBCPP_VERSION) || defined(__GLIBCXX__))) || \ + (defined(_MSC_VER) && !defined(__NVCC__)) +#define ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE 1 +#define ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE 1 +#endif + +// ABSL_HAVE_SOURCE_LOCATION_CURRENT +// +// Indicates whether `absl::SourceLocation::current()` will return useful +// information in some contexts. +#ifndef ABSL_HAVE_SOURCE_LOCATION_CURRENT +#if ABSL_INTERNAL_HAS_KEYWORD(__builtin_LINE) && \ + ABSL_INTERNAL_HAS_KEYWORD(__builtin_FILE) +#define ABSL_HAVE_SOURCE_LOCATION_CURRENT 1 +#elif ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(5, 0) +#define ABSL_HAVE_SOURCE_LOCATION_CURRENT 1 +#endif +#endif + +// ABSL_HAVE_THREAD_LOCAL +// +// Checks whether C++11's `thread_local` storage duration specifier is +// supported. +#ifdef ABSL_HAVE_THREAD_LOCAL +#error ABSL_HAVE_THREAD_LOCAL cannot be directly set +#elif defined(__APPLE__) +// Notes: +// * Xcode's clang did not support `thread_local` until version 8, and +// even then not for all iOS < 9.0. +// * Xcode 9.3 started disallowing `thread_local` for 32-bit iOS simulator +// targeting iOS 9.x. +// * Xcode 10 moves the deployment target check for iOS < 9.0 to link time +// making ABSL_HAVE_FEATURE unreliable there. +// +#if ABSL_HAVE_FEATURE(cxx_thread_local) && \ + !(TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0) +#define ABSL_HAVE_THREAD_LOCAL 1 +#endif +#else // !defined(__APPLE__) +#define ABSL_HAVE_THREAD_LOCAL 1 +#endif + +// There are platforms for which TLS should not be used even though the compiler +// makes it seem like it's supported (Android NDK < r12b for example). +// This is primarily because of linker problems and toolchain misconfiguration: +// Abseil does not intend to support this indefinitely. Currently, the newest +// toolchain that we intend to support that requires this behavior is the +// r11 NDK - allowing for a 5 year support window on that means this option +// is likely to be removed around June of 2021. +// TLS isn't supported until NDK r12b per +// https://developer.android.com/ndk/downloads/revision_history.html +// Since NDK r16, `__NDK_MAJOR__` and `__NDK_MINOR__` are defined in +// . For NDK < r16, users should define these macros, +// e.g. `-D__NDK_MAJOR__=11 -D__NKD_MINOR__=0` for NDK r11. +#if defined(__ANDROID__) && defined(__clang__) +#if __has_include() +#include +#endif // __has_include() +#if defined(__ANDROID__) && defined(__clang__) && defined(__NDK_MAJOR__) && \ + defined(__NDK_MINOR__) && \ + ((__NDK_MAJOR__ < 12) || ((__NDK_MAJOR__ == 12) && (__NDK_MINOR__ < 1))) +#undef ABSL_HAVE_TLS +#undef ABSL_HAVE_THREAD_LOCAL +#endif +#endif // defined(__ANDROID__) && defined(__clang__) + +// ABSL_HAVE_INTRINSIC_INT128 +// +// Checks whether the __int128 compiler extension for a 128-bit integral type is +// supported. +// +// Note: __SIZEOF_INT128__ is defined by Clang and GCC when __int128 is +// supported, but we avoid using it in certain cases: +// * On Clang: +// * Building using Clang for Windows, where the Clang runtime library has +// 128-bit support only on LP64 architectures, but Windows is LLP64. +// * On Nvidia's nvcc: +// * nvcc also defines __GNUC__ and __SIZEOF_INT128__, but not all versions +// actually support __int128. + +/* Unfortunately FB does not support alignment requirements (16) in ODS + +#ifdef ABSL_HAVE_INTRINSIC_INT128 +#error ABSL_HAVE_INTRINSIC_INT128 cannot be directly set +#elif defined(__SIZEOF_INT128__) +#if (defined(__clang__) && !defined(_WIN32)) || \ + (defined(__CUDACC__) && __CUDACC_VER_MAJOR__ >= 9) || \ + (defined(__GNUC__) && !defined(__clang__) && !defined(__CUDACC__)) +#define ABSL_HAVE_INTRINSIC_INT128 1 +#elif defined(__CUDACC__) +// __CUDACC_VER__ is a full version number before CUDA 9, and is defined to a +// string explaining that it has been removed starting with CUDA 9. We use +// nested #ifs because there is no short-circuiting in the preprocessor. +// NOTE: `__CUDACC__` could be undefined while `__CUDACC_VER__` is defined. +#if __CUDACC_VER__ >= 70000 +#define ABSL_HAVE_INTRINSIC_INT128 1 +#endif // __CUDACC_VER__ >= 70000 +#endif // defined(__CUDACC__) +#endif // ABSL_HAVE_INTRINSIC_INT128 + */ +#undef ABSL_HAVE_INTRINSIC_INT128 + +// ABSL_HAVE_EXCEPTIONS +// +// Checks whether the compiler both supports and enables exceptions. Many +// compilers support a "no exceptions" mode that disables exceptions. +// +// Generally, when ABSL_HAVE_EXCEPTIONS is not defined: +// +// * Code using `throw` and `try` may not compile. +// * The `noexcept` specifier will still compile and behave as normal. +// * The `noexcept` operator may still return `false`. +// +// For further details, consult the compiler's documentation. +#ifdef ABSL_HAVE_EXCEPTIONS +#error ABSL_HAVE_EXCEPTIONS cannot be directly set. +#elif ABSL_INTERNAL_HAVE_MIN_CLANG_VERSION(3, 6) +// Clang >= 3.6 +#if ABSL_HAVE_FEATURE(cxx_exceptions) +#define ABSL_HAVE_EXCEPTIONS 1 +#endif // ABSL_HAVE_FEATURE(cxx_exceptions) +#elif defined(__clang__) +// Clang < 3.6 +// http://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html#the-exceptions-macro +#if defined(__EXCEPTIONS) && ABSL_HAVE_FEATURE(cxx_exceptions) +#define ABSL_HAVE_EXCEPTIONS 1 +#endif // defined(__EXCEPTIONS) && ABSL_HAVE_FEATURE(cxx_exceptions) +// Handle remaining special cases and default to exceptions being supported. +#elif !(defined(__GNUC__) && (__GNUC__ < 5) && !defined(__EXCEPTIONS)) && \ + !(ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(5, 0) && \ + !defined(__cpp_exceptions)) && \ + !(defined(_MSC_VER) && !defined(_CPPUNWIND)) +#define ABSL_HAVE_EXCEPTIONS 1 +#endif + +// ----------------------------------------------------------------------------- +// Platform Feature Checks +// ----------------------------------------------------------------------------- + +// Currently supported operating systems and associated preprocessor +// symbols: +// +// Linux and Linux-derived __linux__ +// Android __ANDROID__ (implies __linux__) +// Linux (non-Android) __linux__ && !__ANDROID__ +// Darwin (macOS and iOS) __APPLE__ +// Akaros (http://akaros.org) __ros__ +// Windows _WIN32 +// NaCL __native_client__ +// AsmJS __asmjs__ +// WebAssembly __wasm__ +// Fuchsia __Fuchsia__ +// +// Note that since Android defines both __ANDROID__ and __linux__, one +// may probe for either Linux or Android by simply testing for __linux__. + +// ABSL_HAVE_MMAP +// +// Checks whether the platform has an mmap(2) implementation as defined in +// POSIX.1-2001. +#ifdef ABSL_HAVE_MMAP +#error ABSL_HAVE_MMAP cannot be directly set +#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \ + defined(__ros__) || defined(__native_client__) || defined(__asmjs__) || \ + defined(__wasm__) || defined(__Fuchsia__) || defined(__sun) || \ + defined(__ASYLO__) || defined(__myriad2__) +#define ABSL_HAVE_MMAP 1 +#endif + +// ABSL_HAVE_PTHREAD_GETSCHEDPARAM +// +// Checks whether the platform implements the pthread_(get|set)schedparam(3) +// functions as defined in POSIX.1-2001. +#ifdef ABSL_HAVE_PTHREAD_GETSCHEDPARAM +#error ABSL_HAVE_PTHREAD_GETSCHEDPARAM cannot be directly set +#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \ + defined(__ros__) +#define ABSL_HAVE_PTHREAD_GETSCHEDPARAM 1 +#endif + +// ABSL_HAVE_SCHED_GETCPU +// +// Checks whether sched_getcpu is available. +#ifdef ABSL_HAVE_SCHED_GETCPU +#error ABSL_HAVE_SCHED_GETCPU cannot be directly set +#elif defined(__linux__) +#define ABSL_HAVE_SCHED_GETCPU 1 +#endif + +// ABSL_HAVE_SCHED_YIELD +// +// Checks whether the platform implements sched_yield(2) as defined in +// POSIX.1-2001. +#ifdef ABSL_HAVE_SCHED_YIELD +#error ABSL_HAVE_SCHED_YIELD cannot be directly set +#elif defined(__linux__) || defined(__ros__) || defined(__native_client__) +#define ABSL_HAVE_SCHED_YIELD 1 +#endif + +// ABSL_HAVE_SEMAPHORE_H +// +// Checks whether the platform supports the header and sem_init(3) +// family of functions as standardized in POSIX.1-2001. +// +// Note: While Apple provides for both iOS and macOS, it is +// explicitly deprecated and will cause build failures if enabled for those +// platforms. We side-step the issue by not defining it here for Apple +// platforms. +#ifdef ABSL_HAVE_SEMAPHORE_H +#error ABSL_HAVE_SEMAPHORE_H cannot be directly set +#elif defined(__linux__) || defined(__ros__) +#define ABSL_HAVE_SEMAPHORE_H 1 +#endif + +// ABSL_HAVE_ALARM +// +// Checks whether the platform supports the header and alarm(2) +// function as standardized in POSIX.1-2001. +#ifdef ABSL_HAVE_ALARM +#error ABSL_HAVE_ALARM cannot be directly set +#elif defined(__GOOGLE_GRTE_VERSION__) +// feature tests for Google's GRTE +#define ABSL_HAVE_ALARM 1 +#elif defined(__GLIBC__) +// feature test for glibc +#define ABSL_HAVE_ALARM 1 +#elif defined(_MSC_VER) +// feature tests for Microsoft's library +#elif defined(__MINGW32__) +// mingw32 doesn't provide alarm(2): +// https://osdn.net/projects/mingw/scm/git/mingw-org-wsl/blobs/5.2-trunk/mingwrt/include/unistd.h +// mingw-w64 provides a no-op implementation: +// https://sourceforge.net/p/mingw-w64/mingw-w64/ci/master/tree/mingw-w64-crt/misc/alarm.c +#elif defined(__EMSCRIPTEN__) +// emscripten doesn't support signals +#elif defined(__Fuchsia__) +// Signals don't exist on fuchsia. +#elif defined(__native_client__) +#else +// other standard libraries +#define ABSL_HAVE_ALARM 1 +#endif + +// ABSL_IS_LITTLE_ENDIAN +// ABSL_IS_BIG_ENDIAN +// +// Checks the endianness of the platform. +// +// Notes: uses the built in endian macros provided by GCC (since 4.6) and +// Clang (since 3.2); see +// https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html. +// Otherwise, if _WIN32, assume little endian. Otherwise, bail with an error. +#if defined(ABSL_IS_BIG_ENDIAN) +#error "ABSL_IS_BIG_ENDIAN cannot be directly set." +#endif +#if defined(ABSL_IS_LITTLE_ENDIAN) +#error "ABSL_IS_LITTLE_ENDIAN cannot be directly set." +#endif + +#if (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \ + __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) +#define ABSL_IS_LITTLE_ENDIAN 1 +#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \ + __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define ABSL_IS_BIG_ENDIAN 1 +#elif defined(_WIN32) +#define ABSL_IS_LITTLE_ENDIAN 1 +#else +#error "absl endian detection needs to be set up for your compiler" +#endif + +// macOS 10.13 and iOS 10.11 don't let you use , , or +// even though the headers exist and are publicly noted to work. See +// https://github.com/abseil/abseil-cpp/issues/207 and +// https://developer.apple.com/documentation/xcode_release_notes/xcode_10_release_notes +// libc++ spells out the availability requirements in the file +// llvm-project/libcxx/include/__config via the #define +// _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS. +#if defined(__APPLE__) && defined(_LIBCPP_VERSION) && \ + ((defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \ + __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101400) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && \ + __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 120000) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && \ + __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 50000) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && \ + __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 120000)) +#define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 1 +#else +#define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 0 +#endif + +// ABSL_HAVE_STD_ANY +// +// Checks whether C++17 std::any is available by checking whether exists. +#ifdef ABSL_HAVE_STD_ANY +#error "ABSL_HAVE_STD_ANY cannot be directly set." +#endif + +#ifdef __has_include +#if __has_include() && defined(__cplusplus) && __cplusplus >= 201703L && \ + !ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE +#define ABSL_HAVE_STD_ANY 1 +#endif +#endif + +// ABSL_HAVE_STD_OPTIONAL +// +// Checks whether C++17 std::optional is available. +#ifdef ABSL_HAVE_STD_OPTIONAL +#error "ABSL_HAVE_STD_OPTIONAL cannot be directly set." +#endif + +#ifdef __has_include +#if __has_include() && defined(__cplusplus) && \ + __cplusplus >= 201703L && !ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE +#define ABSL_HAVE_STD_OPTIONAL 1 +#endif +#endif + +// ABSL_HAVE_STD_VARIANT +// +// Checks whether C++17 std::variant is available. +#ifdef ABSL_HAVE_STD_VARIANT +#error "ABSL_HAVE_STD_VARIANT cannot be directly set." +#endif + +#ifdef __has_include +#if __has_include() && defined(__cplusplus) && \ + __cplusplus >= 201703L && !ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE +#define ABSL_HAVE_STD_VARIANT 1 +#endif +#endif + +// ABSL_HAVE_STD_STRING_VIEW +// +// Checks whether C++17 std::string_view is available. +#ifdef ABSL_HAVE_STD_STRING_VIEW +#error "ABSL_HAVE_STD_STRING_VIEW cannot be directly set." +#endif + +#ifdef __has_include +#if __has_include() && defined(__cplusplus) && \ + __cplusplus >= 201703L +#define ABSL_HAVE_STD_STRING_VIEW 1 +#endif +#endif + +// For MSVC, `__has_include` is supported in VS 2017 15.3, which is later than +// the support for , , , . So we use +// _MSC_VER to check whether we have VS 2017 RTM (when , , +// , is implemented) or higher. Also, `__cplusplus` is +// not correctly set by MSVC, so we use `_MSVC_LANG` to check the language +// version. +// TODO(zhangxy): fix tests before enabling aliasing for `std::any`. +#if defined(_MSC_VER) && _MSC_VER >= 1910 && \ + ((defined(_MSVC_LANG) && _MSVC_LANG > 201402) || \ + (defined(__cplusplus) && __cplusplus > 201402)) +// #define ABSL_HAVE_STD_ANY 1 +#define ABSL_HAVE_STD_OPTIONAL 1 +#define ABSL_HAVE_STD_VARIANT 1 +#define ABSL_HAVE_STD_STRING_VIEW 1 +#endif + +// ABSL_USES_STD_ANY +// +// Indicates whether absl::any is an alias for std::any. +#if !defined(ABSL_OPTION_USE_STD_ANY) +#error options.h is misconfigured. +#elif ABSL_OPTION_USE_STD_ANY == 0 || \ + (ABSL_OPTION_USE_STD_ANY == 2 && !defined(ABSL_HAVE_STD_ANY)) +#undef ABSL_USES_STD_ANY +#elif ABSL_OPTION_USE_STD_ANY == 1 || \ + (ABSL_OPTION_USE_STD_ANY == 2 && defined(ABSL_HAVE_STD_ANY)) +#define ABSL_USES_STD_ANY 1 +#else +#error options.h is misconfigured. +#endif + +// ABSL_USES_STD_OPTIONAL +// +// Indicates whether absl::optional is an alias for std::optional. +#if !defined(ABSL_OPTION_USE_STD_OPTIONAL) +#error options.h is misconfigured. +#elif ABSL_OPTION_USE_STD_OPTIONAL == 0 || \ + (ABSL_OPTION_USE_STD_OPTIONAL == 2 && !defined(ABSL_HAVE_STD_OPTIONAL)) +#undef ABSL_USES_STD_OPTIONAL +#elif ABSL_OPTION_USE_STD_OPTIONAL == 1 || \ + (ABSL_OPTION_USE_STD_OPTIONAL == 2 && defined(ABSL_HAVE_STD_OPTIONAL)) +#define ABSL_USES_STD_OPTIONAL 1 +#else +#error options.h is misconfigured. +#endif + +// ABSL_USES_STD_VARIANT +// +// Indicates whether absl::variant is an alias for std::variant. +#if !defined(ABSL_OPTION_USE_STD_VARIANT) +#error options.h is misconfigured. +#elif ABSL_OPTION_USE_STD_VARIANT == 0 || \ + (ABSL_OPTION_USE_STD_VARIANT == 2 && !defined(ABSL_HAVE_STD_VARIANT)) +#undef ABSL_USES_STD_VARIANT +#elif ABSL_OPTION_USE_STD_VARIANT == 1 || \ + (ABSL_OPTION_USE_STD_VARIANT == 2 && defined(ABSL_HAVE_STD_VARIANT)) +#define ABSL_USES_STD_VARIANT 1 +#else +#error options.h is misconfigured. +#endif + +// ABSL_USES_STD_STRING_VIEW +// +// Indicates whether absl::string_view is an alias for std::string_view. +#if !defined(ABSL_OPTION_USE_STD_STRING_VIEW) +#error options.h is misconfigured. +#elif ABSL_OPTION_USE_STD_STRING_VIEW == 0 || \ + (ABSL_OPTION_USE_STD_STRING_VIEW == 2 && \ + !defined(ABSL_HAVE_STD_STRING_VIEW)) +#undef ABSL_USES_STD_STRING_VIEW +#elif ABSL_OPTION_USE_STD_STRING_VIEW == 1 || \ + (ABSL_OPTION_USE_STD_STRING_VIEW == 2 && \ + defined(ABSL_HAVE_STD_STRING_VIEW)) +#define ABSL_USES_STD_STRING_VIEW 1 +#else +#error options.h is misconfigured. +#endif + +// In debug mode, MSVC 2017's std::variant throws a EXCEPTION_ACCESS_VIOLATION +// SEH exception from emplace for variant when constructing the +// struct can throw. This defeats some of variant_test and +// variant_exception_safety_test. +#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_DEBUG) +#define ABSL_INTERNAL_MSVC_2017_DBG_MODE +#endif + +// ABSL_INTERNAL_MANGLED_NS +// ABSL_INTERNAL_MANGLED_BACKREFERENCE +// +// Internal macros for building up mangled names in our internal fork of CCTZ. +// This implementation detail is only needed and provided for the MSVC build. +// +// These macros both expand to string literals. ABSL_INTERNAL_MANGLED_NS is +// the mangled spelling of the `absl` namespace, and +// ABSL_INTERNAL_MANGLED_BACKREFERENCE is a back-reference integer representing +// the proper count to skip past the CCTZ fork namespace names. (This number +// is one larger when there is an inline namespace name to skip.) +#if defined(_MSC_VER) +#if ABSL_OPTION_USE_INLINE_NAMESPACE == 0 +#define ABSL_INTERNAL_MANGLED_NS "absl" +#define ABSL_INTERNAL_MANGLED_BACKREFERENCE "5" +#else +#define ABSL_INTERNAL_MANGLED_NS \ + ABSL_INTERNAL_TOKEN_STR(ABSL_OPTION_INLINE_NAMESPACE_NAME) "@absl" +#define ABSL_INTERNAL_MANGLED_BACKREFERENCE "6" +#endif +#endif + +#undef ABSL_INTERNAL_HAS_KEYWORD + +// ABSL_DLL +// +// When building Abseil as a DLL, this macro expands to `__declspec(dllexport)` +// so we can annotate symbols appropriately as being exported. When used in +// headers consuming a DLL, this macro expands to `__declspec(dllimport)` so +// that consumers know the symbol is defined inside the DLL. In all other cases, +// the macro expands to nothing. +#if defined(_MSC_VER) +#if defined(ABSL_BUILD_DLL) +#define ABSL_DLL __declspec(dllexport) +#elif defined(ABSL_CONSUME_DLL) +#define ABSL_DLL __declspec(dllimport) +#else +#define ABSL_DLL +#endif +#else +#define ABSL_DLL +#endif // defined(_MSC_VER) + +// ABSL_HAVE_MEMORY_SANITIZER +// +// MemorySanitizer (MSan) is a detector of uninitialized reads. It consists of +// a compiler instrumentation module and a run-time library. +#ifdef ABSL_HAVE_MEMORY_SANITIZER +#error "ABSL_HAVE_MEMORY_SANITIZER cannot be directly set." +#elif defined(__SANITIZE_MEMORY__) +#define ABSL_HAVE_MEMORY_SANITIZER 1 +#elif !defined(__native_client__) && ABSL_HAVE_FEATURE(memory_sanitizer) +#define ABSL_HAVE_MEMORY_SANITIZER 1 +#endif + +// ABSL_HAVE_THREAD_SANITIZER +// +// ThreadSanitizer (TSan) is a fast data race detector. +#ifdef ABSL_HAVE_THREAD_SANITIZER +#error "ABSL_HAVE_THREAD_SANITIZER cannot be directly set." +#elif defined(__SANITIZE_THREAD__) +#define ABSL_HAVE_THREAD_SANITIZER 1 +#elif ABSL_HAVE_FEATURE(thread_sanitizer) +#define ABSL_HAVE_THREAD_SANITIZER 1 +#endif + +// ABSL_HAVE_ADDRESS_SANITIZER +// +// AddressSanitizer (ASan) is a fast memory error detector. +#ifdef ABSL_HAVE_ADDRESS_SANITIZER +#error "ABSL_HAVE_ADDRESS_SANITIZER cannot be directly set." +#elif defined(__SANITIZE_ADDRESS__) +#define ABSL_HAVE_ADDRESS_SANITIZER 1 +#elif ABSL_HAVE_FEATURE(address_sanitizer) +#define ABSL_HAVE_ADDRESS_SANITIZER 1 +#endif + +// ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION +// +// Class template argument deduction is a language feature added in C++17. +#ifdef ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION +#error "ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION cannot be directly set." +#elif defined(__cpp_deduction_guides) +#define ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION 1 +#endif + +#endif // ABSL_BASE_CONFIG_H_ diff --git a/extern/int128/absl/base/macros.h b/extern/int128/absl/base/macros.h new file mode 100644 index 0000000000..3e085a916b --- /dev/null +++ b/extern/int128/absl/base/macros.h @@ -0,0 +1,158 @@ +// +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ----------------------------------------------------------------------------- +// File: macros.h +// ----------------------------------------------------------------------------- +// +// This header file defines the set of language macros used within Abseil code. +// For the set of macros used to determine supported compilers and platforms, +// see absl/base/config.h instead. +// +// This code is compiled directly on many platforms, including client +// platforms like Windows, Mac, and embedded systems. Before making +// any changes here, make sure that you're not breaking any platforms. + +#ifndef ABSL_BASE_MACROS_H_ +#define ABSL_BASE_MACROS_H_ + +#include +#include + +#include "absl/base/attributes.h" +#include "absl/base/config.h" +#include "absl/base/optimization.h" +#include "absl/base/port.h" + +// ABSL_ARRAYSIZE() +// +// Returns the number of elements in an array as a compile-time constant, which +// can be used in defining new arrays. If you use this macro on a pointer by +// mistake, you will get a compile-time error. +#define ABSL_ARRAYSIZE(array) \ + (sizeof(::absl::macros_internal::ArraySizeHelper(array))) + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace macros_internal { +// Note: this internal template function declaration is used by ABSL_ARRAYSIZE. +// The function doesn't need a definition, as we only use its type. +template +auto ArraySizeHelper(const T (&array)[N]) -> char (&)[N]; +} // namespace macros_internal +ABSL_NAMESPACE_END +} // namespace absl + +// ABSL_BAD_CALL_IF() +// +// Used on a function overload to trap bad calls: any call that matches the +// overload will cause a compile-time error. This macro uses a clang-specific +// "enable_if" attribute, as described at +// https://clang.llvm.org/docs/AttributeReference.html#enable-if +// +// Overloads which use this macro should be bracketed by +// `#ifdef ABSL_BAD_CALL_IF`. +// +// Example: +// +// int isdigit(int c); +// #ifdef ABSL_BAD_CALL_IF +// int isdigit(int c) +// ABSL_BAD_CALL_IF(c <= -1 || c > 255, +// "'c' must have the value of an unsigned char or EOF"); +// #endif // ABSL_BAD_CALL_IF +#if ABSL_HAVE_ATTRIBUTE(enable_if) +#define ABSL_BAD_CALL_IF(expr, msg) \ + __attribute__((enable_if(expr, "Bad call trap"), unavailable(msg))) +#endif + +// ABSL_ASSERT() +// +// In C++11, `assert` can't be used portably within constexpr functions. +// ABSL_ASSERT functions as a runtime assert but works in C++11 constexpr +// functions. Example: +// +// constexpr double Divide(double a, double b) { +// return ABSL_ASSERT(b != 0), a / b; +// } +// +// This macro is inspired by +// https://akrzemi1.wordpress.com/2017/05/18/asserts-in-constexpr-functions/ +#if defined(NDEBUG) +#define ABSL_ASSERT(expr) \ + (false ? static_cast(expr) : static_cast(0)) +#else +#define ABSL_ASSERT(expr) \ + (ABSL_PREDICT_TRUE((expr)) ? static_cast(0) \ + : [] { assert(false && #expr); }()) // NOLINT +#endif + +// `ABSL_INTERNAL_HARDENING_ABORT()` controls how `ABSL_HARDENING_ASSERT()` +// aborts the program in release mode (when NDEBUG is defined). The +// implementation should abort the program as quickly as possible and ideally it +// should not be possible to ignore the abort request. +#if (ABSL_HAVE_BUILTIN(__builtin_trap) && \ + ABSL_HAVE_BUILTIN(__builtin_unreachable)) || \ + (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_INTERNAL_HARDENING_ABORT() \ + do { \ + __builtin_trap(); \ + __builtin_unreachable(); \ + } while (false) +#else +#define ABSL_INTERNAL_HARDENING_ABORT() abort() +#endif + +// ABSL_HARDENING_ASSERT() +// +// `ABSL_HARDENING_ASSERT()` is like `ABSL_ASSERT()`, but used to implement +// runtime assertions that should be enabled in hardened builds even when +// `NDEBUG` is defined. +// +// When `NDEBUG` is not defined, `ABSL_HARDENING_ASSERT()` is identical to +// `ABSL_ASSERT()`. +// +// See `ABSL_OPTION_HARDENED` in `absl/base/options.h` for more information on +// hardened mode. +#if ABSL_OPTION_HARDENED == 1 && defined(NDEBUG) +#define ABSL_HARDENING_ASSERT(expr) \ + (ABSL_PREDICT_TRUE((expr)) ? static_cast(0) \ + : [] { ABSL_INTERNAL_HARDENING_ABORT(); }()) +#else +#define ABSL_HARDENING_ASSERT(expr) ABSL_ASSERT(expr) +#endif + +#ifdef ABSL_HAVE_EXCEPTIONS +#define ABSL_INTERNAL_TRY try +#define ABSL_INTERNAL_CATCH_ANY catch (...) +#define ABSL_INTERNAL_RETHROW do { throw; } while (false) +#else // ABSL_HAVE_EXCEPTIONS +#define ABSL_INTERNAL_TRY if (true) +#define ABSL_INTERNAL_CATCH_ANY else if (false) +#define ABSL_INTERNAL_RETHROW do {} while (false) +#endif // ABSL_HAVE_EXCEPTIONS + +// `ABSL_INTERNAL_UNREACHABLE` is an unreachable statement. A program which +// reaches one has undefined behavior, and the compiler may optimize +// accordingly. +#if defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable) +#define ABSL_INTERNAL_UNREACHABLE __builtin_unreachable() +#elif defined(_MSC_VER) +#define ABSL_INTERNAL_UNREACHABLE __assume(0) +#else +#define ABSL_INTERNAL_UNREACHABLE +#endif + +#endif // ABSL_BASE_MACROS_H_ diff --git a/extern/int128/absl/base/optimization.h b/extern/int128/absl/base/optimization.h new file mode 100644 index 0000000000..d090be1286 --- /dev/null +++ b/extern/int128/absl/base/optimization.h @@ -0,0 +1,244 @@ +// +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ----------------------------------------------------------------------------- +// File: optimization.h +// ----------------------------------------------------------------------------- +// +// This header file defines portable macros for performance optimization. + +#ifndef ABSL_BASE_OPTIMIZATION_H_ +#define ABSL_BASE_OPTIMIZATION_H_ + +#include + +#include "absl/base/config.h" + +// ABSL_BLOCK_TAIL_CALL_OPTIMIZATION +// +// Instructs the compiler to avoid optimizing tail-call recursion. This macro is +// useful when you wish to preserve the existing function order within a stack +// trace for logging, debugging, or profiling purposes. +// +// Example: +// +// int f() { +// int result = g(); +// ABSL_BLOCK_TAIL_CALL_OPTIMIZATION(); +// return result; +// } +#if defined(__pnacl__) +#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() if (volatile int x = 0) { (void)x; } +#elif defined(__clang__) +// Clang will not tail call given inline volatile assembly. +#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() __asm__ __volatile__("") +#elif defined(__GNUC__) +// GCC will not tail call given inline volatile assembly. +#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() __asm__ __volatile__("") +#elif defined(_MSC_VER) +#include +// The __nop() intrinsic blocks the optimisation. +#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() __nop() +#else +#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() if (volatile int x = 0) { (void)x; } +#endif + +// ABSL_CACHELINE_SIZE +// +// Explicitly defines the size of the L1 cache for purposes of alignment. +// Setting the cacheline size allows you to specify that certain objects be +// aligned on a cacheline boundary with `ABSL_CACHELINE_ALIGNED` declarations. +// (See below.) +// +// NOTE: this macro should be replaced with the following C++17 features, when +// those are generally available: +// +// * `std::hardware_constructive_interference_size` +// * `std::hardware_destructive_interference_size` +// +// See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0154r1.html +// for more information. +#if defined(__GNUC__) +// Cache line alignment +#if defined(__i386__) || defined(__x86_64__) +#define ABSL_CACHELINE_SIZE 64 +#elif defined(__powerpc64__) +#define ABSL_CACHELINE_SIZE 128 +#elif defined(__aarch64__) +// We would need to read special register ctr_el0 to find out L1 dcache size. +// This value is a good estimate based on a real aarch64 machine. +#define ABSL_CACHELINE_SIZE 64 +#elif defined(__arm__) +// Cache line sizes for ARM: These values are not strictly correct since +// cache line sizes depend on implementations, not architectures. There +// are even implementations with cache line sizes configurable at boot +// time. +#if defined(__ARM_ARCH_5T__) +#define ABSL_CACHELINE_SIZE 32 +#elif defined(__ARM_ARCH_7A__) +#define ABSL_CACHELINE_SIZE 64 +#endif +#endif + +#ifndef ABSL_CACHELINE_SIZE +// A reasonable default guess. Note that overestimates tend to waste more +// space, while underestimates tend to waste more time. +#define ABSL_CACHELINE_SIZE 64 +#endif + +// ABSL_CACHELINE_ALIGNED +// +// Indicates that the declared object be cache aligned using +// `ABSL_CACHELINE_SIZE` (see above). Cacheline aligning objects allows you to +// load a set of related objects in the L1 cache for performance improvements. +// Cacheline aligning objects properly allows constructive memory sharing and +// prevents destructive (or "false") memory sharing. +// +// NOTE: callers should replace uses of this macro with `alignas()` using +// `std::hardware_constructive_interference_size` and/or +// `std::hardware_destructive_interference_size` when C++17 becomes available to +// them. +// +// See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0154r1.html +// for more information. +// +// On some compilers, `ABSL_CACHELINE_ALIGNED` expands to an `__attribute__` +// or `__declspec` attribute. For compilers where this is not known to work, +// the macro expands to nothing. +// +// No further guarantees are made here. The result of applying the macro +// to variables and types is always implementation-defined. +// +// WARNING: It is easy to use this attribute incorrectly, even to the point +// of causing bugs that are difficult to diagnose, crash, etc. It does not +// of itself guarantee that objects are aligned to a cache line. +// +// NOTE: Some compilers are picky about the locations of annotations such as +// this attribute, so prefer to put it at the beginning of your declaration. +// For example, +// +// ABSL_CACHELINE_ALIGNED static Foo* foo = ... +// +// class ABSL_CACHELINE_ALIGNED Bar { ... +// +// Recommendations: +// +// 1) Consult compiler documentation; this comment is not kept in sync as +// toolchains evolve. +// 2) Verify your use has the intended effect. This often requires inspecting +// the generated machine code. +// 3) Prefer applying this attribute to individual variables. Avoid +// applying it to types. This tends to localize the effect. +#define ABSL_CACHELINE_ALIGNED __attribute__((aligned(ABSL_CACHELINE_SIZE))) +#elif defined(_MSC_VER) +#define ABSL_CACHELINE_SIZE 64 +#define ABSL_CACHELINE_ALIGNED __declspec(align(ABSL_CACHELINE_SIZE)) +#else +#define ABSL_CACHELINE_SIZE 64 +#define ABSL_CACHELINE_ALIGNED +#endif + +// ABSL_PREDICT_TRUE, ABSL_PREDICT_FALSE +// +// Enables the compiler to prioritize compilation using static analysis for +// likely paths within a boolean branch. +// +// Example: +// +// if (ABSL_PREDICT_TRUE(expression)) { +// return result; // Faster if more likely +// } else { +// return 0; +// } +// +// Compilers can use the information that a certain branch is not likely to be +// taken (for instance, a CHECK failure) to optimize for the common case in +// the absence of better information (ie. compiling gcc with `-fprofile-arcs`). +// +// Recommendation: Modern CPUs dynamically predict branch execution paths, +// typically with accuracy greater than 97%. As a result, annotating every +// branch in a codebase is likely counterproductive; however, annotating +// specific branches that are both hot and consistently mispredicted is likely +// to yield performance improvements. +#if ABSL_HAVE_BUILTIN(__builtin_expect) || \ + (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_PREDICT_FALSE(x) (__builtin_expect(false || (x), false)) +#define ABSL_PREDICT_TRUE(x) (__builtin_expect(false || (x), true)) +#else +#define ABSL_PREDICT_FALSE(x) (x) +#define ABSL_PREDICT_TRUE(x) (x) +#endif + +// ABSL_INTERNAL_ASSUME(cond) +// Informs the compiler that a condition is always true and that it can assume +// it to be true for optimization purposes. The call has undefined behavior if +// the condition is false. +// In !NDEBUG mode, the condition is checked with an assert(). +// NOTE: The expression must not have side effects, as it will only be evaluated +// in some compilation modes and not others. +// +// Example: +// +// int x = ...; +// ABSL_INTERNAL_ASSUME(x >= 0); +// // The compiler can optimize the division to a simple right shift using the +// // assumption specified above. +// int y = x / 16; +// +#if !defined(NDEBUG) +#define ABSL_INTERNAL_ASSUME(cond) assert(cond) +#elif ABSL_HAVE_BUILTIN(__builtin_assume) +#define ABSL_INTERNAL_ASSUME(cond) __builtin_assume(cond) +#elif defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable) +#define ABSL_INTERNAL_ASSUME(cond) \ + do { \ + if (!(cond)) __builtin_unreachable(); \ + } while (0) +#elif defined(_MSC_VER) +#define ABSL_INTERNAL_ASSUME(cond) __assume(cond) +#else +#define ABSL_INTERNAL_ASSUME(cond) \ + do { \ + static_cast(false && (cond)); \ + } while (0) +#endif + +// ABSL_INTERNAL_UNIQUE_SMALL_NAME(cond) +// This macro forces small unique name on a static file level symbols like +// static local variables or static functions. This is intended to be used in +// macro definitions to optimize the cost of generated code. Do NOT use it on +// symbols exported from translation unit since it may cause a link time +// conflict. +// +// Example: +// +// #define MY_MACRO(txt) +// namespace { +// char VeryVeryLongVarName[] ABSL_INTERNAL_UNIQUE_SMALL_NAME() = txt; +// const char* VeryVeryLongFuncName() ABSL_INTERNAL_UNIQUE_SMALL_NAME(); +// const char* VeryVeryLongFuncName() { return txt; } +// } +// + +#if defined(__GNUC__) +#define ABSL_INTERNAL_UNIQUE_SMALL_NAME2(x) #x +#define ABSL_INTERNAL_UNIQUE_SMALL_NAME1(x) ABSL_INTERNAL_UNIQUE_SMALL_NAME2(x) +#define ABSL_INTERNAL_UNIQUE_SMALL_NAME() \ + asm(ABSL_INTERNAL_UNIQUE_SMALL_NAME1(.absl.__COUNTER__)) +#else +#define ABSL_INTERNAL_UNIQUE_SMALL_NAME() +#endif + +#endif // ABSL_BASE_OPTIMIZATION_H_ diff --git a/extern/int128/absl/base/options.h b/extern/int128/absl/base/options.h new file mode 100644 index 0000000000..230bf1eecc --- /dev/null +++ b/extern/int128/absl/base/options.h @@ -0,0 +1,238 @@ +// Copyright 2019 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ----------------------------------------------------------------------------- +// File: options.h +// ----------------------------------------------------------------------------- +// +// This file contains Abseil configuration options for setting specific +// implementations instead of letting Abseil determine which implementation to +// use at compile-time. Setting these options may be useful for package or build +// managers who wish to guarantee ABI stability within binary builds (which are +// otherwise difficult to enforce). +// +// *** IMPORTANT NOTICE FOR PACKAGE MANAGERS: It is important that +// maintainers of package managers who wish to package Abseil read and +// understand this file! *** +// +// Abseil contains a number of possible configuration endpoints, based on +// parameters such as the detected platform, language version, or command-line +// flags used to invoke the underlying binary. As is the case with all +// libraries, binaries which contain Abseil code must ensure that separate +// packages use the same compiled copy of Abseil to avoid a diamond dependency +// problem, which can occur if two packages built with different Abseil +// configuration settings are linked together. Diamond dependency problems in +// C++ may manifest as violations to the One Definition Rule (ODR) (resulting in +// linker errors), or undefined behavior (resulting in crashes). +// +// Diamond dependency problems can be avoided if all packages utilize the same +// exact version of Abseil. Building from source code with the same compilation +// parameters is the easiest way to avoid such dependency problems. However, for +// package managers who cannot control such compilation parameters, we are +// providing the file to allow you to inject ABI (Application Binary Interface) +// stability across builds. Settings options in this file will neither change +// API nor ABI, providing a stable copy of Abseil between packages. +// +// Care must be taken to keep options within these configurations isolated +// from any other dynamic settings, such as command-line flags which could alter +// these options. This file is provided specifically to help build and package +// managers provide a stable copy of Abseil within their libraries and binaries; +// other developers should not have need to alter the contents of this file. +// +// ----------------------------------------------------------------------------- +// Usage +// ----------------------------------------------------------------------------- +// +// For any particular package release, set the appropriate definitions within +// this file to whatever value makes the most sense for your package(s). Note +// that, by default, most of these options, at the moment, affect the +// implementation of types; future options may affect other implementation +// details. +// +// NOTE: the defaults within this file all assume that Abseil can select the +// proper Abseil implementation at compile-time, which will not be sufficient +// to guarantee ABI stability to package managers. + +#ifndef ABSL_BASE_OPTIONS_H_ +#define ABSL_BASE_OPTIONS_H_ + +// Include a standard library header to allow configuration based on the +// standard library in use. +#ifdef __cplusplus +#include +#endif + +// ----------------------------------------------------------------------------- +// Type Compatibility Options +// ----------------------------------------------------------------------------- +// +// ABSL_OPTION_USE_STD_ANY +// +// This option controls whether absl::any is implemented as an alias to +// std::any, or as an independent implementation. +// +// A value of 0 means to use Abseil's implementation. This requires only C++11 +// support, and is expected to work on every toolchain we support. +// +// A value of 1 means to use an alias to std::any. This requires that all code +// using Abseil is built in C++17 mode or later. +// +// A value of 2 means to detect the C++ version being used to compile Abseil, +// and use an alias only if a working std::any is available. This option is +// useful when you are building your entire program, including all of its +// dependencies, from source. It should not be used otherwise -- for example, +// if you are distributing Abseil in a binary package manager -- since in +// mode 2, absl::any will name a different type, with a different mangled name +// and binary layout, depending on the compiler flags passed by the end user. +// For more info, see https://abseil.io/about/design/dropin-types. +// +// User code should not inspect this macro. To check in the preprocessor if +// absl::any is a typedef of std::any, use the feature macro ABSL_USES_STD_ANY. + +#define ABSL_OPTION_USE_STD_ANY 2 + + +// ABSL_OPTION_USE_STD_OPTIONAL +// +// This option controls whether absl::optional is implemented as an alias to +// std::optional, or as an independent implementation. +// +// A value of 0 means to use Abseil's implementation. This requires only C++11 +// support, and is expected to work on every toolchain we support. +// +// A value of 1 means to use an alias to std::optional. This requires that all +// code using Abseil is built in C++17 mode or later. +// +// A value of 2 means to detect the C++ version being used to compile Abseil, +// and use an alias only if a working std::optional is available. This option +// is useful when you are building your program from source. It should not be +// used otherwise -- for example, if you are distributing Abseil in a binary +// package manager -- since in mode 2, absl::optional will name a different +// type, with a different mangled name and binary layout, depending on the +// compiler flags passed by the end user. For more info, see +// https://abseil.io/about/design/dropin-types. + +// User code should not inspect this macro. To check in the preprocessor if +// absl::optional is a typedef of std::optional, use the feature macro +// ABSL_USES_STD_OPTIONAL. + +#define ABSL_OPTION_USE_STD_OPTIONAL 2 + + +// ABSL_OPTION_USE_STD_STRING_VIEW +// +// This option controls whether absl::string_view is implemented as an alias to +// std::string_view, or as an independent implementation. +// +// A value of 0 means to use Abseil's implementation. This requires only C++11 +// support, and is expected to work on every toolchain we support. +// +// A value of 1 means to use an alias to std::string_view. This requires that +// all code using Abseil is built in C++17 mode or later. +// +// A value of 2 means to detect the C++ version being used to compile Abseil, +// and use an alias only if a working std::string_view is available. This +// option is useful when you are building your program from source. It should +// not be used otherwise -- for example, if you are distributing Abseil in a +// binary package manager -- since in mode 2, absl::string_view will name a +// different type, with a different mangled name and binary layout, depending on +// the compiler flags passed by the end user. For more info, see +// https://abseil.io/about/design/dropin-types. +// +// User code should not inspect this macro. To check in the preprocessor if +// absl::string_view is a typedef of std::string_view, use the feature macro +// ABSL_USES_STD_STRING_VIEW. + +#define ABSL_OPTION_USE_STD_STRING_VIEW 2 + +// ABSL_OPTION_USE_STD_VARIANT +// +// This option controls whether absl::variant is implemented as an alias to +// std::variant, or as an independent implementation. +// +// A value of 0 means to use Abseil's implementation. This requires only C++11 +// support, and is expected to work on every toolchain we support. +// +// A value of 1 means to use an alias to std::variant. This requires that all +// code using Abseil is built in C++17 mode or later. +// +// A value of 2 means to detect the C++ version being used to compile Abseil, +// and use an alias only if a working std::variant is available. This option +// is useful when you are building your program from source. It should not be +// used otherwise -- for example, if you are distributing Abseil in a binary +// package manager -- since in mode 2, absl::variant will name a different +// type, with a different mangled name and binary layout, depending on the +// compiler flags passed by the end user. For more info, see +// https://abseil.io/about/design/dropin-types. +// +// User code should not inspect this macro. To check in the preprocessor if +// absl::variant is a typedef of std::variant, use the feature macro +// ABSL_USES_STD_VARIANT. + +#define ABSL_OPTION_USE_STD_VARIANT 2 + + +// ABSL_OPTION_USE_INLINE_NAMESPACE +// ABSL_OPTION_INLINE_NAMESPACE_NAME +// +// These options controls whether all entities in the absl namespace are +// contained within an inner inline namespace. This does not affect the +// user-visible API of Abseil, but it changes the mangled names of all symbols. +// +// This can be useful as a version tag if you are distributing Abseil in +// precompiled form. This will prevent a binary library build of Abseil with +// one inline namespace being used with headers configured with a different +// inline namespace name. Binary packagers are reminded that Abseil does not +// guarantee any ABI stability in Abseil, so any update of Abseil or +// configuration change in such a binary package should be combined with a +// new, unique value for the inline namespace name. +// +// A value of 0 means not to use inline namespaces. +// +// A value of 1 means to use an inline namespace with the given name inside +// namespace absl. If this is set, ABSL_OPTION_INLINE_NAMESPACE_NAME must also +// be changed to a new, unique identifier name. In particular "head" is not +// allowed. + +#define ABSL_OPTION_USE_INLINE_NAMESPACE 0 +#define ABSL_OPTION_INLINE_NAMESPACE_NAME head + +// ABSL_OPTION_HARDENED +// +// This option enables a "hardened" build in release mode (in this context, +// release mode is defined as a build where the `NDEBUG` macro is defined). +// +// A value of 0 means that "hardened" mode is not enabled. +// +// A value of 1 means that "hardened" mode is enabled. +// +// Hardened builds have additional security checks enabled when `NDEBUG` is +// defined. Defining `NDEBUG` is normally used to turn `assert()` macro into a +// no-op, as well as disabling other bespoke program consistency checks. By +// defining ABSL_OPTION_HARDENED to 1, a select set of checks remain enabled in +// release mode. These checks guard against programming errors that may lead to +// security vulnerabilities. In release mode, when one of these programming +// errors is encountered, the program will immediately abort, possibly without +// any attempt at logging. +// +// The checks enabled by this option are not free; they do incur runtime cost. +// +// The checks enabled by this option are always active when `NDEBUG` is not +// defined, even in the case when ABSL_OPTION_HARDENED is defined to 0. The +// checks enabled by this option may abort the program in a different way and +// log additional information when `NDEBUG` is not defined. + +#define ABSL_OPTION_HARDENED 0 + +#endif // ABSL_BASE_OPTIONS_H_ diff --git a/extern/int128/absl/base/policy_checks.h b/extern/int128/absl/base/policy_checks.h new file mode 100644 index 0000000000..06b3243916 --- /dev/null +++ b/extern/int128/absl/base/policy_checks.h @@ -0,0 +1,111 @@ +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ----------------------------------------------------------------------------- +// File: policy_checks.h +// ----------------------------------------------------------------------------- +// +// This header enforces a minimum set of policies at build time, such as the +// supported compiler and library versions. Unsupported configurations are +// reported with `#error`. This enforcement is best effort, so successfully +// compiling this header does not guarantee a supported configuration. + +#ifndef ABSL_BASE_POLICY_CHECKS_H_ +#define ABSL_BASE_POLICY_CHECKS_H_ + +// Included for the __GLIBC_PREREQ macro used below. +#include + +// Included for the _STLPORT_VERSION macro used below. +#if defined(__cplusplus) +#include +#endif + +// ----------------------------------------------------------------------------- +// Operating System Check +// ----------------------------------------------------------------------------- + +#if defined(__CYGWIN__) +#error "Cygwin is not supported." +#endif + +// ----------------------------------------------------------------------------- +// Toolchain Check +// ----------------------------------------------------------------------------- + +// We support MSVC++ 14.0 update 2 and later. +// This minimum will go up. +#if defined(_MSC_FULL_VER) && _MSC_FULL_VER < 190023918 && !defined(__clang__) +#error "This package requires Visual Studio 2015 Update 2 or higher." +#endif + +// We support gcc 4.7 and later. +// This minimum will go up. +#if defined(__GNUC__) && !defined(__clang__) +#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7) +#error "This package requires gcc 4.7 or higher." +#endif +#endif + +// We support Apple Xcode clang 4.2.1 (version 421.11.65) and later. +// This corresponds to Apple Xcode version 4.5. +// This minimum will go up. +#if defined(__apple_build_version__) && __apple_build_version__ < 4211165 +#error "This package requires __apple_build_version__ of 4211165 or higher." +#endif + +// ----------------------------------------------------------------------------- +// C++ Version Check +// ----------------------------------------------------------------------------- + +// Enforce C++11 as the minimum. Note that Visual Studio has not +// advanced __cplusplus despite being good enough for our purposes, so +// so we exempt it from the check. +#if defined(__cplusplus) && !defined(_MSC_VER) +#if __cplusplus < 201103L +#error "C++ versions less than C++11 are not supported." +#endif +#endif + +// ----------------------------------------------------------------------------- +// Standard Library Check +// ----------------------------------------------------------------------------- + +#if defined(_STLPORT_VERSION) +#error "STLPort is not supported." +#endif + +// ----------------------------------------------------------------------------- +// `char` Size Check +// ----------------------------------------------------------------------------- + +// Abseil currently assumes CHAR_BIT == 8. If you would like to use Abseil on a +// platform where this is not the case, please provide us with the details about +// your platform so we can consider relaxing this requirement. +#if CHAR_BIT != 8 +#error "Abseil assumes CHAR_BIT == 8." +#endif + +// ----------------------------------------------------------------------------- +// `int` Size Check +// ----------------------------------------------------------------------------- + +// Abseil currently assumes that an int is 4 bytes. If you would like to use +// Abseil on a platform where this is not the case, please provide us with the +// details about your platform so we can consider relaxing this requirement. +#if INT_MAX < 2147483647 +#error "Abseil assumes that int is at least 4 bytes. " +#endif + +#endif // ABSL_BASE_POLICY_CHECKS_H_ diff --git a/extern/int128/absl/base/port.h b/extern/int128/absl/base/port.h new file mode 100644 index 0000000000..5bc4d6cd95 --- /dev/null +++ b/extern/int128/absl/base/port.h @@ -0,0 +1,25 @@ +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// This files is a forwarding header for other headers containing various +// portability macros and functions. + +#ifndef ABSL_BASE_PORT_H_ +#define ABSL_BASE_PORT_H_ + +#include "absl/base/attributes.h" +#include "absl/base/config.h" +#include "absl/base/optimization.h" + +#endif // ABSL_BASE_PORT_H_ diff --git a/extern/int128/absl/numeric/Makefile b/extern/int128/absl/numeric/Makefile new file mode 100644 index 0000000000..396e95d063 --- /dev/null +++ b/extern/int128/absl/numeric/Makefile @@ -0,0 +1,11 @@ +LIBRARY=libi128$(CROSS).a + +$(LIBRARY): $(wildcard *.cc) $(wildcard *.h) $(wildcard internal/*.h) $(wildcard ../base/*.h) $(wildcard *.inc) Makefile + $(RM) -f *.o + $(CXX) $(CROSS_FLAGS) -I../.. -c -O3 -fPIC int128.cc + $(AR) crs $(LIBRARY) *.o + $(RM) -f *.o + +.PHONY: clean +clean: + $(RM) -f *.o *.a diff --git a/extern/int128/absl/numeric/bits.h b/extern/int128/absl/numeric/bits.h new file mode 100644 index 0000000000..52013ad49b --- /dev/null +++ b/extern/int128/absl/numeric/bits.h @@ -0,0 +1,177 @@ +// Copyright 2020 The Abseil Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ----------------------------------------------------------------------------- +// File: bits.h +// ----------------------------------------------------------------------------- +// +// This file contains implementations of C++20's bitwise math functions, as +// defined by: +// +// P0553R4: +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0553r4.html +// P0556R3: +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0556r3.html +// P1355R2: +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1355r2.html +// P1956R1: +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1956r1.pdf +// +// When using a standard library that implements these functions, we use the +// standard library's implementation. + +#ifndef ABSL_NUMERIC_BITS_H_ +#define ABSL_NUMERIC_BITS_H_ + +#include +#include +#include + +#if (defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L) || \ + (defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L) +#include +#endif + +#include "absl/base/attributes.h" +#include "absl/base/config.h" +#include "absl/numeric/internal/bits.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN + +#if !(defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L) +// rotating +template +ABSL_MUST_USE_RESULT constexpr + typename std::enable_if::value, T>::type + rotl(T x, int s) noexcept { + return numeric_internal::RotateLeft(x, s); +} + +template +ABSL_MUST_USE_RESULT constexpr + typename std::enable_if::value, T>::type + rotr(T x, int s) noexcept { + return numeric_internal::RotateRight(x, s); +} + +// Counting functions +// +// While these functions are typically constexpr, on some platforms, they may +// not be marked as constexpr due to constraints of the compiler/available +// intrinsics. +template +ABSL_INTERNAL_CONSTEXPR_CLZ inline + typename std::enable_if::value, int>::type + countl_zero(T x) noexcept { + return numeric_internal::CountLeadingZeroes(x); +} + +template +ABSL_INTERNAL_CONSTEXPR_CLZ inline + typename std::enable_if::value, int>::type + countl_one(T x) noexcept { + // Avoid integer promotion to a wider type + return countl_zero(static_cast(~x)); +} + +template +ABSL_INTERNAL_CONSTEXPR_CTZ inline + typename std::enable_if::value, int>::type + countr_zero(T x) noexcept { + return numeric_internal::CountTrailingZeroes(x); +} + +template +ABSL_INTERNAL_CONSTEXPR_CTZ inline + typename std::enable_if::value, int>::type + countr_one(T x) noexcept { + // Avoid integer promotion to a wider type + return countr_zero(static_cast(~x)); +} + +template +ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline + typename std::enable_if::value, int>::type + popcount(T x) noexcept { + return numeric_internal::Popcount(x); +} +#else // defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L + +using std::countl_one; +using std::countl_zero; +using std::countr_one; +using std::countr_zero; +using std::popcount; +using std::rotl; +using std::rotr; + +#endif + +#if !(defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L) +// Returns: true if x is an integral power of two; false otherwise. +template +constexpr inline typename std::enable_if::value, bool>::type +has_single_bit(T x) noexcept { + return x != 0 && (x & (x - 1)) == 0; +} + +// Returns: If x == 0, 0; otherwise one plus the base-2 logarithm of x, with any +// fractional part discarded. +template +ABSL_INTERNAL_CONSTEXPR_CLZ inline + typename std::enable_if::value, T>::type + bit_width(T x) noexcept { + return std::numeric_limits::digits - countl_zero(x); +} + +// Returns: If x == 0, 0; otherwise the maximal value y such that +// has_single_bit(y) is true and y <= x. +template +ABSL_INTERNAL_CONSTEXPR_CLZ inline + typename std::enable_if::value, T>::type + bit_floor(T x) noexcept { + return x == 0 ? 0 : T{1} << (bit_width(x) - 1); +} + +// Returns: N, where N is the smallest power of 2 greater than or equal to x. +// +// Preconditions: N is representable as a value of type T. +template +ABSL_INTERNAL_CONSTEXPR_CLZ inline + typename std::enable_if::value, T>::type + bit_ceil(T x) { + // If T is narrower than unsigned, T{1} << bit_width will be promoted. We + // want to force it to wraparound so that bit_ceil of an invalid value are not + // core constant expressions. + // + // BitCeilNonPowerOf2 triggers an overflow in constexpr contexts if we would + // undergo promotion to unsigned but not fit the result into T without + // truncation. + return has_single_bit(x) ? T{1} << (bit_width(x) - 1) + : numeric_internal::BitCeilNonPowerOf2(x); +} +#else // defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L + +using std::bit_ceil; +using std::bit_floor; +using std::bit_width; +using std::has_single_bit; + +#endif + +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_NUMERIC_BITS_H_ diff --git a/extern/int128/absl/numeric/int128.cc b/extern/int128/absl/numeric/int128.cc new file mode 100644 index 0000000000..17d88744ae --- /dev/null +++ b/extern/int128/absl/numeric/int128.cc @@ -0,0 +1,383 @@ +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "absl/numeric/int128.h" + +#include + +#include +#include +#include // NOLINT(readability/streams) +#include +#include +#include + +#include "absl/base/optimization.h" +#include "absl/numeric/bits.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN + +ABSL_DLL const uint128 kuint128max = MakeUint128( + std::numeric_limits::max(), std::numeric_limits::max()); + +namespace { + +// Returns the 0-based position of the last set bit (i.e., most significant bit) +// in the given uint128. The argument is not 0. +// +// For example: +// Given: 5 (decimal) == 101 (binary) +// Returns: 2 +inline ABSL_ATTRIBUTE_ALWAYS_INLINE int Fls128(uint128 n) { + if (uint64_t hi = Uint128High64(n)) { + ABSL_INTERNAL_ASSUME(hi != 0); + return 127 - countl_zero(hi); + } + const uint64_t low = Uint128Low64(n); + ABSL_INTERNAL_ASSUME(low != 0); + return 63 - countl_zero(low); +} + +// Long division/modulo for uint128 implemented using the shift-subtract +// division algorithm adapted from: +// https://stackoverflow.com/questions/5386377/division-without-using +inline void DivModImpl(uint128 dividend, uint128 divisor, uint128* quotient_ret, + uint128* remainder_ret) { + assert(divisor != 0); + + if (divisor > dividend) { + *quotient_ret = 0; + *remainder_ret = dividend; + return; + } + + if (divisor == dividend) { + *quotient_ret = 1; + *remainder_ret = 0; + return; + } + + uint128 denominator = divisor; + uint128 quotient = 0; + + // Left aligns the MSB of the denominator and the dividend. + const int shift = Fls128(dividend) - Fls128(denominator); + denominator <<= shift; + + // Uses shift-subtract algorithm to divide dividend by denominator. The + // remainder will be left in dividend. + for (int i = 0; i <= shift; ++i) { + quotient <<= 1; + if (dividend >= denominator) { + dividend -= denominator; + quotient |= 1; + } + denominator >>= 1; + } + + *quotient_ret = quotient; + *remainder_ret = dividend; +} + +template +uint128 MakeUint128FromFloat(T v) { + static_assert(std::is_floating_point::value, ""); + + // Rounding behavior is towards zero, same as for built-in types. + + // Undefined behavior if v is NaN or cannot fit into uint128. + assert(std::isfinite(v) && v > -1 && + (std::numeric_limits::max_exponent <= 128 || + v < std::ldexp(static_cast(1), 128))); + + if (v >= std::ldexp(static_cast(1), 64)) { + uint64_t hi = static_cast(std::ldexp(v, -64)); + uint64_t lo = static_cast(v - std::ldexp(static_cast(hi), 64)); + return MakeUint128(hi, lo); + } + + return MakeUint128(0, static_cast(v)); +} + +#if defined(__clang__) && !defined(__SSE3__) +// Workaround for clang bug: https://bugs.llvm.org/show_bug.cgi?id=38289 +// Casting from long double to uint64_t is miscompiled and drops bits. +// It is more work, so only use when we need the workaround. +uint128 MakeUint128FromFloat(long double v) { + // Go 50 bits at a time, that fits in a double + static_assert(std::numeric_limits::digits >= 50, ""); + static_assert(std::numeric_limits::digits <= 150, ""); + // Undefined behavior if v is not finite or cannot fit into uint128. + assert(std::isfinite(v) && v > -1 && v < std::ldexp(1.0L, 128)); + + v = std::ldexp(v, -100); + uint64_t w0 = static_cast(static_cast(std::trunc(v))); + v = std::ldexp(v - static_cast(w0), 50); + uint64_t w1 = static_cast(static_cast(std::trunc(v))); + v = std::ldexp(v - static_cast(w1), 50); + uint64_t w2 = static_cast(static_cast(std::trunc(v))); + return (static_cast(w0) << 100) | (static_cast(w1) << 50) | + static_cast(w2); +} +#endif // __clang__ && !__SSE3__ +} // namespace + +uint128::uint128(float v) : uint128(MakeUint128FromFloat(v)) {} +uint128::uint128(double v) : uint128(MakeUint128FromFloat(v)) {} +uint128::uint128(long double v) : uint128(MakeUint128FromFloat(v)) {} + +#if !defined(ABSL_HAVE_INTRINSIC_INT128) +uint128 operator/(uint128 lhs, uint128 rhs) { + uint128 quotient = 0; + uint128 remainder = 0; + DivModImpl(lhs, rhs, "ient, &remainder); + return quotient; +} + +uint128 operator%(uint128 lhs, uint128 rhs) { + uint128 quotient = 0; + uint128 remainder = 0; + DivModImpl(lhs, rhs, "ient, &remainder); + return remainder; +} +#endif // !defined(ABSL_HAVE_INTRINSIC_INT128) + +namespace { + +std::string Uint128ToFormattedString(uint128 v, std::ios_base::fmtflags flags) { + // Select a divisor which is the largest power of the base < 2^64. + uint128 div; + int div_base_log; + switch (flags & std::ios::basefield) { + case std::ios::hex: + div = 0x1000000000000000; // 16^15 + div_base_log = 15; + break; + case std::ios::oct: + div = 01000000000000000000000; // 8^21 + div_base_log = 21; + break; + default: // std::ios::dec + div = 10000000000000000000u; // 10^19 + div_base_log = 19; + break; + } + + // Now piece together the uint128 representation from three chunks of the + // original value, each less than "div" and therefore representable as a + // uint64_t. + std::ostringstream os; + std::ios_base::fmtflags copy_mask = + std::ios::basefield | std::ios::showbase | std::ios::uppercase; + os.setf(flags & copy_mask, copy_mask); + uint128 high = v; + uint128 low; + DivModImpl(high, div, &high, &low); + uint128 mid; + DivModImpl(high, div, &high, &mid); + if (Uint128Low64(high) != 0) { + os << Uint128Low64(high); + os << std::noshowbase << std::setfill('0') << std::setw(div_base_log); + os << Uint128Low64(mid); + os << std::setw(div_base_log); + } else if (Uint128Low64(mid) != 0) { + os << Uint128Low64(mid); + os << std::noshowbase << std::setfill('0') << std::setw(div_base_log); + } + os << Uint128Low64(low); + return os.str(); +} + +} // namespace + +std::ostream& operator<<(std::ostream& os, uint128 v) { + std::ios_base::fmtflags flags = os.flags(); + std::string rep = Uint128ToFormattedString(v, flags); + + // Add the requisite padding. + std::streamsize width = os.width(0); + if (static_cast(width) > rep.size()) { + std::ios::fmtflags adjustfield = flags & std::ios::adjustfield; + if (adjustfield == std::ios::left) { + rep.append(width - rep.size(), os.fill()); + } else if (adjustfield == std::ios::internal && + (flags & std::ios::showbase) && + (flags & std::ios::basefield) == std::ios::hex && v != 0) { + rep.insert(2, width - rep.size(), os.fill()); + } else { + rep.insert(0, width - rep.size(), os.fill()); + } + } + + return os << rep; +} + +namespace { + +uint128 UnsignedAbsoluteValue(int128 v) { + // Cast to uint128 before possibly negating because -Int128Min() is undefined. + return Int128High64(v) < 0 ? -uint128(v) : uint128(v); +} + +} // namespace + +#if !defined(ABSL_HAVE_INTRINSIC_INT128) +namespace { + +template +int128 MakeInt128FromFloat(T v) { + // Conversion when v is NaN or cannot fit into int128 would be undefined + // behavior if using an intrinsic 128-bit integer. + assert(std::isfinite(v) && (std::numeric_limits::max_exponent <= 127 || + (v >= -std::ldexp(static_cast(1), 127) && + v < std::ldexp(static_cast(1), 127)))); + + // We must convert the absolute value and then negate as needed, because + // floating point types are typically sign-magnitude. Otherwise, the + // difference between the high and low 64 bits when interpreted as two's + // complement overwhelms the precision of the mantissa. + uint128 result = v < 0 ? -MakeUint128FromFloat(-v) : MakeUint128FromFloat(v); + return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(result)), + Uint128Low64(result)); +} + +} // namespace + +int128::int128(float v) : int128(MakeInt128FromFloat(v)) {} +int128::int128(double v) : int128(MakeInt128FromFloat(v)) {} +int128::int128(long double v) : int128(MakeInt128FromFloat(v)) {} + +int128 operator/(int128 lhs, int128 rhs) { + assert(lhs != Int128Min() || rhs != -1); // UB on two's complement. + + uint128 quotient = 0; + uint128 remainder = 0; + DivModImpl(UnsignedAbsoluteValue(lhs), UnsignedAbsoluteValue(rhs), + "ient, &remainder); + if ((Int128High64(lhs) < 0) != (Int128High64(rhs) < 0)) quotient = -quotient; + return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(quotient)), + Uint128Low64(quotient)); +} + +int128 operator%(int128 lhs, int128 rhs) { + assert(lhs != Int128Min() || rhs != -1); // UB on two's complement. + + uint128 quotient = 0; + uint128 remainder = 0; + DivModImpl(UnsignedAbsoluteValue(lhs), UnsignedAbsoluteValue(rhs), + "ient, &remainder); + if (Int128High64(lhs) < 0) remainder = -remainder; + return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(remainder)), + Uint128Low64(remainder)); +} +#endif // ABSL_HAVE_INTRINSIC_INT128 + +std::ostream& operator<<(std::ostream& os, int128 v) { + std::ios_base::fmtflags flags = os.flags(); + std::string rep; + + // Add the sign if needed. + bool print_as_decimal = + (flags & std::ios::basefield) == std::ios::dec || + (flags & std::ios::basefield) == std::ios_base::fmtflags(); + if (print_as_decimal) { + if (Int128High64(v) < 0) { + rep = "-"; + } else if (flags & std::ios::showpos) { + rep = "+"; + } + } + + rep.append(Uint128ToFormattedString( + print_as_decimal ? UnsignedAbsoluteValue(v) : uint128(v), os.flags())); + + // Add the requisite padding. + std::streamsize width = os.width(0); + if (static_cast(width) > rep.size()) { + switch (flags & std::ios::adjustfield) { + case std::ios::left: + rep.append(width - rep.size(), os.fill()); + break; + case std::ios::internal: + if (print_as_decimal && (rep[0] == '+' || rep[0] == '-')) { + rep.insert(1, width - rep.size(), os.fill()); + } else if ((flags & std::ios::basefield) == std::ios::hex && + (flags & std::ios::showbase) && v != 0) { + rep.insert(2, width - rep.size(), os.fill()); + } else { + rep.insert(0, width - rep.size(), os.fill()); + } + break; + default: // std::ios::right + rep.insert(0, width - rep.size(), os.fill()); + break; + } + } + + return os << rep; +} + +ABSL_NAMESPACE_END +} // namespace absl + +namespace std { +constexpr bool numeric_limits::is_specialized; +constexpr bool numeric_limits::is_signed; +constexpr bool numeric_limits::is_integer; +constexpr bool numeric_limits::is_exact; +constexpr bool numeric_limits::has_infinity; +constexpr bool numeric_limits::has_quiet_NaN; +constexpr bool numeric_limits::has_signaling_NaN; +constexpr float_denorm_style numeric_limits::has_denorm; +constexpr bool numeric_limits::has_denorm_loss; +constexpr float_round_style numeric_limits::round_style; +constexpr bool numeric_limits::is_iec559; +constexpr bool numeric_limits::is_bounded; +constexpr bool numeric_limits::is_modulo; +constexpr int numeric_limits::digits; +constexpr int numeric_limits::digits10; +constexpr int numeric_limits::max_digits10; +constexpr int numeric_limits::radix; +constexpr int numeric_limits::min_exponent; +constexpr int numeric_limits::min_exponent10; +constexpr int numeric_limits::max_exponent; +constexpr int numeric_limits::max_exponent10; +constexpr bool numeric_limits::traps; +constexpr bool numeric_limits::tinyness_before; + +constexpr bool numeric_limits::is_specialized; +constexpr bool numeric_limits::is_signed; +constexpr bool numeric_limits::is_integer; +constexpr bool numeric_limits::is_exact; +constexpr bool numeric_limits::has_infinity; +constexpr bool numeric_limits::has_quiet_NaN; +constexpr bool numeric_limits::has_signaling_NaN; +constexpr float_denorm_style numeric_limits::has_denorm; +constexpr bool numeric_limits::has_denorm_loss; +constexpr float_round_style numeric_limits::round_style; +constexpr bool numeric_limits::is_iec559; +constexpr bool numeric_limits::is_bounded; +constexpr bool numeric_limits::is_modulo; +constexpr int numeric_limits::digits; +constexpr int numeric_limits::digits10; +constexpr int numeric_limits::max_digits10; +constexpr int numeric_limits::radix; +constexpr int numeric_limits::min_exponent; +constexpr int numeric_limits::min_exponent10; +constexpr int numeric_limits::max_exponent; +constexpr int numeric_limits::max_exponent10; +constexpr bool numeric_limits::traps; +constexpr bool numeric_limits::tinyness_before; +} // namespace std diff --git a/extern/int128/absl/numeric/int128.h b/extern/int128/absl/numeric/int128.h new file mode 100644 index 0000000000..a9cbe489dd --- /dev/null +++ b/extern/int128/absl/numeric/int128.h @@ -0,0 +1,1155 @@ +// +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ----------------------------------------------------------------------------- +// File: int128.h +// ----------------------------------------------------------------------------- +// +// This header file defines 128-bit integer types, `uint128` and `int128`. +// +// TODO(absl-team): This module is inconsistent as many inline `uint128` methods +// are defined in this file, while many inline `int128` methods are defined in +// the `int128_*_intrinsic.inc` files. + +#ifndef ABSL_NUMERIC_INT128_H_ +#define ABSL_NUMERIC_INT128_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include "absl/base/config.h" +#include "absl/base/macros.h" +#include "absl/base/port.h" + +#if defined(_MSC_VER) +// In very old versions of MSVC and when the /Zc:wchar_t flag is off, wchar_t is +// a typedef for unsigned short. Otherwise wchar_t is mapped to the __wchar_t +// builtin type. We need to make sure not to define operator wchar_t() +// alongside operator unsigned short() in these instances. +#define ABSL_INTERNAL_WCHAR_T __wchar_t +#if defined(_M_X64) +#include +#pragma intrinsic(_umul128) +#endif // defined(_M_X64) +#else // defined(_MSC_VER) +#define ABSL_INTERNAL_WCHAR_T wchar_t +#endif // defined(_MSC_VER) + +namespace absl { +ABSL_NAMESPACE_BEGIN + +class int128; + +// uint128 +// +// An unsigned 128-bit integer type. The API is meant to mimic an intrinsic type +// as closely as is practical, including exhibiting undefined behavior in +// analogous cases (e.g. division by zero). This type is intended to be a +// drop-in replacement once C++ supports an intrinsic `uint128_t` type; when +// that occurs, existing well-behaved uses of `uint128` will continue to work +// using that new type. +// +// Note: code written with this type will continue to compile once `uint128_t` +// is introduced, provided the replacement helper functions +// `Uint128(Low|High)64()` and `MakeUint128()` are made. +// +// A `uint128` supports the following: +// +// * Implicit construction from integral types +// * Explicit conversion to integral types +// +// Additionally, if your compiler supports `__int128`, `uint128` is +// interoperable with that type. (Abseil checks for this compatibility through +// the `ABSL_HAVE_INTRINSIC_INT128` macro.) +// +// However, a `uint128` differs from intrinsic integral types in the following +// ways: +// +// * Errors on implicit conversions that do not preserve value (such as +// loss of precision when converting to float values). +// * Requires explicit construction from and conversion to floating point +// types. +// * Conversion to integral types requires an explicit static_cast() to +// mimic use of the `-Wnarrowing` compiler flag. +// * The alignment requirement of `uint128` may differ from that of an +// intrinsic 128-bit integer type depending on platform and build +// configuration. +// +// Example: +// +// float y = absl::Uint128Max(); // Error. uint128 cannot be implicitly +// // converted to float. +// +// absl::uint128 v; +// uint64_t i = v; // Error +// uint64_t i = static_cast(v); // OK +// +class +#if defined(ABSL_HAVE_INTRINSIC_INT128) + alignas(unsigned __int128) +#endif // ABSL_HAVE_INTRINSIC_INT128 + uint128 { + public: + uint128() = default; + + // Constructors from arithmetic types + constexpr uint128(int v); // NOLINT(runtime/explicit) + constexpr uint128(unsigned int v); // NOLINT(runtime/explicit) + constexpr uint128(long v); // NOLINT(runtime/int) + constexpr uint128(unsigned long v); // NOLINT(runtime/int) + constexpr uint128(long long v); // NOLINT(runtime/int) + constexpr uint128(unsigned long long v); // NOLINT(runtime/int) +#ifdef ABSL_HAVE_INTRINSIC_INT128 + constexpr uint128(__int128 v); // NOLINT(runtime/explicit) + constexpr uint128(unsigned __int128 v); // NOLINT(runtime/explicit) +#endif // ABSL_HAVE_INTRINSIC_INT128 + constexpr uint128(int128 v); // NOLINT(runtime/explicit) + explicit uint128(float v); + explicit uint128(double v); + explicit uint128(long double v); + + // Assignment operators from arithmetic types + uint128& operator=(int v); + uint128& operator=(unsigned int v); + uint128& operator=(long v); // NOLINT(runtime/int) + uint128& operator=(unsigned long v); // NOLINT(runtime/int) + uint128& operator=(long long v); // NOLINT(runtime/int) + uint128& operator=(unsigned long long v); // NOLINT(runtime/int) +#ifdef ABSL_HAVE_INTRINSIC_INT128 + uint128& operator=(__int128 v); + uint128& operator=(unsigned __int128 v); +#endif // ABSL_HAVE_INTRINSIC_INT128 + uint128& operator=(int128 v); + + // Conversion operators to other arithmetic types + constexpr explicit operator bool() const; + constexpr explicit operator char() const; + constexpr explicit operator signed char() const; + constexpr explicit operator unsigned char() const; + constexpr explicit operator char16_t() const; + constexpr explicit operator char32_t() const; + constexpr explicit operator ABSL_INTERNAL_WCHAR_T() const; + constexpr explicit operator short() const; // NOLINT(runtime/int) + // NOLINTNEXTLINE(runtime/int) + constexpr explicit operator unsigned short() const; + constexpr explicit operator int() const; + constexpr explicit operator unsigned int() const; + constexpr explicit operator long() const; // NOLINT(runtime/int) + // NOLINTNEXTLINE(runtime/int) + constexpr explicit operator unsigned long() const; + // NOLINTNEXTLINE(runtime/int) + constexpr explicit operator long long() const; + // NOLINTNEXTLINE(runtime/int) + constexpr explicit operator unsigned long long() const; +#ifdef ABSL_HAVE_INTRINSIC_INT128 + constexpr explicit operator __int128() const; + constexpr explicit operator unsigned __int128() const; +#endif // ABSL_HAVE_INTRINSIC_INT128 + explicit operator float() const; + explicit operator double() const; + explicit operator long double() const; + + // Trivial copy constructor, assignment operator and destructor. + + // Arithmetic operators. + uint128& operator+=(uint128 other); + uint128& operator-=(uint128 other); + uint128& operator*=(uint128 other); + // Long division/modulo for uint128. + uint128& operator/=(uint128 other); + uint128& operator%=(uint128 other); + uint128 operator++(int); + uint128 operator--(int); + uint128& operator<<=(int); + uint128& operator>>=(int); + uint128& operator&=(uint128 other); + uint128& operator|=(uint128 other); + uint128& operator^=(uint128 other); + uint128& operator++(); + uint128& operator--(); + + // Uint128Low64() + // + // Returns the lower 64-bit value of a `uint128` value. + friend constexpr uint64_t Uint128Low64(uint128 v); + + // Uint128High64() + // + // Returns the higher 64-bit value of a `uint128` value. + friend constexpr uint64_t Uint128High64(uint128 v); + + // MakeUInt128() + // + // Constructs a `uint128` numeric value from two 64-bit unsigned integers. + // Note that this factory function is the only way to construct a `uint128` + // from integer values greater than 2^64. + // + // Example: + // + // absl::uint128 big = absl::MakeUint128(1, 0); + friend constexpr uint128 MakeUint128(uint64_t high, uint64_t low); + + // Uint128Max() + // + // Returns the highest value for a 128-bit unsigned integer. + friend constexpr uint128 Uint128Max(); + + // Support for absl::Hash. + template + friend H AbslHashValue(H h, uint128 v) { + return H::combine(std::move(h), Uint128High64(v), Uint128Low64(v)); + } + + private: + constexpr uint128(uint64_t high, uint64_t low); + + // TODO(strel) Update implementation to use __int128 once all users of + // uint128 are fixed to not depend on alignof(uint128) == 8. Also add + // alignas(16) to class definition to keep alignment consistent across + // platforms. +#if defined(ABSL_IS_LITTLE_ENDIAN) + uint64_t lo_; + uint64_t hi_; +#elif defined(ABSL_IS_BIG_ENDIAN) + uint64_t hi_; + uint64_t lo_; +#else // byte order +#error "Unsupported byte order: must be little-endian or big-endian." +#endif // byte order +}; + +// Prefer to use the constexpr `Uint128Max()`. +// +// TODO(absl-team) deprecate kuint128max once migration tool is released. +ABSL_DLL extern const uint128 kuint128max; + +// allow uint128 to be logged +std::ostream& operator<<(std::ostream& os, uint128 v); + +// TODO(strel) add operator>>(std::istream&, uint128) + +constexpr uint128 Uint128Max() { + return uint128((std::numeric_limits::max)(), + (std::numeric_limits::max)()); +} + +ABSL_NAMESPACE_END +} // namespace absl + +// Specialized numeric_limits for uint128. +namespace std { +template <> +class numeric_limits { + public: + static constexpr bool is_specialized = true; + static constexpr bool is_signed = false; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr float_denorm_style has_denorm = denorm_absent; + static constexpr bool has_denorm_loss = false; + static constexpr float_round_style round_style = round_toward_zero; + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr int digits = 128; + static constexpr int digits10 = 38; + static constexpr int max_digits10 = 0; + static constexpr int radix = 2; + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; +#ifdef ABSL_HAVE_INTRINSIC_INT128 + static constexpr bool traps = numeric_limits::traps; +#else // ABSL_HAVE_INTRINSIC_INT128 + static constexpr bool traps = numeric_limits::traps; +#endif // ABSL_HAVE_INTRINSIC_INT128 + static constexpr bool tinyness_before = false; + + static constexpr absl::uint128 (min)() { return 0; } + static constexpr absl::uint128 lowest() { return 0; } + static constexpr absl::uint128 (max)() { return absl::Uint128Max(); } + static constexpr absl::uint128 epsilon() { return 0; } + static constexpr absl::uint128 round_error() { return 0; } + static constexpr absl::uint128 infinity() { return 0; } + static constexpr absl::uint128 quiet_NaN() { return 0; } + static constexpr absl::uint128 signaling_NaN() { return 0; } + static constexpr absl::uint128 denorm_min() { return 0; } +}; +} // namespace std + +namespace absl { +ABSL_NAMESPACE_BEGIN + +// int128 +// +// A signed 128-bit integer type. The API is meant to mimic an intrinsic +// integral type as closely as is practical, including exhibiting undefined +// behavior in analogous cases (e.g. division by zero). +// +// An `int128` supports the following: +// +// * Implicit construction from integral types +// * Explicit conversion to integral types +// +// However, an `int128` differs from intrinsic integral types in the following +// ways: +// +// * It is not implicitly convertible to other integral types. +// * Requires explicit construction from and conversion to floating point +// types. + +// Additionally, if your compiler supports `__int128`, `int128` is +// interoperable with that type. (Abseil checks for this compatibility through +// the `ABSL_HAVE_INTRINSIC_INT128` macro.) +// +// The design goal for `int128` is that it will be compatible with a future +// `int128_t`, if that type becomes a part of the standard. +// +// Example: +// +// float y = absl::int128(17); // Error. int128 cannot be implicitly +// // converted to float. +// +// absl::int128 v; +// int64_t i = v; // Error +// int64_t i = static_cast(v); // OK +// +class int128 { + public: + int128() = default; + + // Constructors from arithmetic types + constexpr int128(int v); // NOLINT(runtime/explicit) + constexpr int128(unsigned int v); // NOLINT(runtime/explicit) + constexpr int128(long v); // NOLINT(runtime/int) + constexpr int128(unsigned long v); // NOLINT(runtime/int) + constexpr int128(long long v); // NOLINT(runtime/int) + constexpr int128(unsigned long long v); // NOLINT(runtime/int) +#ifdef ABSL_HAVE_INTRINSIC_INT128 + constexpr int128(__int128 v); // NOLINT(runtime/explicit) + constexpr explicit int128(unsigned __int128 v); +#endif // ABSL_HAVE_INTRINSIC_INT128 + constexpr explicit int128(uint128 v); + explicit int128(float v); + explicit int128(double v); + explicit int128(long double v); + + // Assignment operators from arithmetic types + int128& operator=(int v); + int128& operator=(unsigned int v); + int128& operator=(long v); // NOLINT(runtime/int) + int128& operator=(unsigned long v); // NOLINT(runtime/int) + int128& operator=(long long v); // NOLINT(runtime/int) + int128& operator=(unsigned long long v); // NOLINT(runtime/int) +#ifdef ABSL_HAVE_INTRINSIC_INT128 + int128& operator=(__int128 v); +#endif // ABSL_HAVE_INTRINSIC_INT128 + + // Conversion operators to other arithmetic types + constexpr explicit operator bool() const; + constexpr explicit operator char() const; + constexpr explicit operator signed char() const; + constexpr explicit operator unsigned char() const; + constexpr explicit operator char16_t() const; + constexpr explicit operator char32_t() const; + constexpr explicit operator ABSL_INTERNAL_WCHAR_T() const; + constexpr explicit operator short() const; // NOLINT(runtime/int) + // NOLINTNEXTLINE(runtime/int) + constexpr explicit operator unsigned short() const; + constexpr explicit operator int() const; + constexpr explicit operator unsigned int() const; + constexpr explicit operator long() const; // NOLINT(runtime/int) + // NOLINTNEXTLINE(runtime/int) + constexpr explicit operator unsigned long() const; + // NOLINTNEXTLINE(runtime/int) + constexpr explicit operator long long() const; + // NOLINTNEXTLINE(runtime/int) + constexpr explicit operator unsigned long long() const; +#ifdef ABSL_HAVE_INTRINSIC_INT128 + constexpr explicit operator __int128() const; + constexpr explicit operator unsigned __int128() const; +#endif // ABSL_HAVE_INTRINSIC_INT128 + explicit operator float() const; + explicit operator double() const; + explicit operator long double() const; + + // Trivial copy constructor, assignment operator and destructor. + + // Arithmetic operators + int128& operator+=(int128 other); + int128& operator-=(int128 other); + int128& operator*=(int128 other); + int128& operator/=(int128 other); + int128& operator%=(int128 other); + int128 operator++(int); // postfix increment: i++ + int128 operator--(int); // postfix decrement: i-- + int128& operator++(); // prefix increment: ++i + int128& operator--(); // prefix decrement: --i + int128& operator&=(int128 other); + int128& operator|=(int128 other); + int128& operator^=(int128 other); + int128& operator<<=(int amount); + int128& operator>>=(int amount); + + // Int128Low64() + // + // Returns the lower 64-bit value of a `int128` value. + friend constexpr uint64_t Int128Low64(int128 v); + + // Int128High64() + // + // Returns the higher 64-bit value of a `int128` value. + friend constexpr int64_t Int128High64(int128 v); + + // MakeInt128() + // + // Constructs a `int128` numeric value from two 64-bit integers. Note that + // signedness is conveyed in the upper `high` value. + // + // (absl::int128(1) << 64) * high + low + // + // Note that this factory function is the only way to construct a `int128` + // from integer values greater than 2^64 or less than -2^64. + // + // Example: + // + // absl::int128 big = absl::MakeInt128(1, 0); + // absl::int128 big_n = absl::MakeInt128(-1, 0); + friend constexpr int128 MakeInt128(int64_t high, uint64_t low); + + // Int128Max() + // + // Returns the maximum value for a 128-bit signed integer. + friend constexpr int128 Int128Max(); + + // Int128Min() + // + // Returns the minimum value for a 128-bit signed integer. + friend constexpr int128 Int128Min(); + + // Support for absl::Hash. + template + friend H AbslHashValue(H h, int128 v) { + return H::combine(std::move(h), Int128High64(v), Int128Low64(v)); + } + + private: + constexpr int128(int64_t high, uint64_t low); + +#if defined(ABSL_HAVE_INTRINSIC_INT128) + __int128 v_; +#else // ABSL_HAVE_INTRINSIC_INT128 +#if defined(ABSL_IS_LITTLE_ENDIAN) + uint64_t lo_; + int64_t hi_; +#elif defined(ABSL_IS_BIG_ENDIAN) + int64_t hi_; + uint64_t lo_; +#else // byte order +#error "Unsupported byte order: must be little-endian or big-endian." +#endif // byte order +#endif // ABSL_HAVE_INTRINSIC_INT128 +}; + +std::ostream& operator<<(std::ostream& os, int128 v); + +// TODO(absl-team) add operator>>(std::istream&, int128) + +constexpr int128 Int128Max() { + return int128((std::numeric_limits::max)(), + (std::numeric_limits::max)()); +} + +constexpr int128 Int128Min() { + return int128((std::numeric_limits::min)(), 0); +} + +ABSL_NAMESPACE_END +} // namespace absl + +// Specialized numeric_limits for int128. +namespace std { +template <> +class numeric_limits { + public: + static constexpr bool is_specialized = true; + static constexpr bool is_signed = true; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr float_denorm_style has_denorm = denorm_absent; + static constexpr bool has_denorm_loss = false; + static constexpr float_round_style round_style = round_toward_zero; + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + static constexpr int digits = 127; + static constexpr int digits10 = 38; + static constexpr int max_digits10 = 0; + static constexpr int radix = 2; + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; +#ifdef ABSL_HAVE_INTRINSIC_INT128 + static constexpr bool traps = numeric_limits<__int128>::traps; +#else // ABSL_HAVE_INTRINSIC_INT128 + static constexpr bool traps = numeric_limits::traps; +#endif // ABSL_HAVE_INTRINSIC_INT128 + static constexpr bool tinyness_before = false; + + static constexpr absl::int128 (min)() { return absl::Int128Min(); } + static constexpr absl::int128 lowest() { return absl::Int128Min(); } + static constexpr absl::int128 (max)() { return absl::Int128Max(); } + static constexpr absl::int128 epsilon() { return 0; } + static constexpr absl::int128 round_error() { return 0; } + static constexpr absl::int128 infinity() { return 0; } + static constexpr absl::int128 quiet_NaN() { return 0; } + static constexpr absl::int128 signaling_NaN() { return 0; } + static constexpr absl::int128 denorm_min() { return 0; } +}; +} // namespace std + +// -------------------------------------------------------------------------- +// Implementation details follow +// -------------------------------------------------------------------------- +namespace absl { +ABSL_NAMESPACE_BEGIN + +constexpr uint128 MakeUint128(uint64_t high, uint64_t low) { + return uint128(high, low); +} + +// Assignment from integer types. + +inline uint128& uint128::operator=(int v) { return *this = uint128(v); } + +inline uint128& uint128::operator=(unsigned int v) { + return *this = uint128(v); +} + +inline uint128& uint128::operator=(long v) { // NOLINT(runtime/int) + return *this = uint128(v); +} + +// NOLINTNEXTLINE(runtime/int) +inline uint128& uint128::operator=(unsigned long v) { + return *this = uint128(v); +} + +// NOLINTNEXTLINE(runtime/int) +inline uint128& uint128::operator=(long long v) { + return *this = uint128(v); +} + +// NOLINTNEXTLINE(runtime/int) +inline uint128& uint128::operator=(unsigned long long v) { + return *this = uint128(v); +} + +#ifdef ABSL_HAVE_INTRINSIC_INT128 +inline uint128& uint128::operator=(__int128 v) { + return *this = uint128(v); +} + +inline uint128& uint128::operator=(unsigned __int128 v) { + return *this = uint128(v); +} +#endif // ABSL_HAVE_INTRINSIC_INT128 + +inline uint128& uint128::operator=(int128 v) { + return *this = uint128(v); +} + +// Arithmetic operators. + +uint128 operator<<(uint128 lhs, int amount); +uint128 operator>>(uint128 lhs, int amount); +uint128 operator+(uint128 lhs, uint128 rhs); +uint128 operator-(uint128 lhs, uint128 rhs); +uint128 operator*(uint128 lhs, uint128 rhs); +uint128 operator/(uint128 lhs, uint128 rhs); +uint128 operator%(uint128 lhs, uint128 rhs); + +inline uint128& uint128::operator<<=(int amount) { + *this = *this << amount; + return *this; +} + +inline uint128& uint128::operator>>=(int amount) { + *this = *this >> amount; + return *this; +} + +inline uint128& uint128::operator+=(uint128 other) { + *this = *this + other; + return *this; +} + +inline uint128& uint128::operator-=(uint128 other) { + *this = *this - other; + return *this; +} + +inline uint128& uint128::operator*=(uint128 other) { + *this = *this * other; + return *this; +} + +inline uint128& uint128::operator/=(uint128 other) { + *this = *this / other; + return *this; +} + +inline uint128& uint128::operator%=(uint128 other) { + *this = *this % other; + return *this; +} + +constexpr uint64_t Uint128Low64(uint128 v) { return v.lo_; } + +constexpr uint64_t Uint128High64(uint128 v) { return v.hi_; } + +// Constructors from integer types. + +#if defined(ABSL_IS_LITTLE_ENDIAN) + +constexpr uint128::uint128(uint64_t high, uint64_t low) + : lo_{low}, hi_{high} {} + +constexpr uint128::uint128(int v) + : lo_{static_cast(v)}, + hi_{v < 0 ? (std::numeric_limits::max)() : 0} {} +constexpr uint128::uint128(long v) // NOLINT(runtime/int) + : lo_{static_cast(v)}, + hi_{v < 0 ? (std::numeric_limits::max)() : 0} {} +constexpr uint128::uint128(long long v) // NOLINT(runtime/int) + : lo_{static_cast(v)}, + hi_{v < 0 ? (std::numeric_limits::max)() : 0} {} + +constexpr uint128::uint128(unsigned int v) : lo_{v}, hi_{0} {} +// NOLINTNEXTLINE(runtime/int) +constexpr uint128::uint128(unsigned long v) : lo_{v}, hi_{0} {} +// NOLINTNEXTLINE(runtime/int) +constexpr uint128::uint128(unsigned long long v) : lo_{v}, hi_{0} {} + +#ifdef ABSL_HAVE_INTRINSIC_INT128 +constexpr uint128::uint128(__int128 v) + : lo_{static_cast(v & ~uint64_t{0})}, + hi_{static_cast(static_cast(v) >> 64)} {} +constexpr uint128::uint128(unsigned __int128 v) + : lo_{static_cast(v & ~uint64_t{0})}, + hi_{static_cast(v >> 64)} {} +#endif // ABSL_HAVE_INTRINSIC_INT128 + +constexpr uint128::uint128(int128 v) + : lo_{Int128Low64(v)}, hi_{static_cast(Int128High64(v))} {} + +#elif defined(ABSL_IS_BIG_ENDIAN) + +constexpr uint128::uint128(uint64_t high, uint64_t low) + : hi_{high}, lo_{low} {} + +constexpr uint128::uint128(int v) + : hi_{v < 0 ? (std::numeric_limits::max)() : 0}, + lo_{static_cast(v)} {} +constexpr uint128::uint128(long v) // NOLINT(runtime/int) + : hi_{v < 0 ? (std::numeric_limits::max)() : 0}, + lo_{static_cast(v)} {} +constexpr uint128::uint128(long long v) // NOLINT(runtime/int) + : hi_{v < 0 ? (std::numeric_limits::max)() : 0}, + lo_{static_cast(v)} {} + +constexpr uint128::uint128(unsigned int v) : hi_{0}, lo_{v} {} +// NOLINTNEXTLINE(runtime/int) +constexpr uint128::uint128(unsigned long v) : hi_{0}, lo_{v} {} +// NOLINTNEXTLINE(runtime/int) +constexpr uint128::uint128(unsigned long long v) : hi_{0}, lo_{v} {} + +#ifdef ABSL_HAVE_INTRINSIC_INT128 +constexpr uint128::uint128(__int128 v) + : hi_{static_cast(static_cast(v) >> 64)}, + lo_{static_cast(v & ~uint64_t{0})} {} +constexpr uint128::uint128(unsigned __int128 v) + : hi_{static_cast(v >> 64)}, + lo_{static_cast(v & ~uint64_t{0})} {} +#endif // ABSL_HAVE_INTRINSIC_INT128 + +constexpr uint128::uint128(int128 v) + : hi_{static_cast(Int128High64(v))}, lo_{Int128Low64(v)} {} + +#else // byte order +#error "Unsupported byte order: must be little-endian or big-endian." +#endif // byte order + +// Conversion operators to integer types. + +constexpr uint128::operator bool() const { return lo_ || hi_; } + +constexpr uint128::operator char() const { return static_cast(lo_); } + +constexpr uint128::operator signed char() const { + return static_cast(lo_); +} + +constexpr uint128::operator unsigned char() const { + return static_cast(lo_); +} + +constexpr uint128::operator char16_t() const { + return static_cast(lo_); +} + +constexpr uint128::operator char32_t() const { + return static_cast(lo_); +} + +constexpr uint128::operator ABSL_INTERNAL_WCHAR_T() const { + return static_cast(lo_); +} + +// NOLINTNEXTLINE(runtime/int) +constexpr uint128::operator short() const { return static_cast(lo_); } + +constexpr uint128::operator unsigned short() const { // NOLINT(runtime/int) + return static_cast(lo_); // NOLINT(runtime/int) +} + +constexpr uint128::operator int() const { return static_cast(lo_); } + +constexpr uint128::operator unsigned int() const { + return static_cast(lo_); +} + +// NOLINTNEXTLINE(runtime/int) +constexpr uint128::operator long() const { return static_cast(lo_); } + +constexpr uint128::operator unsigned long() const { // NOLINT(runtime/int) + return static_cast(lo_); // NOLINT(runtime/int) +} + +constexpr uint128::operator long long() const { // NOLINT(runtime/int) + return static_cast(lo_); // NOLINT(runtime/int) +} + +constexpr uint128::operator unsigned long long() const { // NOLINT(runtime/int) + return static_cast(lo_); // NOLINT(runtime/int) +} + +#ifdef ABSL_HAVE_INTRINSIC_INT128 +constexpr uint128::operator __int128() const { + return (static_cast<__int128>(hi_) << 64) + lo_; +} + +constexpr uint128::operator unsigned __int128() const { + return (static_cast(hi_) << 64) + lo_; +} +#endif // ABSL_HAVE_INTRINSIC_INT128 + +// Conversion operators to floating point types. + +inline uint128::operator float() const { + return static_cast(lo_) + std::ldexp(static_cast(hi_), 64); +} + +inline uint128::operator double() const { + return static_cast(lo_) + std::ldexp(static_cast(hi_), 64); +} + +inline uint128::operator long double() const { + return static_cast(lo_) + + std::ldexp(static_cast(hi_), 64); +} + +// Comparison operators. + +inline bool operator==(uint128 lhs, uint128 rhs) { +#if defined(ABSL_HAVE_INTRINSIC_INT128) + return static_cast(lhs) == + static_cast(rhs); +#else + return (Uint128Low64(lhs) == Uint128Low64(rhs) && + Uint128High64(lhs) == Uint128High64(rhs)); +#endif +} + +inline bool operator!=(uint128 lhs, uint128 rhs) { + return !(lhs == rhs); +} + +inline bool operator<(uint128 lhs, uint128 rhs) { +#ifdef ABSL_HAVE_INTRINSIC_INT128 + return static_cast(lhs) < + static_cast(rhs); +#else + return (Uint128High64(lhs) == Uint128High64(rhs)) + ? (Uint128Low64(lhs) < Uint128Low64(rhs)) + : (Uint128High64(lhs) < Uint128High64(rhs)); +#endif +} + +inline bool operator>(uint128 lhs, uint128 rhs) { return rhs < lhs; } + +inline bool operator<=(uint128 lhs, uint128 rhs) { return !(rhs < lhs); } + +inline bool operator>=(uint128 lhs, uint128 rhs) { return !(lhs < rhs); } + +// Unary operators. + +constexpr inline uint128 operator+(uint128 val) { + return val; +} + +constexpr inline int128 operator+(int128 val) { + return val; +} + +inline uint128 operator-(uint128 val) { +#if defined(ABSL_HAVE_INTRINSIC_INT128) + return -static_cast(val); +#else + uint64_t hi = ~Uint128High64(val); + uint64_t lo = ~Uint128Low64(val) + 1; + if (lo == 0) ++hi; // carry + return MakeUint128(hi, lo); +#endif +} + +constexpr inline bool operator!(uint128 val) { +#if defined(ABSL_HAVE_INTRINSIC_INT128) + return !static_cast(val); +#else + return !Uint128High64(val) && !Uint128Low64(val); +#endif +} + +// Logical operators. + +constexpr inline uint128 operator~(uint128 val) { +#if defined(ABSL_HAVE_INTRINSIC_INT128) + return ~static_cast(val); +#else + return MakeUint128(~Uint128High64(val), ~Uint128Low64(val)); +#endif +} + +constexpr inline uint128 operator|(uint128 lhs, uint128 rhs) { +#if defined(ABSL_HAVE_INTRINSIC_INT128) + return static_cast(lhs) | + static_cast(rhs); +#else + return MakeUint128(Uint128High64(lhs) | Uint128High64(rhs), + Uint128Low64(lhs) | Uint128Low64(rhs)); +#endif +} + +constexpr inline uint128 operator&(uint128 lhs, uint128 rhs) { +#if defined(ABSL_HAVE_INTRINSIC_INT128) + return static_cast(lhs) & + static_cast(rhs); +#else + return MakeUint128(Uint128High64(lhs) & Uint128High64(rhs), + Uint128Low64(lhs) & Uint128Low64(rhs)); +#endif +} + +constexpr inline uint128 operator^(uint128 lhs, uint128 rhs) { +#if defined(ABSL_HAVE_INTRINSIC_INT128) + return static_cast(lhs) ^ + static_cast(rhs); +#else + return MakeUint128(Uint128High64(lhs) ^ Uint128High64(rhs), + Uint128Low64(lhs) ^ Uint128Low64(rhs)); +#endif +} + +inline uint128& uint128::operator|=(uint128 other) { + *this = *this | other; + return *this; +} + +inline uint128& uint128::operator&=(uint128 other) { + *this = *this & other; + return *this; +} + +inline uint128& uint128::operator^=(uint128 other) { + *this = *this ^ other; + return *this; +} + +// Arithmetic operators. + +inline uint128 operator<<(uint128 lhs, int amount) { +#ifdef ABSL_HAVE_INTRINSIC_INT128 + return static_cast(lhs) << amount; +#else + // uint64_t shifts of >= 64 are undefined, so we will need some + // special-casing. + if (amount < 64) { + if (amount != 0) { + return MakeUint128( + (Uint128High64(lhs) << amount) | (Uint128Low64(lhs) >> (64 - amount)), + Uint128Low64(lhs) << amount); + } + return lhs; + } + return MakeUint128(Uint128Low64(lhs) << (amount - 64), 0); +#endif +} + +inline uint128 operator>>(uint128 lhs, int amount) { +#ifdef ABSL_HAVE_INTRINSIC_INT128 + return static_cast(lhs) >> amount; +#else + // uint64_t shifts of >= 64 are undefined, so we will need some + // special-casing. + if (amount < 64) { + if (amount != 0) { + return MakeUint128(Uint128High64(lhs) >> amount, + (Uint128Low64(lhs) >> amount) | + (Uint128High64(lhs) << (64 - amount))); + } + return lhs; + } + return MakeUint128(0, Uint128High64(lhs) >> (amount - 64)); +#endif +} + +inline uint128 operator+(uint128 lhs, uint128 rhs) { +#if defined(ABSL_HAVE_INTRINSIC_INT128) + return static_cast(lhs) + + static_cast(rhs); +#else + uint128 result = MakeUint128(Uint128High64(lhs) + Uint128High64(rhs), + Uint128Low64(lhs) + Uint128Low64(rhs)); + if (Uint128Low64(result) < Uint128Low64(lhs)) { // check for carry + return MakeUint128(Uint128High64(result) + 1, Uint128Low64(result)); + } + return result; +#endif +} + +inline uint128 operator-(uint128 lhs, uint128 rhs) { +#if defined(ABSL_HAVE_INTRINSIC_INT128) + return static_cast(lhs) - + static_cast(rhs); +#else + uint128 result = MakeUint128(Uint128High64(lhs) - Uint128High64(rhs), + Uint128Low64(lhs) - Uint128Low64(rhs)); + if (Uint128Low64(lhs) < Uint128Low64(rhs)) { // check for carry + return MakeUint128(Uint128High64(result) - 1, Uint128Low64(result)); + } + return result; +#endif +} + +inline uint128 operator*(uint128 lhs, uint128 rhs) { +#if defined(ABSL_HAVE_INTRINSIC_INT128) + // TODO(strel) Remove once alignment issues are resolved and unsigned __int128 + // can be used for uint128 storage. + return static_cast(lhs) * + static_cast(rhs); +#elif defined(_MSC_VER) && defined(_M_X64) + uint64_t carry; + uint64_t low = _umul128(Uint128Low64(lhs), Uint128Low64(rhs), &carry); + return MakeUint128(Uint128Low64(lhs) * Uint128High64(rhs) + + Uint128High64(lhs) * Uint128Low64(rhs) + carry, + low); +#else // ABSL_HAVE_INTRINSIC128 + uint64_t a32 = Uint128Low64(lhs) >> 32; + uint64_t a00 = Uint128Low64(lhs) & 0xffffffff; + uint64_t b32 = Uint128Low64(rhs) >> 32; + uint64_t b00 = Uint128Low64(rhs) & 0xffffffff; + uint128 result = + MakeUint128(Uint128High64(lhs) * Uint128Low64(rhs) + + Uint128Low64(lhs) * Uint128High64(rhs) + a32 * b32, + a00 * b00); + result += uint128(a32 * b00) << 32; + result += uint128(a00 * b32) << 32; + return result; +#endif // ABSL_HAVE_INTRINSIC128 +} + +#if defined(ABSL_HAVE_INTRINSIC_INT128) +inline uint128 operator/(uint128 lhs, uint128 rhs) { + return static_cast(lhs) / + static_cast(rhs); +} + +inline uint128 operator%(uint128 lhs, uint128 rhs) { + return static_cast(lhs) % + static_cast(rhs); +} +#endif + +// Increment/decrement operators. + +inline uint128 uint128::operator++(int) { + uint128 tmp(*this); + *this += 1; + return tmp; +} + +inline uint128 uint128::operator--(int) { + uint128 tmp(*this); + *this -= 1; + return tmp; +} + +inline uint128& uint128::operator++() { + *this += 1; + return *this; +} + +inline uint128& uint128::operator--() { + *this -= 1; + return *this; +} + +constexpr int128 MakeInt128(int64_t high, uint64_t low) { + return int128(high, low); +} + +// Assignment from integer types. +inline int128& int128::operator=(int v) { + return *this = int128(v); +} + +inline int128& int128::operator=(unsigned int v) { + return *this = int128(v); +} + +inline int128& int128::operator=(long v) { // NOLINT(runtime/int) + return *this = int128(v); +} + +// NOLINTNEXTLINE(runtime/int) +inline int128& int128::operator=(unsigned long v) { + return *this = int128(v); +} + +// NOLINTNEXTLINE(runtime/int) +inline int128& int128::operator=(long long v) { + return *this = int128(v); +} + +// NOLINTNEXTLINE(runtime/int) +inline int128& int128::operator=(unsigned long long v) { + return *this = int128(v); +} + +// Arithmetic operators. + +int128 operator+(int128 lhs, int128 rhs); +int128 operator-(int128 lhs, int128 rhs); +int128 operator*(int128 lhs, int128 rhs); +int128 operator/(int128 lhs, int128 rhs); +int128 operator%(int128 lhs, int128 rhs); +int128 operator|(int128 lhs, int128 rhs); +int128 operator&(int128 lhs, int128 rhs); +int128 operator^(int128 lhs, int128 rhs); +int128 operator<<(int128 lhs, int amount); +int128 operator>>(int128 lhs, int amount); + +inline int128& int128::operator+=(int128 other) { + *this = *this + other; + return *this; +} + +inline int128& int128::operator-=(int128 other) { + *this = *this - other; + return *this; +} + +inline int128& int128::operator*=(int128 other) { + *this = *this * other; + return *this; +} + +inline int128& int128::operator/=(int128 other) { + *this = *this / other; + return *this; +} + +inline int128& int128::operator%=(int128 other) { + *this = *this % other; + return *this; +} + +inline int128& int128::operator|=(int128 other) { + *this = *this | other; + return *this; +} + +inline int128& int128::operator&=(int128 other) { + *this = *this & other; + return *this; +} + +inline int128& int128::operator^=(int128 other) { + *this = *this ^ other; + return *this; +} + +inline int128& int128::operator<<=(int amount) { + *this = *this << amount; + return *this; +} + +inline int128& int128::operator>>=(int amount) { + *this = *this >> amount; + return *this; +} + +namespace int128_internal { + +// Casts from unsigned to signed while preserving the underlying binary +// representation. +constexpr int64_t BitCastToSigned(uint64_t v) { + // Casting an unsigned integer to a signed integer of the same + // width is implementation defined behavior if the source value would not fit + // in the destination type. We step around it with a roundtrip bitwise not + // operation to make sure this function remains constexpr. Clang, GCC, and + // MSVC optimize this to a no-op on x86-64. + return v & (uint64_t{1} << 63) ? ~static_cast(~v) + : static_cast(v); +} + +} // namespace int128_internal + +#if defined(ABSL_HAVE_INTRINSIC_INT128) +#include "absl/numeric/int128_have_intrinsic.inc" // IWYU pragma: export +#else // ABSL_HAVE_INTRINSIC_INT128 +#include "absl/numeric/int128_no_intrinsic.inc" // IWYU pragma: export +#endif // ABSL_HAVE_INTRINSIC_INT128 + +ABSL_NAMESPACE_END +} // namespace absl + +#undef ABSL_INTERNAL_WCHAR_T + +#endif // ABSL_NUMERIC_INT128_H_ diff --git a/extern/int128/absl/numeric/int128_have_intrinsic.inc b/extern/int128/absl/numeric/int128_have_intrinsic.inc new file mode 100644 index 0000000000..d6c76dd320 --- /dev/null +++ b/extern/int128/absl/numeric/int128_have_intrinsic.inc @@ -0,0 +1,302 @@ +// +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This file contains :int128 implementation details that depend on internal +// representation when ABSL_HAVE_INTRINSIC_INT128 is defined. This file is +// included by int128.h and relies on ABSL_INTERNAL_WCHAR_T being defined. + +namespace int128_internal { + +// Casts from unsigned to signed while preserving the underlying binary +// representation. +constexpr __int128 BitCastToSigned(unsigned __int128 v) { + // Casting an unsigned integer to a signed integer of the same + // width is implementation defined behavior if the source value would not fit + // in the destination type. We step around it with a roundtrip bitwise not + // operation to make sure this function remains constexpr. Clang and GCC + // optimize this to a no-op on x86-64. + return v & (static_cast(1) << 127) + ? ~static_cast<__int128>(~v) + : static_cast<__int128>(v); +} + +} // namespace int128_internal + +inline int128& int128::operator=(__int128 v) { + v_ = v; + return *this; +} + +constexpr uint64_t Int128Low64(int128 v) { + return static_cast(v.v_ & ~uint64_t{0}); +} + +constexpr int64_t Int128High64(int128 v) { + // Initially cast to unsigned to prevent a right shift on a negative value. + return int128_internal::BitCastToSigned( + static_cast(static_cast(v.v_) >> 64)); +} + +constexpr int128::int128(int64_t high, uint64_t low) + // Initially cast to unsigned to prevent a left shift that overflows. + : v_(int128_internal::BitCastToSigned(static_cast(high) + << 64) | + low) {} + + +constexpr int128::int128(int v) : v_{v} {} + +constexpr int128::int128(long v) : v_{v} {} // NOLINT(runtime/int) + +constexpr int128::int128(long long v) : v_{v} {} // NOLINT(runtime/int) + +constexpr int128::int128(__int128 v) : v_{v} {} + +constexpr int128::int128(unsigned int v) : v_{v} {} + +constexpr int128::int128(unsigned long v) : v_{v} {} // NOLINT(runtime/int) + +// NOLINTNEXTLINE(runtime/int) +constexpr int128::int128(unsigned long long v) : v_{v} {} + +constexpr int128::int128(unsigned __int128 v) : v_{static_cast<__int128>(v)} {} + +inline int128::int128(float v) { + v_ = static_cast<__int128>(v); +} + +inline int128::int128(double v) { + v_ = static_cast<__int128>(v); +} + +inline int128::int128(long double v) { + v_ = static_cast<__int128>(v); +} + +constexpr int128::int128(uint128 v) : v_{static_cast<__int128>(v)} {} + +constexpr int128::operator bool() const { return static_cast(v_); } + +constexpr int128::operator char() const { return static_cast(v_); } + +constexpr int128::operator signed char() const { + return static_cast(v_); +} + +constexpr int128::operator unsigned char() const { + return static_cast(v_); +} + +constexpr int128::operator char16_t() const { + return static_cast(v_); +} + +constexpr int128::operator char32_t() const { + return static_cast(v_); +} + +constexpr int128::operator ABSL_INTERNAL_WCHAR_T() const { + return static_cast(v_); +} + +constexpr int128::operator short() const { // NOLINT(runtime/int) + return static_cast(v_); // NOLINT(runtime/int) +} + +constexpr int128::operator unsigned short() const { // NOLINT(runtime/int) + return static_cast(v_); // NOLINT(runtime/int) +} + +constexpr int128::operator int() const { + return static_cast(v_); +} + +constexpr int128::operator unsigned int() const { + return static_cast(v_); +} + +constexpr int128::operator long() const { // NOLINT(runtime/int) + return static_cast(v_); // NOLINT(runtime/int) +} + +constexpr int128::operator unsigned long() const { // NOLINT(runtime/int) + return static_cast(v_); // NOLINT(runtime/int) +} + +constexpr int128::operator long long() const { // NOLINT(runtime/int) + return static_cast(v_); // NOLINT(runtime/int) +} + +constexpr int128::operator unsigned long long() const { // NOLINT(runtime/int) + return static_cast(v_); // NOLINT(runtime/int) +} + +constexpr int128::operator __int128() const { return v_; } + +constexpr int128::operator unsigned __int128() const { + return static_cast(v_); +} + +// Clang on PowerPC sometimes produces incorrect __int128 to floating point +// conversions. In that case, we do the conversion with a similar implementation +// to the conversion operators in int128_no_intrinsic.inc. +#if defined(__clang__) && !defined(__ppc64__) +inline int128::operator float() const { return static_cast(v_); } + +inline int128::operator double () const { return static_cast(v_); } + +inline int128::operator long double() const { + return static_cast(v_); +} + +#else // Clang on PowerPC +// Forward declaration for conversion operators to floating point types. +int128 operator-(int128 v); +bool operator!=(int128 lhs, int128 rhs); + +inline int128::operator float() const { + // We must convert the absolute value and then negate as needed, because + // floating point types are typically sign-magnitude. Otherwise, the + // difference between the high and low 64 bits when interpreted as two's + // complement overwhelms the precision of the mantissa. + // + // Also check to make sure we don't negate Int128Min() + return v_ < 0 && *this != Int128Min() + ? -static_cast(-*this) + : static_cast(Int128Low64(*this)) + + std::ldexp(static_cast(Int128High64(*this)), 64); +} + +inline int128::operator double() const { + // See comment in int128::operator float() above. + return v_ < 0 && *this != Int128Min() + ? -static_cast(-*this) + : static_cast(Int128Low64(*this)) + + std::ldexp(static_cast(Int128High64(*this)), 64); +} + +inline int128::operator long double() const { + // See comment in int128::operator float() above. + return v_ < 0 && *this != Int128Min() + ? -static_cast(-*this) + : static_cast(Int128Low64(*this)) + + std::ldexp(static_cast(Int128High64(*this)), + 64); +} +#endif // Clang on PowerPC + +// Comparison operators. + +inline bool operator==(int128 lhs, int128 rhs) { + return static_cast<__int128>(lhs) == static_cast<__int128>(rhs); +} + +inline bool operator!=(int128 lhs, int128 rhs) { + return static_cast<__int128>(lhs) != static_cast<__int128>(rhs); +} + +inline bool operator<(int128 lhs, int128 rhs) { + return static_cast<__int128>(lhs) < static_cast<__int128>(rhs); +} + +inline bool operator>(int128 lhs, int128 rhs) { + return static_cast<__int128>(lhs) > static_cast<__int128>(rhs); +} + +inline bool operator<=(int128 lhs, int128 rhs) { + return static_cast<__int128>(lhs) <= static_cast<__int128>(rhs); +} + +inline bool operator>=(int128 lhs, int128 rhs) { + return static_cast<__int128>(lhs) >= static_cast<__int128>(rhs); +} + +// Unary operators. + +inline int128 operator-(int128 v) { + return -static_cast<__int128>(v); +} + +inline bool operator!(int128 v) { + return !static_cast<__int128>(v); +} + +inline int128 operator~(int128 val) { + return ~static_cast<__int128>(val); +} + +// Arithmetic operators. + +inline int128 operator+(int128 lhs, int128 rhs) { + return static_cast<__int128>(lhs) + static_cast<__int128>(rhs); +} + +inline int128 operator-(int128 lhs, int128 rhs) { + return static_cast<__int128>(lhs) - static_cast<__int128>(rhs); +} + +inline int128 operator*(int128 lhs, int128 rhs) { + return static_cast<__int128>(lhs) * static_cast<__int128>(rhs); +} + +inline int128 operator/(int128 lhs, int128 rhs) { + return static_cast<__int128>(lhs) / static_cast<__int128>(rhs); +} + +inline int128 operator%(int128 lhs, int128 rhs) { + return static_cast<__int128>(lhs) % static_cast<__int128>(rhs); +} + +inline int128 int128::operator++(int) { + int128 tmp(*this); + ++v_; + return tmp; +} + +inline int128 int128::operator--(int) { + int128 tmp(*this); + --v_; + return tmp; +} + +inline int128& int128::operator++() { + ++v_; + return *this; +} + +inline int128& int128::operator--() { + --v_; + return *this; +} + +inline int128 operator|(int128 lhs, int128 rhs) { + return static_cast<__int128>(lhs) | static_cast<__int128>(rhs); +} + +inline int128 operator&(int128 lhs, int128 rhs) { + return static_cast<__int128>(lhs) & static_cast<__int128>(rhs); +} + +inline int128 operator^(int128 lhs, int128 rhs) { + return static_cast<__int128>(lhs) ^ static_cast<__int128>(rhs); +} + +inline int128 operator<<(int128 lhs, int amount) { + return static_cast<__int128>(lhs) << amount; +} + +inline int128 operator>>(int128 lhs, int amount) { + return static_cast<__int128>(lhs) >> amount; +} diff --git a/extern/int128/absl/numeric/int128_no_intrinsic.inc b/extern/int128/absl/numeric/int128_no_intrinsic.inc new file mode 100644 index 0000000000..c753771ae7 --- /dev/null +++ b/extern/int128/absl/numeric/int128_no_intrinsic.inc @@ -0,0 +1,308 @@ +// +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This file contains :int128 implementation details that depend on internal +// representation when ABSL_HAVE_INTRINSIC_INT128 is *not* defined. This file +// is included by int128.h and relies on ABSL_INTERNAL_WCHAR_T being defined. + +constexpr uint64_t Int128Low64(int128 v) { return v.lo_; } + +constexpr int64_t Int128High64(int128 v) { return v.hi_; } + +#if defined(ABSL_IS_LITTLE_ENDIAN) + +constexpr int128::int128(int64_t high, uint64_t low) : + lo_(low), hi_(high) {} + +constexpr int128::int128(int v) + : lo_{static_cast(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {} +constexpr int128::int128(long v) // NOLINT(runtime/int) + : lo_{static_cast(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {} +constexpr int128::int128(long long v) // NOLINT(runtime/int) + : lo_{static_cast(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {} + +constexpr int128::int128(unsigned int v) : lo_{v}, hi_{0} {} +// NOLINTNEXTLINE(runtime/int) +constexpr int128::int128(unsigned long v) : lo_{v}, hi_{0} {} +// NOLINTNEXTLINE(runtime/int) +constexpr int128::int128(unsigned long long v) : lo_{v}, hi_{0} {} + +constexpr int128::int128(uint128 v) + : lo_{Uint128Low64(v)}, hi_{static_cast(Uint128High64(v))} {} + +#elif defined(ABSL_IS_BIG_ENDIAN) + +constexpr int128::int128(int64_t high, uint64_t low) : + hi_{high}, lo_{low} {} + +constexpr int128::int128(int v) + : hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast(v)} {} +constexpr int128::int128(long v) // NOLINT(runtime/int) + : hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast(v)} {} +constexpr int128::int128(long long v) // NOLINT(runtime/int) + : hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast(v)} {} + +constexpr int128::int128(unsigned int v) : hi_{0}, lo_{v} {} +// NOLINTNEXTLINE(runtime/int) +constexpr int128::int128(unsigned long v) : hi_{0}, lo_{v} {} +// NOLINTNEXTLINE(runtime/int) +constexpr int128::int128(unsigned long long v) : hi_{0}, lo_{v} {} + +constexpr int128::int128(uint128 v) + : hi_{static_cast(Uint128High64(v))}, lo_{Uint128Low64(v)} {} + +#else // byte order +#error "Unsupported byte order: must be little-endian or big-endian." +#endif // byte order + +constexpr int128::operator bool() const { return lo_ || hi_; } + +constexpr int128::operator char() const { + // NOLINTNEXTLINE(runtime/int) + return static_cast(static_cast(*this)); +} + +constexpr int128::operator signed char() const { + // NOLINTNEXTLINE(runtime/int) + return static_cast(static_cast(*this)); +} + +constexpr int128::operator unsigned char() const { + return static_cast(lo_); +} + +constexpr int128::operator char16_t() const { + return static_cast(lo_); +} + +constexpr int128::operator char32_t() const { + return static_cast(lo_); +} + +constexpr int128::operator ABSL_INTERNAL_WCHAR_T() const { + // NOLINTNEXTLINE(runtime/int) + return static_cast(static_cast(*this)); +} + +constexpr int128::operator short() const { // NOLINT(runtime/int) + // NOLINTNEXTLINE(runtime/int) + return static_cast(static_cast(*this)); +} + +constexpr int128::operator unsigned short() const { // NOLINT(runtime/int) + return static_cast(lo_); // NOLINT(runtime/int) +} + +constexpr int128::operator int() const { + // NOLINTNEXTLINE(runtime/int) + return static_cast(static_cast(*this)); +} + +constexpr int128::operator unsigned int() const { + return static_cast(lo_); +} + +constexpr int128::operator long() const { // NOLINT(runtime/int) + // NOLINTNEXTLINE(runtime/int) + return static_cast(static_cast(*this)); +} + +constexpr int128::operator unsigned long() const { // NOLINT(runtime/int) + return static_cast(lo_); // NOLINT(runtime/int) +} + +constexpr int128::operator long long() const { // NOLINT(runtime/int) + // We don't bother checking the value of hi_. If *this < 0, lo_'s high bit + // must be set in order for the value to fit into a long long. Conversely, if + // lo_'s high bit is set, *this must be < 0 for the value to fit. + return int128_internal::BitCastToSigned(lo_); +} + +constexpr int128::operator unsigned long long() const { // NOLINT(runtime/int) + return static_cast(lo_); // NOLINT(runtime/int) +} + +// Forward declaration for conversion operators to floating point types. +int128 operator-(int128 v); +bool operator!=(int128 lhs, int128 rhs); + +inline int128::operator float() const { + // We must convert the absolute value and then negate as needed, because + // floating point types are typically sign-magnitude. Otherwise, the + // difference between the high and low 64 bits when interpreted as two's + // complement overwhelms the precision of the mantissa. + // + // Also check to make sure we don't negate Int128Min() + return hi_ < 0 && *this != Int128Min() + ? -static_cast(-*this) + : static_cast(lo_) + + std::ldexp(static_cast(hi_), 64); +} + +inline int128::operator double() const { + // See comment in int128::operator float() above. + return hi_ < 0 && *this != Int128Min() + ? -static_cast(-*this) + : static_cast(lo_) + + std::ldexp(static_cast(hi_), 64); +} + +inline int128::operator long double() const { + // See comment in int128::operator float() above. + return hi_ < 0 && *this != Int128Min() + ? -static_cast(-*this) + : static_cast(lo_) + + std::ldexp(static_cast(hi_), 64); +} + +// Comparison operators. + +inline bool operator==(int128 lhs, int128 rhs) { + return (Int128Low64(lhs) == Int128Low64(rhs) && + Int128High64(lhs) == Int128High64(rhs)); +} + +inline bool operator!=(int128 lhs, int128 rhs) { + return !(lhs == rhs); +} + +inline bool operator<(int128 lhs, int128 rhs) { + return (Int128High64(lhs) == Int128High64(rhs)) + ? (Int128Low64(lhs) < Int128Low64(rhs)) + : (Int128High64(lhs) < Int128High64(rhs)); +} + +inline bool operator>(int128 lhs, int128 rhs) { + return (Int128High64(lhs) == Int128High64(rhs)) + ? (Int128Low64(lhs) > Int128Low64(rhs)) + : (Int128High64(lhs) > Int128High64(rhs)); +} + +inline bool operator<=(int128 lhs, int128 rhs) { + return !(lhs > rhs); +} + +inline bool operator>=(int128 lhs, int128 rhs) { + return !(lhs < rhs); +} + +// Unary operators. + +inline int128 operator-(int128 v) { + int64_t hi = ~Int128High64(v); + uint64_t lo = ~Int128Low64(v) + 1; + if (lo == 0) ++hi; // carry + return MakeInt128(hi, lo); +} + +inline bool operator!(int128 v) { + return !Int128Low64(v) && !Int128High64(v); +} + +inline int128 operator~(int128 val) { + return MakeInt128(~Int128High64(val), ~Int128Low64(val)); +} + +// Arithmetic operators. + +inline int128 operator+(int128 lhs, int128 rhs) { + int128 result = MakeInt128(Int128High64(lhs) + Int128High64(rhs), + Int128Low64(lhs) + Int128Low64(rhs)); + if (Int128Low64(result) < Int128Low64(lhs)) { // check for carry + return MakeInt128(Int128High64(result) + 1, Int128Low64(result)); + } + return result; +} + +inline int128 operator-(int128 lhs, int128 rhs) { + int128 result = MakeInt128(Int128High64(lhs) - Int128High64(rhs), + Int128Low64(lhs) - Int128Low64(rhs)); + if (Int128Low64(lhs) < Int128Low64(rhs)) { // check for carry + return MakeInt128(Int128High64(result) - 1, Int128Low64(result)); + } + return result; +} + +inline int128 operator*(int128 lhs, int128 rhs) { + uint128 result = uint128(lhs) * rhs; + return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(result)), + Uint128Low64(result)); +} + +inline int128 int128::operator++(int) { + int128 tmp(*this); + *this += 1; + return tmp; +} + +inline int128 int128::operator--(int) { + int128 tmp(*this); + *this -= 1; + return tmp; +} + +inline int128& int128::operator++() { + *this += 1; + return *this; +} + +inline int128& int128::operator--() { + *this -= 1; + return *this; +} + +inline int128 operator|(int128 lhs, int128 rhs) { + return MakeInt128(Int128High64(lhs) | Int128High64(rhs), + Int128Low64(lhs) | Int128Low64(rhs)); +} + +inline int128 operator&(int128 lhs, int128 rhs) { + return MakeInt128(Int128High64(lhs) & Int128High64(rhs), + Int128Low64(lhs) & Int128Low64(rhs)); +} + +inline int128 operator^(int128 lhs, int128 rhs) { + return MakeInt128(Int128High64(lhs) ^ Int128High64(rhs), + Int128Low64(lhs) ^ Int128Low64(rhs)); +} + +inline int128 operator<<(int128 lhs, int amount) { + // uint64_t shifts of >= 64 are undefined, so we need some special-casing. + if (amount < 64) { + if (amount != 0) { + return MakeInt128( + (Int128High64(lhs) << amount) | + static_cast(Int128Low64(lhs) >> (64 - amount)), + Int128Low64(lhs) << amount); + } + return lhs; + } + return MakeInt128(static_cast(Int128Low64(lhs) << (amount - 64)), 0); +} + +inline int128 operator>>(int128 lhs, int amount) { + // uint64_t shifts of >= 64 are undefined, so we need some special-casing. + if (amount < 64) { + if (amount != 0) { + return MakeInt128( + Int128High64(lhs) >> amount, + (Int128Low64(lhs) >> amount) | + (static_cast(Int128High64(lhs)) << (64 - amount))); + } + return lhs; + } + return MakeInt128(0, + static_cast(Int128High64(lhs) >> (amount - 64))); +} diff --git a/extern/int128/absl/numeric/internal/bits.h b/extern/int128/absl/numeric/internal/bits.h new file mode 100644 index 0000000000..bfef06bce1 --- /dev/null +++ b/extern/int128/absl/numeric/internal/bits.h @@ -0,0 +1,358 @@ +// Copyright 2020 The Abseil Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ABSL_NUMERIC_INTERNAL_BITS_H_ +#define ABSL_NUMERIC_INTERNAL_BITS_H_ + +#include +#include +#include + +// Clang on Windows has __builtin_clzll; otherwise we need to use the +// windows intrinsic functions. +#if defined(_MSC_VER) && !defined(__clang__) +#include +#endif + +#include "absl/base/attributes.h" +#include "absl/base/config.h" + +#if defined(__GNUC__) && !defined(__clang__) +// GCC +#define ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(x) 1 +#else +#define ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(x) ABSL_HAVE_BUILTIN(x) +#endif + +#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcountl) && \ + ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcountll) +#define ABSL_INTERNAL_CONSTEXPR_POPCOUNT constexpr +#define ABSL_INTERNAL_HAS_CONSTEXPR_POPCOUNT 1 +#else +#define ABSL_INTERNAL_CONSTEXPR_POPCOUNT +#define ABSL_INTERNAL_HAS_CONSTEXPR_POPCOUNT 0 +#endif + +#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clz) && \ + ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clzll) +#define ABSL_INTERNAL_CONSTEXPR_CLZ constexpr +#define ABSL_INTERNAL_HAS_CONSTEXPR_CLZ 1 +#else +#define ABSL_INTERNAL_CONSTEXPR_CLZ +#define ABSL_INTERNAL_HAS_CONSTEXPR_CLZ 0 +#endif + +#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctz) && \ + ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctzll) +#define ABSL_INTERNAL_CONSTEXPR_CTZ constexpr +#define ABSL_INTERNAL_HAS_CONSTEXPR_CTZ 1 +#else +#define ABSL_INTERNAL_CONSTEXPR_CTZ +#define ABSL_INTERNAL_HAS_CONSTEXPR_CTZ 0 +#endif + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace numeric_internal { + +constexpr bool IsPowerOf2(unsigned int x) noexcept { + return x != 0 && (x & (x - 1)) == 0; +} + +template +ABSL_MUST_USE_RESULT ABSL_ATTRIBUTE_ALWAYS_INLINE constexpr T RotateRight( + T x, int s) noexcept { + static_assert(std::is_unsigned::value, "T must be unsigned"); + static_assert(IsPowerOf2(std::numeric_limits::digits), + "T must have a power-of-2 size"); + + return static_cast(x >> (s & (std::numeric_limits::digits - 1))) | + static_cast(x << ((-s) & (std::numeric_limits::digits - 1))); +} + +template +ABSL_MUST_USE_RESULT ABSL_ATTRIBUTE_ALWAYS_INLINE constexpr T RotateLeft( + T x, int s) noexcept { + static_assert(std::is_unsigned::value, "T must be unsigned"); + static_assert(IsPowerOf2(std::numeric_limits::digits), + "T must have a power-of-2 size"); + + return static_cast(x << (s & (std::numeric_limits::digits - 1))) | + static_cast(x >> ((-s) & (std::numeric_limits::digits - 1))); +} + +ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline int +Popcount32(uint32_t x) noexcept { +#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcount) + static_assert(sizeof(unsigned int) == sizeof(x), + "__builtin_popcount does not take 32-bit arg"); + return __builtin_popcount(x); +#else + x -= ((x >> 1) & 0x55555555); + x = ((x >> 2) & 0x33333333) + (x & 0x33333333); + return static_cast((((x + (x >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24); +#endif +} + +ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline int +Popcount64(uint64_t x) noexcept { +#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcountll) + static_assert(sizeof(unsigned long long) == sizeof(x), // NOLINT(runtime/int) + "__builtin_popcount does not take 64-bit arg"); + return __builtin_popcountll(x); +#else + x -= (x >> 1) & 0x5555555555555555ULL; + x = ((x >> 2) & 0x3333333333333333ULL) + (x & 0x3333333333333333ULL); + return static_cast( + (((x + (x >> 4)) & 0xF0F0F0F0F0F0F0FULL) * 0x101010101010101ULL) >> 56); +#endif +} + +template +ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline int +Popcount(T x) noexcept { + static_assert(std::is_unsigned::value, "T must be unsigned"); + static_assert(IsPowerOf2(std::numeric_limits::digits), + "T must have a power-of-2 size"); + static_assert(sizeof(x) <= sizeof(uint64_t), "T is too large"); + return sizeof(x) <= sizeof(uint32_t) ? Popcount32(x) : Popcount64(x); +} + +ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int +CountLeadingZeroes32(uint32_t x) { +#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clz) + // Use __builtin_clz, which uses the following instructions: + // x86: bsr, lzcnt + // ARM64: clz + // PPC: cntlzd + + static_assert(sizeof(unsigned int) == sizeof(x), + "__builtin_clz does not take 32-bit arg"); + // Handle 0 as a special case because __builtin_clz(0) is undefined. + return x == 0 ? 32 : __builtin_clz(x); +#elif defined(_MSC_VER) && !defined(__clang__) + unsigned long result = 0; // NOLINT(runtime/int) + if (_BitScanReverse(&result, x)) { + return 31 - result; + } + return 32; +#else + int zeroes = 28; + if (x >> 16) { + zeroes -= 16; + x >>= 16; + } + if (x >> 8) { + zeroes -= 8; + x >>= 8; + } + if (x >> 4) { + zeroes -= 4; + x >>= 4; + } + return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[x] + zeroes; +#endif +} + +ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int +CountLeadingZeroes16(uint16_t x) { +#if ABSL_HAVE_BUILTIN(__builtin_clzs) + static_assert(sizeof(unsigned short) == sizeof(x), // NOLINT(runtime/int) + "__builtin_clzs does not take 16-bit arg"); + return x == 0 ? 16 : __builtin_clzs(x); +#else + return CountLeadingZeroes32(x) - 16; +#endif +} + +ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int +CountLeadingZeroes64(uint64_t x) { +#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clzll) + // Use __builtin_clzll, which uses the following instructions: + // x86: bsr, lzcnt + // ARM64: clz + // PPC: cntlzd + static_assert(sizeof(unsigned long long) == sizeof(x), // NOLINT(runtime/int) + "__builtin_clzll does not take 64-bit arg"); + + // Handle 0 as a special case because __builtin_clzll(0) is undefined. + return x == 0 ? 64 : __builtin_clzll(x); +#elif defined(_MSC_VER) && !defined(__clang__) && \ + (defined(_M_X64) || defined(_M_ARM64)) + // MSVC does not have __buitin_clzll. Use _BitScanReverse64. + unsigned long result = 0; // NOLINT(runtime/int) + if (_BitScanReverse64(&result, x)) { + return 63 - result; + } + return 64; +#elif defined(_MSC_VER) && !defined(__clang__) + // MSVC does not have __buitin_clzll. Compose two calls to _BitScanReverse + unsigned long result = 0; // NOLINT(runtime/int) + if ((x >> 32) && + _BitScanReverse(&result, static_cast(x >> 32))) { + return 31 - result; + } + if (_BitScanReverse(&result, static_cast(x))) { + return 63 - result; + } + return 64; +#else + int zeroes = 60; + if (x >> 32) { + zeroes -= 32; + x >>= 32; + } + if (x >> 16) { + zeroes -= 16; + x >>= 16; + } + if (x >> 8) { + zeroes -= 8; + x >>= 8; + } + if (x >> 4) { + zeroes -= 4; + x >>= 4; + } + return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[x] + zeroes; +#endif +} + +template +ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int +CountLeadingZeroes(T x) { + static_assert(std::is_unsigned::value, "T must be unsigned"); + static_assert(IsPowerOf2(std::numeric_limits::digits), + "T must have a power-of-2 size"); + static_assert(sizeof(T) <= sizeof(uint64_t), "T too large"); + return sizeof(T) <= sizeof(uint16_t) + ? CountLeadingZeroes16(static_cast(x)) - + (std::numeric_limits::digits - + std::numeric_limits::digits) + : (sizeof(T) <= sizeof(uint32_t) + ? CountLeadingZeroes32(static_cast(x)) - + (std::numeric_limits::digits - + std::numeric_limits::digits) + : CountLeadingZeroes64(x)); +} + +ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int +CountTrailingZeroesNonzero32(uint32_t x) { +#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctz) + static_assert(sizeof(unsigned int) == sizeof(x), + "__builtin_ctz does not take 32-bit arg"); + return __builtin_ctz(x); +#elif defined(_MSC_VER) && !defined(__clang__) + unsigned long result = 0; // NOLINT(runtime/int) + _BitScanForward(&result, x); + return result; +#else + int c = 31; + x &= ~x + 1; + if (x & 0x0000FFFF) c -= 16; + if (x & 0x00FF00FF) c -= 8; + if (x & 0x0F0F0F0F) c -= 4; + if (x & 0x33333333) c -= 2; + if (x & 0x55555555) c -= 1; + return c; +#endif +} + +ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int +CountTrailingZeroesNonzero64(uint64_t x) { +#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctzll) + static_assert(sizeof(unsigned long long) == sizeof(x), // NOLINT(runtime/int) + "__builtin_ctzll does not take 64-bit arg"); + return __builtin_ctzll(x); +#elif defined(_MSC_VER) && !defined(__clang__) && \ + (defined(_M_X64) || defined(_M_ARM64)) + unsigned long result = 0; // NOLINT(runtime/int) + _BitScanForward64(&result, x); + return result; +#elif defined(_MSC_VER) && !defined(__clang__) + unsigned long result = 0; // NOLINT(runtime/int) + if (static_cast(x) == 0) { + _BitScanForward(&result, static_cast(x >> 32)); + return result + 32; + } + _BitScanForward(&result, static_cast(x)); + return result; +#else + int c = 63; + x &= ~x + 1; + if (x & 0x00000000FFFFFFFF) c -= 32; + if (x & 0x0000FFFF0000FFFF) c -= 16; + if (x & 0x00FF00FF00FF00FF) c -= 8; + if (x & 0x0F0F0F0F0F0F0F0F) c -= 4; + if (x & 0x3333333333333333) c -= 2; + if (x & 0x5555555555555555) c -= 1; + return c; +#endif +} + +ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int +CountTrailingZeroesNonzero16(uint16_t x) { +#if ABSL_HAVE_BUILTIN(__builtin_ctzs) + static_assert(sizeof(unsigned short) == sizeof(x), // NOLINT(runtime/int) + "__builtin_ctzs does not take 16-bit arg"); + return __builtin_ctzs(x); +#else + return CountTrailingZeroesNonzero32(x); +#endif +} + +template +ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int +CountTrailingZeroes(T x) noexcept { + static_assert(std::is_unsigned::value, "T must be unsigned"); + static_assert(IsPowerOf2(std::numeric_limits::digits), + "T must have a power-of-2 size"); + static_assert(sizeof(T) <= sizeof(uint64_t), "T too large"); + return x == 0 ? std::numeric_limits::digits + : (sizeof(T) <= sizeof(uint16_t) + ? CountTrailingZeroesNonzero16(static_cast(x)) + : (sizeof(T) <= sizeof(uint32_t) + ? CountTrailingZeroesNonzero32( + static_cast(x)) + : CountTrailingZeroesNonzero64(x))); +} + +// If T is narrower than unsigned, T{1} << bit_width will be promoted. We +// want to force it to wraparound so that bit_ceil of an invalid value are not +// core constant expressions. +template +ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline + typename std::enable_if::value, T>::type + BitCeilPromotionHelper(T x, T promotion) { + return (T{1} << (x + promotion)) >> promotion; +} + +template +ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline + typename std::enable_if::value, T>::type + BitCeilNonPowerOf2(T x) { + // If T is narrower than unsigned, it undergoes promotion to unsigned when we + // shift. We calculate the number of bits added by the wider type. + return BitCeilPromotionHelper( + static_cast(std::numeric_limits::digits - CountLeadingZeroes(x)), + T{sizeof(T) >= sizeof(unsigned) ? 0 + : std::numeric_limits::digits - + std::numeric_limits::digits}); +} + +} // namespace numeric_internal +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_NUMERIC_INTERNAL_BITS_H_ diff --git a/extern/int128/absl/numeric/internal/representation.h b/extern/int128/absl/numeric/internal/representation.h new file mode 100644 index 0000000000..82d332fdde --- /dev/null +++ b/extern/int128/absl/numeric/internal/representation.h @@ -0,0 +1,55 @@ +// Copyright 2021 The Abseil Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ABSL_NUMERIC_INTERNAL_REPRESENTATION_H_ +#define ABSL_NUMERIC_INTERNAL_REPRESENTATION_H_ + +#include + +#include "absl/base/config.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace numeric_internal { + +// Returns true iff long double is represented as a pair of doubles added +// together. +inline constexpr bool IsDoubleDouble() { + // A double-double value always has exactly twice the precision of a double + // value--one double carries the high digits and one double carries the low + // digits. This property is not shared with any other common floating-point + // representation, so this test won't trigger false positives. For reference, + // this table gives the number of bits of precision of each common + // floating-point representation: + // + // type precision + // IEEE single 24 b + // IEEE double 53 + // x86 long double 64 + // double-double 106 + // IEEE quadruple 113 + // + // Note in particular that a quadruple-precision float has greater precision + // than a double-double float despite taking up the same amount of memory; the + // quad has more of its bits allocated to the mantissa than the double-double + // has. + return std::numeric_limits::digits == + 2 * std::numeric_limits::digits; +} + +} // namespace numeric_internal +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_NUMERIC_INTERNAL_REPRESENTATION_H_ diff --git a/extern/ttmath/ttmath.h b/extern/ttmath/ttmath.h deleted file mode 100644 index 9b9e8ee6e5..0000000000 --- a/extern/ttmath/ttmath.h +++ /dev/null @@ -1,2843 +0,0 @@ -/* - * This file is a part of TTMath Bignum Library - * and is distributed under the (new) BSD licence. - * Author: Tomasz Sowa - */ - -/* - * Copyright (c) 2006-2012, Tomasz Sowa - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name Tomasz Sowa nor the names of contributors to this - * project may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - - - -#ifndef headerfilettmathmathtt -#define headerfilettmathmathtt - -/*! - \file ttmath.h - \brief Mathematics functions. -*/ - -#ifdef _MSC_VER -//warning C4127: conditional expression is constant -#pragma warning( disable: 4127 ) -//warning C4702: unreachable code -#pragma warning( disable: 4702 ) -//warning C4800: forcing value to bool 'true' or 'false' (performance warning) -#pragma warning( disable: 4800 ) -#endif - -#define TTMATH_DONT_USE_WCHAR - -#include "ttmathint.h" -#include "ttmathobjects.h" - - -namespace ttmath -{ - /* - * - * functions defined here are used only with Big<> types - * - * - */ - - - /* - * - * functions for rounding - * - * - */ - - - /*! - this function skips the fraction from x - e.g 2.2 = 2 - 2.7 = 2 - -2.2 = 2 - -2.7 = 2 - */ - template - ValueType SkipFraction(const ValueType & x) - { - ValueType result( x ); - result.SkipFraction(); - - return result; - } - - - /*! - this function rounds to the nearest integer value - e.g 2.2 = 2 - 2.7 = 3 - -2.2 = -2 - -2.7 = -3 - */ - template - ValueType Round(const ValueType & x, ErrorCode * err = 0) - { - if( x.IsNan() ) - { - if( err ) - *err = err_improper_argument; - - return x; // NaN - } - - ValueType result( x ); - uint c = result.Round(); - - if( err ) - *err = c ? err_overflow : err_ok; - - return result; - } - - - - /*! - this function returns a value representing the smallest integer - that is greater than or equal to x - - Ceil(-3.7) = -3 - Ceil(-3.1) = -3 - Ceil(-3.0) = -3 - Ceil(4.0) = 4 - Ceil(4.2) = 5 - Ceil(4.8) = 5 - */ - template - ValueType Ceil(const ValueType & x, ErrorCode * err = 0) - { - if( x.IsNan() ) - { - if( err ) - *err = err_improper_argument; - - return x; // NaN - } - - ValueType result(x); - uint c = 0; - - result.SkipFraction(); - - if( result != x ) - { - // x is with fraction - // if x is negative we don't have to do anything - if( !x.IsSign() ) - { - ValueType one; - one.SetOne(); - - c += result.Add(one); - } - } - - if( err ) - *err = c ? err_overflow : err_ok; - - return result; - } - - - /*! - this function returns a value representing the largest integer - that is less than or equal to x - - Floor(-3.6) = -4 - Floor(-3.1) = -4 - Floor(-3) = -3 - Floor(2) = 2 - Floor(2.3) = 2 - Floor(2.8) = 2 - */ - template - ValueType Floor(const ValueType & x, ErrorCode * err = 0) - { - if( x.IsNan() ) - { - if( err ) - *err = err_improper_argument; - - return x; // NaN - } - - ValueType result(x); - uint c = 0; - - result.SkipFraction(); - - if( result != x ) - { - // x is with fraction - // if x is positive we don't have to do anything - if( x.IsSign() ) - { - ValueType one; - one.SetOne(); - - c += result.Sub(one); - } - } - - if( err ) - *err = c ? err_overflow : err_ok; - - return result; - } - - - - /* - * - * logarithms and the exponent - * - * - */ - - - /*! - this function calculates the natural logarithm (logarithm with the base 'e') - */ - template - ValueType Ln(const ValueType & x, ErrorCode * err = 0) - { - if( x.IsNan() ) - { - if( err ) - *err = err_improper_argument; - - return x; // NaN - } - - ValueType result; - uint state = result.Ln(x); - - if( err ) - { - switch( state ) - { - case 0: - *err = err_ok; - break; - case 1: - *err = err_overflow; - break; - case 2: - *err = err_improper_argument; - break; - default: - *err = err_internal_error; - break; - } - } - - - return result; - } - - - /*! - this function calculates the logarithm - */ - template - ValueType Log(const ValueType & x, const ValueType & base, ErrorCode * err = 0) - { - if( x.IsNan() ) - { - if( err ) *err = err_improper_argument; - return x; - } - - if( base.IsNan() ) - { - if( err ) *err = err_improper_argument; - return base; - } - - ValueType result; - uint state = result.Log(x, base); - - if( err ) - { - switch( state ) - { - case 0: - *err = err_ok; - break; - case 1: - *err = err_overflow; - break; - case 2: - case 3: - *err = err_improper_argument; - break; - default: - *err = err_internal_error; - break; - } - } - - return result; - } - - - /*! - this function calculates the expression e^x - */ - template - ValueType Exp(const ValueType & x, ErrorCode * err = 0) - { - if( x.IsNan() ) - { - if( err ) - *err = err_improper_argument; - - return x; // NaN - } - - ValueType result; - uint c = result.Exp(x); - - if( err ) - *err = c ? err_overflow : err_ok; - - return result; - } - - - /*! - * - * trigonometric functions - * - */ - - - /* - this namespace consists of auxiliary functions - (something like 'private' in a class) - */ - namespace auxiliaryfunctions - { - - /*! - an auxiliary function for calculating the Sine - (you don't have to call this function) - */ - template - uint PrepareSin(ValueType & x, bool & change_sign) - { - ValueType temp; - - change_sign = false; - - if( x.IsSign() ) - { - // we're using the formula 'sin(-x) = -sin(x)' - change_sign = !change_sign; - x.ChangeSign(); - } - - // we're reducing the period 2*PI - // (for big values there'll always be zero) - temp.Set2Pi(); - - if( x.Mod(temp) ) - return 1; - - - // we're setting 'x' as being in the range of <0, 0.5PI> - - temp.SetPi(); - - if( x > temp ) - { - // x is in (pi, 2*pi> - x.Sub( temp ); - change_sign = !change_sign; - } - - temp.Set05Pi(); - - if( x > temp ) - { - // x is in (0.5pi, pi> - x.Sub( temp ); - x = temp - x; - } - - return 0; - } - - - /*! - an auxiliary function for calculating the Sine - (you don't have to call this function) - - it returns Sin(x) where 'x' is from <0, PI/2> - we're calculating the Sin with using Taylor series in zero or PI/2 - (depending on which point of these two points is nearer to the 'x') - - Taylor series: - sin(x) = sin(a) + cos(a)*(x-a)/(1!) - - sin(a)*((x-a)^2)/(2!) - cos(a)*((x-a)^3)/(3!) - + sin(a)*((x-a)^4)/(4!) + ... - - when a=0 it'll be: - sin(x) = (x)/(1!) - (x^3)/(3!) + (x^5)/(5!) - (x^7)/(7!) + (x^9)/(9!) ... - - and when a=PI/2: - sin(x) = 1 - ((x-PI/2)^2)/(2!) + ((x-PI/2)^4)/(4!) - ((x-PI/2)^6)/(6!) ... - */ - template - ValueType Sin0pi05(const ValueType & x) - { - ValueType result; - ValueType numerator, denominator; - ValueType d_numerator, d_denominator; - ValueType one, temp, old_result; - - // temp = pi/4 - temp.Set05Pi(); - temp.exponent.SubOne(); - - one.SetOne(); - - if( x < temp ) - { - // we're using the Taylor series with a=0 - result = x; - numerator = x; - denominator = one; - - // d_numerator = x^2 - d_numerator = x; - d_numerator.Mul(x); - - d_denominator = 2; - } - else - { - // we're using the Taylor series with a=PI/2 - result = one; - numerator = one; - denominator = one; - - // d_numerator = (x-pi/2)^2 - ValueType pi05; - pi05.Set05Pi(); - - temp = x; - temp.Sub( pi05 ); - d_numerator = temp; - d_numerator.Mul( temp ); - - d_denominator = one; - } - - uint c = 0; - bool addition = false; - - old_result = result; - for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) - { - // we're starting from a second part of the formula - c += numerator. Mul( d_numerator ); - c += denominator. Mul( d_denominator ); - c += d_denominator.Add( one ); - c += denominator. Mul( d_denominator ); - c += d_denominator.Add( one ); - temp = numerator; - c += temp.Div(denominator); - - if( c ) - // Sin is from <-1,1> and cannot make an overflow - // but the carry can be from the Taylor series - // (then we only break our calculations) - break; - - if( addition ) - result.Add( temp ); - else - result.Sub( temp ); - - - addition = !addition; - - // we're testing whether the result has changed after adding - // the next part of the Taylor formula, if not we end the loop - // (it means 'x' is zero or 'x' is PI/2 or this part of the formula - // is too small) - if( result == old_result ) - break; - - old_result = result; - } - - return result; - } - - } // namespace auxiliaryfunctions - - - - /*! - this function calculates the Sine - */ - template - ValueType Sin(ValueType x, ErrorCode * err = 0) - { - using namespace auxiliaryfunctions; - - ValueType one, result; - bool change_sign; - - if( x.IsNan() ) - { - if( err ) - *err = err_improper_argument; - - return x; - } - - if( err ) - *err = err_ok; - - if( PrepareSin( x, change_sign ) ) - { - // x is too big, we cannnot reduce the 2*PI period - // prior to version 0.8.5 the result was zero - - // result has NaN flag set by default - - if( err ) - *err = err_overflow; // maybe another error code? err_improper_argument? - - return result; // NaN is set by default - } - - result = Sin0pi05( x ); - - one.SetOne(); - - // after calculations there can be small distortions in the result - if( result > one ) - result = one; - else - if( result.IsSign() ) - // we've calculated the sin from <0, pi/2> and the result - // should be positive - result.SetZero(); - - if( change_sign ) - result.ChangeSign(); - - return result; - } - - - /*! - this function calulates the Cosine - we're using the formula cos(x) = sin(x + PI/2) - */ - template - ValueType Cos(ValueType x, ErrorCode * err = 0) - { - if( x.IsNan() ) - { - if( err ) - *err = err_improper_argument; - - return x; // NaN - } - - ValueType pi05; - pi05.Set05Pi(); - - uint c = x.Add( pi05 ); - - if( c ) - { - if( err ) - *err = err_overflow; - - return ValueType(); // result is undefined (NaN is set by default) - } - - return Sin(x, err); - } - - - /*! - this function calulates the Tangent - we're using the formula tan(x) = sin(x) / cos(x) - - it takes more time than calculating the Tan directly - from for example Taylor series but should be a bit preciser - because Tan receives its values from -infinity to +infinity - and when we calculate it from any series then we can make - a greater mistake than calculating 'sin/cos' - */ - template - ValueType Tan(const ValueType & x, ErrorCode * err = 0) - { - ValueType result = Cos(x, err); - - if( err && *err != err_ok ) - return result; - - if( result.IsZero() ) - { - if( err ) - *err = err_improper_argument; - - result.SetNan(); - - return result; - } - - return Sin(x, err) / result; - } - - - /*! - this function calulates the Tangent - look at the description of Tan(...) - - (the abbreviation of Tangent can be 'tg' as well) - */ - template - ValueType Tg(const ValueType & x, ErrorCode * err = 0) - { - return Tan(x, err); - } - - - /*! - this function calulates the Cotangent - we're using the formula tan(x) = cos(x) / sin(x) - - (why do we make it in this way? - look at information in Tan() function) - */ - template - ValueType Cot(const ValueType & x, ErrorCode * err = 0) - { - ValueType result = Sin(x, err); - - if( err && *err != err_ok ) - return result; - - if( result.IsZero() ) - { - if( err ) - *err = err_improper_argument; - - result.SetNan(); - - return result; - } - - return Cos(x, err) / result; - } - - - /*! - this function calulates the Cotangent - look at the description of Cot(...) - - (the abbreviation of Cotangent can be 'ctg' as well) - */ - template - ValueType Ctg(const ValueType & x, ErrorCode * err = 0) - { - return Cot(x, err); - } - - - /* - * - * inverse trigonometric functions - * - * - */ - - namespace auxiliaryfunctions - { - - /*! - an auxiliary function for calculating the Arc Sine - - we're calculating asin from the following formula: - asin(x) = x + (1*x^3)/(2*3) + (1*3*x^5)/(2*4*5) + (1*3*5*x^7)/(2*4*6*7) + ... - where abs(x) <= 1 - - we're using this formula when x is from <0, 1/2> - */ - template - ValueType ASin_0(const ValueType & x) - { - ValueType nominator, denominator, nominator_add, nominator_x, denominator_add, denominator_x; - ValueType two, result(x), x2(x); - ValueType nominator_temp, denominator_temp, old_result = result; - uint c = 0; - - x2.Mul(x); - two = 2; - - nominator.SetOne(); - denominator = two; - nominator_add = nominator; - denominator_add = denominator; - nominator_x = x; - denominator_x = 3; - - for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) - { - c += nominator_x.Mul(x2); - nominator_temp = nominator_x; - c += nominator_temp.Mul(nominator); - denominator_temp = denominator; - c += denominator_temp.Mul(denominator_x); - c += nominator_temp.Div(denominator_temp); - - // if there is a carry somewhere we only break the calculating - // the result should be ok -- it's from <-pi/2, pi/2> - if( c ) - break; - - result.Add(nominator_temp); - - if( result == old_result ) - // there's no sense to calculate more - break; - - old_result = result; - - - c += nominator_add.Add(two); - c += denominator_add.Add(two); - c += nominator.Mul(nominator_add); - c += denominator.Mul(denominator_add); - c += denominator_x.Add(two); - } - - return result; - } - - - - /*! - an auxiliary function for calculating the Arc Sine - - we're calculating asin from the following formula: - asin(x) = pi/2 - sqrt(2)*sqrt(1-x) * asin_temp - asin_temp = 1 + (1*(1-x))/((2*3)*(2)) + (1*3*(1-x)^2)/((2*4*5)*(4)) + (1*3*5*(1-x)^3)/((2*4*6*7)*(8)) + ... - - where abs(x) <= 1 - - we're using this formula when x is from (1/2, 1> - */ - template - ValueType ASin_1(const ValueType & x) - { - ValueType nominator, denominator, nominator_add, nominator_x, nominator_x_add, denominator_add, denominator_x; - ValueType denominator2; - ValueType one, two, result; - ValueType nominator_temp, denominator_temp, old_result; - uint c = 0; - - two = 2; - - one.SetOne(); - nominator = one; - result = one; - old_result = result; - denominator = two; - nominator_add = nominator; - denominator_add = denominator; - nominator_x = one; - nominator_x.Sub(x); - nominator_x_add = nominator_x; - denominator_x = 3; - denominator2 = two; - - - for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) - { - nominator_temp = nominator_x; - c += nominator_temp.Mul(nominator); - denominator_temp = denominator; - c += denominator_temp.Mul(denominator_x); - c += denominator_temp.Mul(denominator2); - c += nominator_temp.Div(denominator_temp); - - // if there is a carry somewhere we only break the calculating - // the result should be ok -- it's from <-pi/2, pi/2> - if( c ) - break; - - result.Add(nominator_temp); - - if( result == old_result ) - // there's no sense to calculate more - break; - - old_result = result; - - c += nominator_x.Mul(nominator_x_add); - c += nominator_add.Add(two); - c += denominator_add.Add(two); - c += nominator.Mul(nominator_add); - c += denominator.Mul(denominator_add); - c += denominator_x.Add(two); - c += denominator2.Mul(two); - } - - - nominator_x_add.exponent.AddOne(); // *2 - one.exponent.SubOne(); // =0.5 - nominator_x_add.Pow(one); // =sqrt(nominator_x_add) - result.Mul(nominator_x_add); - - one.Set05Pi(); - one.Sub(result); - - return one; - } - - - } // namespace auxiliaryfunctions - - - /*! - this function calculates the Arc Sine - x is from <-1,1> - */ - template - ValueType ASin(ValueType x, ErrorCode * err = 0) - { - using namespace auxiliaryfunctions; - - ValueType result, one; - one.SetOne(); - bool change_sign = false; - - if( x.IsNan() ) - { - if( err ) - *err = err_improper_argument; - - return x; - } - - if( x.GreaterWithoutSignThan(one) ) - { - if( err ) - *err = err_improper_argument; - - return result; // NaN is set by default - } - - if( x.IsSign() ) - { - change_sign = true; - x.Abs(); - } - - one.exponent.SubOne(); // =0.5 - - // asin(-x) = -asin(x) - if( x.GreaterWithoutSignThan(one) ) - result = ASin_1(x); - else - result = ASin_0(x); - - if( change_sign ) - result.ChangeSign(); - - if( err ) - *err = err_ok; - - return result; - } - - - /*! - this function calculates the Arc Cosine - - we're using the formula: - acos(x) = pi/2 - asin(x) - */ - template - ValueType ACos(const ValueType & x, ErrorCode * err = 0) - { - ValueType temp; - - temp.Set05Pi(); - temp.Sub(ASin(x, err)); - - return temp; - } - - - - namespace auxiliaryfunctions - { - - /*! - an auxiliary function for calculating the Arc Tangent - - arc tan (x) where x is in <0; 0.5) - (x can be in (-0.5 ; 0.5) too) - - we're using the Taylor series expanded in zero: - atan(x) = x - (x^3)/3 + (x^5)/5 - (x^7)/7 + ... - */ - template - ValueType ATan0(const ValueType & x) - { - ValueType nominator, denominator, nominator_add, denominator_add, temp; - ValueType result, old_result; - bool adding = false; - uint c = 0; - - result = x; - old_result = result; - nominator = x; - nominator_add = x; - nominator_add.Mul(x); - - denominator.SetOne(); - denominator_add = 2; - - for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) - { - c += nominator.Mul(nominator_add); - c += denominator.Add(denominator_add); - - temp = nominator; - c += temp.Div(denominator); - - if( c ) - // the result should be ok - break; - - if( adding ) - result.Add(temp); - else - result.Sub(temp); - - if( result == old_result ) - // there's no sense to calculate more - break; - - old_result = result; - adding = !adding; - } - - return result; - } - - - /*! - an auxiliary function for calculating the Arc Tangent - - where x is in <0 ; 1> - */ - template - ValueType ATan01(const ValueType & x) - { - ValueType half; - half.Set05(); - - /* - it would be better if we chose about sqrt(2)-1=0.41... instead of 0.5 here - - because as you can see below: - when x = sqrt(2)-1 - abs(x) = abs( (x-1)/(1+x) ) - so when we're calculating values around x - then they will be better converged to each other - - for example if we have x=0.4999 then during calculating ATan0(0.4999) - we have to make about 141 iterations but when we have x=0.5 - then during calculating ATan0( (x-1)/(1+x) ) we have to make - only about 89 iterations (both for Big<3,9>) - - in the future this 0.5 can be changed - */ - if( x.SmallerWithoutSignThan(half) ) - return ATan0(x); - - - /* - x>=0.5 and x<=1 - (x can be even smaller than 0.5) - - y = atac(x) - x = tan(y) - - tan(y-b) = (tan(y)-tab(b)) / (1+tan(y)*tan(b)) - y-b = atan( (tan(y)-tab(b)) / (1+tan(y)*tan(b)) ) - y = b + atan( (x-tab(b)) / (1+x*tan(b)) ) - - let b = pi/4 - tan(b) = tan(pi/4) = 1 - y = pi/4 + atan( (x-1)/(1+x) ) - - so - atac(x) = pi/4 + atan( (x-1)/(1+x) ) - when x->1 (x converges to 1) the (x-1)/(1+x) -> 0 - and we can use ATan0() function here - */ - - ValueType n(x),d(x),one,result; - - one.SetOne(); - n.Sub(one); - d.Add(one); - n.Div(d); - - result = ATan0(n); - - n.Set05Pi(); - n.exponent.SubOne(); // =pi/4 - result.Add(n); - - return result; - } - - - /*! - an auxiliary function for calculating the Arc Tangent - where x > 1 - - we're using the formula: - atan(x) = pi/2 - atan(1/x) for x>0 - */ - template - ValueType ATanGreaterThanPlusOne(const ValueType & x) - { - ValueType temp, atan; - - temp.SetOne(); - - if( temp.Div(x) ) - { - // if there was a carry here that means x is very big - // and atan(1/x) fast converged to 0 - atan.SetZero(); - } - else - atan = ATan01(temp); - - temp.Set05Pi(); - temp.Sub(atan); - - return temp; - } - - } // namespace auxiliaryfunctions - - - /*! - this function calculates the Arc Tangent - */ - template - ValueType ATan(ValueType x) - { - using namespace auxiliaryfunctions; - - ValueType one, result; - one.SetOne(); - bool change_sign = false; - - if( x.IsNan() ) - return x; - - // if x is negative we're using the formula: - // atan(-x) = -atan(x) - if( x.IsSign() ) - { - change_sign = true; - x.Abs(); - } - - if( x.GreaterWithoutSignThan(one) ) - result = ATanGreaterThanPlusOne(x); - else - result = ATan01(x); - - if( change_sign ) - result.ChangeSign(); - - return result; - } - - - /*! - this function calculates the Arc Tangent - look at the description of ATan(...) - - (the abbreviation of Arc Tangent can be 'atg' as well) - */ - template - ValueType ATg(const ValueType & x) - { - return ATan(x); - } - - - /*! - this function calculates the Arc Cotangent - - we're using the formula: - actan(x) = pi/2 - atan(x) - */ - template - ValueType ACot(const ValueType & x) - { - ValueType result; - - result.Set05Pi(); - result.Sub(ATan(x)); - - return result; - } - - - /*! - this function calculates the Arc Cotangent - look at the description of ACot(...) - - (the abbreviation of Arc Cotangent can be 'actg' as well) - */ - template - ValueType ACtg(const ValueType & x) - { - return ACot(x); - } - - - /* - * - * hyperbolic functions - * - * - */ - - - /*! - this function calculates the Hyperbolic Sine - - we're using the formula sinh(x)= ( e^x - e^(-x) ) / 2 - */ - template - ValueType Sinh(const ValueType & x, ErrorCode * err = 0) - { - if( x.IsNan() ) - { - if( err ) - *err = err_improper_argument; - - return x; // NaN - } - - ValueType ex, emx; - uint c = 0; - - c += ex.Exp(x); - c += emx.Exp(-x); - - c += ex.Sub(emx); - c += ex.exponent.SubOne(); - - if( err ) - *err = c ? err_overflow : err_ok; - - return ex; - } - - - /*! - this function calculates the Hyperbolic Cosine - - we're using the formula cosh(x)= ( e^x + e^(-x) ) / 2 - */ - template - ValueType Cosh(const ValueType & x, ErrorCode * err = 0) - { - if( x.IsNan() ) - { - if( err ) - *err = err_improper_argument; - - return x; // NaN - } - - ValueType ex, emx; - uint c = 0; - - c += ex.Exp(x); - c += emx.Exp(-x); - - c += ex.Add(emx); - c += ex.exponent.SubOne(); - - if( err ) - *err = c ? err_overflow : err_ok; - - return ex; - } - - - /*! - this function calculates the Hyperbolic Tangent - - we're using the formula tanh(x)= ( e^x - e^(-x) ) / ( e^x + e^(-x) ) - */ - template - ValueType Tanh(const ValueType & x, ErrorCode * err = 0) - { - if( x.IsNan() ) - { - if( err ) - *err = err_improper_argument; - - return x; // NaN - } - - ValueType ex, emx, nominator, denominator; - uint c = 0; - - c += ex.Exp(x); - c += emx.Exp(-x); - - nominator = ex; - c += nominator.Sub(emx); - denominator = ex; - c += denominator.Add(emx); - - c += nominator.Div(denominator); - - if( err ) - *err = c ? err_overflow : err_ok; - - return nominator; - } - - - /*! - this function calculates the Hyperbolic Tangent - look at the description of Tanh(...) - - (the abbreviation of Hyperbolic Tangent can be 'tgh' as well) - */ - template - ValueType Tgh(const ValueType & x, ErrorCode * err = 0) - { - return Tanh(x, err); - } - - /*! - this function calculates the Hyperbolic Cotangent - - we're using the formula coth(x)= ( e^x + e^(-x) ) / ( e^x - e^(-x) ) - */ - template - ValueType Coth(const ValueType & x, ErrorCode * err = 0) - { - if( x.IsNan() ) - { - if( err ) - *err = err_improper_argument; - - return x; // NaN - } - - if( x.IsZero() ) - { - if( err ) - *err = err_improper_argument; - - return ValueType(); // NaN is set by default - } - - ValueType ex, emx, nominator, denominator; - uint c = 0; - - c += ex.Exp(x); - c += emx.Exp(-x); - - nominator = ex; - c += nominator.Add(emx); - denominator = ex; - c += denominator.Sub(emx); - - c += nominator.Div(denominator); - - if( err ) - *err = c ? err_overflow : err_ok; - - return nominator; - } - - - /*! - this function calculates the Hyperbolic Cotangent - look at the description of Coth(...) - - (the abbreviation of Hyperbolic Cotangent can be 'ctgh' as well) - */ - template - ValueType Ctgh(const ValueType & x, ErrorCode * err = 0) - { - return Coth(x, err); - } - - - /* - * - * inverse hyperbolic functions - * - * - */ - - - /*! - inverse hyperbolic sine - - asinh(x) = ln( x + sqrt(x^2 + 1) ) - */ - template - ValueType ASinh(const ValueType & x, ErrorCode * err = 0) - { - if( x.IsNan() ) - { - if( err ) - *err = err_improper_argument; - - return x; // NaN - } - - ValueType xx(x), one, result; - uint c = 0; - one.SetOne(); - - c += xx.Mul(x); - c += xx.Add(one); - one.exponent.SubOne(); // one=0.5 - // xx is >= 1 - c += xx.PowFrac(one); // xx=sqrt(xx) - c += xx.Add(x); - c += result.Ln(xx); // xx > 0 - - // here can only be a carry - if( err ) - *err = c ? err_overflow : err_ok; - - return result; - } - - - /*! - inverse hyperbolic cosine - - acosh(x) = ln( x + sqrt(x^2 - 1) ) x in <1, infinity) - */ - template - ValueType ACosh(const ValueType & x, ErrorCode * err = 0) - { - if( x.IsNan() ) - { - if( err ) - *err = err_improper_argument; - - return x; // NaN - } - - ValueType xx(x), one, result; - uint c = 0; - one.SetOne(); - - if( x < one ) - { - if( err ) - *err = err_improper_argument; - - return result; // NaN is set by default - } - - c += xx.Mul(x); - c += xx.Sub(one); - // xx is >= 0 - // we can't call a PowFrac when the 'x' is zero - // if x is 0 the sqrt(0) is 0 - if( !xx.IsZero() ) - { - one.exponent.SubOne(); // one=0.5 - c += xx.PowFrac(one); // xx=sqrt(xx) - } - c += xx.Add(x); - c += result.Ln(xx); // xx >= 1 - - // here can only be a carry - if( err ) - *err = c ? err_overflow : err_ok; - - return result; - } - - - /*! - inverse hyperbolic tangent - - atanh(x) = 0.5 * ln( (1+x) / (1-x) ) x in (-1, 1) - */ - template - ValueType ATanh(const ValueType & x, ErrorCode * err = 0) - { - if( x.IsNan() ) - { - if( err ) - *err = err_improper_argument; - - return x; // NaN - } - - ValueType nominator(x), denominator, one, result; - uint c = 0; - one.SetOne(); - - if( !x.SmallerWithoutSignThan(one) ) - { - if( err ) - *err = err_improper_argument; - - return result; // NaN is set by default - } - - c += nominator.Add(one); - denominator = one; - c += denominator.Sub(x); - c += nominator.Div(denominator); - c += result.Ln(nominator); - c += result.exponent.SubOne(); - - // here can only be a carry - if( err ) - *err = c ? err_overflow : err_ok; - - return result; - } - - - /*! - inverse hyperbolic tantent - */ - template - ValueType ATgh(const ValueType & x, ErrorCode * err = 0) - { - return ATanh(x, err); - } - - - /*! - inverse hyperbolic cotangent - - acoth(x) = 0.5 * ln( (x+1) / (x-1) ) x in (-infinity, -1) or (1, infinity) - */ - template - ValueType ACoth(const ValueType & x, ErrorCode * err = 0) - { - if( x.IsNan() ) - { - if( err ) - *err = err_improper_argument; - - return x; // NaN - } - - ValueType nominator(x), denominator(x), one, result; - uint c = 0; - one.SetOne(); - - if( !x.GreaterWithoutSignThan(one) ) - { - if( err ) - *err = err_improper_argument; - - return result; // NaN is set by default - } - - c += nominator.Add(one); - c += denominator.Sub(one); - c += nominator.Div(denominator); - c += result.Ln(nominator); - c += result.exponent.SubOne(); - - // here can only be a carry - if( err ) - *err = c ? err_overflow : err_ok; - - return result; - } - - - /*! - inverse hyperbolic cotantent - */ - template - ValueType ACtgh(const ValueType & x, ErrorCode * err = 0) - { - return ACoth(x, err); - } - - - - - - /* - * - * functions for converting between degrees, radians and gradians - * - * - */ - - - /*! - this function converts degrees to radians - - it returns: x * pi / 180 - */ - template - ValueType DegToRad(const ValueType & x, ErrorCode * err = 0) - { - ValueType result, temp; - uint c = 0; - - if( x.IsNan() ) - { - if( err ) - *err = err_improper_argument; - - return x; - } - - result = x; - - // it is better to make division first and then multiplication - // the result is more accurate especially when x is: 90,180,270 or 360 - temp = 180; - c += result.Div(temp); - - temp.SetPi(); - c += result.Mul(temp); - - if( err ) - *err = c ? err_overflow : err_ok; - - return result; - } - - - /*! - this function converts radians to degrees - - it returns: x * 180 / pi - */ - template - ValueType RadToDeg(const ValueType & x, ErrorCode * err = 0) - { - ValueType result, delimiter; - uint c = 0; - - if( x.IsNan() ) - { - if( err ) - *err = err_improper_argument; - - return x; - } - - result = 180; - c += result.Mul(x); - - delimiter.SetPi(); - c += result.Div(delimiter); - - if( err ) - *err = c ? err_overflow : err_ok; - - return result; - } - - - /*! - this function converts degrees in the long format into one value - - long format: (degrees, minutes, seconds) - minutes and seconds must be greater than or equal zero - - result: - if d>=0 : result= d + ((s/60)+m)/60 - if d<0 : result= d - ((s/60)+m)/60 - - ((s/60)+m)/60 = (s+60*m)/3600 (second version is faster because - there's only one division) - - for example: - DegToDeg(10, 30, 0) = 10.5 - DegToDeg(10, 24, 35.6)=10.4098(8) - */ - template - ValueType DegToDeg( const ValueType & d, const ValueType & m, const ValueType & s, - ErrorCode * err = 0) - { - ValueType delimiter, multipler; - uint c = 0; - - if( d.IsNan() || m.IsNan() || s.IsNan() || m.IsSign() || s.IsSign() ) - { - if( err ) - *err = err_improper_argument; - - delimiter.SetZeroNan(); // not needed, only to get rid of GCC warning about an uninitialized variable - - return delimiter; - } - - multipler = 60; - delimiter = 3600; - - c += multipler.Mul(m); - c += multipler.Add(s); - c += multipler.Div(delimiter); - - if( d.IsSign() ) - multipler.ChangeSign(); - - c += multipler.Add(d); - - if( err ) - *err = c ? err_overflow : err_ok; - - return multipler; - } - - - /*! - this function converts degrees in the long format to radians - */ - template - ValueType DegToRad( const ValueType & d, const ValueType & m, const ValueType & s, - ErrorCode * err = 0) - { - ValueType temp_deg = DegToDeg(d,m,s,err); - - if( err && *err!=err_ok ) - return temp_deg; - - return DegToRad(temp_deg, err); - } - - - /*! - this function converts gradians to radians - - it returns: x * pi / 200 - */ - template - ValueType GradToRad(const ValueType & x, ErrorCode * err = 0) - { - ValueType result, temp; - uint c = 0; - - if( x.IsNan() ) - { - if( err ) - *err = err_improper_argument; - - return x; - } - - result = x; - - // it is better to make division first and then multiplication - // the result is more accurate especially when x is: 100,200,300 or 400 - temp = 200; - c += result.Div(temp); - - temp.SetPi(); - c += result.Mul(temp); - - if( err ) - *err = c ? err_overflow : err_ok; - - return result; - } - - - /*! - this function converts radians to gradians - - it returns: x * 200 / pi - */ - template - ValueType RadToGrad(const ValueType & x, ErrorCode * err = 0) - { - ValueType result, delimiter; - uint c = 0; - - if( x.IsNan() ) - { - if( err ) - *err = err_improper_argument; - - return x; - } - - result = 200; - c += result.Mul(x); - - delimiter.SetPi(); - c += result.Div(delimiter); - - if( err ) - *err = c ? err_overflow : err_ok; - - return result; - } - - - /*! - this function converts degrees to gradians - - it returns: x * 200 / 180 - */ - template - ValueType DegToGrad(const ValueType & x, ErrorCode * err = 0) - { - ValueType result, temp; - uint c = 0; - - if( x.IsNan() ) - { - if( err ) - *err = err_improper_argument; - - return x; - } - - result = x; - - temp = 200; - c += result.Mul(temp); - - temp = 180; - c += result.Div(temp); - - if( err ) - *err = c ? err_overflow : err_ok; - - return result; - } - - - /*! - this function converts degrees in the long format to gradians - */ - template - ValueType DegToGrad( const ValueType & d, const ValueType & m, const ValueType & s, - ErrorCode * err = 0) - { - ValueType temp_deg = DegToDeg(d,m,s,err); - - if( err && *err!=err_ok ) - return temp_deg; - - return DegToGrad(temp_deg, err); - } - - - /*! - this function converts degrees to gradians - - it returns: x * 180 / 200 - */ - template - ValueType GradToDeg(const ValueType & x, ErrorCode * err = 0) - { - ValueType result, temp; - uint c = 0; - - if( x.IsNan() ) - { - if( err ) - *err = err_improper_argument; - - return x; - } - - result = x; - - temp = 180; - c += result.Mul(temp); - - temp = 200; - c += result.Div(temp); - - if( err ) - *err = c ? err_overflow : err_ok; - - return result; - } - - - - - /* - * - * another functions - * - * - */ - - - /*! - this function calculates the square root - - Sqrt(9) = 3 - */ - template - ValueType Sqrt(ValueType x, ErrorCode * err = 0) - { - if( x.IsNan() || x.IsSign() ) - { - if( err ) - *err = err_improper_argument; - - x.SetNan(); - - return x; - } - - uint c = x.Sqrt(); - - if( err ) - *err = c ? err_overflow : err_ok; - - return x; - } - - - - namespace auxiliaryfunctions - { - - template - bool RootCheckIndexSign(ValueType & x, const ValueType & index, ErrorCode * err) - { - if( index.IsSign() ) - { - // index cannot be negative - if( err ) - *err = err_improper_argument; - - x.SetNan(); - - return true; - } - - return false; - } - - - template - bool RootCheckIndexZero(ValueType & x, const ValueType & index, ErrorCode * err) - { - if( index.IsZero() ) - { - if( x.IsZero() ) - { - // there isn't root(0;0) - we assume it's not defined - if( err ) - *err = err_improper_argument; - - x.SetNan(); - - return true; - } - - // root(x;0) is 1 (if x!=0) - x.SetOne(); - - if( err ) - *err = err_ok; - - return true; - } - - return false; - } - - - template - bool RootCheckIndexOne(const ValueType & index, ErrorCode * err) - { - ValueType one; - one.SetOne(); - - if( index == one ) - { - //root(x;1) is x - // we do it because if we used the PowFrac function - // we would lose the precision - if( err ) - *err = err_ok; - - return true; - } - - return false; - } - - - template - bool RootCheckIndexTwo(ValueType & x, const ValueType & index, ErrorCode * err) - { - if( index == 2 ) - { - x = Sqrt(x, err); - - return true; - } - - return false; - } - - - template - bool RootCheckIndexFrac(ValueType & x, const ValueType & index, ErrorCode * err) - { - if( !index.IsInteger() ) - { - // index must be integer - if( err ) - *err = err_improper_argument; - - x.SetNan(); - - return true; - } - - return false; - } - - - template - bool RootCheckXZero(ValueType & x, ErrorCode * err) - { - if( x.IsZero() ) - { - // root(0;index) is zero (if index!=0) - // RootCheckIndexZero() must be called beforehand - x.SetZero(); - - if( err ) - *err = err_ok; - - return true; - } - - return false; - } - - - template - bool RootCheckIndex(ValueType & x, const ValueType & index, ErrorCode * err, bool * change_sign) - { - *change_sign = false; - - if( index.Mod2() ) - { - // index is odd (1,3,5...) - if( x.IsSign() ) - { - *change_sign = true; - x.Abs(); - } - } - else - { - // index is even - // x cannot be negative - if( x.IsSign() ) - { - if( err ) - *err = err_improper_argument; - - x.SetNan(); - - return true; - } - } - - return false; - } - - - template - uint RootCorrectInteger(ValueType & old_x, ValueType & x, const ValueType & index) - { - if( !old_x.IsInteger() || x.IsInteger() || !index.exponent.IsSign() ) - return 0; - - // old_x is integer, - // x is not integer, - // index is relatively small (index.exponent<0 or index.exponent<=0) - // (because we're using a special powering algorithm Big::PowUInt()) - - uint c = 0; - - ValueType temp(x); - c += temp.Round(); - - ValueType temp_round(temp); - c += temp.PowUInt(index); - - if( temp == old_x ) - x = temp_round; - - return (c==0)? 0 : 1; - } - - - - } // namespace auxiliaryfunctions - - - - /*! - indexth Root of x - index must be integer and not negative <0;1;2;3....) - - if index==0 the result is one - if x==0 the result is zero and we assume root(0;0) is not defined - - if index is even (2;4;6...) the result is x^(1/index) and x>0 - if index is odd (1;2;3;...) the result is either - -(abs(x)^(1/index)) if x<0 or - x^(1/index)) if x>0 - - (for index==1 the result is equal x) - */ - template - ValueType Root(ValueType x, const ValueType & index, ErrorCode * err = 0) - { - using namespace auxiliaryfunctions; - - if( x.IsNan() || index.IsNan() ) - { - if( err ) - *err = err_improper_argument; - - x.SetNan(); - - return x; - } - - if( RootCheckIndexSign(x, index, err) ) return x; - if( RootCheckIndexZero(x, index, err) ) return x; - if( RootCheckIndexOne ( index, err) ) return x; - if( RootCheckIndexTwo (x, index, err) ) return x; - if( RootCheckIndexFrac(x, index, err) ) return x; - if( RootCheckXZero (x, err) ) return x; - - // index integer and index!=0 - // x!=0 - - ValueType old_x(x); - bool change_sign; - - if( RootCheckIndex(x, index, err, &change_sign ) ) return x; - - ValueType temp; - uint c = 0; - - // we're using the formula: root(x ; n) = exp( ln(x) / n ) - c += temp.Ln(x); - c += temp.Div(index); - c += x.Exp(temp); - - if( change_sign ) - { - // x is different from zero - x.SetSign(); - } - - c += RootCorrectInteger(old_x, x, index); - - if( err ) - *err = c ? err_overflow : err_ok; - - return x; - } - - - - /*! - absolute value of x - e.g. -2 = 2 - 2 = 2 - */ - template - ValueType Abs(const ValueType & x) - { - ValueType result( x ); - result.Abs(); - - return result; - } - - - /*! - it returns the sign of the value - e.g. -2 = -1 - 0 = 0 - 10 = 1 - */ - template - ValueType Sgn(ValueType x) - { - x.Sgn(); - - return x; - } - - - /*! - the remainder from a division - - e.g. - mod( 12.6 ; 3) = 0.6 because 12.6 = 3*4 + 0.6 - mod(-12.6 ; 3) = -0.6 bacause -12.6 = 3*(-4) + (-0.6) - mod( 12.6 ; -3) = 0.6 - mod(-12.6 ; -3) = -0.6 - */ - template - ValueType Mod(ValueType a, const ValueType & b, ErrorCode * err = 0) - { - if( a.IsNan() || b.IsNan() ) - { - if( err ) - *err = err_improper_argument; - - a.SetNan(); - - return a; - } - - uint c = a.Mod(b); - - if( err ) - *err = c ? err_overflow : err_ok; - - return a; - } - - - - namespace auxiliaryfunctions - { - - /*! - this function is used to store factorials in a given container - 'more' means how many values should be added at the end - - e.g. - std::vector fact; - SetFactorialSequence(fact, 3); - // now the container has three values: 1 1 2 - - SetFactorialSequence(fact, 2); - // now the container has five values: 1 1 2 6 24 - */ - template - void SetFactorialSequence(std::vector & fact, uint more = 20) - { - if( more == 0 ) - more = 1; - - uint start = static_cast(fact.size()); - fact.resize(fact.size() + more); - - if( start == 0 ) - { - fact[0] = 1; - ++start; - } - - for(uint i=start ; i - ValueType SetBernoulliNumbersSum(CGamma & cgamma, const ValueType & n_, uint m, - const volatile StopCalculating * stop = 0) - { - ValueType k_, temp, temp2, temp3, sum; - - sum.SetZero(); - - for(uint k=0 ; kWasStopSignal() ) - return ValueType(); // NaN - - if( k>1 && (k & 1) == 1 ) // for that k the Bernoulli number is zero - continue; - - k_ = k; - - temp = n_; // n_ is equal 2 - temp.Pow(k_); - // temp = 2^k - - temp2 = cgamma.fact[m]; - temp3 = cgamma.fact[k]; - temp3.Mul(cgamma.fact[m-k]); - temp2.Div(temp3); - // temp2 = (m k) = m! / ( k! * (m-k)! ) - - temp.Mul(temp2); - temp.Mul(cgamma.bern[k]); - - sum.Add(temp); - // sum += 2^k * (m k) * B(k) - - if( sum.IsNan() ) - break; - } - - return sum; - } - - - /*! - an auxiliary function used to calculate Bernoulli numbers - start is >= 2 - - we use the recurrence formula: - B(m) = 1 / (2*(1 - 2^m)) * sum(m) - where sum(m) is calculated by SetBernoulliNumbersSum() - */ - template - bool SetBernoulliNumbersMore(CGamma & cgamma, uint start, const volatile StopCalculating * stop = 0) - { - ValueType denominator, temp, temp2, temp3, m_, sum, sum2, n_, k_; - - const uint n = 2; - n_ = n; - - // start is >= 2 - for(uint m=start ; mWasStopSignal() ) - { - cgamma.bern.resize(m); // valid numbers are in [0, m-1] - return false; - } - - cgamma.bern[m].Div(denominator); - } - } - - return true; - } - - - /*! - this function is used to calculate Bernoulli numbers, - returns false if there was a stop signal, - 'more' means how many values should be added at the end - - e.g. - typedef Big<1,2> MyBig; - CGamma cgamma; - SetBernoulliNumbers(cgamma, 3); - // now we have three first Bernoulli numbers: 1 -0.5 0.16667 - - SetBernoulliNumbers(cgamma, 4); - // now we have 7 Bernoulli numbers: 1 -0.5 0.16667 0 -0.0333 0 0.0238 - */ - template - bool SetBernoulliNumbers(CGamma & cgamma, uint more = 20, const volatile StopCalculating * stop = 0) - { - if( more == 0 ) - more = 1; - - uint start = static_cast(cgamma.bern.size()); - cgamma.bern.resize(cgamma.bern.size() + more); - - if( start == 0 ) - { - cgamma.bern[0].SetOne(); - ++start; - } - - if( cgamma.bern.size() == 1 ) - return true; - - if( start == 1 ) - { - cgamma.bern[1].Set05(); - cgamma.bern[1].ChangeSign(); - ++start; - } - - // we should have sufficient factorials in cgamma.fact - if( cgamma.fact.size() < cgamma.bern.size() ) - SetFactorialSequence(cgamma.fact, static_cast(cgamma.bern.size() - cgamma.fact.size())); - - - return SetBernoulliNumbersMore(cgamma, start, stop); - } - - - /*! - an auxiliary function used to calculate the Gamma() function - - we calculate a sum: - sum(n) = sum_{m=2} { B(m) / ( (m^2 - m) * n^(m-1) ) } = 1/(12*n) - 1/(360*n^3) + 1/(1260*n^5) + ... - B(m) means a mth Bernoulli number - the sum starts from m=2, we calculate as long as the value will not change after adding a next part - */ - template - ValueType GammaFactorialHighSum(const ValueType & n, CGamma & cgamma, ErrorCode & err, - const volatile StopCalculating * stop) - { - ValueType temp, temp2, denominator, sum, oldsum; - - sum.SetZero(); - - for(uint m=2 ; mWasStopSignal() ) - { - err = err_interrupt; - return ValueType(); // NaN - } - - temp = (m-1); - denominator = n; - denominator.Pow(temp); - // denominator = n ^ (m-1) - - temp = m; - temp2 = temp; - temp.Mul(temp2); - temp.Sub(temp2); - // temp = m^2 - m - - denominator.Mul(temp); - // denominator = (m^2 - m) * n ^ (m-1) - - if( m >= cgamma.bern.size() ) - { - if( !SetBernoulliNumbers(cgamma, m - cgamma.bern.size() + 1 + 3, stop) ) // 3 more than needed - { - // there was the stop signal - err = err_interrupt; - return ValueType(); // NaN - } - } - - temp = cgamma.bern[m]; - temp.Div(denominator); - - oldsum = sum; - sum.Add(temp); - - if( sum.IsNan() || oldsum==sum ) - break; - } - - return sum; - } - - - /*! - an auxiliary function used to calculate the Gamma() function - - we calculate a helper function GammaFactorialHigh() by using Stirling's series: - n! = (n/e)^n * sqrt(2*pi*n) * exp( sum(n) ) - where n is a real number (not only an integer) and is sufficient large (greater than TTMATH_GAMMA_BOUNDARY) - and sum(n) is calculated by GammaFactorialHighSum() - */ - template - ValueType GammaFactorialHigh(const ValueType & n, CGamma & cgamma, ErrorCode & err, - const volatile StopCalculating * stop) - { - ValueType temp, temp2, temp3, denominator, sum; - - temp.Set2Pi(); - temp.Mul(n); - temp2 = Sqrt(temp); - // temp2 = sqrt(2*pi*n) - - temp = n; - temp3.SetE(); - temp.Div(temp3); - temp.Pow(n); - // temp = (n/e)^n - - sum = GammaFactorialHighSum(n, cgamma, err, stop); - temp3.Exp(sum); - // temp3 = exp(sum) - - temp.Mul(temp2); - temp.Mul(temp3); - - return temp; - } - - - /*! - an auxiliary function used to calculate the Gamma() function - - Gamma(x) = GammaFactorialHigh(x-1) - */ - template - ValueType GammaPlusHigh(ValueType n, CGamma & cgamma, ErrorCode & err, const volatile StopCalculating * stop) - { - ValueType one; - - one.SetOne(); - n.Sub(one); - - return GammaFactorialHigh(n, cgamma, err, stop); - } - - - /*! - an auxiliary function used to calculate the Gamma() function - - we use this function when n is integer and a small value (from 0 to TTMATH_GAMMA_BOUNDARY] - we use the formula: - gamma(n) = (n-1)! = 1 * 2 * 3 * ... * (n-1) - */ - template - ValueType GammaPlusLowIntegerInt(uint n, CGamma & cgamma) - { - TTMATH_ASSERT( n > 0 ) - - if( n - 1 < static_cast(cgamma.fact.size()) ) - return cgamma.fact[n - 1]; - - ValueType res; - uint start = 2; - - if( cgamma.fact.size() < 2 ) - { - res.SetOne(); - } - else - { - start = static_cast(cgamma.fact.size()); - res = cgamma.fact[start-1]; - } - - for(uint i=start ; i - ValueType GammaPlusLowInteger(const ValueType & n, CGamma & cgamma) - { - sint n_; - - n.ToInt(n_); - - return GammaPlusLowIntegerInt(n_, cgamma); - } - - - /*! - an auxiliary function used to calculate the Gamma() function - - we use this function when n is a small value (from 0 to TTMATH_GAMMA_BOUNDARY] - we use a recurrence formula: - gamma(z+1) = z * gamma(z) - then: gamma(z) = gamma(z+1) / z - - e.g. - gamma(3.89) = gamma(2001.89) / ( 3.89 * 4.89 * 5.89 * ... * 1999.89 * 2000.89 ) - */ - template - ValueType GammaPlusLow(ValueType n, CGamma & cgamma, ErrorCode & err, const volatile StopCalculating * stop) - { - ValueType one, denominator, temp, boundary; - - if( n.IsInteger() ) - return GammaPlusLowInteger(n, cgamma); - - one.SetOne(); - denominator = n; - boundary = TTMATH_GAMMA_BOUNDARY; - - while( n < boundary ) - { - n.Add(one); - denominator.Mul(n); - } - - n.Add(one); - - // now n is sufficient big - temp = GammaPlusHigh(n, cgamma, err, stop); - temp.Div(denominator); - - return temp; - } - - - /*! - an auxiliary function used to calculate the Gamma() function - */ - template - ValueType GammaPlus(const ValueType & n, CGamma & cgamma, ErrorCode & err, const volatile StopCalculating * stop) - { - if( n > TTMATH_GAMMA_BOUNDARY ) - return GammaPlusHigh(n, cgamma, err, stop); - - return GammaPlusLow(n, cgamma, err, stop); - } - - - /*! - an auxiliary function used to calculate the Gamma() function - - this function is used when n is negative - we use the reflection formula: - gamma(1-z) * gamma(z) = pi / sin(pi*z) - then: gamma(z) = pi / (sin(pi*z) * gamma(1-z)) - - */ - template - ValueType GammaMinus(const ValueType & n, CGamma & cgamma, ErrorCode & err, const volatile StopCalculating * stop) - { - ValueType pi, denominator, temp, temp2; - - if( n.IsInteger() ) - { - // gamma function is not defined when n is negative and integer - err = err_improper_argument; - return temp; // NaN - } - - pi.SetPi(); - - temp = pi; - temp.Mul(n); - temp2 = Sin(temp); - // temp2 = sin(pi * n) - - temp.SetOne(); - temp.Sub(n); - temp = GammaPlus(temp, cgamma, err, stop); - // temp = gamma(1 - n) - - temp.Mul(temp2); - pi.Div(temp); - - return pi; - } - - } // namespace auxiliaryfunctions - - - - /*! - this function calculates the Gamma function - - it's multithread safe, you should create a CGamma<> object and use it whenever you call the Gamma() - e.g. - typedef Big<1,2> MyBig; - MyBig x=234, y=345.53; - CGamma cgamma; - std::cout << Gamma(x, cgamma) << std::endl; - std::cout << Gamma(y, cgamma) << std::endl; - in the CGamma<> object the function stores some coefficients (factorials, Bernoulli numbers), - and they will be reused in next calls to the function - - each thread should have its own CGamma<> object, and you can use these objects with Factorial() function too - */ - template - ValueType Gamma(const ValueType & n, CGamma & cgamma, ErrorCode * err = 0, - const volatile StopCalculating * stop = 0) - { - using namespace auxiliaryfunctions; - - ValueType result; - ErrorCode err_tmp; - - if( n.IsNan() ) - { - if( err ) - *err = err_improper_argument; - - return n; - } - - if( cgamma.history.Get(n, result, err_tmp) ) - { - if( err ) - *err = err_tmp; - - return result; - } - - err_tmp = err_ok; - - if( n.IsSign() ) - { - result = GammaMinus(n, cgamma, err_tmp, stop); - } - else - if( n.IsZero() ) - { - err_tmp = err_improper_argument; - result.SetNan(); - } - else - { - result = GammaPlus(n, cgamma, err_tmp, stop); - } - - if( result.IsNan() && err_tmp==err_ok ) - err_tmp = err_overflow; - - if( err ) - *err = err_tmp; - - if( stop && !stop->WasStopSignal() ) - cgamma.history.Add(n, result, err_tmp); - - return result; - } - - - /*! - this function calculates the Gamma function - - note: this function should be used only in a single-thread environment - */ - template - ValueType Gamma(const ValueType & n, ErrorCode * err = 0) - { - // warning: this static object is not thread safe - static CGamma cgamma; - - return Gamma(n, cgamma, err); - } - - - - namespace auxiliaryfunctions - { - - /*! - an auxiliary function for calculating the factorial function - - we use the formula: - x! = gamma(x+1) - */ - template - ValueType Factorial2(ValueType x, - CGamma * cgamma = 0, - ErrorCode * err = 0, - const volatile StopCalculating * stop = 0) - { - ValueType result, one; - - if( x.IsNan() || x.IsSign() || !x.IsInteger() ) - { - if( err ) - *err = err_improper_argument; - - x.SetNan(); - - return x; - } - - one.SetOne(); - x.Add(one); - - if( cgamma ) - return Gamma(x, *cgamma, err, stop); - - return Gamma(x, err); - } - - } // namespace auxiliaryfunctions - - - - /*! - the factorial from given 'x' - e.g. - Factorial(4) = 4! = 1*2*3*4 - - it's multithread safe, you should create a CGamma<> object and use it whenever you call the Factorial() - e.g. - typedef Big<1,2> MyBig; - MyBig x=234, y=54345; - CGamma cgamma; - std::cout << Factorial(x, cgamma) << std::endl; - std::cout << Factorial(y, cgamma) << std::endl; - in the CGamma<> object the function stores some coefficients (factorials, Bernoulli numbers), - and they will be reused in next calls to the function - - each thread should have its own CGamma<> object, and you can use these objects with Gamma() function too - */ - template - ValueType Factorial(const ValueType & x, CGamma & cgamma, ErrorCode * err = 0, - const volatile StopCalculating * stop = 0) - { - return auxiliaryfunctions::Factorial2(x, &cgamma, err, stop); - } - - - /*! - the factorial from given 'x' - e.g. - Factorial(4) = 4! = 1*2*3*4 - - note: this function should be used only in a single-thread environment - */ - template - ValueType Factorial(const ValueType & x, ErrorCode * err = 0) - { - return auxiliaryfunctions::Factorial2(x, (CGamma*)0, err, 0); - } - - - /*! - this method prepares some coefficients: factorials and Bernoulli numbers - stored in 'fact' and 'bern' objects - - we're defining the method here because we're using Gamma() function which - is not available in ttmathobjects.h - - read the doc info in ttmathobjects.h file where CGamma<> struct is declared - */ - template - void CGamma::InitAll() - { - ValueType x = TTMATH_GAMMA_BOUNDARY + 1; - - // history.Remove(x) removes only one object - // we must be sure that there are not others objects with the key 'x' - while( history.Remove(x) ) - { - } - - // the simplest way to initialize is to call the Gamma function with (TTMATH_GAMMA_BOUNDARY + 1) - // when x is larger then fewer coefficients we need - Gamma(x, *this); - } - - - -} // namespace - - -#ifdef _MSC_VER -//warning C4127: conditional expression is constant -#pragma warning( default: 4127 ) -//warning C4702: unreachable code -#pragma warning( default: 4702 ) -//warning C4800: forcing value to bool 'true' or 'false' (performance warning) -#pragma warning( default: 4800 ) -#endif - -#endif diff --git a/extern/ttmath/ttmathint.h b/extern/ttmath/ttmathint.h deleted file mode 100644 index 8ad0189f93..0000000000 --- a/extern/ttmath/ttmathint.h +++ /dev/null @@ -1,1917 +0,0 @@ -/* - * This file is a part of TTMath Bignum Library - * and is distributed under the (new) BSD licence. - * Author: Tomasz Sowa - */ - -/* - * Copyright (c) 2006-2011, Tomasz Sowa - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name Tomasz Sowa nor the names of contributors to this - * project may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - - - -#ifndef headerfilettmathint -#define headerfilettmathint - -/*! - \file ttmathint.h - \brief template class Int -*/ - -#include "ttmathuint.h" - -namespace ttmath -{ - - -/*! - \brief Int implements a big integer value with a sign - - value_size - how many bytes specify our value - on 32bit platforms: value_size=1 -> 4 bytes -> 32 bits - on 64bit platforms: value_size=1 -> 8 bytes -> 64 bits - value_size = 1,2,3,4,5,6.... -*/ -template -class Int : public UInt -{ -public: - - /*! - this method sets the max value which this class can hold - (all bits will be one besides the last one) - */ - void SetMax() - { - UInt::SetMax(); - UInt::table[value_size-1] = ~ TTMATH_UINT_HIGHEST_BIT; - } - - - /*! - this method sets the min value which this class can hold - (all bits will be zero besides the last one which is one) - */ - void SetMin() - { - UInt::SetZero(); - UInt::table[value_size-1] = TTMATH_UINT_HIGHEST_BIT; - } - - - /*! - this method sets -1 as the value - (-1 is equal the max value in an unsigned type) - */ - void SetSignOne() - { - UInt::SetMax(); - } - - - /*! - we change the sign of the value - - if it isn't possible to change the sign this method returns 1 - else return 0 and changing the sign - */ - uint ChangeSign() - { - /* - if the value is equal that one which has been returned from SetMin - (only the highest bit is set) that means we can't change sign - because the value is too big (bigger about one) - - e.g. when value_size = 1 and value is -2147483648 we can't change it to the - 2147483648 because the max value which can be held is 2147483647 - - we don't change the value and we're using this fact somewhere in some methods - (if we look on our value without the sign we get the correct value - eg. -2147483648 in Int<1> will be 2147483648 on the UInt<1> type) - */ - if( UInt::IsOnlyTheHighestBitSet() ) - return 1; - - UInt temp(*this); - UInt::SetZero(); - UInt::Sub(temp); - - return 0; - } - - - - /*! - this method sets the sign - - e.g. 1 -> -1 - -2 -> -2 - - from a positive value we make a negative value, - if the value is negative we do nothing - */ - void SetSign() - { - if( IsSign() ) - return; - - ChangeSign(); - } - - - - /*! - this method returns true if there's the sign - - (the highest bit will be converted to the bool) - */ - bool IsSign() const - { - return UInt::IsTheHighestBitSet(); - } - - - - /*! - it sets an absolute value - - it can return carry (1) (look on ChangeSign() for details) - */ - uint Abs() - { - if( !IsSign() ) - return 0; - - return ChangeSign(); - } - - - - - /*! - * - * basic mathematic functions - * - */ - -private: - - uint CorrectCarryAfterAdding(bool p1_is_sign, bool p2_is_sign) - { - if( !p1_is_sign && !p2_is_sign ) - { - if( UInt::IsTheHighestBitSet() ) - return 1; - } - - if( p1_is_sign && p2_is_sign ) - { - if( ! UInt::IsTheHighestBitSet() ) - return 1; - } - - return 0; - } - - -public: - - /*! - this method adds two value with a sign and returns a carry - - we're using methods from the base class because values are stored with U2 - we must only make the carry correction - - this = p1(=this) + p2 - - when p1>=0 i p2>=0 carry is set when the highest bit of value is set - when p1<0 i p2<0 carry is set when the highest bit of value is clear - when p1>=0 i p2<0 carry will never be set - when p1<0 i p2>=0 carry will never be set - */ - uint Add(const Int & ss2) - { - bool p1_is_sign = IsSign(); - bool p2_is_sign = ss2.IsSign(); - - UInt::Add(ss2); - - return CorrectCarryAfterAdding(p1_is_sign, p2_is_sign); - } - - - /*! - this method adds one *unsigned* word (at a specific position) - and returns a carry (if it was) - - look at a description in UInt<>::AddInt(...) - */ - uint AddInt(uint value, uint index = 0) - { - bool p1_is_sign = IsSign(); - - UInt::AddInt(value, index); - - return CorrectCarryAfterAdding(p1_is_sign, false); - } - - - /*! - this method adds two *unsigned* words to the existing value - and these words begin on the 'index' position - - index should be equal or smaller than value_size-2 (index <= value_size-2) - x1 - lower word, x2 - higher word - - look at a description in UInt<>::AddTwoInts(...) - */ - uint AddTwoInts(uint x2, uint x1, uint index) - { - bool p1_is_sign = IsSign(); - - UInt::AddTwoInts(x2, x1, index); - - return CorrectCarryAfterAdding(p1_is_sign, false); - } - -private: - - uint CorrectCarryAfterSubtracting(bool p1_is_sign, bool p2_is_sign) - { - if( !p1_is_sign && p2_is_sign ) - { - if( UInt::IsTheHighestBitSet() ) - return 1; - } - - if( p1_is_sign && !p2_is_sign ) - { - if( ! UInt::IsTheHighestBitSet() ) - return 1; - } - - return 0; - } - -public: - - /*! - this method subtracts two values with a sign - - we don't use the previous Add because the method ChangeSign can - sometimes return carry - - this = p1(=this) - p2 - - when p1>=0 i p2>=0 carry will never be set - when p1<0 i p2<0 carry will never be set - when p1>=0 i p2<0 carry is set when the highest bit of value is set - when p1<0 i p2>=0 carry is set when the highest bit of value is clear - */ - uint Sub(const Int & ss2) - { - bool p1_is_sign = IsSign(); - bool p2_is_sign = ss2.IsSign(); - - UInt::Sub(ss2); - - return CorrectCarryAfterSubtracting(p1_is_sign, p2_is_sign); - } - - - /*! - this method subtracts one *unsigned* word (at a specific position) - and returns a carry (if it was) - */ - uint SubInt(uint value, uint index = 0) - { - bool p1_is_sign = IsSign(); - - UInt::SubInt(value, index); - - return CorrectCarryAfterSubtracting(p1_is_sign, false); - } - - - /*! - this method adds one to the value and returns carry - */ - uint AddOne() - { - bool p1_is_sign = IsSign(); - - UInt::AddOne(); - - return CorrectCarryAfterAdding(p1_is_sign, false); - } - - - /*! - this method subtracts one from the value and returns carry - */ - uint SubOne() - { - bool p1_is_sign = IsSign(); - - UInt::SubOne(); - - return CorrectCarryAfterSubtracting(p1_is_sign, false); - } - - -private: - - - uint CheckMinCarry(bool ss1_is_sign, bool ss2_is_sign) - { - /* - we have to examine the sign of the result now - but if the result is with the sign then: - 1. if the signs were the same that means the result is too big - (the result must be without a sign) - 2. if the signs were different that means if the result - is different from that one which has been returned from SetMin() - that is carry (result too big) but if the result is equal SetMin() - there'll be ok (and the next SetSign will has no effect because - the value is actually negative -- look at description of that case - in ChangeSign()) - */ - if( IsSign() ) - { - if( ss1_is_sign != ss2_is_sign ) - { - /* - there can be one case where signs are different and - the result will be equal the value from SetMin() (only the highest bit is set) - (this situation is ok) - */ - if( !UInt::IsOnlyTheHighestBitSet() ) - return 1; - } - else - { - // signs were the same - return 1; - } - } - - return 0; - } - - -public: - - - /*! - multiplication: this = this * ss2 - - it can return a carry - */ - uint MulInt(sint ss2) - { - bool ss1_is_sign, ss2_is_sign; - uint c; - - ss1_is_sign = IsSign(); - - /* - we don't have to check the carry from Abs (values will be correct - because next we're using the method MulInt from the base class UInt - which is without a sign) - */ - Abs(); - - if( ss2 < 0 ) - { - ss2 = -ss2; - ss2_is_sign = true; - } - else - { - ss2_is_sign = false; - } - - c = UInt::MulInt((uint)ss2); - c += CheckMinCarry(ss1_is_sign, ss2_is_sign); - - if( ss1_is_sign != ss2_is_sign ) - SetSign(); - - return c; - } - - - - /*! - multiplication this = this * ss2 - - it returns carry if the result is too big - (we're using the method from the base class but we have to make - one correction in account of signs) - */ - uint Mul(Int ss2) - { - bool ss1_is_sign, ss2_is_sign; - uint c; - - ss1_is_sign = IsSign(); - ss2_is_sign = ss2.IsSign(); - - /* - we don't have to check the carry from Abs (values will be correct - because next we're using the method Mul from the base class UInt - which is without a sign) - */ - Abs(); - ss2.Abs(); - - c = UInt::Mul(ss2); - c += CheckMinCarry(ss1_is_sign, ss2_is_sign); - - if( ss1_is_sign != ss2_is_sign ) - SetSign(); - - return c; - } - - - /*! - division this = this / ss2 - returned values: - 0 - ok - 1 - division by zero - - for example: (result means 'this') - 20 / 3 --> result: 6 remainder: 2 - -20 / 3 --> result: -6 remainder: -2 - 20 / -3 --> result: -6 remainder: 2 - -20 / -3 --> result: 6 remainder: -2 - - in other words: this(old) = ss2 * this(new)(result) + remainder - */ - uint Div(Int ss2, Int * remainder = 0) - { - bool ss1_is_sign, ss2_is_sign; - - ss1_is_sign = IsSign(); - ss2_is_sign = ss2.IsSign(); - - /* - we don't have to test the carry from Abs as well as in Mul - */ - Abs(); - ss2.Abs(); - - uint c = UInt::Div(ss2, remainder); - - if( ss1_is_sign != ss2_is_sign ) - SetSign(); - - if( ss1_is_sign && remainder ) - remainder->SetSign(); - - return c; - } - - uint Div(const Int & ss2, Int & remainder) - { - return Div(ss2, &remainder); - } - - - /*! - division this = this / ss2 (ss2 is int) - returned values: - 0 - ok - 1 - division by zero - - for example: (result means 'this') - 20 / 3 --> result: 6 remainder: 2 - -20 / 3 --> result: -6 remainder: -2 - 20 / -3 --> result: -6 remainder: 2 - -20 / -3 --> result: 6 remainder: -2 - - in other words: this(old) = ss2 * this(new)(result) + remainder - */ - uint DivInt(sint ss2, sint * remainder = 0) - { - bool ss1_is_sign, ss2_is_sign; - - ss1_is_sign = IsSign(); - - /* - we don't have to test the carry from Abs as well as in Mul - */ - Abs(); - - if( ss2 < 0 ) - { - ss2 = -ss2; - ss2_is_sign = true; - } - else - { - ss2_is_sign = false; - } - - uint rem; - uint c = UInt::DivInt((uint)ss2, &rem); - - if( ss1_is_sign != ss2_is_sign ) - SetSign(); - - if( remainder ) - { - if( ss1_is_sign ) - *remainder = -sint(rem); - else - *remainder = sint(rem); - } - - return c; - } - - - uint DivInt(sint ss2, sint & remainder) - { - return DivInt(ss2, &remainder); - } - - -private: - - - /*! - power this = this ^ pow - this can be negative - pow is >= 0 - */ - uint Pow2(const Int & pow) - { - bool was_sign = IsSign(); - uint c = 0; - - if( was_sign ) - c += Abs(); - - uint c_temp = UInt::Pow(pow); - if( c_temp > 0 ) - return c_temp; // c_temp can be: 0, 1 or 2 - - if( was_sign && (pow.table[0] & 1) == 1 ) - // negative value to the power of odd number is negative - c += ChangeSign(); - - return (c==0)? 0 : 1; - } - - -public: - - - /*! - power this = this ^ pow - - return values: - 0 - ok - 1 - carry - 2 - incorrect arguments 0^0 or 0^(-something) - */ - uint Pow(Int pow) - { - if( !pow.IsSign() ) - return Pow2(pow); - - if( UInt::IsZero() ) - // if 'pow' is negative then - // 'this' must be different from zero - return 2; - - if( pow.ChangeSign() ) - return 1; - - Int t(*this); - uint c_temp = t.Pow2(pow); - if( c_temp > 0 ) - return c_temp; - - UInt::SetOne(); - if( Div(t) ) - return 1; - - return 0; - } - - - - /*! - * - * convertion methods - * - */ -private: - - - /*! - an auxiliary method for converting both from UInt and Int - */ - template - uint FromUIntOrInt(const UInt & p, bool UInt_type) - { - uint min_size = (value_size < argument_size)? value_size : argument_size; - uint i; - - for(i=0 ; i::table[i] = p.table[i]; - - - if( value_size > argument_size ) - { - uint fill; - - if( UInt_type ) - fill = 0; - else - fill = (p.table[argument_size-1] & TTMATH_UINT_HIGHEST_BIT)? - TTMATH_UINT_MAX_VALUE : 0; - - // 'this' is longer than 'p' - for( ; i::table[i] = fill; - } - else - { - uint test = (UInt::table[value_size-1] & TTMATH_UINT_HIGHEST_BIT)? - TTMATH_UINT_MAX_VALUE : 0; - - if( UInt_type && test!=0 ) - return 1; - - for( ; i type into this class - - this operation has mainly sense if the value from p - can be held in this type - - it returns a carry if the value 'p' is too big - */ - template - uint FromInt(const Int & p) - { - return FromUIntOrInt(p, false); - } - - - /*! - this method converts the sint type into this class - */ - uint FromInt(sint value) - { - uint fill = ( value<0 ) ? TTMATH_UINT_MAX_VALUE : 0; - - for(uint i=1 ; i::table[i] = fill; - - UInt::table[0] = uint(value); - - // there'll never be a carry here - return 0; - } - - - /*! - this method converts UInt into this class - */ - template - uint FromUInt(const UInt & p) - { - return FromUIntOrInt(p, true); - } - - - /*! - this method converts UInt into this class - */ - template - uint FromInt(const UInt & p) - { - return FromUIntOrInt(p, true); - } - - - /*! - this method converts the uint type into this class - */ - uint FromUInt(uint value) - { - for(uint i=1 ; i::table[i] = 0; - - UInt::table[0] = value; - - // there can be a carry here when the size of this value is equal one word - // and the 'value' has the highest bit set - if( value_size==1 && (value & TTMATH_UINT_HIGHEST_BIT)!=0 ) - return 1; - - return 0; - } - - - /*! - this method converts the uint type into this class - */ - uint FromInt(uint value) - { - return FromUInt(value); - } - - - /*! - the default assignment operator - */ -/* Int & operator=(const Int & p) - { - FromInt(p); - - return *this; - } - */ - - /*! - this operator converts an Int type to this class - - it doesn't return a carry - */ -/* template - Int & operator=(const Int & p) - { - FromInt(p); - - return *this; - } - */ - - /*! - this method converts the sint type to this class - */ - Int & operator=(sint i) - { - FromInt(i); - - return *this; - } - - - /*! - a constructor for converting the uint to this class - */ -/* Int(sint i) - { - FromInt(i); - } -*/ - - /*! - a copy constructor - */ -/* Int(const Int & u) - { - FromInt(u); - } -*/ - - /*! - a constructor for copying from another types - */ -/* template - Int(const Int & u) - { - // look that 'size' we still set as 'value_size' and not as u.value_size - FromInt(u); - } -*/ - - - /*! - this operator converts an UInt type to this class - - it doesn't return a carry - */ - template - Int & operator=(const UInt & p) - { - FromUInt(p); - - return *this; - } - - - /*! - this method converts the Uint type to this class - */ - Int & operator=(uint i) - { - FromUInt(i); - - return *this; - } - - - /*! - a constructor for converting the uint to this class - */ -/* Int(uint i) - { - FromUInt(i); - } -*/ - - /*! - a constructor for copying from another types - */ -/* template - Int(const UInt & u) - { - // look that 'size' we still set as 'value_size' and not as u.value_size - FromUInt(u); - } -*/ - - -#ifdef TTMATH_PLATFORM32 - - - /*! - this method converts unsigned 64 bit int type to this class - ***this method is created only on a 32bit platform*** - */ - uint FromUInt(ulint n) - { - uint c = UInt::FromUInt(n); - - if( c ) - return 1; - - if( value_size == 1 ) - return ((UInt::table[0] & TTMATH_UINT_HIGHEST_BIT) == 0) ? 0 : 1; - - if( value_size == 2 ) - return ((UInt::table[1] & TTMATH_UINT_HIGHEST_BIT) == 0) ? 0 : 1; - - return 0; - } - - - /*! - this method converts unsigned 64 bit int type to this class - ***this method is created only on a 32bit platform*** - */ - uint FromInt(ulint n) - { - return FromUInt(n); - } - - - /*! - this method converts signed 64 bit int type to this class - ***this method is created only on a 32bit platform*** - */ - uint FromInt(slint n) - { - uint mask = (n < 0) ? TTMATH_UINT_MAX_VALUE : 0; - - UInt::table[0] = (uint)(ulint)n; - - if( value_size == 1 ) - { - if( uint(ulint(n) >> 32) != mask ) - return 1; - - return ((UInt::table[0] & TTMATH_UINT_HIGHEST_BIT) == (mask & TTMATH_UINT_HIGHEST_BIT)) ? 0 : 1; - } - - UInt::table[1] = (uint)(ulint(n) >> 32); - - for(uint i=2 ; i::table[i] = mask; - - return 0; - } - - - /*! - this operator converts unsigned 64 bit int type to this class - ***this operator is created only on a 32bit platform*** - */ - Int & operator=(ulint n) - { - FromUInt(n); - - return *this; - } - - - /*! - a constructor for converting unsigned 64 bit int to this class - ***this constructor is created only on a 32bit platform*** - */ -/* Int(ulint n) - { - FromUInt(n); - } -*/ - - /*! - this operator converts signed 64 bit int type to this class - ***this operator is created only on a 32bit platform*** - */ - Int & operator=(slint n) - { - FromInt(n); - - return *this; - } - - - /*! - a constructor for converting signed 64 bit int to this class - ***this constructor is created only on a 32bit platform*** - */ -/* Int(slint n) - { - FromInt(n); - } -*/ -#endif - - - - -#ifdef TTMATH_PLATFORM64 - - /*! - this method converts 32 bit unsigned int type to this class - ***this operator is created only on a 64bit platform*** - */ - uint FromUInt(unsigned int i) - { - return FromUInt(uint(i)); - } - - - /*! - this method converts 32 bit unsigned int type to this class - ***this operator is created only on a 64bit platform*** - */ - uint FromInt(unsigned int i) - { - return FromUInt(i); - } - - - /*! - this method converts 32 bit signed int type to this class - ***this operator is created only on a 64bit platform*** - */ - uint FromInt(signed int i) - { - return FromInt(sint(i)); - } - - - /*! - this method converts 32 bit unsigned int type to this class - ***this operator is created only on a 64bit platform*** - */ - Int & operator=(unsigned int i) - { - FromUInt(i); - - return *this; - } - - - /*! - a constructor for converting 32 bit unsigned int to this class - ***this constructor is created only on a 64bit platform*** - */ -/* Int(unsigned int i) - { - FromUInt(i); - } -*/ - - /*! - this operator converts 32 bit signed int type to this class - ***this operator is created only on a 64bit platform*** - */ - Int & operator=(signed int i) - { - FromInt(i); - - return *this; - } - - - /*! - a constructor for converting 32 bit signed int to this class - ***this constructor is created only on a 64bit platform*** - */ -/* Int(signed int i) - { - FromInt(i); - } -*/ -#endif - - - - /*! - a constructor for converting string to this class (with the base=10) - */ -/* Int(const char * s) - { - FromString(s); - } -*/ - - /*! - a constructor for converting a string to this class (with the base=10) - */ -/* Int(const std::string & s) - { - FromString( s.c_str() ); - } -*/ - -#ifndef TTMATH_DONT_USE_WCHAR - - /*! - a constructor for converting string to this class (with the base=10) - */ - Int(const wchar_t * s) - { - FromString(s); - } - - - /*! - a constructor for converting a string to this class (with the base=10) - */ - Int(const std::wstring & s) - { - FromString( s.c_str() ); - } - -#endif - - - /*! - a default constructor - - we don't clear table etc. - */ -/* Int() - { - } -*/ - - /*! - the destructor - */ -/* ~Int() - { - } -*/ - - /*! - this method returns the lowest value from table with a sign - - we must be sure when we using this method whether the value - will hold in an sint type or not (the rest value from table must be zero or -1) - */ - sint ToInt() const - { - return sint( UInt::table[0] ); - } - - - /*! - this method converts the value to uint type - can return a carry if the value is too long to store it in uint type - */ - uint ToUInt(uint & result) const - { - uint c = UInt::ToUInt(result); - - if( value_size == 1 ) - return (result & TTMATH_UINT_HIGHEST_BIT) == 0 ? 0 : 1; - - return c; - } - - - /*! - this method converts the value to uint type - can return a carry if the value is too long to store it in uint type - */ - uint ToInt(uint & result) const - { - return ToUInt(result); - } - - - /*! - this method converts the value to sint type - can return a carry if the value is too long to store it in sint type - */ - uint ToInt(sint & result) const - { - result = sint( UInt::table[0] ); - uint mask = IsSign() ? TTMATH_UINT_MAX_VALUE : 0; - - if( (result & TTMATH_UINT_HIGHEST_BIT) != (mask & TTMATH_UINT_HIGHEST_BIT) ) - return 1; - - for(uint i=1 ; i::table[i] != mask ) - return 1; - - return 0; - } - - -#ifdef TTMATH_PLATFORM32 - - /*! - this method converts the value to ulint type (64 bit unsigned integer) - can return a carry if the value is too long to store it in ulint type - *** this method is created only on a 32 bit platform *** - */ - uint ToUInt(ulint & result) const - { - uint c = UInt::ToUInt(result); - - if( value_size == 1 ) - return (UInt::table[0] & TTMATH_UINT_HIGHEST_BIT) == 0 ? 0 : 1; - - if( value_size == 2 ) - return (UInt::table[1] & TTMATH_UINT_HIGHEST_BIT) == 0 ? 0 : 1; - - return c; - } - - - /*! - this method converts the value to ulint type (64 bit unsigned integer) - can return a carry if the value is too long to store it in ulint type - *** this method is created only on a 32 bit platform *** - */ - uint ToInt(ulint & result) const - { - return ToUInt(result); - } - - - /*! - this method converts the value to slint type (64 bit signed integer) - can return a carry if the value is too long to store it in slint type - *** this method is created only on a 32 bit platform *** - */ - uint ToInt(slint & result) const - { - if( value_size == 1 ) - { - result = slint(sint(UInt::table[0])); - } - else - { - uint low = UInt::table[0]; - uint high = UInt::table[1]; - - result = low; - result |= (ulint(high) << TTMATH_BITS_PER_UINT); - - uint mask = IsSign() ? TTMATH_UINT_MAX_VALUE : 0; - - if( (high & TTMATH_UINT_HIGHEST_BIT) != (mask & TTMATH_UINT_HIGHEST_BIT) ) - return 1; - - for(uint i=2 ; i::table[i] != mask ) - return 1; - } - - return 0; - } - -#endif - - - -#ifdef TTMATH_PLATFORM64 - - /*! - this method converts the value to a 32 bit unsigned integer - can return a carry if the value is too long to store it in this type - *** this method is created only on a 64 bit platform *** - */ - uint ToUInt(unsigned int & result) const - { - uint c = UInt::ToUInt(result); - - if( c || IsSign() ) - return 1; - - return 0; - } - - - /*! - this method converts the value to a 32 bit unsigned integer - can return a carry if the value is too long to store it in this type - *** this method is created only on a 64 bit platform *** - */ - uint ToInt(unsigned int & result) const - { - return ToUInt(result); - } - - - /*! - this method converts the value to a 32 bit signed integer - can return a carry if the value is too long to store it in this type - *** this method is created only on a 64 bit platform *** - */ - uint ToInt(int & result) const - { - uint first = UInt::table[0]; - - result = int(first); - uint mask = IsSign() ? TTMATH_UINT_MAX_VALUE : 0; - - if( (first >> 31) != (mask >> 31) ) - return 1; - - for(uint i=1 ; i::table[i] != mask ) - return 1; - - return 0; - } - -#endif - - - - /*! - an auxiliary method for converting to a string - */ - template - void ToStringBase(string_type & result, uint b = 10) const - { - if( IsSign() ) - { - Int temp(*this); - temp.Abs(); - temp.UInt::ToStringBase(result, b, true); - } - else - { - UInt::ToStringBase(result, b, false); - } - } - - /*! - this method converts the value to a string with a base equal 'b' - */ - void ToString(std::string & result, uint b = 10) const - { - return ToStringBase(result, b); - } - - - /*! - this method converts the value to a string with a base equal 'b' - */ - std::string ToString(uint b = 10) const - { - std::string result; - ToStringBase(result, b); - - return result; - } - - -#ifndef TTMATH_DONT_USE_WCHAR - - /*! - this method converts the value to a string with a base equal 'b' - */ - void ToString(std::wstring & result, uint b = 10) const - { - return ToStringBase(result, b); - } - - - /*! - this method converts the value to a string with a base equal 'b' - */ - std::wstring ToWString(uint b = 10) const - { - std::wstring result; - ToStringBase(result, b); - - return result; - } - -#endif - - - -private: - - /*! - an auxiliary method for converting from a string - */ - template - uint FromStringBase(const char_type * s, uint b = 10, const char_type ** after_source = 0, bool * value_read = 0) - { - bool is_sign = false; - - Misc::SkipWhiteCharacters(s); - - if( *s == '-' ) - { - is_sign = true; - Misc::SkipWhiteCharacters(++s); - } - else - if( *s == '+' ) - { - Misc::SkipWhiteCharacters(++s); - } - - if( UInt::FromString(s,b,after_source,value_read) ) - return 1; - - if( is_sign ) - { - Int mmin; - - mmin.SetMin(); - - /* - the reference to mmin will be automatically converted to the reference - to UInt type - (this value can be equal mmin -- look at a description in ChangeSign()) - */ - if( UInt::operator>( mmin ) ) - return 1; - - /* - if the value is equal mmin the method ChangeSign() does nothing (only returns 1 but we ignore it) - */ - ChangeSign(); - } - else - { - Int mmax; - - mmax.SetMax(); - - if( UInt::operator>( mmax ) ) - return 1; - } - - return 0; - } - - -public: - - /*! - this method converts a string into its value - it returns carry=1 if the value will be too big or an incorrect base 'b' is given - - string is ended with a non-digit value, for example: - "-12" will be translated to -12 - as well as: - "- 12foo" will be translated to -12 too - - existing first white characters will be ommited - (between '-' and a first digit can be white characters too) - - after_source (if exists) is pointing at the end of the parsed string - - value_read (if exists) tells whether something has actually been read (at least one digit) - */ - uint FromString(const char * s, uint b = 10, const char ** after_source = 0, bool * value_read = 0) - { - return FromStringBase(s, b, after_source, value_read); - } - - - /*! - this method converts a string into its value - */ - uint FromString(const wchar_t * s, uint b = 10, const wchar_t ** after_source = 0, bool * value_read = 0) - { - return FromStringBase(s, b, after_source, value_read); - } - - - /*! - this method converts a string into its value - it returns carry=1 if the value will be too big or an incorrect base 'b' is given - */ - uint FromString(const std::string & s, uint b = 10) - { - return FromString( s.c_str(), b ); - } - - - /*! - this operator converts a string into its value (with base = 10) - */ - Int & operator=(const char * s) - { - FromString(s); - - return *this; - } - - -#ifndef TTMATH_DONT_USE_WCHAR - - - /*! - this method converts a string into its value - it returns carry=1 if the value will be too big or an incorrect base 'b' is given - */ - uint FromString(const std::wstring & s, uint b = 10) - { - return FromString( s.c_str(), b ); - } - - - /*! - this operator converts a string into its value (with base = 10) - */ - Int & operator=(const wchar_t * s) - { - FromString(s); - - return *this; - } - - - /*! - this operator converts a string into its value (with base = 10) - */ - Int & operator=(const std::wstring & s) - { - FromString( s.c_str() ); - - return *this; - } - -#endif - - - /*! - this operator converts a string into its value (with base = 10) - */ - Int & operator=(const std::string & s) - { - FromString( s.c_str() ); - - return *this; - } - - - - /*! - * - * methods for comparing - * - * - */ - - bool operator==(const Int & l) const - { - return UInt::operator==(l); - } - - bool operator!=(const Int & l) const - { - return UInt::operator!=(l); - } - - bool operator<(const Int & l) const - { - sint i=value_size-1; - - sint a1 = sint(UInt::table[i]); - sint a2 = sint(l.table[i]); - - if( a1 != a2 ) - return a1 < a2; - - - for(--i ; i>=0 ; --i) - { - if( UInt::table[i] != l.table[i] ) - // comparison as unsigned int - return UInt::table[i] < l.table[i]; - } - - // they're equal - return false; - } - - - bool operator>(const Int & l) const - { - sint i=value_size-1; - - sint a1 = sint(UInt::table[i]); - sint a2 = sint(l.table[i]); - - if( a1 != a2 ) - return a1 > a2; - - - for(--i ; i>=0 ; --i) - { - if( UInt::table[i] != l.table[i] ) - // comparison as unsigned int - return UInt::table[i] > l.table[i]; - } - - // they're equal - return false; - } - - - bool operator<=(const Int & l) const - { - sint i=value_size-1; - - sint a1 = sint(UInt::table[i]); - sint a2 = sint(l.table[i]); - - if( a1 != a2 ) - return a1 < a2; - - - for(--i ; i>=0 ; --i) - { - if( UInt::table[i] != l.table[i] ) - // comparison as unsigned int - return UInt::table[i] < l.table[i]; - } - - // they're equal - return true; - } - - - bool operator>=(const Int & l) const - { - sint i=value_size-1; - - sint a1 = sint(UInt::table[i]); - sint a2 = sint(l.table[i]); - - if( a1 != a2 ) - return a1 > a2; - - - for(--i ; i>=0 ; --i) - { - if( UInt::table[i] != l.table[i] ) - // comparison as unsigned int - return UInt::table[i] > l.table[i]; - } - - // they're equal - return true; - } - - - - /*! - * - * standard mathematical operators - * - */ - - - /*! - an operator for changing the sign - - it's not changing 'this' but the changed value will be returned - */ - Int operator-() const - { - Int temp(*this); - - temp.ChangeSign(); - - return temp; - } - - - Int operator-(const Int & p2) const - { - Int temp(*this); - - temp.Sub(p2); - - return temp; - } - - - Int & operator-=(const Int & p2) - { - Sub(p2); - - return *this; - } - - - Int operator+(const Int & p2) const - { - Int temp(*this); - - temp.Add(p2); - - return temp; - } - - - Int & operator+=(const Int & p2) - { - Add(p2); - - return *this; - } - - - Int operator*(const Int & p2) const - { - Int temp(*this); - - temp.Mul(p2); - - return temp; - } - - - Int & operator*=(const Int & p2) - { - Mul(p2); - - return *this; - } - - - Int operator/(const Int & p2) const - { - Int temp(*this); - - temp.Div(p2); - - return temp; - } - - - Int & operator/=(const Int & p2) - { - Div(p2); - - return *this; - } - - - Int operator%(const Int & p2) const - { - Int temp(*this); - Int remainder; - - temp.Div(p2, remainder); - - return remainder; - } - - - Int & operator%=(const Int & p2) - { - Int remainder; - - Div(p2, remainder); - operator=(remainder); - - return *this; - } - - - /*! - Prefix operator e.g. ++variable - */ - UInt & operator++() - { - AddOne(); - - return *this; - } - - - /*! - Postfix operator e.g. variable++ - */ - UInt operator++(int) - { - UInt temp( *this ); - - AddOne(); - - return temp; - } - - - UInt & operator--() - { - SubOne(); - - return *this; - } - - - UInt operator--(int) - { - UInt temp( *this ); - - SubOne(); - - return temp; - } - - - - /*! - * - * input/output operators for standard streams - * - */ - -private: - - /*! - an auxiliary method for outputing to standard streams - */ - template - static ostream_type & OutputToStream(ostream_type & s, const Int & l) - { - string_type ss; - - l.ToString(ss); - s << ss; - - return s; - } - - - -public: - - - /*! - output to standard streams - */ - friend std::ostream & operator<<(std::ostream & s, const Int & l) - { - return OutputToStream(s, l); - } - - -#ifndef TTMATH_DONT_USE_WCHAR - - /*! - output to standard streams - */ - friend std::wostream & operator<<(std::wostream & s, const Int & l) - { - return OutputToStream(s, l); - } - -#endif - - - -private: - - /*! - an auxiliary method for converting from a string - */ - template - static istream_type & InputFromStream(istream_type & s, Int & l) - { - string_type ss; - - // char or wchar_t for operator>> - char_type z; - - // operator>> omits white characters if they're set for ommiting - s >> z; - - if( z=='-' || z=='+' ) - { - ss += z; - s >> z; // we're reading a next character (white characters can be ommited) - } - - // we're reading only digits (base=10) - while( s.good() && Misc::CharToDigit(z, 10)>=0 ) - { - ss += z; - z = static_cast(s.get()); - } - - // we're leaving the last readed character - // (it's not belonging to the value) - s.unget(); - - l.FromString(ss); - - return s; - } - - -public: - - /*! - input from standard streams - */ - friend std::istream & operator>>(std::istream & s, Int & l) - { - return InputFromStream(s, l); - } - - -#ifndef TTMATH_DONT_USE_WCHAR - - /*! - input from standard streams - */ - friend std::wistream & operator>>(std::wistream & s, Int & l) - { - return InputFromStream(s, l); - } -#endif - - -}; - -} // namespace - -#endif diff --git a/extern/ttmath/ttmathmisc.h b/extern/ttmath/ttmathmisc.h deleted file mode 100644 index 330a43a468..0000000000 --- a/extern/ttmath/ttmathmisc.h +++ /dev/null @@ -1,250 +0,0 @@ -/* - * This file is a part of TTMath Bignum Library - * and is distributed under the (new) BSD licence. - * Author: Tomasz Sowa - */ - -/* - * Copyright (c) 2006-2010, Tomasz Sowa - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name Tomasz Sowa nor the names of contributors to this - * project may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef headerfilettmathmisc -#define headerfilettmathmisc - - -/*! - \file ttmathmisc.h - \brief some helpful functions -*/ - - -#include - - -namespace ttmath -{ - -/*! - some helpful functions -*/ -class Misc -{ -public: - - -/* - * - * AssignString(result, str) - * result = str - * - */ - -/*! - result = str -*/ -static void AssignString(std::string & result, const char * str) -{ - result = str; -} - - -#ifndef TTMATH_DONT_USE_WCHAR - -/*! - result = str -*/ -static void AssignString(std::wstring & result, const char * str) -{ - result.clear(); - - for( ; *str ; ++str ) - result += *str; -} - - -/*! - result = str -*/ -static void AssignString(std::wstring & result, const std::string & str) -{ - return AssignString(result, str.c_str()); -} - - -/*! - result = str -*/ -static void AssignString(std::string & result, const wchar_t * str) -{ - result.clear(); - - for( ; *str ; ++str ) - result += static_cast(*str); -} - - -/*! - result = str -*/ -static void AssignString(std::string & result, const std::wstring & str) -{ - return AssignString(result, str.c_str()); -} - -#endif - - -/* - * - * AddString(result, str) - * result += str - * - */ - - -/*! - result += str -*/ -static void AddString(std::string & result, const char * str) -{ - result += str; -} - - -#ifndef TTMATH_DONT_USE_WCHAR - -/*! - result += str -*/ -static void AddString(std::wstring & result, const char * str) -{ - for( ; *str ; ++str ) - result += *str; -} - -#endif - - -/* - this method omits any white characters from the string - char_type is char or wchar_t -*/ -template -static void SkipWhiteCharacters(const char_type * & c) -{ - // 13 is at the end in a DOS text file (\r\n) - while( (*c==' ' ) || (*c=='\t') || (*c==13 ) || (*c=='\n') ) - ++c; -} - - - - -/*! - this static method converts one character into its value - - for example: - 1 -> 1 - 8 -> 8 - A -> 10 - f -> 15 - - this method don't check whether c is correct or not -*/ -static uint CharToDigit(uint c) -{ - if(c>='0' && c<='9') - return c-'0'; - - if(c>='a' && c<='z') - return c-'a'+10; - -return c-'A'+10; -} - - -/*! - this method changes a character 'c' into its value - (if there can't be a correct value it returns -1) - - for example: - c=2, base=10 -> function returns 2 - c=A, base=10 -> function returns -1 - c=A, base=16 -> function returns 10 -*/ -static sint CharToDigit(uint c, uint base) -{ - if( c>='0' && c<='9' ) - c=c-'0'; - else - if( c>='a' && c<='z' ) - c=c-'a'+10; - else - if( c>='A' && c<='Z' ) - c=c-'A'+10; - else - return -1; - - - if( c >= base ) - return -1; - - -return sint(c); -} - - - -/*! - this method converts a digit into a char - digit should be from <0,F> - (we don't have to get a base) - - for example: - 1 -> 1 - 8 -> 8 - 10 -> A - 15 -> F -*/ -static uint DigitToChar(uint digit) -{ - if( digit < 10 ) - return digit + '0'; - -return digit - 10 + 'A'; -} - - -}; // struct Misc - -} - - -#endif diff --git a/extern/ttmath/ttmathobjects.h b/extern/ttmath/ttmathobjects.h deleted file mode 100644 index c35026bbd0..0000000000 --- a/extern/ttmath/ttmathobjects.h +++ /dev/null @@ -1,809 +0,0 @@ -/* - * This file is a part of TTMath Mathematical Library - * and is distributed under the (new) BSD licence. - * Author: Tomasz Sowa - */ - -/* - * Copyright (c) 2006-2010, Tomasz Sowa - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name Tomasz Sowa nor the names of contributors to this - * project may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - - -#ifndef headerfilettmathobject -#define headerfilettmathobject - -/*! - \file ttmathobjects.h - \brief Mathematic functions. -*/ - -#include -#include -#include -#include - -#include "ttmathtypes.h" -#include "ttmathmisc.h" - - -namespace ttmath -{ - -/*! - objects of this class are used with the mathematical parser - they hold variables or functions defined by a user - - each object has its own table in which we're keeping variables or functions -*/ -class Objects -{ -public: - - - /*! - one item (variable or function) - 'items' will be on the table - */ - struct Item - { - // name of a variable of a function - // internally we store variables and funcions as std::string (not std::wstring even when wide characters are used) - std::string value; - - // number of parameters required by the function - // (if there's a variable this 'param' is ignored) - int param; - - Item() {} - Item(const std::string & v, int p) : value(v), param(p) {} - }; - - // 'Table' is the type of our table - typedef std::map Table; - typedef Table::iterator Iterator; - typedef Table::const_iterator CIterator; - - - - /*! - this method returns true if a character 'c' is a character - which can be in a name - - if 'can_be_digit' is true that means when the 'c' is a digit this - method returns true otherwise it returns false - */ - static bool CorrectCharacter(int c, bool can_be_digit) - { - if( (c>='a' && c<='z') || (c>='A' && c<='Z') ) - return true; - - if( can_be_digit && ((c>='0' && c<='9') || c=='_') ) - return true; - - return false; - } - - - /*! - this method returns true if the name can be as a name of an object - */ - template - static bool IsNameCorrect(const string_type & name) - { - if( name.empty() ) - return false; - - if( !CorrectCharacter(name[0], false) ) - return false; - - typename string_type::const_iterator i = name.begin(); - - for(++i ; i!=name.end() ; ++i) - if( !CorrectCharacter(*i, true) ) - return false; - - return true; - } - - - /*! - this method returns true if such an object is defined (name exists) - */ - bool IsDefined(const std::string & name) - { - Iterator i = table.find(name); - - if( i != table.end() ) - // we have this object in our table - return true; - - return false; - } - - - -#ifndef TTMATH_DONT_USE_WCHAR - - /*! - this method returns true if such an object is defined (name exists) - */ - bool IsDefined(const std::wstring & name) - { - // we should check whether the name (in wide characters) are correct - // before calling AssignString() function - if( !IsNameCorrect(name) ) - return false; - - Misc::AssignString(str_tmp1, name); - - return IsDefined(str_tmp1); - } - -#endif - - - /*! - this method adds one object (variable of function) into the table - */ - ErrorCode Add(const std::string & name, const std::string & value, int param = 0) - { - if( !IsNameCorrect(name) ) - return err_incorrect_name; - - Iterator i = table.find(name); - - if( i != table.end() ) - // we have this object in our table - return err_object_exists; - - table.insert( std::make_pair(name, Item(value, param)) ); - - return err_ok; - } - - -#ifndef TTMATH_DONT_USE_WCHAR - - /*! - this method adds one object (variable of function) into the table - */ - ErrorCode Add(const std::wstring & name, const std::wstring & value, int param = 0) - { - // we should check whether the name (in wide characters) are correct - // before calling AssignString() function - if( !IsNameCorrect(name) ) - return err_incorrect_name; - - Misc::AssignString(str_tmp1, name); - Misc::AssignString(str_tmp2, value); - - return Add(str_tmp1, str_tmp2, param); - } - -#endif - - - /*! - this method returns 'true' if the table is empty - */ - bool Empty() const - { - return table.empty(); - } - - - /*! - this method clears the table - */ - void Clear() - { - return table.clear(); - } - - - /*! - this method returns 'const_iterator' on the first item on the table - */ - CIterator Begin() const - { - return table.begin(); - } - - - /*! - this method returns 'const_iterator' pointing at the space after last item - (returns table.end()) - */ - CIterator End() const - { - return table.end(); - } - - - /*! - this method changes the value and the number of parameters for a specific object - */ - ErrorCode EditValue(const std::string & name, const std::string & value, int param = 0) - { - if( !IsNameCorrect(name) ) - return err_incorrect_name; - - Iterator i = table.find(name); - - if( i == table.end() ) - return err_unknown_object; - - i->second.value = value; - i->second.param = param; - - return err_ok; - } - - -#ifndef TTMATH_DONT_USE_WCHAR - - - /*! - this method changes the value and the number of parameters for a specific object - */ - ErrorCode EditValue(const std::wstring & name, const std::wstring & value, int param = 0) - { - // we should check whether the name (in wide characters) are correct - // before calling AssignString() function - if( !IsNameCorrect(name) ) - return err_incorrect_name; - - Misc::AssignString(str_tmp1, name); - Misc::AssignString(str_tmp2, value); - - return EditValue(str_tmp1, str_tmp2, param); - } - -#endif - - - /*! - this method changes the name of a specific object - */ - ErrorCode EditName(const std::string & old_name, const std::string & new_name) - { - if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) ) - return err_incorrect_name; - - Iterator old_i = table.find(old_name); - if( old_i == table.end() ) - return err_unknown_object; - - if( old_name == new_name ) - // the new name is the same as the old one - // we treat it as a normal situation - return err_ok; - - ErrorCode err = Add(new_name, old_i->second.value, old_i->second.param); - - if( err == err_ok ) - { - old_i = table.find(old_name); - TTMATH_ASSERT( old_i != table.end() ) - - table.erase(old_i); - } - - return err; - } - - - -#ifndef TTMATH_DONT_USE_WCHAR - - - /*! - this method changes the name of a specific object - */ - ErrorCode EditName(const std::wstring & old_name, const std::wstring & new_name) - { - // we should check whether the name (in wide characters) are correct - // before calling AssignString() function - if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) ) - return err_incorrect_name; - - Misc::AssignString(str_tmp1, old_name); - Misc::AssignString(str_tmp2, new_name); - - return EditName(str_tmp1, str_tmp2); - } - -#endif - - - /*! - this method deletes an object - */ - ErrorCode Delete(const std::string & name) - { - if( !IsNameCorrect(name) ) - return err_incorrect_name; - - Iterator i = table.find(name); - - if( i == table.end() ) - return err_unknown_object; - - table.erase( i ); - - return err_ok; - } - - -#ifndef TTMATH_DONT_USE_WCHAR - - - /*! - this method deletes an object - */ - ErrorCode Delete(const std::wstring & name) - { - // we should check whether the name (in wide characters) are correct - // before calling AssignString() function - if( !IsNameCorrect(name) ) - return err_incorrect_name; - - Misc::AssignString(str_tmp1, name); - - return Delete(str_tmp1); - } - -#endif - - - /*! - this method gets the value of a specific object - */ - ErrorCode GetValue(const std::string & name, std::string & value) const - { - if( !IsNameCorrect(name) ) - return err_incorrect_name; - - CIterator i = table.find(name); - - if( i == table.end() ) - { - value.clear(); - return err_unknown_object; - } - - value = i->second.value; - - return err_ok; - } - - -#ifndef TTMATH_DONT_USE_WCHAR - - /*! - this method gets the value of a specific object - */ - ErrorCode GetValue(const std::wstring & name, std::wstring & value) - { - // we should check whether the name (in wide characters) are correct - // before calling AssignString() function - if( !IsNameCorrect(name) ) - return err_incorrect_name; - - Misc::AssignString(str_tmp1, name); - ErrorCode err = GetValue(str_tmp1, str_tmp2); - Misc::AssignString(value, str_tmp2); - - return err; - } - -#endif - - - /*! - this method gets the value of a specific object - (this version is used for not copying the whole string) - */ - ErrorCode GetValue(const std::string & name, const char ** value) const - { - if( !IsNameCorrect(name) ) - return err_incorrect_name; - - CIterator i = table.find(name); - - if( i == table.end() ) - { - *value = 0; - return err_unknown_object; - } - - *value = i->second.value.c_str(); - - return err_ok; - } - - -#ifndef TTMATH_DONT_USE_WCHAR - - /*! - this method gets the value of a specific object - (this version is used for not copying the whole string) - */ - ErrorCode GetValue(const std::wstring & name, const char ** value) - { - // we should check whether the name (in wide characters) are correct - // before calling AssignString() function - if( !IsNameCorrect(name) ) - return err_incorrect_name; - - Misc::AssignString(str_tmp1, name); - - return GetValue(str_tmp1, value); - } - -#endif - - - /*! - this method gets the value and the number of parameters - of a specific object - */ - ErrorCode GetValueAndParam(const std::string & name, std::string & value, int * param) const - { - if( !IsNameCorrect(name) ) - return err_incorrect_name; - - CIterator i = table.find(name); - - if( i == table.end() ) - { - value.empty(); - *param = 0; - return err_unknown_object; - } - - value = i->second.value; - *param = i->second.param; - - return err_ok; - } - - -#ifndef TTMATH_DONT_USE_WCHAR - - /*! - this method gets the value and the number of parameters - of a specific object - */ - ErrorCode GetValueAndParam(const std::wstring & name, std::wstring & value, int * param) - { - // we should check whether the name (in wide characters) are correct - // before calling AssignString() function - if( !IsNameCorrect(name) ) - return err_incorrect_name; - - Misc::AssignString(str_tmp1, name); - ErrorCode err = GetValueAndParam(str_tmp1, str_tmp2, param); - Misc::AssignString(value, str_tmp2); - - return err; - } - -#endif - - - /*! - this method sets the value and the number of parameters - of a specific object - (this version is used for not copying the whole string) - */ - ErrorCode GetValueAndParam(const std::string & name, const char ** value, int * param) const - { - if( !IsNameCorrect(name) ) - return err_incorrect_name; - - CIterator i = table.find(name); - - if( i == table.end() ) - { - *value = 0; - *param = 0; - return err_unknown_object; - } - - *value = i->second.value.c_str(); - *param = i->second.param; - - return err_ok; - } - - -#ifndef TTMATH_DONT_USE_WCHAR - - - /*! - this method sets the value and the number of parameters - of a specific object - (this version is used for not copying the whole string - but in fact we make one copying during AssignString()) - */ - ErrorCode GetValueAndParam(const std::wstring & name, const char ** value, int * param) - { - // we should check whether the name (in wide characters) are correct - // before calling AssignString() function - if( !IsNameCorrect(name) ) - return err_incorrect_name; - - Misc::AssignString(str_tmp1, name); - - return GetValueAndParam(str_tmp1, value, param); - } - - -#endif - - - /*! - this method returns a pointer into the table - */ - Table * GetTable() - { - return &table; - } - - -private: - - Table table; - std::string str_tmp1, str_tmp2; - -}; // end of class Objects - - - - - - - -/*! - objects of the class History are used to keep values in functions - which take a lot of time during calculating, for instance in the - function Factorial(x) - - it means that when we're calculating e.g. Factorial(1000) and the - Factorial finds that we have calculated it before, the value (result) - is taken from the history -*/ -template -class History -{ - /*! - one item in the History's object holds a key, a value for the key - and a corresponding error code - */ - struct Item - { - ValueType key, value; - ErrorCode err; - }; - - - /*! - we use std::list for simply deleting the first item - but because we're searching through the whole container - (in the method Get) the container should not be too big - (linear time of searching) - */ - typedef std::list buffer_type; - buffer_type buffer; - typename buffer_type::size_type buffer_max_size; - -public: - - /*! - default constructor - default max size of the History's container is 15 items - */ - History() - { - buffer_max_size = 15; - } - - - /*! - a constructor which takes another value of the max size - of the History's container - */ - History(typename buffer_type::size_type new_size) - { - buffer_max_size = new_size; - } - - - /*! - this method adds one item into the History - if the size of the container is greater than buffer_max_size - the first item will be removed - */ - void Add(const ValueType & key, const ValueType & value, ErrorCode err) - { - Item item; - item.key = key; - item.value = value; - item.err = err; - - buffer.insert( buffer.end(), item ); - - if( buffer.size() > buffer_max_size ) - buffer.erase(buffer.begin()); - } - - - /*! - this method checks whether we have an item which has the key equal 'key' - - if there's such item the method sets the 'value' and the 'err' - and returns true otherwise it returns false and 'value' and 'err' - remain unchanged - */ - bool Get(const ValueType & key, ValueType & value, ErrorCode & err) - { - typename buffer_type::iterator i = buffer.begin(); - - for( ; i != buffer.end() ; ++i ) - { - if( i->key == key ) - { - value = i->value; - err = i->err; - return true; - } - } - - return false; - } - - - /*! - this methods deletes an item - - we assume that there is only one item with the 'key' - (this methods removes the first one) - */ - bool Remove(const ValueType & key) - { - typename buffer_type::iterator i = buffer.begin(); - - for( ; i != buffer.end() ; ++i ) - { - if( i->key == key ) - { - buffer.erase(i); - return true; - } - } - - return false; - } - - -}; // end of class History - - - -/*! - this is an auxiliary class used when calculating Gamma() or Factorial() - - in multithreaded environment you can provide an object of this class to - the Gamma() or Factorial() function, e.g; - typedef Big<1, 3> MyBig; - MyBig x = 123456; - CGamma cgamma; - std::cout << Gamma(x, cgamma); - each thread should have its own CGamma<> object - - in a single-thread environment a CGamma<> object is a static variable - in a second version of Gamma() and you don't have to explicitly use it, e.g. - typedef Big<1, 3> MyBig; - MyBig x = 123456; - std::cout << Gamma(x); -*/ -template -struct CGamma -{ - /*! - this table holds factorials - 1 - 1 - 2 - 6 - 24 - 120 - 720 - ....... - */ - std::vector fact; - - - /*! - this table holds Bernoulli numbers - 1 - -0.5 - 0.166666666666666666666666667 - 0 - -0.0333333333333333333333333333 - 0 - 0.0238095238095238095238095238 - 0 - -0.0333333333333333333333333333 - 0 - 0.075757575757575757575757576 - ..... - */ - std::vector bern; - - - /*! - here we store some calculated values - (this is for speeding up, if the next argument of Gamma() or Factorial() - is in the 'history' then the result we are not calculating but simply - return from the 'history' object) - */ - History history; - - - /*! - this method prepares some coefficients: factorials and Bernoulli numbers - stored in 'fact' and 'bern' objects - - how many values should be depends on the size of the mantissa - if - the mantissa is larger then we must calculate more values - for a mantissa which consists of 256 bits (8 words on a 32bit platform) - we have to calculate about 30 values (the size of fact and bern will be 30), - and for a 2048 bits mantissa we have to calculate 306 coefficients - - you don't have to call this method, these coefficients will be automatically calculated - when they are needed - - you must note that calculating these coefficients is a little time-consuming operation, - (especially when the mantissa is large) and first call to Gamma() or Factorial() - can take more time than next calls, and in the end this is the point when InitAll() - comes in handy: you can call this method somewhere at the beginning of your program - */ - void InitAll(); - // definition is in ttmath.h -}; - - - - -} // namespace - -#endif diff --git a/extern/ttmath/ttmaththreads.h b/extern/ttmath/ttmaththreads.h deleted file mode 100644 index 586227f2fc..0000000000 --- a/extern/ttmath/ttmaththreads.h +++ /dev/null @@ -1,250 +0,0 @@ -/* - * This file is a part of TTMath Bignum Library - * and is distributed under the (new) BSD licence. - * Author: Tomasz Sowa - */ - -/* - * Copyright (c) 2006-2009, Tomasz Sowa - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name Tomasz Sowa nor the names of contributors to this - * project may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - - - -#ifndef headerfilettmaththreads -#define headerfilettmaththreads - -#include "ttmathtypes.h" - -#ifdef TTMATH_WIN32_THREADS -#include -#include -#endif - -#ifdef TTMATH_POSIX_THREADS -#include -#endif - - - -/*! - \file ttmaththreads.h - \brief Some objects used in multithreads environment -*/ - - -/* - this is a simple skeleton of a program in multithreads environment: - - #define TTMATH_MULTITHREADS - #include - - TTMATH_MULTITHREADS_HELPER - - int main() - { - [...] - } - - make sure that macro TTMATH_MULTITHREADS is defined and (somewhere in *.cpp file) - use TTMATH_MULTITHREADS_HELPER macro (outside of any classes/functions/namespaces scope) -*/ - - -namespace ttmath -{ - - -#ifdef TTMATH_WIN32_THREADS - - /* - we use win32 threads - */ - - - /*! - in multithreads environment you should use TTMATH_MULTITHREADS_HELPER macro - somewhere in *.cpp file - - (at the moment in win32 this macro does nothing) - */ - #define TTMATH_MULTITHREADS_HELPER - - - /*! - objects of this class are used to synchronize - */ - class ThreadLock - { - HANDLE mutex_handle; - - - void CreateName(char * buffer) const - { - #ifdef _MSC_VER - #pragma warning (disable : 4996) - // warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. - #endif - - sprintf(buffer, "TTMATH_LOCK_%ul", (unsigned long)GetCurrentProcessId()); - - #ifdef _MSC_VER - #pragma warning (default : 4996) - #endif - } - - - public: - - bool Lock() - { - char buffer[50]; - - CreateName(buffer); - mutex_handle = CreateMutexA(0, false, buffer); - - if( mutex_handle == 0 ) - return false; - - WaitForSingleObject(mutex_handle, INFINITE); - - return true; - } - - - ThreadLock() - { - mutex_handle = 0; - } - - - ~ThreadLock() - { - if( mutex_handle != 0 ) - { - ReleaseMutex(mutex_handle); - CloseHandle(mutex_handle); - } - } - }; - -#endif // #ifdef TTMATH_WIN32_THREADS - - - - - -#ifdef TTMATH_POSIX_THREADS - - /* - we use posix threads - */ - - - /*! - in multithreads environment you should use TTMATH_MULTITHREADS_HELPER macro - somewhere in *.cpp file - (this macro defines a pthread_mutex_t object used by TTMath library) - */ - #define TTMATH_MULTITHREADS_HELPER \ - namespace ttmath \ - { \ - pthread_mutex_t ttmath_mutex = PTHREAD_MUTEX_INITIALIZER; \ - } - - - /*! - ttmath_mutex will be defined by TTMATH_MULTITHREADS_HELPER macro - */ - extern pthread_mutex_t ttmath_mutex; - - - /*! - objects of this class are used to synchronize - */ - class ThreadLock - { - public: - - bool Lock() - { - if( pthread_mutex_lock(&ttmath_mutex) != 0 ) - return false; - - return true; - } - - - ~ThreadLock() - { - pthread_mutex_unlock(&ttmath_mutex); - } - }; - -#endif // #ifdef TTMATH_POSIX_THREADS - - - - -#if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS) - - /*! - we don't use win32 and pthreads - */ - - /*! - */ - #define TTMATH_MULTITHREADS_HELPER - - - /*! - objects of this class are used to synchronize - actually we don't synchronize, the method Lock() returns always 'false' - */ - class ThreadLock - { - public: - - bool Lock() - { - return false; - } - }; - - -#endif // #if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS) - - - - - -} // namespace - -#endif - diff --git a/extern/ttmath/ttmathtypes.h b/extern/ttmath/ttmathtypes.h deleted file mode 100644 index 3d9ddbe7b0..0000000000 --- a/extern/ttmath/ttmathtypes.h +++ /dev/null @@ -1,676 +0,0 @@ -/* - * This file is a part of TTMath Bignum Library - * and is distributed under the (new) BSD licence. - * Author: Tomasz Sowa - */ - -/* - * Copyright (c) 2006-2012, Tomasz Sowa - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name Tomasz Sowa nor the names of contributors to this - * project may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - - -#ifndef headerfilettmathtypes -#define headerfilettmathtypes - -/*! - \file ttmathtypes.h - \brief constants used in the library - - As our library is written in header files (templates) we cannot use - constants like 'const int' etc. because we should have some source files - *.cpp to define this variables. Only what we can have are constants - defined by #define preprocessor macros. - - All macros are preceded by TTMATH_ prefix -*/ - - -#include -#include -#include - -#ifndef _MSC_VER -#include -// for uint64_t and int64_t on a 32 bit platform -#endif - - - -/*! - the version of the library - - TTMATH_PRERELEASE_VER is either zero or one - zero means that this is the release version of the library - (one means something like beta) -*/ -#define TTMATH_MAJOR_VER 0 -#define TTMATH_MINOR_VER 9 -#define TTMATH_REVISION_VER 3 - -#define TTMATH_PRERELEASE_VER 0 - - - -/*! - you can define a platform explicitly by defining either - TTMATH_PLATFORM32 or TTMATH_PLATFORM64 macro -*/ -#if !defined TTMATH_PLATFORM32 && !defined TTMATH_PLATFORM64 - - #if !defined _M_X64 && !defined __x86_64__ - - /* - other platforms than x86 and amd64 are not recognized at the moment - so you should set TTMATH_PLATFORMxx manually - */ - - // we're using a 32bit platform - #define TTMATH_PLATFORM32 - - #else - - // we're using a 64bit platform - #define TTMATH_PLATFORM64 - - #endif - -#endif - - -/*! - asm version of the library is available by default only for: - x86 and amd64 platforms and for Microsoft Visual and GCC compilers - - but you can force using asm version (the same asm as for Microsoft Visual) - by defining TTMATH_FORCEASM macro - you have to be sure that your compiler accept such an asm format -*/ -#ifndef TTMATH_FORCEASM - - #if !defined __i386__ && !defined _X86_ && !defined _M_IX86 && !defined __x86_64__ && !defined _M_X64 - /*! - x86 architecture: - __i386__ defined by GNU C - _X86_ defined by MinGW32 - _M_IX86 defined by Visual Studio, Intel C/C++, Digital Mars and Watcom C/C++ - - amd64 architecture: - __x86_64__ defined by GNU C, CLANG (LLVM) and Sun Studio - _M_X64 defined by Visual Studio - - asm version is available only for x86 or amd64 platforms - */ - #define TTMATH_NOASM - #endif - - - - #if !defined _MSC_VER && !defined __GNUC__ - /*! - another compilers than MS VC or GCC or CLANG (LLVM) by default use no asm version - (CLANG defines __GNUC__ too) - */ - #define TTMATH_NOASM - #endif - -#endif - - -namespace ttmath -{ - - -#ifdef TTMATH_PLATFORM32 - - /*! - on 32bit platforms one word (uint, sint) will be equal 32bits - */ - typedef unsigned int uint; - typedef signed int sint; - - /*! - on 32 bit platform ulint and slint will be equal 64 bits - */ - #ifdef _MSC_VER - // long long on MS Windows (Visual and GCC mingw compilers) have 64 bits - // stdint.h is not available on Visual Studio prior to VS 2010 version - typedef unsigned long long int ulint; - typedef signed long long int slint; - #else - // we do not use 'long' here because there is a difference in unix and windows - // environments: in unix 'long' has 64 bits but in windows it has only 32 bits - typedef uint64_t ulint; - typedef int64_t slint; - #endif - - /*! - how many bits there are in the uint type - */ - #define TTMATH_BITS_PER_UINT 32u - - /*! - the mask for the highest bit in the unsigned 32bit word (2^31) - */ - #define TTMATH_UINT_HIGHEST_BIT 2147483648u - - /*! - the max value of the unsigned 32bit word (2^32 - 1) - (all bits equal one) - */ - #define TTMATH_UINT_MAX_VALUE 4294967295u - - /*! - the number of words (32bit words on 32bit platform) - which are kept in built-in variables for a Big<> type - (these variables are defined in ttmathbig.h) - */ - #define TTMATH_BUILTIN_VARIABLES_SIZE 256u - - /*! - this macro returns the number of machine words - capable to hold min_bits bits - e.g. TTMATH_BITS(128) returns 4 - */ - #define TTMATH_BITS(min_bits) ((min_bits-1)/32 + 1) - -#else - - /*! - on 64bit platforms one word (uint, sint) will be equal 64bits - */ - #ifdef _MSC_VER - /* in VC 'long' type has 32 bits, __int64 is VC extension */ - typedef unsigned __int64 uint; - typedef signed __int64 sint; - #else - typedef unsigned long uint; - typedef signed long sint; - #endif - - /*! - on 64bit platforms we do not define ulint and slint - */ - - /*! - how many bits there are in the uint type - */ - #define TTMATH_BITS_PER_UINT 64ul - - /*! - the mask for the highest bit in the unsigned 64bit word (2^63) - */ - #define TTMATH_UINT_HIGHEST_BIT 9223372036854775808ul - - /*! - the max value of the unsigned 64bit word (2^64 - 1) - (all bits equal one) - */ - #define TTMATH_UINT_MAX_VALUE 18446744073709551615ul - - /*! - the number of words (64bit words on 64bit platforms) - which are kept in built-in variables for a Big<> type - (these variables are defined in ttmathbig.h) - */ - #define TTMATH_BUILTIN_VARIABLES_SIZE 128ul - - /*! - this macro returns the number of machine words - capable to hold min_bits bits - e.g. TTMATH_BITS(128) returns 2 - */ - #define TTMATH_BITS(min_bits) ((min_bits-1)/64 + 1) - -#endif -} - - -#if defined(TTMATH_MULTITHREADS) && !defined(TTMATH_MULTITHREADS_NOSYNC) - #if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS) - - #if defined(_WIN32) - #define TTMATH_WIN32_THREADS - #elif defined(unix) || defined(__unix__) || defined(__unix) - #define TTMATH_POSIX_THREADS - #endif - - #endif -#endif - - - -/*! - this variable defines how many iterations are performed - during some kind of calculating when we're making any long formulas - (for example Taylor series) - - it's used in ExpSurrounding0(...), LnSurrounding1(...), Sin0pi05(...), etc. - - note! there'll not be so many iterations, iterations are stopped when - there is no sense to continue calculating (for example when the result - still remains unchanged after adding next series and we know that the next - series are smaller than previous ones) -*/ -#define TTMATH_ARITHMETIC_MAX_LOOP 10000 - - - -/*! - this is a limit when calculating Karatsuba multiplication - if the size of a vector is smaller than TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE - the Karatsuba algorithm will use standard schoolbook multiplication -*/ -#ifdef TTMATH_DEBUG_LOG - // if TTMATH_DEBUG_LOG is defined then we should use the same size regardless of the compiler - #define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 3 -#else - #ifdef __GNUC__ - #define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 3 - #else - #define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 5 - #endif -#endif - - -/*! - this is a special value used when calculating the Gamma(x) function - if x is greater than this value then the Gamma(x) will be calculated using - some kind of series - - don't use smaller values than about 100 -*/ -#define TTMATH_GAMMA_BOUNDARY 2000 - - - - - -namespace ttmath -{ - - /*! - lib type codes: - asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits) - asm_gcc_32 - with asm code designed for GCC (32 bits) - asm_vc_64 - with asm for VC (64 bit) - asm_gcc_64 - with asm for GCC (64 bit) - no_asm_32 - pure C++ version (32 bit) - without any asm code - no_asm_64 - pure C++ version (64 bit) - without any asm code - */ - enum LibTypeCode - { - asm_vc_32 = 0, - asm_gcc_32, - asm_vc_64, - asm_gcc_64, - no_asm_32, - no_asm_64 - }; - - - /*! - error codes - */ - enum ErrorCode - { - err_ok = 0, - err_nothing_has_read, - err_unknown_character, - err_unexpected_final_bracket, - err_stack_not_clear, - err_unknown_variable, - err_division_by_zero, - err_interrupt, - err_overflow, - err_unknown_function, - err_unknown_operator, - err_unexpected_semicolon_operator, - err_improper_amount_of_arguments, - err_improper_argument, - err_unexpected_end, - err_internal_error, - err_incorrect_name, - err_incorrect_value, - err_variable_exists, - err_variable_loop, - err_functions_loop, - err_must_be_only_one_value, - err_object_exists, - err_unknown_object, - err_still_calculating, - err_in_short_form_used_function, - err_percent_from - }; - - - /*! - this struct is used when converting to/from a string - /temporarily only in Big::ToString() and Big::FromString()/ - */ - struct Conv - { - /*! - base (radix) on which the value will be shown (or read) - default: 10 - */ - uint base; - - - /*! - used only in Big::ToString() - if true the value will be always shown in the scientific mode, e.g: 123e+30 - default: false - */ - bool scient; - - - /*! - used only in Big::ToString() - if scient is false then the value will be printed in the scientific mode - only if the exponent is greater than scien_from - default: 15 - */ - sint scient_from; - - - /*! - if 'base_round' is true and 'base' is different from 2, 4, 8, or 16 - and the result value is not an integer then we make an additional rounding - (after converting the last digit from the result is skipped) - default: true - - e.g. - Conv c; - c.base_round = false; - Big<1, 1> a = "0.1"; // decimal input - std::cout << a.ToString(c) << std::endl; // the result is: 0.099999999 - */ - bool base_round; - - - /*! - used only in Big::ToString() - tells how many digits after comma are possible - default: -1 which means all digits are printed - - set it to zero if you want integer value only - - for example when the value is: - 12.345678 and 'round' is 4 - then the result will be - 12.3457 (the last digit was rounded) - */ - sint round; - - - /*! - if true that not mattered digits in the mantissa will be cut off - (zero characters at the end -- after the comma operator) - e.g. 1234,78000 will be: 1234,78 - default: true - */ - bool trim_zeroes; - - - /*! - the main comma operator (used when reading and writing) - default is a dot '.' - */ - uint comma; - - - /*! - additional comma operator (used only when reading) - if you don't want it just set it to zero - default is a comma ',' - - this allowes you to convert from a value: - 123.45 as well as from 123,45 - */ - uint comma2; - - - /*! - it sets the character which is used for grouping - if group=' ' then: 1234,56789 will be printed as: 1 234,567 89 - - if you don't want grouping just set it to zero (which is default) - */ - uint group; - - - /*! - how many digits should be grouped (it is used if 'group' is non zero) - default: 3 - */ - uint group_digits; - - - /*! - */ - uint group_exp; // not implemented yet - - - - - Conv() - { - // default values - base = 10; - scient = false; - scient_from = 15; - base_round = true; - round = -1; - trim_zeroes = true; - comma = '.'; - comma2 = ','; - group = 0; - group_digits = 3; - group_exp = 0; - } - }; - - - - /*! - this simple class can be used in multithreading model - (you can write your own class derived from this one) - - for example: in some functions like Factorial() - /at the moment only Factorial/ you can give a pointer to - the 'stop object', if the method WasStopSignal() of this - object returns true that means we should break the calculating - and return - */ - class StopCalculating - { - public: - virtual bool WasStopSignal() const volatile { return false; } - virtual ~StopCalculating(){} - }; - - - /*! - a small class which is useful when compiling with gcc - - object of this type holds the name and the line of a file - in which the macro TTMATH_ASSERT or TTMATH_REFERENCE_ASSERT was used - */ - class ExceptionInfo - { - const char * file; - int line; - - public: - ExceptionInfo() : file(0), line(0) {} - ExceptionInfo(const char * f, int l) : file(f), line(l) {} - - std::string Where() const - { - if( !file ) - return "unknown"; - - std::ostringstream result; - result << file << ":" << line; - - return result.str(); - } - }; - - - /*! - A small class used for reporting 'reference' errors - - In the library is used macro TTMATH_REFERENCE_ASSERT which - can throw an exception of this type - - ** from version 0.9.2 this macro is removed from all methods - in public interface so you don't have to worry about it ** - - If you compile with gcc you can get a small benefit - from using method Where() (it returns std::string) with - the name and the line of a file where the macro TTMATH_REFERENCE_ASSERT - was used) - */ - class ReferenceError : public std::logic_error, public ExceptionInfo - { - public: - - ReferenceError() : std::logic_error("reference error") - { - } - - ReferenceError(const char * f, int l) : - std::logic_error("reference error"), ExceptionInfo(f,l) - { - } - - std::string Where() const - { - return ExceptionInfo::Where(); - } - }; - - - /*! - a small class used for reporting errors - - in the library is used macro TTMATH_ASSERT which - (if the condition in it is false) throw an exception - of this type - - if you compile with gcc you can get a small benefit - from using method Where() (it returns std::string) with - the name and the line of a file where the macro TTMATH_ASSERT - was used) - */ - class RuntimeError : public std::runtime_error, public ExceptionInfo - { - public: - - RuntimeError() : std::runtime_error("internal error") - { - } - - RuntimeError(const char * f, int l) : - std::runtime_error("internal error"), ExceptionInfo(f,l) - { - } - - std::string Where() const - { - return ExceptionInfo::Where(); - } - }; - - - - /*! - TTMATH_DEBUG - this macro enables further testing during writing your code - you don't have to define it in a release mode - - if this macro is set then macros TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT - are set as well and these macros can throw an exception if a condition in it - is not fulfilled (look at the definition of TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT) - - TTMATH_DEBUG is set automatically if DEBUG or _DEBUG are defined - */ - #if defined DEBUG || defined _DEBUG - #define TTMATH_DEBUG - #endif - - - #ifdef TTMATH_DEBUG - - #if defined(__FILE__) && defined(__LINE__) - - #define TTMATH_REFERENCE_ASSERT(expression) \ - if( &(expression) == this ) throw ttmath::ReferenceError(__FILE__, __LINE__); - - #define TTMATH_ASSERT(expression) \ - if( !(expression) ) throw ttmath::RuntimeError(__FILE__, __LINE__); - - #else - - #define TTMATH_REFERENCE_ASSERT(expression) \ - if( &(expression) == this ) throw ReferenceError(); - - #define TTMATH_ASSERT(expression) \ - if( !(expression) ) throw RuntimeError(); - #endif - - #else - #define TTMATH_REFERENCE_ASSERT(expression) - #define TTMATH_ASSERT(expression) - #endif - - - - #ifdef TTMATH_DEBUG_LOG - #define TTMATH_LOG(msg) PrintLog(msg, std::cout); - #define TTMATH_LOGC(msg, carry) PrintLog(msg, carry, std::cout); - #define TTMATH_VECTOR_LOG(msg, vector, len) PrintVectorLog(msg, std::cout, vector, len); - #define TTMATH_VECTOR_LOGC(msg, carry, vector, len) PrintVectorLog(msg, carry, std::cout, vector, len); - #else - #define TTMATH_LOG(msg) - #define TTMATH_LOGC(msg, carry) - #define TTMATH_VECTOR_LOG(msg, vector, len) - #define TTMATH_VECTOR_LOGC(msg, carry, vector, len) - #endif - - - - -} // namespace - - -#endif - diff --git a/extern/ttmath/ttmathuint.h b/extern/ttmath/ttmathuint.h deleted file mode 100644 index b9cf67cd11..0000000000 --- a/extern/ttmath/ttmathuint.h +++ /dev/null @@ -1,4126 +0,0 @@ -/* - * This file is a part of TTMath Bignum Library - * and is distributed under the (new) BSD licence. - * Author: Tomasz Sowa - */ - -/* - * Copyright (c) 2006-2011, Tomasz Sowa - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name Tomasz Sowa nor the names of contributors to this - * project may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - - - -#ifndef headerfilettmathuint -#define headerfilettmathuint - - -/*! - \file ttmathuint.h - \brief template class UInt -*/ - -#include -#include - - -#include "ttmathtypes.h" -#include "ttmathmisc.h" - - - -/*! - \brief a namespace for the TTMath library -*/ -namespace ttmath -{ - -/*! - \brief UInt implements a big integer value without a sign - - value_size - how many bytes specify our value - on 32bit platforms: value_size=1 -> 4 bytes -> 32 bits - on 64bit platforms: value_size=1 -> 8 bytes -> 64 bits - value_size = 1,2,3,4,5,6.... -*/ -template -class UInt -{ -public: - - /*! - buffer for the integer value - table[0] - the lowest word of the value - */ - uint table[value_size]; - - - - /*! - some methods used for debugging purposes - */ - - - /*! - this method is used when macro TTMATH_DEBUG_LOG is defined - */ - template - static void PrintVectorLog(const char_type * msg, ostream_type & output, const uint * vector, uint vector_len) - { - output << msg << std::endl; - - for(uint i=0 ; i - static void PrintVectorLog(const char_type * msg, uint carry, ostream_type & output, const uint * vector, uint vector_len) - { - PrintVectorLog(msg, output, vector, vector_len); - output << " carry: " << carry << std::endl; - } - - - /*! - this method is used when macro TTMATH_DEBUG_LOG is defined - */ - template - void PrintLog(const char_type * msg, ostream_type & output) const - { - PrintVectorLog(msg, output, table, value_size); - } - - - /*! - this method is used when macro TTMATH_DEBUG_LOG is defined - */ - template - void PrintLog(const char_type * msg, uint carry, ostream_type & output) const - { - PrintVectorLog(msg, output, table, value_size); - output << " carry: " << carry << std::endl; - } - - - /*! - this method returns the size of the table - */ - uint Size() const - { - return value_size; - } - - - /*! - this method sets zero - */ - void SetZero() - { - // in the future here can be 'memset' - - for(uint i=0 ; i & ss2) - { - for(uint i=0 ; i=0 && temp_table_index=0 ; --i) - table[i] = 0; - - - TTMATH_LOG("UInt::SetFromTable") - } - -#endif - - -#ifdef TTMATH_PLATFORM64 - /*! - this method copies the value stored in an another table - (warning: first values in temp_table are the highest words -- it's different - from our table) - - ***this method is created only on a 64bit platform*** - - we copy as many words as it is possible - - if temp_table_len is bigger than value_size we'll try to round - the lowest word from table depending on the last not used bit in temp_table - (this rounding isn't a perfect rounding -- look at the description below) - - and if temp_table_len is smaller than value_size we'll clear the rest words - in the table - - warning: we're using 'temp_table' as a pointer at 32bit words - */ - void SetFromTable(const unsigned int * temp_table, uint temp_table_len) - { - uint temp_table_index = 0; - sint i; // 'i' with a sign - - for(i=value_size-1 ; i>=0 && temp_table_index= 0 ; --i) - table[i] = 0; - - TTMATH_LOG("UInt::SetFromTable") - } - -#endif - - - - - - /*! - * - * basic mathematic functions - * - */ - - - - - /*! - this method adds one to the existing value - */ - uint AddOne() - { - return AddInt(1); - } - - - /*! - this method subtracts one from the existing value - */ - uint SubOne() - { - return SubInt(1); - } - - -private: - - - /*! - an auxiliary method for moving bits into the left hand side - - this method moves only words - */ - void RclMoveAllWords(uint & rest_bits, uint & last_c, uint bits, uint c) - { - rest_bits = bits % TTMATH_BITS_PER_UINT; - uint all_words = bits / TTMATH_BITS_PER_UINT; - uint mask = ( c ) ? TTMATH_UINT_MAX_VALUE : 0; - - - if( all_words >= value_size ) - { - if( all_words == value_size && rest_bits == 0 ) - last_c = table[0] & 1; - // else: last_c is default set to 0 - - // clearing - for(uint i = 0 ; i 0 ) - { - // 0 < all_words < value_size - - sint first, second; - last_c = table[value_size - all_words] & 1; // all_words is greater than 0 - - // copying the first part of the value - for(first = value_size-1, second=first-all_words ; second>=0 ; --first, --second) - table[first] = table[second]; - - // setting the rest to 'c' - for( ; first>=0 ; --first ) - table[first] = mask; - } - - TTMATH_LOG("UInt::RclMoveAllWords") - } - -public: - - /*! - moving all bits into the left side 'bits' times - return value <- this <- C - - bits is from a range of <0, man * TTMATH_BITS_PER_UINT> - or it can be even bigger then all bits will be set to 'c' - - the value c will be set into the lowest bits - and the method returns state of the last moved bit - */ - uint Rcl(uint bits, uint c=0) - { - uint last_c = 0; - uint rest_bits = bits; - - if( bits == 0 ) - return 0; - - if( bits >= TTMATH_BITS_PER_UINT ) - RclMoveAllWords(rest_bits, last_c, bits, c); - - if( rest_bits == 0 ) - { - TTMATH_LOG("UInt::Rcl") - return last_c; - } - - // rest_bits is from 1 to TTMATH_BITS_PER_UINT-1 now - if( rest_bits == 1 ) - { - last_c = Rcl2_one(c); - } - else if( rest_bits == 2 ) - { - // performance tests showed that for rest_bits==2 it's better to use Rcl2_one twice instead of Rcl2(2,c) - Rcl2_one(c); - last_c = Rcl2_one(c); - } - else - { - last_c = Rcl2(rest_bits, c); - } - - TTMATH_LOGC("UInt::Rcl", last_c) - - return last_c; - } - -private: - - /*! - an auxiliary method for moving bits into the right hand side - - this method moves only words - */ - void RcrMoveAllWords(uint & rest_bits, uint & last_c, uint bits, uint c) - { - rest_bits = bits % TTMATH_BITS_PER_UINT; - uint all_words = bits / TTMATH_BITS_PER_UINT; - uint mask = ( c ) ? TTMATH_UINT_MAX_VALUE : 0; - - - if( all_words >= value_size ) - { - if( all_words == value_size && rest_bits == 0 ) - last_c = (table[value_size-1] & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0; - // else: last_c is default set to 0 - - // clearing - for(uint i = 0 ; i 0 ) - { - // 0 < all_words < value_size - - uint first, second; - last_c = (table[all_words - 1] & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0; // all_words is > 0 - - // copying the first part of the value - for(first=0, second=all_words ; second this -> return value - - bits is from a range of <0, man * TTMATH_BITS_PER_UINT> - or it can be even bigger then all bits will be set to 'c' - - the value c will be set into the highest bits - and the method returns state of the last moved bit - */ - uint Rcr(uint bits, uint c=0) - { - uint last_c = 0; - uint rest_bits = bits; - - if( bits == 0 ) - return 0; - - if( bits >= TTMATH_BITS_PER_UINT ) - RcrMoveAllWords(rest_bits, last_c, bits, c); - - if( rest_bits == 0 ) - { - TTMATH_LOG("UInt::Rcr") - return last_c; - } - - // rest_bits is from 1 to TTMATH_BITS_PER_UINT-1 now - if( rest_bits == 1 ) - { - last_c = Rcr2_one(c); - } - else if( rest_bits == 2 ) - { - // performance tests showed that for rest_bits==2 it's better to use Rcr2_one twice instead of Rcr2(2,c) - Rcr2_one(c); - last_c = Rcr2_one(c); - } - else - { - last_c = Rcr2(rest_bits, c); - } - - TTMATH_LOGC("UInt::Rcr", last_c) - - return last_c; - } - - - /*! - this method moves all bits into the left side - (it returns value how many bits have been moved) - */ - uint CompensationToLeft() - { - uint moving = 0; - - // a - index a last word which is different from zero - sint a; - for(a=value_size-1 ; a>=0 && table[a]==0 ; --a); - - if( a < 0 ) - return moving; // all words in table have zero - - if( a != value_size-1 ) - { - moving += ( value_size-1 - a ) * TTMATH_BITS_PER_UINT; - - // moving all words - sint i; - for(i=value_size-1 ; a>=0 ; --i, --a) - table[i] = table[a]; - - // setting the rest word to zero - for(; i>=0 ; --i) - table[i] = 0; - } - - uint moving2 = FindLeadingBitInWord( table[value_size-1] ); - // moving2 is different from -1 because the value table[value_size-1] - // is not zero - - moving2 = TTMATH_BITS_PER_UINT - moving2 - 1; - Rcl(moving2); - - TTMATH_LOG("UInt::CompensationToLeft") - - return moving + moving2; - } - - - /*! - this method looks for the highest set bit - - result: - if 'this' is not zero: - return value - true - 'table_id' - the index of a word <0..value_size-1> - 'index' - the index of this set bit in the word <0..TTMATH_BITS_PER_UINT) - - if 'this' is zero: - return value - false - both 'table_id' and 'index' are zero - */ - bool FindLeadingBit(uint & table_id, uint & index) const - { - for(table_id=value_size-1 ; table_id!=0 && table[table_id]==0 ; --table_id); - - if( table_id==0 && table[table_id]==0 ) - { - // is zero - index = 0; - - return false; - } - - // table[table_id] is different from 0 - index = FindLeadingBitInWord( table[table_id] ); - - return true; - } - - - /*! - this method looks for the smallest set bit - - result: - if 'this' is not zero: - return value - true - 'table_id' - the index of a word <0..value_size-1> - 'index' - the index of this set bit in the word <0..TTMATH_BITS_PER_UINT) - - if 'this' is zero: - return value - false - both 'table_id' and 'index' are zero - */ - bool FindLowestBit(uint & table_id, uint & index) const - { - for(table_id=0 ; table_id= value_size ) - { - // is zero - index = 0; - table_id = 0; - - return false; - } - - // table[table_id] is different from 0 - index = FindLowestBitInWord( table[table_id] ); - - return true; - } - - - /*! - getting the 'bit_index' bit - - bit_index bigger or equal zero - */ - uint GetBit(uint bit_index) const - { - TTMATH_ASSERT( bit_index < value_size * TTMATH_BITS_PER_UINT ) - - uint index = bit_index / TTMATH_BITS_PER_UINT; - uint bit = bit_index % TTMATH_BITS_PER_UINT; - - uint temp = table[index]; - uint res = SetBitInWord(temp, bit); - - return res; - } - - - /*! - setting the 'bit_index' bit - and returning the last state of the bit - - bit_index bigger or equal zero - */ - uint SetBit(uint bit_index) - { - TTMATH_ASSERT( bit_index < value_size * TTMATH_BITS_PER_UINT ) - - uint index = bit_index / TTMATH_BITS_PER_UINT; - uint bit = bit_index % TTMATH_BITS_PER_UINT; - uint res = SetBitInWord(table[index], bit); - - TTMATH_LOG("UInt::SetBit") - - return res; - } - - - /*! - this method performs a bitwise operation AND - */ - void BitAnd(const UInt & ss2) - { - for(uint x=0 ; x & ss2) - { - for(uint x=0 ; x & ss2) - { - for(uint x=0 ; x - - for example: - BitNot2(8) = BitNot2( 1000(bin) ) = 111(bin) = 7 - */ - void BitNot2() - { - uint table_id, index; - - if( FindLeadingBit(table_id, index) ) - { - for(uint x=0 ; x>= shift; - - table[table_id] ^= mask; - } - else - table[0] = 1; - - - TTMATH_LOG("UInt::BitNot2") - } - - - - /*! - * - * Multiplication - * - * - */ - -public: - - /*! - multiplication: this = this * ss2 - - it can return a carry - */ - uint MulInt(uint ss2) - { - uint r1, r2, x1; - uint c = 0; - - UInt u(*this); - SetZero(); - - if( ss2 == 0 ) - { - TTMATH_LOGC("UInt::MulInt(uint)", 0) - return 0; - } - - for(x1=0 ; x1 - void MulInt(uint ss2, UInt & result) const - { - TTMATH_ASSERT( result_size > value_size ) - - uint r2,r1; - uint x1size=value_size; - uint x1start=0; - - result.SetZero(); - - if( ss2 == 0 ) - { - TTMATH_VECTOR_LOG("UInt::MulInt(uint, UInt<>)", result.table, result_size) - return; - } - - if( value_size > 2 ) - { - // if the value_size is smaller than or equal to 2 - // there is no sense to set x1size and x1start to another values - - for(x1size=value_size ; x1size>0 && table[x1size-1]==0 ; --x1size); - - if( x1size == 0 ) - { - TTMATH_VECTOR_LOG("UInt::MulInt(uint, UInt<>)", result.table, result_size) - return; - } - - for(x1start=0 ; x1start)", result.table, result_size) - - return; - } - - - - /*! - the multiplication 'this' = 'this' * ss2 - - algorithm: 100 - means automatically choose the fastest algorithm - */ - uint Mul(const UInt & ss2, uint algorithm = 100) - { - switch( algorithm ) - { - case 1: - return Mul1(ss2); - - case 2: - return Mul2(ss2); - - case 3: - return Mul3(ss2); - - case 100: - default: - return MulFastest(ss2); - } - } - - - /*! - the multiplication 'result' = 'this' * ss2 - - since the 'result' is twice bigger than 'this' and 'ss2' - this method never returns a carry - - algorithm: 100 - means automatically choose the fastest algorithm - */ - void MulBig(const UInt & ss2, - UInt & result, - uint algorithm = 100) - { - switch( algorithm ) - { - case 1: - return Mul1Big(ss2, result); - - case 2: - return Mul2Big(ss2, result); - - case 3: - return Mul3Big(ss2, result); - - case 100: - default: - return MulFastestBig(ss2, result); - } - } - - - - /*! - the first version of the multiplication algorithm - */ - -private: - - /*! - multiplication: this = this * ss2 - - it returns carry if it has been - */ - uint Mul1Ref(const UInt & ss2) - { - TTMATH_REFERENCE_ASSERT( ss2 ) - - UInt ss1( *this ); - SetZero(); - - for(uint i=0; i < value_size*TTMATH_BITS_PER_UINT ; ++i) - { - if( Add(*this) ) - { - TTMATH_LOGC("UInt::Mul1", 1) - return 1; - } - - if( ss1.Rcl(1) ) - if( Add(ss2) ) - { - TTMATH_LOGC("UInt::Mul1", 1) - return 1; - } - } - - TTMATH_LOGC("UInt::Mul1", 0) - - return 0; - } - - -public: - - /*! - multiplication: this = this * ss2 - can return carry - */ - uint Mul1(const UInt & ss2) - { - if( this == &ss2 ) - { - UInt copy_ss2(ss2); - return Mul1Ref(copy_ss2); - } - else - { - return Mul1Ref(ss2); - } - } - - - /*! - multiplication: result = this * ss2 - - result is twice bigger than 'this' and 'ss2' - this method never returns carry - */ - void Mul1Big(const UInt & ss2_, UInt & result) - { - UInt ss2; - uint i; - - // copying *this into result and ss2_ into ss2 - for(i=0 ; i & ss2) - { - UInt result; - uint i, c = 0; - - Mul2Big(ss2, result); - - // copying result - for(i=0 ; i & ss2, UInt & result) - { - Mul2Big2(table, ss2.table, result); - - TTMATH_LOG("UInt::Mul2Big") - } - - -private: - - /*! - an auxiliary method for calculating the multiplication - - arguments we're taking as pointers (this is to improve the Mul3Big2()- avoiding - unnecessary copying objects), the result should be taken as a pointer too, - but at the moment there is no method AddTwoInts() which can operate on pointers - */ - template - void Mul2Big2(const uint * ss1, const uint * ss2, UInt & result) - { - uint x1size = ss_size, x2size = ss_size; - uint x1start = 0, x2start = 0; - - if( ss_size > 2 ) - { - // if the ss_size is smaller than or equal to 2 - // there is no sense to set x1size (and others) to another values - - for(x1size=ss_size ; x1size>0 && ss1[x1size-1]==0 ; --x1size); - for(x2size=ss_size ; x2size>0 && ss2[x2size-1]==0 ; --x2size); - - for(x1start=0 ; x1start(ss1, ss2, result, x1start, x1size, x2start, x2size); - } - - - - /*! - an auxiliary method for calculating the multiplication - */ - template - void Mul2Big3(const uint * ss1, const uint * ss2, UInt & result, uint x1start, uint x1size, uint x2start, uint x2size) - { - uint r2, r1; - - result.SetZero(); - - if( x1size==0 || x2size==0 ) - return; - - for(uint x1=x1start ; x1 & ss2) - { - UInt result; - uint i, c = 0; - - Mul3Big(ss2, result); - - // copying result - for(i=0 ; i & ss2, UInt & result) - { - Mul3Big2(table, ss2.table, result.table); - - TTMATH_LOG("UInt::Mul3Big") - } - - - -private: - - /*! - an auxiliary method for calculating the Karatsuba multiplication - - result_size is equal ss_size*2 - */ - template - void Mul3Big2(const uint * ss1, const uint * ss2, uint * result) - { - const uint * x1, * x0, * y1, * y0; - - - if( ss_size>1 && ss_size res; - Mul2Big2(ss1, ss2, res); - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wtautological-compare" -#endif - - for(uint i=0 ; i(x1, x0, y1, y0, result); - } - else - { - // ss_size is even - x0 = ss1; - y0 = ss2; - x1 = ss1 + ss_size / 2; - y1 = ss2 + ss_size / 2; - - // all four vectors (x0 x1 y0 y1) are equal in size - Mul3Big3(x1, x0, y1, y0, result); - } - } - - - -#ifdef _MSC_VER -#pragma warning (disable : 4717) -//warning C4717: recursive on all control paths, function will cause runtime stack overflow -//we have the stop point in Mul3Big2() method -#endif - - - /*! - an auxiliary method for calculating the Karatsuba multiplication - - x = x1*B^m + x0 - y = y1*B^m + y0 - - first_size - is the size of vectors: x0 and y0 - second_size - is the size of vectors: x1 and y1 (can be either equal first_size or smaller about one from first_size) - - x*y = (x1*B^m + x0)(y1*B^m + y0) = z2*B^(2m) + z1*B^m + z0 - where - z0 = x0*y0 - z2 = x1*y1 - z1 = (x1 + x0)*(y1 + y0) - z2 - z0 - */ - template - uint Mul3Big3(const uint * x1, const uint * x0, const uint * y1, const uint * y0, uint * result) - { - uint i, c, xc, yc; - - UInt temp, temp2; - UInt z1; - - // z0 and z2 we store directly in the result (we don't use any temporary variables) - Mul3Big2(x0, y0, result); // z0 - Mul3Big2(x1, y1, result+first_size*2); // z2 - - // now we calculate z1 - // temp = (x0 + x1) - // temp2 = (y0 + y1) - // we're using temp and temp2 with UInt, although there can be a carry but - // we simple remember it in xc and yc (xc and yc can be either 0 or 1), - // and (x0 + x1)*(y0 + y1) we calculate in this way (schoolbook algorithm): - // - // xc | temp - // yc | temp2 - // -------------------- - // (temp * temp2) - // xc*temp2 | - // yc*temp | - // xc*yc | - // ---------- z1 -------- - // - // and the result is never larger in size than 3*first_size - - xc = AddVector(x0, x1, first_size, second_size, temp.table); - yc = AddVector(y0, y1, first_size, second_size, temp2.table); - - Mul3Big2(temp.table, temp2.table, z1.table); - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wtautological-compare" -#endif - - // clearing the rest of z1 - for(i=first_size*2 ; i second_size ) - { - uint z1_size = result_size - first_size; - TTMATH_ASSERT( z1_size <= first_size*3 ) - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wtautological-compare" -#endif - - for(i=z1_size ; i & ss2) - { - UInt result; - uint i, c = 0; - - MulFastestBig(ss2, result); - - // copying result - for(i=0 ; i & ss2, UInt & result) - { - if( value_size < TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE ) - return Mul2Big(ss2, result); - - uint x1size = value_size, x2size = value_size; - uint x1start = 0, x2start = 0; - - for(x1size=value_size ; x1size>0 && table[x1size-1]==0 ; --x1size); - for(x2size=value_size ; x2size>0 && ss2.table[x2size-1]==0 ; --x2size); - - if( x1size==0 || x2size==0 ) - { - // either 'this' or 'ss2' is equal zero - the result is zero too - result.SetZero(); - return; - } - - for(x1start=0 ; x1start(table, ss2.table, result, x1start, x1size, x2start, x2size); - - - // Karatsuba multiplication - Mul3Big(ss2, result); - - TTMATH_LOG("UInt::MulFastestBig") - } - - - /*! - * - * Division - * - * - */ - -public: - - - /*! - division by one unsigned word - - returns 1 when divisor is zero - */ - uint DivInt(uint divisor, uint * remainder = 0) - { - if( divisor == 0 ) - { - if( remainder ) - *remainder = 0; // this is for convenience, without it the compiler can report that 'remainder' is uninitialized - - TTMATH_LOG("UInt::DivInt") - - return 1; - } - - if( divisor == 1 ) - { - if( remainder ) - *remainder = 0; - - TTMATH_LOG("UInt::DivInt") - - return 0; - } - - UInt dividend(*this); - SetZero(); - - sint i; // i must be with a sign - uint r = 0; - - // we're looking for the last word in ss1 - for(i=value_size-1 ; i>0 && dividend.table[i]==0 ; --i); - - for( ; i>=0 ; --i) - DivTwoWords(r, dividend.table[i], divisor, &table[i], &r); - - if( remainder ) - *remainder = r; - - TTMATH_LOG("UInt::DivInt") - - return 0; - } - - uint DivInt(uint divisor, uint & remainder) - { - return DivInt(divisor, &remainder); - } - - - - /*! - division this = this / ss2 - - return values: - 0 - ok - 1 - division by zero - 'this' will be the quotient - 'remainder' - remainder - */ - uint Div( const UInt & divisor, - UInt * remainder = 0, - uint algorithm = 3) - { - switch( algorithm ) - { - case 1: - return Div1(divisor, remainder); - - case 2: - return Div2(divisor, remainder); - - case 3: - default: - return Div3(divisor, remainder); - } - } - - uint Div(const UInt & divisor, UInt & remainder, uint algorithm = 3) - { - return Div(divisor, &remainder, algorithm); - } - - - -private: - - /*! - return values: - 0 - none has to be done - 1 - division by zero - 2 - division should be made - */ - uint Div_StandardTest( const UInt & v, - uint & m, uint & n, - UInt * remainder = 0) - { - switch( Div_CalculatingSize(v, m, n) ) - { - case 4: // 'this' is equal v - if( remainder ) - remainder->SetZero(); - - SetOne(); - TTMATH_LOG("UInt::Div_StandardTest") - return 0; - - case 3: // 'this' is smaller than v - if( remainder ) - *remainder = *this; - - SetZero(); - TTMATH_LOG("UInt::Div_StandardTest") - return 0; - - case 2: // 'this' is zero - if( remainder ) - remainder->SetZero(); - - SetZero(); - TTMATH_LOG("UInt::Div_StandardTest") - return 0; - - case 1: // v is zero - TTMATH_LOG("UInt::Div_StandardTest") - return 1; - } - - TTMATH_LOG("UInt::Div_StandardTest") - - return 2; - } - - - - /*! - return values: - 0 - ok - 'm' - is the index (from 0) of last non-zero word in table ('this') - 'n' - is the index (from 0) of last non-zero word in v.table - 1 - v is zero - 2 - 'this' is zero - 3 - 'this' is smaller than v - 4 - 'this' is equal v - - if the return value is different than zero the 'm' and 'n' are undefined - */ - uint Div_CalculatingSize(const UInt & v, uint & m, uint & n) - { - m = n = value_size-1; - - for( ; n!=0 && v.table[n]==0 ; --n); - - if( n==0 && v.table[n]==0 ) - return 1; - - for( ; m!=0 && table[m]==0 ; --m); - - if( m==0 && table[m]==0 ) - return 2; - - if( m < n ) - return 3; - else - if( m == n ) - { - uint i; - for(i = n ; i!=0 && table[i]==v.table[i] ; --i); - - if( table[i] < v.table[i] ) - return 3; - else - if (table[i] == v.table[i] ) - return 4; - } - - return 0; - } - - -public: - - /*! - the first division algorithm - radix 2 - */ - uint Div1(const UInt & divisor, UInt * remainder = 0) - { - uint m,n, test; - - test = Div_StandardTest(divisor, m, n, remainder); - if( test < 2 ) - return test; - - if( !remainder ) - { - UInt rem; - - return Div1_Calculate(divisor, rem); - } - - return Div1_Calculate(divisor, *remainder); - } - - - /*! - the first division algorithm - radix 2 - */ - uint Div1(const UInt & divisor, UInt & remainder) - { - return Div1(divisor, &remainder); - } - - -private: - - uint Div1_Calculate(const UInt & divisor, UInt & rest) - { - if( this == &divisor ) - { - UInt divisor_copy(divisor); - return Div1_CalculateRef(divisor_copy, rest); - } - else - { - return Div1_CalculateRef(divisor, rest); - } - } - - - uint Div1_CalculateRef(const UInt & divisor, UInt & rest) - { - TTMATH_REFERENCE_ASSERT( divisor ) - - sint loop; - sint c; - - rest.SetZero(); - loop = value_size * TTMATH_BITS_PER_UINT; - c = 0; - - - div_a: - c = Rcl(1, c); - c = rest.Add(rest,c); - c = rest.Sub(divisor,c); - - c = !c; - - if(!c) - goto div_d; - - - div_b: - --loop; - if(loop) - goto div_a; - - c = Rcl(1, c); - TTMATH_LOG("UInt::Div1_Calculate") - return 0; - - - div_c: - c = Rcl(1, c); - c = rest.Add(rest,c); - c = rest.Add(divisor); - - if(c) - goto div_b; - - - div_d: - --loop; - if(loop) - goto div_c; - - c = Rcl(1, c); - c = rest.Add(divisor); - - TTMATH_LOG("UInt::Div1_Calculate") - - return 0; - } - - -public: - - /*! - the second division algorithm - - return values: - 0 - ok - 1 - division by zero - */ - uint Div2(const UInt & divisor, UInt * remainder = 0) - { - if( this == &divisor ) - { - UInt divisor_copy(divisor); - return Div2Ref(divisor_copy, remainder); - } - else - { - return Div2Ref(divisor, remainder); - } - } - - - /*! - the second division algorithm - - return values: - 0 - ok - 1 - division by zero - */ - uint Div2(const UInt & divisor, UInt & remainder) - { - return Div2(divisor, &remainder); - } - - -private: - - /*! - the second division algorithm - - return values: - 0 - ok - 1 - division by zero - */ - uint Div2Ref(const UInt & divisor, UInt * remainder = 0) - { - uint bits_diff; - uint status = Div2_Calculate(divisor, remainder, bits_diff); - if( status < 2 ) - return status; - - if( CmpBiggerEqual(divisor) ) - { - Div2(divisor, remainder); - SetBit(bits_diff); - } - else - { - if( remainder ) - *remainder = *this; - - SetZero(); - SetBit(bits_diff); - } - - TTMATH_LOG("UInt::Div2") - - return 0; - } - - - /*! - return values: - 0 - we've calculated the division - 1 - division by zero - 2 - we have to still calculate - - */ - uint Div2_Calculate(const UInt & divisor, UInt * remainder, - uint & bits_diff) - { - uint table_id, index; - uint divisor_table_id, divisor_index; - - uint status = Div2_FindLeadingBitsAndCheck( divisor, remainder, - table_id, index, - divisor_table_id, divisor_index); - - if( status < 2 ) - { - TTMATH_LOG("UInt::Div2_Calculate") - return status; - } - - // here we know that 'this' is greater than divisor - // then 'index' is greater or equal 'divisor_index' - bits_diff = index - divisor_index; - - UInt divisor_copy(divisor); - divisor_copy.Rcl(bits_diff, 0); - - if( CmpSmaller(divisor_copy, table_id) ) - { - divisor_copy.Rcr(1); - --bits_diff; - } - - Sub(divisor_copy, 0); - - TTMATH_LOG("UInt::Div2_Calculate") - - return 2; - } - - - /*! - return values: - 0 - we've calculated the division - 1 - division by zero - 2 - we have to still calculate - */ - uint Div2_FindLeadingBitsAndCheck( const UInt & divisor, - UInt * remainder, - uint & table_id, uint & index, - uint & divisor_table_id, uint & divisor_index) - { - if( !divisor.FindLeadingBit(divisor_table_id, divisor_index) ) - { - // division by zero - TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck") - return 1; - } - - if( !FindLeadingBit(table_id, index) ) - { - // zero is divided by something - - SetZero(); - - if( remainder ) - remainder->SetZero(); - - TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck") - - return 0; - } - - divisor_index += divisor_table_id * TTMATH_BITS_PER_UINT; - index += table_id * TTMATH_BITS_PER_UINT; - - if( divisor_table_id == 0 ) - { - // dividor has only one 32-bit word - - uint r; - DivInt(divisor.table[0], &r); - - if( remainder ) - { - remainder->SetZero(); - remainder->table[0] = r; - } - - TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck") - - return 0; - } - - - if( Div2_DivisorGreaterOrEqual( divisor, remainder, - table_id, index, - divisor_index) ) - { - TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck") - return 0; - } - - - TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck") - - return 2; - } - - - /*! - return values: - true if divisor is equal or greater than 'this' - */ - bool Div2_DivisorGreaterOrEqual( const UInt & divisor, - UInt * remainder, - uint table_id, uint index, - uint divisor_index ) - { - if( divisor_index > index ) - { - // divisor is greater than this - - if( remainder ) - *remainder = *this; - - SetZero(); - - TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual") - - return true; - } - - if( divisor_index == index ) - { - // table_id == divisor_table_id as well - - uint i; - for(i = table_id ; i!=0 && table[i]==divisor.table[i] ; --i); - - if( table[i] < divisor.table[i] ) - { - // divisor is greater than 'this' - - if( remainder ) - *remainder = *this; - - SetZero(); - - TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual") - - return true; - } - else - if( table[i] == divisor.table[i] ) - { - // divisor is equal 'this' - - if( remainder ) - remainder->SetZero(); - - SetOne(); - - TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual") - - return true; - } - } - - TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual") - - return false; - } - - -public: - - /*! - the third division algorithm - */ - uint Div3(const UInt & ss2, UInt * remainder = 0) - { - if( this == &ss2 ) - { - UInt copy_ss2(ss2); - return Div3Ref(copy_ss2, remainder); - } - else - { - return Div3Ref(ss2, remainder); - } - } - - - /*! - the third division algorithm - */ - uint Div3(const UInt & ss2, UInt & remainder) - { - return Div3(ss2, &remainder); - } - - -private: - - /*! - the third division algorithm - - this algorithm is described in the following book: - "The art of computer programming 2" (4.3.1 page 272) - Donald E. Knuth - !! give the description here (from the book) - */ - uint Div3Ref(const UInt & v, UInt * remainder = 0) - { - uint m,n, test; - - test = Div_StandardTest(v, m, n, remainder); - if( test < 2 ) - return test; - - if( n == 0 ) - { - uint r; - DivInt( v.table[0], &r ); - - if( remainder ) - { - remainder->SetZero(); - remainder->table[0] = r; - } - - TTMATH_LOG("UInt::Div3") - - return 0; - } - - - // we can only use the third division algorithm when - // the divisor is greater or equal 2^32 (has more than one 32-bit word) - ++m; - ++n; - m = m - n; - Div3_Division(v, remainder, m, n); - - TTMATH_LOG("UInt::Div3") - - return 0; - } - - - -private: - - - void Div3_Division(UInt v, UInt * remainder, uint m, uint n) - { - TTMATH_ASSERT( n>=2 ) - - UInt uu, vv; - UInt q; - uint d, u_value_size, u0, u1, u2, v1, v0, j=m; - - u_value_size = Div3_Normalize(v, n, d); - - if( j+n == value_size ) - u2 = u_value_size; - else - u2 = table[j+n]; - - Div3_MakeBiggerV(v, vv); - - for(uint i = j+1 ; i & uu, uint j, uint n, uint u_max) - { - uint i; - - for(i=0 ; i so and 'i' is from <0..value_size> - // then table[i] is always correct (look at the declaration of 'uu') - uu.table[i] = u_max; - - for( ++i ; i & uu, uint j, uint n) - { - uint i; - - for(i=0 ; i & v, UInt & vv) - { - for(uint i=0 ; i & v, uint n, uint & d) - { - // v.table[n-1] is != 0 - - uint bit = (uint)FindLeadingBitInWord(v.table[n-1]); - uint move = (TTMATH_BITS_PER_UINT - bit - 1); - uint res = table[value_size-1]; - d = move; - - if( move > 0 ) - { - v.Rcl(move, 0); - Rcl(move, 0); - res = res >> (bit + 1); - } - else - { - res = 0; - } - - TTMATH_LOG("UInt::Div3_Normalize") - - return res; - } - - - void Div3_Unnormalize(UInt * remainder, uint n, uint d) - { - for(uint i=n ; i u_temp; - uint rp; - bool next_test; - - TTMATH_ASSERT( v1 != 0 ) - - u_temp.table[1] = u2; - u_temp.table[0] = u1; - u_temp.DivInt(v1, &rp); - - TTMATH_ASSERT( u_temp.table[1]==0 || u_temp.table[1]==1 ) - - do - { - bool decrease = false; - - if( u_temp.table[1] == 1 ) - decrease = true; - else - { - UInt<2> temp1, temp2; - - UInt<2>::MulTwoWords(u_temp.table[0], v0, temp1.table+1, temp1.table); - temp2.table[1] = rp; - temp2.table[0] = u0; - - if( temp1 > temp2 ) - decrease = true; - } - - next_test = false; - - if( decrease ) - { - u_temp.SubOne(); - - rp += v1; - - if( rp >= v1 ) // it means that there wasn't a carry (r & uu, - const UInt & vv, uint & qp) - { - // D4 (in the book) - - UInt vv_temp(vv); - vv_temp.MulInt(qp); - - if( uu.Sub(vv_temp) ) - { - // there was a carry - - // - // !!! this part of code was not tested - // - - --qp; - uu.Add(vv); - - // can be a carry from this additions but it should be ignored - // because it cancels with the borrow from uu.Sub(vv_temp) - } - - TTMATH_LOG("UInt::Div3_MultiplySubtract") - } - - - - - - -public: - - - /*! - power this = this ^ pow - binary algorithm (r-to-l) - - return values: - 0 - ok - 1 - carry - 2 - incorrect argument (0^0) - */ - uint Pow(UInt pow) - { - if(pow.IsZero() && IsZero()) - // we don't define zero^zero - return 2; - - UInt start(*this); - UInt result; - result.SetOne(); - uint c = 0; - - while( !c ) - { - if( pow.table[0] & 1 ) - c += result.Mul(start); - - pow.Rcr2_one(0); - if( pow.IsZero() ) - break; - - c += start.Mul(start); - } - - *this = result; - - TTMATH_LOGC("UInt::Pow(UInt<>)", c) - - return (c==0)? 0 : 1; - } - - - /*! - square root - e.g. Sqrt(9) = 3 - ('digit-by-digit' algorithm) - */ - void Sqrt() - { - UInt bit, temp; - - if( IsZero() ) - return; - - UInt value(*this); - - SetZero(); - bit.SetZero(); - bit.table[value_size-1] = (TTMATH_UINT_HIGHEST_BIT >> 1); - - while( bit > value ) - bit.Rcr(2); - - while( !bit.IsZero() ) - { - temp = *this; - temp.Add(bit); - - if( value >= temp ) - { - value.Sub(temp); - Rcr(1); - Add(bit); - } - else - { - Rcr(1); - } - - bit.Rcr(2); - } - - TTMATH_LOG("UInt::Sqrt") - } - - - - /*! - this method sets n first bits to value zero - - For example: - let n=2 then if there's a value 111 (bin) there'll be '100' (bin) - */ - void ClearFirstBits(uint n) - { - if( n >= value_size*TTMATH_BITS_PER_UINT ) - { - SetZero(); - TTMATH_LOG("UInt::ClearFirstBits") - return; - } - - uint * p = table; - - // first we're clearing the whole words - while( n >= TTMATH_BITS_PER_UINT ) - { - *p++ = 0; - n -= TTMATH_BITS_PER_UINT; - } - - if( n == 0 ) - { - TTMATH_LOG("UInt::ClearFirstBits") - return; - } - - // and then we're clearing one word which has left - // mask -- all bits are set to one - uint mask = TTMATH_UINT_MAX_VALUE; - - mask = mask << n; - - (*p) &= mask; - - TTMATH_LOG("UInt::ClearFirstBits") - } - - - /*! - this method returns true if the highest bit of the value is set - */ - bool IsTheHighestBitSet() const - { - return (table[value_size-1] & TTMATH_UINT_HIGHEST_BIT) != 0; - } - - - /*! - this method returns true if the lowest bit of the value is set - */ - bool IsTheLowestBitSet() const - { - return (*table & 1) != 0; - } - - - /*! - returning true if only the highest bit is set - */ - bool IsOnlyTheHighestBitSet() const - { -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wtautological-compare" -#endif - - for(uint i=0 ; i> (TTMATH_BITS_PER_UINT - rest); - - return (table[i] & mask) == 0; - } - - - - /*! - * - * conversion methods - * - */ - - - - /*! - this method converts an UInt type to this class - - this operation has mainly sense if the value from p is - equal or smaller than that one which is returned from UInt::SetMax() - - it returns a carry if the value 'p' is too big - */ - template - uint FromUInt(const UInt & p) - { - uint min_size = (value_size < argument_size)? value_size : argument_size; - uint i; - - for(i=0 ; i argument_size ) - { - // 'this' is longer than 'p' - - for( ; i)", 1) - return 1; - } - } - - TTMATH_LOGC("UInt::FromUInt(UInt<>)", 0) - - return 0; - } - - - /*! - this method converts an UInt type to this class - - this operation has mainly sense if the value from p is - equal or smaller than that one which is returned from UInt::SetMax() - - it returns a carry if the value 'p' is too big - */ - template - uint FromInt(const UInt & p) - { - return FromUInt(p); - } - - - /*! - this method converts the uint type to this class - */ - uint FromUInt(uint value) - { - for(uint i=1 ; i type to this class - - it doesn't return a carry - */ -/* template - UInt & operator=(const UInt & p) - { - FromUInt(p); - - return *this; - } -*/ - - /*! - the assignment operator - */ -/* UInt & operator=(const UInt & p) - { - for(uint i=0 ; i)") - - return *this; - } -*/ - - /*! - this method converts the uint type to this class - */ - UInt & operator=(uint i) - { - FromUInt(i); - - return *this; - } - - - /*! - a constructor for converting the uint to this class - */ -/* UInt(uint i) - { - FromUInt(i); - } -*/ - - /*! - this method converts the sint type to this class - */ - UInt & operator=(sint i) - { - FromInt(i); - - return *this; - } - - - /*! - a constructor for converting the sint to this class - - look at the description of UInt::operator=(sint) - */ -/* UInt(sint i) - { - FromInt(i); - } -*/ - -#ifdef TTMATH_PLATFORM32 - - - /*! - this method converts unsigned 64 bit int type to this class - ***this method is created only on a 32bit platform*** - */ - uint FromUInt(ulint n) - { - table[0] = (uint)n; - - if( value_size == 1 ) - { - uint c = ((n >> TTMATH_BITS_PER_UINT) == 0) ? 0 : 1; - - TTMATH_LOGC("UInt::FromUInt(ulint)", c) - return c; - } - - table[1] = (uint)(n >> TTMATH_BITS_PER_UINT); - - for(uint i=2 ; i & operator=(ulint n) - { - FromUInt(n); - - return *this; - } - - - /*! - a constructor for converting unsigned 64 bit int to this class - ***this constructor is created only on a 32bit platform*** - */ -/* UInt(ulint n) - { - FromUInt(n); - } -*/ - - /*! - this operator converts signed 64 bit int type to this class - ***this operator is created only on a 32bit platform*** - */ - UInt & operator=(slint n) - { - FromInt(n); - - return *this; - } - - - /*! - a constructor for converting signed 64 bit int to this class - ***this constructor is created only on a 32bit platform*** - */ -/* UInt(slint n) - { - FromInt(n); - } -*/ -#endif - - - -#ifdef TTMATH_PLATFORM64 - - - /*! - this method converts 32 bit unsigned int type to this class - ***this operator is created only on a 64bit platform*** - */ - uint FromUInt(unsigned int i) - { - return FromUInt(uint(i)); - } - - /*! - this method converts 32 bit unsigned int type to this class - ***this operator is created only on a 64bit platform*** - */ - uint FromInt(unsigned int i) - { - return FromUInt(uint(i)); - } - - - /*! - this method converts 32 bit signed int type to this class - ***this operator is created only on a 64bit platform*** - */ - uint FromInt(signed int i) - { - return FromInt(sint(i)); - } - - - /*! - this operator converts 32 bit unsigned int type to this class - ***this operator is created only on a 64bit platform*** - */ - UInt & operator=(unsigned int i) - { - FromUInt(i); - - return *this; - } - - - /*! - a constructor for converting 32 bit unsigned int to this class - ***this constructor is created only on a 64bit platform*** - */ -/* UInt(unsigned int i) - { - FromUInt(i); - } -*/ - - /*! - an operator for converting 32 bit signed int to this class - ***this constructor is created only on a 64bit platform*** - */ - UInt & operator=(signed int i) - { - FromInt(i); - - return *this; - } - - - /*! - a constructor for converting 32 bit signed int to this class - ***this constructor is created only on a 64bit platform*** - */ -/* UInt(signed int i) - { - FromInt(i); - } -*/ - -#endif - - - - - - /*! - a constructor for converting a string to this class (with the base=10) - */ -/* UInt(const char * s) - { - FromString(s); - } -*/ - - /*! - a constructor for converting a string to this class (with the base=10) - */ -/* UInt(const std::string & s) - { - FromString( s.c_str() ); - } -*/ - -#ifndef TTMATH_DONT_USE_WCHAR - - /*! - a constructor for converting a string to this class (with the base=10) - */ - UInt(const wchar_t * s) - { - FromString(s); - } - - - /*! - a constructor for converting a string to this class (with the base=10) - */ - UInt(const std::wstring & s) - { - FromString( s.c_str() ); - } - -#endif - - - - - /*! - a default constructor - - we don't clear the table - */ -/* UInt() - { - // when macro TTMATH_DEBUG_LOG is defined - // we set special values to the table - // in order to be everywhere the same value of the UInt object - // without this it would be difficult to analyse the log file - #ifdef TTMATH_DEBUG_LOG - #ifdef TTMATH_PLATFORM32 - for(uint i=0 ; i & u) - { - for(uint i=0 ; i)") - } -*/ - - - /*! - a template for producting constructors for copying from another types - */ -/* template - UInt(const UInt & u) - { - // look that 'size' we still set as 'value_size' and not as u.value_size - FromUInt(u); - } -*/ - - - - /*! - a destructor - */ -/* ~UInt() - { - } -*/ - - /*! - this method returns the lowest value from table - - we must be sure when we using this method whether the value - will hold in an uint type or not (the rest value from the table must be zero) - */ - uint ToUInt() const - { - return table[0]; - } - - - /*! - this method converts the value to uint type - can return a carry if the value is too long to store it in uint type - */ - uint ToUInt(uint & result) const - { - result = table[0]; - - for(uint i=1 ; i> 32) != 0 ) - return 1; - - for(uint i=1 ; i - */ - double ToStringLog2(uint x) const - { - static double log_tab[] = { - 1.000000000000000000, - 0.630929753571457437, - 0.500000000000000000, - 0.430676558073393050, - 0.386852807234541586, - 0.356207187108022176, - 0.333333333333333333, - 0.315464876785728718, - 0.301029995663981195, - 0.289064826317887859, - 0.278942945651129843, - 0.270238154427319741, - 0.262649535037193547, - 0.255958024809815489, - 0.250000000000000000 - }; - - if( x<2 || x>16 ) - return 0; - - return log_tab[x-2]; - } - - -public: - - - /*! - an auxiliary method for converting to a string - it's used from Int::ToString() too (negative is set true then) - */ - template - void ToStringBase(string_type & result, uint b = 10, bool negative = false) const - { - UInt temp(*this); - uint rest, table_id, index, digits; - double digits_d; - char character; - - result.clear(); - - if( b<2 || b>16 ) - return; - - if( !FindLeadingBit(table_id, index) ) - { - result = '0'; - return; - } - - if( negative ) - result = '-'; - - digits_d = table_id; // for not making an overflow in uint type - digits_d *= TTMATH_BITS_PER_UINT; - digits_d += index + 1; - digits_d *= ToStringLog2(b); - digits = static_cast(digits_d) + 3; // plus some epsilon - - if( result.capacity() < digits ) - result.reserve(digits); - - do - { - temp.DivInt(b, &rest); - character = static_cast(Misc::DigitToChar(rest)); - result.insert(result.end(), character); - } - while( !temp.IsZero() ); - - size_t i1 = negative ? 1 : 0; // the first is a hyphen (when negative is true) - size_t i2 = result.size() - 1; - - for( ; i1 < i2 ; ++i1, --i2 ) - { - char tempc = static_cast(result[i1]); - result[i1] = result[i2]; - result[i2] = tempc; - } - } - - - - /*! - this method converts the value to a string with a base equal 'b' - */ - void ToString(std::string & result, uint b = 10) const - { - return ToStringBase(result, b); - } - - - std::string ToString(uint b = 10) const - { - std::string result; - ToStringBase(result, b); - - return result; - } - - -#ifndef TTMATH_DONT_USE_WCHAR - - void ToString(std::wstring & result, uint b = 10) const - { - return ToStringBase(result, b); - } - - std::wstring ToWString(uint b = 10) const - { - std::wstring result; - ToStringBase(result, b); - - return result; - } - -#endif - - - -private: - - /*! - an auxiliary method for converting from a string - */ - template - uint FromStringBase(const char_type * s, uint b = 10, const char_type ** after_source = 0, bool * value_read = 0) - { - UInt base; - base.FromUInt( b ); - UInt temp; - sint z; - uint c = 0; - - SetZero(); - temp.SetZero(); - Misc::SkipWhiteCharacters(s); - - if( after_source ) - *after_source = s; - - if( value_read ) - *value_read = false; - - if( b<2 || b>16 ) - return 1; - - - for( ; (z=Misc::CharToDigit(*s, b)) != -1 ; ++s) - { - if( value_read ) - *value_read = true; - - if( c == 0 ) - { - temp.table[0] = z; - - c += Mul(base); // !! IMPROVE ME: there can be used MulInt here - c += Add(temp); - } - } - - if( after_source ) - *after_source = s; - - TTMATH_LOGC("UInt::FromString", c) - - return (c==0)? 0 : 1; - } - - -public: - - - /*! - this method converts a string into its value - it returns carry=1 if the value will be too big or an incorrect base 'b' is given - - string is ended with a non-digit value, for example: - "12" will be translated to 12 - as well as: - "12foo" will be translated to 12 too - - existing first white characters will be ommited - - if the value from s is too large the rest digits will be skipped - - after_source (if exists) is pointing at the end of the parsed string - - value_read (if exists) tells whether something has actually been read (at least one digit) - */ - uint FromString(const char * s, uint b = 10, const char ** after_source = 0, bool * value_read = 0) - { - return FromStringBase(s, b, after_source, value_read); - } - - - /*! - this method converts a string into its value - - (it returns carry=1 if the value will be too big or an incorrect base 'b' is given) - */ - uint FromString(const std::string & s, uint b = 10) - { - return FromString( s.c_str(), b ); - } - - - /*! - this operator converts a string into its value (with base = 10) - */ - UInt & operator=(const char * s) - { - FromString(s); - - return *this; - } - - - /*! - this operator converts a string into its value (with base = 10) - */ - UInt & operator=(const std::string & s) - { - FromString( s.c_str() ); - - return *this; - } - - - -#ifndef TTMATH_DONT_USE_WCHAR - - /*! - this method converts a string into its value - */ - uint FromString(const wchar_t * s, uint b = 10, const wchar_t ** after_source = 0, bool * value_read = 0) - { - return FromStringBase(s, b, after_source, value_read); - } - - - /*! - this method converts a string into its value - - (it returns carry=1 if the value will be too big or an incorrect base 'b' is given) - */ - uint FromString(const std::wstring & s, uint b = 10) - { - return FromString( s.c_str(), b ); - } - - - /*! - this operator converts a string into its value (with base = 10) - */ - UInt & operator=(const wchar_t * s) - { - FromString(s); - - return *this; - } - - - /*! - this operator converts a string into its value (with base = 10) - */ - UInt & operator=(const std::wstring & s) - { - FromString( s.c_str() ); - - return *this; - } - -#endif - - - /*! - * - * methods for comparing - * - */ - - - /*! - this method returns true if 'this' is smaller than 'l' - - 'index' is an index of the first word from will be the comparison performed - (note: we start the comparison from back - from the last word, when index is -1 /default/ - it is automatically set into the last word) - I introduced it for some kind of optimization made in the second division algorithm (Div2) - */ - bool CmpSmaller(const UInt & l, sint index = -1) const - { - sint i; - - if( index==-1 || index>=sint(value_size) ) - i = value_size - 1; - else - i = index; - - - for( ; i>=0 ; --i) - { - if( table[i] != l.table[i] ) - return table[i] < l.table[i]; - } - - // they're equal - return false; - } - - - - /*! - this method returns true if 'this' is bigger than 'l' - - 'index' is an index of the first word from will be the comparison performed - (note: we start the comparison from back - from the last word, when index is -1 /default/ - it is automatically set into the last word) - - I introduced it for some kind of optimization made in the second division algorithm (Div2) - */ - bool CmpBigger(const UInt & l, sint index = -1) const - { - sint i; - - if( index==-1 || index>=sint(value_size) ) - i = value_size - 1; - else - i = index; - - - for( ; i>=0 ; --i) - { - if( table[i] != l.table[i] ) - return table[i] > l.table[i]; - } - - // they're equal - return false; - } - - - /*! - this method returns true if 'this' is equal 'l' - - 'index' is an index of the first word from will be the comparison performed - (note: we start the comparison from back - from the last word, when index is -1 /default/ - it is automatically set into the last word) - */ - bool CmpEqual(const UInt & l, sint index = -1) const - { - sint i; - - if( index==-1 || index>=sint(value_size) ) - i = value_size - 1; - else - i = index; - - - for( ; i>=0 ; --i) - if( table[i] != l.table[i] ) - return false; - - return true; - } - - - - /*! - this method returns true if 'this' is smaller than or equal 'l' - - 'index' is an index of the first word from will be the comparison performed - (note: we start the comparison from back - from the last word, when index is -1 /default/ - it is automatically set into the last word) - */ - bool CmpSmallerEqual(const UInt & l, sint index=-1) const - { - sint i; - - if( index==-1 || index>=sint(value_size) ) - i = value_size - 1; - else - i = index; - - - for( ; i>=0 ; --i) - { - if( table[i] != l.table[i] ) - return table[i] < l.table[i]; - } - - // they're equal - return true; - } - - - - /*! - this method returns true if 'this' is bigger than or equal 'l' - - 'index' is an index of the first word from will be the comparison performed - (note: we start the comparison from back - from the last word, when index is -1 /default/ - it is automatically set into the last word) - */ - bool CmpBiggerEqual(const UInt & l, sint index=-1) const - { - sint i; - - if( index==-1 || index>=sint(value_size) ) - i = value_size - 1; - else - i = index; - - - for( ; i>=0 ; --i) - { - if( table[i] != l.table[i] ) - return table[i] > l.table[i]; - } - - // they're equal - return true; - } - - - /* - operators for comparising - */ - - bool operator<(const UInt & l) const - { - return CmpSmaller(l); - } - - - bool operator>(const UInt & l) const - { - return CmpBigger(l); - } - - - bool operator==(const UInt & l) const - { - return CmpEqual(l); - } - - - bool operator!=(const UInt & l) const - { - return !operator==(l); - } - - - bool operator<=(const UInt & l) const - { - return CmpSmallerEqual(l); - } - - bool operator>=(const UInt & l) const - { - return CmpBiggerEqual(l); - } - - - /*! - * - * standard mathematical operators - * - */ - - UInt operator-(const UInt & p2) const - { - UInt temp(*this); - - temp.Sub(p2); - - return temp; - } - - UInt & operator-=(const UInt & p2) - { - Sub(p2); - - return *this; - } - - UInt operator+(const UInt & p2) const - { - UInt temp(*this); - - temp.Add(p2); - - return temp; - } - - UInt & operator+=(const UInt & p2) - { - Add(p2); - - return *this; - } - - - UInt operator*(const UInt & p2) const - { - UInt temp(*this); - - temp.Mul(p2); - - return temp; - } - - - UInt & operator*=(const UInt & p2) - { - Mul(p2); - - return *this; - } - - - UInt operator/(const UInt & p2) const - { - UInt temp(*this); - - temp.Div(p2); - - return temp; - } - - - UInt & operator/=(const UInt & p2) - { - Div(p2); - - return *this; - } - - - UInt operator%(const UInt & p2) const - { - UInt temp(*this); - UInt remainder; - - temp.Div( p2, remainder ); - - return remainder; - } - - - UInt & operator%=(const UInt & p2) - { - UInt remainder; - - Div( p2, remainder ); - operator=(remainder); - - return *this; - } - - - /*! - Prefix operator e.g ++variable - */ - UInt & operator++() - { - AddOne(); - - return *this; - } - - - /*! - Postfix operator e.g variable++ - */ - UInt operator++(int) - { - UInt temp( *this ); - - AddOne(); - - return temp; - } - - - UInt & operator--() - { - SubOne(); - - return *this; - } - - - UInt operator--(int) - { - UInt temp( *this ); - - SubOne(); - - return temp; - } - - - - /*! - * - * bitwise operators - * - */ - - UInt operator~() const - { - UInt temp( *this ); - - temp.BitNot(); - - return temp; - } - - - UInt operator&(const UInt & p2) const - { - UInt temp( *this ); - - temp.BitAnd(p2); - - return temp; - } - - - UInt & operator&=(const UInt & p2) - { - BitAnd(p2); - - return *this; - } - - - UInt operator|(const UInt & p2) const - { - UInt temp( *this ); - - temp.BitOr(p2); - - return temp; - } - - - UInt & operator|=(const UInt & p2) - { - BitOr(p2); - - return *this; - } - - - UInt operator^(const UInt & p2) const - { - UInt temp( *this ); - - temp.BitXor(p2); - - return temp; - } - - - UInt & operator^=(const UInt & p2) - { - BitXor(p2); - - return *this; - } - - - UInt operator>>(int move) const - { - UInt temp( *this ); - - temp.Rcr(move); - - return temp; - } - - - UInt & operator>>=(int move) - { - Rcr(move); - - return *this; - } - - - UInt operator<<(int move) const - { - UInt temp( *this ); - - temp.Rcl(move); - - return temp; - } - - - UInt & operator<<=(int move) - { - Rcl(move); - - return *this; - } - - - /*! - * - * input/output operators for standard streams - * - * (they are very simple, in the future they should be changed) - * - */ - - -private: - - - /*! - an auxiliary method for outputing to standard streams - */ - template - static ostream_type & OutputToStream(ostream_type & s, const UInt & l) - { - string_type ss; - - l.ToString(ss); - s << ss; - - return s; - } - - -public: - - - /*! - output to standard streams - */ - friend std::ostream & operator<<(std::ostream & s, const UInt & l) - { - return OutputToStream(s, l); - } - - -#ifndef TTMATH_DONT_USE_WCHAR - - /*! - output to standard streams - */ - friend std::wostream & operator<<(std::wostream & s, const UInt & l) - { - return OutputToStream(s, l); - } - -#endif - - - -private: - - /*! - an auxiliary method for reading from standard streams - */ - template - static istream_type & InputFromStream(istream_type & s, UInt & l) - { - string_type ss; - - // char or wchar_t for operator>> - char_type z; - - // operator>> omits white characters if they're set for ommiting - s >> z; - - // we're reading only digits (base=10) - while( s.good() && Misc::CharToDigit(z, 10)>=0 ) - { - ss += z; - z = static_cast(s.get()); - } - - // we're leaving the last read character - // (it's not belonging to the value) - s.unget(); - - l.FromString(ss); - - return s; - } - -public: - - - /*! - input from standard streams - */ - friend std::istream & operator>>(std::istream & s, UInt & l) - { - return InputFromStream(s, l); - } - - -#ifndef TTMATH_DONT_USE_WCHAR - - /*! - input from standard streams - */ - friend std::wistream & operator>>(std::wistream & s, UInt & l) - { - return InputFromStream(s, l); - } - -#endif - - - /* - Following methods are defined in: - ttmathuint_x86.h - ttmathuint_x86_64.h - ttmathuint_noasm.h - */ - -#ifdef TTMATH_NOASM - static uint AddTwoWords(uint a, uint b, uint carry, uint * result); - static uint SubTwoWords(uint a, uint b, uint carry, uint * result); - -#ifdef TTMATH_PLATFORM64 - - union uint_ - { - struct - { - unsigned int low; // 32 bit - unsigned int high; // 32 bit - } u_; - - uint u; // 64 bit - }; - - - static void DivTwoWords2(uint a,uint b, uint c, uint * r, uint * rest); - static uint DivTwoWordsNormalize(uint_ & a_, uint_ & b_, uint_ & c_); - static uint DivTwoWordsUnnormalize(uint u, uint d); - static unsigned int DivTwoWordsCalculate(uint_ u_, unsigned int u3, uint_ v_); - static void MultiplySubtract(uint_ & u_, unsigned int & u3, unsigned int & q, uint_ v_); - -#endif // TTMATH_PLATFORM64 -#endif // TTMATH_NOASM - - -private: - uint Rcl2_one(uint c); - uint Rcr2_one(uint c); - uint Rcl2(uint bits, uint c); - uint Rcr2(uint bits, uint c); - -public: - static const char * LibTypeStr(); - static LibTypeCode LibType(); - uint Add(const UInt & ss2, uint c=0); - uint AddInt(uint value, uint index = 0); - uint AddTwoInts(uint x2, uint x1, uint index); - static uint AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result); - uint Sub(const UInt & ss2, uint c=0); - uint SubInt(uint value, uint index = 0); - static uint SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result); - static sint FindLeadingBitInWord(uint x); - static sint FindLowestBitInWord(uint x); - static uint SetBitInWord(uint & value, uint bit); - static void MulTwoWords(uint a, uint b, uint * result_high, uint * result_low); - static void DivTwoWords(uint a,uint b, uint c, uint * r, uint * rest); - -}; - - - -/*! - this specialization is needed in order to not confused the compiler "error: ISO C++ forbids zero-size array" - when compiling Mul3Big2() method -*/ -template<> -class UInt<0> -{ -public: - uint table[1]; - - void Mul2Big(const UInt<0> &, UInt<0> &) { TTMATH_ASSERT(false) }; - void SetZero() { TTMATH_ASSERT(false) }; - uint AddTwoInts(uint, uint, uint) { TTMATH_ASSERT(false) return 0; }; -}; - - -} //namespace - - -#include "ttmathuint_x86.h" -#include "ttmathuint_x86_64.h" -#include "ttmathuint_noasm.h" - -#endif diff --git a/extern/ttmath/ttmathuint_noasm.h b/extern/ttmath/ttmathuint_noasm.h deleted file mode 100644 index 07c73fc499..0000000000 --- a/extern/ttmath/ttmathuint_noasm.h +++ /dev/null @@ -1,1017 +0,0 @@ -/* - * This file is a part of TTMath Bignum Library - * and is distributed under the (new) BSD licence. - * Author: Tomasz Sowa - */ - -/* - * Copyright (c) 2006-2010, Tomasz Sowa - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name Tomasz Sowa nor the names of contributors to this - * project may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef headerfilettmathuint_noasm -#define headerfilettmathuint_noasm - - -#ifdef TTMATH_NOASM - -/*! - \file ttmathuint_noasm.h - \brief template class UInt with methods without any assembler code - - this file is included at the end of ttmathuint.h -*/ - - -namespace ttmath -{ - - /*! - returning the string represents the currect type of the library - we have following types: - asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits) - asm_gcc_32 - with asm code designed for GCC (32 bits) - asm_vc_64 - with asm for VC (64 bit) - asm_gcc_64 - with asm for GCC (64 bit) - no_asm_32 - pure C++ version (32 bit) - without any asm code - no_asm_64 - pure C++ version (64 bit) - without any asm code - */ - template - const char * UInt::LibTypeStr() - { - #ifdef TTMATH_PLATFORM32 - static const char info[] = "no_asm_32"; - #endif - - #ifdef TTMATH_PLATFORM64 - static const char info[] = "no_asm_64"; - #endif - - return info; - } - - - /*! - returning the currect type of the library - */ - template - LibTypeCode UInt::LibType() - { - #ifdef TTMATH_PLATFORM32 - LibTypeCode info = no_asm_32; - #endif - - #ifdef TTMATH_PLATFORM64 - LibTypeCode info = no_asm_64; - #endif - - return info; - } - - - /*! - this method adds two words together - returns carry - - this method is created only when TTMATH_NOASM macro is defined - */ - template - uint UInt::AddTwoWords(uint a, uint b, uint carry, uint * result) - { - uint temp; - - if( carry == 0 ) - { - temp = a + b; - - if( temp < a ) - carry = 1; - } - else - { - carry = 1; - temp = a + b + carry; - - if( temp > a ) // !(temp<=a) - carry = 0; - } - - *result = temp; - - return carry; - } - - - - /*! - this method adding ss2 to the this and adding carry if it's defined - (this = this + ss2 + c) - - c must be zero or one (might be a bigger value than 1) - function returns carry (1) (if it was) - */ - - template - uint UInt::Add(const UInt & ss2, uint c) - { - uint i; - - for(i=0 ; i - uint UInt::AddInt(uint value, uint index) - { - uint i, c; - - TTMATH_ASSERT( index < value_size ) - - - c = AddTwoWords(table[index], value, 0, &table[index]); - - for(i=index+1 ; i - uint UInt::AddTwoInts(uint x2, uint x1, uint index) - { - uint i, c; - - TTMATH_ASSERT( index < value_size - 1 ) - - - c = AddTwoWords(table[index], x1, 0, &table[index]); - c = AddTwoWords(table[index+1], x2, c, &table[index+1]); - - for(i=index+2 ; i - uint UInt::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) - { - uint i, c = 0; - - TTMATH_ASSERT( ss1_size >= ss2_size ) - - for(i=0 ; i - uint UInt::SubTwoWords(uint a, uint b, uint carry, uint * result) - { - if( carry == 0 ) - { - *result = a - b; - - if( a < b ) - carry = 1; - } - else - { - carry = 1; - *result = a - b - carry; - - if( a > b ) // !(a <= b ) - carry = 0; - } - - return carry; - } - - - - - /*! - this method's subtracting ss2 from the 'this' and subtracting - carry if it has been defined - (this = this - ss2 - c) - - c must be zero or one (might be a bigger value than 1) - function returns carry (1) (if it was) - */ - template - uint UInt::Sub(const UInt & ss2, uint c) - { - uint i; - - for(i=0 ; i - uint UInt::SubInt(uint value, uint index) - { - uint i, c; - - TTMATH_ASSERT( index < value_size ) - - - c = SubTwoWords(table[index], value, 0, &table[index]); - - for(i=index+1 ; i - uint UInt::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) - { - uint i, c = 0; - - TTMATH_ASSERT( ss1_size >= ss2_size ) - - for(i=0 ; i - uint UInt::Rcl2_one(uint c) - { - uint i, new_c; - - if( c != 0 ) - c = 1; - - for(i=0 ; i this -> return value - - the highest *bit* will be held the 'c' and - the state of one additional bit (on the right hand side) - will be returned - - for example: - let this is 000000010 - after Rcr2_one(1) there'll be 100000001 and Rcr2_one returns 0 - */ - template - uint UInt::Rcr2_one(uint c) - { - sint i; // signed i - uint new_c; - - if( c != 0 ) - c = TTMATH_UINT_HIGHEST_BIT; - - for(i=sint(value_size)-1 ; i>=0 ; --i) - { - new_c = (table[i] & 1) ? TTMATH_UINT_HIGHEST_BIT : 0; - table[i] = (table[i] >> 1) | c; - c = new_c; - } - - c = (c != 0)? 1 : 0; - - TTMATH_LOGC("UInt::Rcr2_one", c) - - return c; - } - - - - - /*! - this method moves all bits into the left hand side - return value <- this <- c - - the lowest *bits* will be held the 'c' and - the state of one additional bit (on the left hand side) - will be returned - - for example: - let this is 001010000 - after Rcl2(3, 1) there'll be 010000111 and Rcl2 returns 1 - */ - template - uint UInt::Rcl2(uint bits, uint c) - { - TTMATH_ASSERT( bits>0 && bits> move; - - for(i=0 ; i> move; - table[i] = (table[i] << bits) | c; - c = new_c; - } - - TTMATH_LOGC("UInt::Rcl2", (c & 1)) - - return (c & 1); - } - - - - - /*! - this method moves all bits into the right hand side - C -> this -> return value - - the highest *bits* will be held the 'c' and - the state of one additional bit (on the right hand side) - will be returned - - for example: - let this is 000000010 - after Rcr2(2, 1) there'll be 110000000 and Rcr2 returns 1 - */ - template - uint UInt::Rcr2(uint bits, uint c) - { - TTMATH_ASSERT( bits>0 && bits=0 ; --i) - { - new_c = table[i] << move; - table[i] = (table[i] >> bits) | c; - c = new_c; - } - - c = (c & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0; - - TTMATH_LOGC("UInt::Rcr2", c) - - return c; - } - - - - - /*! - this method returns the number of the highest set bit in x - if the 'x' is zero this method returns '-1' - */ - template - sint UInt::FindLeadingBitInWord(uint x) - { - if( x == 0 ) - return -1; - - uint bit = TTMATH_BITS_PER_UINT - 1; - - while( (x & TTMATH_UINT_HIGHEST_BIT) == 0 ) - { - x = x << 1; - --bit; - } - - return bit; - } - - - - /*! - this method returns the number of the highest set bit in x - if the 'x' is zero this method returns '-1' - */ - template - sint UInt::FindLowestBitInWord(uint x) - { - if( x == 0 ) - return -1; - - uint bit = 0; - - while( (x & 1) == 0 ) - { - x = x >> 1; - ++bit; - } - - return bit; - } - - - - /*! - this method sets a special bit in the 'value' - and returns the last state of the bit (zero or one) - - bit is from <0,TTMATH_BITS_PER_UINT-1> - - e.g. - uint x = 100; - uint bit = SetBitInWord(x, 3); - now: x = 108 and bit = 0 - */ - template - uint UInt::SetBitInWord(uint & value, uint bit) - { - TTMATH_ASSERT( bit < TTMATH_BITS_PER_UINT ) - - uint mask = 1; - - if( bit > 0 ) - mask = mask << bit; - - uint last = value & mask; - value = value | mask; - - return (last != 0) ? 1 : 0; - } - - - - - - - /*! - * - * Multiplication - * - * - */ - - - /*! - multiplication: result_high:result_low = a * b - result_high - higher word of the result - result_low - lower word of the result - - this methos never returns a carry - this method is used in the second version of the multiplication algorithms - */ - template - void UInt::MulTwoWords(uint a, uint b, uint * result_high, uint * result_low) - { - #ifdef TTMATH_PLATFORM32 - - /* - on 32bit platforms we have defined 'unsigned long long int' type known as 'ulint' in ttmath namespace - this type has 64 bits, then we're using only one multiplication: 32bit * 32bit = 64bit - */ - - union uint_ - { - struct - { - uint low; // 32 bits - uint high; // 32 bits - } u_; - - ulint u; // 64 bits - } res; - - res.u = ulint(a) * ulint(b); // multiply two 32bit words, the result has 64 bits - - *result_high = res.u_.high; - *result_low = res.u_.low; - - #else - - /* - 64 bits platforms - - we don't have a native type which has 128 bits - then we're splitting 'a' and 'b' to 4 parts (high and low halves) - and using 4 multiplications (with additions and carry correctness) - */ - - uint_ a_; - uint_ b_; - uint_ res_high1, res_high2; - uint_ res_low1, res_low2; - - a_.u = a; - b_.u = b; - - /* - the multiplication is as follows (schoolbook algorithm with O(n^2) ): - - 32 bits 32 bits - - +--------------------------------+ - | a_.u_.high | a_.u_.low | - +--------------------------------+ - | b_.u_.high | b_.u_.low | - +--------------------------------+--------------------------------+ - | res_high1.u | res_low1.u | - +--------------------------------+--------------------------------+ - | res_high2.u | res_low2.u | - +--------------------------------+--------------------------------+ - - 64 bits 64 bits - */ - - - uint_ temp; - - res_low1.u = uint(b_.u_.low) * uint(a_.u_.low); - - temp.u = uint(res_low1.u_.high) + uint(b_.u_.low) * uint(a_.u_.high); - res_low1.u_.high = temp.u_.low; - res_high1.u_.low = temp.u_.high; - res_high1.u_.high = 0; - - res_low2.u_.low = 0; - temp.u = uint(b_.u_.high) * uint(a_.u_.low); - res_low2.u_.high = temp.u_.low; - - res_high2.u = uint(b_.u_.high) * uint(a_.u_.high) + uint(temp.u_.high); - - uint c = AddTwoWords(res_low1.u, res_low2.u, 0, &res_low2.u); - AddTwoWords(res_high1.u, res_high2.u, c, &res_high2.u); // there is no carry from here - - *result_high = res_high2.u; - *result_low = res_low2.u; - - #endif - } - - - - - /*! - * - * Division - * - * - */ - - - /*! - this method calculates 64bits word a:b / 32bits c (a higher, b lower word) - r = a:b / c and rest - remainder - - * - * WARNING: - * the c has to be suitably large for the result being keeped in one word, - * if c is equal zero there'll be a hardware interruption (0) - * and probably the end of your program - * - */ - template - void UInt::DivTwoWords(uint a, uint b, uint c, uint * r, uint * rest) - { - // (a < c ) for the result to be one word - TTMATH_ASSERT( c != 0 && a < c ) - - #ifdef TTMATH_PLATFORM32 - - union - { - struct - { - uint low; // 32 bits - uint high; // 32 bits - } u_; - - ulint u; // 64 bits - } ab; - - ab.u_.high = a; - ab.u_.low = b; - - *r = uint(ab.u / c); - *rest = uint(ab.u % c); - - #else - - uint_ c_; - c_.u = c; - - - if( a == 0 ) - { - *r = b / c; - *rest = b % c; - } - else - if( c_.u_.high == 0 ) - { - // higher half of 'c' is zero - // then higher half of 'a' is zero too (look at the asserts at the beginning - 'a' is smaller than 'c') - uint_ a_, b_, res_, temp1, temp2; - - a_.u = a; - b_.u = b; - - temp1.u_.high = a_.u_.low; - temp1.u_.low = b_.u_.high; - - res_.u_.high = (unsigned int)(temp1.u / c); - temp2.u_.high = (unsigned int)(temp1.u % c); - temp2.u_.low = b_.u_.low; - - res_.u_.low = (unsigned int)(temp2.u / c); - *rest = temp2.u % c; - - *r = res_.u; - } - else - { - return DivTwoWords2(a, b, c, r, rest); - } - - #endif - } - - -#ifdef TTMATH_PLATFORM64 - - - /*! - this method is available only on 64bit platforms - - the same algorithm like the third division algorithm in ttmathuint.h - but now with the radix=2^32 - */ - template - void UInt::DivTwoWords2(uint a, uint b, uint c, uint * r, uint * rest) - { - // a is not zero - // c_.u_.high is not zero - - uint_ a_, b_, c_, u_, q_; - unsigned int u3; // 32 bit - - a_.u = a; - b_.u = b; - c_.u = c; - - // normalizing - uint d = DivTwoWordsNormalize(a_, b_, c_); - - // loop from j=1 to j=0 - // the first step (for j=2) is skipped because our result is only in one word, - // (first 'q' were 0 and nothing would be changed) - u_.u_.high = a_.u_.high; - u_.u_.low = a_.u_.low; - u3 = b_.u_.high; - q_.u_.high = DivTwoWordsCalculate(u_, u3, c_); - MultiplySubtract(u_, u3, q_.u_.high, c_); - - u_.u_.high = u_.u_.low; - u_.u_.low = u3; - u3 = b_.u_.low; - q_.u_.low = DivTwoWordsCalculate(u_, u3, c_); - MultiplySubtract(u_, u3, q_.u_.low, c_); - - *r = q_.u; - - // unnormalizing for the remainder - u_.u_.high = u_.u_.low; - u_.u_.low = u3; - *rest = DivTwoWordsUnnormalize(u_.u, d); - } - - - - - template - uint UInt::DivTwoWordsNormalize(uint_ & a_, uint_ & b_, uint_ & c_) - { - uint d = 0; - - for( ; (c_.u & TTMATH_UINT_HIGHEST_BIT) == 0 ; ++d ) - { - c_.u = c_.u << 1; - - uint bc = b_.u & TTMATH_UINT_HIGHEST_BIT; // carry from 'b' - - b_.u = b_.u << 1; - a_.u = a_.u << 1; // carry bits from 'a' are simply skipped - - if( bc ) - a_.u = a_.u | 1; - } - - return d; - } - - - template - uint UInt::DivTwoWordsUnnormalize(uint u, uint d) - { - if( d == 0 ) - return u; - - u = u >> d; - - return u; - } - - - template - unsigned int UInt::DivTwoWordsCalculate(uint_ u_, unsigned int u3, uint_ v_) - { - bool next_test; - uint_ qp_, rp_, temp_; - - qp_.u = u_.u / uint(v_.u_.high); - rp_.u = u_.u % uint(v_.u_.high); - - TTMATH_ASSERT( qp_.u_.high==0 || qp_.u_.high==1 ) - - do - { - bool decrease = false; - - if( qp_.u_.high == 1 ) - decrease = true; - else - { - temp_.u_.high = rp_.u_.low; - temp_.u_.low = u3; - - if( qp_.u * uint(v_.u_.low) > temp_.u ) - decrease = true; - } - - next_test = false; - - if( decrease ) - { - --qp_.u; - rp_.u += v_.u_.high; - - if( rp_.u_.high == 0 ) - next_test = true; - } - } - while( next_test ); - - return qp_.u_.low; - } - - - template - void UInt::MultiplySubtract(uint_ & u_, unsigned int & u3, unsigned int & q, uint_ v_) - { - uint_ temp_; - - uint res_high; - uint res_low; - - MulTwoWords(v_.u, q, &res_high, &res_low); - - uint_ sub_res_high_; - uint_ sub_res_low_; - - temp_.u_.high = u_.u_.low; - temp_.u_.low = u3; - - uint c = SubTwoWords(temp_.u, res_low, 0, &sub_res_low_.u); - - temp_.u_.high = 0; - temp_.u_.low = u_.u_.high; - c = SubTwoWords(temp_.u, res_high, c, &sub_res_high_.u); - - if( c ) - { - --q; - - c = AddTwoWords(sub_res_low_.u, v_.u, 0, &sub_res_low_.u); - AddTwoWords(sub_res_high_.u, 0, c, &sub_res_high_.u); - } - - u_.u_.high = sub_res_high_.u_.low; - u_.u_.low = sub_res_low_.u_.high; - u3 = sub_res_low_.u_.low; - } - -#endif // #ifdef TTMATH_PLATFORM64 - - - -} //namespace - - -#endif //ifdef TTMATH_NOASM -#endif - - - - diff --git a/extern/ttmath/ttmathuint_x86.h b/extern/ttmath/ttmathuint_x86.h deleted file mode 100644 index 1dd087f524..0000000000 --- a/extern/ttmath/ttmathuint_x86.h +++ /dev/null @@ -1,1602 +0,0 @@ -/* - * This file is a part of TTMath Bignum Library - * and is distributed under the (new) BSD licence. - * Author: Tomasz Sowa - */ - -/* - * Copyright (c) 2006-2009, Tomasz Sowa - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name Tomasz Sowa nor the names of contributors to this - * project may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - - - -#ifndef headerfilettmathuint_x86 -#define headerfilettmathuint_x86 - - -#ifndef TTMATH_NOASM -#ifdef TTMATH_PLATFORM32 - - -/*! - \file ttmathuint_x86.h - \brief template class UInt with assembler code for 32bit x86 processors - - this file is included at the end of ttmathuint.h -*/ - - - -/*! - \brief a namespace for the TTMath library -*/ -namespace ttmath -{ - - /*! - returning the string represents the currect type of the library - we have following types: - asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits) - asm_gcc_32 - with asm code designed for GCC (32 bits) - asm_vc_64 - with asm for VC (64 bit) - asm_gcc_64 - with asm for GCC (64 bit) - no_asm_32 - pure C++ version (32 bit) - without any asm code - no_asm_64 - pure C++ version (64 bit) - without any asm code - */ - template - const char * UInt::LibTypeStr() - { - #ifndef __GNUC__ - static const char info[] = "asm_vc_32"; - #endif - - #ifdef __GNUC__ - static const char info[] = "asm_gcc_32"; - #endif - - return info; - } - - - /*! - returning the currect type of the library - */ - template - LibTypeCode UInt::LibType() - { - #ifndef __GNUC__ - LibTypeCode info = asm_vc_32; - #endif - - #ifdef __GNUC__ - LibTypeCode info = asm_gcc_32; - #endif - - return info; - } - - - - /*! - * - * basic mathematic functions - * - */ - - - /*! - adding ss2 to the this and adding carry if it's defined - (this = this + ss2 + c) - - c must be zero or one (might be a bigger value than 1) - function returns carry (1) (if it has been) - */ - template - uint UInt::Add(const UInt & ss2, uint c) - { - uint b = value_size; - uint * p1 = table; - uint * p2 = const_cast(ss2.table); - - // we don't have to use TTMATH_REFERENCE_ASSERT here - // this algorithm doesn't require it - - #ifndef __GNUC__ - - // this part might be compiled with for example visual c - - __asm - { - push eax - push ebx - push ecx - push edx - push esi - - mov ecx,[b] - - mov ebx,[p1] - mov esi,[p2] - - xor edx,edx // edx=0 - mov eax,[c] - neg eax // CF=1 if rax!=0 , CF=0 if rax==0 - - ttmath_loop: - mov eax,[esi+edx*4] - adc [ebx+edx*4],eax - - inc edx - dec ecx - jnz ttmath_loop - - adc ecx, ecx - mov [c], ecx - - pop esi - pop edx - pop ecx - pop ebx - pop eax - } - - - - #endif - - - #ifdef __GNUC__ - uint dummy, dummy2; - // this part should be compiled with gcc - - __asm__ __volatile__( - - "xorl %%edx, %%edx \n" - "negl %%eax \n" // CF=1 if rax!=0 , CF=0 if rax==0 - - "1: \n" - "movl (%%esi,%%edx,4), %%eax \n" - "adcl %%eax, (%%ebx,%%edx,4) \n" - - "incl %%edx \n" - "decl %%ecx \n" - "jnz 1b \n" - - "adc %%ecx, %%ecx \n" - - : "=c" (c), "=a" (dummy), "=d" (dummy2) - : "0" (b), "1" (c), "b" (p1), "S" (p2) - : "cc", "memory" ); - #endif - - TTMATH_LOGC("UInt::Add", c) - - return c; - } - - - - /*! - adding one word (at a specific position) - and returning a carry (if it has been) - - e.g. - - if we've got (value_size=3): - table[0] = 10; - table[1] = 30; - table[2] = 5; - and we call: - AddInt(2,1) - then it'll be: - table[0] = 10; - table[1] = 30 + 2; - table[2] = 5; - - of course if there was a carry from table[2] it would be returned - */ - template - uint UInt::AddInt(uint value, uint index) - { - uint b = value_size; - uint * p1 = table; - uint c; - - TTMATH_ASSERT( index < value_size ) - - #ifndef __GNUC__ - - __asm - { - push eax - push ebx - push ecx - push edx - - mov ecx, [b] - sub ecx, [index] - - mov edx, [index] - mov ebx, [p1] - - mov eax, [value] - - ttmath_loop: - add [ebx+edx*4], eax - jnc ttmath_end - - mov eax, 1 - inc edx - dec ecx - jnz ttmath_loop - - ttmath_end: - setc al - movzx edx, al - mov [c], edx - - pop edx - pop ecx - pop ebx - pop eax - } - - #endif - - - #ifdef __GNUC__ - uint dummy, dummy2; - - __asm__ __volatile__( - - "subl %%edx, %%ecx \n" - - "1: \n" - "addl %%eax, (%%ebx,%%edx,4) \n" - "jnc 2f \n" - - "movl $1, %%eax \n" - "incl %%edx \n" - "decl %%ecx \n" - "jnz 1b \n" - - "2: \n" - "setc %%al \n" - "movzx %%al, %%edx \n" - - : "=d" (c), "=a" (dummy), "=c" (dummy2) - : "0" (index), "1" (value), "2" (b), "b" (p1) - : "cc", "memory" ); - - #endif - - TTMATH_LOGC("UInt::AddInt", c) - - return c; - } - - - - - /*! - adding only two unsigned words to the existing value - and these words begin on the 'index' position - (it's used in the multiplication algorithm 2) - - index should be equal or smaller than value_size-2 (index <= value_size-2) - x1 - lower word, x2 - higher word - - for example if we've got value_size equal 4 and: - table[0] = 3 - table[1] = 4 - table[2] = 5 - table[3] = 6 - then let - x1 = 10 - x2 = 20 - and - index = 1 - - the result of this method will be: - table[0] = 3 - table[1] = 4 + x1 = 14 - table[2] = 5 + x2 = 25 - table[3] = 6 - - and no carry at the end of table[3] - - (of course if there was a carry in table[2](5+20) then - this carry would be passed to the table[3] etc.) - */ - template - uint UInt::AddTwoInts(uint x2, uint x1, uint index) - { - uint b = value_size; - uint * p1 = table; - uint c; - - TTMATH_ASSERT( index < value_size - 1 ) - - #ifndef __GNUC__ - __asm - { - push eax - push ebx - push ecx - push edx - - mov ecx, [b] - sub ecx, [index] - - mov ebx, [p1] - mov edx, [index] - - mov eax, [x1] - add [ebx+edx*4], eax - inc edx - dec ecx - - mov eax, [x2] - - ttmath_loop: - adc [ebx+edx*4], eax - jnc ttmath_end - - mov eax, 0 - inc edx - dec ecx - jnz ttmath_loop - - ttmath_end: - setc al - movzx edx, al - mov [c], edx - - pop edx - pop ecx - pop ebx - pop eax - - } - #endif - - - #ifdef __GNUC__ - uint dummy, dummy2; - - __asm__ __volatile__( - - "subl %%edx, %%ecx \n" - - "addl %%esi, (%%ebx,%%edx,4) \n" - "incl %%edx \n" - "decl %%ecx \n" - - "1: \n" - "adcl %%eax, (%%ebx,%%edx,4) \n" - "jnc 2f \n" - - "mov $0, %%eax \n" - "incl %%edx \n" - "decl %%ecx \n" - "jnz 1b \n" - - "2: \n" - "setc %%al \n" - "movzx %%al, %%eax \n" - - : "=a" (c), "=c" (dummy), "=d" (dummy2) - : "0" (x2), "1" (b), "2" (index), "b" (p1), "S" (x1) - : "cc", "memory" ); - - #endif - - TTMATH_LOGC("UInt::AddTwoInts", c) - - return c; - } - - - - /*! - this static method addes one vector to the other - 'ss1' is larger in size or equal to 'ss2' - - ss1 points to the first (larger) vector - ss2 points to the second vector - ss1_size - size of the ss1 (and size of the result too) - ss2_size - size of the ss2 - result - is the result vector (which has size the same as ss1: ss1_size) - - Example: ss1_size is 5, ss2_size is 3 - ss1: ss2: result (output): - 5 1 5+1 - 4 3 4+3 - 2 7 2+7 - 6 6 - 9 9 - of course the carry is propagated and will be returned from the last item - (this method is used by the Karatsuba multiplication algorithm) - */ - template - uint UInt::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) - { - TTMATH_ASSERT( ss1_size >= ss2_size ) - - uint rest = ss1_size - ss2_size; - uint c; - - #ifndef __GNUC__ - - // this part might be compiled with for example visual c - __asm - { - pushad - - mov ecx, [ss2_size] - xor edx, edx // edx = 0, cf = 0 - - mov esi, [ss1] - mov ebx, [ss2] - mov edi, [result] - - ttmath_loop: - mov eax, [esi+edx*4] - adc eax, [ebx+edx*4] - mov [edi+edx*4], eax - - inc edx - dec ecx - jnz ttmath_loop - - adc ecx, ecx // ecx has the cf state - - mov ebx, [rest] - or ebx, ebx - jz ttmath_end - - xor ebx, ebx // ebx = 0 - neg ecx // setting cf from ecx - mov ecx, [rest] // ecx is != 0 - - ttmath_loop2: - mov eax, [esi+edx*4] - adc eax, ebx - mov [edi+edx*4], eax - - inc edx - dec ecx - jnz ttmath_loop2 - - adc ecx, ecx - - ttmath_end: - mov [c], ecx - - popad - } - - #endif - - - #ifdef __GNUC__ - - // this part should be compiled with gcc - uint dummy1, dummy2, dummy3; - - __asm__ __volatile__( - "push %%edx \n" - "xor %%edx, %%edx \n" // edx = 0, cf = 0 - "1: \n" - "mov (%%esi,%%edx,4), %%eax \n" - "adc (%%ebx,%%edx,4), %%eax \n" - "mov %%eax, (%%edi,%%edx,4) \n" - - "inc %%edx \n" - "dec %%ecx \n" - "jnz 1b \n" - - "adc %%ecx, %%ecx \n" // ecx has the cf state - "pop %%eax \n" // eax = rest - - "or %%eax, %%eax \n" - "jz 3f \n" - - "xor %%ebx, %%ebx \n" // ebx = 0 - "neg %%ecx \n" // setting cf from ecx - "mov %%eax, %%ecx \n" // ecx=rest and is != 0 - "2: \n" - "mov (%%esi, %%edx, 4), %%eax \n" - "adc %%ebx, %%eax \n" - "mov %%eax, (%%edi, %%edx, 4) \n" - - "inc %%edx \n" - "dec %%ecx \n" - "jnz 2b \n" - - "adc %%ecx, %%ecx \n" - "3: \n" - - : "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3) - : "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result) - : "cc", "memory" ); - - #endif - - TTMATH_VECTOR_LOGC("UInt::AddVector", c, result, ss1_size) - - return c; - } - - - /*! - subtracting ss2 from the 'this' and subtracting - carry if it has been defined - (this = this - ss2 - c) - - c must be zero or one (might be a bigger value than 1) - function returns carry (1) (if it has been) - */ - template - uint UInt::Sub(const UInt & ss2, uint c) - { - uint b = value_size; - uint * p1 = table; - uint * p2 = const_cast(ss2.table); - - // we don't have to use TTMATH_REFERENCE_ASSERT here - // this algorithm doesn't require it - - #ifndef __GNUC__ - - __asm - { - push eax - push ebx - push ecx - push edx - push esi - - mov ecx,[b] - - mov ebx,[p1] - mov esi,[p2] - - xor edx,edx // edx=0 - mov eax,[c] - neg eax // CF=1 if rax!=0 , CF=0 if rax==0 - - ttmath_loop: - mov eax,[esi+edx*4] - sbb [ebx+edx*4],eax - - inc edx - dec ecx - jnz ttmath_loop - - adc ecx, ecx - mov [c], ecx - - pop esi - pop edx - pop ecx - pop ebx - pop eax - } - - #endif - - - #ifdef __GNUC__ - uint dummy, dummy2; - - __asm__ __volatile__( - - "xorl %%edx, %%edx \n" - "negl %%eax \n" // CF=1 if rax!=0 , CF=0 if rax==0 - - "1: \n" - "movl (%%esi,%%edx,4), %%eax \n" - "sbbl %%eax, (%%ebx,%%edx,4) \n" - - "incl %%edx \n" - "decl %%ecx \n" - "jnz 1b \n" - - "adc %%ecx, %%ecx \n" - - : "=c" (c), "=a" (dummy), "=d" (dummy2) - : "0" (b), "1" (c), "b" (p1), "S" (p2) - : "cc", "memory" ); - - #endif - - TTMATH_LOGC("UInt::Sub", c) - - return c; - } - - - - - /*! - this method subtracts one word (at a specific position) - and returns a carry (if it was) - - e.g. - - if we've got (value_size=3): - table[0] = 10; - table[1] = 30; - table[2] = 5; - and we call: - SubInt(2,1) - then it'll be: - table[0] = 10; - table[1] = 30 - 2; - table[2] = 5; - - of course if there was a carry from table[2] it would be returned - */ - template - uint UInt::SubInt(uint value, uint index) - { - uint b = value_size; - uint * p1 = table; - uint c; - - TTMATH_ASSERT( index < value_size ) - - #ifndef __GNUC__ - - __asm - { - push eax - push ebx - push ecx - push edx - - mov ecx, [b] - sub ecx, [index] - - mov edx, [index] - mov ebx, [p1] - - mov eax, [value] - - ttmath_loop: - sub [ebx+edx*4], eax - jnc ttmath_end - - mov eax, 1 - inc edx - dec ecx - jnz ttmath_loop - - ttmath_end: - setc al - movzx edx, al - mov [c], edx - - pop edx - pop ecx - pop ebx - pop eax - } - - #endif - - - #ifdef __GNUC__ - uint dummy, dummy2; - - __asm__ __volatile__( - - "subl %%edx, %%ecx \n" - - "1: \n" - "subl %%eax, (%%ebx,%%edx,4) \n" - "jnc 2f \n" - - "movl $1, %%eax \n" - "incl %%edx \n" - "decl %%ecx \n" - "jnz 1b \n" - - "2: \n" - "setc %%al \n" - "movzx %%al, %%edx \n" - - : "=d" (c), "=a" (dummy), "=c" (dummy2) - : "0" (index), "1" (value), "2" (b), "b" (p1) - : "cc", "memory" ); - - #endif - - TTMATH_LOGC("UInt::SubInt", c) - - return c; - } - - - - /*! - this static method subtractes one vector from the other - 'ss1' is larger in size or equal to 'ss2' - - ss1 points to the first (larger) vector - ss2 points to the second vector - ss1_size - size of the ss1 (and size of the result too) - ss2_size - size of the ss2 - result - is the result vector (which has size the same as ss1: ss1_size) - - Example: ss1_size is 5, ss2_size is 3 - ss1: ss2: result (output): - 5 1 5-1 - 4 3 4-3 - 2 7 2-7 - 6 6-1 (the borrow from previous item) - 9 9 - return (carry): 0 - of course the carry (borrow) is propagated and will be returned from the last item - (this method is used by the Karatsuba multiplication algorithm) - */ - template - uint UInt::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) - { - TTMATH_ASSERT( ss1_size >= ss2_size ) - - uint rest = ss1_size - ss2_size; - uint c; - - #ifndef __GNUC__ - - // this part might be compiled with for example visual c - - /* - the asm code is nearly the same as in AddVector - only two instructions 'adc' are changed to 'sbb' - */ - __asm - { - pushad - - mov ecx, [ss2_size] - xor edx, edx // edx = 0, cf = 0 - - mov esi, [ss1] - mov ebx, [ss2] - mov edi, [result] - - ttmath_loop: - mov eax, [esi+edx*4] - sbb eax, [ebx+edx*4] - mov [edi+edx*4], eax - - inc edx - dec ecx - jnz ttmath_loop - - adc ecx, ecx // ecx has the cf state - - mov ebx, [rest] - or ebx, ebx - jz ttmath_end - - xor ebx, ebx // ebx = 0 - neg ecx // setting cf from ecx - mov ecx, [rest] // ecx is != 0 - - ttmath_loop2: - mov eax, [esi+edx*4] - sbb eax, ebx - mov [edi+edx*4], eax - - inc edx - dec ecx - jnz ttmath_loop2 - - adc ecx, ecx - - ttmath_end: - mov [c], ecx - - popad - } - - #endif - - - #ifdef __GNUC__ - - // this part should be compiled with gcc - uint dummy1, dummy2, dummy3; - - __asm__ __volatile__( - "push %%edx \n" - "xor %%edx, %%edx \n" // edx = 0, cf = 0 - "1: \n" - "mov (%%esi,%%edx,4), %%eax \n" - "sbb (%%ebx,%%edx,4), %%eax \n" - "mov %%eax, (%%edi,%%edx,4) \n" - - "inc %%edx \n" - "dec %%ecx \n" - "jnz 1b \n" - - "adc %%ecx, %%ecx \n" // ecx has the cf state - "pop %%eax \n" // eax = rest - - "or %%eax, %%eax \n" - "jz 3f \n" - - "xor %%ebx, %%ebx \n" // ebx = 0 - "neg %%ecx \n" // setting cf from ecx - "mov %%eax, %%ecx \n" // ecx=rest and is != 0 - "2: \n" - "mov (%%esi, %%edx, 4), %%eax \n" - "sbb %%ebx, %%eax \n" - "mov %%eax, (%%edi, %%edx, 4) \n" - - "inc %%edx \n" - "dec %%ecx \n" - "jnz 2b \n" - - "adc %%ecx, %%ecx \n" - "3: \n" - - : "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3) - : "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result) - : "cc", "memory" ); - - #endif - - TTMATH_VECTOR_LOGC("UInt::SubVector", c, result, ss1_size) - - return c; - } - - - - /*! - this method moves all bits into the left hand side - return value <- this <- c - - the lowest *bit* will be held the 'c' and - the state of one additional bit (on the left hand side) - will be returned - - for example: - let this is 001010000 - after Rcl2_one(1) there'll be 010100001 and Rcl2_one returns 0 - */ - template - uint UInt::Rcl2_one(uint c) - { - uint b = value_size; - uint * p1 = table; - - #ifndef __GNUC__ - __asm - { - push ebx - push ecx - push edx - - mov ebx, [p1] - xor edx, edx - mov ecx, [c] - neg ecx - mov ecx, [b] - - ttmath_loop: - rcl dword ptr [ebx+edx*4], 1 - - inc edx - dec ecx - jnz ttmath_loop - - adc ecx, ecx - mov [c], ecx - - pop edx - pop ecx - pop ebx - } - #endif - - - #ifdef __GNUC__ - uint dummy, dummy2; - - __asm__ __volatile__( - - "xorl %%edx, %%edx \n" // edx=0 - "negl %%eax \n" // CF=1 if eax!=0 , CF=0 if eax==0 - - "1: \n" - "rcll $1, (%%ebx, %%edx, 4) \n" - - "incl %%edx \n" - "decl %%ecx \n" - "jnz 1b \n" - - "adcl %%ecx, %%ecx \n" - - : "=c" (c), "=a" (dummy), "=d" (dummy2) - : "0" (b), "1" (c), "b" (p1) - : "cc", "memory" ); - - #endif - - TTMATH_LOGC("UInt::Rcl2_one", c) - - return c; - } - - - - /*! - this method moves all bits into the right hand side - c -> this -> return value - - the highest *bit* will be held the 'c' and - the state of one additional bit (on the right hand side) - will be returned - - for example: - let this is 000000010 - after Rcr2_one(1) there'll be 100000001 and Rcr2_one returns 0 - */ - template - uint UInt::Rcr2_one(uint c) - { - uint b = value_size; - uint * p1 = table; - - #ifndef __GNUC__ - __asm - { - push ebx - push ecx - - mov ebx, [p1] - mov ecx, [c] - neg ecx - mov ecx, [b] - - ttmath_loop: - rcr dword ptr [ebx+ecx*4-4], 1 - - dec ecx - jnz ttmath_loop - - adc ecx, ecx - mov [c], ecx - - pop ecx - pop ebx - } - #endif - - - #ifdef __GNUC__ - uint dummy; - - __asm__ __volatile__( - - "negl %%eax \n" // CF=1 if eax!=0 , CF=0 if eax==0 - - "1: \n" - "rcrl $1, -4(%%ebx, %%ecx, 4) \n" - - "decl %%ecx \n" - "jnz 1b \n" - - "adcl %%ecx, %%ecx \n" - - : "=c" (c), "=a" (dummy) - : "0" (b), "1" (c), "b" (p1) - : "cc", "memory" ); - - #endif - - TTMATH_LOGC("UInt::Rcr2_one", c) - - return c; - } - - - -#ifdef _MSC_VER -#pragma warning (disable : 4731) -//warning C4731: frame pointer register 'ebp' modified by inline assembly code -#endif - - - - /*! - this method moves all bits into the left hand side - return value <- this <- c - - the lowest *bits* will be held the 'c' and - the state of one additional bit (on the left hand side) - will be returned - - for example: - let this is 001010000 - after Rcl2(3, 1) there'll be 010000111 and Rcl2 returns 1 - */ - template - uint UInt::Rcl2(uint bits, uint c) - { - TTMATH_ASSERT( bits>0 && bits edx -> cf) (cl times) - "movl %%edx, %%ebp \n" // ebp = edx = mask - "movl %%esi, %%ecx \n" - - "xorl %%edx, %%edx \n" - "movl %%edx, %%esi \n" - "orl %%eax, %%eax \n" - "cmovnz %%ebp, %%esi \n" // if(c) esi=mask else esi=0 - - "1: \n" - "roll %%cl, (%%ebx,%%edx,4) \n" - - "movl (%%ebx,%%edx,4), %%eax \n" - "andl %%ebp, %%eax \n" - "xorl %%eax, (%%ebx,%%edx,4) \n" - "orl %%esi, (%%ebx,%%edx,4) \n" - "movl %%eax, %%esi \n" - - "incl %%edx \n" - "decl %%edi \n" - "jnz 1b \n" - - "and $1, %%eax \n" - - "pop %%ebp \n" - - : "=a" (c), "=D" (dummy), "=S" (dummy2), "=d" (dummy3) - : "0" (c), "1" (b), "b" (p1), "c" (bits) - : "cc", "memory" ); - - #endif - - TTMATH_LOGC("UInt::Rcl2", c) - - return c; - } - - - - - /*! - this method moves all bits into the right hand side - C -> this -> return value - - the highest *bits* will be held the 'c' and - the state of one additional bit (on the right hand side) - will be returned - - for example: - let this is 000000010 - after Rcr2(2, 1) there'll be 110000000 and Rcr2 returns 1 - */ - template - uint UInt::Rcr2(uint bits, uint c) - { - TTMATH_ASSERT( bits>0 && bits - sint UInt::FindLeadingBitInWord(uint x) - { - sint result; - - #ifndef __GNUC__ - __asm - { - push eax - push edx - - mov edx,-1 - bsr eax,[x] - cmovz eax,edx - mov [result], eax - - pop edx - pop eax - } - #endif - - - #ifdef __GNUC__ - uint dummy; - - __asm__ ( - - "movl $-1, %1 \n" - "bsrl %2, %0 \n" - "cmovz %1, %0 \n" - - : "=r" (result), "=&r" (dummy) - : "r" (x) - : "cc" ); - - #endif - - return result; - } - - - - /* - this method returns the number of the smallest set bit in one 32-bit word - if the 'x' is zero this method returns '-1' - */ - template - sint UInt::FindLowestBitInWord(uint x) - { - sint result; - - #ifndef __GNUC__ - __asm - { - push eax - push edx - - mov edx,-1 - bsf eax,[x] - cmovz eax,edx - mov [result], eax - - pop edx - pop eax - } - #endif - - - #ifdef __GNUC__ - uint dummy; - - __asm__ ( - - "movl $-1, %1 \n" - "bsfl %2, %0 \n" - "cmovz %1, %0 \n" - - : "=r" (result), "=&r" (dummy) - : "r" (x) - : "cc" ); - - #endif - - return result; - } - - - - /*! - this method sets a special bit in the 'value' - and returns the last state of the bit (zero or one) - - bit is from <0,31> - e.g. - uint x = 100; - uint bit = SetBitInWord(x, 3); - now: x = 108 and bit = 0 - */ - template - uint UInt::SetBitInWord(uint & value, uint bit) - { - TTMATH_ASSERT( bit < TTMATH_BITS_PER_UINT ) - - uint old_bit; - uint v = value; - - #ifndef __GNUC__ - __asm - { - push ebx - push eax - - mov eax, [v] - mov ebx, [bit] - bts eax, ebx - mov [v], eax - - setc bl - movzx ebx, bl - mov [old_bit], ebx - - pop eax - pop ebx - } - #endif - - - #ifdef __GNUC__ - __asm__ ( - - "btsl %%ebx, %%eax \n" - "setc %%bl \n" - "movzx %%bl, %%ebx \n" - - : "=a" (v), "=b" (old_bit) - : "0" (v), "1" (bit) - : "cc" ); - - #endif - - value = v; - - return old_bit; - } - - - - - /*! - multiplication: result_high:result_low = a * b - result_high - higher word of the result - result_low - lower word of the result - - this methos never returns a carry - this method is used in the second version of the multiplication algorithms - */ - template - void UInt::MulTwoWords(uint a, uint b, uint * result_high, uint * result_low) - { - /* - we must use these temporary variables in order to inform the compilator - that value pointed with result1 and result2 has changed - - this has no effect in visual studio but it's useful when - using gcc and options like -Ox - */ - uint result1_; - uint result2_; - - #ifndef __GNUC__ - - __asm - { - push eax - push edx - - mov eax, [a] - mul dword ptr [b] - - mov [result2_], edx - mov [result1_], eax - - pop edx - pop eax - } - - #endif - - - #ifdef __GNUC__ - - __asm__ ( - - "mull %%edx \n" - - : "=a" (result1_), "=d" (result2_) - : "0" (a), "1" (b) - : "cc" ); - - #endif - - - *result_low = result1_; - *result_high = result2_; - } - - - - - - /*! - * - * Division - * - * - */ - - - - - /*! - this method calculates 64bits word a:b / 32bits c (a higher, b lower word) - r = a:b / c and rest - remainder - - * - * WARNING: - * if r (one word) is too small for the result or c is equal zero - * there'll be a hardware interruption (0) - * and probably the end of your program - * - */ - template - void UInt::DivTwoWords(uint a, uint b, uint c, uint * r, uint * rest) - { - uint r_; - uint rest_; - /* - these variables have similar meaning like those in - the multiplication algorithm MulTwoWords - */ - - TTMATH_ASSERT( c != 0 ) - - #ifndef __GNUC__ - __asm - { - push eax - push edx - - mov edx, [a] - mov eax, [b] - div dword ptr [c] - - mov [r_], eax - mov [rest_], edx - - pop edx - pop eax - } - #endif - - - #ifdef __GNUC__ - - __asm__ ( - - "divl %%ecx \n" - - : "=a" (r_), "=d" (rest_) - : "0" (b), "1" (a), "c" (c) - : "cc" ); - - #endif - - - *r = r_; - *rest = rest_; - - } - - - -} //namespace - - - -#endif //ifdef TTMATH_PLATFORM32 -#endif //ifndef TTMATH_NOASM -#endif diff --git a/extern/ttmath/ttmathuint_x86_64.h b/extern/ttmath/ttmathuint_x86_64.h deleted file mode 100644 index 188fc5e7bd..0000000000 --- a/extern/ttmath/ttmathuint_x86_64.h +++ /dev/null @@ -1,1146 +0,0 @@ -/* - * This file is a part of TTMath Bignum Library - * and is distributed under the (new) BSD licence. - * Author: Tomasz Sowa - */ - -/* - * Copyright (c) 2006-2010, Tomasz Sowa - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name Tomasz Sowa nor the names of contributors to this - * project may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - - -#ifndef headerfilettmathuint_x86_64 -#define headerfilettmathuint_x86_64 - - -#ifndef TTMATH_NOASM -#ifdef TTMATH_PLATFORM64 - - -/*! - \file ttmathuint_x86_64.h - \brief template class UInt with assembler code for 64bit x86_64 processors - - this file is included at the end of ttmathuint.h -*/ - -#ifndef __GNUC__ -#include -#endif - - -namespace ttmath -{ - - #ifndef __GNUC__ - - extern "C" - { - uint __fastcall ttmath_adc_x64(uint* p1, const uint* p2, uint nSize, uint c); - uint __fastcall ttmath_addindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue); - uint __fastcall ttmath_addindexed2_x64(uint* p1, uint nSize, uint nPos, uint nValue1, uint nValue2); - uint __fastcall ttmath_addvector_x64(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result); - uint __fastcall ttmath_sbb_x64(uint* p1, const uint* p2, uint nSize, uint c); - uint __fastcall ttmath_subindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue); - uint __fastcall ttmath_subvector_x64(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result); - uint __fastcall ttmath_rcl_x64(uint* p1, uint nSize, uint nLowestBit); - uint __fastcall ttmath_rcr_x64(uint* p1, uint nSize, uint nLowestBit); - uint __fastcall ttmath_div_x64(uint* pnValHi, uint* pnValLo, uint nDiv); - uint __fastcall ttmath_rcl2_x64(uint* p1, uint nSize, uint nBits, uint c); - uint __fastcall ttmath_rcr2_x64(uint* p1, uint nSize, uint nBits, uint c); - }; - #endif - - - /*! - returning the string represents the currect type of the library - we have following types: - asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits) - asm_gcc_32 - with asm code designed for GCC (32 bits) - asm_vc_64 - with asm for VC (64 bit) - asm_gcc_64 - with asm for GCC (64 bit) - no_asm_32 - pure C++ version (32 bit) - without any asm code - no_asm_64 - pure C++ version (64 bit) - without any asm code - */ - template - const char * UInt::LibTypeStr() - { - #ifndef __GNUC__ - static const char info[] = "asm_vc_64"; - #endif - - #ifdef __GNUC__ - static const char info[] = "asm_gcc_64"; - #endif - - return info; - } - - - /*! - returning the currect type of the library - */ - template - LibTypeCode UInt::LibType() - { - #ifndef __GNUC__ - LibTypeCode info = asm_vc_64; - #endif - - #ifdef __GNUC__ - LibTypeCode info = asm_gcc_64; - #endif - - return info; - } - - - /*! - * - * basic mathematic functions - * - */ - - - - /*! - this method adding ss2 to the this and adding carry if it's defined - (this = this + ss2 + c) - - ***this method is created only on a 64bit platform*** - - c must be zero or one (might be a bigger value than 1) - function returns carry (1) (if it was) - */ - template - uint UInt::Add(const UInt & ss2, uint c) - { - uint b = value_size; - uint * p1 = table; - const uint * p2 = ss2.table; - - // we don't have to use TTMATH_REFERENCE_ASSERT here - // this algorithm doesn't require it - - #ifndef __GNUC__ - c = ttmath_adc_x64(p1,p2,b,c); - #endif - - #ifdef __GNUC__ - uint dummy, dummy2; - - /* - this part should be compiled with gcc - */ - __asm__ __volatile__( - - "xorq %%rdx, %%rdx \n" - "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 - - "1: \n" - "movq (%%rsi,%%rdx,8), %%rax \n" - "adcq %%rax, (%%rbx,%%rdx,8) \n" - - "incq %%rdx \n" - "decq %%rcx \n" - "jnz 1b \n" - - "adcq %%rcx, %%rcx \n" - - : "=c" (c), "=a" (dummy), "=d" (dummy2) - : "0" (b), "1" (c), "b" (p1), "S" (p2) - : "cc", "memory" ); - - #endif - - TTMATH_LOGC("UInt::Add", c) - - return c; - } - - - - /*! - this method adds one word (at a specific position) - and returns a carry (if it was) - - ***this method is created only on a 64bit platform*** - - - if we've got (value_size=3): - table[0] = 10; - table[1] = 30; - table[2] = 5; - and we call: - AddInt(2,1) - then it'll be: - table[0] = 10; - table[1] = 30 + 2; - table[2] = 5; - - of course if there was a carry from table[2] it would be returned - */ - template - uint UInt::AddInt(uint value, uint index) - { - uint b = value_size; - uint * p1 = table; - uint c; - - TTMATH_ASSERT( index < value_size ) - - #ifndef __GNUC__ - c = ttmath_addindexed_x64(p1,b,index,value); - #endif - - - #ifdef __GNUC__ - uint dummy, dummy2; - - __asm__ __volatile__( - - "subq %%rdx, %%rcx \n" - - "1: \n" - "addq %%rax, (%%rbx,%%rdx,8) \n" - "jnc 2f \n" - - "movq $1, %%rax \n" - "incq %%rdx \n" - "decq %%rcx \n" - "jnz 1b \n" - - "2: \n" - "setc %%al \n" - "movzx %%al, %%rdx \n" - - : "=d" (c), "=a" (dummy), "=c" (dummy2) - : "0" (index), "1" (value), "2" (b), "b" (p1) - : "cc", "memory" ); - - #endif - - TTMATH_LOGC("UInt::AddInt", c) - - return c; - } - - - - /*! - this method adds only two unsigned words to the existing value - and these words begin on the 'index' position - (it's used in the multiplication algorithm 2) - - ***this method is created only on a 64bit platform*** - - index should be equal or smaller than value_size-2 (index <= value_size-2) - x1 - lower word, x2 - higher word - - for example if we've got value_size equal 4 and: - table[0] = 3 - table[1] = 4 - table[2] = 5 - table[3] = 6 - then let - x1 = 10 - x2 = 20 - and - index = 1 - - the result of this method will be: - table[0] = 3 - table[1] = 4 + x1 = 14 - table[2] = 5 + x2 = 25 - table[3] = 6 - - and no carry at the end of table[3] - - (of course if there was a carry in table[2](5+20) then - this carry would be passed to the table[3] etc.) - */ - template - uint UInt::AddTwoInts(uint x2, uint x1, uint index) - { - uint b = value_size; - uint * p1 = table; - uint c; - - TTMATH_ASSERT( index < value_size - 1 ) - - #ifndef __GNUC__ - c = ttmath_addindexed2_x64(p1,b,index,x1,x2); - #endif - - - #ifdef __GNUC__ - uint dummy, dummy2; - - __asm__ __volatile__( - - "subq %%rdx, %%rcx \n" - - "addq %%rsi, (%%rbx,%%rdx,8) \n" - "incq %%rdx \n" - "decq %%rcx \n" - - "1: \n" - "adcq %%rax, (%%rbx,%%rdx,8) \n" - "jnc 2f \n" - - "mov $0, %%rax \n" - "incq %%rdx \n" - "decq %%rcx \n" - "jnz 1b \n" - - "2: \n" - "setc %%al \n" - "movzx %%al, %%rax \n" - - : "=a" (c), "=c" (dummy), "=d" (dummy2) - : "0" (x2), "1" (b), "2" (index), "b" (p1), "S" (x1) - : "cc", "memory" ); - - #endif - - TTMATH_LOGC("UInt::AddTwoInts", c) - - return c; - } - - - - /*! - this static method addes one vector to the other - 'ss1' is larger in size or equal to 'ss2' - - ss1 points to the first (larger) vector - ss2 points to the second vector - ss1_size - size of the ss1 (and size of the result too) - ss2_size - size of the ss2 - result - is the result vector (which has size the same as ss1: ss1_size) - - Example: ss1_size is 5, ss2_size is 3 - ss1: ss2: result (output): - 5 1 5+1 - 4 3 4+3 - 2 7 2+7 - 6 6 - 9 9 - of course the carry is propagated and will be returned from the last item - (this method is used by the Karatsuba multiplication algorithm) - */ - template - uint UInt::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) - { - TTMATH_ASSERT( ss1_size >= ss2_size ) - - uint c; - - #ifndef __GNUC__ - c = ttmath_addvector_x64(ss1, ss2, ss1_size, ss2_size, result); - #endif - - - #ifdef __GNUC__ - uint dummy1, dummy2, dummy3; - uint rest = ss1_size - ss2_size; - - // this part should be compiled with gcc - - __asm__ __volatile__( - "mov %%rdx, %%r8 \n" - "xor %%rdx, %%rdx \n" // rdx = 0, cf = 0 - "1: \n" - "mov (%%rsi,%%rdx,8), %%rax \n" - "adc (%%rbx,%%rdx,8), %%rax \n" - "mov %%rax, (%%rdi,%%rdx,8) \n" - - "inc %%rdx \n" - "dec %%rcx \n" - "jnz 1b \n" - - "adc %%rcx, %%rcx \n" // rcx has the cf state - - "or %%r8, %%r8 \n" - "jz 3f \n" - - "xor %%rbx, %%rbx \n" // ebx = 0 - "neg %%rcx \n" // setting cf from rcx - "mov %%r8, %%rcx \n" // rcx=rest and is != 0 - "2: \n" - "mov (%%rsi, %%rdx, 8), %%rax \n" - "adc %%rbx, %%rax \n" - "mov %%rax, (%%rdi, %%rdx, 8) \n" - - "inc %%rdx \n" - "dec %%rcx \n" - "jnz 2b \n" - - "adc %%rcx, %%rcx \n" - "3: \n" - - : "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3) - : "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result) - : "%r8", "cc", "memory" ); - - #endif - - TTMATH_VECTOR_LOGC("UInt::AddVector", c, result, ss1_size) - - return c; - } - - - - /*! - this method's subtracting ss2 from the 'this' and subtracting - carry if it has been defined - (this = this - ss2 - c) - - ***this method is created only on a 64bit platform*** - - c must be zero or one (might be a bigger value than 1) - function returns carry (1) (if it was) - */ - template - uint UInt::Sub(const UInt & ss2, uint c) - { - uint b = value_size; - uint * p1 = table; - const uint * p2 = ss2.table; - - // we don't have to use TTMATH_REFERENCE_ASSERT here - // this algorithm doesn't require it - - #ifndef __GNUC__ - c = ttmath_sbb_x64(p1,p2,b,c); - #endif - - - #ifdef __GNUC__ - uint dummy, dummy2; - - __asm__ __volatile__( - - "xorq %%rdx, %%rdx \n" - "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 - - "1: \n" - "movq (%%rsi,%%rdx,8), %%rax \n" - "sbbq %%rax, (%%rbx,%%rdx,8) \n" - - "incq %%rdx \n" - "decq %%rcx \n" - "jnz 1b \n" - - "adcq %%rcx, %%rcx \n" - - : "=c" (c), "=a" (dummy), "=d" (dummy2) - : "0" (b), "1" (c), "b" (p1), "S" (p2) - : "cc", "memory" ); - - #endif - - TTMATH_LOGC("UInt::Sub", c) - - return c; - } - - - - /*! - this method subtracts one word (at a specific position) - and returns a carry (if it was) - - ***this method is created only on a 64bit platform*** - - if we've got (value_size=3): - table[0] = 10; - table[1] = 30; - table[2] = 5; - and we call: - SubInt(2,1) - then it'll be: - table[0] = 10; - table[1] = 30 - 2; - table[2] = 5; - - of course if there was a carry from table[2] it would be returned - */ - template - uint UInt::SubInt(uint value, uint index) - { - uint b = value_size; - uint * p1 = table; - uint c; - - TTMATH_ASSERT( index < value_size ) - - #ifndef __GNUC__ - c = ttmath_subindexed_x64(p1,b,index,value); - #endif - - - #ifdef __GNUC__ - uint dummy, dummy2; - - __asm__ __volatile__( - - "subq %%rdx, %%rcx \n" - - "1: \n" - "subq %%rax, (%%rbx,%%rdx,8) \n" - "jnc 2f \n" - - "movq $1, %%rax \n" - "incq %%rdx \n" - "decq %%rcx \n" - "jnz 1b \n" - - "2: \n" - "setc %%al \n" - "movzx %%al, %%rdx \n" - - : "=d" (c), "=a" (dummy), "=c" (dummy2) - : "0" (index), "1" (value), "2" (b), "b" (p1) - : "cc", "memory" ); - - #endif - - TTMATH_LOGC("UInt::SubInt", c) - - return c; - } - - - /*! - this static method subtractes one vector from the other - 'ss1' is larger in size or equal to 'ss2' - - ss1 points to the first (larger) vector - ss2 points to the second vector - ss1_size - size of the ss1 (and size of the result too) - ss2_size - size of the ss2 - result - is the result vector (which has size the same as ss1: ss1_size) - - Example: ss1_size is 5, ss2_size is 3 - ss1: ss2: result (output): - 5 1 5-1 - 4 3 4-3 - 2 7 2-7 - 6 6-1 (the borrow from previous item) - 9 9 - return (carry): 0 - of course the carry (borrow) is propagated and will be returned from the last item - (this method is used by the Karatsuba multiplication algorithm) - */ - template - uint UInt::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) - { - TTMATH_ASSERT( ss1_size >= ss2_size ) - - uint c; - - #ifndef __GNUC__ - c = ttmath_subvector_x64(ss1, ss2, ss1_size, ss2_size, result); - #endif - - - #ifdef __GNUC__ - - // the asm code is nearly the same as in AddVector - // only two instructions 'adc' are changed to 'sbb' - - uint dummy1, dummy2, dummy3; - uint rest = ss1_size - ss2_size; - - __asm__ __volatile__( - "mov %%rdx, %%r8 \n" - "xor %%rdx, %%rdx \n" // rdx = 0, cf = 0 - "1: \n" - "mov (%%rsi,%%rdx,8), %%rax \n" - "sbb (%%rbx,%%rdx,8), %%rax \n" - "mov %%rax, (%%rdi,%%rdx,8) \n" - - "inc %%rdx \n" - "dec %%rcx \n" - "jnz 1b \n" - - "adc %%rcx, %%rcx \n" // rcx has the cf state - - "or %%r8, %%r8 \n" - "jz 3f \n" - - "xor %%rbx, %%rbx \n" // ebx = 0 - "neg %%rcx \n" // setting cf from rcx - "mov %%r8, %%rcx \n" // rcx=rest and is != 0 - "2: \n" - "mov (%%rsi, %%rdx, 8), %%rax \n" - "sbb %%rbx, %%rax \n" - "mov %%rax, (%%rdi, %%rdx, 8) \n" - - "inc %%rdx \n" - "dec %%rcx \n" - "jnz 2b \n" - - "adc %%rcx, %%rcx \n" - "3: \n" - - : "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3) - : "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result) - : "%r8", "cc", "memory" ); - - #endif - - TTMATH_VECTOR_LOGC("UInt::SubVector", c, result, ss1_size) - - return c; - } - - - /*! - this method moves all bits into the left hand side - return value <- this <- c - - the lowest *bit* will be held the 'c' and - the state of one additional bit (on the left hand side) - will be returned - - for example: - let this is 001010000 - after Rcl2_one(1) there'll be 010100001 and Rcl2_one returns 0 - - ***this method is created only on a 64bit platform*** - */ - template - uint UInt::Rcl2_one(uint c) - { - sint b = value_size; - uint * p1 = table; - - - #ifndef __GNUC__ - c = ttmath_rcl_x64(p1,b,c); - #endif - - - #ifdef __GNUC__ - uint dummy, dummy2; - - __asm__ __volatile__( - - "xorq %%rdx, %%rdx \n" // rdx=0 - "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 - - "1: \n" - "rclq $1, (%%rbx, %%rdx, 8) \n" - - "incq %%rdx \n" - "decq %%rcx \n" - "jnz 1b \n" - - "adcq %%rcx, %%rcx \n" - - : "=c" (c), "=a" (dummy), "=d" (dummy2) - : "0" (b), "1" (c), "b" (p1) - : "cc", "memory" ); - - #endif - - TTMATH_LOGC("UInt::Rcl2_one", c) - - return c; - } - - - /*! - this method moves all bits into the right hand side - c -> this -> return value - - the highest *bit* will be held the 'c' and - the state of one additional bit (on the right hand side) - will be returned - - for example: - let this is 000000010 - after Rcr2_one(1) there'll be 100000001 and Rcr2_one returns 0 - - ***this method is created only on a 64bit platform*** - */ - template - uint UInt::Rcr2_one(uint c) - { - sint b = value_size; - uint * p1 = table; - - - #ifndef __GNUC__ - c = ttmath_rcr_x64(p1,b,c); - #endif - - - #ifdef __GNUC__ - uint dummy; - - __asm__ __volatile__( - - "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 - - "1: \n" - "rcrq $1, -8(%%rbx, %%rcx, 8) \n" - - "decq %%rcx \n" - "jnz 1b \n" - - "adcq %%rcx, %%rcx \n" - - : "=c" (c), "=a" (dummy) - : "0" (b), "1" (c), "b" (p1) - : "cc", "memory" ); - - #endif - - TTMATH_LOGC("UInt::Rcr2_one", c) - - return c; - } - - - - /*! - this method moves all bits into the left hand side - return value <- this <- c - - the lowest *bits* will be held the 'c' and - the state of one additional bit (on the left hand side) - will be returned - - for example: - let this is 001010000 - after Rcl2(3, 1) there'll be 010000111 and Rcl2 returns 1 - - ***this method is created only on a 64bit platform*** - */ - template - uint UInt::Rcl2(uint bits, uint c) - { - TTMATH_ASSERT( bits>0 && bits this -> return value - - the highest *bits* will be held the 'c' and - the state of one additional bit (on the right hand side) - will be returned - - for example: - let this is 000000010 - after Rcr2(2, 1) there'll be 110000000 and Rcr2 returns 1 - - ***this method is created only on a 64bit platform*** - */ - template - uint UInt::Rcr2(uint bits, uint c) - { - TTMATH_ASSERT( bits>0 && bits - sint UInt::FindLeadingBitInWord(uint x) - { - sint result; - - - #ifndef __GNUC__ - - unsigned long nIndex = 0; - - if( _BitScanReverse64(&nIndex,x) == 0 ) - result = -1; - else - result = nIndex; - - #endif - - - #ifdef __GNUC__ - uint dummy; - - __asm__ ( - - "movq $-1, %1 \n" - "bsrq %2, %0 \n" - "cmovz %1, %0 \n" - - : "=r" (result), "=&r" (dummy) - : "r" (x) - : "cc" ); - - #endif - - - return result; - } - - - /* - this method returns the number of the highest set bit in one 64-bit word - if the 'x' is zero this method returns '-1' - - ***this method is created only on a 64bit platform*** - */ - template - sint UInt::FindLowestBitInWord(uint x) - { - sint result; - - - #ifndef __GNUC__ - - unsigned long nIndex = 0; - - if( _BitScanForward64(&nIndex,x) == 0 ) - result = -1; - else - result = nIndex; - - #endif - - - #ifdef __GNUC__ - uint dummy; - - __asm__ ( - - "movq $-1, %1 \n" - "bsfq %2, %0 \n" - "cmovz %1, %0 \n" - - : "=r" (result), "=&r" (dummy) - : "r" (x) - : "cc" ); - - #endif - - - return result; - } - - - /*! - this method sets a special bit in the 'value' - and returns the last state of the bit (zero or one) - - ***this method is created only on a 64bit platform*** - - bit is from <0,63> - - e.g. - uint x = 100; - uint bit = SetBitInWord(x, 3); - now: x = 108 and bit = 0 - */ - template - uint UInt::SetBitInWord(uint & value, uint bit) - { - TTMATH_ASSERT( bit < TTMATH_BITS_PER_UINT ) - - uint old_bit; - uint v = value; - - - #ifndef __GNUC__ - old_bit = _bittestandset64((__int64*)&value,bit) != 0; - #endif - - - #ifdef __GNUC__ - - __asm__ ( - - "btsq %%rbx, %%rax \n" - "setc %%bl \n" - "movzx %%bl, %%rbx \n" - - : "=a" (v), "=b" (old_bit) - : "0" (v), "1" (bit) - : "cc" ); - - #endif - - value = v; - - return old_bit; - } - - - /*! - * - * Multiplication - * - * - */ - - - /*! - multiplication: result_high:result_low = a * b - result_high - higher word of the result - result_low - lower word of the result - - this methos never returns a carry - this method is used in the second version of the multiplication algorithms - - ***this method is created only on a 64bit platform*** - */ - template - void UInt::MulTwoWords(uint a, uint b, uint * result_high, uint * result_low) - { - /* - we must use these temporary variables in order to inform the compilator - that value pointed with result1 and result2 has changed - - this has no effect in visual studio but it's usefull when - using gcc and options like -O - */ - uint result1_; - uint result2_; - - - #ifndef __GNUC__ - result1_ = _umul128(a,b,&result2_); - #endif - - - #ifdef __GNUC__ - - __asm__ ( - - "mulq %%rdx \n" - - : "=a" (result1_), "=d" (result2_) - : "0" (a), "1" (b) - : "cc" ); - - #endif - - - *result_low = result1_; - *result_high = result2_; - } - - - - - /*! - * - * Division - * - * - */ - - - /*! - this method calculates 64bits word a:b / 32bits c (a higher, b lower word) - r = a:b / c and rest - remainder - - ***this method is created only on a 64bit platform*** - - * - * WARNING: - * if r (one word) is too small for the result or c is equal zero - * there'll be a hardware interruption (0) - * and probably the end of your program - * - */ - template - void UInt::DivTwoWords(uint a,uint b, uint c, uint * r, uint * rest) - { - uint r_; - uint rest_; - /* - these variables have similar meaning like those in - the multiplication algorithm MulTwoWords - */ - - TTMATH_ASSERT( c != 0 ) - - - #ifndef __GNUC__ - - ttmath_div_x64(&a,&b,c); - r_ = a; - rest_ = b; - - #endif - - - #ifdef __GNUC__ - - __asm__ ( - - "divq %%rcx \n" - - : "=a" (r_), "=d" (rest_) - : "d" (a), "a" (b), "c" (c) - : "cc" ); - - #endif - - - *r = r_; - *rest = rest_; - } - -} //namespace - - -#endif //ifdef TTMATH_PLATFORM64 -#endif //ifndef TTMATH_NOASM -#endif - - diff --git a/extern/ttmath/ttmathuint_x86_64_msvc.asm b/extern/ttmath/ttmathuint_x86_64_msvc.asm deleted file mode 100644 index aae113f636..0000000000 --- a/extern/ttmath/ttmathuint_x86_64_msvc.asm +++ /dev/null @@ -1,548 +0,0 @@ -; -; This file is a part of TTMath Bignum Library -; and is distributed under the (new) BSD licence. -; Author: Christian Kaiser -; - -; -; Copyright (c) 2009, Christian Kaiser -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions are met: -; -; * Redistributions of source code must retain the above copyright notice, -; this list of conditions and the following disclaimer. -; -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in the -; documentation and/or other materials provided with the distribution. -; -; * Neither the name Christian Kaiser nor the names of contributors to this -; project may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -; ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -; THE POSSIBILITY OF SUCH DAMAGE. -; - -; -; compile with debug info: ml64.exe /c /Zd /Zi ttmathuint_x86_64_msvc.asm -; compile without debug info: ml64.exe /c ttmathuint_x86_64_msvc.asm -; this creates ttmathuint_x86_64_msvc.obj file which can be linked with your program -; - -PUBLIC ttmath_adc_x64 -PUBLIC ttmath_addindexed_x64 -PUBLIC ttmath_addindexed2_x64 -PUBLIC ttmath_addvector_x64 - -PUBLIC ttmath_sbb_x64 -PUBLIC ttmath_subindexed_x64 -PUBLIC ttmath_subvector_x64 - -PUBLIC ttmath_rcl_x64 -PUBLIC ttmath_rcr_x64 - -PUBLIC ttmath_rcl2_x64 -PUBLIC ttmath_rcr2_x64 - -PUBLIC ttmath_div_x64 - -; -; Microsoft x86_64 convention: http://msdn.microsoft.com/en-us/library/9b372w95.aspx -; -; "rax, rcx, rdx, r8-r11 are volatile." -; "rbx, rbp, rdi, rsi, r12-r15 are nonvolatile." -; - - -.CODE - - - ALIGN 8 - -;---------------------------------------- - -ttmath_adc_x64 PROC - ; rcx = p1 - ; rdx = p2 - ; r8 = nSize - ; r9 = nCarry - - xor rax, rax - xor r11, r11 - sub rax, r9 ; sets CARRY if r9 != 0 - - ALIGN 16 - loop1: - mov rax,qword ptr [rdx + r11 * 8] - adc qword ptr [rcx + r11 * 8], rax - lea r11, [r11+1] - dec r8 - jnz loop1 - - setc al - movzx rax, al - - ret - -ttmath_adc_x64 ENDP - -;---------------------------------------- - - ALIGN 8 - -;---------------------------------------- - -ttmath_addindexed_x64 PROC - - ; rcx = p1 - ; rdx = nSize - ; r8 = nPos - ; r9 = nValue - - xor rax, rax ; rax = result - sub rdx, r8 ; rdx = remaining count of uints - - add qword ptr [rcx + r8 * 8], r9 - jc next1 - - ret - -next1: - mov r9, 1 - - ALIGN 16 -loop1: - dec rdx - jz done_with_cy - lea r8, [r8+1] - add qword ptr [rcx + r8 * 8], r9 - jc loop1 - - ret - -done_with_cy: - lea rax, [rax+1] ; rax = 1 - - ret - -ttmath_addindexed_x64 ENDP - -;---------------------------------------- - - ALIGN 8 - -;---------------------------------------- - -ttmath_addindexed2_x64 PROC - - ; rcx = p1 (pointer) - ; rdx = b (value size) - ; r8 = nPos - ; r9 = nValue1 - ; [rsp+0x28] = nValue2 - - xor rax, rax ; return value - mov r11, rcx ; table - sub rdx, r8 ; rdx = remaining count of uints - mov r10, [rsp+028h] ; r10 = nValue2 - - add qword ptr [r11 + r8 * 8], r9 - lea r8, [r8+1] - lea rdx, [rdx-1] - adc qword ptr [r11 + r8 * 8], r10 - jc next - ret - - ALIGN 16 -loop1: - lea r8, [r8+1] - add qword ptr [r11 + r8 * 8], 1 - jc next - ret - -next: - dec rdx ; does not modify CY too... - jnz loop1 - lea rax, [rax+1] - ret - -ttmath_addindexed2_x64 ENDP - - - -;---------------------------------------- - - ALIGN 8 - -;---------------------------------------- - - -ttmath_addvector_x64 PROC - ; rcx = ss1 - ; rdx = ss2 - ; r8 = ss1_size - ; r9 = ss2_size - ; [rsp+0x28] = result - - mov r10, [rsp+028h] - sub r8, r9 - xor r11, r11 ; r11=0, cf=0 - - ALIGN 16 - loop1: - mov rax, qword ptr [rcx + r11 * 8] - adc rax, qword ptr [rdx + r11 * 8] - mov qword ptr [r10 + r11 * 8], rax - inc r11 - dec r9 - jnz loop1 - - adc r9, r9 ; r9 has the cf state - - or r8, r8 - jz done - - neg r9 ; setting cf from r9 - mov r9, 0 ; don't use xor here (cf is used) - loop2: - mov rax, qword ptr [rcx + r11 * 8] - adc rax, r9 - mov qword ptr [r10 + r11 * 8], rax - inc r11 - dec r8 - jnz loop2 - - adc r8, r8 - mov rax, r8 - - ret - -done: - mov rax, r9 - ret - -ttmath_addvector_x64 ENDP - - -;---------------------------------------- - - ALIGN 8 - -;---------------------------------------- - -ttmath_sbb_x64 PROC - - ; rcx = p1 - ; rdx = p2 - ; r8 = nCount - ; r9 = nCarry - - xor rax, rax - xor r11, r11 - sub rax, r9 ; sets CARRY if r9 != 0 - - ALIGN 16 - loop1: - mov rax,qword ptr [rdx + r11 * 8] - sbb qword ptr [rcx + r11 * 8], rax - lea r11, [r11+1] - dec r8 - jnz loop1 - - setc al - movzx rax, al - - ret - -ttmath_sbb_x64 ENDP - -;---------------------------------------- - - ALIGN 8 - -;---------------------------------------- - -ttmath_subindexed_x64 PROC - ; rcx = p1 - ; rdx = nSize - ; r8 = nPos - ; r9 = nValue - - sub rdx, r8 ; rdx = remaining count of uints - - ALIGN 16 -loop1: - sub qword ptr [rcx + r8 * 8], r9 - jnc done - - lea r8, [r8+1] - mov r9, 1 - dec rdx - jnz loop1 - - mov rax, 1 - ret - -done: - xor rax, rax - ret - -ttmath_subindexed_x64 ENDP - - - -;---------------------------------------- - - ALIGN 8 - -;---------------------------------------- - -; the same asm code as in addvector_x64 only two instructions 'adc' changed to 'sbb' - -ttmath_subvector_x64 PROC - ; rcx = ss1 - ; rdx = ss2 - ; r8 = ss1_size - ; r9 = ss2_size - ; [rsp+0x28] = result - - mov r10, [rsp+028h] - sub r8, r9 - xor r11, r11 ; r11=0, cf=0 - - ALIGN 16 - loop1: - mov rax, qword ptr [rcx + r11 * 8] - sbb rax, qword ptr [rdx + r11 * 8] - mov qword ptr [r10 + r11 * 8], rax - inc r11 - dec r9 - jnz loop1 - - adc r9, r9 ; r9 has the cf state - - or r8, r8 - jz done - - neg r9 ; setting cf from r9 - mov r9, 0 ; don't use xor here (cf is used) - loop2: - mov rax, qword ptr [rcx + r11 * 8] - sbb rax, r9 - mov qword ptr [r10 + r11 * 8], rax - inc r11 - dec r8 - jnz loop2 - - adc r8, r8 - mov rax, r8 - - ret - -done: - mov rax, r9 - ret - -ttmath_subvector_x64 ENDP - - - - -;---------------------------------------- - - ALIGN 8 - -;---------------------------------------- - -ttmath_rcl_x64 PROC - ; rcx = p1 - ; rdx = b - ; r8 = nLowestBit - - mov r11, rcx ; table - xor r10, r10 - neg r8 ; CY set if r8 <> 0 - - ALIGN 16 -loop1: - rcl qword ptr [r11 + r10 * 8], 1 - lea r10, [r10+1] - dec rdx - jnz loop1 - - setc al - movzx rax, al - - ret - -ttmath_rcl_x64 ENDP - -;---------------------------------------- - - ALIGN 8 - -;---------------------------------------- - -ttmath_rcr_x64 PROC - ; rcx = p1 - ; rdx = nSize - ; r8 = nLowestBit - - xor r10, r10 - neg r8 ; CY set if r8 <> 0 - - ALIGN 16 -loop1: - rcr qword ptr -8[rcx + rdx * 8], 1 - dec rdx - jnz loop1 - - setc al - movzx rax, al - - ret - -ttmath_rcr_x64 ENDP - -;---------------------------------------- - - ALIGN 8 - -;---------------------------------------- - -ttmath_div_x64 PROC - - ; rcx = &Hi - ; rdx = &Lo - ; r8 = nDiv - - mov r11, rcx - mov r10, rdx - - mov rdx, qword ptr [r11] - mov rax, qword ptr [r10] - div r8 - mov qword ptr [r10], rdx ; remainder - mov qword ptr [r11], rax ; value - - ret - -ttmath_div_x64 ENDP - -;---------------------------------------- - - ALIGN 8 - -;---------------------------------------- - -ttmath_rcl2_x64 PROC - ; rcx = p1 - ; rdx = nSize - ; r8 = bits - ; r9 = c - - push rbx - - mov r10, rcx ; r10 = p1 - xor rax, rax - - mov rcx, 64 - sub rcx, r8 - - mov r11, -1 - shr r11, cl ; r11 = mask - - mov rcx, r8 ; rcx = count of bits - - mov rbx, rax ; rbx = old value = 0 - or r9, r9 - cmovnz rbx, r11 ; if (c) then old value = mask - - mov r9, rax ; r9 = index (0..nSize-1) - - ALIGN 16 -loop1: - rol qword ptr [r10+r9*8], cl - mov rax, qword ptr [r10+r9*8] - and rax, r11 - xor qword ptr [r10+r9*8], rax - or qword ptr [r10+r9*8], rbx - mov rbx, rax - - lea r9, [r9+1] - dec rdx - - jnz loop1 - - and rax, 1 - pop rbx - ret - -ttmath_rcl2_x64 ENDP - -;---------------------------------------- - - ALIGN 8 - -;---------------------------------------- - -ttmath_rcr2_x64 PROC - ; rcx = p1 - ; rdx = nSize - ; r8 = bits - ; r9 = c - - push rbx - mov r10, rcx ; r10 = p1 - xor rax, rax - - mov rcx, 64 - sub rcx, r8 - - mov r11, -1 - shl r11, cl ; r11 = mask - - mov rcx, r8 ; rcx = count of bits - - mov rbx, rax ; rbx = old value = 0 - or r9, r9 - cmovnz rbx, r11 ; if (c) then old value = mask - - mov r9, rdx ; r9 = index (0..nSize-1) - lea r9, [r9-1] - - ALIGN 16 -loop1: - ror qword ptr [r10+r9*8], cl - mov rax, qword ptr [r10+r9*8] - and rax, r11 - xor qword ptr [r10+r9*8], rax - or qword ptr [r10+r9*8], rbx - mov rbx, rax - - lea r9, [r9-1] - dec rdx - - jnz loop1 - - rol rax, 1 - and rax, 1 - pop rbx - - ret - -ttmath_rcr2_x64 ENDP - -END diff --git a/src/common/Int128.cpp b/src/common/Int128.cpp index d3158dddeb..88414b041d 100644 --- a/src/common/Int128.cpp +++ b/src/common/Int128.cpp @@ -56,60 +56,18 @@ const CInt128 minus1(-1); namespace Firebird { -Int128 Int128::set(SLONG value, int scale) -{ - v = ttmath::sint(value); - setScale(scale); - return *this; -} - -Int128 Int128::set(SINT64 value, int scale) -{ -#ifdef TTMATH_PLATFORM32 - v = ttmath::slint(value); -#else - v = ttmath::sint(value); -#endif - setScale(scale); - return *this; -} - Int128 Int128::set(const char* value) { // This is simplified method - it does not perform all what's needed for CVT_decompose - v.FromString(value); - return *this; -} - -Int128 Int128::set(double value) -{ - bool sgn = false; - if (value < 0.0) - { - value = -value; - sgn = true; - } - - double parts[4]; - for (int i = 0; i < 4; ++i) + for (v = 0; ; ++value) { - parts[i] = value; - value /= p2_32; - } - fb_assert(value < 1.0); + if (*value < '0' or *value > '9') + break; - unsigned dwords[4]; - value = 0.0; - for (int i = 4; i--;) - { - dwords[i] = (parts[i] - value); - value += p2_32 * dwords[i]; + v *= 10; + v += (*value - '0'); } - setTable32(dwords); - if (sgn) - v.ChangeSign(); - return *this; } @@ -122,14 +80,14 @@ Int128 Int128::set(DecimalStatus decSt, Decimal128 value) value.getBcd(&bcd); fb_assert(bcd.exp == 0); - v.SetZero(); + v = 0; for (unsigned b = 0; b < sizeof(bcd.bcd); ++b) { - v.MulInt(10); - v.AddInt(bcd.bcd[b]); + v *= 10; + v += bcd.bcd[b]; } if (bcd.sign < 0) - v.ChangeSign(); + v = -v; return *this; } @@ -138,9 +96,13 @@ void Int128::setScale(int scale) { if (scale > 0) { - ttmath::sint rem = 0; + int rem = 0; while (scale--) - v.DivInt(10, scale == 0 ? &rem : nullptr); + { + if (scale == 0) + rem = int(v % 10); + v /= 10; + } if (rem > 4) v++; @@ -152,21 +114,11 @@ void Int128::setScale(int scale) while (scale++) { if (v > i128limit.v || v < -i128limit.v) (Arg::Gds(isc_arith_except) << Arg::Gds(isc_numeric_out_of_range)).raise(); - v.MulInt(10); + v *= 10; } } } -int Int128::toInteger(int scale) const -{ - Int128 tmp(*this); - tmp.setScale(scale); - int rc; - if (tmp.v.ToInt(rc)) - overflow(); - return rc; -} - void Int128::toString(int scale, unsigned length, char* to) const { string buffer; @@ -181,10 +133,22 @@ void Int128::toString(int scale, unsigned length, char* to) const void Int128::toString(int scale, string& to) const { - v.ToStringBase(to); - bool sgn = to[0] == '-'; + to.erase(); + absl::int128 vv = v; + + bool sgn = (vv < 0); if (sgn) - to.erase(0, 1); + vv = -vv; + + while (vv > 0) + { + int dig = int(vv % 10); + to.insert(string::size_type(0), string::size_type(1), char(dig + '0')); + vv /= 10; + } + + if (to.isEmpty()) + to = "0"; if (scale) { @@ -220,78 +184,23 @@ void Int128::toString(int scale, string& to) const to.insert(0, "-"); } -SINT64 Int128::toInt64(int scale) const -{ - Int128 tmp(*this); - tmp.setScale(scale); - if (tmp.v < i64min.v || tmp.v > i64max.v) - overflow(); - - unsigned dwords[4]; - tmp.getTable32(dwords); - SINT64 rc = int(dwords[1]); - rc <<= 32; - rc += dwords[0]; - - return rc; -} - -double Int128::toDouble() const -{ - unsigned dwords[4]; - getTable32(dwords); - double rc = int(dwords[3]); - for (int i = 3; i--;) - { - rc *= p2_32; - rc += dwords[i]; - } - - return rc; -} - -int Int128::compare(Int128 tgt) const -{ - return v < tgt.v ? -1 : v > tgt.v ? 1 : 0; -} - Int128 Int128::abs() const { - Int128 rc(*this); - if (rc.v.Abs()) + if (compare(MIN_Int128) == 0) overflow(); - return rc; -} -Int128 Int128::neg() const -{ - Int128 rc(*this); - if (rc.v.ChangeSign()) - overflow(); - return rc; -} - -Int128 Int128::add(Int128 op2) const -{ - Int128 rc(*this); - if (rc.v.Add(op2.v)) - overflow(); + Int128 rc; + rc.v = v < 0 ? -v : v; return rc; } -Int128 Int128::sub(Int128 op2) const +Int128 Int128::neg() const { - Int128 rc(*this); - if (rc.v.Sub(op2.v)) + if (compare(MIN_Int128) == 0) overflow(); - return rc; -} -Int128 Int128::mul(Int128 op2) const -{ - Int128 rc(*this); - if (rc.v.Mul(op2.v)) - overflow(); + Int128 rc; + rc.v = -v; return rc; } @@ -300,210 +209,37 @@ Int128 Int128::div(Int128 op2, int scale) const if (compare(MIN_Int128) == 0 && op2.compare(minus1) == 0) Arg::Gds(isc_exception_integer_overflow).raise(); + if (op2.v == 0) + zerodivide(); + static const CInt128 MIN_BY10(MIN_Int128 / 10); static const CInt128 MAX_BY10(MAX_Int128 / 10); // Scale op1 by as many of the needed powers of 10 as possible without an overflow. - CInt128 op1(*this); + Int128 op1(*this); int sign1 = op1.sign(); while ((scale < 0) && (sign1 >= 0 ? op1.compare(MAX_BY10) <= 0 : op1.compare(MIN_BY10) >= 0)) { - op1 *= 10; + op1.v *= 10; ++scale; } // Scale op2 shifting it to the right as long as only zeroes are thrown away. - CInt128 tmp(op2); while (scale < 0) { - ttmath::sint rem = 0; - tmp.v.DivInt(10, &rem); + int rem = int(v % 10); if (rem) break; - op2 = tmp; + op2.v /= 10; ++scale; } - if (op1.v.Div(op2.v)) - zerodivide(); + op1.v /= op2.v; op1.setScale(scale); return op1; } -Int128 Int128::mod(Int128 op2) const -{ - Int128 tmp(*this); - Int128 rc; - if (tmp.v.Div(op2.v, rc.v)) - zerodivide(); - return rc; -} - -int Int128::sign() const -{ - return v.IsSign() ? -1 : v.IsZero() ? 0 : 1; -} - -UCHAR* Int128::getBytes() -{ - return (UCHAR*)(v.table); -} - -void Int128::getTable32(unsigned* dwords) const -{ - static_assert((sizeof(v.table[0]) == 4) || (sizeof(v.table[0]) == 8), - "Unsupported size of integer in ttmath"); - - if (sizeof(v.table[0]) == 4) - { - for (int i = 0; i < 4; ++i) - dwords[i] = v.table[i]; - } - else if (sizeof(v.table[0]) == 8) - { - for (int i = 0; i < 2; ++i) - { - dwords[i * 2] = v.table[i] & 0xFFFFFFFF; - dwords[i * 2 + 1] = (v.table[i] >> 32) & 0xFFFFFFFF; - } - } -} - -void Int128::setTable32(const unsigned* dwords) -{ - static_assert((sizeof(v.table[0]) == 4) || (sizeof(v.table[0]) == 8), - "Unsupported size of integer in ttmath"); - - if (sizeof(v.table[0]) == 4) - { - for (int i = 0; i < 4; ++i) - v.table[i] = dwords[i]; - } - else if (sizeof(v.table[0]) == 8) - { - for (int i = 0; i < 2; ++i) - { - v.table[i] = dwords[i * 2 + 1]; - v.table[i] <<= 32; - v.table[i] += dwords[i * 2]; - } - } -} - -Int128 Int128::operator&=(FB_UINT64 mask) -{ - v.table[0] &= mask; - unsigned i = 1; - if (sizeof(v.table[0]) == 4) - { - i = 2; - v.table[1] &= (mask >> 32); - } - - for (; i < FB_NELEM(v.table); ++i) - v.table[i] = 0; - return *this; -} - -Int128 Int128::operator&=(ULONG mask) -{ - v.table[0] &= mask; - - for (unsigned i = 1; i < FB_NELEM(v.table); ++i) - v.table[i] = 0; - return *this; -} - -Int128 Int128::operator/(unsigned value) const -{ - Int128 rc(*this); - rc.v.DivInt(value); - return rc; -} - -Int128 Int128::operator<<(int value) const -{ - Int128 rc(*this); - rc.v <<= value; - return rc; -} - -Int128 Int128::operator>>(int value) const -{ - Int128 rc(*this); - rc.v >>= value; - return rc; -} - -Int128 Int128::operator&=(Int128 value) -{ - v &= value.v; - return *this; -} - -Int128 Int128::operator|=(Int128 value) -{ - v |= value.v; - return *this; -} - -Int128 Int128::operator^=(Int128 value) -{ - v ^= value.v; - return *this; -} - -Int128 Int128::operator~() const -{ - Int128 rc(*this); - rc.v.BitNot(); - return rc; -} - -Int128 Int128::operator-() const -{ - return neg(); -} - -Int128 Int128::operator+=(unsigned value) -{ - v.AddInt(value); - return *this; -} - -Int128 Int128::operator-=(unsigned value) -{ - v.SubInt(value); - return *this; -} - -Int128 Int128::operator*=(unsigned value) -{ - v.MulInt(value); - return *this; -} - -bool Int128::operator>(Int128 value) const -{ - return v > value.v; -} - -bool Int128::operator>=(Int128 value) const -{ - return v >= value.v; -} - -bool Int128::operator==(Int128 value) const -{ - return v == value.v; -} - -bool Int128::operator!=(Int128 value) const -{ - return v != value.v; -} - void Int128::zerodivide() { (Arg::Gds(isc_arith_except) << Arg::Gds(isc_exception_integer_divide_by_zero)).raise(); @@ -533,10 +269,10 @@ CInt128::CInt128(minmax mm) switch(mm) { case MkMax: - v.SetMax(); + v = absl::Int128Max(); break; case MkMin: - v.SetMin(); + v = absl::Int128Min(); break; } } diff --git a/src/common/Int128.h b/src/common/Int128.h index 5fde931ff9..432023d176 100644 --- a/src/common/Int128.h +++ b/src/common/Int128.h @@ -36,7 +36,7 @@ #include "classes/fb_string.h" -#include "../../extern/ttmath/ttmath.h" +#include "absl/numeric/int128.h" namespace Firebird { @@ -53,10 +53,29 @@ public: return set(SLONG(value), scale); } #endif - Int128 set(SLONG value, int scale); - Int128 set(SINT64 value, int scale); - Int128 set(double value); + + Int128 set(SLONG value, int scale) + { + v = value; + setScale(scale); + return *this; + } + + Int128 set(SINT64 value, int scale) + { + v = value; + setScale(scale); + return *this; + } + + Int128 set(double value) + { + v = absl::int128(value); + return *this; + } + Int128 set(DecimalStatus decSt, Decimal128 value); + Int128 set(Int128 value) { v = value.v; @@ -73,49 +92,217 @@ public: const char* show(); #endif - int toInteger(int scale) const; - SINT64 toInt64(int scale) const; + int toInteger(int scale) const + { + Int128 tmp(*this); + tmp.setScale(scale); + int rc = int(tmp.v); + if (tmp.v != rc) + overflow(); + return rc; + } + + SINT64 toInt64(int scale) const + { + Int128 tmp(*this); + tmp.setScale(scale); + SINT64 rc = SINT64(tmp.v); + if (tmp.v != rc) + overflow(); + return rc; + } + void toString(int scale, unsigned length, char* to) const; void toString(int scale, string& to) const; - double toDouble() const; - - Int128 operator&=(FB_UINT64 mask); - Int128 operator&=(ULONG mask); - Int128 operator-() const; - Int128 operator/(unsigned value) const; - Int128 operator+=(unsigned value); - Int128 operator-=(unsigned value); - Int128 operator*=(unsigned value); - - Int128 operator<<(int value) const; - Int128 operator>>(int value) const; - - int compare(Int128 tgt) const; - bool operator>(Int128 value) const; - bool operator>=(Int128 value) const; - bool operator==(Int128 value) const; - bool operator!=(Int128 value) const; - Int128 operator&=(Int128 value); - Int128 operator|=(Int128 value); - Int128 operator^=(Int128 value); - Int128 operator~() const; - int sign() const; + + double toDouble() const + { + return double(v); + } + + Int128 operator&=(FB_UINT64 mask) + { + v &= mask; + return *this; + } + + Int128 operator&=(ULONG mask) + { + v &= mask; + return *this; + } + + Int128 operator-() const + { + Int128 rc; + rc.v = -v; + return rc; + } + + Int128 operator/(unsigned value) const + { + Int128 rc; + rc.v = v / value; + return rc; + } + + Int128 operator+=(unsigned value) + { + v += value; + return *this; + } + + Int128 operator-=(unsigned value) + { + v -= value; + return *this; + } + + Int128 operator*=(unsigned value) + { + v *= value; + return *this; + } + + Int128 operator<<(int value) const + { + Int128 rc; + rc.v = v << value; + return rc; + } + + Int128 operator>>(int value) const + { + Int128 rc; + rc.v = v >> value; + return rc; + } + + int compare(Int128 tgt) const + { + return v < tgt.v ? -1 : v > tgt.v ? 1 : 0; + } + + bool operator>(Int128 value) const + { + return v > value.v; + } + + bool operator>=(Int128 value) const + { + return v >= value.v; + } + + bool operator==(Int128 value) const + { + return v == value.v; + } + + bool operator!=(Int128 value) const + { + return v != value.v; + } + + Int128 operator&=(Int128 value) + { + v &= value.v; + return *this; + } + + Int128 operator|=(Int128 value) + { + v |= value.v; + return *this; + } + + Int128 operator^=(Int128 value) + { + v ^= value.v; + return *this; + } + + Int128 operator~() const + { + Int128 rc; + rc.v = ~v; + return rc; + } + + int sign() const + { + return v < 0 ? -1 : v == 0 ? 0 : 1; + } Int128 abs() const; Int128 neg() const; - Int128 add(Int128 op2) const; - Int128 sub(Int128 op2) const; - Int128 mul(Int128 op2) const; + + Int128 add(Int128 op2) const + { + Int128 rc; + rc.v = v + op2.v; + + // see comment ArithmeticNode::add2() + if (sign() == op2.sign() && op2.sign() != rc.sign()) + overflow(); + + return rc; + } + + Int128 sub(Int128 op2) const + { + Int128 rc; + rc.v = v - op2.v; + + // see comment ArithmeticNode::add2() + if (sign() != op2.sign() && op2.sign() == rc.sign()) + overflow(); + + return rc; + } + + Int128 mul(Int128 op2) const + { + Int128 rc; + rc.v = v * op2.v; + + if (rc.v / v != op2.v) + overflow(); + + return rc; + } + Int128 div(Int128 op2, int scale) const; - Int128 mod(Int128 op2) const; - void getTable32(unsigned* dwords) const; // internal data in per-32bit form - void setTable32(const unsigned* dwords); + Int128 mod(Int128 op2) const + { + if (op2.v == 0) + zerodivide(); + + Int128 rc; + rc.v = v % op2.v; + return rc; + } + + // returns internal data in per-32bit form + void getTable32(unsigned* dwords) const + { + absl::int128 vv = v; + for (int i = 0; i < 4; ++i) + { + dwords[i] = unsigned(vv); + vv >>= 32; + } + } + void setScale(int scale); - UCHAR* getBytes(); + + UCHAR* getBytes() + { + return (UCHAR*)(&v); + } protected: - ttmath::Int v; + absl::int128 v; static void overflow(); static void zerodivide(); @@ -143,10 +330,10 @@ class I128limit : public Int128 public: I128limit() { - v.SetOne(); + v = 1; for (int i = 0; i < 126; ++i) - v.MulInt(2); - v.DivInt(5); + v *= 2; + v *= 5; } }; diff --git a/src/jrd/align.h b/src/jrd/align.h index aa4631488d..c94f0f4da3 100644 --- a/src/jrd/align.h +++ b/src/jrd/align.h @@ -114,7 +114,7 @@ static const USHORT type_alignments[DTYPE_TYPE_MAX] = sizeof(UCHAR), /* dtype_boolean */ sizeof(Firebird::Decimal64),/* dtype_dec64 */ sizeof(Firebird::Decimal64),/* dtype_dec128 */ - sizeof(Firebird::Decimal64),/* dtype_int128 */ + sizeof(SINT64), /* dtype_int128 */ sizeof(GDS_TIME), /* dtype_sql_time_tz */ sizeof(GDS_DATE), /* dtype_timestamp_tz */ sizeof(GDS_TIME), /* dtype_ex_time_tz */