From effd287358f2196d87d0b60510f7fd641d0af2ac Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Thu, 25 Jul 2019 00:35:47 +0000 Subject: [PATCH 01/51] - Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild Signed-off-by: Fedora Release Engineering --- firebird.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/firebird.spec b/firebird.spec index d24ce52..39b4d0f 100644 --- a/firebird.spec +++ b/firebird.spec @@ -6,7 +6,7 @@ Name: firebird Version: %{upversion} -Release: 2%{?dist} +Release: 3%{?dist} Summary: SQL relational database management system License: Interbase @@ -374,6 +374,9 @@ fi %changelog +* Thu Jul 25 2019 Fedora Release Engineering - 3.0.4.33054-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + * Thu Jan 31 2019 Fedora Release Engineering - 3.0.4.33054-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild From 5a4a0896a077b02e530758ac1a0303747b9a26fc Mon Sep 17 00:00:00 2001 From: Davide Bolcioni Date: Mon, 28 Oct 2019 18:29:01 +0000 Subject: [PATCH 02/51] Fix login shell to /sbin/nologin Fix https://bugzilla.redhat.com/show_bug.cgi?id=1764128 --- firebird.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firebird.spec b/firebird.spec index b43f70b..cedc11e 100644 --- a/firebird.spec +++ b/firebird.spec @@ -266,7 +266,7 @@ cp .%{_datadir}/%{name}/misc/%{name}-superserver.service .%{_unitdir}/%{name}-su %pre # Create the firebird group if it doesn't exist getent group %{name} || /usr/sbin/groupadd -r %{name} -getent passwd %{name} >/dev/null || /usr/sbin/useradd -d / -g %{name} -s /bin/nologin -r %{name} +getent passwd %{name} >/dev/null || /usr/sbin/useradd -d / -g %{name} -s /sbin/nologin -r %{name} # Add gds_db to /etc/services if needed FileName=/etc/services From 02f4ee98e366477bb6e2845c61f2195f36dea3e9 Mon Sep 17 00:00:00 2001 From: Philippe Makowski Date: Mon, 4 Nov 2019 09:07:34 +0000 Subject: [PATCH 03/51] Fix firebird-superserver.service file permissions Set firebird-superserver.service not executable Fix https://bugzilla.redhat.com/show_bug.cgi?id=1768091 --- firebird.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firebird.spec b/firebird.spec index cedc11e..698b420 100644 --- a/firebird.spec +++ b/firebird.spec @@ -323,7 +323,7 @@ fi %config(noreplace) %attr(0644,root,root) %{_sysconfdir}/logrotate.d/%{name} %defattr(0755,root,root,0755) -%{_unitdir}/%{name}-superserver.service +%attr(0644,root,root) %{_unitdir}/%{name}-superserver.service %files devel From c1692a38e7b60e58ac555aeae04bbac9dec8b439 Mon Sep 17 00:00:00 2001 From: Philippe Makowski Date: Mon, 4 Nov 2019 11:59:07 +0100 Subject: [PATCH 04/51] Change firebird-superserver.service file permissions, fix #1768091 Set login shell to /sbin/nologin, fix #1764128: --- firebird.spec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/firebird.spec b/firebird.spec index 698b420..ce4117d 100644 --- a/firebird.spec +++ b/firebird.spec @@ -6,7 +6,7 @@ Name: firebird Version: %{upversion} -Release: 4%{?dist} +Release: 5%{?dist} Summary: SQL relational database management system License: Interbase @@ -322,7 +322,6 @@ fi %config(noreplace) %attr(0664,%{name},%{name}) %{_localstatedir}/log/%{name}/%{name}.log %config(noreplace) %attr(0644,root,root) %{_sysconfdir}/logrotate.d/%{name} -%defattr(0755,root,root,0755) %attr(0644,root,root) %{_unitdir}/%{name}-superserver.service @@ -371,6 +370,10 @@ fi %changelog +* Mon Nov 4 2019 Philippe Makowski - 3.0.5.33054-4 +- Change firebird-superserver.service file permissions, fix #1768091 +- Set login shell to /sbin/nologin, fix #1764128: + * Wed Aug 21 2019 Philippe Makowski - 3.0.4.33054-4 - Remove tmpfile, fix #1687058 From 2d4b965aff7ff28e7c473687dc204080c9d83abd Mon Sep 17 00:00:00 2001 From: Philippe Makowski Date: Mon, 4 Nov 2019 13:44:03 +0100 Subject: [PATCH 05/51] Remove BR libtermcap-devel --- firebird.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firebird.spec b/firebird.spec index ce4117d..4b09905 100644 --- a/firebird.spec +++ b/firebird.spec @@ -39,7 +39,6 @@ BuildRequires: automake BuildRequires: libtommath-devel BuildRequires: libtool BuildRequires: ncurses-devel -BuildRequires: libtermcap-devel BuildRequires: libicu-devel BuildRequires: libedit-devel BuildRequires: gcc-c++ @@ -372,7 +371,8 @@ fi %changelog * Mon Nov 4 2019 Philippe Makowski - 3.0.5.33054-4 - Change firebird-superserver.service file permissions, fix #1768091 -- Set login shell to /sbin/nologin, fix #1764128: +- Set login shell to /sbin/nologin, fix #1764128 +- Remove BR libtermcap-devel * Wed Aug 21 2019 Philippe Makowski - 3.0.4.33054-4 - Remove tmpfile, fix #1687058 From a5c4f2dcbd5fd9ca042e6657192aaec761e5265b Mon Sep 17 00:00:00 2001 From: Philippe Makowski Date: Mon, 4 Nov 2019 15:32:12 +0100 Subject: [PATCH 06/51] Change firebird-superserver.service file permissions, fix #1768091 Set login shell to /sbin/nologin, fix #1764128 Remove BR libtermcap-devel --- firebird.spec | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/firebird.spec b/firebird.spec index 0fdd7e7..8ba293e 100644 --- a/firebird.spec +++ b/firebird.spec @@ -6,7 +6,7 @@ Name: firebird Version: %{upversion} -Release: 3%{?dist} +Release: 4%{?dist} Summary: SQL relational database management system License: Interbase @@ -39,7 +39,6 @@ BuildRequires: automake BuildRequires: libtommath-devel BuildRequires: libtool BuildRequires: ncurses-devel -BuildRequires: libtermcap-devel BuildRequires: libicu-devel BuildRequires: libedit-devel BuildRequires: gcc-c++ @@ -266,7 +265,7 @@ cp .%{_datadir}/%{name}/misc/%{name}-superserver.service .%{_unitdir}/%{name}-su %pre # Create the firebird group if it doesn't exist getent group %{name} || /usr/sbin/groupadd -r %{name} -getent passwd %{name} >/dev/null || /usr/sbin/useradd -d / -g %{name} -s /bin/nologin -r %{name} +getent passwd %{name} >/dev/null || /usr/sbin/useradd -d / -g %{name} -s /sbin/nologin -r %{name} # Add gds_db to /etc/services if needed FileName=/etc/services @@ -322,8 +321,7 @@ fi %config(noreplace) %attr(0664,%{name},%{name}) %{_localstatedir}/log/%{name}/%{name}.log %config(noreplace) %attr(0644,root,root) %{_sysconfdir}/logrotate.d/%{name} -%defattr(0755,root,root,0755) -%{_unitdir}/%{name}-superserver.service +%attr(0644,root,root) %{_unitdir}/%{name}-superserver.service %files devel @@ -371,6 +369,11 @@ fi %changelog +* Mon Nov 4 2019 Philippe Makowski - 3.0.4.33054-4 +- Change firebird-superserver.service file permissions, fix #1768091 +- Set login shell to /sbin/nologin, fix #1764128 +- Remove BR libtermcap-devel + * Wed Aug 21 2019 Philippe Makowski - 3.0.4.33054-3 - Remove tmpfile, fix #1687058 From ca51082022323536560bf76b5adb078733523a6f Mon Sep 17 00:00:00 2001 From: Philippe Makowski Date: Mon, 20 Jan 2020 11:21:08 +0100 Subject: [PATCH 07/51] new upstream release fix #1786885 --- .gitignore | 1 + cloop-honour-build-flags.patch | 4 ++-- firebird.spec | 11 +++++++---- no-copy-from-icu.patch | 9 ++++----- sources | 2 +- 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 1023084..2e29dee 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ Firebird-2.1.3.18185-0.RC2.tar.bz2 /Firebird-3.0.2.32703-0.tar.bz2 /Firebird-3.0.3.32900-0.tar.bz2 /Firebird-3.0.4.33054-0.tar.bz2 +/Firebird-3.0.5.33220-0.tar.bz2 diff --git a/cloop-honour-build-flags.patch b/cloop-honour-build-flags.patch index 1f556e0..735e3b9 100644 --- a/cloop-honour-build-flags.patch +++ b/cloop-honour-build-flags.patch @@ -6,8 +6,8 @@ Forwarded: no +++ b/extern/cloop/Makefile @@ -6,7 +6,7 @@ TARGET := release - CC := gcc - CXX := g++ + CC := $(CC) + CXX := $(CXX) -LD := $(CXX) +LD := $(CXX) $(LDFLAGS) diff --git a/firebird.spec b/firebird.spec index 4b09905..a018a3c 100644 --- a/firebird.spec +++ b/firebird.spec @@ -1,4 +1,4 @@ -%global upversion 3.0.4.33054 +%global upversion 3.0.5.33220 %global pkgversion Firebird-%{upversion}-0 %global major 3.0 @@ -6,13 +6,13 @@ Name: firebird Version: %{upversion} -Release: 5%{?dist} +Release: 1%{?dist} Summary: SQL relational database management system License: Interbase URL: http://www.firebirdsql.org/ -Source0: https://github.com/FirebirdSQL/firebird/releases/download/R3_0_4/%{pkgversion}.tar.bz2 +Source0: https://github.com/FirebirdSQL/firebird/releases/download/R3_0_5/%{pkgversion}.tar.bz2 Source1: firebird-logrotate Source2: README.Fedora Source3: firebird-superserver.service @@ -369,7 +369,10 @@ fi %changelog -* Mon Nov 4 2019 Philippe Makowski - 3.0.5.33054-4 +* Mon Jan 20 2020 Philippe Makowski - 3.0.5.33220-1 +- new upstream release fix #1786885 + +* Mon Nov 4 2019 Philippe Makowski - 3.0.4.33054-5 - Change firebird-superserver.service file permissions, fix #1768091 - Set login shell to /sbin/nologin, fix #1764128 - Remove BR libtermcap-devel diff --git a/no-copy-from-icu.patch b/no-copy-from-icu.patch index ca26688..94c2b80 100644 --- a/no-copy-from-icu.patch +++ b/no-copy-from-icu.patch @@ -3,7 +3,7 @@ Author: Damyan Ivanov --- a/src/isql/isql.epp +++ b/src/isql/isql.epp -@@ -168,34 +168,6 @@ const char* UNKNOWN = "*unknown*"; +@@ -167,34 +167,6 @@ const char* UNKNOWN = "*unknown*"; namespace IcuUtil { @@ -40,13 +40,12 @@ Author: Damyan Ivanov { --- a/builds/posix/Makefile.in +++ b/builds/posix/Makefile.in -@@ -476,7 +476,8 @@ $(GSTAT): $(GSTAT_Objects) $(COMMON_LIB +@@ -481,7 +481,7 @@ $(GSTAT): $(GSTAT_Objects) $(COMMON_LIB isql: $(ISQL) $(ISQL): $(ISQL_Objects) $(COMMON_LIB) -- $(EXE_LINK) $(EXE_LINK_OPTIONS) $^ -o $@ $(FIREBIRD_LIBRARY_LINK) $(LIBEDITLINE) $(LINK_LIBS) -+ $(EXE_LINK) $(EXE_LINK_OPTIONS) $^ -o $@ $(FIREBIRD_LIBRARY_LINK) \ -+ $(LIBEDITLINE) $(LINK_LIBS) $(ICU_LIBS) +- $(EXE_LINK) $(EXE_LINK_OPTIONS) $^ -o $@ $(FIREBIRD_LIBRARY_LINK) $(LIBEDITLINE) $(LINK_LIBS) $(call LINK_DARWIN_RPATH,..) ++ $(EXE_LINK) $(EXE_LINK_OPTIONS) $^ -o $@ $(FIREBIRD_LIBRARY_LINK) $(LIBEDITLINE) $(LINK_LIBS) $(ICU_LIBS) $(call LINK_DARWIN_RPATH,..) nbackup: $(NBACKUP) diff --git a/sources b/sources index 5e9598a..5d5ee07 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (Firebird-3.0.4.33054-0.tar.bz2) = a346ebd53aeccf0b33eac5d35c3c3356624c1fbd0ad897173b3f68d940143062b28460a2822df807e8e8a1ea8792ebf98ed33e5b3ae273d86e6e36295a7fc8ad +SHA512 (Firebird-3.0.5.33220-0.tar.bz2) = 67120c54f563cac84408cb50f0f8ea80755342527a441552a975925926ea263937914bce69474f12cf82e004c0f804297fa714aaba4200685f4bff1e47b4df11 From 6737b9d1b836e28ab0a238daf910baee1d23f4af Mon Sep 17 00:00:00 2001 From: Kalev Lember Date: Tue, 21 Jan 2020 22:54:25 +0100 Subject: [PATCH 08/51] Avoid hardcoding /usr prefix When building flatpaks, the prefix can also be /app. --- firebird.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firebird.spec b/firebird.spec index a018a3c..8ceff9b 100644 --- a/firebird.spec +++ b/firebird.spec @@ -227,7 +227,7 @@ make -f Makefile.install buildRoot chmod -R u+w buildroot%{_docdir}/%{name} %install -chmod u+rw,a+rx gen/buildroot/usr/include/firebird/firebird/impl +chmod u+rw,a+rx gen/buildroot/%{_includedir}/firebird/firebird/impl cp -r gen/buildroot/* ${RPM_BUILD_ROOT}/ mkdir -p ${RPM_BUILD_ROOT}%{_libdir}/pkgconfig cp -v gen/install/misc/*.pc ${RPM_BUILD_ROOT}%{_libdir}/pkgconfig/ From b64da7953268d778cba9b87b85b95cc1d73b04c2 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Tue, 28 Jan 2020 18:31:36 +0000 Subject: [PATCH 09/51] - Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild Signed-off-by: Fedora Release Engineering --- firebird.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/firebird.spec b/firebird.spec index 8ceff9b..15b52fa 100644 --- a/firebird.spec +++ b/firebird.spec @@ -6,7 +6,7 @@ Name: firebird Version: %{upversion} -Release: 1%{?dist} +Release: 2%{?dist} Summary: SQL relational database management system License: Interbase @@ -369,6 +369,9 @@ fi %changelog +* Tue Jan 28 2020 Fedora Release Engineering - 3.0.5.33220-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + * Mon Jan 20 2020 Philippe Makowski - 3.0.5.33220-1 - new upstream release fix #1786885 From 20be64fb96de9df582b2432c558371bdddd6189d Mon Sep 17 00:00:00 2001 From: Philippe Makowski Date: Mon, 3 Feb 2020 13:33:31 +0100 Subject: [PATCH 10/51] fix Unnecessary output from scriptlets, fix #1796532 --- firebird.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firebird.spec b/firebird.spec index 15b52fa..9188e40 100644 --- a/firebird.spec +++ b/firebird.spec @@ -264,7 +264,7 @@ cp .%{_datadir}/%{name}/misc/%{name}-superserver.service .%{_unitdir}/%{name}-su %pre # Create the firebird group if it doesn't exist -getent group %{name} || /usr/sbin/groupadd -r %{name} +getent group %{name} > /dev/null || /usr/sbin/groupadd -r %{name} getent passwd %{name} >/dev/null || /usr/sbin/useradd -d / -g %{name} -s /sbin/nologin -r %{name} # Add gds_db to /etc/services if needed From f568f52f53176a1ad0124b4cbb272e80f39d9ea1 Mon Sep 17 00:00:00 2001 From: Stephan Bergmann Date: Wed, 12 Feb 2020 18:47:34 +0100 Subject: [PATCH 11/51] Remove spurious symlinks when building flatpak For some unexplored reason, the firebird build system creates some additional symlinks in the build root when building a flatpak. Instead of trying to patch the firebird build system to prevent them, just delete them afterwards (to avoid "Installed (but unpackaged) file(s) found" errors). --- firebird.spec | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/firebird.spec b/firebird.spec index 9188e40..da548f2 100644 --- a/firebird.spec +++ b/firebird.spec @@ -261,6 +261,12 @@ cp -f %{SOURCE3} .%{_datadir}/%{name}/misc/%{name}-superserver.service mkdir -p .%{_unitdir} cp .%{_datadir}/%{name}/misc/%{name}-superserver.service .%{_unitdir}/%{name}-superserver.service +%if 0%{?flatpak} +# Remove spurious symlinks to /app/include/firebird/...: +rm -vr usr/include/firebird +rm -v usr/include/{ibase,iberror,ib_util}.h +%endif + %pre # Create the firebird group if it doesn't exist From 01ab1313986d72108359143572a50a4fa01cbc09 Mon Sep 17 00:00:00 2001 From: Philippe Makowski Date: Wed, 8 Jul 2020 13:42:20 +0200 Subject: [PATCH 12/51] new upstream release fix #1850675 --- .gitignore | 1 + firebird.spec | 9 ++++++--- sources | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 2e29dee..6d300c3 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ Firebird-2.1.3.18185-0.RC2.tar.bz2 /Firebird-3.0.3.32900-0.tar.bz2 /Firebird-3.0.4.33054-0.tar.bz2 /Firebird-3.0.5.33220-0.tar.bz2 +/Firebird-3.0.6.33328-0.tar.bz2 diff --git a/firebird.spec b/firebird.spec index da548f2..ab89302 100644 --- a/firebird.spec +++ b/firebird.spec @@ -1,4 +1,4 @@ -%global upversion 3.0.5.33220 +%global upversion 3.0.6.33328 %global pkgversion Firebird-%{upversion}-0 %global major 3.0 @@ -6,13 +6,13 @@ Name: firebird Version: %{upversion} -Release: 2%{?dist} +Release: 1%{?dist} Summary: SQL relational database management system License: Interbase URL: http://www.firebirdsql.org/ -Source0: https://github.com/FirebirdSQL/firebird/releases/download/R3_0_5/%{pkgversion}.tar.bz2 +Source0: https://github.com/FirebirdSQL/firebird/releases/download/R3_0_6/%{pkgversion}.tar.bz2 Source1: firebird-logrotate Source2: README.Fedora Source3: firebird-superserver.service @@ -375,6 +375,9 @@ fi %changelog +* Wed Jul 08 2020 Philippe Makowski - 3.0.6.33328-1 +- new upstream release fix #1850675 + * Tue Jan 28 2020 Fedora Release Engineering - 3.0.5.33220-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild diff --git a/sources b/sources index 5d5ee07..49a1844 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (Firebird-3.0.5.33220-0.tar.bz2) = 67120c54f563cac84408cb50f0f8ea80755342527a441552a975925926ea263937914bce69474f12cf82e004c0f804297fa714aaba4200685f4bff1e47b4df11 +SHA512 (Firebird-3.0.6.33328-0.tar.bz2) = e8fabb9b4e3e9c8f6a1ae5566f94b64d268cc3264b486650246ab6214baf3f073e8e77c009b92f8061dc3ad9c5d4da0dc5c5c1817b66b8bc7f41ac40cf82f62b From 84194bfd15cce5cc0e6fd731d49f6460e3184a7e Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Mon, 27 Jul 2020 17:28:21 +0000 Subject: [PATCH 13/51] - Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild Signed-off-by: Fedora Release Engineering --- firebird.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/firebird.spec b/firebird.spec index ab89302..4185156 100644 --- a/firebird.spec +++ b/firebird.spec @@ -6,7 +6,7 @@ Name: firebird Version: %{upversion} -Release: 1%{?dist} +Release: 2%{?dist} Summary: SQL relational database management system License: Interbase @@ -375,6 +375,9 @@ fi %changelog +* Mon Jul 27 2020 Fedora Release Engineering - 3.0.6.33328-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + * Wed Jul 08 2020 Philippe Makowski - 3.0.6.33328-1 - new upstream release fix #1850675 From 868d216b86bde6bba77a1e6bf503df22aa078c46 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Sat, 1 Aug 2020 00:58:59 +0000 Subject: [PATCH 14/51] - Second attempt - Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild Signed-off-by: Fedora Release Engineering --- firebird.spec | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/firebird.spec b/firebird.spec index 4185156..92658da 100644 --- a/firebird.spec +++ b/firebird.spec @@ -6,7 +6,7 @@ Name: firebird Version: %{upversion} -Release: 2%{?dist} +Release: 3%{?dist} Summary: SQL relational database management system License: Interbase @@ -375,6 +375,10 @@ fi %changelog +* Sat Aug 01 2020 Fedora Release Engineering - 3.0.6.33328-3 +- Second attempt - Rebuilt for + https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + * Mon Jul 27 2020 Fedora Release Engineering - 3.0.6.33328-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild From 5f2dab2eee4efeea92d75c8296ac9d71a544efd0 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Mon, 10 Aug 2020 22:10:29 -0600 Subject: [PATCH 15/51] Disable LTO on s390x for now --- firebird.spec | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/firebird.spec b/firebird.spec index 92658da..8919f75 100644 --- a/firebird.spec +++ b/firebird.spec @@ -6,7 +6,7 @@ Name: firebird Version: %{upversion} -Release: 3%{?dist} +Release: 4%{?dist} Summary: SQL relational database management system License: Interbase @@ -199,6 +199,11 @@ in production systems, under a variety of names, since 1981. %patch401 -p1 %build +# firebird is mis-compiled on s390x when LTO is enabled. A root +# cause analysis has not yet been completed. Disable LTO for now +%ifarch s390x +%global _lto_cflags %{nil} +%endif export CFLAGS="%{optflags} -fno-strict-aliasing" export CXXFLAGS="${CFLAGS} -fno-delete-null-pointer-checks" NOCONFIGURE=1 ./autogen.sh @@ -375,6 +380,9 @@ fi %changelog +* Mon Aug 10 2020 Jeff Law - 3.0.6.33328-4 +- Disable LTO on s390x for now + * Sat Aug 01 2020 Fedora Release Engineering - 3.0.6.33328-3 - Second attempt - Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild From afb28c0109515b5846a83945a0632e3202887b80 Mon Sep 17 00:00:00 2001 From: Philippe Makowski Date: Fri, 23 Oct 2020 14:07:32 +0200 Subject: [PATCH 16/51] new upstream release fix #1887991 --- .gitignore | 1 + firebird.spec | 9 ++++++--- sources | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 6d300c3..0b55e70 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ Firebird-2.1.3.18185-0.RC2.tar.bz2 /Firebird-3.0.4.33054-0.tar.bz2 /Firebird-3.0.5.33220-0.tar.bz2 /Firebird-3.0.6.33328-0.tar.bz2 +/Firebird-3.0.7.33374-0.tar.bz2 diff --git a/firebird.spec b/firebird.spec index 8919f75..c6fae92 100644 --- a/firebird.spec +++ b/firebird.spec @@ -1,4 +1,4 @@ -%global upversion 3.0.6.33328 +%global upversion 3.0.7.33374 %global pkgversion Firebird-%{upversion}-0 %global major 3.0 @@ -6,13 +6,13 @@ Name: firebird Version: %{upversion} -Release: 4%{?dist} +Release: 1%{?dist} Summary: SQL relational database management system License: Interbase URL: http://www.firebirdsql.org/ -Source0: https://github.com/FirebirdSQL/firebird/releases/download/R3_0_6/%{pkgversion}.tar.bz2 +Source0: https://github.com/FirebirdSQL/firebird/releases/download/R3_0_7/%{pkgversion}.tar.bz2 Source1: firebird-logrotate Source2: README.Fedora Source3: firebird-superserver.service @@ -380,6 +380,9 @@ fi %changelog +* Fri Oct 23 2020 Philippe Makowski - 3.0.7.33374-1 +- new upstream release fix #1887991 + * Mon Aug 10 2020 Jeff Law - 3.0.6.33328-4 - Disable LTO on s390x for now diff --git a/sources b/sources index 49a1844..0d3873e 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (Firebird-3.0.6.33328-0.tar.bz2) = e8fabb9b4e3e9c8f6a1ae5566f94b64d268cc3264b486650246ab6214baf3f073e8e77c009b92f8061dc3ad9c5d4da0dc5c5c1817b66b8bc7f41ac40cf82f62b +SHA512 (Firebird-3.0.7.33374-0.tar.bz2) = ee89cda6d9ace16419515689ed245fbd1bb0e2464bd2d50637e0f474a6aca2e5b86e874ce8bd9714431705a93c038d46de6be1806f0c37d236880a855e725943 From 2e33bbcffde0f4bcb6c77e33ac0b4ebb597aaae1 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Tue, 27 Oct 2020 14:55:15 -0600 Subject: [PATCH 17/51] Force C++14 as this code is not C++17 ready --- firebird.spec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/firebird.spec b/firebird.spec index c6fae92..df62a64 100644 --- a/firebird.spec +++ b/firebird.spec @@ -6,7 +6,7 @@ Name: firebird Version: %{upversion} -Release: 1%{?dist} +Release: 2%{?dist} Summary: SQL relational database management system License: Interbase @@ -205,7 +205,7 @@ in production systems, under a variety of names, since 1981. %global _lto_cflags %{nil} %endif export CFLAGS="%{optflags} -fno-strict-aliasing" -export CXXFLAGS="${CFLAGS} -fno-delete-null-pointer-checks" +export CXXFLAGS="-std=c++14 ${CFLAGS} -fno-delete-null-pointer-checks" NOCONFIGURE=1 ./autogen.sh %configure --prefix=%{_prefix} \ --disable-binreloc \ @@ -380,6 +380,9 @@ fi %changelog +* Tue Oct 27 2020 Jeff Law - 3.0.7.33374-2 +- Force C++14 as this code is not C++17 ready + * Fri Oct 23 2020 Philippe Makowski - 3.0.7.33374-1 - new upstream release fix #1887991 From 6c51737edb1b29f82c297500c86a300d5a0e2da3 Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Fri, 18 Dec 2020 22:38:38 +0000 Subject: [PATCH 18/51] Add BuildRequires: make https://fedoraproject.org/wiki/Changes/Remove_make_from_BuildRoot --- firebird.spec | 1 + 1 file changed, 1 insertion(+) diff --git a/firebird.spec b/firebird.spec index df62a64..ba4182b 100644 --- a/firebird.spec +++ b/firebird.spec @@ -47,6 +47,7 @@ BuildRequires: systemd-units BuildRequires: chrpath BuildRequires: zlib-devel BuildRequires: procmail +BuildRequires: make Requires(postun): /usr/sbin/userdel Requires(postun): /usr/sbin/groupdel From 3223a0cc203c185f2c78c895aafa708835cbfcff Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Tue, 26 Jan 2021 05:33:36 +0000 Subject: [PATCH 19/51] - Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild Signed-off-by: Fedora Release Engineering --- firebird.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/firebird.spec b/firebird.spec index ba4182b..e01c0f2 100644 --- a/firebird.spec +++ b/firebird.spec @@ -6,7 +6,7 @@ Name: firebird Version: %{upversion} -Release: 2%{?dist} +Release: 3%{?dist} Summary: SQL relational database management system License: Interbase @@ -381,6 +381,9 @@ fi %changelog +* Tue Jan 26 2021 Fedora Release Engineering - 3.0.7.33374-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + * Tue Oct 27 2020 Jeff Law - 3.0.7.33374-2 - Force C++14 as this code is not C++17 ready From fda770b289d9e88a65d5afd58f5a59b09e15b288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 2 Mar 2021 16:13:50 +0100 Subject: [PATCH 20/51] Rebuilt for updated systemd-rpm-macros See https://pagure.io/fesco/issue/2583. --- firebird.spec | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/firebird.spec b/firebird.spec index e01c0f2..e31f08d 100644 --- a/firebird.spec +++ b/firebird.spec @@ -6,7 +6,7 @@ Name: firebird Version: %{upversion} -Release: 3%{?dist} +Release: 4%{?dist} Summary: SQL relational database management system License: Interbase @@ -381,6 +381,10 @@ fi %changelog +* Tue Mar 02 2021 Zbigniew Jędrzejewski-Szmek - 3.0.7.33374-4 +- Rebuilt for updated systemd-rpm-macros + See https://pagure.io/fesco/issue/2583. + * Tue Jan 26 2021 Fedora Release Engineering - 3.0.7.33374-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild From dbf28280b4f5dfd623a2749702cb5e6a149633e7 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Mon, 10 May 2021 13:48:12 -0600 Subject: [PATCH 21/51] Re-enable LTO --- firebird.spec | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/firebird.spec b/firebird.spec index e31f08d..14619d7 100644 --- a/firebird.spec +++ b/firebird.spec @@ -6,7 +6,7 @@ Name: firebird Version: %{upversion} -Release: 4%{?dist} +Release: 5%{?dist} Summary: SQL relational database management system License: Interbase @@ -200,11 +200,6 @@ in production systems, under a variety of names, since 1981. %patch401 -p1 %build -# firebird is mis-compiled on s390x when LTO is enabled. A root -# cause analysis has not yet been completed. Disable LTO for now -%ifarch s390x -%global _lto_cflags %{nil} -%endif export CFLAGS="%{optflags} -fno-strict-aliasing" export CXXFLAGS="-std=c++14 ${CFLAGS} -fno-delete-null-pointer-checks" NOCONFIGURE=1 ./autogen.sh @@ -381,6 +376,9 @@ fi %changelog +* Mon May 10 2021 Jeff Law - 3.0.7.33374-5 +- Re-enable LTO + * Tue Mar 02 2021 Zbigniew Jędrzejewski-Szmek - 3.0.7.33374-4 - Rebuilt for updated systemd-rpm-macros See https://pagure.io/fesco/issue/2583. From 1a99e62b9e2709e1d3590837ee836ba5c6dba5a4 Mon Sep 17 00:00:00 2001 From: Philippe Makowski Date: Tue, 8 Jun 2021 11:49:50 +0200 Subject: [PATCH 22/51] Update to 4.0.0 (#1963311) --- .gitignore | 1 + 0001-Port-to-RISC-V-64-bit-riscv64.patch | 134 ---- ...lobal-delete-operators-when-compiled.patch | 36 - README.Fedora | 7 +- add-pkgconfig-files.patch | 24 +- c++17.patch | 144 ++++ cloop-honour-build-flags.patch | 23 +- firebird.service | 15 + firebird.spec | 158 ++--- honour-buildflags.patch | 78 -- no-copy-from-icu.patch | 31 +- noexcept.patch | 664 ++++++++++++++++++ obsolete-syslogd.target.patch | 14 - sources | 2 +- 14 files changed, 942 insertions(+), 389 deletions(-) delete mode 100644 0001-Port-to-RISC-V-64-bit-riscv64.patch delete mode 100644 Provide-sized-global-delete-operators-when-compiled.patch create mode 100644 c++17.patch create mode 100644 firebird.service delete mode 100644 honour-buildflags.patch create mode 100644 noexcept.patch delete mode 100644 obsolete-syslogd.target.patch diff --git a/.gitignore b/.gitignore index 0b55e70..c242f8c 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ Firebird-2.1.3.18185-0.RC2.tar.bz2 /Firebird-3.0.5.33220-0.tar.bz2 /Firebird-3.0.6.33328-0.tar.bz2 /Firebird-3.0.7.33374-0.tar.bz2 +/Firebird-4.0.0.2496-0.tar.xz diff --git a/0001-Port-to-RISC-V-64-bit-riscv64.patch b/0001-Port-to-RISC-V-64-bit-riscv64.patch deleted file mode 100644 index 6fcc1fc..0000000 --- a/0001-Port-to-RISC-V-64-bit-riscv64.patch +++ /dev/null @@ -1,134 +0,0 @@ -diff -urN Firebird-3.0.3.32900-0.old/builds/posix/prefix.linux_riscv64 Firebird-3.0.3.32900-0/builds/posix/prefix.linux_riscv64 ---- Firebird-3.0.3.32900-0.old/builds/posix/prefix.linux_riscv64 1970-01-01 01:00:00.000000000 +0100 -+++ Firebird-3.0.3.32900-0/builds/posix/prefix.linux_riscv64 2018-03-19 08:56:57.254118156 +0000 -@@ -0,0 +1,26 @@ -+# The contents of this file are subject to the Interbase Public -+# License Version 1.0 (the "License"); you may not use this file -+# except in compliance with the License. You may obtain a copy -+# of the License at http://www.Inprise.com/IPL.html -+# -+# Software distributed under the License is distributed on an -+# "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express -+# or implied. See the License for the specific language governing -+# rights and limitations under the License. -+# -+# The Original Code was created by Inprise Corporation -+# and its predecessors. Portions created by Inprise Corporation are -+# Copyright (C) Inprise Corporation. -+# -+# All Rights Reserved. -+# Contributor(s): ______________________________________. -+# Start of file prefix.linux: $(VERSION) $(PLATFORM) -+# -+# Richard W.M. Jones, Red Hat Inc. -+ -+WARN_FLAGS=-Wall -Wno-switch -Wno-parentheses -Wno-unknown-pragmas -Wno-unused-variable -Wno-invalid-offsetof -Wno-narrowing -Wno-unused-local-typedefs -+ -+PROD_FLAGS=-O3 -DLINUX -DRISCV64 -pipe -p -MMD -fPIC -fsigned-char -fmessage-length=0 -+DEV_FLAGS=-ggdb -DLINUX -DRISCV64 -pipe -p -MMD -fPIC -Wall -fsigned-char -fmessage-length=0 $(WARN_FLAGS) -+ -+CXXFLAGS := $(CXXFLAGS) -std=c++11 -diff -urN Firebird-3.0.3.32900-0.old/configure.ac Firebird-3.0.3.32900-0/configure.ac ---- Firebird-3.0.3.32900-0.old/configure.ac 2018-03-19 08:56:23.222156918 +0000 -+++ Firebird-3.0.3.32900-0/configure.ac 2018-03-19 08:56:57.254118156 +0000 -@@ -251,6 +251,18 @@ - libdir=/usr/lib64 - ;; - -+ riscv64*-*-linux*) -+ MAKEFILE_PREFIX=linux_riscv64 -+ INSTALL_PREFIX=linux -+ PLATFORM=LINUX -+ AC_DEFINE(LINUX, 1, [Define this if OS is Linux]) -+ EDITLINE_FLG=Y -+ SHRLIB_EXT=so -+ STD_EDITLINE=true -+ STD_ICU=true -+ libdir=/usr/lib64 -+ ;; -+ - powerpc64le-*-linux*) - MAKEFILE_PREFIX=linux_powerpc64el - INSTALL_PREFIX=linux -diff -urN Firebird-3.0.3.32900-0.old/src/common/classes/DbImplementation.cpp Firebird-3.0.3.32900-0/src/common/classes/DbImplementation.cpp ---- Firebird-3.0.3.32900-0.old/src/common/classes/DbImplementation.cpp 2018-02-02 11:00:35.000000000 +0000 -+++ Firebird-3.0.3.32900-0/src/common/classes/DbImplementation.cpp 2018-03-19 08:56:57.254118156 +0000 -@@ -49,6 +49,7 @@ - static const UCHAR CpuArm64 = 15; - static const UCHAR CpuPowerPc64el = 16; - static const UCHAR CpuM68k = 17; -+static const UCHAR CpuRiscV64 = 18; - - static const UCHAR OsWindows = 0; - static const UCHAR OsLinux = 1; -@@ -89,7 +90,8 @@ - "Alpha", - "ARM64", - "PowerPC64el", -- "M68k" -+ "M68k", -+ "RiscV64" - }; - - const char* operatingSystem[] = { -@@ -116,22 +118,22 @@ - // This table lists pre-fb3 implementation codes - const UCHAR backwardTable[FB_NELEM(hardware) * FB_NELEM(operatingSystem)] = - { --// Intel AMD Sparc PPC PPC64 MIPSEL MIPS ARM IA64 s390 s390x SH SHEB HPPA Alpha ARM64 PowerPC64el --/* Windows */ 50, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, --/* Linux */ 60, 66, 65, 69, 86, 71, 72, 75, 76, 79, 78, 80, 81, 82, 83, 84, 85, --/* Darwin */ 70, 73, 0, 63, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, --/* Solaris */ 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, --/* HPUX */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, --/* AIX */ 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, --/* MVS */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, --/* FreeBSD */ 61, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, --/* NetBSD */ 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -+// Intel AMD Sparc PPC PPC64 MIPSEL MIPS ARM IA64 s390 s390x SH SHEB HPPA Alpha ARM64 PowerPC64el RiscV64 -+/* Windows */ 50, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+/* Linux */ 60, 66, 65, 69, 86, 71, 72, 75, 76, 79, 78, 80, 81, 82, 83, 84, 85, 88, -+/* Darwin */ 70, 73, 0, 63, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+/* Solaris */ 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+/* HPUX */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, -+/* AIX */ 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+/* MVS */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+/* FreeBSD */ 61, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+/* NetBSD */ 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - - const UCHAR backEndianess[FB_NELEM(hardware)] = - { --// Intel AMD Sparc PPC PPC64 MIPSEL MIPS ARM IA64 s390 s390x SH SHEB HPPA Alpha ARM64 PowerPC64el M68k -- 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1 -+// Intel AMD Sparc PPC PPC64 MIPSEL MIPS ARM IA64 s390 s390x SH SHEB HPPA Alpha ARM64 PowerPC64el M68k RiscV64 -+ 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, - }; - - } // anonymous namespace -diff -urN Firebird-3.0.3.32900-0.old/src/common/common.h Firebird-3.0.3.32900-0/src/common/common.h ---- Firebird-3.0.3.32900-0.old/src/common/common.h 2018-03-19 08:56:23.377156741 +0000 -+++ Firebird-3.0.3.32900-0/src/common/common.h 2018-03-19 08:56:57.255118154 +0000 -@@ -135,6 +135,10 @@ - #define FB_CPU CpuArm64 - #endif /* ARM64 */ - -+#ifdef RISCV64 -+#define FB_CPU CpuRiscV64 -+#endif /* RISCV64 */ -+ - #ifdef sparc - #define FB_CPU CpuUltraSparc - #define RISC_ALIGNMENT -diff -urN Firebird-3.0.3.32900-0.old/src/jrd/inf_pub.h Firebird-3.0.3.32900-0/src/jrd/inf_pub.h ---- Firebird-3.0.3.32900-0.old/src/jrd/inf_pub.h 2018-02-02 11:00:36.000000000 +0000 -+++ Firebird-3.0.3.32900-0/src/jrd/inf_pub.h 2018-03-19 08:56:57.255118154 +0000 -@@ -245,7 +245,7 @@ - isc_info_db_impl_linux_ppc64el = 85, - isc_info_db_impl_linux_ppc64 = 86, - isc_info_db_impl_linux_m68k = 87, -- -+ isc_info_db_impl_linux_riscv64 = 88, - - isc_info_db_impl_last_value // Leave this LAST! - }; diff --git a/Provide-sized-global-delete-operators-when-compiled.patch b/Provide-sized-global-delete-operators-when-compiled.patch deleted file mode 100644 index 1302d1d..0000000 --- a/Provide-sized-global-delete-operators-when-compiled.patch +++ /dev/null @@ -1,36 +0,0 @@ -From: Michal Kubecek -Date: Mon, 25 Apr 2016 08:55:36 +0200 -Subject: Provide sized global delete operators when compiled in C++14 mode -Patch-mainline: submitted -Git-commit: 038f9fbf559e56032e4cb49eb7ce4c3ead23fda9 -References: bsc#964466 CORE-5099 - ---- - src/common/classes/alloc.h | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -diff --git a/src/common/classes/alloc.h b/src/common/classes/alloc.h -index b1026ce2aac4..fda5bfebb0cc 100644 ---- a/src/common/classes/alloc.h -+++ b/src/common/classes/alloc.h -@@ -331,6 +331,16 @@ inline void operator delete[](void* mem, Firebird::MemoryPool& pool ALLOC_PARAMS - MemoryPool::globalFree(mem); - } - -+#if __cplusplus >= 201402L -+inline void operator delete(void* mem, std::size_t s ALLOC_PARAMS) throw() -+{ -+ MemoryPool::globalFree(mem); -+} -+inline void operator delete[](void* mem, std::size_t s ALLOC_PARAMS) throw() -+{ -+ MemoryPool::globalFree(mem); -+} -+#endif - #ifdef DEBUG_GDS_ALLOC - - #ifdef __clang__ --- -2.8.2 - - diff --git a/README.Fedora b/README.Fedora index 9f869cb..071b351 100644 --- a/README.Fedora +++ b/README.Fedora @@ -8,13 +8,10 @@ Differences between upstream and the Fedora package * By default, Firebird is set as superserver mode. Please read the Firebird doc if you want to change the mode. - To help you, you have systemd units in /usr/share/firebird/misc. * According to Fedora packaging rules, firebird service is not started automatically. You need to start it, as root : - for SuperServer : - systemctl start firebird-superserver.service + systemctl start firebird.service If you want to have firebird started at each boot, as root : - for SuperServer : - systemctl enable firebird-superserver.service + systemctl enable firebird.service diff --git a/add-pkgconfig-files.patch b/add-pkgconfig-files.patch index d8ea48c..981afe2 100644 --- a/add-pkgconfig-files.patch +++ b/add-pkgconfig-files.patch @@ -1,16 +1,6 @@ -From: Michal Kubecek -Date: Tue, 12 Jun 2012 14:32:44 +0200 -Subject: add pkgconfig files - ---- - builds/install/arch-specific/linux/misc/fbclient.pc.in | 10 ++++++++++ - configure.ac | 1 + - 2 files changed, 11 insertions(+) - create mode 100644 builds/install/arch-specific/linux/misc/fbclient.pc.in - diff --git a/builds/install/arch-specific/linux/misc/fbclient.pc.in b/builds/install/arch-specific/linux/misc/fbclient.pc.in new file mode 100644 -index 000000000000..d49fdc5821c5 +index 0000000..d49fdc5 --- /dev/null +++ b/builds/install/arch-specific/linux/misc/fbclient.pc.in @@ -0,0 +1,10 @@ @@ -25,18 +15,14 @@ index 000000000000..d49fdc5821c5 +Cflags: -I${includedir}/firebird +Libs: -L${libdir} -lfbclient diff --git a/configure.ac b/configure.ac -index 717f5eccc53d..60b3aaa5b08b 100644 +index 0a3de36..922c778 100644 --- a/configure.ac +++ b/configure.ac -@@ -1200,6 +1200,7 @@ case "$PLATFORM" in +@@ -1307,6 +1307,7 @@ case "$PLATFORM" in gen/install/misc/firebird.init.d.gentoo:builds/install/arch-specific/linux/firebird.init.d.gentoo.in gen/install/misc/firebird.init.d.slackware:builds/install/arch-specific/linux/firebird.init.d.slackware.in gen/install/misc/rc.config.firebird:builds/install/arch-specific/linux/rc.config.firebird.in + gen/install/misc/fbclient.pc:builds/install/arch-specific/linux/misc/fbclient.pc.in gen/Release/firebird/bin/linuxLibrary.sh:builds/install/arch-specific/linux/linuxLibrary.sh.in - gen/install/misc/firebird-classic@.service:builds/install/arch-specific/linux/firebird-classic.service.in - gen/install/misc/firebird-classic.socket:builds/install/arch-specific/linux/firebird-classic.socket.in --- -2.3.4 - - + gen/install/misc/firebird.service:builds/install/arch-specific/linux/firebird.service.in + ], diff --git a/c++17.patch b/c++17.patch new file mode 100644 index 0000000..76cd4e2 --- /dev/null +++ b/c++17.patch @@ -0,0 +1,144 @@ +From ff49d71b0cdbab75f8a22717c4f88343a5961868 Mon Sep 17 00:00:00 2001 +From: Adriano dos Santos Fernandes +Date: Mon, 31 May 2021 08:55:26 -0300 +Subject: [PATCH] Set POSIX build to use C++17. + +--- + CMakeLists.txt | 4 ++-- + builds/posix/make.defaults | 2 +- + builds/posix/prefix.freebsd_amd64 | 2 +- + configure.ac | 2 +- + examples/extauth/Makefile | 2 +- + examples/interfaces/makefile | 2 +- + extern/icu/android/aarch64/config.sh | 2 +- + extern/icu/android/armv7a/config.sh | 4 ++-- + extern/icu/android/linux/config.sh | 2 +- + 9 files changed, 11 insertions(+), 11 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 620fd032af4..5f336efd611 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -206,14 +206,14 @@ if (MINGW) + set(CMAKE_STATIC_LIBRARY_PREFIX) + + add_definitions(-D_WIN32_WINNT=0x0600) +- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4 -std=c++11") ++ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4 -std=c++17") + endif() + + if (UNIX) + set(OS_DIR posix) + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") +- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -msse4 -std=c++11") ++ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -msse4 -std=c++17") + + if (NOT CMAKE_CROSSCOMPILING) + set(LIB_readline readline) +diff --git a/builds/posix/make.defaults b/builds/posix/make.defaults +index d96e89053fa..57bbb006865 100755 +--- a/builds/posix/make.defaults ++++ b/builds/posix/make.defaults +@@ -103,7 +103,7 @@ GLOB_OPTIONS:= + #____________________________________________________________________________ + + # Global c++ flags: firebird needs no RTTI, choose build standard +-PLUSPLUS_FLAGS:= -fno-rtti -std=c++11 ++PLUSPLUS_FLAGS:= -fno-rtti -std=c++17 + + # If this is defined then we use special rules useful for developers only + IsDeveloper = @DEVEL_FLG@ +diff --git a/builds/posix/prefix.freebsd_amd64 b/builds/posix/prefix.freebsd_amd64 +index f27567a2715..0736d87e935 100644 +--- a/builds/posix/prefix.freebsd_amd64 ++++ b/builds/posix/prefix.freebsd_amd64 +@@ -26,4 +26,4 @@ DEV_FLAGS=-ggdb -DFREEBSD -DAMD64 -pipe -MMD -p -fPIC -Wall -Wno-non-virtual-dto + # This file must be compiled with SSE4.2 support + %/CRC32C.o: CXXFLAGS += -msse4 + +-CXXFLAGS := $(CXXFLAGS) -std=c++11 ++CXXFLAGS := $(CXXFLAGS) -std=c++17 +diff --git a/configure.ac b/configure.ac +index 9b40be43101..e4a83cf8d3b 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -899,7 +899,7 @@ dnl if 64-bit mode, then archive tool, ar, needs -X64 option + fi + + XE_SAVE_ENV() +-CXXFLAGS="$CXXFLAGS -std=c++11" ++CXXFLAGS="$CXXFLAGS -std=c++17" + AC_CACHE_CHECK([whether the C++ compiler understands noexcept], [ac_cv_cxx_noexcept], [ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[int f(int x) noexcept { return x + 1; }]], [[]])], + [ac_cv_cxx_noexcept=yes], [ac_cv_cxx_noexcept=no])]) +diff --git a/examples/extauth/Makefile b/examples/extauth/Makefile +index 9da7bbd357f..3c8b878d225 100644 +--- a/examples/extauth/Makefile ++++ b/examples/extauth/Makefile +@@ -61,7 +61,7 @@ KEYGEN_objects=$(INTERMED)/keygen.o + TCWRAP_objects=$(INTERMED)/TcWrapper.o + KEY_AUTH_objects=$(INTERMED)/ExtAuth.o + +-CXXFLAGS=-std=c++11 -pthread -I$(ROOT)/include -fPIC $(TOMCRYPT_COMPILE) ++CXXFLAGS=-std=c++17 -pthread -I$(ROOT)/include -fPIC $(TOMCRYPT_COMPILE) + LDFLAGS=-pthread -L$(LIB) -Wl,-rpath,'$$ORIGIN/../lib' $(TOMCRYPT_LINK) + + LINK_LIBS=-lfbclient -ltomcrypt -ltommath +diff --git a/examples/interfaces/makefile b/examples/interfaces/makefile +index 153c3d558dc..b65dba90a7d 100644 +--- a/examples/interfaces/makefile ++++ b/examples/interfaces/makefile +@@ -33,7 +33,7 @@ FBCLIENT = $(FIREBIRD)/lib/libfbclient.so + # General Compiler and linker Defines for Linux + # --------------------------------------------------------------------- + CXX = c++ +-CXXFLAGS= -c -Wall -g3 -std=c++11 -fno-rtti $(INCLUDE) ++CXXFLAGS= -c -Wall -g3 -std=c++17 -fno-rtti $(INCLUDE) + RM = rm -f + + # +diff --git a/extern/icu/android/aarch64/config.sh b/extern/icu/android/aarch64/config.sh +index 51ef623a3c5..f464d930ec2 100755 +--- a/extern/icu/android/aarch64/config.sh ++++ b/extern/icu/android/aarch64/config.sh +@@ -18,7 +18,7 @@ + --enable-dyload \ + --with-cross-build=$CROSS_BUILD_DIR \ + CFLAGS='-Os' \ +- CXXFLAGS='--std=c++11' \ ++ CXXFLAGS='--std=c++17' \ + LDFLAGS='-static-libstdc++' \ + CC=aarch64-linux-android24-clang \ + CXX=aarch64-linux-android24-clang++ \ +diff --git a/extern/icu/android/armv7a/config.sh b/extern/icu/android/armv7a/config.sh +index fe1bd037456..0e458c690e7 100755 +--- a/extern/icu/android/armv7a/config.sh ++++ b/extern/icu/android/armv7a/config.sh +@@ -18,10 +18,10 @@ + --enable-dyload \ + --with-cross-build=$CROSS_BUILD_DIR \ + CFLAGS='-Os -march=armv7-a -mfloat-abi=softfp -mfpu=neon' \ +- CXXFLAGS='--std=c++11 -march=armv7-a -mfloat-abi=softfp -mfpu=neon' \ ++ CXXFLAGS='--std=c++17 -march=armv7-a -mfloat-abi=softfp -mfpu=neon' \ + LDFLAGS='-static-libstdc++ -march=armv7-a -Wl,--fix-cortex-a8' \ + CC=arm-linux-androideabi-clang \ + CXX=arm-linux-androideabi-clang++ \ + AR=arm-linux-androideabi-ar \ + RANLIB=arm-linux-androideabi-ranlib \ +- --with-data-packaging=archive +\ No newline at end of file ++ --with-data-packaging=archive +diff --git a/extern/icu/android/linux/config.sh b/extern/icu/android/linux/config.sh +index a8b56024aae..6e7d9c5f5c8 100755 +--- a/extern/icu/android/linux/config.sh ++++ b/extern/icu/android/linux/config.sh +@@ -1,7 +1,7 @@ + #!/bin/sh + ../source/runConfigureICU Linux --prefix=$PWD/prebuilt \ + CFLAGS="-Os" \ +- CXXFLAGS="--std=c++11" \ ++ CXXFLAGS="--std=c++17" \ + --enable-static \ + --enable-shared=no \ + --enable-extras=no \ diff --git a/cloop-honour-build-flags.patch b/cloop-honour-build-flags.patch index 735e3b9..b854300 100644 --- a/cloop-honour-build-flags.patch +++ b/cloop-honour-build-flags.patch @@ -1,7 +1,5 @@ -Description: make cloop build honor compiler/linker flags from the environment -Author: Damyan Ivanov -Forwarded: no - +diff --git a/extern/cloop/Makefile b/extern/cloop/Makefile +index 08516c2..1573dc2 100644 --- a/extern/cloop/Makefile +++ b/extern/cloop/Makefile @@ -6,7 +6,7 @@ TARGET := release @@ -13,7 +11,7 @@ Forwarded: no SRC_DIR := src BUILD_DIR := build -@@ -27,8 +27,9 @@ SRCS_CPP := $(foreach sdir,$(SRC_DIRS),$ +@@ -27,8 +27,9 @@ SRCS_CPP := $(foreach sdir,$(SRC_DIRS),$(wildcard $(sdir)/*.cpp)) OBJS_C := $(patsubst $(SRC_DIR)/%.c,$(OBJ_DIR)/%.o,$(SRCS_C)) OBJS_CPP := $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(SRCS_CPP)) @@ -24,4 +22,17 @@ Forwarded: no +CXX_FLAGS := $(COMMON_C_FLAGS) $(CXXFLAGS) $(CPPFLAGS) FPC_FLAGS := -Mdelphi - ifeq ($(TARGET),release) + ifeq ($(shell uname),FreeBSD) +diff --git a/extern/btyacc/Makefile b/extern/btyacc/Makefile +index f432965..52d8443 100644 +--- a/extern/btyacc/Makefile ++++ b/extern/btyacc/Makefile +@@ -12,7 +12,7 @@ HDRS = defs.h mstring.h + # across all of our supported compilers/platforms. + + # Vanilla CFLAGS +-CFLAGS= ++CFLAGS=-fPIE + + # No LDFLAGS + #LDFLAGS= diff --git a/firebird.service b/firebird.service new file mode 100644 index 0000000..bd48870 --- /dev/null +++ b/firebird.service @@ -0,0 +1,15 @@ +[Unit] +Description=Firebird Database Server +After=network.target +Conflicts=firebird-classic.socket + +[Service] +User=firebird +Group=firebird +ExecStart=/usr/sbin/fbguard -forever +StandardError=syslog +RuntimeDirectory=firebird +RuntimeDirectoryMode=0775 + +[Install] +WantedBy=multi-user.target diff --git a/firebird.spec b/firebird.spec index 14619d7..c05f6a6 100644 --- a/firebird.spec +++ b/firebird.spec @@ -1,53 +1,55 @@ -%global upversion 3.0.7.33374 +%global upversion 4.0.0.2496 %global pkgversion Firebird-%{upversion}-0 -%global major 3.0 +%global major 4.0 %global _hardened_build 1 +# firebird is mis-compiled when LTO is enabled. A root +# cause analysis has not yet been completed. Reported upstream. +# Disable LTO for now +%global _lto_cflags %nil Name: firebird Version: %{upversion} -Release: 5%{?dist} +Release: 1%{?dist} Summary: SQL relational database management system License: Interbase URL: http://www.firebirdsql.org/ -Source0: https://github.com/FirebirdSQL/firebird/releases/download/R3_0_7/%{pkgversion}.tar.bz2 +Source0: https://github.com/FirebirdSQL/firebird/releases/download/v4.0.0/%{pkgversion}.tar.xz Source1: firebird-logrotate Source2: README.Fedora -Source3: firebird-superserver.service +Source3: firebird.service Source4: fb_config # from OpenSuse Patch101: add-pkgconfig-files.patch -Patch103: Provide-sized-global-delete-operators-when-compiled.patch # from Debian to be sent upstream -Patch201: obsolete-syslogd.target.patch -Patch202: honour-buildflags.patch Patch203: no-copy-from-icu.patch Patch205: cloop-honour-build-flags.patch # from upstream +Patch301: c++17.patch +Patch302: noexcept.patch -# Support for riscv64, sent upstream: -# http://tracker.firebirdsql.org/browse/CORE-5779 -Patch401: 0001-Port-to-RISC-V-64-bit-riscv64.patch - -BuildRequires: autoconf -BuildRequires: automake -BuildRequires: libtommath-devel -BuildRequires: libtool -BuildRequires: ncurses-devel -BuildRequires: libicu-devel -BuildRequires: libedit-devel -BuildRequires: gcc-c++ -BuildRequires: libstdc++-static -BuildRequires: systemd-units -BuildRequires: chrpath -BuildRequires: zlib-devel -BuildRequires: procmail +BuildRequires: autoconf +BuildRequires: automake +BuildRequires: libtommath-devel +BuildRequires: libtool +BuildRequires: ncurses-devel +BuildRequires: libicu-devel +BuildRequires: libedit-devel +BuildRequires: gcc-c++ +BuildRequires: libstdc++-static +BuildRequires: systemd-units +BuildRequires: chrpath +BuildRequires: zlib-devel +BuildRequires: procmail BuildRequires: make +BuildRequires: libtomcrypt-devel +BuildRequires: unzip +BuildRequires: sed Requires(postun): /usr/sbin/userdel Requires(postun): /usr/sbin/groupdel @@ -61,18 +63,18 @@ Requires: libfbclient2 = %{version}-%{release} Requires: libib-util = %{version}-%{release} Requires: %{name}-utils = %{version}-%{release} -Obsoletes: firebird-arch < 3.0 -Obsoletes: firebird-filesystem < 3.0 -Obsoletes: firebird-classic-common < 3.0 -Obsoletes: firebird-classic < 3.0 -Obsoletes: firebird-superclassic < 3.0 -Obsoletes: firebird-superserver < 3.0 -Conflicts: firebird-arch < 3.0 -Conflicts: firebird-filesystem < 3.0 -Conflicts: firebird-classic-common < 3.0 -Conflicts: firebird-classic < 3.0 -Conflicts: firebird-superclassic < 3.0 -Conflicts: firebird-superserver < 3.0 +Obsoletes: firebird-arch < 4.0 +Obsoletes: firebird-filesystem < 4.0 +Obsoletes: firebird-classic-common < 4.0 +Obsoletes: firebird-classic < 4.0 +Obsoletes: firebird-superclassic < 4.0 +Obsoletes: firebird-superserver < 4.0 +Conflicts: firebird-arch < 4.0 +Conflicts: firebird-filesystem < 4.0 +Conflicts: firebird-classic-common < 4.0 +Conflicts: firebird-classic < 4.0 +Conflicts: firebird-superclassic < 4.0 +Conflicts: firebird-superserver < 4.0 %description @@ -115,9 +117,9 @@ in production systems, under a variety of names, since 1981. %package -n libfbclient2 Summary: Firebird SQL server client library -Obsoletes: firebird-libfbclient < 3.0 -Conflicts: firebird-libfbclient < 3.0 -Obsoletes: firebird-libfbembed < 3.0 +Obsoletes: firebird-libfbclient < 4.0 +Conflicts: firebird-libfbclient < 4.0 +Obsoletes: firebird-libfbembed < 4.0 %description -n libfbclient2 Shared client library for Firebird SQL server. @@ -192,43 +194,41 @@ in production systems, under a variety of names, since 1981. %prep %setup -q -n %{pkgversion} %patch101 -p1 -%patch103 -p1 -%patch201 -p1 -%patch202 -p1 %patch203 -p1 %patch205 -p1 -%patch401 -p1 +%patch301 -p1 +%patch302 -p1 %build export CFLAGS="%{optflags} -fno-strict-aliasing" -export CXXFLAGS="-std=c++14 ${CFLAGS} -fno-delete-null-pointer-checks" +export CXXFLAGS="${CFLAGS} -fno-delete-null-pointer-checks" NOCONFIGURE=1 ./autogen.sh -%configure --prefix=%{_prefix} \ - --disable-binreloc \ +%configure --disable-rpath --prefix=%{_prefix} \ --with-system-editline \ --with-fbbin=%{_bindir} --with-fbsbin=%{_sbindir} \ --with-fbconf=%{_sysconfdir}/%{name} \ - --with-fblib=%{_libdir} --with-fbinclude=%{_includedir}/%{name} \ + --with-fblib=%{_libdir} --with-fbinclude=%{_includedir} \ --with-fbdoc=%{_defaultdocdir}/%{name} \ - --with-fbudf=%{_libdir}/%{name}/udf \ --with-fbsample=%{_defaultdocdir}/%{name}/sample \ - --with-fbsample-db=%{_localstatedir}/lib/%{name}/data/ \ - --with-fbhelp=%{_localstatedir}/lib/%{name}/system/ \ + --with-fbsample-db=%{_localstatedir}/lib/%{name}/data \ + --with-fbhelp=%{_localstatedir}/lib/%{name}/system \ --with-fbintl=%{_libdir}/%{name}/intl \ --with-fbmisc=%{_datadir}/%{name}/misc \ - --with-fbsecure-db=%{_localstatedir}/lib/%{name}/secdb/ \ - --with-fbmsg=%{_localstatedir}/lib/%{name}/system/ \ + --with-fbsecure-db=%{_localstatedir}/lib/%{name}/secdb \ + --with-fbmsg=%{_localstatedir}/lib/%{name}/system \ --with-fblog=%{_localstatedir}/log/%{name} \ - --with-fbglock=%{_var}/run/%{name} \ - --with-fbplugins=%{_libdir}/%{name}/plugins + --with-fbglock=/run/%{name} \ + --with-fbplugins=%{_libdir}/%{name}/plugins \ + --with-fbtzdata=%{_localstatedir}/lib/%{name}/tzdata make %{?_smp_mflags} cd gen -make -f Makefile.install buildRoot +sed -i '/linkFiles "/d' ./install/makeInstallImage.sh +./install/makeInstallImage.sh chmod -R u+w buildroot%{_docdir}/%{name} %install -chmod u+rw,a+rx gen/buildroot/%{_includedir}/firebird/firebird/impl +chmod u+rw,a+rx gen/buildroot/%{_includedir}/firebird/impl cp -r gen/buildroot/* ${RPM_BUILD_ROOT}/ mkdir -p ${RPM_BUILD_ROOT}%{_libdir}/pkgconfig cp -v gen/install/misc/*.pc ${RPM_BUILD_ROOT}%{_libdir}/pkgconfig/ @@ -237,36 +237,27 @@ cd ${RPM_BUILD_ROOT} rm -vf .%{_sbindir}/*.sh mv -v .%{_sbindir}/fb_config .%{_libdir}/ install -p -m 0755 %{SOURCE4} %{buildroot}%{_sbindir}/fb_config -rm -vf .%{_includedir}/%{name}/perf.h +rm -vf .%{_includedir}/perf.h rm -vf .%{_libdir}/libicu*.so -rm -vf .%{_includedir}/*.h chmod -R u+w .%{_docdir}/%{name} -rm -vf .%{_datadir}/%{name}/misc/firebird.init.* -rm -vf .%{_datadir}/%{name}/misc/firebird.xinetd -rm -vf .%{_datadir}/%{name}/misc/rc.config.firebird -mv -v .%{_sysconfdir}/%{name}/README .%{_sysconfdir}/%{name}/WhatsNew \ +mv -v .%{_datadir}/%{name}/misc/upgrade/udf/* .%{_docdir}/%{name}/ +rm -rvf .%{_datadir}/%{name}/misc +mv -v .%{_sysconfdir}/%{name}/README.md .%{_sysconfdir}/%{name}/CHANGELOG.md \ .%{_docdir}/%{name}/ mv -v .%{_sysconfdir}/%{name}/IDPLicense.txt .%{_docdir}/%{name}/ mv -v .%{_sysconfdir}/%{name}/IPLicense.txt .%{_docdir}/%{name}/ install -p -m 0644 -D %{SOURCE2} .%{_docdir}/%{name}/README.Fedora mv -v .%{_bindir}/gstat .%{_bindir}/gstat-fb mv -v .%{_bindir}/isql .%{_bindir}/isql-fb +rm -rvf .%{_defaultdocdir}/%{name}/sample/prebuilt mkdir -p .%{_localstatedir}/log/%{name} mkdir -p .%{_sysconfdir}/logrotate.d echo 1 > .%{_localstatedir}/log/%{name}/%{name}.log sed "s@%{name}.log@%{_localstatedir}/log/%{name}/%{name}.log@g" %{SOURCE1} > .%{_sysconfdir}/logrotate.d/%{name} -cp -f %{SOURCE3} .%{_datadir}/%{name}/misc/%{name}-superserver.service - mkdir -p .%{_unitdir} -cp .%{_datadir}/%{name}/misc/%{name}-superserver.service .%{_unitdir}/%{name}-superserver.service - -%if 0%{?flatpak} -# Remove spurious symlinks to /app/include/firebird/...: -rm -vr usr/include/firebird -rm -v usr/include/{ibase,iberror,ib_util}.h -%endif +cp -f %{SOURCE3} .%{_unitdir}/%{name}.service %pre @@ -284,15 +275,15 @@ fi %post -%systemd_post firebird-superserver.service +%systemd_post firebird.service %postun -%systemd_postun_with_restart firebird-superserver.service +%systemd_postun_with_restart firebird.service %preun -%systemd_preun firebird-superserver.service +%systemd_preun firebird.service %files @@ -308,30 +299,32 @@ fi %config(noreplace) %{_sysconfdir}/%{name}/fbtrace.conf %config(noreplace) %{_sysconfdir}/%{name}/firebird.conf %config(noreplace) %{_sysconfdir}/%{name}/plugins.conf +%config(noreplace) %{_sysconfdir}/%{name}/replication.conf %dir %{_libdir}/%{name} %dir %{_datadir}/%{name} %{_libdir}/%{name}/intl %{_libdir}/%{name}/plugins -%{_libdir}/%{name}/udf -%{_datadir}/%{name}/misc %dir %{_localstatedir}/lib/%{name} %dir %attr(0700,%{name},%{name}) %{_localstatedir}/lib/%{name}/secdb %dir %attr(0700,%{name},%{name}) %{_localstatedir}/lib/%{name}/data %dir %attr(0755,%{name},%{name}) %{_localstatedir}/lib/%{name}/system -%attr(0600,firebird,firebird) %config(noreplace) %{_localstatedir}/lib/%{name}/secdb/security3.fdb +%dir %attr(0755,%{name},%{name}) %{_localstatedir}/lib/%{name}/tzdata +%attr(0600,firebird,firebird) %config(noreplace) %{_localstatedir}/lib/%{name}/secdb/security4.fdb %attr(0644,firebird,firebird) %{_localstatedir}/lib/%{name}/system/help.fdb %attr(0644,firebird,firebird) %{_localstatedir}/lib/%{name}/system/firebird.msg -%ghost %dir %attr(0775,%{name},%{name}) %{_var}/run/%{name} -%ghost %attr(0644,%{name},%{name}) %{_var}/run/%{name}/fb_guard +%attr(0644,firebird,firebird) %{_localstatedir}/lib/%{name}/tzdata/*.res +%ghost %dir %attr(0775,%{name},%{name}) /run/%{name} +%ghost %attr(0644,%{name},%{name}) /run/%{name}/fb_guard %dir %{_localstatedir}/log/%{name} %config(noreplace) %attr(0664,%{name},%{name}) %{_localstatedir}/log/%{name}/%{name}.log %config(noreplace) %attr(0644,root,root) %{_sysconfdir}/logrotate.d/%{name} -%attr(0644,root,root) %{_unitdir}/%{name}-superserver.service +%attr(0644,root,root) %{_unitdir}/%{name}.service %files devel +%{_includedir}/*.h %{_includedir}/%{name} %{_libdir}/fb_config %{_sbindir}/fb_config @@ -376,6 +369,9 @@ fi %changelog +* Tue Jun 08 2021 Philippe Makowski - 4.0.0.2496-1 +- Update to 4.0.0 (#1963311) + * Mon May 10 2021 Jeff Law - 3.0.7.33374-5 - Re-enable LTO diff --git a/honour-buildflags.patch b/honour-buildflags.patch deleted file mode 100644 index 221241d..0000000 --- a/honour-buildflags.patch +++ /dev/null @@ -1,78 +0,0 @@ -Description: improved support for build flags - The first change makes linking makeHeader use the same CPP/CXX/LD flags as the - rest of the sources. - The second change stops btyacc/Makefile from ignoring CFLAGS from the - environment. - The third change stops overriding CXXFLAGS - The result is using hardening flags from the environment when compiling and - linking. -Author: Damyan Ivanov - ---- a/builds/posix/Makefile.in -+++ b/builds/posix/Makefile.in -@@ -623,7 +623,7 @@ MAKE_HEADER_Src = $(addprefix $(SRC_ROOT - MAKE_HEADER_Bin = ./makeHeader - - $(INCLUDE_DEST)/ibase.h: $(SRC_IBASE_ExtraFiles) -- $(STATICEXE_LINK) -o $(MAKE_HEADER_Bin) $(MAKE_HEADER_Src) -+ $(STATICEXE_LINK) $(EXE_LINK_OPTIONS) $(LINK_OPTS) $(CPPFLAGS) -o $(MAKE_HEADER_Bin) $(MAKE_HEADER_Src) - $(CP) $^ . - $(MAKE_HEADER_Bin) $@ - $(RM) -f ibase.h ---- a/extern/btyacc/Makefile -+++ b/extern/btyacc/Makefile -@@ -42,7 +42,7 @@ OTHERS = README README.BYACC \ - all: $(PROGRAM) - - $(PROGRAM): $(OBJS) $(LIBS) -- $(CC) $(LDFLAGS) -o $(PROGRAM) $(OBJS) $(LIBS) -+ $(CC) $(CFLAGS) $(LDFLAGS) -o $(PROGRAM) $(OBJS) $(LIBS) - - clean:; rm -f $(OBJS) - ---- a/builds/posix/make.defaults -+++ b/builds/posix/make.defaults -@@ -166,8 +166,8 @@ LD = @CXX@ - - LIB_LINK = $(CXX) $(GLOB_OPTIONS) $(CXXFLAGS) - STATICLIB_LINK = $(AR) crus --EXE_LINK = $(CXX) $(GLOB_OPTIONS) $(CXXFLAGS) --STATICEXE_LINK = $(CXX) $(GLOB_OPTIONS) $(CXXFLAGS) -+EXE_LINK = $(CXX) $(GLOB_OPTIONS) $(CXXFLAGS) $(LDFLAGS) -+STATICEXE_LINK = $(CXX) $(GLOB_OPTIONS) $(CXXFLAGS) $(LDFLAGS) - - LINK_LIBS = @LIBS@ - STATICLINK_LIBS = @LIBS@ ---- a/builds/posix/prefix.linux -+++ b/builds/posix/prefix.linux -@@ -19,7 +19,7 @@ - # 2 Oct 2002, Nickolay Samofatov - Major cleanup - - COMMON_FLAGS=-ggdb -DFB_SEND_FLAGS=MSG_NOSIGNAL -DLINUX -pipe -MMD -fPIC -fmessage-length=0 -fno-delete-null-pointer-checks --CXXFLAGS=-std=gnu++03 -+CXXFLAGS+=-std=gnu++03 - OPTIMIZE_FLAGS=-O3 -march=i586 -mtune=i686 -fno-omit-frame-pointer - WARN_FLAGS=-Wall -Wno-switch -Wno-parentheses -Wno-unknown-pragmas -Wno-unused-variable -Wno-narrowing - ---- a/builds/posix/prefix.linux_amd64 -+++ b/builds/posix/prefix.linux_amd64 -@@ -19,7 +19,7 @@ - # 2 Oct 2002, Nickolay Samofatov - Major cleanup - - COMMON_FLAGS=-ggdb -DFB_SEND_FLAGS=MSG_NOSIGNAL -DLINUX -DAMD64 -pipe -MMD -fPIC -fmessage-length=0 -fno-delete-null-pointer-checks --CXXFLAGS=-std=gnu++03 -+CXXFLAGS+=-std=gnu++03 - OPTIMIZE_FLAGS=-O3 -fno-omit-frame-pointer - WARN_FLAGS=-Wall -Wno-switch -Wno-parentheses -Wno-unknown-pragmas -Wno-unused-variable -Wno-invalid-offsetof -Wno-narrowing -Wno-unused-local-typedefs - ---- a/builds/posix/prefix.linux_generic -+++ b/builds/posix/prefix.linux_generic -@@ -19,7 +19,7 @@ - # 2 Oct 2002, Nickolay Samofatov - Major cleanup - - COMMON_FLAGS=-DLINUX -pipe -MMD -fPIC -DFB_SEND_FLAGS=MSG_NOSIGNAL -fno-delete-null-pointer-checks --CXXFLAGS=-std=gnu++03 -+CXXFLAGS+=-std=gnu++03 - - PROD_FLAGS=-ggdb -O3 $(COMMON_FLAGS) - DEV_FLAGS=-ggdb -p -Wall -Wno-switch $(COMMON_FLAGS) -Wno-non-virtual-dtor diff --git a/no-copy-from-icu.patch b/no-copy-from-icu.patch index 94c2b80..7f84e0b 100644 --- a/no-copy-from-icu.patch +++ b/no-copy-from-icu.patch @@ -1,9 +1,21 @@ -Description: Link isql with ICU instead of embedding part of it in the source -Author: Damyan Ivanov - +diff --git a/builds/posix/Makefile.in b/builds/posix/Makefile.in +index bb4ceb1..87e75a2 100644 +--- a/builds/posix/Makefile.in ++++ b/builds/posix/Makefile.in +@@ -534,7 +534,7 @@ $(GSTAT): $(GSTAT_Objects) $(COMMON_LIB) + isql: $(ISQL) + + $(ISQL): $(ISQL_Objects) $(COMMON_LIB) +- $(EXE_LINK) $(EXE_LINK_OPTIONS) $^ -o $@ $(FIREBIRD_LIBRARY_LINK) $(LIBEDITLINE) $(TERMLIB) $(LINK_LIBS) $(call LINK_DARWIN_RPATH,..) ++ $(EXE_LINK) $(EXE_LINK_OPTIONS) $^ -o $@ $(FIREBIRD_LIBRARY_LINK) $(LIBEDITLINE) $(TERMLIB) $(LINK_LIBS) $(ICU_LIBS) $(call LINK_DARWIN_RPATH,..) + + nbackup: $(NBACKUP) + +diff --git a/src/isql/isql.epp b/src/isql/isql.epp +index 79da1f7..4554252 100644 --- a/src/isql/isql.epp +++ b/src/isql/isql.epp -@@ -167,34 +167,6 @@ const char* UNKNOWN = "*unknown*"; +@@ -173,34 +173,6 @@ const char* UNKNOWN = "*unknown*"; namespace IcuUtil { @@ -38,14 +50,3 @@ Author: Damyan Ivanov // Return the number of characters of a string. static unsigned charLength(SSHORT charset, unsigned len, const char* str) { ---- a/builds/posix/Makefile.in -+++ b/builds/posix/Makefile.in -@@ -481,7 +481,7 @@ $(GSTAT): $(GSTAT_Objects) $(COMMON_LIB - isql: $(ISQL) - - $(ISQL): $(ISQL_Objects) $(COMMON_LIB) -- $(EXE_LINK) $(EXE_LINK_OPTIONS) $^ -o $@ $(FIREBIRD_LIBRARY_LINK) $(LIBEDITLINE) $(LINK_LIBS) $(call LINK_DARWIN_RPATH,..) -+ $(EXE_LINK) $(EXE_LINK_OPTIONS) $^ -o $@ $(FIREBIRD_LIBRARY_LINK) $(LIBEDITLINE) $(LINK_LIBS) $(ICU_LIBS) $(call LINK_DARWIN_RPATH,..) - - nbackup: $(NBACKUP) - diff --git a/noexcept.patch b/noexcept.patch new file mode 100644 index 0000000..f1a1f48 --- /dev/null +++ b/noexcept.patch @@ -0,0 +1,664 @@ +From a999f35f0fad27798fdc88a3f5cdf2e3e9041594 Mon Sep 17 00:00:00 2001 +From: Adriano dos Santos Fernandes +Date: Mon, 31 May 2021 08:55:26 -0300 +Subject: [PATCH] Replace FB_NOTHROW by noexcept and remove FB_THROW. + +--- + src/common/classes/alloc.cpp | 128 +++++++++++++++++------------------ + src/common/classes/alloc.h | 74 ++++++++------------ + 2 files changed, 94 insertions(+), 108 deletions(-) + +diff --git a/src/common/classes/alloc.cpp b/src/common/classes/alloc.cpp +index 1bd6ad4f09d..ee91ab89df8 100644 +--- a/src/common/classes/alloc.cpp ++++ b/src/common/classes/alloc.cpp +@@ -68,19 +68,19 @@ + #define VALGRIND_FIX_IT // overrides suspicious valgrind behavior + #endif // USE_VALGRIND + +-void* operator new(size_t s ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) ++void* operator new(size_t s ALLOC_PARAMS) + { + return MemoryPool::globalAlloc(s ALLOC_PASS_ARGS); + } +-void* operator new[](size_t s ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) ++void* operator new[](size_t s ALLOC_PARAMS) + { + return MemoryPool::globalAlloc(s ALLOC_PASS_ARGS); + } +-void operator delete(void* mem ALLOC_PARAMS) FB_NOTHROW ++void operator delete(void* mem ALLOC_PARAMS) noexcept + { + MemoryPool::globalFree(mem); + } +-void operator delete[](void* mem ALLOC_PARAMS) FB_NOTHROW ++void operator delete[](void* mem ALLOC_PARAMS) noexcept + { + MemoryPool::globalFree(mem); + } +@@ -109,7 +109,7 @@ static const int GUARD_BYTES = 0; + #endif + + template +-T absVal(T n) FB_NOTHROW ++T absVal(T n) noexcept + { + return n < 0 ? -n : n; + } +@@ -160,7 +160,7 @@ struct FailedBlock + FailedBlock* failedList = NULL; + #endif + +-void corrupt(const char* text) FB_NOTHROW ++void corrupt(const char* text) noexcept + { + #ifdef DEV_BUILD + fprintf(stderr, "%s\n", text); +@@ -377,7 +377,7 @@ class MemHeader + + #ifdef MEM_DEBUG + void print_contents(bool used, FILE* file, bool used_only, +- const char* filter_path, const size_t filter_len) FB_NOTHROW ++ const char* filter_path, const size_t filter_len) noexcept + { + if (used || !used_only) + { +@@ -406,7 +406,7 @@ class MemHeader + } + #endif + +- void validate(MemPool* p, StatInt& vUse) FB_NOTHROW ++ void validate(MemPool* p, StatInt& vUse) noexcept + { + if (p == pool && !isExtent()) + vUse += getSize(); +@@ -461,7 +461,7 @@ class MemBaseHunk + } + + public: +- void validate(MemPool* pool, size_t hdr, StatInt& vMap, StatInt& vUse) FB_NOTHROW ++ void validate(MemPool* pool, size_t hdr, StatInt& vMap, StatInt& vUse) noexcept + { + if (length >= DEFAULT_ALLOCATION) + { +@@ -526,7 +526,7 @@ class MemSmallHunk : public MemBaseHunk + + #ifdef MEM_DEBUG + void print_contents(FILE* file, MemPool* pool, bool used_only, +- const char* filter_path, const size_t filter_len) FB_NOTHROW ++ const char* filter_path, const size_t filter_len) noexcept + { + UCHAR* m = ((UCHAR*) this) + hdrSize(); + fprintf(file, "Small hunk %p: memory=[%p:%p) spaceRemaining=%" SIZEFORMAT " length=%" SIZEFORMAT "\n", +@@ -598,7 +598,7 @@ class MemMediumHunk : public MemBaseHunk + + #ifdef MEM_DEBUG + void print_contents(FILE* file, MemPool* pool, bool used_only, +- const char* filter_path, const size_t filter_len) FB_NOTHROW ++ const char* filter_path, const size_t filter_len) noexcept + { + UCHAR* m = ((UCHAR*) this) + hdrSize(); + fprintf(file, "Medium hunk %p: memory=[%p:%p) spaceRemaining=%" SIZEFORMAT " length=%" SIZEFORMAT "\n", +@@ -630,7 +630,7 @@ class MemBigHunk + + #ifdef MEM_DEBUG + void print_contents(FILE* file, MemPool* pool, bool used_only, +- const char* filter_path, const size_t filter_len) FB_NOTHROW ++ const char* filter_path, const size_t filter_len) noexcept + { + fprintf(file, "Big hunk %p: memory=%p length=%" SIZEFORMAT "\n", + this, block, length); +@@ -1647,7 +1647,7 @@ class FreeObjects + + ~FreeObjects(); + +- FreeObjPtr allocateBlock(MemPool* pool, size_t from, size_t& size) FB_THROW (OOM_EXCEPTION) ++ FreeObjPtr allocateBlock(MemPool* pool, size_t from, size_t& size) + { + size_t full_size = size + (from ? 0 : ListBuilder::MEM_OVERHEAD); + if (full_size > Limits::TOP_LIMIT) +@@ -1696,7 +1696,7 @@ class FreeObjects + + #ifdef MEM_DEBUG + void print_contents(FILE* file, MemPool* pool, bool used_only, +- const char* filter_path, const size_t filter_len) FB_NOTHROW ++ const char* filter_path, const size_t filter_len) noexcept + { + for (Extent* ext = currentExtent; ext; ext = ext->next) + ext->print_contents(file, pool, used_only, filter_path, filter_len); +@@ -1717,7 +1717,7 @@ class FreeObjects + ListBuilder listBuilder; + Extent* currentExtent; + +- MemBlock* newBlock(MemPool* pool, unsigned slot) FB_THROW (OOM_EXCEPTION); ++ MemBlock* newBlock(MemPool* pool, unsigned slot); + }; + + +@@ -1799,26 +1799,26 @@ class MemPool + }; + #endif // VALIDATE_POOL + +- MemBlock* alloc(size_t from, size_t& length, bool flagRedirect) FB_THROW (OOM_EXCEPTION); +- void releaseBlock(MemBlock *block, bool flagDecr) FB_NOTHROW; ++ MemBlock* alloc(size_t from, size_t& length, bool flagRedirect); ++ void releaseBlock(MemBlock *block, bool flagDecr) noexcept; + + public: +- void* allocate(size_t size ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION); +- MemBlock* allocate2(size_t from, size_t& size ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION); ++ void* allocate(size_t size ALLOC_PARAMS); ++ MemBlock* allocate2(size_t from, size_t& size ALLOC_PARAMS); + + private: +- virtual void memoryIsExhausted(void) FB_THROW (OOM_EXCEPTION); +- void* allocRaw(size_t length) FB_THROW (OOM_EXCEPTION); +- static void releaseMemory(void* block, bool flagExtent) FB_NOTHROW; +- static void releaseRaw(bool destroying, void *block, size_t size, bool use_cache = true) FB_NOTHROW; +- void* getExtent(size_t from, size_t& to) FB_THROW (OOM_EXCEPTION); ++ virtual void memoryIsExhausted(void); ++ void* allocRaw(size_t length); ++ static void releaseMemory(void* block, bool flagExtent) noexcept; ++ static void releaseRaw(bool destroying, void *block, size_t size, bool use_cache = true) noexcept; ++ void* getExtent(size_t from, size_t& to); + + public: +- static void releaseExtent(bool destroying, void *block, size_t size, MemPool* pool) FB_NOTHROW; ++ static void releaseExtent(bool destroying, void *block, size_t size, MemPool* pool) noexcept; + + // pass desired size, return actual extent size + template +- void newExtent(size_t& size, Extent** linkedList) FB_THROW (OOM_EXCEPTION); ++ void newExtent(size_t& size, Extent** linkedList); + + private: + #ifdef USE_VALGRIND +@@ -1830,9 +1830,9 @@ class MemPool + + public: + static void deletePool(MemPool* pool); +- static void globalFree(void* block) FB_NOTHROW; ++ static void globalFree(void* block) noexcept; + +- static void deallocate(void* block) FB_NOTHROW; ++ static void deallocate(void* block) noexcept; + bool validate(char* buf, FB_SIZE_T size); + + // Create memory pool instance +@@ -1840,7 +1840,7 @@ class MemPool + + // Set statistics group for pool. Usage counters will be decremented from + // previously set group and added to new +- void setStatsGroup(MemoryStats& stats) FB_NOTHROW; ++ void setStatsGroup(MemoryStats& stats) noexcept; + + // Initialize and finalize global memory pool + static MemPool* init() +@@ -1893,25 +1893,25 @@ class MemPool + } + + // Statistics +- void increment_usage(size_t size) FB_NOTHROW ++ void increment_usage(size_t size) noexcept + { + stats->increment_usage(size); + used_memory += size; + } + +- void decrement_usage(size_t size) FB_NOTHROW ++ void decrement_usage(size_t size) noexcept + { + stats->decrement_usage(size); + used_memory -= size; + } + +- void increment_mapping(size_t size) FB_NOTHROW ++ void increment_mapping(size_t size) noexcept + { + stats->increment_mapping(size); + mapped_memory += size; + } + +- void decrement_mapping(size_t size) FB_NOTHROW ++ void decrement_mapping(size_t size) noexcept + { + stats->decrement_mapping(size); + mapped_memory -= size; +@@ -1919,9 +1919,9 @@ class MemPool + + #ifdef MEM_DEBUG + // Print out pool contents. This is debugging routine +- void print_contents(FILE*, unsigned flags, const char* filter_path) FB_NOTHROW; ++ void print_contents(FILE*, unsigned flags, const char* filter_path) noexcept; + // The same routine, but more easily callable from the debugger +- void print_contents(const char* filename, unsigned flags, const char* filter_path) FB_NOTHROW; ++ void print_contents(const char* filename, unsigned flags, const char* filter_path) noexcept; + + private: + MemPool* next; +@@ -1961,7 +1961,7 @@ void DoubleLinkedList::decrUsage(MemMediumHunk* hunk, MemPool* pool) + + + template +-MemBlock* FreeObjects::newBlock(MemPool* pool, unsigned slot) FB_THROW (OOM_EXCEPTION) ++MemBlock* FreeObjects::newBlock(MemPool* pool, unsigned slot) + { + size_t size = Limits::getSize(slot); + +@@ -2170,7 +2170,7 @@ MemPool::~MemPool(void) + } + + template +-void MemPool::newExtent(size_t& size, Extent** linkedList) FB_THROW(OOM_EXCEPTION) ++void MemPool::newExtent(size_t& size, Extent** linkedList) + { + // No large enough block found. We need to extend the pool + void* memory = NULL; +@@ -2214,7 +2214,7 @@ MemoryPool* MemoryPool::createPool(MemoryPool* parentPool, MemoryStats& stats) + return FB_NEW_POOL(*parentPool) MemoryPool(p); + } + +-void MemPool::setStatsGroup(MemoryStats& newStats) FB_NOTHROW ++void MemPool::setStatsGroup(MemoryStats& newStats) noexcept + { + MutexLockGuard guard(mutex, "MemPool::setStatsGroup"); + +@@ -2230,12 +2230,12 @@ void MemPool::setStatsGroup(MemoryStats& newStats) FB_NOTHROW + stats->increment_usage(sav_used_memory); + } + +-void MemoryPool::setStatsGroup(MemoryStats& newStats) FB_NOTHROW ++void MemoryPool::setStatsGroup(MemoryStats& newStats) noexcept + { + pool->setStatsGroup(newStats); + } + +-MemBlock* MemPool::alloc(size_t from, size_t& length, bool flagRedirect) FB_THROW (OOM_EXCEPTION) ++MemBlock* MemPool::alloc(size_t from, size_t& length, bool flagRedirect) + { + MutexEnsureUnlock guard(mutex, "MemPool::alloc"); + guard.enter(); +@@ -2294,7 +2294,7 @@ MemBlock* MemPool::allocate2(size_t from, size_t& size + #ifdef DEBUG_GDS_ALLOC + , const char* fileName, int line + #endif +-) FB_THROW (OOM_EXCEPTION) ++) + { + size_t length = from ? size : ROUNDUP(size + VALGRIND_REDZONE, roundingSize) + GUARD_BYTES; + MemBlock* memory = alloc(from, length, true); +@@ -2324,7 +2324,7 @@ MemBlock* MemPool::allocate2(size_t from, size_t& size + } + + +-void* MemPool::allocate(size_t size ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) ++void* MemPool::allocate(size_t size ALLOC_PARAMS) + { + #ifdef VALIDATE_POOL + MutexLockGuard guard(mutex, "MemPool::allocate"); +@@ -2339,7 +2339,7 @@ void* MemPool::allocate(size_t size ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) + } + + +-void MemPool::releaseMemory(void* object, bool flagExtent) FB_NOTHROW ++void MemPool::releaseMemory(void* object, bool flagExtent) noexcept + { + if (object) + { +@@ -2403,7 +2403,7 @@ void MemPool::releaseMemory(void* object, bool flagExtent) FB_NOTHROW + } + } + +-void MemPool::releaseBlock(MemBlock* block, bool decrUsage) FB_NOTHROW ++void MemPool::releaseBlock(MemBlock* block, bool decrUsage) noexcept + { + if (block->pool != this) + corrupt("bad block released"); +@@ -2464,12 +2464,12 @@ void MemPool::releaseBlock(MemBlock* block, bool decrUsage) FB_NOTHROW + releaseRaw(pool_destroying, hunk, hunk->length, false); + } + +-void MemPool::memoryIsExhausted(void) FB_THROW (OOM_EXCEPTION) ++void MemPool::memoryIsExhausted(void) + { + Firebird::BadAlloc::raise(); + } + +-void* MemPool::allocRaw(size_t size) FB_THROW (OOM_EXCEPTION) ++void* MemPool::allocRaw(size_t size) + { + #ifndef USE_VALGRIND + if (size == DEFAULT_ALLOCATION) +@@ -2549,7 +2549,7 @@ void* MemPool::allocRaw(size_t size) FB_THROW (OOM_EXCEPTION) + } + + +-void* MemPool::getExtent(size_t from, size_t& to) FB_THROW(OOM_EXCEPTION) // pass desired minimum size, return actual extent size ++void* MemPool::getExtent(size_t from, size_t& to) // pass desired minimum size, return actual extent size + { + #ifdef VALIDATE_POOL + MutexLockGuard guard(mutex, "MemPool::getExtent"); +@@ -2560,7 +2560,7 @@ void* MemPool::getExtent(size_t from, size_t& to) FB_THROW(OOM_EXCEPTION) // pa + } + + +-void MemPool::releaseExtent(bool destroying, void* block, size_t size, MemPool* pool) FB_NOTHROW ++void MemPool::releaseExtent(bool destroying, void* block, size_t size, MemPool* pool) noexcept + { + if (size < DEFAULT_ALLOCATION) + releaseMemory(block, true); +@@ -2573,7 +2573,7 @@ void MemPool::releaseExtent(bool destroying, void* block, size_t size, MemPool* + } + + +-void MemPool::releaseRaw(bool destroying, void* block, size_t size, bool use_cache) FB_NOTHROW ++void MemPool::releaseRaw(bool destroying, void* block, size_t size, bool use_cache) noexcept + { + #ifndef USE_VALGRIND + if (use_cache && (size == DEFAULT_ALLOCATION)) +@@ -2666,19 +2666,19 @@ void MemPool::releaseRaw(bool destroying, void* block, size_t size, bool use_cac + } + } + +-void MemPool::globalFree(void* block) FB_NOTHROW ++void MemPool::globalFree(void* block) noexcept + { + deallocate(block); + } + +-void* MemoryPool::calloc(size_t size ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) ++void* MemoryPool::calloc(size_t size ALLOC_PARAMS) + { + void* block = allocate(size ALLOC_PASS_ARGS); + memset(block, 0, size); + return block; + } + +-void MemPool::deallocate(void* block) FB_NOTHROW ++void MemPool::deallocate(void* block) noexcept + { + releaseMemory(block, false); + } +@@ -2720,7 +2720,7 @@ bool MemPool::validate(char* buf, FB_SIZE_T size) + } + + #ifdef MEM_DEBUG +-void MemPool::print_contents(const char* filename, unsigned flags, const char* filter_path) FB_NOTHROW ++void MemPool::print_contents(const char* filename, unsigned flags, const char* filter_path) noexcept + { + FILE* out = os_utils::fopen(filename, "w"); + if (!out) +@@ -2731,7 +2731,7 @@ void MemPool::print_contents(const char* filename, unsigned flags, const char* f + } + + // This member function can't be const because there are calls to the mutex. +-void MemPool::print_contents(FILE* file, unsigned flags, const char* filter_path) FB_NOTHROW ++void MemPool::print_contents(FILE* file, unsigned flags, const char* filter_path) noexcept + { + bool used_only = flags & MemoryPool::PRINT_USED_ONLY; + +@@ -2818,7 +2818,7 @@ MemoryPool& AutoStorage::getAutoMemoryPool() + } + + #ifdef LIBC_CALLS_NEW +-void* MemoryPool::globalAlloc(size_t s ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) ++void* MemoryPool::globalAlloc(size_t s ALLOC_PARAMS) + { + if (!defaultMemoryManager) + { +@@ -2831,17 +2831,17 @@ void* MemoryPool::globalAlloc(size_t s ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) + } + #endif // LIBC_CALLS_NEW + +-void MemoryPool::globalFree(void* block) FB_NOTHROW ++void MemoryPool::globalFree(void* block) noexcept + { + MemPool::globalFree(block); + } + +-void* MemoryPool::allocate(size_t size ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) ++void* MemoryPool::allocate(size_t size ALLOC_PARAMS) + { + return pool->allocate(size ALLOC_PASS_ARGS); + } + +-void MemoryPool::deallocate(void* block) FB_NOTHROW ++void MemoryPool::deallocate(void* block) noexcept + { + pool->deallocate(block); + } +@@ -2870,14 +2870,14 @@ void MemoryPool::deletePool(MemoryPool* pool) + delete pool; + } + +-void MemoryPool::print_contents(FILE* file, unsigned flags, const char* filter_path) FB_NOTHROW ++void MemoryPool::print_contents(FILE* file, unsigned flags, const char* filter_path) noexcept + { + #ifdef MEM_DEBUG + pool->print_contents(file, flags, filter_path); + #endif + } + +-void MemoryPool::print_contents(const char* filename, unsigned flags, const char* filter_path) FB_NOTHROW ++void MemoryPool::print_contents(const char* filename, unsigned flags, const char* filter_path) noexcept + { + #ifdef MEM_DEBUG + pool->print_contents(filename, flags, filter_path); +@@ -2950,21 +2950,21 @@ void AutoStorage::ProbeStack() const + // in a case when we actually need "new" only with file/line information + // this version should be also present as a pair for "delete". + #ifdef DEBUG_GDS_ALLOC +-void* operator new(size_t s) FB_THROW (OOM_EXCEPTION) ++void* operator new(size_t s) + { + return MemoryPool::globalAlloc(s ALLOC_ARGS); + } +-void* operator new[](size_t s) FB_THROW (OOM_EXCEPTION) ++void* operator new[](size_t s) + { + return MemoryPool::globalAlloc(s ALLOC_ARGS); + } + +-void operator delete(void* mem) FB_NOTHROW ++void operator delete(void* mem) noexcept + { + MemoryPool::globalFree(mem); + } + +-void operator delete[](void* mem) FB_NOTHROW ++void operator delete[](void* mem) noexcept + { + MemoryPool::globalFree(mem); + } +diff --git a/src/common/classes/alloc.h b/src/common/classes/alloc.h +index 65f9afbb8a9..44d9e0ea462 100644 +--- a/src/common/classes/alloc.h ++++ b/src/common/classes/alloc.h +@@ -58,20 +58,6 @@ + + #include + +-#define OOM_EXCEPTION std::bad_alloc +- +-#if __cplusplus >= 201103L +-#define FB_NO_THROW_SPECIFIER +-#endif +- +-#ifdef FB_NO_THROW_SPECIFIER +-#define FB_THROW(x) +-#define FB_NOTHROW noexcept +-#else +-#define FB_THROW(x) throw(x) +-#define FB_NOTHROW throw() +-#endif +- + #ifdef DEBUG_GDS_ALLOC + #define FB_NEW new(__FILE__, __LINE__) + #define FB_NEW_POOL(pool) new(pool, __FILE__, __LINE__) +@@ -106,10 +92,10 @@ class MemoryStats + ~MemoryStats() + {} + +- size_t getCurrentUsage() const FB_NOTHROW { return mst_usage.value(); } +- size_t getMaximumUsage() const FB_NOTHROW { return mst_max_usage; } +- size_t getCurrentMapping() const FB_NOTHROW { return mst_mapped.value(); } +- size_t getMaximumMapping() const FB_NOTHROW { return mst_max_mapped; } ++ size_t getCurrentUsage() const noexcept { return mst_usage.value(); } ++ size_t getMaximumUsage() const noexcept { return mst_max_usage; } ++ size_t getCurrentMapping() const noexcept { return mst_mapped.value(); } ++ size_t getMaximumMapping() const noexcept { return mst_max_mapped; } + + private: + // Forbid copying/assignment +@@ -131,7 +117,7 @@ class MemoryStats + size_t mst_max_mapped; + + // These methods are thread-safe due to usage of atomic counters only +- void increment_usage(size_t size) FB_NOTHROW ++ void increment_usage(size_t size) noexcept + { + for (MemoryStats* statistics = this; statistics; statistics = statistics->mst_parent) + { +@@ -141,7 +127,7 @@ class MemoryStats + } + } + +- void decrement_usage(size_t size) FB_NOTHROW ++ void decrement_usage(size_t size) noexcept + { + for (MemoryStats* statistics = this; statistics; statistics = statistics->mst_parent) + { +@@ -149,7 +135,7 @@ class MemoryStats + } + } + +- void increment_mapping(size_t size) FB_NOTHROW ++ void increment_mapping(size_t size) noexcept + { + for (MemoryStats* statistics = this; statistics; statistics = statistics->mst_parent) + { +@@ -159,7 +145,7 @@ class MemoryStats + } + } + +- void decrement_mapping(size_t size) FB_NOTHROW ++ void decrement_mapping(size_t size) noexcept + { + for (MemoryStats* statistics = this; statistics; statistics = statistics->mst_parent) + { +@@ -205,21 +191,21 @@ class MemoryPool + #define ALLOC_PASS_ARGS + #endif // DEBUG_GDS_ALLOC + +- void* calloc(size_t size ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION); ++ void* calloc(size_t size ALLOC_PARAMS); + + #ifdef LIBC_CALLS_NEW +- static void* globalAlloc(size_t s ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION); ++ static void* globalAlloc(size_t s ALLOC_PARAMS); + #else +- static void* globalAlloc(size_t s ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) ++ static void* globalAlloc(size_t s ALLOC_PARAMS) + { + return defaultMemoryManager->allocate(s ALLOC_PASS_ARGS); + } + #endif // LIBC_CALLS_NEW + +- void* allocate(size_t size ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION); ++ void* allocate(size_t size ALLOC_PARAMS); + +- static void globalFree(void* mem) FB_NOTHROW; +- void deallocate(void* mem) FB_NOTHROW; ++ static void globalFree(void* mem) noexcept; ++ void deallocate(void* mem) noexcept; + + // Set context pool for current thread of execution + static MemoryPool* setContextPool(MemoryPool* newPool); +@@ -229,7 +215,7 @@ class MemoryPool + + // Set statistics group for pool. Usage counters will be decremented from + // previously set group and added to new +- void setStatsGroup(MemoryStats& stats) FB_NOTHROW; ++ void setStatsGroup(MemoryStats& stats) noexcept; + + // Initialize and finalize global memory pool + static void init(); +@@ -241,9 +227,9 @@ class MemoryPool + // Print out pool contents. This is debugging routine + static const unsigned PRINT_USED_ONLY = 0x01; + static const unsigned PRINT_RECURSIVE = 0x02; +- void print_contents(FILE*, unsigned flags = 0, const char* filter_path = 0) FB_NOTHROW; ++ void print_contents(FILE*, unsigned flags = 0, const char* filter_path = 0) noexcept; + // The same routine, but more easily callable from the debugger +- void print_contents(const char* filename, unsigned flags = 0, const char* filter_path = 0) FB_NOTHROW; ++ void print_contents(const char* filename, unsigned flags = 0, const char* filter_path = 0) noexcept; + + public: + struct Finalizer +@@ -298,7 +284,7 @@ class MemoryPool + + } // namespace Firebird + +-static inline Firebird::MemoryPool* getDefaultMemoryPool() FB_NOTHROW ++static inline Firebird::MemoryPool* getDefaultMemoryPool() noexcept + { + fb_assert(Firebird::MemoryPool::defaultMemoryManager); + return Firebird::MemoryPool::defaultMemoryManager; +@@ -355,36 +341,36 @@ class SubsystemContextPoolHolder : public ContextPoolHolder + using Firebird::MemoryPool; + + // operators new and delete +-extern void* operator new(size_t s ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION); +-extern void* operator new[](size_t s ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION); +-extern void operator delete(void* mem ALLOC_PARAMS) FB_NOTHROW; +-extern void operator delete[](void* mem ALLOC_PARAMS) FB_NOTHROW; ++extern void* operator new(size_t s ALLOC_PARAMS); ++extern void* operator new[](size_t s ALLOC_PARAMS); ++extern void operator delete(void* mem ALLOC_PARAMS) noexcept; ++extern void operator delete[](void* mem ALLOC_PARAMS) noexcept; + + +-inline void* operator new(size_t s, Firebird::MemoryPool& pool ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) ++inline void* operator new(size_t s, Firebird::MemoryPool& pool ALLOC_PARAMS) + { + return pool.allocate(s ALLOC_PASS_ARGS); + } +-inline void* operator new[](size_t s, Firebird::MemoryPool& pool ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) ++inline void* operator new[](size_t s, Firebird::MemoryPool& pool ALLOC_PARAMS) + { + return pool.allocate(s ALLOC_PASS_ARGS); + } + +-inline void operator delete(void* mem, Firebird::MemoryPool& pool ALLOC_PARAMS) FB_NOTHROW ++inline void operator delete(void* mem, Firebird::MemoryPool& pool ALLOC_PARAMS) noexcept + { + MemoryPool::globalFree(mem); + } +-inline void operator delete[](void* mem, Firebird::MemoryPool& pool ALLOC_PARAMS) FB_NOTHROW ++inline void operator delete[](void* mem, Firebird::MemoryPool& pool ALLOC_PARAMS) noexcept + { + MemoryPool::globalFree(mem); + } + + #if __cplusplus >= 201402L +-inline void operator delete(void* mem, std::size_t s ALLOC_PARAMS) FB_NOTHROW ++inline void operator delete(void* mem, std::size_t s ALLOC_PARAMS) noexcept + { + MemoryPool::globalFree(mem); + } +-inline void operator delete[](void* mem, std::size_t s ALLOC_PARAMS) FB_NOTHROW ++inline void operator delete[](void* mem, std::size_t s ALLOC_PARAMS) noexcept + { + MemoryPool::globalFree(mem); + } +@@ -392,8 +378,8 @@ inline void operator delete[](void* mem, std::size_t s ALLOC_PARAMS) FB_NOTHROW + + #ifdef DEBUG_GDS_ALLOC + +-extern void operator delete(void* mem) FB_NOTHROW; +-extern void operator delete[](void* mem) FB_NOTHROW; ++extern void operator delete(void* mem) noexcept; ++extern void operator delete[](void* mem) noexcept; + + #endif // DEBUG_GDS_ALLOC + diff --git a/obsolete-syslogd.target.patch b/obsolete-syslogd.target.patch deleted file mode 100644 index a08276c..0000000 --- a/obsolete-syslogd.target.patch +++ /dev/null @@ -1,14 +0,0 @@ -Description: remove reference to obsolete syslog.target - Syslog is socket-activated, so no need to declare a dependency on it -Author: Damyan Ivanov - ---- a/builds/install/arch-specific/linux/firebird-superserver.service.in -+++ b/builds/install/arch-specific/linux/firebird-superserver.service.in -@@ -1,6 +1,6 @@ - [Unit] - Description=Firebird Database Server ( SuperServer ) --After=syslog.target network.target -+After=network.target - Conflicts=firebird-classic.socket - - [Service] diff --git a/sources b/sources index 0d3873e..b4b3596 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (Firebird-3.0.7.33374-0.tar.bz2) = ee89cda6d9ace16419515689ed245fbd1bb0e2464bd2d50637e0f474a6aca2e5b86e874ce8bd9714431705a93c038d46de6be1806f0c37d236880a855e725943 +SHA512 (Firebird-4.0.0.2496-0.tar.xz) = 110f1e9b245631ba04fb1f3f3fe16209e432157615c5c23046a277f3e6a164a2142c6732e793d9cc6650d65239a0da8bf37a74329134bd006b7d2cb070812bd6 From 4ff4f3d5ace40351f1bb6dc57432ba448d2844ac Mon Sep 17 00:00:00 2001 From: Philippe Makowski Date: Tue, 8 Jun 2021 12:55:07 +0200 Subject: [PATCH 23/51] Firebird 4 have build issues under s390x --- firebird.spec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/firebird.spec b/firebird.spec index c05f6a6..9047431 100644 --- a/firebird.spec +++ b/firebird.spec @@ -32,6 +32,8 @@ Patch205: cloop-honour-build-flags.patch # from upstream Patch301: c++17.patch Patch302: noexcept.patch +# Firebird 4 have build issues (bz 1969393) +ExcludeArch: s390x BuildRequires: autoconf BuildRequires: automake From bc1d9a8a8ccc9a37e21468531b7682fece54cf8d Mon Sep 17 00:00:00 2001 From: Philippe Makowski Date: Fri, 11 Jun 2021 15:27:57 +0200 Subject: [PATCH 24/51] use variable fro rundir --- firebird.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firebird.spec b/firebird.spec index 9047431..40c2d17 100644 --- a/firebird.spec +++ b/firebird.spec @@ -219,7 +219,7 @@ NOCONFIGURE=1 ./autogen.sh --with-fbsecure-db=%{_localstatedir}/lib/%{name}/secdb \ --with-fbmsg=%{_localstatedir}/lib/%{name}/system \ --with-fblog=%{_localstatedir}/log/%{name} \ - --with-fbglock=/run/%{name} \ + --with-fbglock=%{_rundir}/%{name} \ --with-fbplugins=%{_libdir}/%{name}/plugins \ --with-fbtzdata=%{_localstatedir}/lib/%{name}/tzdata From 2bad4e256bec74302c37286038785ff95ed19772 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Wed, 21 Jul 2021 22:58:58 +0000 Subject: [PATCH 25/51] - Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild Signed-off-by: Fedora Release Engineering --- firebird.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/firebird.spec b/firebird.spec index 40c2d17..f0a5d46 100644 --- a/firebird.spec +++ b/firebird.spec @@ -10,7 +10,7 @@ Name: firebird Version: %{upversion} -Release: 1%{?dist} +Release: 2%{?dist} Summary: SQL relational database management system License: Interbase @@ -371,6 +371,9 @@ fi %changelog +* Wed Jul 21 2021 Fedora Release Engineering - 4.0.0.2496-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild + * Tue Jun 08 2021 Philippe Makowski - 4.0.0.2496-1 - Update to 4.0.0 (#1963311) From 2cf663a2c7e7c76d5041bd5f07e20c584cbeb181 Mon Sep 17 00:00:00 2001 From: Philippe Makowski Date: Fri, 20 Aug 2021 10:14:08 +0200 Subject: [PATCH 26/51] Fix build on s390x (#1969393) --- firebird.spec | 17 +- fix_build_on_big_endian_platforms.patch | 36 + ttmath-abseil.4.0.0.patch | 21255 ++++++++++++++++++++++ 3 files changed, 21305 insertions(+), 3 deletions(-) create mode 100644 fix_build_on_big_endian_platforms.patch create mode 100644 ttmath-abseil.4.0.0.patch diff --git a/firebird.spec b/firebird.spec index f0a5d46..3d841aa 100644 --- a/firebird.spec +++ b/firebird.spec @@ -10,7 +10,7 @@ Name: firebird Version: %{upversion} -Release: 2%{?dist} +Release: 3%{?dist} Summary: SQL relational database management system License: Interbase @@ -32,8 +32,8 @@ Patch205: cloop-honour-build-flags.patch # from upstream Patch301: c++17.patch Patch302: noexcept.patch -# Firebird 4 have build issues (bz 1969393) -ExcludeArch: s390x +Patch303: fix_build_on_big_endian_platforms.patch +Patch304: ttmath-abseil.4.0.0.patch BuildRequires: autoconf BuildRequires: automake @@ -200,8 +200,16 @@ in production systems, under a variety of names, since 1981. %patch205 -p1 %patch301 -p1 %patch302 -p1 +%ifarch s390x +%patch303 -p1 +%patch304 -p1 +%endif + %build +%ifarch s390x +%global _lto_cflags %{nil} +%endif export CFLAGS="%{optflags} -fno-strict-aliasing" export CXXFLAGS="${CFLAGS} -fno-delete-null-pointer-checks" NOCONFIGURE=1 ./autogen.sh @@ -371,6 +379,9 @@ fi %changelog +* Fri Aug 20 2021 Philippe Makowski - 4.0.0.2496-3 +- Fix build on s390x (#1969393) + * Wed Jul 21 2021 Fedora Release Engineering - 4.0.0.2496-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild diff --git a/fix_build_on_big_endian_platforms.patch b/fix_build_on_big_endian_platforms.patch new file mode 100644 index 0000000..73be27b --- /dev/null +++ b/fix_build_on_big_endian_platforms.patch @@ -0,0 +1,36 @@ +From cd0682bc55eb01d53278d09edc1e9e2e9bfb9983 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Dan=20Hor=C3=A1k?= +Date: Fri, 11 Jun 2021 12:39:31 +0200 +Subject: [PATCH] fix build on big endian platforms (#6852) + +* fix missing declaration of type_alignments[] for big endian platforms +* add missing definition of lwp for big endian platforms +--- + src/jrd/sort.cpp | 1 + + src/jrd/sort.h | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/src/jrd/sort.cpp b/src/jrd/sort.cpp +index 37f5f816407..77ca69c2536 100644 +--- a/src/jrd/sort.cpp ++++ b/src/jrd/sort.cpp +@@ -713,6 +713,7 @@ void Sort::diddleKey(UCHAR* record, bool direction, bool duplicateHandling) + for (sort_key_def* key = m_description.begin(), *end = m_description.end(); key < end; key++) + { + UCHAR* p = record + key->getSkdOffset(); ++ SORTP* lwp = (SORTP*) p; + USHORT n = key->getSkdLength(); + USHORT complement = key->skd_flags & SKD_descending; + +diff --git a/src/jrd/sort.h b/src/jrd/sort.h +index 8e23e70ccc5..e3bbbb7779c 100644 +--- a/src/jrd/sort.h ++++ b/src/jrd/sort.h +@@ -27,6 +27,7 @@ + #include "../include/fb_blk.h" + #include "../common/DecFloat.h" + #include "../jrd/TempSpace.h" ++#include "../jrd/align.h" + + namespace Jrd { + diff --git a/ttmath-abseil.4.0.0.patch b/ttmath-abseil.4.0.0.patch new file mode 100644 index 0000000..ee98e95 --- /dev/null +++ b/ttmath-abseil.4.0.0.patch @@ -0,0 +1,21255 @@ +diff --git a/builds/posix/Makefile.in b/builds/posix/Makefile.in +index bb4ceb12fb..dcd2b173ae 100644 +--- a/builds/posix/Makefile.in ++++ b/builds/posix/Makefile.in +@@ -170,6 +170,9 @@ external: + $(MAKE) -C $(ROOT)/extern/decNumber + ln -sf $(ROOT)/extern/decNumber/libdecFloat.a $(LIB) + ++ $(MAKE) -C $(ROOT)/extern/int128/absl/numeric ++ ln -sf $(ROOT)/extern/int128/absl/numeric/libi128.a $(LIB) ++ + CXXFLAGS="-O3 -g -fPIC" $(MAKE) -C $(ROOT)/extern/re2 + ln -sf $(ROOT)/extern/re2/obj/libre2.a $(LIB) + +@@ -328,6 +331,8 @@ cross2: + $(MAKE) re2 + $(MAKE) -C $(ROOT)/extern/decNumber + ln -sf $(ROOT)/extern/decNumber/libdecFloat$(CROSS).a $(LIB) ++ $(MAKE) -C $(ROOT)/extern/int128/absl/numeric ++ ln -sf $(ROOT)/extern/int128/absl/numeric/libi128$(CROSS).a $(LIB) + $(MAKE) yvalve + $(MAKE) engine + $(MAKE) fbintl +@@ -738,12 +743,12 @@ install install-embedded silent_install package packages dist: + # + .PHONY: clean clean_objects clean_dependancies clean_extern_objects clean_build \ + clean_gpre_gen clean_icu clean_dbs clean_examples clean_makefiles \ +- clean_editline clean_all clean_decfloat clean_vers clean_misc ++ clean_editline clean_all clean_decfloat clean_int128 clean_vers clean_misc + + + clean: clean_objects clean_dependancies clean_extern_objects clean_build \ + clean_yacc_gen clean_gpre_gen clean_dbs clean_examples clean_tommath \ +- clean_tomcrypt clean_decfloat clean_vers clean_misc ++ clean_tomcrypt clean_decfloat clean_int128 clean_vers clean_misc + + clean_vers: + $(RM) *.vers +@@ -797,6 +802,9 @@ clean_tomcrypt: + clean_decfloat: + -$(MAKE) -C $(ROOT)/extern/decNumber clean + ++clean_int128: ++ -$(MAKE) -C $(ROOT)/extern/int128/absl/numeric clean ++ + clean_objects: + $(RM) `find $(TMP_ROOT)/ -type f -name '*.o' -print` + $(RM) `find $(TMP_ROOT)/ -type f -name '*.a' -print` +diff --git a/builds/posix/make.android.arm64 b/builds/posix/make.android.arm64 +index 79fbb90c2e..ff0d8d85ff 100644 +--- a/builds/posix/make.android.arm64 ++++ b/builds/posix/make.android.arm64 +@@ -41,7 +41,7 @@ DEV_FLAGS=$(COMMON_FLAGS) $(WARN_FLAGS) + CROSS_CONFIG=android.arm64 + + LDFLAGS += --sysroot=$(CROSS_SYSROOT) -static-libstdc++ +-DroidLibs := -lm -ldl $(DECLIB) $(RE2LIB) ++DroidLibs := -lm -ldl $(DECLIB) $(RE2LIB) $(I128LIB) + + LINK_LIBS = $(DroidLibs) + STATICLINK_LIBS = $(DroidLibs) +diff --git a/builds/posix/make.android.arme b/builds/posix/make.android.arme +index c7233d0191..b6ae33587d 100644 +--- a/builds/posix/make.android.arme ++++ b/builds/posix/make.android.arme +@@ -40,7 +40,7 @@ DEV_FLAGS=$(COMMON_FLAGS) $(WARN_FLAGS) + CROSS_CONFIG=android.arme + + LDFLAGS += --sysroot=$(CROSS_PLATFORM) -static-libstdc++ +-DroidLibs := -lm -ldl $(DECLIB) $(RE2LIB) ++DroidLibs := -lm -ldl $(DECLIB) $(RE2LIB) $(I128LIB) + UDR_SUPPORT_LIBS := + + LINK_LIBS = $(DroidLibs) +diff --git a/builds/posix/make.defaults b/builds/posix/make.defaults +index 6dfd3ab118..9421947a59 100755 +--- a/builds/posix/make.defaults ++++ b/builds/posix/make.defaults +@@ -134,6 +134,7 @@ CAS_OPTIONS=@CAS_OPTIONS@ + # multiple-precision integer library + MATHLIB=@MATHLIB@ + DECLIB=-ldecFloat$(CROSS) ++I128LIB=-li128$(CROSS) + RE2LIB=-lre2 + + # crypt library +@@ -190,8 +191,8 @@ endif + STATICLIB_LINK = $(AR) crus + STATICEXE_LINK = $(CXX) $(GLOB_OPTIONS) $(CXXFLAGS) -static-libstdc++ + +-LINK_LIBS = @LIBS@ $(DECLIB) $(RE2LIB) +-SO_LINK_LIBS = @LIBS@ $(DECLIB) $(RE2LIB) ++LINK_LIBS = @LIBS@ $(DECLIB) $(RE2LIB) $(I128LIB) ++SO_LINK_LIBS = @LIBS@ $(DECLIB) $(RE2LIB) $(I128LIB) + + # Default extensions + +diff --git a/builds/posix/make.rules b/builds/posix/make.rules +index 3afd891141..e725b93067 100644 +--- a/builds/posix/make.rules ++++ b/builds/posix/make.rules +@@ -32,7 +32,7 @@ + + + # Please don't use compiler/platform specific flags here - nmcc 02-Nov-2002 +-WFLAGS =-I$(SRC_ROOT)/include/gen -I$(SRC_ROOT)/include -I$(ROOT)/extern/re2 $(CPPFLAGS) $(LTCSOURCE) ++WFLAGS =-I$(SRC_ROOT)/include/gen -I$(SRC_ROOT)/include -I$(ROOT)/extern/re2 -I$(ROOT)/extern/int128 $(CPPFLAGS) $(LTCSOURCE) + + ifeq ($(TOMMATH_BUILD_FLG),Y) + WFLAGS += -I$(TOMMATH_INC) +diff --git a/builds/posix/prefix.linux_s390x b/builds/posix/prefix.linux_s390x +index ccb2340123..cb0992bb41 100644 +--- a/builds/posix/prefix.linux_s390x ++++ b/builds/posix/prefix.linux_s390x +@@ -18,10 +18,10 @@ + # + # 2 Oct 2002, Nickolay Samofatov - Major cleanup + +-COMMON_FLAGS=-ggdb -DFB_SEND_FLAGS=MSG_NOSIGNAL -DLINUX -pipe -MMD -fPIC -fmessage-length=0 -fsigned-char ++COMMON_FLAGS=-ggdb -DFB_SEND_FLAGS=MSG_NOSIGNAL -DLINUX -pipe -MMD -fPIC -fmessage-length=0 -fsigned-char -Wno-invalid-offsetof + OPTIMIZE_FLAGS=-O3 -fno-omit-frame-pointer -fno-builtin + WARN_FLAGS=-Wall -Wno-switch -Wno-parentheses -Wno-unknown-pragmas -Wno-unused-variable -Wno-non-virtual-dtor + + PROD_FLAGS=$(COMMON_FLAGS) $(OPTIMIZE_FLAGS) +-DEV_FLAGS=-DUSE_VALGRIND -p $(COMMON_FLAGS) $(WARN_FLAGS) +-#DEV_FLAGS=-p $(COMMON_FLAGS) $(WARN_FLAGS) ++#DEV_FLAGS=-DUSE_VALGRIND -p $(COMMON_FLAGS) $(WARN_FLAGS) ++DEV_FLAGS=-p $(COMMON_FLAGS) $(WARN_FLAGS) +diff --git a/extern/int128/absl/base/attributes.h b/extern/int128/absl/base/attributes.h +new file mode 100644 +index 0000000000..52139556f2 +--- /dev/null ++++ b/extern/int128/absl/base/attributes.h +@@ -0,0 +1,721 @@ ++// Copyright 2017 The Abseil Authors. ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// https://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++// ++// This header file defines macros for declaring attributes for functions, ++// types, and variables. ++// ++// These macros are used within Abseil and allow the compiler to optimize, where ++// applicable, certain function calls. ++// ++// Most macros here are exposing GCC or Clang features, and are stubbed out for ++// other compilers. ++// ++// GCC attributes documentation: ++// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html ++// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Variable-Attributes.html ++// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Type-Attributes.html ++// ++// Most attributes in this file are already supported by GCC 4.7. However, some ++// of them are not supported in older version of Clang. Thus, we check ++// `__has_attribute()` first. If the check fails, we check if we are on GCC and ++// assume the attribute exists on GCC (which is verified on GCC 4.7). ++ ++#ifndef ABSL_BASE_ATTRIBUTES_H_ ++#define ABSL_BASE_ATTRIBUTES_H_ ++ ++#include "absl/base/config.h" ++ ++// ABSL_HAVE_ATTRIBUTE ++// ++// A function-like feature checking macro that is a wrapper around ++// `__has_attribute`, which is defined by GCC 5+ and Clang and evaluates to a ++// nonzero constant integer if the attribute is supported or 0 if not. ++// ++// It evaluates to zero if `__has_attribute` is not defined by the compiler. ++// ++// GCC: https://gcc.gnu.org/gcc-5/changes.html ++// Clang: https://clang.llvm.org/docs/LanguageExtensions.html ++#ifdef __has_attribute ++#define ABSL_HAVE_ATTRIBUTE(x) __has_attribute(x) ++#else ++#define ABSL_HAVE_ATTRIBUTE(x) 0 ++#endif ++ ++// ABSL_HAVE_CPP_ATTRIBUTE ++// ++// A function-like feature checking macro that accepts C++11 style attributes. ++// It's a wrapper around `__has_cpp_attribute`, defined by ISO C++ SD-6 ++// (https://en.cppreference.com/w/cpp/experimental/feature_test). If we don't ++// find `__has_cpp_attribute`, will evaluate to 0. ++#if defined(__cplusplus) && defined(__has_cpp_attribute) ++// NOTE: requiring __cplusplus above should not be necessary, but ++// works around https://bugs.llvm.org/show_bug.cgi?id=23435. ++#define ABSL_HAVE_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) ++#else ++#define ABSL_HAVE_CPP_ATTRIBUTE(x) 0 ++#endif ++ ++// ----------------------------------------------------------------------------- ++// Function Attributes ++// ----------------------------------------------------------------------------- ++// ++// GCC: https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html ++// Clang: https://clang.llvm.org/docs/AttributeReference.html ++ ++// ABSL_PRINTF_ATTRIBUTE ++// ABSL_SCANF_ATTRIBUTE ++// ++// Tells the compiler to perform `printf` format string checking if the ++// compiler supports it; see the 'format' attribute in ++// . ++// ++// Note: As the GCC manual states, "[s]ince non-static C++ methods ++// have an implicit 'this' argument, the arguments of such methods ++// should be counted from two, not one." ++#if ABSL_HAVE_ATTRIBUTE(format) || (defined(__GNUC__) && !defined(__clang__)) ++#define ABSL_PRINTF_ATTRIBUTE(string_index, first_to_check) \ ++ __attribute__((__format__(__printf__, string_index, first_to_check))) ++#define ABSL_SCANF_ATTRIBUTE(string_index, first_to_check) \ ++ __attribute__((__format__(__scanf__, string_index, first_to_check))) ++#else ++#define ABSL_PRINTF_ATTRIBUTE(string_index, first_to_check) ++#define ABSL_SCANF_ATTRIBUTE(string_index, first_to_check) ++#endif ++ ++// ABSL_ATTRIBUTE_ALWAYS_INLINE ++// ABSL_ATTRIBUTE_NOINLINE ++// ++// Forces functions to either inline or not inline. Introduced in gcc 3.1. ++#if ABSL_HAVE_ATTRIBUTE(always_inline) || \ ++ (defined(__GNUC__) && !defined(__clang__)) ++#define ABSL_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline)) ++#define ABSL_HAVE_ATTRIBUTE_ALWAYS_INLINE 1 ++#else ++#define ABSL_ATTRIBUTE_ALWAYS_INLINE ++#endif ++ ++#if ABSL_HAVE_ATTRIBUTE(noinline) || (defined(__GNUC__) && !defined(__clang__)) ++#define ABSL_ATTRIBUTE_NOINLINE __attribute__((noinline)) ++#define ABSL_HAVE_ATTRIBUTE_NOINLINE 1 ++#else ++#define ABSL_ATTRIBUTE_NOINLINE ++#endif ++ ++// ABSL_ATTRIBUTE_NO_TAIL_CALL ++// ++// Prevents the compiler from optimizing away stack frames for functions which ++// end in a call to another function. ++#if ABSL_HAVE_ATTRIBUTE(disable_tail_calls) ++#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1 ++#define ABSL_ATTRIBUTE_NO_TAIL_CALL __attribute__((disable_tail_calls)) ++#elif defined(__GNUC__) && !defined(__clang__) && !defined(__e2k__) ++#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1 ++#define ABSL_ATTRIBUTE_NO_TAIL_CALL \ ++ __attribute__((optimize("no-optimize-sibling-calls"))) ++#else ++#define ABSL_ATTRIBUTE_NO_TAIL_CALL ++#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 0 ++#endif ++ ++// ABSL_ATTRIBUTE_WEAK ++// ++// Tags a function as weak for the purposes of compilation and linking. ++// Weak attributes did not work properly in LLVM's Windows backend before ++// 9.0.0, so disable them there. See https://bugs.llvm.org/show_bug.cgi?id=37598 ++// for further information. ++// The MinGW compiler doesn't complain about the weak attribute until the link ++// step, presumably because Windows doesn't use ELF binaries. ++#if (ABSL_HAVE_ATTRIBUTE(weak) || \ ++ (defined(__GNUC__) && !defined(__clang__))) && \ ++ (!defined(_WIN32) || __clang_major__ < 9) && !defined(__MINGW32__) ++#undef ABSL_ATTRIBUTE_WEAK ++#define ABSL_ATTRIBUTE_WEAK __attribute__((weak)) ++#define ABSL_HAVE_ATTRIBUTE_WEAK 1 ++#else ++#define ABSL_ATTRIBUTE_WEAK ++#define ABSL_HAVE_ATTRIBUTE_WEAK 0 ++#endif ++ ++// ABSL_ATTRIBUTE_NONNULL ++// ++// Tells the compiler either (a) that a particular function parameter ++// should be a non-null pointer, or (b) that all pointer arguments should ++// be non-null. ++// ++// Note: As the GCC manual states, "[s]ince non-static C++ methods ++// have an implicit 'this' argument, the arguments of such methods ++// should be counted from two, not one." ++// ++// Args are indexed starting at 1. ++// ++// For non-static class member functions, the implicit `this` argument ++// is arg 1, and the first explicit argument is arg 2. For static class member ++// functions, there is no implicit `this`, and the first explicit argument is ++// arg 1. ++// ++// Example: ++// ++// /* arg_a cannot be null, but arg_b can */ ++// void Function(void* arg_a, void* arg_b) ABSL_ATTRIBUTE_NONNULL(1); ++// ++// class C { ++// /* arg_a cannot be null, but arg_b can */ ++// void Method(void* arg_a, void* arg_b) ABSL_ATTRIBUTE_NONNULL(2); ++// ++// /* arg_a cannot be null, but arg_b can */ ++// static void StaticMethod(void* arg_a, void* arg_b) ++// ABSL_ATTRIBUTE_NONNULL(1); ++// }; ++// ++// If no arguments are provided, then all pointer arguments should be non-null. ++// ++// /* No pointer arguments may be null. */ ++// void Function(void* arg_a, void* arg_b, int arg_c) ABSL_ATTRIBUTE_NONNULL(); ++// ++// NOTE: The GCC nonnull attribute actually accepts a list of arguments, but ++// ABSL_ATTRIBUTE_NONNULL does not. ++#if ABSL_HAVE_ATTRIBUTE(nonnull) || (defined(__GNUC__) && !defined(__clang__)) ++#define ABSL_ATTRIBUTE_NONNULL(arg_index) __attribute__((nonnull(arg_index))) ++#else ++#define ABSL_ATTRIBUTE_NONNULL(...) ++#endif ++ ++// ABSL_ATTRIBUTE_NORETURN ++// ++// Tells the compiler that a given function never returns. ++#if ABSL_HAVE_ATTRIBUTE(noreturn) || (defined(__GNUC__) && !defined(__clang__)) ++#define ABSL_ATTRIBUTE_NORETURN __attribute__((noreturn)) ++#elif defined(_MSC_VER) ++#define ABSL_ATTRIBUTE_NORETURN __declspec(noreturn) ++#else ++#define ABSL_ATTRIBUTE_NORETURN ++#endif ++ ++// ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS ++// ++// Tells the AddressSanitizer (or other memory testing tools) to ignore a given ++// function. Useful for cases when a function reads random locations on stack, ++// calls _exit from a cloned subprocess, deliberately accesses buffer ++// out of bounds or does other scary things with memory. ++// NOTE: GCC supports AddressSanitizer(asan) since 4.8. ++// https://gcc.gnu.org/gcc-4.8/changes.html ++#if ABSL_HAVE_ATTRIBUTE(no_sanitize_address) ++#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) ++#else ++#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS ++#endif ++ ++// ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY ++// ++// Tells the MemorySanitizer to relax the handling of a given function. All "Use ++// of uninitialized value" warnings from such functions will be suppressed, and ++// all values loaded from memory will be considered fully initialized. This ++// attribute is similar to the ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS attribute ++// above, but deals with initialized-ness rather than addressability issues. ++// NOTE: MemorySanitizer(msan) is supported by Clang but not GCC. ++#if ABSL_HAVE_ATTRIBUTE(no_sanitize_memory) ++#define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory)) ++#else ++#define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY ++#endif ++ ++// ABSL_ATTRIBUTE_NO_SANITIZE_THREAD ++// ++// Tells the ThreadSanitizer to not instrument a given function. ++// NOTE: GCC supports ThreadSanitizer(tsan) since 4.8. ++// https://gcc.gnu.org/gcc-4.8/changes.html ++#if ABSL_HAVE_ATTRIBUTE(no_sanitize_thread) ++#define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread)) ++#else ++#define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD ++#endif ++ ++// ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED ++// ++// Tells the UndefinedSanitizer to ignore a given function. Useful for cases ++// where certain behavior (eg. division by zero) is being used intentionally. ++// NOTE: GCC supports UndefinedBehaviorSanitizer(ubsan) since 4.9. ++// https://gcc.gnu.org/gcc-4.9/changes.html ++#if ABSL_HAVE_ATTRIBUTE(no_sanitize_undefined) ++#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \ ++ __attribute__((no_sanitize_undefined)) ++#elif ABSL_HAVE_ATTRIBUTE(no_sanitize) ++#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \ ++ __attribute__((no_sanitize("undefined"))) ++#else ++#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED ++#endif ++ ++// ABSL_ATTRIBUTE_NO_SANITIZE_CFI ++// ++// Tells the ControlFlowIntegrity sanitizer to not instrument a given function. ++// See https://clang.llvm.org/docs/ControlFlowIntegrity.html for details. ++#if ABSL_HAVE_ATTRIBUTE(no_sanitize) ++#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI __attribute__((no_sanitize("cfi"))) ++#else ++#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI ++#endif ++ ++// ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK ++// ++// Tells the SafeStack to not instrument a given function. ++// See https://clang.llvm.org/docs/SafeStack.html for details. ++#if ABSL_HAVE_ATTRIBUTE(no_sanitize) ++#define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK \ ++ __attribute__((no_sanitize("safe-stack"))) ++#else ++#define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK ++#endif ++ ++// ABSL_ATTRIBUTE_RETURNS_NONNULL ++// ++// Tells the compiler that a particular function never returns a null pointer. ++#if ABSL_HAVE_ATTRIBUTE(returns_nonnull) ++#define ABSL_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull)) ++#else ++#define ABSL_ATTRIBUTE_RETURNS_NONNULL ++#endif ++ ++// ABSL_HAVE_ATTRIBUTE_SECTION ++// ++// Indicates whether labeled sections are supported. Weak symbol support is ++// a prerequisite. Labeled sections are not supported on Darwin/iOS. ++#ifdef ABSL_HAVE_ATTRIBUTE_SECTION ++#error ABSL_HAVE_ATTRIBUTE_SECTION cannot be directly set ++#elif (ABSL_HAVE_ATTRIBUTE(section) || \ ++ (defined(__GNUC__) && !defined(__clang__))) && \ ++ !defined(__APPLE__) && ABSL_HAVE_ATTRIBUTE_WEAK ++#define ABSL_HAVE_ATTRIBUTE_SECTION 1 ++ ++// ABSL_ATTRIBUTE_SECTION ++// ++// Tells the compiler/linker to put a given function into a section and define ++// `__start_ ## name` and `__stop_ ## name` symbols to bracket the section. ++// This functionality is supported by GNU linker. Any function annotated with ++// `ABSL_ATTRIBUTE_SECTION` must not be inlined, or it will be placed into ++// whatever section its caller is placed into. ++// ++#ifndef ABSL_ATTRIBUTE_SECTION ++#define ABSL_ATTRIBUTE_SECTION(name) \ ++ __attribute__((section(#name))) __attribute__((noinline)) ++#endif ++ ++ ++// ABSL_ATTRIBUTE_SECTION_VARIABLE ++// ++// Tells the compiler/linker to put a given variable into a section and define ++// `__start_ ## name` and `__stop_ ## name` symbols to bracket the section. ++// This functionality is supported by GNU linker. ++#ifndef ABSL_ATTRIBUTE_SECTION_VARIABLE ++#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) __attribute__((section(#name))) ++#endif ++ ++// ABSL_DECLARE_ATTRIBUTE_SECTION_VARS ++// ++// A weak section declaration to be used as a global declaration ++// for ABSL_ATTRIBUTE_SECTION_START|STOP(name) to compile and link ++// even without functions with ABSL_ATTRIBUTE_SECTION(name). ++// ABSL_DEFINE_ATTRIBUTE_SECTION should be in the exactly one file; it's ++// a no-op on ELF but not on Mach-O. ++// ++#ifndef ABSL_DECLARE_ATTRIBUTE_SECTION_VARS ++#define ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) \ ++ extern char __start_##name[] ABSL_ATTRIBUTE_WEAK; \ ++ extern char __stop_##name[] ABSL_ATTRIBUTE_WEAK ++#endif ++#ifndef ABSL_DEFINE_ATTRIBUTE_SECTION_VARS ++#define ABSL_INIT_ATTRIBUTE_SECTION_VARS(name) ++#define ABSL_DEFINE_ATTRIBUTE_SECTION_VARS(name) ++#endif ++ ++// ABSL_ATTRIBUTE_SECTION_START ++// ++// Returns `void*` pointers to start/end of a section of code with ++// functions having ABSL_ATTRIBUTE_SECTION(name). ++// Returns 0 if no such functions exist. ++// One must ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) for this to compile and ++// link. ++// ++#define ABSL_ATTRIBUTE_SECTION_START(name) \ ++ (reinterpret_cast(__start_##name)) ++#define ABSL_ATTRIBUTE_SECTION_STOP(name) \ ++ (reinterpret_cast(__stop_##name)) ++ ++#else // !ABSL_HAVE_ATTRIBUTE_SECTION ++ ++#define ABSL_HAVE_ATTRIBUTE_SECTION 0 ++ ++// provide dummy definitions ++#define ABSL_ATTRIBUTE_SECTION(name) ++#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) ++#define ABSL_INIT_ATTRIBUTE_SECTION_VARS(name) ++#define ABSL_DEFINE_ATTRIBUTE_SECTION_VARS(name) ++#define ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) ++#define ABSL_ATTRIBUTE_SECTION_START(name) (reinterpret_cast(0)) ++#define ABSL_ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast(0)) ++ ++#endif // ABSL_ATTRIBUTE_SECTION ++ ++// ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC ++// ++// Support for aligning the stack on 32-bit x86. ++#if ABSL_HAVE_ATTRIBUTE(force_align_arg_pointer) || \ ++ (defined(__GNUC__) && !defined(__clang__)) ++#if defined(__i386__) ++#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC \ ++ __attribute__((force_align_arg_pointer)) ++#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) ++#elif defined(__x86_64__) ++#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (1) ++#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC ++#else // !__i386__ && !__x86_64 ++#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) ++#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC ++#endif // __i386__ ++#else ++#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC ++#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) ++#endif ++ ++// ABSL_MUST_USE_RESULT ++// ++// Tells the compiler to warn about unused results. ++// ++// When annotating a function, it must appear as the first part of the ++// declaration or definition. The compiler will warn if the return value from ++// such a function is unused: ++// ++// ABSL_MUST_USE_RESULT Sprocket* AllocateSprocket(); ++// AllocateSprocket(); // Triggers a warning. ++// ++// When annotating a class, it is equivalent to annotating every function which ++// returns an instance. ++// ++// class ABSL_MUST_USE_RESULT Sprocket {}; ++// Sprocket(); // Triggers a warning. ++// ++// Sprocket MakeSprocket(); ++// MakeSprocket(); // Triggers a warning. ++// ++// Note that references and pointers are not instances: ++// ++// Sprocket* SprocketPointer(); ++// SprocketPointer(); // Does *not* trigger a warning. ++// ++// ABSL_MUST_USE_RESULT allows using cast-to-void to suppress the unused result ++// warning. For that, warn_unused_result is used only for clang but not for gcc. ++// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425 ++// ++// Note: past advice was to place the macro after the argument list. ++#if ABSL_HAVE_ATTRIBUTE(nodiscard) ++#define ABSL_MUST_USE_RESULT [[nodiscard]] ++#elif defined(__clang__) && ABSL_HAVE_ATTRIBUTE(warn_unused_result) ++#define ABSL_MUST_USE_RESULT __attribute__((warn_unused_result)) ++#else ++#define ABSL_MUST_USE_RESULT ++#endif ++ ++// ABSL_ATTRIBUTE_HOT, ABSL_ATTRIBUTE_COLD ++// ++// Tells GCC that a function is hot or cold. GCC can use this information to ++// improve static analysis, i.e. a conditional branch to a cold function ++// is likely to be not-taken. ++// This annotation is used for function declarations. ++// ++// Example: ++// ++// int foo() ABSL_ATTRIBUTE_HOT; ++#if ABSL_HAVE_ATTRIBUTE(hot) || (defined(__GNUC__) && !defined(__clang__)) ++#define ABSL_ATTRIBUTE_HOT __attribute__((hot)) ++#else ++#define ABSL_ATTRIBUTE_HOT ++#endif ++ ++#if ABSL_HAVE_ATTRIBUTE(cold) || (defined(__GNUC__) && !defined(__clang__)) ++#define ABSL_ATTRIBUTE_COLD __attribute__((cold)) ++#else ++#define ABSL_ATTRIBUTE_COLD ++#endif ++ ++// ABSL_XRAY_ALWAYS_INSTRUMENT, ABSL_XRAY_NEVER_INSTRUMENT, ABSL_XRAY_LOG_ARGS ++// ++// We define the ABSL_XRAY_ALWAYS_INSTRUMENT and ABSL_XRAY_NEVER_INSTRUMENT ++// macro used as an attribute to mark functions that must always or never be ++// instrumented by XRay. Currently, this is only supported in Clang/LLVM. ++// ++// For reference on the LLVM XRay instrumentation, see ++// http://llvm.org/docs/XRay.html. ++// ++// A function with the XRAY_ALWAYS_INSTRUMENT macro attribute in its declaration ++// will always get the XRay instrumentation sleds. These sleds may introduce ++// some binary size and runtime overhead and must be used sparingly. ++// ++// These attributes only take effect when the following conditions are met: ++// ++// * The file/target is built in at least C++11 mode, with a Clang compiler ++// that supports XRay attributes. ++// * The file/target is built with the -fxray-instrument flag set for the ++// Clang/LLVM compiler. ++// * The function is defined in the translation unit (the compiler honors the ++// attribute in either the definition or the declaration, and must match). ++// ++// There are cases when, even when building with XRay instrumentation, users ++// might want to control specifically which functions are instrumented for a ++// particular build using special-case lists provided to the compiler. These ++// special case lists are provided to Clang via the ++// -fxray-always-instrument=... and -fxray-never-instrument=... flags. The ++// attributes in source take precedence over these special-case lists. ++// ++// To disable the XRay attributes at build-time, users may define ++// ABSL_NO_XRAY_ATTRIBUTES. Do NOT define ABSL_NO_XRAY_ATTRIBUTES on specific ++// packages/targets, as this may lead to conflicting definitions of functions at ++// link-time. ++// ++// XRay isn't currently supported on Android: ++// https://github.com/android/ndk/issues/368 ++#if ABSL_HAVE_CPP_ATTRIBUTE(clang::xray_always_instrument) && \ ++ !defined(ABSL_NO_XRAY_ATTRIBUTES) && !defined(__ANDROID__) ++#define ABSL_XRAY_ALWAYS_INSTRUMENT [[clang::xray_always_instrument]] ++#define ABSL_XRAY_NEVER_INSTRUMENT [[clang::xray_never_instrument]] ++#if ABSL_HAVE_CPP_ATTRIBUTE(clang::xray_log_args) ++#define ABSL_XRAY_LOG_ARGS(N) \ ++ [[clang::xray_always_instrument, clang::xray_log_args(N)]] ++#else ++#define ABSL_XRAY_LOG_ARGS(N) [[clang::xray_always_instrument]] ++#endif ++#else ++#define ABSL_XRAY_ALWAYS_INSTRUMENT ++#define ABSL_XRAY_NEVER_INSTRUMENT ++#define ABSL_XRAY_LOG_ARGS(N) ++#endif ++ ++// ABSL_ATTRIBUTE_REINITIALIZES ++// ++// Indicates that a member function reinitializes the entire object to a known ++// state, independent of the previous state of the object. ++// ++// The clang-tidy check bugprone-use-after-move allows member functions marked ++// with this attribute to be called on objects that have been moved from; ++// without the attribute, this would result in a use-after-move warning. ++#if ABSL_HAVE_CPP_ATTRIBUTE(clang::reinitializes) ++#define ABSL_ATTRIBUTE_REINITIALIZES [[clang::reinitializes]] ++#else ++#define ABSL_ATTRIBUTE_REINITIALIZES ++#endif ++ ++// ----------------------------------------------------------------------------- ++// Variable Attributes ++// ----------------------------------------------------------------------------- ++ ++// ABSL_ATTRIBUTE_UNUSED ++// ++// Prevents the compiler from complaining about variables that appear unused. ++// ++// For code or headers that are assured to only build with C++17 and up, prefer ++// just using the standard '[[maybe_unused]]' directly over this macro. ++// ++// Due to differences in positioning requirements between the old, compiler ++// specific __attribute__ syntax and the now standard [[maybe_unused]], this ++// macro does not attempt to take advantage of '[[maybe_unused]]'. ++#if ABSL_HAVE_ATTRIBUTE(unused) || (defined(__GNUC__) && !defined(__clang__)) ++#undef ABSL_ATTRIBUTE_UNUSED ++#define ABSL_ATTRIBUTE_UNUSED __attribute__((__unused__)) ++#else ++#define ABSL_ATTRIBUTE_UNUSED ++#endif ++ ++// ABSL_ATTRIBUTE_INITIAL_EXEC ++// ++// Tells the compiler to use "initial-exec" mode for a thread-local variable. ++// See http://people.redhat.com/drepper/tls.pdf for the gory details. ++#if ABSL_HAVE_ATTRIBUTE(tls_model) || (defined(__GNUC__) && !defined(__clang__)) ++#define ABSL_ATTRIBUTE_INITIAL_EXEC __attribute__((tls_model("initial-exec"))) ++#else ++#define ABSL_ATTRIBUTE_INITIAL_EXEC ++#endif ++ ++// ABSL_ATTRIBUTE_PACKED ++// ++// Instructs the compiler not to use natural alignment for a tagged data ++// structure, but instead to reduce its alignment to 1. This attribute can ++// either be applied to members of a structure or to a structure in its ++// entirety. Applying this attribute (judiciously) to a structure in its ++// entirety to optimize the memory footprint of very commonly-used structs is ++// fine. Do not apply this attribute to a structure in its entirety if the ++// purpose is to control the offsets of the members in the structure. Instead, ++// apply this attribute only to structure members that need it. ++// ++// When applying ABSL_ATTRIBUTE_PACKED only to specific structure members the ++// natural alignment of structure members not annotated is preserved. Aligned ++// member accesses are faster than non-aligned member accesses even if the ++// targeted microprocessor supports non-aligned accesses. ++#if ABSL_HAVE_ATTRIBUTE(packed) || (defined(__GNUC__) && !defined(__clang__)) ++#define ABSL_ATTRIBUTE_PACKED __attribute__((__packed__)) ++#else ++#define ABSL_ATTRIBUTE_PACKED ++#endif ++ ++// ABSL_ATTRIBUTE_FUNC_ALIGN ++// ++// Tells the compiler to align the function start at least to certain ++// alignment boundary ++#if ABSL_HAVE_ATTRIBUTE(aligned) || (defined(__GNUC__) && !defined(__clang__)) ++#define ABSL_ATTRIBUTE_FUNC_ALIGN(bytes) __attribute__((aligned(bytes))) ++#else ++#define ABSL_ATTRIBUTE_FUNC_ALIGN(bytes) ++#endif ++ ++// ABSL_FALLTHROUGH_INTENDED ++// ++// Annotates implicit fall-through between switch labels, allowing a case to ++// indicate intentional fallthrough and turn off warnings about any lack of a ++// `break` statement. The ABSL_FALLTHROUGH_INTENDED macro should be followed by ++// a semicolon and can be used in most places where `break` can, provided that ++// no statements exist between it and the next switch label. ++// ++// Example: ++// ++// switch (x) { ++// case 40: ++// case 41: ++// if (truth_is_out_there) { ++// ++x; ++// ABSL_FALLTHROUGH_INTENDED; // Use instead of/along with annotations ++// // in comments ++// } else { ++// return x; ++// } ++// case 42: ++// ... ++// ++// Notes: When supported, GCC and Clang can issue a warning on switch labels ++// with unannotated fallthrough using the warning `-Wimplicit-fallthrough`. See ++// clang documentation on language extensions for details: ++// https://clang.llvm.org/docs/AttributeReference.html#fallthrough-clang-fallthrough ++// ++// When used with unsupported compilers, the ABSL_FALLTHROUGH_INTENDED macro has ++// no effect on diagnostics. In any case this macro has no effect on runtime ++// behavior and performance of code. ++ ++#ifdef ABSL_FALLTHROUGH_INTENDED ++#error "ABSL_FALLTHROUGH_INTENDED should not be defined." ++#elif ABSL_HAVE_CPP_ATTRIBUTE(fallthrough) ++#define ABSL_FALLTHROUGH_INTENDED [[fallthrough]] ++#elif ABSL_HAVE_CPP_ATTRIBUTE(clang::fallthrough) ++#define ABSL_FALLTHROUGH_INTENDED [[clang::fallthrough]] ++#elif ABSL_HAVE_CPP_ATTRIBUTE(gnu::fallthrough) ++#define ABSL_FALLTHROUGH_INTENDED [[gnu::fallthrough]] ++#else ++#define ABSL_FALLTHROUGH_INTENDED \ ++ do { \ ++ } while (0) ++#endif ++ ++// ABSL_DEPRECATED() ++// ++// Marks a deprecated class, struct, enum, function, method and variable ++// declarations. The macro argument is used as a custom diagnostic message (e.g. ++// suggestion of a better alternative). ++// ++// Examples: ++// ++// class ABSL_DEPRECATED("Use Bar instead") Foo {...}; ++// ++// ABSL_DEPRECATED("Use Baz() instead") void Bar() {...} ++// ++// template ++// ABSL_DEPRECATED("Use DoThat() instead") ++// void DoThis(); ++// ++// Every usage of a deprecated entity will trigger a warning when compiled with ++// clang's `-Wdeprecated-declarations` option. This option is turned off by ++// default, but the warnings will be reported by clang-tidy. ++#if defined(__clang__) && defined(__cplusplus) && __cplusplus >= 201103L ++#define ABSL_DEPRECATED(message) __attribute__((deprecated(message))) ++#endif ++ ++#ifndef ABSL_DEPRECATED ++#define ABSL_DEPRECATED(message) ++#endif ++ ++// ABSL_CONST_INIT ++// ++// A variable declaration annotated with the `ABSL_CONST_INIT` attribute will ++// not compile (on supported platforms) unless the variable has a constant ++// initializer. This is useful for variables with static and thread storage ++// duration, because it guarantees that they will not suffer from the so-called ++// "static init order fiasco". Prefer to put this attribute on the most visible ++// declaration of the variable, if there's more than one, because code that ++// accesses the variable can then use the attribute for optimization. ++// ++// Example: ++// ++// class MyClass { ++// public: ++// ABSL_CONST_INIT static MyType my_var; ++// }; ++// ++// MyType MyClass::my_var = MakeMyType(...); ++// ++// Note that this attribute is redundant if the variable is declared constexpr. ++#if ABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization) ++#define ABSL_CONST_INIT [[clang::require_constant_initialization]] ++#else ++#define ABSL_CONST_INIT ++#endif // ABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization) ++ ++// ABSL_ATTRIBUTE_PURE_FUNCTION ++// ++// ABSL_ATTRIBUTE_PURE_FUNCTION is used to annotate declarations of "pure" ++// functions. A function is pure if its return value is only a function of its ++// arguments. The pure attribute prohibits a function from modifying the state ++// of the program that is observable by means other than inspecting the ++// function's return value. Declaring such functions with the pure attribute ++// allows the compiler to avoid emitting some calls in repeated invocations of ++// the function with the same argument values. ++// ++// Example: ++// ++// ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Milliseconds(Duration d); ++#if ABSL_HAVE_CPP_ATTRIBUTE(gnu::pure) ++#define ABSL_ATTRIBUTE_PURE_FUNCTION [[gnu::pure]] ++#elif ABSL_HAVE_ATTRIBUTE(pure) ++#define ABSL_ATTRIBUTE_PURE_FUNCTION __attribute__((pure)) ++#else ++#define ABSL_ATTRIBUTE_PURE_FUNCTION ++#endif ++ ++// ABSL_ATTRIBUTE_LIFETIME_BOUND indicates that a resource owned by a function ++// parameter or implicit object parameter is retained by the return value of the ++// annotated function (or, for a parameter of a constructor, in the value of the ++// constructed object). This attribute causes warnings to be produced if a ++// temporary object does not live long enough. ++// ++// When applied to a reference parameter, the referenced object is assumed to be ++// retained by the return value of the function. When applied to a non-reference ++// parameter (for example, a pointer or a class type), all temporaries ++// referenced by the parameter are assumed to be retained by the return value of ++// the function. ++// ++// See also the upstream documentation: ++// https://clang.llvm.org/docs/AttributeReference.html#lifetimebound ++#if ABSL_HAVE_CPP_ATTRIBUTE(clang::lifetimebound) ++#define ABSL_ATTRIBUTE_LIFETIME_BOUND [[clang::lifetimebound]] ++#elif ABSL_HAVE_ATTRIBUTE(lifetimebound) ++#define ABSL_ATTRIBUTE_LIFETIME_BOUND __attribute__((lifetimebound)) ++#else ++#define ABSL_ATTRIBUTE_LIFETIME_BOUND ++#endif ++ ++#endif // ABSL_BASE_ATTRIBUTES_H_ +diff --git a/extern/int128/absl/base/config.h b/extern/int128/absl/base/config.h +new file mode 100644 +index 0000000000..a6e7c86a0c +--- /dev/null ++++ b/extern/int128/absl/base/config.h +@@ -0,0 +1,745 @@ ++// ++// Copyright 2017 The Abseil Authors. ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// https://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++// ++// ----------------------------------------------------------------------------- ++// File: config.h ++// ----------------------------------------------------------------------------- ++// ++// This header file defines a set of macros for checking the presence of ++// important compiler and platform features. Such macros can be used to ++// produce portable code by parameterizing compilation based on the presence or ++// lack of a given feature. ++// ++// We define a "feature" as some interface we wish to program to: for example, ++// a library function or system call. A value of `1` indicates support for ++// that feature; any other value indicates the feature support is undefined. ++// ++// Example: ++// ++// Suppose a programmer wants to write a program that uses the 'mmap()' system ++// call. The Abseil macro for that feature (`ABSL_HAVE_MMAP`) allows you to ++// selectively include the `mmap.h` header and bracket code using that feature ++// in the macro: ++// ++// #include "absl/base/config.h" ++// ++// #ifdef ABSL_HAVE_MMAP ++// #include "sys/mman.h" ++// #endif //ABSL_HAVE_MMAP ++// ++// ... ++// #ifdef ABSL_HAVE_MMAP ++// void *ptr = mmap(...); ++// ... ++// #endif // ABSL_HAVE_MMAP ++ ++#ifndef ABSL_BASE_CONFIG_H_ ++#define ABSL_BASE_CONFIG_H_ ++ ++// Included for the __GLIBC__ macro (or similar macros on other systems). ++#include ++ ++#ifdef __cplusplus ++// Included for __GLIBCXX__, _LIBCPP_VERSION ++#include ++#endif // __cplusplus ++ ++#if defined(__APPLE__) ++// Included for TARGET_OS_IPHONE, __IPHONE_OS_VERSION_MIN_REQUIRED, ++// __IPHONE_8_0. ++#include ++#include ++#endif ++ ++#include "absl/base/options.h" ++#include "absl/base/policy_checks.h" ++ ++// Helper macro to convert a CPP variable to a string literal. ++#define ABSL_INTERNAL_DO_TOKEN_STR(x) #x ++#define ABSL_INTERNAL_TOKEN_STR(x) ABSL_INTERNAL_DO_TOKEN_STR(x) ++ ++// ----------------------------------------------------------------------------- ++// Abseil namespace annotations ++// ----------------------------------------------------------------------------- ++ ++// ABSL_NAMESPACE_BEGIN/ABSL_NAMESPACE_END ++// ++// An annotation placed at the beginning/end of each `namespace absl` scope. ++// This is used to inject an inline namespace. ++// ++// The proper way to write Abseil code in the `absl` namespace is: ++// ++// namespace absl { ++// ABSL_NAMESPACE_BEGIN ++// ++// void Foo(); // absl::Foo(). ++// ++// ABSL_NAMESPACE_END ++// } // namespace absl ++// ++// Users of Abseil should not use these macros, because users of Abseil should ++// not write `namespace absl {` in their own code for any reason. (Abseil does ++// not support forward declarations of its own types, nor does it support ++// user-provided specialization of Abseil templates. Code that violates these ++// rules may be broken without warning.) ++#if !defined(ABSL_OPTION_USE_INLINE_NAMESPACE) || \ ++ !defined(ABSL_OPTION_INLINE_NAMESPACE_NAME) ++#error options.h is misconfigured. ++#endif ++ ++// Check that ABSL_OPTION_INLINE_NAMESPACE_NAME is neither "head" nor "" ++#if defined(__cplusplus) && ABSL_OPTION_USE_INLINE_NAMESPACE == 1 ++ ++#define ABSL_INTERNAL_INLINE_NAMESPACE_STR \ ++ ABSL_INTERNAL_TOKEN_STR(ABSL_OPTION_INLINE_NAMESPACE_NAME) ++ ++static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != '\0', ++ "options.h misconfigured: ABSL_OPTION_INLINE_NAMESPACE_NAME must " ++ "not be empty."); ++static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' || ++ ABSL_INTERNAL_INLINE_NAMESPACE_STR[1] != 'e' || ++ ABSL_INTERNAL_INLINE_NAMESPACE_STR[2] != 'a' || ++ ABSL_INTERNAL_INLINE_NAMESPACE_STR[3] != 'd' || ++ ABSL_INTERNAL_INLINE_NAMESPACE_STR[4] != '\0', ++ "options.h misconfigured: ABSL_OPTION_INLINE_NAMESPACE_NAME must " ++ "be changed to a new, unique identifier name."); ++ ++#endif ++ ++#if ABSL_OPTION_USE_INLINE_NAMESPACE == 0 ++#define ABSL_NAMESPACE_BEGIN ++#define ABSL_NAMESPACE_END ++#define ABSL_INTERNAL_C_SYMBOL(x) x ++#elif ABSL_OPTION_USE_INLINE_NAMESPACE == 1 ++#define ABSL_NAMESPACE_BEGIN \ ++ inline namespace ABSL_OPTION_INLINE_NAMESPACE_NAME { ++#define ABSL_NAMESPACE_END } ++#define ABSL_INTERNAL_C_SYMBOL_HELPER_2(x, v) x##_##v ++#define ABSL_INTERNAL_C_SYMBOL_HELPER_1(x, v) \ ++ ABSL_INTERNAL_C_SYMBOL_HELPER_2(x, v) ++#define ABSL_INTERNAL_C_SYMBOL(x) \ ++ ABSL_INTERNAL_C_SYMBOL_HELPER_1(x, ABSL_OPTION_INLINE_NAMESPACE_NAME) ++#else ++#error options.h is misconfigured. ++#endif ++ ++// ----------------------------------------------------------------------------- ++// Compiler Feature Checks ++// ----------------------------------------------------------------------------- ++ ++// ABSL_HAVE_BUILTIN() ++// ++// Checks whether the compiler supports a Clang Feature Checking Macro, and if ++// so, checks whether it supports the provided builtin function "x" where x ++// is one of the functions noted in ++// https://clang.llvm.org/docs/LanguageExtensions.html ++// ++// Note: Use this macro to avoid an extra level of #ifdef __has_builtin check. ++// http://releases.llvm.org/3.3/tools/clang/docs/LanguageExtensions.html ++#ifdef __has_builtin ++#define ABSL_HAVE_BUILTIN(x) __has_builtin(x) ++#else ++#define ABSL_HAVE_BUILTIN(x) 0 ++#endif ++ ++#if defined(__is_identifier) ++#define ABSL_INTERNAL_HAS_KEYWORD(x) !(__is_identifier(x)) ++#else ++#define ABSL_INTERNAL_HAS_KEYWORD(x) 0 ++#endif ++ ++#ifdef __has_feature ++#define ABSL_HAVE_FEATURE(f) __has_feature(f) ++#else ++#define ABSL_HAVE_FEATURE(f) 0 ++#endif ++ ++// Portable check for GCC minimum version: ++// https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html ++#if defined(__GNUC__) && defined(__GNUC_MINOR__) ++#define ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(x, y) \ ++ (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y)) ++#else ++#define ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(x, y) 0 ++#endif ++ ++#if defined(__clang__) && defined(__clang_major__) && defined(__clang_minor__) ++#define ABSL_INTERNAL_HAVE_MIN_CLANG_VERSION(x, y) \ ++ (__clang_major__ > (x) || __clang_major__ == (x) && __clang_minor__ >= (y)) ++#else ++#define ABSL_INTERNAL_HAVE_MIN_CLANG_VERSION(x, y) 0 ++#endif ++ ++// ABSL_HAVE_TLS is defined to 1 when __thread should be supported. ++// We assume __thread is supported on Linux when compiled with Clang or compiled ++// against libstdc++ with _GLIBCXX_HAVE_TLS defined. ++#ifdef ABSL_HAVE_TLS ++#error ABSL_HAVE_TLS cannot be directly set ++#elif defined(__linux__) && (defined(__clang__) || defined(_GLIBCXX_HAVE_TLS)) ++#define ABSL_HAVE_TLS 1 ++#endif ++ ++// ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE ++// ++// Checks whether `std::is_trivially_destructible` is supported. ++// ++// Notes: All supported compilers using libc++ support this feature, as does ++// gcc >= 4.8.1 using libstdc++, and Visual Studio. ++#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE ++#error ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE cannot be directly set ++#elif defined(_LIBCPP_VERSION) || defined(_MSC_VER) || \ ++ (!defined(__clang__) && defined(__GLIBCXX__) && \ ++ ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(4, 8)) ++#define ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE 1 ++#endif ++ ++// ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE ++// ++// Checks whether `std::is_trivially_default_constructible` and ++// `std::is_trivially_copy_constructible` are supported. ++ ++// ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE ++// ++// Checks whether `std::is_trivially_copy_assignable` is supported. ++ ++// Notes: Clang with libc++ supports these features, as does gcc >= 5.1 with ++// either libc++ or libstdc++, and Visual Studio (but not NVCC). ++#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) ++#error ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE cannot be directly set ++#elif defined(ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE) ++#error ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE cannot directly set ++#elif (defined(__clang__) && defined(_LIBCPP_VERSION)) || \ ++ (!defined(__clang__) && ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(7, 4) && \ ++ (defined(_LIBCPP_VERSION) || defined(__GLIBCXX__))) || \ ++ (defined(_MSC_VER) && !defined(__NVCC__)) ++#define ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE 1 ++#define ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE 1 ++#endif ++ ++// ABSL_HAVE_SOURCE_LOCATION_CURRENT ++// ++// Indicates whether `absl::SourceLocation::current()` will return useful ++// information in some contexts. ++#ifndef ABSL_HAVE_SOURCE_LOCATION_CURRENT ++#if ABSL_INTERNAL_HAS_KEYWORD(__builtin_LINE) && \ ++ ABSL_INTERNAL_HAS_KEYWORD(__builtin_FILE) ++#define ABSL_HAVE_SOURCE_LOCATION_CURRENT 1 ++#elif ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(5, 0) ++#define ABSL_HAVE_SOURCE_LOCATION_CURRENT 1 ++#endif ++#endif ++ ++// ABSL_HAVE_THREAD_LOCAL ++// ++// Checks whether C++11's `thread_local` storage duration specifier is ++// supported. ++#ifdef ABSL_HAVE_THREAD_LOCAL ++#error ABSL_HAVE_THREAD_LOCAL cannot be directly set ++#elif defined(__APPLE__) ++// Notes: ++// * Xcode's clang did not support `thread_local` until version 8, and ++// even then not for all iOS < 9.0. ++// * Xcode 9.3 started disallowing `thread_local` for 32-bit iOS simulator ++// targeting iOS 9.x. ++// * Xcode 10 moves the deployment target check for iOS < 9.0 to link time ++// making ABSL_HAVE_FEATURE unreliable there. ++// ++#if ABSL_HAVE_FEATURE(cxx_thread_local) && \ ++ !(TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0) ++#define ABSL_HAVE_THREAD_LOCAL 1 ++#endif ++#else // !defined(__APPLE__) ++#define ABSL_HAVE_THREAD_LOCAL 1 ++#endif ++ ++// There are platforms for which TLS should not be used even though the compiler ++// makes it seem like it's supported (Android NDK < r12b for example). ++// This is primarily because of linker problems and toolchain misconfiguration: ++// Abseil does not intend to support this indefinitely. Currently, the newest ++// toolchain that we intend to support that requires this behavior is the ++// r11 NDK - allowing for a 5 year support window on that means this option ++// is likely to be removed around June of 2021. ++// TLS isn't supported until NDK r12b per ++// https://developer.android.com/ndk/downloads/revision_history.html ++// Since NDK r16, `__NDK_MAJOR__` and `__NDK_MINOR__` are defined in ++// . For NDK < r16, users should define these macros, ++// e.g. `-D__NDK_MAJOR__=11 -D__NKD_MINOR__=0` for NDK r11. ++#if defined(__ANDROID__) && defined(__clang__) ++#if __has_include() ++#include ++#endif // __has_include() ++#if defined(__ANDROID__) && defined(__clang__) && defined(__NDK_MAJOR__) && \ ++ defined(__NDK_MINOR__) && \ ++ ((__NDK_MAJOR__ < 12) || ((__NDK_MAJOR__ == 12) && (__NDK_MINOR__ < 1))) ++#undef ABSL_HAVE_TLS ++#undef ABSL_HAVE_THREAD_LOCAL ++#endif ++#endif // defined(__ANDROID__) && defined(__clang__) ++ ++// ABSL_HAVE_INTRINSIC_INT128 ++// ++// Checks whether the __int128 compiler extension for a 128-bit integral type is ++// supported. ++// ++// Note: __SIZEOF_INT128__ is defined by Clang and GCC when __int128 is ++// supported, but we avoid using it in certain cases: ++// * On Clang: ++// * Building using Clang for Windows, where the Clang runtime library has ++// 128-bit support only on LP64 architectures, but Windows is LLP64. ++// * On Nvidia's nvcc: ++// * nvcc also defines __GNUC__ and __SIZEOF_INT128__, but not all versions ++// actually support __int128. ++ ++/* Unfortunately FB does not support alignment requirements (16) in ODS ++ ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++#error ABSL_HAVE_INTRINSIC_INT128 cannot be directly set ++#elif defined(__SIZEOF_INT128__) ++#if (defined(__clang__) && !defined(_WIN32)) || \ ++ (defined(__CUDACC__) && __CUDACC_VER_MAJOR__ >= 9) || \ ++ (defined(__GNUC__) && !defined(__clang__) && !defined(__CUDACC__)) ++#define ABSL_HAVE_INTRINSIC_INT128 1 ++#elif defined(__CUDACC__) ++// __CUDACC_VER__ is a full version number before CUDA 9, and is defined to a ++// string explaining that it has been removed starting with CUDA 9. We use ++// nested #ifs because there is no short-circuiting in the preprocessor. ++// NOTE: `__CUDACC__` could be undefined while `__CUDACC_VER__` is defined. ++#if __CUDACC_VER__ >= 70000 ++#define ABSL_HAVE_INTRINSIC_INT128 1 ++#endif // __CUDACC_VER__ >= 70000 ++#endif // defined(__CUDACC__) ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ */ ++#undef ABSL_HAVE_INTRINSIC_INT128 ++ ++// ABSL_HAVE_EXCEPTIONS ++// ++// Checks whether the compiler both supports and enables exceptions. Many ++// compilers support a "no exceptions" mode that disables exceptions. ++// ++// Generally, when ABSL_HAVE_EXCEPTIONS is not defined: ++// ++// * Code using `throw` and `try` may not compile. ++// * The `noexcept` specifier will still compile and behave as normal. ++// * The `noexcept` operator may still return `false`. ++// ++// For further details, consult the compiler's documentation. ++#ifdef ABSL_HAVE_EXCEPTIONS ++#error ABSL_HAVE_EXCEPTIONS cannot be directly set. ++#elif ABSL_INTERNAL_HAVE_MIN_CLANG_VERSION(3, 6) ++// Clang >= 3.6 ++#if ABSL_HAVE_FEATURE(cxx_exceptions) ++#define ABSL_HAVE_EXCEPTIONS 1 ++#endif // ABSL_HAVE_FEATURE(cxx_exceptions) ++#elif defined(__clang__) ++// Clang < 3.6 ++// http://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html#the-exceptions-macro ++#if defined(__EXCEPTIONS) && ABSL_HAVE_FEATURE(cxx_exceptions) ++#define ABSL_HAVE_EXCEPTIONS 1 ++#endif // defined(__EXCEPTIONS) && ABSL_HAVE_FEATURE(cxx_exceptions) ++// Handle remaining special cases and default to exceptions being supported. ++#elif !(defined(__GNUC__) && (__GNUC__ < 5) && !defined(__EXCEPTIONS)) && \ ++ !(ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(5, 0) && \ ++ !defined(__cpp_exceptions)) && \ ++ !(defined(_MSC_VER) && !defined(_CPPUNWIND)) ++#define ABSL_HAVE_EXCEPTIONS 1 ++#endif ++ ++// ----------------------------------------------------------------------------- ++// Platform Feature Checks ++// ----------------------------------------------------------------------------- ++ ++// Currently supported operating systems and associated preprocessor ++// symbols: ++// ++// Linux and Linux-derived __linux__ ++// Android __ANDROID__ (implies __linux__) ++// Linux (non-Android) __linux__ && !__ANDROID__ ++// Darwin (macOS and iOS) __APPLE__ ++// Akaros (http://akaros.org) __ros__ ++// Windows _WIN32 ++// NaCL __native_client__ ++// AsmJS __asmjs__ ++// WebAssembly __wasm__ ++// Fuchsia __Fuchsia__ ++// ++// Note that since Android defines both __ANDROID__ and __linux__, one ++// may probe for either Linux or Android by simply testing for __linux__. ++ ++// ABSL_HAVE_MMAP ++// ++// Checks whether the platform has an mmap(2) implementation as defined in ++// POSIX.1-2001. ++#ifdef ABSL_HAVE_MMAP ++#error ABSL_HAVE_MMAP cannot be directly set ++#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \ ++ defined(__ros__) || defined(__native_client__) || defined(__asmjs__) || \ ++ defined(__wasm__) || defined(__Fuchsia__) || defined(__sun) || \ ++ defined(__ASYLO__) || defined(__myriad2__) ++#define ABSL_HAVE_MMAP 1 ++#endif ++ ++// ABSL_HAVE_PTHREAD_GETSCHEDPARAM ++// ++// Checks whether the platform implements the pthread_(get|set)schedparam(3) ++// functions as defined in POSIX.1-2001. ++#ifdef ABSL_HAVE_PTHREAD_GETSCHEDPARAM ++#error ABSL_HAVE_PTHREAD_GETSCHEDPARAM cannot be directly set ++#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \ ++ defined(__ros__) ++#define ABSL_HAVE_PTHREAD_GETSCHEDPARAM 1 ++#endif ++ ++// ABSL_HAVE_SCHED_GETCPU ++// ++// Checks whether sched_getcpu is available. ++#ifdef ABSL_HAVE_SCHED_GETCPU ++#error ABSL_HAVE_SCHED_GETCPU cannot be directly set ++#elif defined(__linux__) ++#define ABSL_HAVE_SCHED_GETCPU 1 ++#endif ++ ++// ABSL_HAVE_SCHED_YIELD ++// ++// Checks whether the platform implements sched_yield(2) as defined in ++// POSIX.1-2001. ++#ifdef ABSL_HAVE_SCHED_YIELD ++#error ABSL_HAVE_SCHED_YIELD cannot be directly set ++#elif defined(__linux__) || defined(__ros__) || defined(__native_client__) ++#define ABSL_HAVE_SCHED_YIELD 1 ++#endif ++ ++// ABSL_HAVE_SEMAPHORE_H ++// ++// Checks whether the platform supports the header and sem_init(3) ++// family of functions as standardized in POSIX.1-2001. ++// ++// Note: While Apple provides for both iOS and macOS, it is ++// explicitly deprecated and will cause build failures if enabled for those ++// platforms. We side-step the issue by not defining it here for Apple ++// platforms. ++#ifdef ABSL_HAVE_SEMAPHORE_H ++#error ABSL_HAVE_SEMAPHORE_H cannot be directly set ++#elif defined(__linux__) || defined(__ros__) ++#define ABSL_HAVE_SEMAPHORE_H 1 ++#endif ++ ++// ABSL_HAVE_ALARM ++// ++// Checks whether the platform supports the header and alarm(2) ++// function as standardized in POSIX.1-2001. ++#ifdef ABSL_HAVE_ALARM ++#error ABSL_HAVE_ALARM cannot be directly set ++#elif defined(__GOOGLE_GRTE_VERSION__) ++// feature tests for Google's GRTE ++#define ABSL_HAVE_ALARM 1 ++#elif defined(__GLIBC__) ++// feature test for glibc ++#define ABSL_HAVE_ALARM 1 ++#elif defined(_MSC_VER) ++// feature tests for Microsoft's library ++#elif defined(__MINGW32__) ++// mingw32 doesn't provide alarm(2): ++// https://osdn.net/projects/mingw/scm/git/mingw-org-wsl/blobs/5.2-trunk/mingwrt/include/unistd.h ++// mingw-w64 provides a no-op implementation: ++// https://sourceforge.net/p/mingw-w64/mingw-w64/ci/master/tree/mingw-w64-crt/misc/alarm.c ++#elif defined(__EMSCRIPTEN__) ++// emscripten doesn't support signals ++#elif defined(__Fuchsia__) ++// Signals don't exist on fuchsia. ++#elif defined(__native_client__) ++#else ++// other standard libraries ++#define ABSL_HAVE_ALARM 1 ++#endif ++ ++// ABSL_IS_LITTLE_ENDIAN ++// ABSL_IS_BIG_ENDIAN ++// ++// Checks the endianness of the platform. ++// ++// Notes: uses the built in endian macros provided by GCC (since 4.6) and ++// Clang (since 3.2); see ++// https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html. ++// Otherwise, if _WIN32, assume little endian. Otherwise, bail with an error. ++#if defined(ABSL_IS_BIG_ENDIAN) ++#error "ABSL_IS_BIG_ENDIAN cannot be directly set." ++#endif ++#if defined(ABSL_IS_LITTLE_ENDIAN) ++#error "ABSL_IS_LITTLE_ENDIAN cannot be directly set." ++#endif ++ ++#if (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \ ++ __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) ++#define ABSL_IS_LITTLE_ENDIAN 1 ++#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \ ++ __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ++#define ABSL_IS_BIG_ENDIAN 1 ++#elif defined(_WIN32) ++#define ABSL_IS_LITTLE_ENDIAN 1 ++#else ++#error "absl endian detection needs to be set up for your compiler" ++#endif ++ ++// macOS 10.13 and iOS 10.11 don't let you use , , or ++// even though the headers exist and are publicly noted to work. See ++// https://github.com/abseil/abseil-cpp/issues/207 and ++// https://developer.apple.com/documentation/xcode_release_notes/xcode_10_release_notes ++// libc++ spells out the availability requirements in the file ++// llvm-project/libcxx/include/__config via the #define ++// _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS. ++#if defined(__APPLE__) && defined(_LIBCPP_VERSION) && \ ++ ((defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \ ++ __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101400) || \ ++ (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && \ ++ __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 120000) || \ ++ (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && \ ++ __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 50000) || \ ++ (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && \ ++ __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 120000)) ++#define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 1 ++#else ++#define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 0 ++#endif ++ ++// ABSL_HAVE_STD_ANY ++// ++// Checks whether C++17 std::any is available by checking whether exists. ++#ifdef ABSL_HAVE_STD_ANY ++#error "ABSL_HAVE_STD_ANY cannot be directly set." ++#endif ++ ++#ifdef __has_include ++#if __has_include() && defined(__cplusplus) && __cplusplus >= 201703L && \ ++ !ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE ++#define ABSL_HAVE_STD_ANY 1 ++#endif ++#endif ++ ++// ABSL_HAVE_STD_OPTIONAL ++// ++// Checks whether C++17 std::optional is available. ++#ifdef ABSL_HAVE_STD_OPTIONAL ++#error "ABSL_HAVE_STD_OPTIONAL cannot be directly set." ++#endif ++ ++#ifdef __has_include ++#if __has_include() && defined(__cplusplus) && \ ++ __cplusplus >= 201703L && !ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE ++#define ABSL_HAVE_STD_OPTIONAL 1 ++#endif ++#endif ++ ++// ABSL_HAVE_STD_VARIANT ++// ++// Checks whether C++17 std::variant is available. ++#ifdef ABSL_HAVE_STD_VARIANT ++#error "ABSL_HAVE_STD_VARIANT cannot be directly set." ++#endif ++ ++#ifdef __has_include ++#if __has_include() && defined(__cplusplus) && \ ++ __cplusplus >= 201703L && !ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE ++#define ABSL_HAVE_STD_VARIANT 1 ++#endif ++#endif ++ ++// ABSL_HAVE_STD_STRING_VIEW ++// ++// Checks whether C++17 std::string_view is available. ++#ifdef ABSL_HAVE_STD_STRING_VIEW ++#error "ABSL_HAVE_STD_STRING_VIEW cannot be directly set." ++#endif ++ ++#ifdef __has_include ++#if __has_include() && defined(__cplusplus) && \ ++ __cplusplus >= 201703L ++#define ABSL_HAVE_STD_STRING_VIEW 1 ++#endif ++#endif ++ ++// For MSVC, `__has_include` is supported in VS 2017 15.3, which is later than ++// the support for , , , . So we use ++// _MSC_VER to check whether we have VS 2017 RTM (when , , ++// , is implemented) or higher. Also, `__cplusplus` is ++// not correctly set by MSVC, so we use `_MSVC_LANG` to check the language ++// version. ++// TODO(zhangxy): fix tests before enabling aliasing for `std::any`. ++#if defined(_MSC_VER) && _MSC_VER >= 1910 && \ ++ ((defined(_MSVC_LANG) && _MSVC_LANG > 201402) || \ ++ (defined(__cplusplus) && __cplusplus > 201402)) ++// #define ABSL_HAVE_STD_ANY 1 ++#define ABSL_HAVE_STD_OPTIONAL 1 ++#define ABSL_HAVE_STD_VARIANT 1 ++#define ABSL_HAVE_STD_STRING_VIEW 1 ++#endif ++ ++// ABSL_USES_STD_ANY ++// ++// Indicates whether absl::any is an alias for std::any. ++#if !defined(ABSL_OPTION_USE_STD_ANY) ++#error options.h is misconfigured. ++#elif ABSL_OPTION_USE_STD_ANY == 0 || \ ++ (ABSL_OPTION_USE_STD_ANY == 2 && !defined(ABSL_HAVE_STD_ANY)) ++#undef ABSL_USES_STD_ANY ++#elif ABSL_OPTION_USE_STD_ANY == 1 || \ ++ (ABSL_OPTION_USE_STD_ANY == 2 && defined(ABSL_HAVE_STD_ANY)) ++#define ABSL_USES_STD_ANY 1 ++#else ++#error options.h is misconfigured. ++#endif ++ ++// ABSL_USES_STD_OPTIONAL ++// ++// Indicates whether absl::optional is an alias for std::optional. ++#if !defined(ABSL_OPTION_USE_STD_OPTIONAL) ++#error options.h is misconfigured. ++#elif ABSL_OPTION_USE_STD_OPTIONAL == 0 || \ ++ (ABSL_OPTION_USE_STD_OPTIONAL == 2 && !defined(ABSL_HAVE_STD_OPTIONAL)) ++#undef ABSL_USES_STD_OPTIONAL ++#elif ABSL_OPTION_USE_STD_OPTIONAL == 1 || \ ++ (ABSL_OPTION_USE_STD_OPTIONAL == 2 && defined(ABSL_HAVE_STD_OPTIONAL)) ++#define ABSL_USES_STD_OPTIONAL 1 ++#else ++#error options.h is misconfigured. ++#endif ++ ++// ABSL_USES_STD_VARIANT ++// ++// Indicates whether absl::variant is an alias for std::variant. ++#if !defined(ABSL_OPTION_USE_STD_VARIANT) ++#error options.h is misconfigured. ++#elif ABSL_OPTION_USE_STD_VARIANT == 0 || \ ++ (ABSL_OPTION_USE_STD_VARIANT == 2 && !defined(ABSL_HAVE_STD_VARIANT)) ++#undef ABSL_USES_STD_VARIANT ++#elif ABSL_OPTION_USE_STD_VARIANT == 1 || \ ++ (ABSL_OPTION_USE_STD_VARIANT == 2 && defined(ABSL_HAVE_STD_VARIANT)) ++#define ABSL_USES_STD_VARIANT 1 ++#else ++#error options.h is misconfigured. ++#endif ++ ++// ABSL_USES_STD_STRING_VIEW ++// ++// Indicates whether absl::string_view is an alias for std::string_view. ++#if !defined(ABSL_OPTION_USE_STD_STRING_VIEW) ++#error options.h is misconfigured. ++#elif ABSL_OPTION_USE_STD_STRING_VIEW == 0 || \ ++ (ABSL_OPTION_USE_STD_STRING_VIEW == 2 && \ ++ !defined(ABSL_HAVE_STD_STRING_VIEW)) ++#undef ABSL_USES_STD_STRING_VIEW ++#elif ABSL_OPTION_USE_STD_STRING_VIEW == 1 || \ ++ (ABSL_OPTION_USE_STD_STRING_VIEW == 2 && \ ++ defined(ABSL_HAVE_STD_STRING_VIEW)) ++#define ABSL_USES_STD_STRING_VIEW 1 ++#else ++#error options.h is misconfigured. ++#endif ++ ++// In debug mode, MSVC 2017's std::variant throws a EXCEPTION_ACCESS_VIOLATION ++// SEH exception from emplace for variant when constructing the ++// struct can throw. This defeats some of variant_test and ++// variant_exception_safety_test. ++#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_DEBUG) ++#define ABSL_INTERNAL_MSVC_2017_DBG_MODE ++#endif ++ ++// ABSL_INTERNAL_MANGLED_NS ++// ABSL_INTERNAL_MANGLED_BACKREFERENCE ++// ++// Internal macros for building up mangled names in our internal fork of CCTZ. ++// This implementation detail is only needed and provided for the MSVC build. ++// ++// These macros both expand to string literals. ABSL_INTERNAL_MANGLED_NS is ++// the mangled spelling of the `absl` namespace, and ++// ABSL_INTERNAL_MANGLED_BACKREFERENCE is a back-reference integer representing ++// the proper count to skip past the CCTZ fork namespace names. (This number ++// is one larger when there is an inline namespace name to skip.) ++#if defined(_MSC_VER) ++#if ABSL_OPTION_USE_INLINE_NAMESPACE == 0 ++#define ABSL_INTERNAL_MANGLED_NS "absl" ++#define ABSL_INTERNAL_MANGLED_BACKREFERENCE "5" ++#else ++#define ABSL_INTERNAL_MANGLED_NS \ ++ ABSL_INTERNAL_TOKEN_STR(ABSL_OPTION_INLINE_NAMESPACE_NAME) "@absl" ++#define ABSL_INTERNAL_MANGLED_BACKREFERENCE "6" ++#endif ++#endif ++ ++#undef ABSL_INTERNAL_HAS_KEYWORD ++ ++// ABSL_DLL ++// ++// When building Abseil as a DLL, this macro expands to `__declspec(dllexport)` ++// so we can annotate symbols appropriately as being exported. When used in ++// headers consuming a DLL, this macro expands to `__declspec(dllimport)` so ++// that consumers know the symbol is defined inside the DLL. In all other cases, ++// the macro expands to nothing. ++#if defined(_MSC_VER) ++#if defined(ABSL_BUILD_DLL) ++#define ABSL_DLL __declspec(dllexport) ++#elif defined(ABSL_CONSUME_DLL) ++#define ABSL_DLL __declspec(dllimport) ++#else ++#define ABSL_DLL ++#endif ++#else ++#define ABSL_DLL ++#endif // defined(_MSC_VER) ++ ++// ABSL_HAVE_MEMORY_SANITIZER ++// ++// MemorySanitizer (MSan) is a detector of uninitialized reads. It consists of ++// a compiler instrumentation module and a run-time library. ++#ifdef ABSL_HAVE_MEMORY_SANITIZER ++#error "ABSL_HAVE_MEMORY_SANITIZER cannot be directly set." ++#elif defined(__SANITIZE_MEMORY__) ++#define ABSL_HAVE_MEMORY_SANITIZER 1 ++#elif !defined(__native_client__) && ABSL_HAVE_FEATURE(memory_sanitizer) ++#define ABSL_HAVE_MEMORY_SANITIZER 1 ++#endif ++ ++// ABSL_HAVE_THREAD_SANITIZER ++// ++// ThreadSanitizer (TSan) is a fast data race detector. ++#ifdef ABSL_HAVE_THREAD_SANITIZER ++#error "ABSL_HAVE_THREAD_SANITIZER cannot be directly set." ++#elif defined(__SANITIZE_THREAD__) ++#define ABSL_HAVE_THREAD_SANITIZER 1 ++#elif ABSL_HAVE_FEATURE(thread_sanitizer) ++#define ABSL_HAVE_THREAD_SANITIZER 1 ++#endif ++ ++// ABSL_HAVE_ADDRESS_SANITIZER ++// ++// AddressSanitizer (ASan) is a fast memory error detector. ++#ifdef ABSL_HAVE_ADDRESS_SANITIZER ++#error "ABSL_HAVE_ADDRESS_SANITIZER cannot be directly set." ++#elif defined(__SANITIZE_ADDRESS__) ++#define ABSL_HAVE_ADDRESS_SANITIZER 1 ++#elif ABSL_HAVE_FEATURE(address_sanitizer) ++#define ABSL_HAVE_ADDRESS_SANITIZER 1 ++#endif ++ ++// ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION ++// ++// Class template argument deduction is a language feature added in C++17. ++#ifdef ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION ++#error "ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION cannot be directly set." ++#elif defined(__cpp_deduction_guides) ++#define ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION 1 ++#endif ++ ++#endif // ABSL_BASE_CONFIG_H_ +diff --git a/extern/int128/absl/base/macros.h b/extern/int128/absl/base/macros.h +new file mode 100644 +index 0000000000..3e085a916b +--- /dev/null ++++ b/extern/int128/absl/base/macros.h +@@ -0,0 +1,158 @@ ++// ++// Copyright 2017 The Abseil Authors. ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// https://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++// ++// ----------------------------------------------------------------------------- ++// File: macros.h ++// ----------------------------------------------------------------------------- ++// ++// This header file defines the set of language macros used within Abseil code. ++// For the set of macros used to determine supported compilers and platforms, ++// see absl/base/config.h instead. ++// ++// This code is compiled directly on many platforms, including client ++// platforms like Windows, Mac, and embedded systems. Before making ++// any changes here, make sure that you're not breaking any platforms. ++ ++#ifndef ABSL_BASE_MACROS_H_ ++#define ABSL_BASE_MACROS_H_ ++ ++#include ++#include ++ ++#include "absl/base/attributes.h" ++#include "absl/base/config.h" ++#include "absl/base/optimization.h" ++#include "absl/base/port.h" ++ ++// ABSL_ARRAYSIZE() ++// ++// Returns the number of elements in an array as a compile-time constant, which ++// can be used in defining new arrays. If you use this macro on a pointer by ++// mistake, you will get a compile-time error. ++#define ABSL_ARRAYSIZE(array) \ ++ (sizeof(::absl::macros_internal::ArraySizeHelper(array))) ++ ++namespace absl { ++ABSL_NAMESPACE_BEGIN ++namespace macros_internal { ++// Note: this internal template function declaration is used by ABSL_ARRAYSIZE. ++// The function doesn't need a definition, as we only use its type. ++template ++auto ArraySizeHelper(const T (&array)[N]) -> char (&)[N]; ++} // namespace macros_internal ++ABSL_NAMESPACE_END ++} // namespace absl ++ ++// ABSL_BAD_CALL_IF() ++// ++// Used on a function overload to trap bad calls: any call that matches the ++// overload will cause a compile-time error. This macro uses a clang-specific ++// "enable_if" attribute, as described at ++// https://clang.llvm.org/docs/AttributeReference.html#enable-if ++// ++// Overloads which use this macro should be bracketed by ++// `#ifdef ABSL_BAD_CALL_IF`. ++// ++// Example: ++// ++// int isdigit(int c); ++// #ifdef ABSL_BAD_CALL_IF ++// int isdigit(int c) ++// ABSL_BAD_CALL_IF(c <= -1 || c > 255, ++// "'c' must have the value of an unsigned char or EOF"); ++// #endif // ABSL_BAD_CALL_IF ++#if ABSL_HAVE_ATTRIBUTE(enable_if) ++#define ABSL_BAD_CALL_IF(expr, msg) \ ++ __attribute__((enable_if(expr, "Bad call trap"), unavailable(msg))) ++#endif ++ ++// ABSL_ASSERT() ++// ++// In C++11, `assert` can't be used portably within constexpr functions. ++// ABSL_ASSERT functions as a runtime assert but works in C++11 constexpr ++// functions. Example: ++// ++// constexpr double Divide(double a, double b) { ++// return ABSL_ASSERT(b != 0), a / b; ++// } ++// ++// This macro is inspired by ++// https://akrzemi1.wordpress.com/2017/05/18/asserts-in-constexpr-functions/ ++#if defined(NDEBUG) ++#define ABSL_ASSERT(expr) \ ++ (false ? static_cast(expr) : static_cast(0)) ++#else ++#define ABSL_ASSERT(expr) \ ++ (ABSL_PREDICT_TRUE((expr)) ? static_cast(0) \ ++ : [] { assert(false && #expr); }()) // NOLINT ++#endif ++ ++// `ABSL_INTERNAL_HARDENING_ABORT()` controls how `ABSL_HARDENING_ASSERT()` ++// aborts the program in release mode (when NDEBUG is defined). The ++// implementation should abort the program as quickly as possible and ideally it ++// should not be possible to ignore the abort request. ++#if (ABSL_HAVE_BUILTIN(__builtin_trap) && \ ++ ABSL_HAVE_BUILTIN(__builtin_unreachable)) || \ ++ (defined(__GNUC__) && !defined(__clang__)) ++#define ABSL_INTERNAL_HARDENING_ABORT() \ ++ do { \ ++ __builtin_trap(); \ ++ __builtin_unreachable(); \ ++ } while (false) ++#else ++#define ABSL_INTERNAL_HARDENING_ABORT() abort() ++#endif ++ ++// ABSL_HARDENING_ASSERT() ++// ++// `ABSL_HARDENING_ASSERT()` is like `ABSL_ASSERT()`, but used to implement ++// runtime assertions that should be enabled in hardened builds even when ++// `NDEBUG` is defined. ++// ++// When `NDEBUG` is not defined, `ABSL_HARDENING_ASSERT()` is identical to ++// `ABSL_ASSERT()`. ++// ++// See `ABSL_OPTION_HARDENED` in `absl/base/options.h` for more information on ++// hardened mode. ++#if ABSL_OPTION_HARDENED == 1 && defined(NDEBUG) ++#define ABSL_HARDENING_ASSERT(expr) \ ++ (ABSL_PREDICT_TRUE((expr)) ? static_cast(0) \ ++ : [] { ABSL_INTERNAL_HARDENING_ABORT(); }()) ++#else ++#define ABSL_HARDENING_ASSERT(expr) ABSL_ASSERT(expr) ++#endif ++ ++#ifdef ABSL_HAVE_EXCEPTIONS ++#define ABSL_INTERNAL_TRY try ++#define ABSL_INTERNAL_CATCH_ANY catch (...) ++#define ABSL_INTERNAL_RETHROW do { throw; } while (false) ++#else // ABSL_HAVE_EXCEPTIONS ++#define ABSL_INTERNAL_TRY if (true) ++#define ABSL_INTERNAL_CATCH_ANY else if (false) ++#define ABSL_INTERNAL_RETHROW do {} while (false) ++#endif // ABSL_HAVE_EXCEPTIONS ++ ++// `ABSL_INTERNAL_UNREACHABLE` is an unreachable statement. A program which ++// reaches one has undefined behavior, and the compiler may optimize ++// accordingly. ++#if defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable) ++#define ABSL_INTERNAL_UNREACHABLE __builtin_unreachable() ++#elif defined(_MSC_VER) ++#define ABSL_INTERNAL_UNREACHABLE __assume(0) ++#else ++#define ABSL_INTERNAL_UNREACHABLE ++#endif ++ ++#endif // ABSL_BASE_MACROS_H_ +diff --git a/extern/int128/absl/base/optimization.h b/extern/int128/absl/base/optimization.h +new file mode 100644 +index 0000000000..d090be1286 +--- /dev/null ++++ b/extern/int128/absl/base/optimization.h +@@ -0,0 +1,244 @@ ++// ++// Copyright 2017 The Abseil Authors. ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// https://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++// ++// ----------------------------------------------------------------------------- ++// File: optimization.h ++// ----------------------------------------------------------------------------- ++// ++// This header file defines portable macros for performance optimization. ++ ++#ifndef ABSL_BASE_OPTIMIZATION_H_ ++#define ABSL_BASE_OPTIMIZATION_H_ ++ ++#include ++ ++#include "absl/base/config.h" ++ ++// ABSL_BLOCK_TAIL_CALL_OPTIMIZATION ++// ++// Instructs the compiler to avoid optimizing tail-call recursion. This macro is ++// useful when you wish to preserve the existing function order within a stack ++// trace for logging, debugging, or profiling purposes. ++// ++// Example: ++// ++// int f() { ++// int result = g(); ++// ABSL_BLOCK_TAIL_CALL_OPTIMIZATION(); ++// return result; ++// } ++#if defined(__pnacl__) ++#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() if (volatile int x = 0) { (void)x; } ++#elif defined(__clang__) ++// Clang will not tail call given inline volatile assembly. ++#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() __asm__ __volatile__("") ++#elif defined(__GNUC__) ++// GCC will not tail call given inline volatile assembly. ++#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() __asm__ __volatile__("") ++#elif defined(_MSC_VER) ++#include ++// The __nop() intrinsic blocks the optimisation. ++#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() __nop() ++#else ++#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() if (volatile int x = 0) { (void)x; } ++#endif ++ ++// ABSL_CACHELINE_SIZE ++// ++// Explicitly defines the size of the L1 cache for purposes of alignment. ++// Setting the cacheline size allows you to specify that certain objects be ++// aligned on a cacheline boundary with `ABSL_CACHELINE_ALIGNED` declarations. ++// (See below.) ++// ++// NOTE: this macro should be replaced with the following C++17 features, when ++// those are generally available: ++// ++// * `std::hardware_constructive_interference_size` ++// * `std::hardware_destructive_interference_size` ++// ++// See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0154r1.html ++// for more information. ++#if defined(__GNUC__) ++// Cache line alignment ++#if defined(__i386__) || defined(__x86_64__) ++#define ABSL_CACHELINE_SIZE 64 ++#elif defined(__powerpc64__) ++#define ABSL_CACHELINE_SIZE 128 ++#elif defined(__aarch64__) ++// We would need to read special register ctr_el0 to find out L1 dcache size. ++// This value is a good estimate based on a real aarch64 machine. ++#define ABSL_CACHELINE_SIZE 64 ++#elif defined(__arm__) ++// Cache line sizes for ARM: These values are not strictly correct since ++// cache line sizes depend on implementations, not architectures. There ++// are even implementations with cache line sizes configurable at boot ++// time. ++#if defined(__ARM_ARCH_5T__) ++#define ABSL_CACHELINE_SIZE 32 ++#elif defined(__ARM_ARCH_7A__) ++#define ABSL_CACHELINE_SIZE 64 ++#endif ++#endif ++ ++#ifndef ABSL_CACHELINE_SIZE ++// A reasonable default guess. Note that overestimates tend to waste more ++// space, while underestimates tend to waste more time. ++#define ABSL_CACHELINE_SIZE 64 ++#endif ++ ++// ABSL_CACHELINE_ALIGNED ++// ++// Indicates that the declared object be cache aligned using ++// `ABSL_CACHELINE_SIZE` (see above). Cacheline aligning objects allows you to ++// load a set of related objects in the L1 cache for performance improvements. ++// Cacheline aligning objects properly allows constructive memory sharing and ++// prevents destructive (or "false") memory sharing. ++// ++// NOTE: callers should replace uses of this macro with `alignas()` using ++// `std::hardware_constructive_interference_size` and/or ++// `std::hardware_destructive_interference_size` when C++17 becomes available to ++// them. ++// ++// See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0154r1.html ++// for more information. ++// ++// On some compilers, `ABSL_CACHELINE_ALIGNED` expands to an `__attribute__` ++// or `__declspec` attribute. For compilers where this is not known to work, ++// the macro expands to nothing. ++// ++// No further guarantees are made here. The result of applying the macro ++// to variables and types is always implementation-defined. ++// ++// WARNING: It is easy to use this attribute incorrectly, even to the point ++// of causing bugs that are difficult to diagnose, crash, etc. It does not ++// of itself guarantee that objects are aligned to a cache line. ++// ++// NOTE: Some compilers are picky about the locations of annotations such as ++// this attribute, so prefer to put it at the beginning of your declaration. ++// For example, ++// ++// ABSL_CACHELINE_ALIGNED static Foo* foo = ... ++// ++// class ABSL_CACHELINE_ALIGNED Bar { ... ++// ++// Recommendations: ++// ++// 1) Consult compiler documentation; this comment is not kept in sync as ++// toolchains evolve. ++// 2) Verify your use has the intended effect. This often requires inspecting ++// the generated machine code. ++// 3) Prefer applying this attribute to individual variables. Avoid ++// applying it to types. This tends to localize the effect. ++#define ABSL_CACHELINE_ALIGNED __attribute__((aligned(ABSL_CACHELINE_SIZE))) ++#elif defined(_MSC_VER) ++#define ABSL_CACHELINE_SIZE 64 ++#define ABSL_CACHELINE_ALIGNED __declspec(align(ABSL_CACHELINE_SIZE)) ++#else ++#define ABSL_CACHELINE_SIZE 64 ++#define ABSL_CACHELINE_ALIGNED ++#endif ++ ++// ABSL_PREDICT_TRUE, ABSL_PREDICT_FALSE ++// ++// Enables the compiler to prioritize compilation using static analysis for ++// likely paths within a boolean branch. ++// ++// Example: ++// ++// if (ABSL_PREDICT_TRUE(expression)) { ++// return result; // Faster if more likely ++// } else { ++// return 0; ++// } ++// ++// Compilers can use the information that a certain branch is not likely to be ++// taken (for instance, a CHECK failure) to optimize for the common case in ++// the absence of better information (ie. compiling gcc with `-fprofile-arcs`). ++// ++// Recommendation: Modern CPUs dynamically predict branch execution paths, ++// typically with accuracy greater than 97%. As a result, annotating every ++// branch in a codebase is likely counterproductive; however, annotating ++// specific branches that are both hot and consistently mispredicted is likely ++// to yield performance improvements. ++#if ABSL_HAVE_BUILTIN(__builtin_expect) || \ ++ (defined(__GNUC__) && !defined(__clang__)) ++#define ABSL_PREDICT_FALSE(x) (__builtin_expect(false || (x), false)) ++#define ABSL_PREDICT_TRUE(x) (__builtin_expect(false || (x), true)) ++#else ++#define ABSL_PREDICT_FALSE(x) (x) ++#define ABSL_PREDICT_TRUE(x) (x) ++#endif ++ ++// ABSL_INTERNAL_ASSUME(cond) ++// Informs the compiler that a condition is always true and that it can assume ++// it to be true for optimization purposes. The call has undefined behavior if ++// the condition is false. ++// In !NDEBUG mode, the condition is checked with an assert(). ++// NOTE: The expression must not have side effects, as it will only be evaluated ++// in some compilation modes and not others. ++// ++// Example: ++// ++// int x = ...; ++// ABSL_INTERNAL_ASSUME(x >= 0); ++// // The compiler can optimize the division to a simple right shift using the ++// // assumption specified above. ++// int y = x / 16; ++// ++#if !defined(NDEBUG) ++#define ABSL_INTERNAL_ASSUME(cond) assert(cond) ++#elif ABSL_HAVE_BUILTIN(__builtin_assume) ++#define ABSL_INTERNAL_ASSUME(cond) __builtin_assume(cond) ++#elif defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable) ++#define ABSL_INTERNAL_ASSUME(cond) \ ++ do { \ ++ if (!(cond)) __builtin_unreachable(); \ ++ } while (0) ++#elif defined(_MSC_VER) ++#define ABSL_INTERNAL_ASSUME(cond) __assume(cond) ++#else ++#define ABSL_INTERNAL_ASSUME(cond) \ ++ do { \ ++ static_cast(false && (cond)); \ ++ } while (0) ++#endif ++ ++// ABSL_INTERNAL_UNIQUE_SMALL_NAME(cond) ++// This macro forces small unique name on a static file level symbols like ++// static local variables or static functions. This is intended to be used in ++// macro definitions to optimize the cost of generated code. Do NOT use it on ++// symbols exported from translation unit since it may cause a link time ++// conflict. ++// ++// Example: ++// ++// #define MY_MACRO(txt) ++// namespace { ++// char VeryVeryLongVarName[] ABSL_INTERNAL_UNIQUE_SMALL_NAME() = txt; ++// const char* VeryVeryLongFuncName() ABSL_INTERNAL_UNIQUE_SMALL_NAME(); ++// const char* VeryVeryLongFuncName() { return txt; } ++// } ++// ++ ++#if defined(__GNUC__) ++#define ABSL_INTERNAL_UNIQUE_SMALL_NAME2(x) #x ++#define ABSL_INTERNAL_UNIQUE_SMALL_NAME1(x) ABSL_INTERNAL_UNIQUE_SMALL_NAME2(x) ++#define ABSL_INTERNAL_UNIQUE_SMALL_NAME() \ ++ asm(ABSL_INTERNAL_UNIQUE_SMALL_NAME1(.absl.__COUNTER__)) ++#else ++#define ABSL_INTERNAL_UNIQUE_SMALL_NAME() ++#endif ++ ++#endif // ABSL_BASE_OPTIMIZATION_H_ +diff --git a/extern/int128/absl/base/options.h b/extern/int128/absl/base/options.h +new file mode 100644 +index 0000000000..230bf1eecc +--- /dev/null ++++ b/extern/int128/absl/base/options.h +@@ -0,0 +1,238 @@ ++// Copyright 2019 The Abseil Authors. ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// https://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++// ++// ----------------------------------------------------------------------------- ++// File: options.h ++// ----------------------------------------------------------------------------- ++// ++// This file contains Abseil configuration options for setting specific ++// implementations instead of letting Abseil determine which implementation to ++// use at compile-time. Setting these options may be useful for package or build ++// managers who wish to guarantee ABI stability within binary builds (which are ++// otherwise difficult to enforce). ++// ++// *** IMPORTANT NOTICE FOR PACKAGE MANAGERS: It is important that ++// maintainers of package managers who wish to package Abseil read and ++// understand this file! *** ++// ++// Abseil contains a number of possible configuration endpoints, based on ++// parameters such as the detected platform, language version, or command-line ++// flags used to invoke the underlying binary. As is the case with all ++// libraries, binaries which contain Abseil code must ensure that separate ++// packages use the same compiled copy of Abseil to avoid a diamond dependency ++// problem, which can occur if two packages built with different Abseil ++// configuration settings are linked together. Diamond dependency problems in ++// C++ may manifest as violations to the One Definition Rule (ODR) (resulting in ++// linker errors), or undefined behavior (resulting in crashes). ++// ++// Diamond dependency problems can be avoided if all packages utilize the same ++// exact version of Abseil. Building from source code with the same compilation ++// parameters is the easiest way to avoid such dependency problems. However, for ++// package managers who cannot control such compilation parameters, we are ++// providing the file to allow you to inject ABI (Application Binary Interface) ++// stability across builds. Settings options in this file will neither change ++// API nor ABI, providing a stable copy of Abseil between packages. ++// ++// Care must be taken to keep options within these configurations isolated ++// from any other dynamic settings, such as command-line flags which could alter ++// these options. This file is provided specifically to help build and package ++// managers provide a stable copy of Abseil within their libraries and binaries; ++// other developers should not have need to alter the contents of this file. ++// ++// ----------------------------------------------------------------------------- ++// Usage ++// ----------------------------------------------------------------------------- ++// ++// For any particular package release, set the appropriate definitions within ++// this file to whatever value makes the most sense for your package(s). Note ++// that, by default, most of these options, at the moment, affect the ++// implementation of types; future options may affect other implementation ++// details. ++// ++// NOTE: the defaults within this file all assume that Abseil can select the ++// proper Abseil implementation at compile-time, which will not be sufficient ++// to guarantee ABI stability to package managers. ++ ++#ifndef ABSL_BASE_OPTIONS_H_ ++#define ABSL_BASE_OPTIONS_H_ ++ ++// Include a standard library header to allow configuration based on the ++// standard library in use. ++#ifdef __cplusplus ++#include ++#endif ++ ++// ----------------------------------------------------------------------------- ++// Type Compatibility Options ++// ----------------------------------------------------------------------------- ++// ++// ABSL_OPTION_USE_STD_ANY ++// ++// This option controls whether absl::any is implemented as an alias to ++// std::any, or as an independent implementation. ++// ++// A value of 0 means to use Abseil's implementation. This requires only C++11 ++// support, and is expected to work on every toolchain we support. ++// ++// A value of 1 means to use an alias to std::any. This requires that all code ++// using Abseil is built in C++17 mode or later. ++// ++// A value of 2 means to detect the C++ version being used to compile Abseil, ++// and use an alias only if a working std::any is available. This option is ++// useful when you are building your entire program, including all of its ++// dependencies, from source. It should not be used otherwise -- for example, ++// if you are distributing Abseil in a binary package manager -- since in ++// mode 2, absl::any will name a different type, with a different mangled name ++// and binary layout, depending on the compiler flags passed by the end user. ++// For more info, see https://abseil.io/about/design/dropin-types. ++// ++// User code should not inspect this macro. To check in the preprocessor if ++// absl::any is a typedef of std::any, use the feature macro ABSL_USES_STD_ANY. ++ ++#define ABSL_OPTION_USE_STD_ANY 2 ++ ++ ++// ABSL_OPTION_USE_STD_OPTIONAL ++// ++// This option controls whether absl::optional is implemented as an alias to ++// std::optional, or as an independent implementation. ++// ++// A value of 0 means to use Abseil's implementation. This requires only C++11 ++// support, and is expected to work on every toolchain we support. ++// ++// A value of 1 means to use an alias to std::optional. This requires that all ++// code using Abseil is built in C++17 mode or later. ++// ++// A value of 2 means to detect the C++ version being used to compile Abseil, ++// and use an alias only if a working std::optional is available. This option ++// is useful when you are building your program from source. It should not be ++// used otherwise -- for example, if you are distributing Abseil in a binary ++// package manager -- since in mode 2, absl::optional will name a different ++// type, with a different mangled name and binary layout, depending on the ++// compiler flags passed by the end user. For more info, see ++// https://abseil.io/about/design/dropin-types. ++ ++// User code should not inspect this macro. To check in the preprocessor if ++// absl::optional is a typedef of std::optional, use the feature macro ++// ABSL_USES_STD_OPTIONAL. ++ ++#define ABSL_OPTION_USE_STD_OPTIONAL 2 ++ ++ ++// ABSL_OPTION_USE_STD_STRING_VIEW ++// ++// This option controls whether absl::string_view is implemented as an alias to ++// std::string_view, or as an independent implementation. ++// ++// A value of 0 means to use Abseil's implementation. This requires only C++11 ++// support, and is expected to work on every toolchain we support. ++// ++// A value of 1 means to use an alias to std::string_view. This requires that ++// all code using Abseil is built in C++17 mode or later. ++// ++// A value of 2 means to detect the C++ version being used to compile Abseil, ++// and use an alias only if a working std::string_view is available. This ++// option is useful when you are building your program from source. It should ++// not be used otherwise -- for example, if you are distributing Abseil in a ++// binary package manager -- since in mode 2, absl::string_view will name a ++// different type, with a different mangled name and binary layout, depending on ++// the compiler flags passed by the end user. For more info, see ++// https://abseil.io/about/design/dropin-types. ++// ++// User code should not inspect this macro. To check in the preprocessor if ++// absl::string_view is a typedef of std::string_view, use the feature macro ++// ABSL_USES_STD_STRING_VIEW. ++ ++#define ABSL_OPTION_USE_STD_STRING_VIEW 2 ++ ++// ABSL_OPTION_USE_STD_VARIANT ++// ++// This option controls whether absl::variant is implemented as an alias to ++// std::variant, or as an independent implementation. ++// ++// A value of 0 means to use Abseil's implementation. This requires only C++11 ++// support, and is expected to work on every toolchain we support. ++// ++// A value of 1 means to use an alias to std::variant. This requires that all ++// code using Abseil is built in C++17 mode or later. ++// ++// A value of 2 means to detect the C++ version being used to compile Abseil, ++// and use an alias only if a working std::variant is available. This option ++// is useful when you are building your program from source. It should not be ++// used otherwise -- for example, if you are distributing Abseil in a binary ++// package manager -- since in mode 2, absl::variant will name a different ++// type, with a different mangled name and binary layout, depending on the ++// compiler flags passed by the end user. For more info, see ++// https://abseil.io/about/design/dropin-types. ++// ++// User code should not inspect this macro. To check in the preprocessor if ++// absl::variant is a typedef of std::variant, use the feature macro ++// ABSL_USES_STD_VARIANT. ++ ++#define ABSL_OPTION_USE_STD_VARIANT 2 ++ ++ ++// ABSL_OPTION_USE_INLINE_NAMESPACE ++// ABSL_OPTION_INLINE_NAMESPACE_NAME ++// ++// These options controls whether all entities in the absl namespace are ++// contained within an inner inline namespace. This does not affect the ++// user-visible API of Abseil, but it changes the mangled names of all symbols. ++// ++// This can be useful as a version tag if you are distributing Abseil in ++// precompiled form. This will prevent a binary library build of Abseil with ++// one inline namespace being used with headers configured with a different ++// inline namespace name. Binary packagers are reminded that Abseil does not ++// guarantee any ABI stability in Abseil, so any update of Abseil or ++// configuration change in such a binary package should be combined with a ++// new, unique value for the inline namespace name. ++// ++// A value of 0 means not to use inline namespaces. ++// ++// A value of 1 means to use an inline namespace with the given name inside ++// namespace absl. If this is set, ABSL_OPTION_INLINE_NAMESPACE_NAME must also ++// be changed to a new, unique identifier name. In particular "head" is not ++// allowed. ++ ++#define ABSL_OPTION_USE_INLINE_NAMESPACE 0 ++#define ABSL_OPTION_INLINE_NAMESPACE_NAME head ++ ++// ABSL_OPTION_HARDENED ++// ++// This option enables a "hardened" build in release mode (in this context, ++// release mode is defined as a build where the `NDEBUG` macro is defined). ++// ++// A value of 0 means that "hardened" mode is not enabled. ++// ++// A value of 1 means that "hardened" mode is enabled. ++// ++// Hardened builds have additional security checks enabled when `NDEBUG` is ++// defined. Defining `NDEBUG` is normally used to turn `assert()` macro into a ++// no-op, as well as disabling other bespoke program consistency checks. By ++// defining ABSL_OPTION_HARDENED to 1, a select set of checks remain enabled in ++// release mode. These checks guard against programming errors that may lead to ++// security vulnerabilities. In release mode, when one of these programming ++// errors is encountered, the program will immediately abort, possibly without ++// any attempt at logging. ++// ++// The checks enabled by this option are not free; they do incur runtime cost. ++// ++// The checks enabled by this option are always active when `NDEBUG` is not ++// defined, even in the case when ABSL_OPTION_HARDENED is defined to 0. The ++// checks enabled by this option may abort the program in a different way and ++// log additional information when `NDEBUG` is not defined. ++ ++#define ABSL_OPTION_HARDENED 0 ++ ++#endif // ABSL_BASE_OPTIONS_H_ +diff --git a/extern/int128/absl/base/policy_checks.h b/extern/int128/absl/base/policy_checks.h +new file mode 100644 +index 0000000000..06b3243916 +--- /dev/null ++++ b/extern/int128/absl/base/policy_checks.h +@@ -0,0 +1,111 @@ ++// Copyright 2017 The Abseil Authors. ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// https://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++// ++// ----------------------------------------------------------------------------- ++// File: policy_checks.h ++// ----------------------------------------------------------------------------- ++// ++// This header enforces a minimum set of policies at build time, such as the ++// supported compiler and library versions. Unsupported configurations are ++// reported with `#error`. This enforcement is best effort, so successfully ++// compiling this header does not guarantee a supported configuration. ++ ++#ifndef ABSL_BASE_POLICY_CHECKS_H_ ++#define ABSL_BASE_POLICY_CHECKS_H_ ++ ++// Included for the __GLIBC_PREREQ macro used below. ++#include ++ ++// Included for the _STLPORT_VERSION macro used below. ++#if defined(__cplusplus) ++#include ++#endif ++ ++// ----------------------------------------------------------------------------- ++// Operating System Check ++// ----------------------------------------------------------------------------- ++ ++#if defined(__CYGWIN__) ++#error "Cygwin is not supported." ++#endif ++ ++// ----------------------------------------------------------------------------- ++// Toolchain Check ++// ----------------------------------------------------------------------------- ++ ++// We support MSVC++ 14.0 update 2 and later. ++// This minimum will go up. ++#if defined(_MSC_FULL_VER) && _MSC_FULL_VER < 190023918 && !defined(__clang__) ++#error "This package requires Visual Studio 2015 Update 2 or higher." ++#endif ++ ++// We support gcc 4.7 and later. ++// This minimum will go up. ++#if defined(__GNUC__) && !defined(__clang__) ++#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7) ++#error "This package requires gcc 4.7 or higher." ++#endif ++#endif ++ ++// We support Apple Xcode clang 4.2.1 (version 421.11.65) and later. ++// This corresponds to Apple Xcode version 4.5. ++// This minimum will go up. ++#if defined(__apple_build_version__) && __apple_build_version__ < 4211165 ++#error "This package requires __apple_build_version__ of 4211165 or higher." ++#endif ++ ++// ----------------------------------------------------------------------------- ++// C++ Version Check ++// ----------------------------------------------------------------------------- ++ ++// Enforce C++11 as the minimum. Note that Visual Studio has not ++// advanced __cplusplus despite being good enough for our purposes, so ++// so we exempt it from the check. ++#if defined(__cplusplus) && !defined(_MSC_VER) ++#if __cplusplus < 201103L ++#error "C++ versions less than C++11 are not supported." ++#endif ++#endif ++ ++// ----------------------------------------------------------------------------- ++// Standard Library Check ++// ----------------------------------------------------------------------------- ++ ++#if defined(_STLPORT_VERSION) ++#error "STLPort is not supported." ++#endif ++ ++// ----------------------------------------------------------------------------- ++// `char` Size Check ++// ----------------------------------------------------------------------------- ++ ++// Abseil currently assumes CHAR_BIT == 8. If you would like to use Abseil on a ++// platform where this is not the case, please provide us with the details about ++// your platform so we can consider relaxing this requirement. ++#if CHAR_BIT != 8 ++#error "Abseil assumes CHAR_BIT == 8." ++#endif ++ ++// ----------------------------------------------------------------------------- ++// `int` Size Check ++// ----------------------------------------------------------------------------- ++ ++// Abseil currently assumes that an int is 4 bytes. If you would like to use ++// Abseil on a platform where this is not the case, please provide us with the ++// details about your platform so we can consider relaxing this requirement. ++#if INT_MAX < 2147483647 ++#error "Abseil assumes that int is at least 4 bytes. " ++#endif ++ ++#endif // ABSL_BASE_POLICY_CHECKS_H_ +diff --git a/extern/int128/absl/base/port.h b/extern/int128/absl/base/port.h +new file mode 100644 +index 0000000000..5bc4d6cd95 +--- /dev/null ++++ b/extern/int128/absl/base/port.h +@@ -0,0 +1,25 @@ ++// Copyright 2017 The Abseil Authors. ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// https://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++// ++// This files is a forwarding header for other headers containing various ++// portability macros and functions. ++ ++#ifndef ABSL_BASE_PORT_H_ ++#define ABSL_BASE_PORT_H_ ++ ++#include "absl/base/attributes.h" ++#include "absl/base/config.h" ++#include "absl/base/optimization.h" ++ ++#endif // ABSL_BASE_PORT_H_ +diff --git a/extern/int128/absl/numeric/Makefile b/extern/int128/absl/numeric/Makefile +new file mode 100644 +index 0000000000..396e95d063 +--- /dev/null ++++ b/extern/int128/absl/numeric/Makefile +@@ -0,0 +1,11 @@ ++LIBRARY=libi128$(CROSS).a ++ ++$(LIBRARY): $(wildcard *.cc) $(wildcard *.h) $(wildcard internal/*.h) $(wildcard ../base/*.h) $(wildcard *.inc) Makefile ++ $(RM) -f *.o ++ $(CXX) $(CROSS_FLAGS) -I../.. -c -O3 -fPIC int128.cc ++ $(AR) crs $(LIBRARY) *.o ++ $(RM) -f *.o ++ ++.PHONY: clean ++clean: ++ $(RM) -f *.o *.a +diff --git a/extern/int128/absl/numeric/bits.h b/extern/int128/absl/numeric/bits.h +new file mode 100644 +index 0000000000..52013ad49b +--- /dev/null ++++ b/extern/int128/absl/numeric/bits.h +@@ -0,0 +1,177 @@ ++// Copyright 2020 The Abseil Authors ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// https://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++// ++// ----------------------------------------------------------------------------- ++// File: bits.h ++// ----------------------------------------------------------------------------- ++// ++// This file contains implementations of C++20's bitwise math functions, as ++// defined by: ++// ++// P0553R4: ++// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0553r4.html ++// P0556R3: ++// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0556r3.html ++// P1355R2: ++// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1355r2.html ++// P1956R1: ++// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1956r1.pdf ++// ++// When using a standard library that implements these functions, we use the ++// standard library's implementation. ++ ++#ifndef ABSL_NUMERIC_BITS_H_ ++#define ABSL_NUMERIC_BITS_H_ ++ ++#include ++#include ++#include ++ ++#if (defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L) || \ ++ (defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L) ++#include ++#endif ++ ++#include "absl/base/attributes.h" ++#include "absl/base/config.h" ++#include "absl/numeric/internal/bits.h" ++ ++namespace absl { ++ABSL_NAMESPACE_BEGIN ++ ++#if !(defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L) ++// rotating ++template ++ABSL_MUST_USE_RESULT constexpr ++ typename std::enable_if::value, T>::type ++ rotl(T x, int s) noexcept { ++ return numeric_internal::RotateLeft(x, s); ++} ++ ++template ++ABSL_MUST_USE_RESULT constexpr ++ typename std::enable_if::value, T>::type ++ rotr(T x, int s) noexcept { ++ return numeric_internal::RotateRight(x, s); ++} ++ ++// Counting functions ++// ++// While these functions are typically constexpr, on some platforms, they may ++// not be marked as constexpr due to constraints of the compiler/available ++// intrinsics. ++template ++ABSL_INTERNAL_CONSTEXPR_CLZ inline ++ typename std::enable_if::value, int>::type ++ countl_zero(T x) noexcept { ++ return numeric_internal::CountLeadingZeroes(x); ++} ++ ++template ++ABSL_INTERNAL_CONSTEXPR_CLZ inline ++ typename std::enable_if::value, int>::type ++ countl_one(T x) noexcept { ++ // Avoid integer promotion to a wider type ++ return countl_zero(static_cast(~x)); ++} ++ ++template ++ABSL_INTERNAL_CONSTEXPR_CTZ inline ++ typename std::enable_if::value, int>::type ++ countr_zero(T x) noexcept { ++ return numeric_internal::CountTrailingZeroes(x); ++} ++ ++template ++ABSL_INTERNAL_CONSTEXPR_CTZ inline ++ typename std::enable_if::value, int>::type ++ countr_one(T x) noexcept { ++ // Avoid integer promotion to a wider type ++ return countr_zero(static_cast(~x)); ++} ++ ++template ++ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline ++ typename std::enable_if::value, int>::type ++ popcount(T x) noexcept { ++ return numeric_internal::Popcount(x); ++} ++#else // defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L ++ ++using std::countl_one; ++using std::countl_zero; ++using std::countr_one; ++using std::countr_zero; ++using std::popcount; ++using std::rotl; ++using std::rotr; ++ ++#endif ++ ++#if !(defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L) ++// Returns: true if x is an integral power of two; false otherwise. ++template ++constexpr inline typename std::enable_if::value, bool>::type ++has_single_bit(T x) noexcept { ++ return x != 0 && (x & (x - 1)) == 0; ++} ++ ++// Returns: If x == 0, 0; otherwise one plus the base-2 logarithm of x, with any ++// fractional part discarded. ++template ++ABSL_INTERNAL_CONSTEXPR_CLZ inline ++ typename std::enable_if::value, T>::type ++ bit_width(T x) noexcept { ++ return std::numeric_limits::digits - countl_zero(x); ++} ++ ++// Returns: If x == 0, 0; otherwise the maximal value y such that ++// has_single_bit(y) is true and y <= x. ++template ++ABSL_INTERNAL_CONSTEXPR_CLZ inline ++ typename std::enable_if::value, T>::type ++ bit_floor(T x) noexcept { ++ return x == 0 ? 0 : T{1} << (bit_width(x) - 1); ++} ++ ++// Returns: N, where N is the smallest power of 2 greater than or equal to x. ++// ++// Preconditions: N is representable as a value of type T. ++template ++ABSL_INTERNAL_CONSTEXPR_CLZ inline ++ typename std::enable_if::value, T>::type ++ bit_ceil(T x) { ++ // If T is narrower than unsigned, T{1} << bit_width will be promoted. We ++ // want to force it to wraparound so that bit_ceil of an invalid value are not ++ // core constant expressions. ++ // ++ // BitCeilNonPowerOf2 triggers an overflow in constexpr contexts if we would ++ // undergo promotion to unsigned but not fit the result into T without ++ // truncation. ++ return has_single_bit(x) ? T{1} << (bit_width(x) - 1) ++ : numeric_internal::BitCeilNonPowerOf2(x); ++} ++#else // defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L ++ ++using std::bit_ceil; ++using std::bit_floor; ++using std::bit_width; ++using std::has_single_bit; ++ ++#endif ++ ++ABSL_NAMESPACE_END ++} // namespace absl ++ ++#endif // ABSL_NUMERIC_BITS_H_ +diff --git a/extern/int128/absl/numeric/int128.cc b/extern/int128/absl/numeric/int128.cc +new file mode 100644 +index 0000000000..17d88744ae +--- /dev/null ++++ b/extern/int128/absl/numeric/int128.cc +@@ -0,0 +1,383 @@ ++// Copyright 2017 The Abseil Authors. ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// https://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++#include "absl/numeric/int128.h" ++ ++#include ++ ++#include ++#include ++#include // NOLINT(readability/streams) ++#include ++#include ++#include ++ ++#include "absl/base/optimization.h" ++#include "absl/numeric/bits.h" ++ ++namespace absl { ++ABSL_NAMESPACE_BEGIN ++ ++ABSL_DLL const uint128 kuint128max = MakeUint128( ++ std::numeric_limits::max(), std::numeric_limits::max()); ++ ++namespace { ++ ++// Returns the 0-based position of the last set bit (i.e., most significant bit) ++// in the given uint128. The argument is not 0. ++// ++// For example: ++// Given: 5 (decimal) == 101 (binary) ++// Returns: 2 ++inline ABSL_ATTRIBUTE_ALWAYS_INLINE int Fls128(uint128 n) { ++ if (uint64_t hi = Uint128High64(n)) { ++ ABSL_INTERNAL_ASSUME(hi != 0); ++ return 127 - countl_zero(hi); ++ } ++ const uint64_t low = Uint128Low64(n); ++ ABSL_INTERNAL_ASSUME(low != 0); ++ return 63 - countl_zero(low); ++} ++ ++// Long division/modulo for uint128 implemented using the shift-subtract ++// division algorithm adapted from: ++// https://stackoverflow.com/questions/5386377/division-without-using ++inline void DivModImpl(uint128 dividend, uint128 divisor, uint128* quotient_ret, ++ uint128* remainder_ret) { ++ assert(divisor != 0); ++ ++ if (divisor > dividend) { ++ *quotient_ret = 0; ++ *remainder_ret = dividend; ++ return; ++ } ++ ++ if (divisor == dividend) { ++ *quotient_ret = 1; ++ *remainder_ret = 0; ++ return; ++ } ++ ++ uint128 denominator = divisor; ++ uint128 quotient = 0; ++ ++ // Left aligns the MSB of the denominator and the dividend. ++ const int shift = Fls128(dividend) - Fls128(denominator); ++ denominator <<= shift; ++ ++ // Uses shift-subtract algorithm to divide dividend by denominator. The ++ // remainder will be left in dividend. ++ for (int i = 0; i <= shift; ++i) { ++ quotient <<= 1; ++ if (dividend >= denominator) { ++ dividend -= denominator; ++ quotient |= 1; ++ } ++ denominator >>= 1; ++ } ++ ++ *quotient_ret = quotient; ++ *remainder_ret = dividend; ++} ++ ++template ++uint128 MakeUint128FromFloat(T v) { ++ static_assert(std::is_floating_point::value, ""); ++ ++ // Rounding behavior is towards zero, same as for built-in types. ++ ++ // Undefined behavior if v is NaN or cannot fit into uint128. ++ assert(std::isfinite(v) && v > -1 && ++ (std::numeric_limits::max_exponent <= 128 || ++ v < std::ldexp(static_cast(1), 128))); ++ ++ if (v >= std::ldexp(static_cast(1), 64)) { ++ uint64_t hi = static_cast(std::ldexp(v, -64)); ++ uint64_t lo = static_cast(v - std::ldexp(static_cast(hi), 64)); ++ return MakeUint128(hi, lo); ++ } ++ ++ return MakeUint128(0, static_cast(v)); ++} ++ ++#if defined(__clang__) && !defined(__SSE3__) ++// Workaround for clang bug: https://bugs.llvm.org/show_bug.cgi?id=38289 ++// Casting from long double to uint64_t is miscompiled and drops bits. ++// It is more work, so only use when we need the workaround. ++uint128 MakeUint128FromFloat(long double v) { ++ // Go 50 bits at a time, that fits in a double ++ static_assert(std::numeric_limits::digits >= 50, ""); ++ static_assert(std::numeric_limits::digits <= 150, ""); ++ // Undefined behavior if v is not finite or cannot fit into uint128. ++ assert(std::isfinite(v) && v > -1 && v < std::ldexp(1.0L, 128)); ++ ++ v = std::ldexp(v, -100); ++ uint64_t w0 = static_cast(static_cast(std::trunc(v))); ++ v = std::ldexp(v - static_cast(w0), 50); ++ uint64_t w1 = static_cast(static_cast(std::trunc(v))); ++ v = std::ldexp(v - static_cast(w1), 50); ++ uint64_t w2 = static_cast(static_cast(std::trunc(v))); ++ return (static_cast(w0) << 100) | (static_cast(w1) << 50) | ++ static_cast(w2); ++} ++#endif // __clang__ && !__SSE3__ ++} // namespace ++ ++uint128::uint128(float v) : uint128(MakeUint128FromFloat(v)) {} ++uint128::uint128(double v) : uint128(MakeUint128FromFloat(v)) {} ++uint128::uint128(long double v) : uint128(MakeUint128FromFloat(v)) {} ++ ++#if !defined(ABSL_HAVE_INTRINSIC_INT128) ++uint128 operator/(uint128 lhs, uint128 rhs) { ++ uint128 quotient = 0; ++ uint128 remainder = 0; ++ DivModImpl(lhs, rhs, "ient, &remainder); ++ return quotient; ++} ++ ++uint128 operator%(uint128 lhs, uint128 rhs) { ++ uint128 quotient = 0; ++ uint128 remainder = 0; ++ DivModImpl(lhs, rhs, "ient, &remainder); ++ return remainder; ++} ++#endif // !defined(ABSL_HAVE_INTRINSIC_INT128) ++ ++namespace { ++ ++std::string Uint128ToFormattedString(uint128 v, std::ios_base::fmtflags flags) { ++ // Select a divisor which is the largest power of the base < 2^64. ++ uint128 div; ++ int div_base_log; ++ switch (flags & std::ios::basefield) { ++ case std::ios::hex: ++ div = 0x1000000000000000; // 16^15 ++ div_base_log = 15; ++ break; ++ case std::ios::oct: ++ div = 01000000000000000000000; // 8^21 ++ div_base_log = 21; ++ break; ++ default: // std::ios::dec ++ div = 10000000000000000000u; // 10^19 ++ div_base_log = 19; ++ break; ++ } ++ ++ // Now piece together the uint128 representation from three chunks of the ++ // original value, each less than "div" and therefore representable as a ++ // uint64_t. ++ std::ostringstream os; ++ std::ios_base::fmtflags copy_mask = ++ std::ios::basefield | std::ios::showbase | std::ios::uppercase; ++ os.setf(flags & copy_mask, copy_mask); ++ uint128 high = v; ++ uint128 low; ++ DivModImpl(high, div, &high, &low); ++ uint128 mid; ++ DivModImpl(high, div, &high, &mid); ++ if (Uint128Low64(high) != 0) { ++ os << Uint128Low64(high); ++ os << std::noshowbase << std::setfill('0') << std::setw(div_base_log); ++ os << Uint128Low64(mid); ++ os << std::setw(div_base_log); ++ } else if (Uint128Low64(mid) != 0) { ++ os << Uint128Low64(mid); ++ os << std::noshowbase << std::setfill('0') << std::setw(div_base_log); ++ } ++ os << Uint128Low64(low); ++ return os.str(); ++} ++ ++} // namespace ++ ++std::ostream& operator<<(std::ostream& os, uint128 v) { ++ std::ios_base::fmtflags flags = os.flags(); ++ std::string rep = Uint128ToFormattedString(v, flags); ++ ++ // Add the requisite padding. ++ std::streamsize width = os.width(0); ++ if (static_cast(width) > rep.size()) { ++ std::ios::fmtflags adjustfield = flags & std::ios::adjustfield; ++ if (adjustfield == std::ios::left) { ++ rep.append(width - rep.size(), os.fill()); ++ } else if (adjustfield == std::ios::internal && ++ (flags & std::ios::showbase) && ++ (flags & std::ios::basefield) == std::ios::hex && v != 0) { ++ rep.insert(2, width - rep.size(), os.fill()); ++ } else { ++ rep.insert(0, width - rep.size(), os.fill()); ++ } ++ } ++ ++ return os << rep; ++} ++ ++namespace { ++ ++uint128 UnsignedAbsoluteValue(int128 v) { ++ // Cast to uint128 before possibly negating because -Int128Min() is undefined. ++ return Int128High64(v) < 0 ? -uint128(v) : uint128(v); ++} ++ ++} // namespace ++ ++#if !defined(ABSL_HAVE_INTRINSIC_INT128) ++namespace { ++ ++template ++int128 MakeInt128FromFloat(T v) { ++ // Conversion when v is NaN or cannot fit into int128 would be undefined ++ // behavior if using an intrinsic 128-bit integer. ++ assert(std::isfinite(v) && (std::numeric_limits::max_exponent <= 127 || ++ (v >= -std::ldexp(static_cast(1), 127) && ++ v < std::ldexp(static_cast(1), 127)))); ++ ++ // We must convert the absolute value and then negate as needed, because ++ // floating point types are typically sign-magnitude. Otherwise, the ++ // difference between the high and low 64 bits when interpreted as two's ++ // complement overwhelms the precision of the mantissa. ++ uint128 result = v < 0 ? -MakeUint128FromFloat(-v) : MakeUint128FromFloat(v); ++ return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(result)), ++ Uint128Low64(result)); ++} ++ ++} // namespace ++ ++int128::int128(float v) : int128(MakeInt128FromFloat(v)) {} ++int128::int128(double v) : int128(MakeInt128FromFloat(v)) {} ++int128::int128(long double v) : int128(MakeInt128FromFloat(v)) {} ++ ++int128 operator/(int128 lhs, int128 rhs) { ++ assert(lhs != Int128Min() || rhs != -1); // UB on two's complement. ++ ++ uint128 quotient = 0; ++ uint128 remainder = 0; ++ DivModImpl(UnsignedAbsoluteValue(lhs), UnsignedAbsoluteValue(rhs), ++ "ient, &remainder); ++ if ((Int128High64(lhs) < 0) != (Int128High64(rhs) < 0)) quotient = -quotient; ++ return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(quotient)), ++ Uint128Low64(quotient)); ++} ++ ++int128 operator%(int128 lhs, int128 rhs) { ++ assert(lhs != Int128Min() || rhs != -1); // UB on two's complement. ++ ++ uint128 quotient = 0; ++ uint128 remainder = 0; ++ DivModImpl(UnsignedAbsoluteValue(lhs), UnsignedAbsoluteValue(rhs), ++ "ient, &remainder); ++ if (Int128High64(lhs) < 0) remainder = -remainder; ++ return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(remainder)), ++ Uint128Low64(remainder)); ++} ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ ++std::ostream& operator<<(std::ostream& os, int128 v) { ++ std::ios_base::fmtflags flags = os.flags(); ++ std::string rep; ++ ++ // Add the sign if needed. ++ bool print_as_decimal = ++ (flags & std::ios::basefield) == std::ios::dec || ++ (flags & std::ios::basefield) == std::ios_base::fmtflags(); ++ if (print_as_decimal) { ++ if (Int128High64(v) < 0) { ++ rep = "-"; ++ } else if (flags & std::ios::showpos) { ++ rep = "+"; ++ } ++ } ++ ++ rep.append(Uint128ToFormattedString( ++ print_as_decimal ? UnsignedAbsoluteValue(v) : uint128(v), os.flags())); ++ ++ // Add the requisite padding. ++ std::streamsize width = os.width(0); ++ if (static_cast(width) > rep.size()) { ++ switch (flags & std::ios::adjustfield) { ++ case std::ios::left: ++ rep.append(width - rep.size(), os.fill()); ++ break; ++ case std::ios::internal: ++ if (print_as_decimal && (rep[0] == '+' || rep[0] == '-')) { ++ rep.insert(1, width - rep.size(), os.fill()); ++ } else if ((flags & std::ios::basefield) == std::ios::hex && ++ (flags & std::ios::showbase) && v != 0) { ++ rep.insert(2, width - rep.size(), os.fill()); ++ } else { ++ rep.insert(0, width - rep.size(), os.fill()); ++ } ++ break; ++ default: // std::ios::right ++ rep.insert(0, width - rep.size(), os.fill()); ++ break; ++ } ++ } ++ ++ return os << rep; ++} ++ ++ABSL_NAMESPACE_END ++} // namespace absl ++ ++namespace std { ++constexpr bool numeric_limits::is_specialized; ++constexpr bool numeric_limits::is_signed; ++constexpr bool numeric_limits::is_integer; ++constexpr bool numeric_limits::is_exact; ++constexpr bool numeric_limits::has_infinity; ++constexpr bool numeric_limits::has_quiet_NaN; ++constexpr bool numeric_limits::has_signaling_NaN; ++constexpr float_denorm_style numeric_limits::has_denorm; ++constexpr bool numeric_limits::has_denorm_loss; ++constexpr float_round_style numeric_limits::round_style; ++constexpr bool numeric_limits::is_iec559; ++constexpr bool numeric_limits::is_bounded; ++constexpr bool numeric_limits::is_modulo; ++constexpr int numeric_limits::digits; ++constexpr int numeric_limits::digits10; ++constexpr int numeric_limits::max_digits10; ++constexpr int numeric_limits::radix; ++constexpr int numeric_limits::min_exponent; ++constexpr int numeric_limits::min_exponent10; ++constexpr int numeric_limits::max_exponent; ++constexpr int numeric_limits::max_exponent10; ++constexpr bool numeric_limits::traps; ++constexpr bool numeric_limits::tinyness_before; ++ ++constexpr bool numeric_limits::is_specialized; ++constexpr bool numeric_limits::is_signed; ++constexpr bool numeric_limits::is_integer; ++constexpr bool numeric_limits::is_exact; ++constexpr bool numeric_limits::has_infinity; ++constexpr bool numeric_limits::has_quiet_NaN; ++constexpr bool numeric_limits::has_signaling_NaN; ++constexpr float_denorm_style numeric_limits::has_denorm; ++constexpr bool numeric_limits::has_denorm_loss; ++constexpr float_round_style numeric_limits::round_style; ++constexpr bool numeric_limits::is_iec559; ++constexpr bool numeric_limits::is_bounded; ++constexpr bool numeric_limits::is_modulo; ++constexpr int numeric_limits::digits; ++constexpr int numeric_limits::digits10; ++constexpr int numeric_limits::max_digits10; ++constexpr int numeric_limits::radix; ++constexpr int numeric_limits::min_exponent; ++constexpr int numeric_limits::min_exponent10; ++constexpr int numeric_limits::max_exponent; ++constexpr int numeric_limits::max_exponent10; ++constexpr bool numeric_limits::traps; ++constexpr bool numeric_limits::tinyness_before; ++} // namespace std +diff --git a/extern/int128/absl/numeric/int128.h b/extern/int128/absl/numeric/int128.h +new file mode 100644 +index 0000000000..a9cbe489dd +--- /dev/null ++++ b/extern/int128/absl/numeric/int128.h +@@ -0,0 +1,1155 @@ ++// ++// Copyright 2017 The Abseil Authors. ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// https://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++// ++// ----------------------------------------------------------------------------- ++// File: int128.h ++// ----------------------------------------------------------------------------- ++// ++// This header file defines 128-bit integer types, `uint128` and `int128`. ++// ++// TODO(absl-team): This module is inconsistent as many inline `uint128` methods ++// are defined in this file, while many inline `int128` methods are defined in ++// the `int128_*_intrinsic.inc` files. ++ ++#ifndef ABSL_NUMERIC_INT128_H_ ++#define ABSL_NUMERIC_INT128_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "absl/base/config.h" ++#include "absl/base/macros.h" ++#include "absl/base/port.h" ++ ++#if defined(_MSC_VER) ++// In very old versions of MSVC and when the /Zc:wchar_t flag is off, wchar_t is ++// a typedef for unsigned short. Otherwise wchar_t is mapped to the __wchar_t ++// builtin type. We need to make sure not to define operator wchar_t() ++// alongside operator unsigned short() in these instances. ++#define ABSL_INTERNAL_WCHAR_T __wchar_t ++#if defined(_M_X64) ++#include ++#pragma intrinsic(_umul128) ++#endif // defined(_M_X64) ++#else // defined(_MSC_VER) ++#define ABSL_INTERNAL_WCHAR_T wchar_t ++#endif // defined(_MSC_VER) ++ ++namespace absl { ++ABSL_NAMESPACE_BEGIN ++ ++class int128; ++ ++// uint128 ++// ++// An unsigned 128-bit integer type. The API is meant to mimic an intrinsic type ++// as closely as is practical, including exhibiting undefined behavior in ++// analogous cases (e.g. division by zero). This type is intended to be a ++// drop-in replacement once C++ supports an intrinsic `uint128_t` type; when ++// that occurs, existing well-behaved uses of `uint128` will continue to work ++// using that new type. ++// ++// Note: code written with this type will continue to compile once `uint128_t` ++// is introduced, provided the replacement helper functions ++// `Uint128(Low|High)64()` and `MakeUint128()` are made. ++// ++// A `uint128` supports the following: ++// ++// * Implicit construction from integral types ++// * Explicit conversion to integral types ++// ++// Additionally, if your compiler supports `__int128`, `uint128` is ++// interoperable with that type. (Abseil checks for this compatibility through ++// the `ABSL_HAVE_INTRINSIC_INT128` macro.) ++// ++// However, a `uint128` differs from intrinsic integral types in the following ++// ways: ++// ++// * Errors on implicit conversions that do not preserve value (such as ++// loss of precision when converting to float values). ++// * Requires explicit construction from and conversion to floating point ++// types. ++// * Conversion to integral types requires an explicit static_cast() to ++// mimic use of the `-Wnarrowing` compiler flag. ++// * The alignment requirement of `uint128` may differ from that of an ++// intrinsic 128-bit integer type depending on platform and build ++// configuration. ++// ++// Example: ++// ++// float y = absl::Uint128Max(); // Error. uint128 cannot be implicitly ++// // converted to float. ++// ++// absl::uint128 v; ++// uint64_t i = v; // Error ++// uint64_t i = static_cast(v); // OK ++// ++class ++#if defined(ABSL_HAVE_INTRINSIC_INT128) ++ alignas(unsigned __int128) ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ uint128 { ++ public: ++ uint128() = default; ++ ++ // Constructors from arithmetic types ++ constexpr uint128(int v); // NOLINT(runtime/explicit) ++ constexpr uint128(unsigned int v); // NOLINT(runtime/explicit) ++ constexpr uint128(long v); // NOLINT(runtime/int) ++ constexpr uint128(unsigned long v); // NOLINT(runtime/int) ++ constexpr uint128(long long v); // NOLINT(runtime/int) ++ constexpr uint128(unsigned long long v); // NOLINT(runtime/int) ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++ constexpr uint128(__int128 v); // NOLINT(runtime/explicit) ++ constexpr uint128(unsigned __int128 v); // NOLINT(runtime/explicit) ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ constexpr uint128(int128 v); // NOLINT(runtime/explicit) ++ explicit uint128(float v); ++ explicit uint128(double v); ++ explicit uint128(long double v); ++ ++ // Assignment operators from arithmetic types ++ uint128& operator=(int v); ++ uint128& operator=(unsigned int v); ++ uint128& operator=(long v); // NOLINT(runtime/int) ++ uint128& operator=(unsigned long v); // NOLINT(runtime/int) ++ uint128& operator=(long long v); // NOLINT(runtime/int) ++ uint128& operator=(unsigned long long v); // NOLINT(runtime/int) ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++ uint128& operator=(__int128 v); ++ uint128& operator=(unsigned __int128 v); ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ uint128& operator=(int128 v); ++ ++ // Conversion operators to other arithmetic types ++ constexpr explicit operator bool() const; ++ constexpr explicit operator char() const; ++ constexpr explicit operator signed char() const; ++ constexpr explicit operator unsigned char() const; ++ constexpr explicit operator char16_t() const; ++ constexpr explicit operator char32_t() const; ++ constexpr explicit operator ABSL_INTERNAL_WCHAR_T() const; ++ constexpr explicit operator short() const; // NOLINT(runtime/int) ++ // NOLINTNEXTLINE(runtime/int) ++ constexpr explicit operator unsigned short() const; ++ constexpr explicit operator int() const; ++ constexpr explicit operator unsigned int() const; ++ constexpr explicit operator long() const; // NOLINT(runtime/int) ++ // NOLINTNEXTLINE(runtime/int) ++ constexpr explicit operator unsigned long() const; ++ // NOLINTNEXTLINE(runtime/int) ++ constexpr explicit operator long long() const; ++ // NOLINTNEXTLINE(runtime/int) ++ constexpr explicit operator unsigned long long() const; ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++ constexpr explicit operator __int128() const; ++ constexpr explicit operator unsigned __int128() const; ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ explicit operator float() const; ++ explicit operator double() const; ++ explicit operator long double() const; ++ ++ // Trivial copy constructor, assignment operator and destructor. ++ ++ // Arithmetic operators. ++ uint128& operator+=(uint128 other); ++ uint128& operator-=(uint128 other); ++ uint128& operator*=(uint128 other); ++ // Long division/modulo for uint128. ++ uint128& operator/=(uint128 other); ++ uint128& operator%=(uint128 other); ++ uint128 operator++(int); ++ uint128 operator--(int); ++ uint128& operator<<=(int); ++ uint128& operator>>=(int); ++ uint128& operator&=(uint128 other); ++ uint128& operator|=(uint128 other); ++ uint128& operator^=(uint128 other); ++ uint128& operator++(); ++ uint128& operator--(); ++ ++ // Uint128Low64() ++ // ++ // Returns the lower 64-bit value of a `uint128` value. ++ friend constexpr uint64_t Uint128Low64(uint128 v); ++ ++ // Uint128High64() ++ // ++ // Returns the higher 64-bit value of a `uint128` value. ++ friend constexpr uint64_t Uint128High64(uint128 v); ++ ++ // MakeUInt128() ++ // ++ // Constructs a `uint128` numeric value from two 64-bit unsigned integers. ++ // Note that this factory function is the only way to construct a `uint128` ++ // from integer values greater than 2^64. ++ // ++ // Example: ++ // ++ // absl::uint128 big = absl::MakeUint128(1, 0); ++ friend constexpr uint128 MakeUint128(uint64_t high, uint64_t low); ++ ++ // Uint128Max() ++ // ++ // Returns the highest value for a 128-bit unsigned integer. ++ friend constexpr uint128 Uint128Max(); ++ ++ // Support for absl::Hash. ++ template ++ friend H AbslHashValue(H h, uint128 v) { ++ return H::combine(std::move(h), Uint128High64(v), Uint128Low64(v)); ++ } ++ ++ private: ++ constexpr uint128(uint64_t high, uint64_t low); ++ ++ // TODO(strel) Update implementation to use __int128 once all users of ++ // uint128 are fixed to not depend on alignof(uint128) == 8. Also add ++ // alignas(16) to class definition to keep alignment consistent across ++ // platforms. ++#if defined(ABSL_IS_LITTLE_ENDIAN) ++ uint64_t lo_; ++ uint64_t hi_; ++#elif defined(ABSL_IS_BIG_ENDIAN) ++ uint64_t hi_; ++ uint64_t lo_; ++#else // byte order ++#error "Unsupported byte order: must be little-endian or big-endian." ++#endif // byte order ++}; ++ ++// Prefer to use the constexpr `Uint128Max()`. ++// ++// TODO(absl-team) deprecate kuint128max once migration tool is released. ++ABSL_DLL extern const uint128 kuint128max; ++ ++// allow uint128 to be logged ++std::ostream& operator<<(std::ostream& os, uint128 v); ++ ++// TODO(strel) add operator>>(std::istream&, uint128) ++ ++constexpr uint128 Uint128Max() { ++ return uint128((std::numeric_limits::max)(), ++ (std::numeric_limits::max)()); ++} ++ ++ABSL_NAMESPACE_END ++} // namespace absl ++ ++// Specialized numeric_limits for uint128. ++namespace std { ++template <> ++class numeric_limits { ++ public: ++ static constexpr bool is_specialized = true; ++ static constexpr bool is_signed = false; ++ static constexpr bool is_integer = true; ++ static constexpr bool is_exact = true; ++ static constexpr bool has_infinity = false; ++ static constexpr bool has_quiet_NaN = false; ++ static constexpr bool has_signaling_NaN = false; ++ static constexpr float_denorm_style has_denorm = denorm_absent; ++ static constexpr bool has_denorm_loss = false; ++ static constexpr float_round_style round_style = round_toward_zero; ++ static constexpr bool is_iec559 = false; ++ static constexpr bool is_bounded = true; ++ static constexpr bool is_modulo = true; ++ static constexpr int digits = 128; ++ static constexpr int digits10 = 38; ++ static constexpr int max_digits10 = 0; ++ static constexpr int radix = 2; ++ static constexpr int min_exponent = 0; ++ static constexpr int min_exponent10 = 0; ++ static constexpr int max_exponent = 0; ++ static constexpr int max_exponent10 = 0; ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++ static constexpr bool traps = numeric_limits::traps; ++#else // ABSL_HAVE_INTRINSIC_INT128 ++ static constexpr bool traps = numeric_limits::traps; ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ static constexpr bool tinyness_before = false; ++ ++ static constexpr absl::uint128 (min)() { return 0; } ++ static constexpr absl::uint128 lowest() { return 0; } ++ static constexpr absl::uint128 (max)() { return absl::Uint128Max(); } ++ static constexpr absl::uint128 epsilon() { return 0; } ++ static constexpr absl::uint128 round_error() { return 0; } ++ static constexpr absl::uint128 infinity() { return 0; } ++ static constexpr absl::uint128 quiet_NaN() { return 0; } ++ static constexpr absl::uint128 signaling_NaN() { return 0; } ++ static constexpr absl::uint128 denorm_min() { return 0; } ++}; ++} // namespace std ++ ++namespace absl { ++ABSL_NAMESPACE_BEGIN ++ ++// int128 ++// ++// A signed 128-bit integer type. The API is meant to mimic an intrinsic ++// integral type as closely as is practical, including exhibiting undefined ++// behavior in analogous cases (e.g. division by zero). ++// ++// An `int128` supports the following: ++// ++// * Implicit construction from integral types ++// * Explicit conversion to integral types ++// ++// However, an `int128` differs from intrinsic integral types in the following ++// ways: ++// ++// * It is not implicitly convertible to other integral types. ++// * Requires explicit construction from and conversion to floating point ++// types. ++ ++// Additionally, if your compiler supports `__int128`, `int128` is ++// interoperable with that type. (Abseil checks for this compatibility through ++// the `ABSL_HAVE_INTRINSIC_INT128` macro.) ++// ++// The design goal for `int128` is that it will be compatible with a future ++// `int128_t`, if that type becomes a part of the standard. ++// ++// Example: ++// ++// float y = absl::int128(17); // Error. int128 cannot be implicitly ++// // converted to float. ++// ++// absl::int128 v; ++// int64_t i = v; // Error ++// int64_t i = static_cast(v); // OK ++// ++class int128 { ++ public: ++ int128() = default; ++ ++ // Constructors from arithmetic types ++ constexpr int128(int v); // NOLINT(runtime/explicit) ++ constexpr int128(unsigned int v); // NOLINT(runtime/explicit) ++ constexpr int128(long v); // NOLINT(runtime/int) ++ constexpr int128(unsigned long v); // NOLINT(runtime/int) ++ constexpr int128(long long v); // NOLINT(runtime/int) ++ constexpr int128(unsigned long long v); // NOLINT(runtime/int) ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++ constexpr int128(__int128 v); // NOLINT(runtime/explicit) ++ constexpr explicit int128(unsigned __int128 v); ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ constexpr explicit int128(uint128 v); ++ explicit int128(float v); ++ explicit int128(double v); ++ explicit int128(long double v); ++ ++ // Assignment operators from arithmetic types ++ int128& operator=(int v); ++ int128& operator=(unsigned int v); ++ int128& operator=(long v); // NOLINT(runtime/int) ++ int128& operator=(unsigned long v); // NOLINT(runtime/int) ++ int128& operator=(long long v); // NOLINT(runtime/int) ++ int128& operator=(unsigned long long v); // NOLINT(runtime/int) ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++ int128& operator=(__int128 v); ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ ++ // Conversion operators to other arithmetic types ++ constexpr explicit operator bool() const; ++ constexpr explicit operator char() const; ++ constexpr explicit operator signed char() const; ++ constexpr explicit operator unsigned char() const; ++ constexpr explicit operator char16_t() const; ++ constexpr explicit operator char32_t() const; ++ constexpr explicit operator ABSL_INTERNAL_WCHAR_T() const; ++ constexpr explicit operator short() const; // NOLINT(runtime/int) ++ // NOLINTNEXTLINE(runtime/int) ++ constexpr explicit operator unsigned short() const; ++ constexpr explicit operator int() const; ++ constexpr explicit operator unsigned int() const; ++ constexpr explicit operator long() const; // NOLINT(runtime/int) ++ // NOLINTNEXTLINE(runtime/int) ++ constexpr explicit operator unsigned long() const; ++ // NOLINTNEXTLINE(runtime/int) ++ constexpr explicit operator long long() const; ++ // NOLINTNEXTLINE(runtime/int) ++ constexpr explicit operator unsigned long long() const; ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++ constexpr explicit operator __int128() const; ++ constexpr explicit operator unsigned __int128() const; ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ explicit operator float() const; ++ explicit operator double() const; ++ explicit operator long double() const; ++ ++ // Trivial copy constructor, assignment operator and destructor. ++ ++ // Arithmetic operators ++ int128& operator+=(int128 other); ++ int128& operator-=(int128 other); ++ int128& operator*=(int128 other); ++ int128& operator/=(int128 other); ++ int128& operator%=(int128 other); ++ int128 operator++(int); // postfix increment: i++ ++ int128 operator--(int); // postfix decrement: i-- ++ int128& operator++(); // prefix increment: ++i ++ int128& operator--(); // prefix decrement: --i ++ int128& operator&=(int128 other); ++ int128& operator|=(int128 other); ++ int128& operator^=(int128 other); ++ int128& operator<<=(int amount); ++ int128& operator>>=(int amount); ++ ++ // Int128Low64() ++ // ++ // Returns the lower 64-bit value of a `int128` value. ++ friend constexpr uint64_t Int128Low64(int128 v); ++ ++ // Int128High64() ++ // ++ // Returns the higher 64-bit value of a `int128` value. ++ friend constexpr int64_t Int128High64(int128 v); ++ ++ // MakeInt128() ++ // ++ // Constructs a `int128` numeric value from two 64-bit integers. Note that ++ // signedness is conveyed in the upper `high` value. ++ // ++ // (absl::int128(1) << 64) * high + low ++ // ++ // Note that this factory function is the only way to construct a `int128` ++ // from integer values greater than 2^64 or less than -2^64. ++ // ++ // Example: ++ // ++ // absl::int128 big = absl::MakeInt128(1, 0); ++ // absl::int128 big_n = absl::MakeInt128(-1, 0); ++ friend constexpr int128 MakeInt128(int64_t high, uint64_t low); ++ ++ // Int128Max() ++ // ++ // Returns the maximum value for a 128-bit signed integer. ++ friend constexpr int128 Int128Max(); ++ ++ // Int128Min() ++ // ++ // Returns the minimum value for a 128-bit signed integer. ++ friend constexpr int128 Int128Min(); ++ ++ // Support for absl::Hash. ++ template ++ friend H AbslHashValue(H h, int128 v) { ++ return H::combine(std::move(h), Int128High64(v), Int128Low64(v)); ++ } ++ ++ private: ++ constexpr int128(int64_t high, uint64_t low); ++ ++#if defined(ABSL_HAVE_INTRINSIC_INT128) ++ __int128 v_; ++#else // ABSL_HAVE_INTRINSIC_INT128 ++#if defined(ABSL_IS_LITTLE_ENDIAN) ++ uint64_t lo_; ++ int64_t hi_; ++#elif defined(ABSL_IS_BIG_ENDIAN) ++ int64_t hi_; ++ uint64_t lo_; ++#else // byte order ++#error "Unsupported byte order: must be little-endian or big-endian." ++#endif // byte order ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++}; ++ ++std::ostream& operator<<(std::ostream& os, int128 v); ++ ++// TODO(absl-team) add operator>>(std::istream&, int128) ++ ++constexpr int128 Int128Max() { ++ return int128((std::numeric_limits::max)(), ++ (std::numeric_limits::max)()); ++} ++ ++constexpr int128 Int128Min() { ++ return int128((std::numeric_limits::min)(), 0); ++} ++ ++ABSL_NAMESPACE_END ++} // namespace absl ++ ++// Specialized numeric_limits for int128. ++namespace std { ++template <> ++class numeric_limits { ++ public: ++ static constexpr bool is_specialized = true; ++ static constexpr bool is_signed = true; ++ static constexpr bool is_integer = true; ++ static constexpr bool is_exact = true; ++ static constexpr bool has_infinity = false; ++ static constexpr bool has_quiet_NaN = false; ++ static constexpr bool has_signaling_NaN = false; ++ static constexpr float_denorm_style has_denorm = denorm_absent; ++ static constexpr bool has_denorm_loss = false; ++ static constexpr float_round_style round_style = round_toward_zero; ++ static constexpr bool is_iec559 = false; ++ static constexpr bool is_bounded = true; ++ static constexpr bool is_modulo = false; ++ static constexpr int digits = 127; ++ static constexpr int digits10 = 38; ++ static constexpr int max_digits10 = 0; ++ static constexpr int radix = 2; ++ static constexpr int min_exponent = 0; ++ static constexpr int min_exponent10 = 0; ++ static constexpr int max_exponent = 0; ++ static constexpr int max_exponent10 = 0; ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++ static constexpr bool traps = numeric_limits<__int128>::traps; ++#else // ABSL_HAVE_INTRINSIC_INT128 ++ static constexpr bool traps = numeric_limits::traps; ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ static constexpr bool tinyness_before = false; ++ ++ static constexpr absl::int128 (min)() { return absl::Int128Min(); } ++ static constexpr absl::int128 lowest() { return absl::Int128Min(); } ++ static constexpr absl::int128 (max)() { return absl::Int128Max(); } ++ static constexpr absl::int128 epsilon() { return 0; } ++ static constexpr absl::int128 round_error() { return 0; } ++ static constexpr absl::int128 infinity() { return 0; } ++ static constexpr absl::int128 quiet_NaN() { return 0; } ++ static constexpr absl::int128 signaling_NaN() { return 0; } ++ static constexpr absl::int128 denorm_min() { return 0; } ++}; ++} // namespace std ++ ++// -------------------------------------------------------------------------- ++// Implementation details follow ++// -------------------------------------------------------------------------- ++namespace absl { ++ABSL_NAMESPACE_BEGIN ++ ++constexpr uint128 MakeUint128(uint64_t high, uint64_t low) { ++ return uint128(high, low); ++} ++ ++// Assignment from integer types. ++ ++inline uint128& uint128::operator=(int v) { return *this = uint128(v); } ++ ++inline uint128& uint128::operator=(unsigned int v) { ++ return *this = uint128(v); ++} ++ ++inline uint128& uint128::operator=(long v) { // NOLINT(runtime/int) ++ return *this = uint128(v); ++} ++ ++// NOLINTNEXTLINE(runtime/int) ++inline uint128& uint128::operator=(unsigned long v) { ++ return *this = uint128(v); ++} ++ ++// NOLINTNEXTLINE(runtime/int) ++inline uint128& uint128::operator=(long long v) { ++ return *this = uint128(v); ++} ++ ++// NOLINTNEXTLINE(runtime/int) ++inline uint128& uint128::operator=(unsigned long long v) { ++ return *this = uint128(v); ++} ++ ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++inline uint128& uint128::operator=(__int128 v) { ++ return *this = uint128(v); ++} ++ ++inline uint128& uint128::operator=(unsigned __int128 v) { ++ return *this = uint128(v); ++} ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ ++inline uint128& uint128::operator=(int128 v) { ++ return *this = uint128(v); ++} ++ ++// Arithmetic operators. ++ ++uint128 operator<<(uint128 lhs, int amount); ++uint128 operator>>(uint128 lhs, int amount); ++uint128 operator+(uint128 lhs, uint128 rhs); ++uint128 operator-(uint128 lhs, uint128 rhs); ++uint128 operator*(uint128 lhs, uint128 rhs); ++uint128 operator/(uint128 lhs, uint128 rhs); ++uint128 operator%(uint128 lhs, uint128 rhs); ++ ++inline uint128& uint128::operator<<=(int amount) { ++ *this = *this << amount; ++ return *this; ++} ++ ++inline uint128& uint128::operator>>=(int amount) { ++ *this = *this >> amount; ++ return *this; ++} ++ ++inline uint128& uint128::operator+=(uint128 other) { ++ *this = *this + other; ++ return *this; ++} ++ ++inline uint128& uint128::operator-=(uint128 other) { ++ *this = *this - other; ++ return *this; ++} ++ ++inline uint128& uint128::operator*=(uint128 other) { ++ *this = *this * other; ++ return *this; ++} ++ ++inline uint128& uint128::operator/=(uint128 other) { ++ *this = *this / other; ++ return *this; ++} ++ ++inline uint128& uint128::operator%=(uint128 other) { ++ *this = *this % other; ++ return *this; ++} ++ ++constexpr uint64_t Uint128Low64(uint128 v) { return v.lo_; } ++ ++constexpr uint64_t Uint128High64(uint128 v) { return v.hi_; } ++ ++// Constructors from integer types. ++ ++#if defined(ABSL_IS_LITTLE_ENDIAN) ++ ++constexpr uint128::uint128(uint64_t high, uint64_t low) ++ : lo_{low}, hi_{high} {} ++ ++constexpr uint128::uint128(int v) ++ : lo_{static_cast(v)}, ++ hi_{v < 0 ? (std::numeric_limits::max)() : 0} {} ++constexpr uint128::uint128(long v) // NOLINT(runtime/int) ++ : lo_{static_cast(v)}, ++ hi_{v < 0 ? (std::numeric_limits::max)() : 0} {} ++constexpr uint128::uint128(long long v) // NOLINT(runtime/int) ++ : lo_{static_cast(v)}, ++ hi_{v < 0 ? (std::numeric_limits::max)() : 0} {} ++ ++constexpr uint128::uint128(unsigned int v) : lo_{v}, hi_{0} {} ++// NOLINTNEXTLINE(runtime/int) ++constexpr uint128::uint128(unsigned long v) : lo_{v}, hi_{0} {} ++// NOLINTNEXTLINE(runtime/int) ++constexpr uint128::uint128(unsigned long long v) : lo_{v}, hi_{0} {} ++ ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++constexpr uint128::uint128(__int128 v) ++ : lo_{static_cast(v & ~uint64_t{0})}, ++ hi_{static_cast(static_cast(v) >> 64)} {} ++constexpr uint128::uint128(unsigned __int128 v) ++ : lo_{static_cast(v & ~uint64_t{0})}, ++ hi_{static_cast(v >> 64)} {} ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ ++constexpr uint128::uint128(int128 v) ++ : lo_{Int128Low64(v)}, hi_{static_cast(Int128High64(v))} {} ++ ++#elif defined(ABSL_IS_BIG_ENDIAN) ++ ++constexpr uint128::uint128(uint64_t high, uint64_t low) ++ : hi_{high}, lo_{low} {} ++ ++constexpr uint128::uint128(int v) ++ : hi_{v < 0 ? (std::numeric_limits::max)() : 0}, ++ lo_{static_cast(v)} {} ++constexpr uint128::uint128(long v) // NOLINT(runtime/int) ++ : hi_{v < 0 ? (std::numeric_limits::max)() : 0}, ++ lo_{static_cast(v)} {} ++constexpr uint128::uint128(long long v) // NOLINT(runtime/int) ++ : hi_{v < 0 ? (std::numeric_limits::max)() : 0}, ++ lo_{static_cast(v)} {} ++ ++constexpr uint128::uint128(unsigned int v) : hi_{0}, lo_{v} {} ++// NOLINTNEXTLINE(runtime/int) ++constexpr uint128::uint128(unsigned long v) : hi_{0}, lo_{v} {} ++// NOLINTNEXTLINE(runtime/int) ++constexpr uint128::uint128(unsigned long long v) : hi_{0}, lo_{v} {} ++ ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++constexpr uint128::uint128(__int128 v) ++ : hi_{static_cast(static_cast(v) >> 64)}, ++ lo_{static_cast(v & ~uint64_t{0})} {} ++constexpr uint128::uint128(unsigned __int128 v) ++ : hi_{static_cast(v >> 64)}, ++ lo_{static_cast(v & ~uint64_t{0})} {} ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ ++constexpr uint128::uint128(int128 v) ++ : hi_{static_cast(Int128High64(v))}, lo_{Int128Low64(v)} {} ++ ++#else // byte order ++#error "Unsupported byte order: must be little-endian or big-endian." ++#endif // byte order ++ ++// Conversion operators to integer types. ++ ++constexpr uint128::operator bool() const { return lo_ || hi_; } ++ ++constexpr uint128::operator char() const { return static_cast(lo_); } ++ ++constexpr uint128::operator signed char() const { ++ return static_cast(lo_); ++} ++ ++constexpr uint128::operator unsigned char() const { ++ return static_cast(lo_); ++} ++ ++constexpr uint128::operator char16_t() const { ++ return static_cast(lo_); ++} ++ ++constexpr uint128::operator char32_t() const { ++ return static_cast(lo_); ++} ++ ++constexpr uint128::operator ABSL_INTERNAL_WCHAR_T() const { ++ return static_cast(lo_); ++} ++ ++// NOLINTNEXTLINE(runtime/int) ++constexpr uint128::operator short() const { return static_cast(lo_); } ++ ++constexpr uint128::operator unsigned short() const { // NOLINT(runtime/int) ++ return static_cast(lo_); // NOLINT(runtime/int) ++} ++ ++constexpr uint128::operator int() const { return static_cast(lo_); } ++ ++constexpr uint128::operator unsigned int() const { ++ return static_cast(lo_); ++} ++ ++// NOLINTNEXTLINE(runtime/int) ++constexpr uint128::operator long() const { return static_cast(lo_); } ++ ++constexpr uint128::operator unsigned long() const { // NOLINT(runtime/int) ++ return static_cast(lo_); // NOLINT(runtime/int) ++} ++ ++constexpr uint128::operator long long() const { // NOLINT(runtime/int) ++ return static_cast(lo_); // NOLINT(runtime/int) ++} ++ ++constexpr uint128::operator unsigned long long() const { // NOLINT(runtime/int) ++ return static_cast(lo_); // NOLINT(runtime/int) ++} ++ ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++constexpr uint128::operator __int128() const { ++ return (static_cast<__int128>(hi_) << 64) + lo_; ++} ++ ++constexpr uint128::operator unsigned __int128() const { ++ return (static_cast(hi_) << 64) + lo_; ++} ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ ++// Conversion operators to floating point types. ++ ++inline uint128::operator float() const { ++ return static_cast(lo_) + std::ldexp(static_cast(hi_), 64); ++} ++ ++inline uint128::operator double() const { ++ return static_cast(lo_) + std::ldexp(static_cast(hi_), 64); ++} ++ ++inline uint128::operator long double() const { ++ return static_cast(lo_) + ++ std::ldexp(static_cast(hi_), 64); ++} ++ ++// Comparison operators. ++ ++inline bool operator==(uint128 lhs, uint128 rhs) { ++#if defined(ABSL_HAVE_INTRINSIC_INT128) ++ return static_cast(lhs) == ++ static_cast(rhs); ++#else ++ return (Uint128Low64(lhs) == Uint128Low64(rhs) && ++ Uint128High64(lhs) == Uint128High64(rhs)); ++#endif ++} ++ ++inline bool operator!=(uint128 lhs, uint128 rhs) { ++ return !(lhs == rhs); ++} ++ ++inline bool operator<(uint128 lhs, uint128 rhs) { ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++ return static_cast(lhs) < ++ static_cast(rhs); ++#else ++ return (Uint128High64(lhs) == Uint128High64(rhs)) ++ ? (Uint128Low64(lhs) < Uint128Low64(rhs)) ++ : (Uint128High64(lhs) < Uint128High64(rhs)); ++#endif ++} ++ ++inline bool operator>(uint128 lhs, uint128 rhs) { return rhs < lhs; } ++ ++inline bool operator<=(uint128 lhs, uint128 rhs) { return !(rhs < lhs); } ++ ++inline bool operator>=(uint128 lhs, uint128 rhs) { return !(lhs < rhs); } ++ ++// Unary operators. ++ ++constexpr inline uint128 operator+(uint128 val) { ++ return val; ++} ++ ++constexpr inline int128 operator+(int128 val) { ++ return val; ++} ++ ++inline uint128 operator-(uint128 val) { ++#if defined(ABSL_HAVE_INTRINSIC_INT128) ++ return -static_cast(val); ++#else ++ uint64_t hi = ~Uint128High64(val); ++ uint64_t lo = ~Uint128Low64(val) + 1; ++ if (lo == 0) ++hi; // carry ++ return MakeUint128(hi, lo); ++#endif ++} ++ ++constexpr inline bool operator!(uint128 val) { ++#if defined(ABSL_HAVE_INTRINSIC_INT128) ++ return !static_cast(val); ++#else ++ return !Uint128High64(val) && !Uint128Low64(val); ++#endif ++} ++ ++// Logical operators. ++ ++constexpr inline uint128 operator~(uint128 val) { ++#if defined(ABSL_HAVE_INTRINSIC_INT128) ++ return ~static_cast(val); ++#else ++ return MakeUint128(~Uint128High64(val), ~Uint128Low64(val)); ++#endif ++} ++ ++constexpr inline uint128 operator|(uint128 lhs, uint128 rhs) { ++#if defined(ABSL_HAVE_INTRINSIC_INT128) ++ return static_cast(lhs) | ++ static_cast(rhs); ++#else ++ return MakeUint128(Uint128High64(lhs) | Uint128High64(rhs), ++ Uint128Low64(lhs) | Uint128Low64(rhs)); ++#endif ++} ++ ++constexpr inline uint128 operator&(uint128 lhs, uint128 rhs) { ++#if defined(ABSL_HAVE_INTRINSIC_INT128) ++ return static_cast(lhs) & ++ static_cast(rhs); ++#else ++ return MakeUint128(Uint128High64(lhs) & Uint128High64(rhs), ++ Uint128Low64(lhs) & Uint128Low64(rhs)); ++#endif ++} ++ ++constexpr inline uint128 operator^(uint128 lhs, uint128 rhs) { ++#if defined(ABSL_HAVE_INTRINSIC_INT128) ++ return static_cast(lhs) ^ ++ static_cast(rhs); ++#else ++ return MakeUint128(Uint128High64(lhs) ^ Uint128High64(rhs), ++ Uint128Low64(lhs) ^ Uint128Low64(rhs)); ++#endif ++} ++ ++inline uint128& uint128::operator|=(uint128 other) { ++ *this = *this | other; ++ return *this; ++} ++ ++inline uint128& uint128::operator&=(uint128 other) { ++ *this = *this & other; ++ return *this; ++} ++ ++inline uint128& uint128::operator^=(uint128 other) { ++ *this = *this ^ other; ++ return *this; ++} ++ ++// Arithmetic operators. ++ ++inline uint128 operator<<(uint128 lhs, int amount) { ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++ return static_cast(lhs) << amount; ++#else ++ // uint64_t shifts of >= 64 are undefined, so we will need some ++ // special-casing. ++ if (amount < 64) { ++ if (amount != 0) { ++ return MakeUint128( ++ (Uint128High64(lhs) << amount) | (Uint128Low64(lhs) >> (64 - amount)), ++ Uint128Low64(lhs) << amount); ++ } ++ return lhs; ++ } ++ return MakeUint128(Uint128Low64(lhs) << (amount - 64), 0); ++#endif ++} ++ ++inline uint128 operator>>(uint128 lhs, int amount) { ++#ifdef ABSL_HAVE_INTRINSIC_INT128 ++ return static_cast(lhs) >> amount; ++#else ++ // uint64_t shifts of >= 64 are undefined, so we will need some ++ // special-casing. ++ if (amount < 64) { ++ if (amount != 0) { ++ return MakeUint128(Uint128High64(lhs) >> amount, ++ (Uint128Low64(lhs) >> amount) | ++ (Uint128High64(lhs) << (64 - amount))); ++ } ++ return lhs; ++ } ++ return MakeUint128(0, Uint128High64(lhs) >> (amount - 64)); ++#endif ++} ++ ++inline uint128 operator+(uint128 lhs, uint128 rhs) { ++#if defined(ABSL_HAVE_INTRINSIC_INT128) ++ return static_cast(lhs) + ++ static_cast(rhs); ++#else ++ uint128 result = MakeUint128(Uint128High64(lhs) + Uint128High64(rhs), ++ Uint128Low64(lhs) + Uint128Low64(rhs)); ++ if (Uint128Low64(result) < Uint128Low64(lhs)) { // check for carry ++ return MakeUint128(Uint128High64(result) + 1, Uint128Low64(result)); ++ } ++ return result; ++#endif ++} ++ ++inline uint128 operator-(uint128 lhs, uint128 rhs) { ++#if defined(ABSL_HAVE_INTRINSIC_INT128) ++ return static_cast(lhs) - ++ static_cast(rhs); ++#else ++ uint128 result = MakeUint128(Uint128High64(lhs) - Uint128High64(rhs), ++ Uint128Low64(lhs) - Uint128Low64(rhs)); ++ if (Uint128Low64(lhs) < Uint128Low64(rhs)) { // check for carry ++ return MakeUint128(Uint128High64(result) - 1, Uint128Low64(result)); ++ } ++ return result; ++#endif ++} ++ ++inline uint128 operator*(uint128 lhs, uint128 rhs) { ++#if defined(ABSL_HAVE_INTRINSIC_INT128) ++ // TODO(strel) Remove once alignment issues are resolved and unsigned __int128 ++ // can be used for uint128 storage. ++ return static_cast(lhs) * ++ static_cast(rhs); ++#elif defined(_MSC_VER) && defined(_M_X64) ++ uint64_t carry; ++ uint64_t low = _umul128(Uint128Low64(lhs), Uint128Low64(rhs), &carry); ++ return MakeUint128(Uint128Low64(lhs) * Uint128High64(rhs) + ++ Uint128High64(lhs) * Uint128Low64(rhs) + carry, ++ low); ++#else // ABSL_HAVE_INTRINSIC128 ++ uint64_t a32 = Uint128Low64(lhs) >> 32; ++ uint64_t a00 = Uint128Low64(lhs) & 0xffffffff; ++ uint64_t b32 = Uint128Low64(rhs) >> 32; ++ uint64_t b00 = Uint128Low64(rhs) & 0xffffffff; ++ uint128 result = ++ MakeUint128(Uint128High64(lhs) * Uint128Low64(rhs) + ++ Uint128Low64(lhs) * Uint128High64(rhs) + a32 * b32, ++ a00 * b00); ++ result += uint128(a32 * b00) << 32; ++ result += uint128(a00 * b32) << 32; ++ return result; ++#endif // ABSL_HAVE_INTRINSIC128 ++} ++ ++#if defined(ABSL_HAVE_INTRINSIC_INT128) ++inline uint128 operator/(uint128 lhs, uint128 rhs) { ++ return static_cast(lhs) / ++ static_cast(rhs); ++} ++ ++inline uint128 operator%(uint128 lhs, uint128 rhs) { ++ return static_cast(lhs) % ++ static_cast(rhs); ++} ++#endif ++ ++// Increment/decrement operators. ++ ++inline uint128 uint128::operator++(int) { ++ uint128 tmp(*this); ++ *this += 1; ++ return tmp; ++} ++ ++inline uint128 uint128::operator--(int) { ++ uint128 tmp(*this); ++ *this -= 1; ++ return tmp; ++} ++ ++inline uint128& uint128::operator++() { ++ *this += 1; ++ return *this; ++} ++ ++inline uint128& uint128::operator--() { ++ *this -= 1; ++ return *this; ++} ++ ++constexpr int128 MakeInt128(int64_t high, uint64_t low) { ++ return int128(high, low); ++} ++ ++// Assignment from integer types. ++inline int128& int128::operator=(int v) { ++ return *this = int128(v); ++} ++ ++inline int128& int128::operator=(unsigned int v) { ++ return *this = int128(v); ++} ++ ++inline int128& int128::operator=(long v) { // NOLINT(runtime/int) ++ return *this = int128(v); ++} ++ ++// NOLINTNEXTLINE(runtime/int) ++inline int128& int128::operator=(unsigned long v) { ++ return *this = int128(v); ++} ++ ++// NOLINTNEXTLINE(runtime/int) ++inline int128& int128::operator=(long long v) { ++ return *this = int128(v); ++} ++ ++// NOLINTNEXTLINE(runtime/int) ++inline int128& int128::operator=(unsigned long long v) { ++ return *this = int128(v); ++} ++ ++// Arithmetic operators. ++ ++int128 operator+(int128 lhs, int128 rhs); ++int128 operator-(int128 lhs, int128 rhs); ++int128 operator*(int128 lhs, int128 rhs); ++int128 operator/(int128 lhs, int128 rhs); ++int128 operator%(int128 lhs, int128 rhs); ++int128 operator|(int128 lhs, int128 rhs); ++int128 operator&(int128 lhs, int128 rhs); ++int128 operator^(int128 lhs, int128 rhs); ++int128 operator<<(int128 lhs, int amount); ++int128 operator>>(int128 lhs, int amount); ++ ++inline int128& int128::operator+=(int128 other) { ++ *this = *this + other; ++ return *this; ++} ++ ++inline int128& int128::operator-=(int128 other) { ++ *this = *this - other; ++ return *this; ++} ++ ++inline int128& int128::operator*=(int128 other) { ++ *this = *this * other; ++ return *this; ++} ++ ++inline int128& int128::operator/=(int128 other) { ++ *this = *this / other; ++ return *this; ++} ++ ++inline int128& int128::operator%=(int128 other) { ++ *this = *this % other; ++ return *this; ++} ++ ++inline int128& int128::operator|=(int128 other) { ++ *this = *this | other; ++ return *this; ++} ++ ++inline int128& int128::operator&=(int128 other) { ++ *this = *this & other; ++ return *this; ++} ++ ++inline int128& int128::operator^=(int128 other) { ++ *this = *this ^ other; ++ return *this; ++} ++ ++inline int128& int128::operator<<=(int amount) { ++ *this = *this << amount; ++ return *this; ++} ++ ++inline int128& int128::operator>>=(int amount) { ++ *this = *this >> amount; ++ return *this; ++} ++ ++namespace int128_internal { ++ ++// Casts from unsigned to signed while preserving the underlying binary ++// representation. ++constexpr int64_t BitCastToSigned(uint64_t v) { ++ // Casting an unsigned integer to a signed integer of the same ++ // width is implementation defined behavior if the source value would not fit ++ // in the destination type. We step around it with a roundtrip bitwise not ++ // operation to make sure this function remains constexpr. Clang, GCC, and ++ // MSVC optimize this to a no-op on x86-64. ++ return v & (uint64_t{1} << 63) ? ~static_cast(~v) ++ : static_cast(v); ++} ++ ++} // namespace int128_internal ++ ++#if defined(ABSL_HAVE_INTRINSIC_INT128) ++#include "absl/numeric/int128_have_intrinsic.inc" // IWYU pragma: export ++#else // ABSL_HAVE_INTRINSIC_INT128 ++#include "absl/numeric/int128_no_intrinsic.inc" // IWYU pragma: export ++#endif // ABSL_HAVE_INTRINSIC_INT128 ++ ++ABSL_NAMESPACE_END ++} // namespace absl ++ ++#undef ABSL_INTERNAL_WCHAR_T ++ ++#endif // ABSL_NUMERIC_INT128_H_ +diff --git a/extern/int128/absl/numeric/int128_have_intrinsic.inc b/extern/int128/absl/numeric/int128_have_intrinsic.inc +new file mode 100644 +index 0000000000..d6c76dd320 +--- /dev/null ++++ b/extern/int128/absl/numeric/int128_have_intrinsic.inc +@@ -0,0 +1,302 @@ ++// ++// Copyright 2017 The Abseil Authors. ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// https://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++// This file contains :int128 implementation details that depend on internal ++// representation when ABSL_HAVE_INTRINSIC_INT128 is defined. This file is ++// included by int128.h and relies on ABSL_INTERNAL_WCHAR_T being defined. ++ ++namespace int128_internal { ++ ++// Casts from unsigned to signed while preserving the underlying binary ++// representation. ++constexpr __int128 BitCastToSigned(unsigned __int128 v) { ++ // Casting an unsigned integer to a signed integer of the same ++ // width is implementation defined behavior if the source value would not fit ++ // in the destination type. We step around it with a roundtrip bitwise not ++ // operation to make sure this function remains constexpr. Clang and GCC ++ // optimize this to a no-op on x86-64. ++ return v & (static_cast(1) << 127) ++ ? ~static_cast<__int128>(~v) ++ : static_cast<__int128>(v); ++} ++ ++} // namespace int128_internal ++ ++inline int128& int128::operator=(__int128 v) { ++ v_ = v; ++ return *this; ++} ++ ++constexpr uint64_t Int128Low64(int128 v) { ++ return static_cast(v.v_ & ~uint64_t{0}); ++} ++ ++constexpr int64_t Int128High64(int128 v) { ++ // Initially cast to unsigned to prevent a right shift on a negative value. ++ return int128_internal::BitCastToSigned( ++ static_cast(static_cast(v.v_) >> 64)); ++} ++ ++constexpr int128::int128(int64_t high, uint64_t low) ++ // Initially cast to unsigned to prevent a left shift that overflows. ++ : v_(int128_internal::BitCastToSigned(static_cast(high) ++ << 64) | ++ low) {} ++ ++ ++constexpr int128::int128(int v) : v_{v} {} ++ ++constexpr int128::int128(long v) : v_{v} {} // NOLINT(runtime/int) ++ ++constexpr int128::int128(long long v) : v_{v} {} // NOLINT(runtime/int) ++ ++constexpr int128::int128(__int128 v) : v_{v} {} ++ ++constexpr int128::int128(unsigned int v) : v_{v} {} ++ ++constexpr int128::int128(unsigned long v) : v_{v} {} // NOLINT(runtime/int) ++ ++// NOLINTNEXTLINE(runtime/int) ++constexpr int128::int128(unsigned long long v) : v_{v} {} ++ ++constexpr int128::int128(unsigned __int128 v) : v_{static_cast<__int128>(v)} {} ++ ++inline int128::int128(float v) { ++ v_ = static_cast<__int128>(v); ++} ++ ++inline int128::int128(double v) { ++ v_ = static_cast<__int128>(v); ++} ++ ++inline int128::int128(long double v) { ++ v_ = static_cast<__int128>(v); ++} ++ ++constexpr int128::int128(uint128 v) : v_{static_cast<__int128>(v)} {} ++ ++constexpr int128::operator bool() const { return static_cast(v_); } ++ ++constexpr int128::operator char() const { return static_cast(v_); } ++ ++constexpr int128::operator signed char() const { ++ return static_cast(v_); ++} ++ ++constexpr int128::operator unsigned char() const { ++ return static_cast(v_); ++} ++ ++constexpr int128::operator char16_t() const { ++ return static_cast(v_); ++} ++ ++constexpr int128::operator char32_t() const { ++ return static_cast(v_); ++} ++ ++constexpr int128::operator ABSL_INTERNAL_WCHAR_T() const { ++ return static_cast(v_); ++} ++ ++constexpr int128::operator short() const { // NOLINT(runtime/int) ++ return static_cast(v_); // NOLINT(runtime/int) ++} ++ ++constexpr int128::operator unsigned short() const { // NOLINT(runtime/int) ++ return static_cast(v_); // NOLINT(runtime/int) ++} ++ ++constexpr int128::operator int() const { ++ return static_cast(v_); ++} ++ ++constexpr int128::operator unsigned int() const { ++ return static_cast(v_); ++} ++ ++constexpr int128::operator long() const { // NOLINT(runtime/int) ++ return static_cast(v_); // NOLINT(runtime/int) ++} ++ ++constexpr int128::operator unsigned long() const { // NOLINT(runtime/int) ++ return static_cast(v_); // NOLINT(runtime/int) ++} ++ ++constexpr int128::operator long long() const { // NOLINT(runtime/int) ++ return static_cast(v_); // NOLINT(runtime/int) ++} ++ ++constexpr int128::operator unsigned long long() const { // NOLINT(runtime/int) ++ return static_cast(v_); // NOLINT(runtime/int) ++} ++ ++constexpr int128::operator __int128() const { return v_; } ++ ++constexpr int128::operator unsigned __int128() const { ++ return static_cast(v_); ++} ++ ++// Clang on PowerPC sometimes produces incorrect __int128 to floating point ++// conversions. In that case, we do the conversion with a similar implementation ++// to the conversion operators in int128_no_intrinsic.inc. ++#if defined(__clang__) && !defined(__ppc64__) ++inline int128::operator float() const { return static_cast(v_); } ++ ++inline int128::operator double () const { return static_cast(v_); } ++ ++inline int128::operator long double() const { ++ return static_cast(v_); ++} ++ ++#else // Clang on PowerPC ++// Forward declaration for conversion operators to floating point types. ++int128 operator-(int128 v); ++bool operator!=(int128 lhs, int128 rhs); ++ ++inline int128::operator float() const { ++ // We must convert the absolute value and then negate as needed, because ++ // floating point types are typically sign-magnitude. Otherwise, the ++ // difference between the high and low 64 bits when interpreted as two's ++ // complement overwhelms the precision of the mantissa. ++ // ++ // Also check to make sure we don't negate Int128Min() ++ return v_ < 0 && *this != Int128Min() ++ ? -static_cast(-*this) ++ : static_cast(Int128Low64(*this)) + ++ std::ldexp(static_cast(Int128High64(*this)), 64); ++} ++ ++inline int128::operator double() const { ++ // See comment in int128::operator float() above. ++ return v_ < 0 && *this != Int128Min() ++ ? -static_cast(-*this) ++ : static_cast(Int128Low64(*this)) + ++ std::ldexp(static_cast(Int128High64(*this)), 64); ++} ++ ++inline int128::operator long double() const { ++ // See comment in int128::operator float() above. ++ return v_ < 0 && *this != Int128Min() ++ ? -static_cast(-*this) ++ : static_cast(Int128Low64(*this)) + ++ std::ldexp(static_cast(Int128High64(*this)), ++ 64); ++} ++#endif // Clang on PowerPC ++ ++// Comparison operators. ++ ++inline bool operator==(int128 lhs, int128 rhs) { ++ return static_cast<__int128>(lhs) == static_cast<__int128>(rhs); ++} ++ ++inline bool operator!=(int128 lhs, int128 rhs) { ++ return static_cast<__int128>(lhs) != static_cast<__int128>(rhs); ++} ++ ++inline bool operator<(int128 lhs, int128 rhs) { ++ return static_cast<__int128>(lhs) < static_cast<__int128>(rhs); ++} ++ ++inline bool operator>(int128 lhs, int128 rhs) { ++ return static_cast<__int128>(lhs) > static_cast<__int128>(rhs); ++} ++ ++inline bool operator<=(int128 lhs, int128 rhs) { ++ return static_cast<__int128>(lhs) <= static_cast<__int128>(rhs); ++} ++ ++inline bool operator>=(int128 lhs, int128 rhs) { ++ return static_cast<__int128>(lhs) >= static_cast<__int128>(rhs); ++} ++ ++// Unary operators. ++ ++inline int128 operator-(int128 v) { ++ return -static_cast<__int128>(v); ++} ++ ++inline bool operator!(int128 v) { ++ return !static_cast<__int128>(v); ++} ++ ++inline int128 operator~(int128 val) { ++ return ~static_cast<__int128>(val); ++} ++ ++// Arithmetic operators. ++ ++inline int128 operator+(int128 lhs, int128 rhs) { ++ return static_cast<__int128>(lhs) + static_cast<__int128>(rhs); ++} ++ ++inline int128 operator-(int128 lhs, int128 rhs) { ++ return static_cast<__int128>(lhs) - static_cast<__int128>(rhs); ++} ++ ++inline int128 operator*(int128 lhs, int128 rhs) { ++ return static_cast<__int128>(lhs) * static_cast<__int128>(rhs); ++} ++ ++inline int128 operator/(int128 lhs, int128 rhs) { ++ return static_cast<__int128>(lhs) / static_cast<__int128>(rhs); ++} ++ ++inline int128 operator%(int128 lhs, int128 rhs) { ++ return static_cast<__int128>(lhs) % static_cast<__int128>(rhs); ++} ++ ++inline int128 int128::operator++(int) { ++ int128 tmp(*this); ++ ++v_; ++ return tmp; ++} ++ ++inline int128 int128::operator--(int) { ++ int128 tmp(*this); ++ --v_; ++ return tmp; ++} ++ ++inline int128& int128::operator++() { ++ ++v_; ++ return *this; ++} ++ ++inline int128& int128::operator--() { ++ --v_; ++ return *this; ++} ++ ++inline int128 operator|(int128 lhs, int128 rhs) { ++ return static_cast<__int128>(lhs) | static_cast<__int128>(rhs); ++} ++ ++inline int128 operator&(int128 lhs, int128 rhs) { ++ return static_cast<__int128>(lhs) & static_cast<__int128>(rhs); ++} ++ ++inline int128 operator^(int128 lhs, int128 rhs) { ++ return static_cast<__int128>(lhs) ^ static_cast<__int128>(rhs); ++} ++ ++inline int128 operator<<(int128 lhs, int amount) { ++ return static_cast<__int128>(lhs) << amount; ++} ++ ++inline int128 operator>>(int128 lhs, int amount) { ++ return static_cast<__int128>(lhs) >> amount; ++} +diff --git a/extern/int128/absl/numeric/int128_no_intrinsic.inc b/extern/int128/absl/numeric/int128_no_intrinsic.inc +new file mode 100644 +index 0000000000..c753771ae7 +--- /dev/null ++++ b/extern/int128/absl/numeric/int128_no_intrinsic.inc +@@ -0,0 +1,308 @@ ++// ++// Copyright 2017 The Abseil Authors. ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// https://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++// This file contains :int128 implementation details that depend on internal ++// representation when ABSL_HAVE_INTRINSIC_INT128 is *not* defined. This file ++// is included by int128.h and relies on ABSL_INTERNAL_WCHAR_T being defined. ++ ++constexpr uint64_t Int128Low64(int128 v) { return v.lo_; } ++ ++constexpr int64_t Int128High64(int128 v) { return v.hi_; } ++ ++#if defined(ABSL_IS_LITTLE_ENDIAN) ++ ++constexpr int128::int128(int64_t high, uint64_t low) : ++ lo_(low), hi_(high) {} ++ ++constexpr int128::int128(int v) ++ : lo_{static_cast(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {} ++constexpr int128::int128(long v) // NOLINT(runtime/int) ++ : lo_{static_cast(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {} ++constexpr int128::int128(long long v) // NOLINT(runtime/int) ++ : lo_{static_cast(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {} ++ ++constexpr int128::int128(unsigned int v) : lo_{v}, hi_{0} {} ++// NOLINTNEXTLINE(runtime/int) ++constexpr int128::int128(unsigned long v) : lo_{v}, hi_{0} {} ++// NOLINTNEXTLINE(runtime/int) ++constexpr int128::int128(unsigned long long v) : lo_{v}, hi_{0} {} ++ ++constexpr int128::int128(uint128 v) ++ : lo_{Uint128Low64(v)}, hi_{static_cast(Uint128High64(v))} {} ++ ++#elif defined(ABSL_IS_BIG_ENDIAN) ++ ++constexpr int128::int128(int64_t high, uint64_t low) : ++ hi_{high}, lo_{low} {} ++ ++constexpr int128::int128(int v) ++ : hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast(v)} {} ++constexpr int128::int128(long v) // NOLINT(runtime/int) ++ : hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast(v)} {} ++constexpr int128::int128(long long v) // NOLINT(runtime/int) ++ : hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast(v)} {} ++ ++constexpr int128::int128(unsigned int v) : hi_{0}, lo_{v} {} ++// NOLINTNEXTLINE(runtime/int) ++constexpr int128::int128(unsigned long v) : hi_{0}, lo_{v} {} ++// NOLINTNEXTLINE(runtime/int) ++constexpr int128::int128(unsigned long long v) : hi_{0}, lo_{v} {} ++ ++constexpr int128::int128(uint128 v) ++ : hi_{static_cast(Uint128High64(v))}, lo_{Uint128Low64(v)} {} ++ ++#else // byte order ++#error "Unsupported byte order: must be little-endian or big-endian." ++#endif // byte order ++ ++constexpr int128::operator bool() const { return lo_ || hi_; } ++ ++constexpr int128::operator char() const { ++ // NOLINTNEXTLINE(runtime/int) ++ return static_cast(static_cast(*this)); ++} ++ ++constexpr int128::operator signed char() const { ++ // NOLINTNEXTLINE(runtime/int) ++ return static_cast(static_cast(*this)); ++} ++ ++constexpr int128::operator unsigned char() const { ++ return static_cast(lo_); ++} ++ ++constexpr int128::operator char16_t() const { ++ return static_cast(lo_); ++} ++ ++constexpr int128::operator char32_t() const { ++ return static_cast(lo_); ++} ++ ++constexpr int128::operator ABSL_INTERNAL_WCHAR_T() const { ++ // NOLINTNEXTLINE(runtime/int) ++ return static_cast(static_cast(*this)); ++} ++ ++constexpr int128::operator short() const { // NOLINT(runtime/int) ++ // NOLINTNEXTLINE(runtime/int) ++ return static_cast(static_cast(*this)); ++} ++ ++constexpr int128::operator unsigned short() const { // NOLINT(runtime/int) ++ return static_cast(lo_); // NOLINT(runtime/int) ++} ++ ++constexpr int128::operator int() const { ++ // NOLINTNEXTLINE(runtime/int) ++ return static_cast(static_cast(*this)); ++} ++ ++constexpr int128::operator unsigned int() const { ++ return static_cast(lo_); ++} ++ ++constexpr int128::operator long() const { // NOLINT(runtime/int) ++ // NOLINTNEXTLINE(runtime/int) ++ return static_cast(static_cast(*this)); ++} ++ ++constexpr int128::operator unsigned long() const { // NOLINT(runtime/int) ++ return static_cast(lo_); // NOLINT(runtime/int) ++} ++ ++constexpr int128::operator long long() const { // NOLINT(runtime/int) ++ // We don't bother checking the value of hi_. If *this < 0, lo_'s high bit ++ // must be set in order for the value to fit into a long long. Conversely, if ++ // lo_'s high bit is set, *this must be < 0 for the value to fit. ++ return int128_internal::BitCastToSigned(lo_); ++} ++ ++constexpr int128::operator unsigned long long() const { // NOLINT(runtime/int) ++ return static_cast(lo_); // NOLINT(runtime/int) ++} ++ ++// Forward declaration for conversion operators to floating point types. ++int128 operator-(int128 v); ++bool operator!=(int128 lhs, int128 rhs); ++ ++inline int128::operator float() const { ++ // We must convert the absolute value and then negate as needed, because ++ // floating point types are typically sign-magnitude. Otherwise, the ++ // difference between the high and low 64 bits when interpreted as two's ++ // complement overwhelms the precision of the mantissa. ++ // ++ // Also check to make sure we don't negate Int128Min() ++ return hi_ < 0 && *this != Int128Min() ++ ? -static_cast(-*this) ++ : static_cast(lo_) + ++ std::ldexp(static_cast(hi_), 64); ++} ++ ++inline int128::operator double() const { ++ // See comment in int128::operator float() above. ++ return hi_ < 0 && *this != Int128Min() ++ ? -static_cast(-*this) ++ : static_cast(lo_) + ++ std::ldexp(static_cast(hi_), 64); ++} ++ ++inline int128::operator long double() const { ++ // See comment in int128::operator float() above. ++ return hi_ < 0 && *this != Int128Min() ++ ? -static_cast(-*this) ++ : static_cast(lo_) + ++ std::ldexp(static_cast(hi_), 64); ++} ++ ++// Comparison operators. ++ ++inline bool operator==(int128 lhs, int128 rhs) { ++ return (Int128Low64(lhs) == Int128Low64(rhs) && ++ Int128High64(lhs) == Int128High64(rhs)); ++} ++ ++inline bool operator!=(int128 lhs, int128 rhs) { ++ return !(lhs == rhs); ++} ++ ++inline bool operator<(int128 lhs, int128 rhs) { ++ return (Int128High64(lhs) == Int128High64(rhs)) ++ ? (Int128Low64(lhs) < Int128Low64(rhs)) ++ : (Int128High64(lhs) < Int128High64(rhs)); ++} ++ ++inline bool operator>(int128 lhs, int128 rhs) { ++ return (Int128High64(lhs) == Int128High64(rhs)) ++ ? (Int128Low64(lhs) > Int128Low64(rhs)) ++ : (Int128High64(lhs) > Int128High64(rhs)); ++} ++ ++inline bool operator<=(int128 lhs, int128 rhs) { ++ return !(lhs > rhs); ++} ++ ++inline bool operator>=(int128 lhs, int128 rhs) { ++ return !(lhs < rhs); ++} ++ ++// Unary operators. ++ ++inline int128 operator-(int128 v) { ++ int64_t hi = ~Int128High64(v); ++ uint64_t lo = ~Int128Low64(v) + 1; ++ if (lo == 0) ++hi; // carry ++ return MakeInt128(hi, lo); ++} ++ ++inline bool operator!(int128 v) { ++ return !Int128Low64(v) && !Int128High64(v); ++} ++ ++inline int128 operator~(int128 val) { ++ return MakeInt128(~Int128High64(val), ~Int128Low64(val)); ++} ++ ++// Arithmetic operators. ++ ++inline int128 operator+(int128 lhs, int128 rhs) { ++ int128 result = MakeInt128(Int128High64(lhs) + Int128High64(rhs), ++ Int128Low64(lhs) + Int128Low64(rhs)); ++ if (Int128Low64(result) < Int128Low64(lhs)) { // check for carry ++ return MakeInt128(Int128High64(result) + 1, Int128Low64(result)); ++ } ++ return result; ++} ++ ++inline int128 operator-(int128 lhs, int128 rhs) { ++ int128 result = MakeInt128(Int128High64(lhs) - Int128High64(rhs), ++ Int128Low64(lhs) - Int128Low64(rhs)); ++ if (Int128Low64(lhs) < Int128Low64(rhs)) { // check for carry ++ return MakeInt128(Int128High64(result) - 1, Int128Low64(result)); ++ } ++ return result; ++} ++ ++inline int128 operator*(int128 lhs, int128 rhs) { ++ uint128 result = uint128(lhs) * rhs; ++ return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(result)), ++ Uint128Low64(result)); ++} ++ ++inline int128 int128::operator++(int) { ++ int128 tmp(*this); ++ *this += 1; ++ return tmp; ++} ++ ++inline int128 int128::operator--(int) { ++ int128 tmp(*this); ++ *this -= 1; ++ return tmp; ++} ++ ++inline int128& int128::operator++() { ++ *this += 1; ++ return *this; ++} ++ ++inline int128& int128::operator--() { ++ *this -= 1; ++ return *this; ++} ++ ++inline int128 operator|(int128 lhs, int128 rhs) { ++ return MakeInt128(Int128High64(lhs) | Int128High64(rhs), ++ Int128Low64(lhs) | Int128Low64(rhs)); ++} ++ ++inline int128 operator&(int128 lhs, int128 rhs) { ++ return MakeInt128(Int128High64(lhs) & Int128High64(rhs), ++ Int128Low64(lhs) & Int128Low64(rhs)); ++} ++ ++inline int128 operator^(int128 lhs, int128 rhs) { ++ return MakeInt128(Int128High64(lhs) ^ Int128High64(rhs), ++ Int128Low64(lhs) ^ Int128Low64(rhs)); ++} ++ ++inline int128 operator<<(int128 lhs, int amount) { ++ // uint64_t shifts of >= 64 are undefined, so we need some special-casing. ++ if (amount < 64) { ++ if (amount != 0) { ++ return MakeInt128( ++ (Int128High64(lhs) << amount) | ++ static_cast(Int128Low64(lhs) >> (64 - amount)), ++ Int128Low64(lhs) << amount); ++ } ++ return lhs; ++ } ++ return MakeInt128(static_cast(Int128Low64(lhs) << (amount - 64)), 0); ++} ++ ++inline int128 operator>>(int128 lhs, int amount) { ++ // uint64_t shifts of >= 64 are undefined, so we need some special-casing. ++ if (amount < 64) { ++ if (amount != 0) { ++ return MakeInt128( ++ Int128High64(lhs) >> amount, ++ (Int128Low64(lhs) >> amount) | ++ (static_cast(Int128High64(lhs)) << (64 - amount))); ++ } ++ return lhs; ++ } ++ return MakeInt128(0, ++ static_cast(Int128High64(lhs) >> (amount - 64))); ++} +diff --git a/extern/int128/absl/numeric/internal/bits.h b/extern/int128/absl/numeric/internal/bits.h +new file mode 100644 +index 0000000000..bfef06bce1 +--- /dev/null ++++ b/extern/int128/absl/numeric/internal/bits.h +@@ -0,0 +1,358 @@ ++// Copyright 2020 The Abseil Authors ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// https://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++#ifndef ABSL_NUMERIC_INTERNAL_BITS_H_ ++#define ABSL_NUMERIC_INTERNAL_BITS_H_ ++ ++#include ++#include ++#include ++ ++// Clang on Windows has __builtin_clzll; otherwise we need to use the ++// windows intrinsic functions. ++#if defined(_MSC_VER) && !defined(__clang__) ++#include ++#endif ++ ++#include "absl/base/attributes.h" ++#include "absl/base/config.h" ++ ++#if defined(__GNUC__) && !defined(__clang__) ++// GCC ++#define ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(x) 1 ++#else ++#define ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(x) ABSL_HAVE_BUILTIN(x) ++#endif ++ ++#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcountl) && \ ++ ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcountll) ++#define ABSL_INTERNAL_CONSTEXPR_POPCOUNT constexpr ++#define ABSL_INTERNAL_HAS_CONSTEXPR_POPCOUNT 1 ++#else ++#define ABSL_INTERNAL_CONSTEXPR_POPCOUNT ++#define ABSL_INTERNAL_HAS_CONSTEXPR_POPCOUNT 0 ++#endif ++ ++#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clz) && \ ++ ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clzll) ++#define ABSL_INTERNAL_CONSTEXPR_CLZ constexpr ++#define ABSL_INTERNAL_HAS_CONSTEXPR_CLZ 1 ++#else ++#define ABSL_INTERNAL_CONSTEXPR_CLZ ++#define ABSL_INTERNAL_HAS_CONSTEXPR_CLZ 0 ++#endif ++ ++#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctz) && \ ++ ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctzll) ++#define ABSL_INTERNAL_CONSTEXPR_CTZ constexpr ++#define ABSL_INTERNAL_HAS_CONSTEXPR_CTZ 1 ++#else ++#define ABSL_INTERNAL_CONSTEXPR_CTZ ++#define ABSL_INTERNAL_HAS_CONSTEXPR_CTZ 0 ++#endif ++ ++namespace absl { ++ABSL_NAMESPACE_BEGIN ++namespace numeric_internal { ++ ++constexpr bool IsPowerOf2(unsigned int x) noexcept { ++ return x != 0 && (x & (x - 1)) == 0; ++} ++ ++template ++ABSL_MUST_USE_RESULT ABSL_ATTRIBUTE_ALWAYS_INLINE constexpr T RotateRight( ++ T x, int s) noexcept { ++ static_assert(std::is_unsigned::value, "T must be unsigned"); ++ static_assert(IsPowerOf2(std::numeric_limits::digits), ++ "T must have a power-of-2 size"); ++ ++ return static_cast(x >> (s & (std::numeric_limits::digits - 1))) | ++ static_cast(x << ((-s) & (std::numeric_limits::digits - 1))); ++} ++ ++template ++ABSL_MUST_USE_RESULT ABSL_ATTRIBUTE_ALWAYS_INLINE constexpr T RotateLeft( ++ T x, int s) noexcept { ++ static_assert(std::is_unsigned::value, "T must be unsigned"); ++ static_assert(IsPowerOf2(std::numeric_limits::digits), ++ "T must have a power-of-2 size"); ++ ++ return static_cast(x << (s & (std::numeric_limits::digits - 1))) | ++ static_cast(x >> ((-s) & (std::numeric_limits::digits - 1))); ++} ++ ++ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline int ++Popcount32(uint32_t x) noexcept { ++#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcount) ++ static_assert(sizeof(unsigned int) == sizeof(x), ++ "__builtin_popcount does not take 32-bit arg"); ++ return __builtin_popcount(x); ++#else ++ x -= ((x >> 1) & 0x55555555); ++ x = ((x >> 2) & 0x33333333) + (x & 0x33333333); ++ return static_cast((((x + (x >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24); ++#endif ++} ++ ++ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline int ++Popcount64(uint64_t x) noexcept { ++#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcountll) ++ static_assert(sizeof(unsigned long long) == sizeof(x), // NOLINT(runtime/int) ++ "__builtin_popcount does not take 64-bit arg"); ++ return __builtin_popcountll(x); ++#else ++ x -= (x >> 1) & 0x5555555555555555ULL; ++ x = ((x >> 2) & 0x3333333333333333ULL) + (x & 0x3333333333333333ULL); ++ return static_cast( ++ (((x + (x >> 4)) & 0xF0F0F0F0F0F0F0FULL) * 0x101010101010101ULL) >> 56); ++#endif ++} ++ ++template ++ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline int ++Popcount(T x) noexcept { ++ static_assert(std::is_unsigned::value, "T must be unsigned"); ++ static_assert(IsPowerOf2(std::numeric_limits::digits), ++ "T must have a power-of-2 size"); ++ static_assert(sizeof(x) <= sizeof(uint64_t), "T is too large"); ++ return sizeof(x) <= sizeof(uint32_t) ? Popcount32(x) : Popcount64(x); ++} ++ ++ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int ++CountLeadingZeroes32(uint32_t x) { ++#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clz) ++ // Use __builtin_clz, which uses the following instructions: ++ // x86: bsr, lzcnt ++ // ARM64: clz ++ // PPC: cntlzd ++ ++ static_assert(sizeof(unsigned int) == sizeof(x), ++ "__builtin_clz does not take 32-bit arg"); ++ // Handle 0 as a special case because __builtin_clz(0) is undefined. ++ return x == 0 ? 32 : __builtin_clz(x); ++#elif defined(_MSC_VER) && !defined(__clang__) ++ unsigned long result = 0; // NOLINT(runtime/int) ++ if (_BitScanReverse(&result, x)) { ++ return 31 - result; ++ } ++ return 32; ++#else ++ int zeroes = 28; ++ if (x >> 16) { ++ zeroes -= 16; ++ x >>= 16; ++ } ++ if (x >> 8) { ++ zeroes -= 8; ++ x >>= 8; ++ } ++ if (x >> 4) { ++ zeroes -= 4; ++ x >>= 4; ++ } ++ return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[x] + zeroes; ++#endif ++} ++ ++ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int ++CountLeadingZeroes16(uint16_t x) { ++#if ABSL_HAVE_BUILTIN(__builtin_clzs) ++ static_assert(sizeof(unsigned short) == sizeof(x), // NOLINT(runtime/int) ++ "__builtin_clzs does not take 16-bit arg"); ++ return x == 0 ? 16 : __builtin_clzs(x); ++#else ++ return CountLeadingZeroes32(x) - 16; ++#endif ++} ++ ++ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int ++CountLeadingZeroes64(uint64_t x) { ++#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clzll) ++ // Use __builtin_clzll, which uses the following instructions: ++ // x86: bsr, lzcnt ++ // ARM64: clz ++ // PPC: cntlzd ++ static_assert(sizeof(unsigned long long) == sizeof(x), // NOLINT(runtime/int) ++ "__builtin_clzll does not take 64-bit arg"); ++ ++ // Handle 0 as a special case because __builtin_clzll(0) is undefined. ++ return x == 0 ? 64 : __builtin_clzll(x); ++#elif defined(_MSC_VER) && !defined(__clang__) && \ ++ (defined(_M_X64) || defined(_M_ARM64)) ++ // MSVC does not have __buitin_clzll. Use _BitScanReverse64. ++ unsigned long result = 0; // NOLINT(runtime/int) ++ if (_BitScanReverse64(&result, x)) { ++ return 63 - result; ++ } ++ return 64; ++#elif defined(_MSC_VER) && !defined(__clang__) ++ // MSVC does not have __buitin_clzll. Compose two calls to _BitScanReverse ++ unsigned long result = 0; // NOLINT(runtime/int) ++ if ((x >> 32) && ++ _BitScanReverse(&result, static_cast(x >> 32))) { ++ return 31 - result; ++ } ++ if (_BitScanReverse(&result, static_cast(x))) { ++ return 63 - result; ++ } ++ return 64; ++#else ++ int zeroes = 60; ++ if (x >> 32) { ++ zeroes -= 32; ++ x >>= 32; ++ } ++ if (x >> 16) { ++ zeroes -= 16; ++ x >>= 16; ++ } ++ if (x >> 8) { ++ zeroes -= 8; ++ x >>= 8; ++ } ++ if (x >> 4) { ++ zeroes -= 4; ++ x >>= 4; ++ } ++ return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[x] + zeroes; ++#endif ++} ++ ++template ++ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int ++CountLeadingZeroes(T x) { ++ static_assert(std::is_unsigned::value, "T must be unsigned"); ++ static_assert(IsPowerOf2(std::numeric_limits::digits), ++ "T must have a power-of-2 size"); ++ static_assert(sizeof(T) <= sizeof(uint64_t), "T too large"); ++ return sizeof(T) <= sizeof(uint16_t) ++ ? CountLeadingZeroes16(static_cast(x)) - ++ (std::numeric_limits::digits - ++ std::numeric_limits::digits) ++ : (sizeof(T) <= sizeof(uint32_t) ++ ? CountLeadingZeroes32(static_cast(x)) - ++ (std::numeric_limits::digits - ++ std::numeric_limits::digits) ++ : CountLeadingZeroes64(x)); ++} ++ ++ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int ++CountTrailingZeroesNonzero32(uint32_t x) { ++#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctz) ++ static_assert(sizeof(unsigned int) == sizeof(x), ++ "__builtin_ctz does not take 32-bit arg"); ++ return __builtin_ctz(x); ++#elif defined(_MSC_VER) && !defined(__clang__) ++ unsigned long result = 0; // NOLINT(runtime/int) ++ _BitScanForward(&result, x); ++ return result; ++#else ++ int c = 31; ++ x &= ~x + 1; ++ if (x & 0x0000FFFF) c -= 16; ++ if (x & 0x00FF00FF) c -= 8; ++ if (x & 0x0F0F0F0F) c -= 4; ++ if (x & 0x33333333) c -= 2; ++ if (x & 0x55555555) c -= 1; ++ return c; ++#endif ++} ++ ++ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int ++CountTrailingZeroesNonzero64(uint64_t x) { ++#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctzll) ++ static_assert(sizeof(unsigned long long) == sizeof(x), // NOLINT(runtime/int) ++ "__builtin_ctzll does not take 64-bit arg"); ++ return __builtin_ctzll(x); ++#elif defined(_MSC_VER) && !defined(__clang__) && \ ++ (defined(_M_X64) || defined(_M_ARM64)) ++ unsigned long result = 0; // NOLINT(runtime/int) ++ _BitScanForward64(&result, x); ++ return result; ++#elif defined(_MSC_VER) && !defined(__clang__) ++ unsigned long result = 0; // NOLINT(runtime/int) ++ if (static_cast(x) == 0) { ++ _BitScanForward(&result, static_cast(x >> 32)); ++ return result + 32; ++ } ++ _BitScanForward(&result, static_cast(x)); ++ return result; ++#else ++ int c = 63; ++ x &= ~x + 1; ++ if (x & 0x00000000FFFFFFFF) c -= 32; ++ if (x & 0x0000FFFF0000FFFF) c -= 16; ++ if (x & 0x00FF00FF00FF00FF) c -= 8; ++ if (x & 0x0F0F0F0F0F0F0F0F) c -= 4; ++ if (x & 0x3333333333333333) c -= 2; ++ if (x & 0x5555555555555555) c -= 1; ++ return c; ++#endif ++} ++ ++ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int ++CountTrailingZeroesNonzero16(uint16_t x) { ++#if ABSL_HAVE_BUILTIN(__builtin_ctzs) ++ static_assert(sizeof(unsigned short) == sizeof(x), // NOLINT(runtime/int) ++ "__builtin_ctzs does not take 16-bit arg"); ++ return __builtin_ctzs(x); ++#else ++ return CountTrailingZeroesNonzero32(x); ++#endif ++} ++ ++template ++ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int ++CountTrailingZeroes(T x) noexcept { ++ static_assert(std::is_unsigned::value, "T must be unsigned"); ++ static_assert(IsPowerOf2(std::numeric_limits::digits), ++ "T must have a power-of-2 size"); ++ static_assert(sizeof(T) <= sizeof(uint64_t), "T too large"); ++ return x == 0 ? std::numeric_limits::digits ++ : (sizeof(T) <= sizeof(uint16_t) ++ ? CountTrailingZeroesNonzero16(static_cast(x)) ++ : (sizeof(T) <= sizeof(uint32_t) ++ ? CountTrailingZeroesNonzero32( ++ static_cast(x)) ++ : CountTrailingZeroesNonzero64(x))); ++} ++ ++// If T is narrower than unsigned, T{1} << bit_width will be promoted. We ++// want to force it to wraparound so that bit_ceil of an invalid value are not ++// core constant expressions. ++template ++ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline ++ typename std::enable_if::value, T>::type ++ BitCeilPromotionHelper(T x, T promotion) { ++ return (T{1} << (x + promotion)) >> promotion; ++} ++ ++template ++ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline ++ typename std::enable_if::value, T>::type ++ BitCeilNonPowerOf2(T x) { ++ // If T is narrower than unsigned, it undergoes promotion to unsigned when we ++ // shift. We calculate the number of bits added by the wider type. ++ return BitCeilPromotionHelper( ++ static_cast(std::numeric_limits::digits - CountLeadingZeroes(x)), ++ T{sizeof(T) >= sizeof(unsigned) ? 0 ++ : std::numeric_limits::digits - ++ std::numeric_limits::digits}); ++} ++ ++} // namespace numeric_internal ++ABSL_NAMESPACE_END ++} // namespace absl ++ ++#endif // ABSL_NUMERIC_INTERNAL_BITS_H_ +diff --git a/extern/int128/absl/numeric/internal/representation.h b/extern/int128/absl/numeric/internal/representation.h +new file mode 100644 +index 0000000000..82d332fdde +--- /dev/null ++++ b/extern/int128/absl/numeric/internal/representation.h +@@ -0,0 +1,55 @@ ++// Copyright 2021 The Abseil Authors ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// https://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++#ifndef ABSL_NUMERIC_INTERNAL_REPRESENTATION_H_ ++#define ABSL_NUMERIC_INTERNAL_REPRESENTATION_H_ ++ ++#include ++ ++#include "absl/base/config.h" ++ ++namespace absl { ++ABSL_NAMESPACE_BEGIN ++namespace numeric_internal { ++ ++// Returns true iff long double is represented as a pair of doubles added ++// together. ++inline constexpr bool IsDoubleDouble() { ++ // A double-double value always has exactly twice the precision of a double ++ // value--one double carries the high digits and one double carries the low ++ // digits. This property is not shared with any other common floating-point ++ // representation, so this test won't trigger false positives. For reference, ++ // this table gives the number of bits of precision of each common ++ // floating-point representation: ++ // ++ // type precision ++ // IEEE single 24 b ++ // IEEE double 53 ++ // x86 long double 64 ++ // double-double 106 ++ // IEEE quadruple 113 ++ // ++ // Note in particular that a quadruple-precision float has greater precision ++ // than a double-double float despite taking up the same amount of memory; the ++ // quad has more of its bits allocated to the mantissa than the double-double ++ // has. ++ return std::numeric_limits::digits == ++ 2 * std::numeric_limits::digits; ++} ++ ++} // namespace numeric_internal ++ABSL_NAMESPACE_END ++} // namespace absl ++ ++#endif // ABSL_NUMERIC_INTERNAL_REPRESENTATION_H_ +diff --git a/extern/ttmath/ttmath.h b/extern/ttmath/ttmath.h +deleted file mode 100644 +index 9b9e8ee6e5..0000000000 +--- a/extern/ttmath/ttmath.h ++++ /dev/null +@@ -1,2843 +0,0 @@ +-/* +- * This file is a part of TTMath Bignum Library +- * and is distributed under the (new) BSD licence. +- * Author: Tomasz Sowa +- */ +- +-/* +- * Copyright (c) 2006-2012, Tomasz Sowa +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * +- * * Redistributions of source code must retain the above copyright notice, +- * this list of conditions and the following disclaimer. +- * +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * +- * * Neither the name Tomasz Sowa nor the names of contributors to this +- * project may be used to endorse or promote products derived +- * from this software without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +- * THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +- +- +-#ifndef headerfilettmathmathtt +-#define headerfilettmathmathtt +- +-/*! +- \file ttmath.h +- \brief Mathematics functions. +-*/ +- +-#ifdef _MSC_VER +-//warning C4127: conditional expression is constant +-#pragma warning( disable: 4127 ) +-//warning C4702: unreachable code +-#pragma warning( disable: 4702 ) +-//warning C4800: forcing value to bool 'true' or 'false' (performance warning) +-#pragma warning( disable: 4800 ) +-#endif +- +-#define TTMATH_DONT_USE_WCHAR +- +-#include "ttmathint.h" +-#include "ttmathobjects.h" +- +- +-namespace ttmath +-{ +- /* +- * +- * functions defined here are used only with Big<> types +- * +- * +- */ +- +- +- /* +- * +- * functions for rounding +- * +- * +- */ +- +- +- /*! +- this function skips the fraction from x +- e.g 2.2 = 2 +- 2.7 = 2 +- -2.2 = 2 +- -2.7 = 2 +- */ +- template +- ValueType SkipFraction(const ValueType & x) +- { +- ValueType result( x ); +- result.SkipFraction(); +- +- return result; +- } +- +- +- /*! +- this function rounds to the nearest integer value +- e.g 2.2 = 2 +- 2.7 = 3 +- -2.2 = -2 +- -2.7 = -3 +- */ +- template +- ValueType Round(const ValueType & x, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; // NaN +- } +- +- ValueType result( x ); +- uint c = result.Round(); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return result; +- } +- +- +- +- /*! +- this function returns a value representing the smallest integer +- that is greater than or equal to x +- +- Ceil(-3.7) = -3 +- Ceil(-3.1) = -3 +- Ceil(-3.0) = -3 +- Ceil(4.0) = 4 +- Ceil(4.2) = 5 +- Ceil(4.8) = 5 +- */ +- template +- ValueType Ceil(const ValueType & x, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; // NaN +- } +- +- ValueType result(x); +- uint c = 0; +- +- result.SkipFraction(); +- +- if( result != x ) +- { +- // x is with fraction +- // if x is negative we don't have to do anything +- if( !x.IsSign() ) +- { +- ValueType one; +- one.SetOne(); +- +- c += result.Add(one); +- } +- } +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return result; +- } +- +- +- /*! +- this function returns a value representing the largest integer +- that is less than or equal to x +- +- Floor(-3.6) = -4 +- Floor(-3.1) = -4 +- Floor(-3) = -3 +- Floor(2) = 2 +- Floor(2.3) = 2 +- Floor(2.8) = 2 +- */ +- template +- ValueType Floor(const ValueType & x, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; // NaN +- } +- +- ValueType result(x); +- uint c = 0; +- +- result.SkipFraction(); +- +- if( result != x ) +- { +- // x is with fraction +- // if x is positive we don't have to do anything +- if( x.IsSign() ) +- { +- ValueType one; +- one.SetOne(); +- +- c += result.Sub(one); +- } +- } +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return result; +- } +- +- +- +- /* +- * +- * logarithms and the exponent +- * +- * +- */ +- +- +- /*! +- this function calculates the natural logarithm (logarithm with the base 'e') +- */ +- template +- ValueType Ln(const ValueType & x, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; // NaN +- } +- +- ValueType result; +- uint state = result.Ln(x); +- +- if( err ) +- { +- switch( state ) +- { +- case 0: +- *err = err_ok; +- break; +- case 1: +- *err = err_overflow; +- break; +- case 2: +- *err = err_improper_argument; +- break; +- default: +- *err = err_internal_error; +- break; +- } +- } +- +- +- return result; +- } +- +- +- /*! +- this function calculates the logarithm +- */ +- template +- ValueType Log(const ValueType & x, const ValueType & base, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) *err = err_improper_argument; +- return x; +- } +- +- if( base.IsNan() ) +- { +- if( err ) *err = err_improper_argument; +- return base; +- } +- +- ValueType result; +- uint state = result.Log(x, base); +- +- if( err ) +- { +- switch( state ) +- { +- case 0: +- *err = err_ok; +- break; +- case 1: +- *err = err_overflow; +- break; +- case 2: +- case 3: +- *err = err_improper_argument; +- break; +- default: +- *err = err_internal_error; +- break; +- } +- } +- +- return result; +- } +- +- +- /*! +- this function calculates the expression e^x +- */ +- template +- ValueType Exp(const ValueType & x, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; // NaN +- } +- +- ValueType result; +- uint c = result.Exp(x); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return result; +- } +- +- +- /*! +- * +- * trigonometric functions +- * +- */ +- +- +- /* +- this namespace consists of auxiliary functions +- (something like 'private' in a class) +- */ +- namespace auxiliaryfunctions +- { +- +- /*! +- an auxiliary function for calculating the Sine +- (you don't have to call this function) +- */ +- template +- uint PrepareSin(ValueType & x, bool & change_sign) +- { +- ValueType temp; +- +- change_sign = false; +- +- if( x.IsSign() ) +- { +- // we're using the formula 'sin(-x) = -sin(x)' +- change_sign = !change_sign; +- x.ChangeSign(); +- } +- +- // we're reducing the period 2*PI +- // (for big values there'll always be zero) +- temp.Set2Pi(); +- +- if( x.Mod(temp) ) +- return 1; +- +- +- // we're setting 'x' as being in the range of <0, 0.5PI> +- +- temp.SetPi(); +- +- if( x > temp ) +- { +- // x is in (pi, 2*pi> +- x.Sub( temp ); +- change_sign = !change_sign; +- } +- +- temp.Set05Pi(); +- +- if( x > temp ) +- { +- // x is in (0.5pi, pi> +- x.Sub( temp ); +- x = temp - x; +- } +- +- return 0; +- } +- +- +- /*! +- an auxiliary function for calculating the Sine +- (you don't have to call this function) +- +- it returns Sin(x) where 'x' is from <0, PI/2> +- we're calculating the Sin with using Taylor series in zero or PI/2 +- (depending on which point of these two points is nearer to the 'x') +- +- Taylor series: +- sin(x) = sin(a) + cos(a)*(x-a)/(1!) +- - sin(a)*((x-a)^2)/(2!) - cos(a)*((x-a)^3)/(3!) +- + sin(a)*((x-a)^4)/(4!) + ... +- +- when a=0 it'll be: +- sin(x) = (x)/(1!) - (x^3)/(3!) + (x^5)/(5!) - (x^7)/(7!) + (x^9)/(9!) ... +- +- and when a=PI/2: +- sin(x) = 1 - ((x-PI/2)^2)/(2!) + ((x-PI/2)^4)/(4!) - ((x-PI/2)^6)/(6!) ... +- */ +- template +- ValueType Sin0pi05(const ValueType & x) +- { +- ValueType result; +- ValueType numerator, denominator; +- ValueType d_numerator, d_denominator; +- ValueType one, temp, old_result; +- +- // temp = pi/4 +- temp.Set05Pi(); +- temp.exponent.SubOne(); +- +- one.SetOne(); +- +- if( x < temp ) +- { +- // we're using the Taylor series with a=0 +- result = x; +- numerator = x; +- denominator = one; +- +- // d_numerator = x^2 +- d_numerator = x; +- d_numerator.Mul(x); +- +- d_denominator = 2; +- } +- else +- { +- // we're using the Taylor series with a=PI/2 +- result = one; +- numerator = one; +- denominator = one; +- +- // d_numerator = (x-pi/2)^2 +- ValueType pi05; +- pi05.Set05Pi(); +- +- temp = x; +- temp.Sub( pi05 ); +- d_numerator = temp; +- d_numerator.Mul( temp ); +- +- d_denominator = one; +- } +- +- uint c = 0; +- bool addition = false; +- +- old_result = result; +- for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) +- { +- // we're starting from a second part of the formula +- c += numerator. Mul( d_numerator ); +- c += denominator. Mul( d_denominator ); +- c += d_denominator.Add( one ); +- c += denominator. Mul( d_denominator ); +- c += d_denominator.Add( one ); +- temp = numerator; +- c += temp.Div(denominator); +- +- if( c ) +- // Sin is from <-1,1> and cannot make an overflow +- // but the carry can be from the Taylor series +- // (then we only break our calculations) +- break; +- +- if( addition ) +- result.Add( temp ); +- else +- result.Sub( temp ); +- +- +- addition = !addition; +- +- // we're testing whether the result has changed after adding +- // the next part of the Taylor formula, if not we end the loop +- // (it means 'x' is zero or 'x' is PI/2 or this part of the formula +- // is too small) +- if( result == old_result ) +- break; +- +- old_result = result; +- } +- +- return result; +- } +- +- } // namespace auxiliaryfunctions +- +- +- +- /*! +- this function calculates the Sine +- */ +- template +- ValueType Sin(ValueType x, ErrorCode * err = 0) +- { +- using namespace auxiliaryfunctions; +- +- ValueType one, result; +- bool change_sign; +- +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; +- } +- +- if( err ) +- *err = err_ok; +- +- if( PrepareSin( x, change_sign ) ) +- { +- // x is too big, we cannnot reduce the 2*PI period +- // prior to version 0.8.5 the result was zero +- +- // result has NaN flag set by default +- +- if( err ) +- *err = err_overflow; // maybe another error code? err_improper_argument? +- +- return result; // NaN is set by default +- } +- +- result = Sin0pi05( x ); +- +- one.SetOne(); +- +- // after calculations there can be small distortions in the result +- if( result > one ) +- result = one; +- else +- if( result.IsSign() ) +- // we've calculated the sin from <0, pi/2> and the result +- // should be positive +- result.SetZero(); +- +- if( change_sign ) +- result.ChangeSign(); +- +- return result; +- } +- +- +- /*! +- this function calulates the Cosine +- we're using the formula cos(x) = sin(x + PI/2) +- */ +- template +- ValueType Cos(ValueType x, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; // NaN +- } +- +- ValueType pi05; +- pi05.Set05Pi(); +- +- uint c = x.Add( pi05 ); +- +- if( c ) +- { +- if( err ) +- *err = err_overflow; +- +- return ValueType(); // result is undefined (NaN is set by default) +- } +- +- return Sin(x, err); +- } +- +- +- /*! +- this function calulates the Tangent +- we're using the formula tan(x) = sin(x) / cos(x) +- +- it takes more time than calculating the Tan directly +- from for example Taylor series but should be a bit preciser +- because Tan receives its values from -infinity to +infinity +- and when we calculate it from any series then we can make +- a greater mistake than calculating 'sin/cos' +- */ +- template +- ValueType Tan(const ValueType & x, ErrorCode * err = 0) +- { +- ValueType result = Cos(x, err); +- +- if( err && *err != err_ok ) +- return result; +- +- if( result.IsZero() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- result.SetNan(); +- +- return result; +- } +- +- return Sin(x, err) / result; +- } +- +- +- /*! +- this function calulates the Tangent +- look at the description of Tan(...) +- +- (the abbreviation of Tangent can be 'tg' as well) +- */ +- template +- ValueType Tg(const ValueType & x, ErrorCode * err = 0) +- { +- return Tan(x, err); +- } +- +- +- /*! +- this function calulates the Cotangent +- we're using the formula tan(x) = cos(x) / sin(x) +- +- (why do we make it in this way? +- look at information in Tan() function) +- */ +- template +- ValueType Cot(const ValueType & x, ErrorCode * err = 0) +- { +- ValueType result = Sin(x, err); +- +- if( err && *err != err_ok ) +- return result; +- +- if( result.IsZero() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- result.SetNan(); +- +- return result; +- } +- +- return Cos(x, err) / result; +- } +- +- +- /*! +- this function calulates the Cotangent +- look at the description of Cot(...) +- +- (the abbreviation of Cotangent can be 'ctg' as well) +- */ +- template +- ValueType Ctg(const ValueType & x, ErrorCode * err = 0) +- { +- return Cot(x, err); +- } +- +- +- /* +- * +- * inverse trigonometric functions +- * +- * +- */ +- +- namespace auxiliaryfunctions +- { +- +- /*! +- an auxiliary function for calculating the Arc Sine +- +- we're calculating asin from the following formula: +- asin(x) = x + (1*x^3)/(2*3) + (1*3*x^5)/(2*4*5) + (1*3*5*x^7)/(2*4*6*7) + ... +- where abs(x) <= 1 +- +- we're using this formula when x is from <0, 1/2> +- */ +- template +- ValueType ASin_0(const ValueType & x) +- { +- ValueType nominator, denominator, nominator_add, nominator_x, denominator_add, denominator_x; +- ValueType two, result(x), x2(x); +- ValueType nominator_temp, denominator_temp, old_result = result; +- uint c = 0; +- +- x2.Mul(x); +- two = 2; +- +- nominator.SetOne(); +- denominator = two; +- nominator_add = nominator; +- denominator_add = denominator; +- nominator_x = x; +- denominator_x = 3; +- +- for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) +- { +- c += nominator_x.Mul(x2); +- nominator_temp = nominator_x; +- c += nominator_temp.Mul(nominator); +- denominator_temp = denominator; +- c += denominator_temp.Mul(denominator_x); +- c += nominator_temp.Div(denominator_temp); +- +- // if there is a carry somewhere we only break the calculating +- // the result should be ok -- it's from <-pi/2, pi/2> +- if( c ) +- break; +- +- result.Add(nominator_temp); +- +- if( result == old_result ) +- // there's no sense to calculate more +- break; +- +- old_result = result; +- +- +- c += nominator_add.Add(two); +- c += denominator_add.Add(two); +- c += nominator.Mul(nominator_add); +- c += denominator.Mul(denominator_add); +- c += denominator_x.Add(two); +- } +- +- return result; +- } +- +- +- +- /*! +- an auxiliary function for calculating the Arc Sine +- +- we're calculating asin from the following formula: +- asin(x) = pi/2 - sqrt(2)*sqrt(1-x) * asin_temp +- asin_temp = 1 + (1*(1-x))/((2*3)*(2)) + (1*3*(1-x)^2)/((2*4*5)*(4)) + (1*3*5*(1-x)^3)/((2*4*6*7)*(8)) + ... +- +- where abs(x) <= 1 +- +- we're using this formula when x is from (1/2, 1> +- */ +- template +- ValueType ASin_1(const ValueType & x) +- { +- ValueType nominator, denominator, nominator_add, nominator_x, nominator_x_add, denominator_add, denominator_x; +- ValueType denominator2; +- ValueType one, two, result; +- ValueType nominator_temp, denominator_temp, old_result; +- uint c = 0; +- +- two = 2; +- +- one.SetOne(); +- nominator = one; +- result = one; +- old_result = result; +- denominator = two; +- nominator_add = nominator; +- denominator_add = denominator; +- nominator_x = one; +- nominator_x.Sub(x); +- nominator_x_add = nominator_x; +- denominator_x = 3; +- denominator2 = two; +- +- +- for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) +- { +- nominator_temp = nominator_x; +- c += nominator_temp.Mul(nominator); +- denominator_temp = denominator; +- c += denominator_temp.Mul(denominator_x); +- c += denominator_temp.Mul(denominator2); +- c += nominator_temp.Div(denominator_temp); +- +- // if there is a carry somewhere we only break the calculating +- // the result should be ok -- it's from <-pi/2, pi/2> +- if( c ) +- break; +- +- result.Add(nominator_temp); +- +- if( result == old_result ) +- // there's no sense to calculate more +- break; +- +- old_result = result; +- +- c += nominator_x.Mul(nominator_x_add); +- c += nominator_add.Add(two); +- c += denominator_add.Add(two); +- c += nominator.Mul(nominator_add); +- c += denominator.Mul(denominator_add); +- c += denominator_x.Add(two); +- c += denominator2.Mul(two); +- } +- +- +- nominator_x_add.exponent.AddOne(); // *2 +- one.exponent.SubOne(); // =0.5 +- nominator_x_add.Pow(one); // =sqrt(nominator_x_add) +- result.Mul(nominator_x_add); +- +- one.Set05Pi(); +- one.Sub(result); +- +- return one; +- } +- +- +- } // namespace auxiliaryfunctions +- +- +- /*! +- this function calculates the Arc Sine +- x is from <-1,1> +- */ +- template +- ValueType ASin(ValueType x, ErrorCode * err = 0) +- { +- using namespace auxiliaryfunctions; +- +- ValueType result, one; +- one.SetOne(); +- bool change_sign = false; +- +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; +- } +- +- if( x.GreaterWithoutSignThan(one) ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return result; // NaN is set by default +- } +- +- if( x.IsSign() ) +- { +- change_sign = true; +- x.Abs(); +- } +- +- one.exponent.SubOne(); // =0.5 +- +- // asin(-x) = -asin(x) +- if( x.GreaterWithoutSignThan(one) ) +- result = ASin_1(x); +- else +- result = ASin_0(x); +- +- if( change_sign ) +- result.ChangeSign(); +- +- if( err ) +- *err = err_ok; +- +- return result; +- } +- +- +- /*! +- this function calculates the Arc Cosine +- +- we're using the formula: +- acos(x) = pi/2 - asin(x) +- */ +- template +- ValueType ACos(const ValueType & x, ErrorCode * err = 0) +- { +- ValueType temp; +- +- temp.Set05Pi(); +- temp.Sub(ASin(x, err)); +- +- return temp; +- } +- +- +- +- namespace auxiliaryfunctions +- { +- +- /*! +- an auxiliary function for calculating the Arc Tangent +- +- arc tan (x) where x is in <0; 0.5) +- (x can be in (-0.5 ; 0.5) too) +- +- we're using the Taylor series expanded in zero: +- atan(x) = x - (x^3)/3 + (x^5)/5 - (x^7)/7 + ... +- */ +- template +- ValueType ATan0(const ValueType & x) +- { +- ValueType nominator, denominator, nominator_add, denominator_add, temp; +- ValueType result, old_result; +- bool adding = false; +- uint c = 0; +- +- result = x; +- old_result = result; +- nominator = x; +- nominator_add = x; +- nominator_add.Mul(x); +- +- denominator.SetOne(); +- denominator_add = 2; +- +- for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) +- { +- c += nominator.Mul(nominator_add); +- c += denominator.Add(denominator_add); +- +- temp = nominator; +- c += temp.Div(denominator); +- +- if( c ) +- // the result should be ok +- break; +- +- if( adding ) +- result.Add(temp); +- else +- result.Sub(temp); +- +- if( result == old_result ) +- // there's no sense to calculate more +- break; +- +- old_result = result; +- adding = !adding; +- } +- +- return result; +- } +- +- +- /*! +- an auxiliary function for calculating the Arc Tangent +- +- where x is in <0 ; 1> +- */ +- template +- ValueType ATan01(const ValueType & x) +- { +- ValueType half; +- half.Set05(); +- +- /* +- it would be better if we chose about sqrt(2)-1=0.41... instead of 0.5 here +- +- because as you can see below: +- when x = sqrt(2)-1 +- abs(x) = abs( (x-1)/(1+x) ) +- so when we're calculating values around x +- then they will be better converged to each other +- +- for example if we have x=0.4999 then during calculating ATan0(0.4999) +- we have to make about 141 iterations but when we have x=0.5 +- then during calculating ATan0( (x-1)/(1+x) ) we have to make +- only about 89 iterations (both for Big<3,9>) +- +- in the future this 0.5 can be changed +- */ +- if( x.SmallerWithoutSignThan(half) ) +- return ATan0(x); +- +- +- /* +- x>=0.5 and x<=1 +- (x can be even smaller than 0.5) +- +- y = atac(x) +- x = tan(y) +- +- tan(y-b) = (tan(y)-tab(b)) / (1+tan(y)*tan(b)) +- y-b = atan( (tan(y)-tab(b)) / (1+tan(y)*tan(b)) ) +- y = b + atan( (x-tab(b)) / (1+x*tan(b)) ) +- +- let b = pi/4 +- tan(b) = tan(pi/4) = 1 +- y = pi/4 + atan( (x-1)/(1+x) ) +- +- so +- atac(x) = pi/4 + atan( (x-1)/(1+x) ) +- when x->1 (x converges to 1) the (x-1)/(1+x) -> 0 +- and we can use ATan0() function here +- */ +- +- ValueType n(x),d(x),one,result; +- +- one.SetOne(); +- n.Sub(one); +- d.Add(one); +- n.Div(d); +- +- result = ATan0(n); +- +- n.Set05Pi(); +- n.exponent.SubOne(); // =pi/4 +- result.Add(n); +- +- return result; +- } +- +- +- /*! +- an auxiliary function for calculating the Arc Tangent +- where x > 1 +- +- we're using the formula: +- atan(x) = pi/2 - atan(1/x) for x>0 +- */ +- template +- ValueType ATanGreaterThanPlusOne(const ValueType & x) +- { +- ValueType temp, atan; +- +- temp.SetOne(); +- +- if( temp.Div(x) ) +- { +- // if there was a carry here that means x is very big +- // and atan(1/x) fast converged to 0 +- atan.SetZero(); +- } +- else +- atan = ATan01(temp); +- +- temp.Set05Pi(); +- temp.Sub(atan); +- +- return temp; +- } +- +- } // namespace auxiliaryfunctions +- +- +- /*! +- this function calculates the Arc Tangent +- */ +- template +- ValueType ATan(ValueType x) +- { +- using namespace auxiliaryfunctions; +- +- ValueType one, result; +- one.SetOne(); +- bool change_sign = false; +- +- if( x.IsNan() ) +- return x; +- +- // if x is negative we're using the formula: +- // atan(-x) = -atan(x) +- if( x.IsSign() ) +- { +- change_sign = true; +- x.Abs(); +- } +- +- if( x.GreaterWithoutSignThan(one) ) +- result = ATanGreaterThanPlusOne(x); +- else +- result = ATan01(x); +- +- if( change_sign ) +- result.ChangeSign(); +- +- return result; +- } +- +- +- /*! +- this function calculates the Arc Tangent +- look at the description of ATan(...) +- +- (the abbreviation of Arc Tangent can be 'atg' as well) +- */ +- template +- ValueType ATg(const ValueType & x) +- { +- return ATan(x); +- } +- +- +- /*! +- this function calculates the Arc Cotangent +- +- we're using the formula: +- actan(x) = pi/2 - atan(x) +- */ +- template +- ValueType ACot(const ValueType & x) +- { +- ValueType result; +- +- result.Set05Pi(); +- result.Sub(ATan(x)); +- +- return result; +- } +- +- +- /*! +- this function calculates the Arc Cotangent +- look at the description of ACot(...) +- +- (the abbreviation of Arc Cotangent can be 'actg' as well) +- */ +- template +- ValueType ACtg(const ValueType & x) +- { +- return ACot(x); +- } +- +- +- /* +- * +- * hyperbolic functions +- * +- * +- */ +- +- +- /*! +- this function calculates the Hyperbolic Sine +- +- we're using the formula sinh(x)= ( e^x - e^(-x) ) / 2 +- */ +- template +- ValueType Sinh(const ValueType & x, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; // NaN +- } +- +- ValueType ex, emx; +- uint c = 0; +- +- c += ex.Exp(x); +- c += emx.Exp(-x); +- +- c += ex.Sub(emx); +- c += ex.exponent.SubOne(); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return ex; +- } +- +- +- /*! +- this function calculates the Hyperbolic Cosine +- +- we're using the formula cosh(x)= ( e^x + e^(-x) ) / 2 +- */ +- template +- ValueType Cosh(const ValueType & x, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; // NaN +- } +- +- ValueType ex, emx; +- uint c = 0; +- +- c += ex.Exp(x); +- c += emx.Exp(-x); +- +- c += ex.Add(emx); +- c += ex.exponent.SubOne(); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return ex; +- } +- +- +- /*! +- this function calculates the Hyperbolic Tangent +- +- we're using the formula tanh(x)= ( e^x - e^(-x) ) / ( e^x + e^(-x) ) +- */ +- template +- ValueType Tanh(const ValueType & x, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; // NaN +- } +- +- ValueType ex, emx, nominator, denominator; +- uint c = 0; +- +- c += ex.Exp(x); +- c += emx.Exp(-x); +- +- nominator = ex; +- c += nominator.Sub(emx); +- denominator = ex; +- c += denominator.Add(emx); +- +- c += nominator.Div(denominator); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return nominator; +- } +- +- +- /*! +- this function calculates the Hyperbolic Tangent +- look at the description of Tanh(...) +- +- (the abbreviation of Hyperbolic Tangent can be 'tgh' as well) +- */ +- template +- ValueType Tgh(const ValueType & x, ErrorCode * err = 0) +- { +- return Tanh(x, err); +- } +- +- /*! +- this function calculates the Hyperbolic Cotangent +- +- we're using the formula coth(x)= ( e^x + e^(-x) ) / ( e^x - e^(-x) ) +- */ +- template +- ValueType Coth(const ValueType & x, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; // NaN +- } +- +- if( x.IsZero() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return ValueType(); // NaN is set by default +- } +- +- ValueType ex, emx, nominator, denominator; +- uint c = 0; +- +- c += ex.Exp(x); +- c += emx.Exp(-x); +- +- nominator = ex; +- c += nominator.Add(emx); +- denominator = ex; +- c += denominator.Sub(emx); +- +- c += nominator.Div(denominator); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return nominator; +- } +- +- +- /*! +- this function calculates the Hyperbolic Cotangent +- look at the description of Coth(...) +- +- (the abbreviation of Hyperbolic Cotangent can be 'ctgh' as well) +- */ +- template +- ValueType Ctgh(const ValueType & x, ErrorCode * err = 0) +- { +- return Coth(x, err); +- } +- +- +- /* +- * +- * inverse hyperbolic functions +- * +- * +- */ +- +- +- /*! +- inverse hyperbolic sine +- +- asinh(x) = ln( x + sqrt(x^2 + 1) ) +- */ +- template +- ValueType ASinh(const ValueType & x, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; // NaN +- } +- +- ValueType xx(x), one, result; +- uint c = 0; +- one.SetOne(); +- +- c += xx.Mul(x); +- c += xx.Add(one); +- one.exponent.SubOne(); // one=0.5 +- // xx is >= 1 +- c += xx.PowFrac(one); // xx=sqrt(xx) +- c += xx.Add(x); +- c += result.Ln(xx); // xx > 0 +- +- // here can only be a carry +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return result; +- } +- +- +- /*! +- inverse hyperbolic cosine +- +- acosh(x) = ln( x + sqrt(x^2 - 1) ) x in <1, infinity) +- */ +- template +- ValueType ACosh(const ValueType & x, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; // NaN +- } +- +- ValueType xx(x), one, result; +- uint c = 0; +- one.SetOne(); +- +- if( x < one ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return result; // NaN is set by default +- } +- +- c += xx.Mul(x); +- c += xx.Sub(one); +- // xx is >= 0 +- // we can't call a PowFrac when the 'x' is zero +- // if x is 0 the sqrt(0) is 0 +- if( !xx.IsZero() ) +- { +- one.exponent.SubOne(); // one=0.5 +- c += xx.PowFrac(one); // xx=sqrt(xx) +- } +- c += xx.Add(x); +- c += result.Ln(xx); // xx >= 1 +- +- // here can only be a carry +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return result; +- } +- +- +- /*! +- inverse hyperbolic tangent +- +- atanh(x) = 0.5 * ln( (1+x) / (1-x) ) x in (-1, 1) +- */ +- template +- ValueType ATanh(const ValueType & x, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; // NaN +- } +- +- ValueType nominator(x), denominator, one, result; +- uint c = 0; +- one.SetOne(); +- +- if( !x.SmallerWithoutSignThan(one) ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return result; // NaN is set by default +- } +- +- c += nominator.Add(one); +- denominator = one; +- c += denominator.Sub(x); +- c += nominator.Div(denominator); +- c += result.Ln(nominator); +- c += result.exponent.SubOne(); +- +- // here can only be a carry +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return result; +- } +- +- +- /*! +- inverse hyperbolic tantent +- */ +- template +- ValueType ATgh(const ValueType & x, ErrorCode * err = 0) +- { +- return ATanh(x, err); +- } +- +- +- /*! +- inverse hyperbolic cotangent +- +- acoth(x) = 0.5 * ln( (x+1) / (x-1) ) x in (-infinity, -1) or (1, infinity) +- */ +- template +- ValueType ACoth(const ValueType & x, ErrorCode * err = 0) +- { +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; // NaN +- } +- +- ValueType nominator(x), denominator(x), one, result; +- uint c = 0; +- one.SetOne(); +- +- if( !x.GreaterWithoutSignThan(one) ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return result; // NaN is set by default +- } +- +- c += nominator.Add(one); +- c += denominator.Sub(one); +- c += nominator.Div(denominator); +- c += result.Ln(nominator); +- c += result.exponent.SubOne(); +- +- // here can only be a carry +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return result; +- } +- +- +- /*! +- inverse hyperbolic cotantent +- */ +- template +- ValueType ACtgh(const ValueType & x, ErrorCode * err = 0) +- { +- return ACoth(x, err); +- } +- +- +- +- +- +- /* +- * +- * functions for converting between degrees, radians and gradians +- * +- * +- */ +- +- +- /*! +- this function converts degrees to radians +- +- it returns: x * pi / 180 +- */ +- template +- ValueType DegToRad(const ValueType & x, ErrorCode * err = 0) +- { +- ValueType result, temp; +- uint c = 0; +- +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; +- } +- +- result = x; +- +- // it is better to make division first and then multiplication +- // the result is more accurate especially when x is: 90,180,270 or 360 +- temp = 180; +- c += result.Div(temp); +- +- temp.SetPi(); +- c += result.Mul(temp); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return result; +- } +- +- +- /*! +- this function converts radians to degrees +- +- it returns: x * 180 / pi +- */ +- template +- ValueType RadToDeg(const ValueType & x, ErrorCode * err = 0) +- { +- ValueType result, delimiter; +- uint c = 0; +- +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; +- } +- +- result = 180; +- c += result.Mul(x); +- +- delimiter.SetPi(); +- c += result.Div(delimiter); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return result; +- } +- +- +- /*! +- this function converts degrees in the long format into one value +- +- long format: (degrees, minutes, seconds) +- minutes and seconds must be greater than or equal zero +- +- result: +- if d>=0 : result= d + ((s/60)+m)/60 +- if d<0 : result= d - ((s/60)+m)/60 +- +- ((s/60)+m)/60 = (s+60*m)/3600 (second version is faster because +- there's only one division) +- +- for example: +- DegToDeg(10, 30, 0) = 10.5 +- DegToDeg(10, 24, 35.6)=10.4098(8) +- */ +- template +- ValueType DegToDeg( const ValueType & d, const ValueType & m, const ValueType & s, +- ErrorCode * err = 0) +- { +- ValueType delimiter, multipler; +- uint c = 0; +- +- if( d.IsNan() || m.IsNan() || s.IsNan() || m.IsSign() || s.IsSign() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- delimiter.SetZeroNan(); // not needed, only to get rid of GCC warning about an uninitialized variable +- +- return delimiter; +- } +- +- multipler = 60; +- delimiter = 3600; +- +- c += multipler.Mul(m); +- c += multipler.Add(s); +- c += multipler.Div(delimiter); +- +- if( d.IsSign() ) +- multipler.ChangeSign(); +- +- c += multipler.Add(d); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return multipler; +- } +- +- +- /*! +- this function converts degrees in the long format to radians +- */ +- template +- ValueType DegToRad( const ValueType & d, const ValueType & m, const ValueType & s, +- ErrorCode * err = 0) +- { +- ValueType temp_deg = DegToDeg(d,m,s,err); +- +- if( err && *err!=err_ok ) +- return temp_deg; +- +- return DegToRad(temp_deg, err); +- } +- +- +- /*! +- this function converts gradians to radians +- +- it returns: x * pi / 200 +- */ +- template +- ValueType GradToRad(const ValueType & x, ErrorCode * err = 0) +- { +- ValueType result, temp; +- uint c = 0; +- +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; +- } +- +- result = x; +- +- // it is better to make division first and then multiplication +- // the result is more accurate especially when x is: 100,200,300 or 400 +- temp = 200; +- c += result.Div(temp); +- +- temp.SetPi(); +- c += result.Mul(temp); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return result; +- } +- +- +- /*! +- this function converts radians to gradians +- +- it returns: x * 200 / pi +- */ +- template +- ValueType RadToGrad(const ValueType & x, ErrorCode * err = 0) +- { +- ValueType result, delimiter; +- uint c = 0; +- +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; +- } +- +- result = 200; +- c += result.Mul(x); +- +- delimiter.SetPi(); +- c += result.Div(delimiter); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return result; +- } +- +- +- /*! +- this function converts degrees to gradians +- +- it returns: x * 200 / 180 +- */ +- template +- ValueType DegToGrad(const ValueType & x, ErrorCode * err = 0) +- { +- ValueType result, temp; +- uint c = 0; +- +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; +- } +- +- result = x; +- +- temp = 200; +- c += result.Mul(temp); +- +- temp = 180; +- c += result.Div(temp); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return result; +- } +- +- +- /*! +- this function converts degrees in the long format to gradians +- */ +- template +- ValueType DegToGrad( const ValueType & d, const ValueType & m, const ValueType & s, +- ErrorCode * err = 0) +- { +- ValueType temp_deg = DegToDeg(d,m,s,err); +- +- if( err && *err!=err_ok ) +- return temp_deg; +- +- return DegToGrad(temp_deg, err); +- } +- +- +- /*! +- this function converts degrees to gradians +- +- it returns: x * 180 / 200 +- */ +- template +- ValueType GradToDeg(const ValueType & x, ErrorCode * err = 0) +- { +- ValueType result, temp; +- uint c = 0; +- +- if( x.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return x; +- } +- +- result = x; +- +- temp = 180; +- c += result.Mul(temp); +- +- temp = 200; +- c += result.Div(temp); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return result; +- } +- +- +- +- +- /* +- * +- * another functions +- * +- * +- */ +- +- +- /*! +- this function calculates the square root +- +- Sqrt(9) = 3 +- */ +- template +- ValueType Sqrt(ValueType x, ErrorCode * err = 0) +- { +- if( x.IsNan() || x.IsSign() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- x.SetNan(); +- +- return x; +- } +- +- uint c = x.Sqrt(); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return x; +- } +- +- +- +- namespace auxiliaryfunctions +- { +- +- template +- bool RootCheckIndexSign(ValueType & x, const ValueType & index, ErrorCode * err) +- { +- if( index.IsSign() ) +- { +- // index cannot be negative +- if( err ) +- *err = err_improper_argument; +- +- x.SetNan(); +- +- return true; +- } +- +- return false; +- } +- +- +- template +- bool RootCheckIndexZero(ValueType & x, const ValueType & index, ErrorCode * err) +- { +- if( index.IsZero() ) +- { +- if( x.IsZero() ) +- { +- // there isn't root(0;0) - we assume it's not defined +- if( err ) +- *err = err_improper_argument; +- +- x.SetNan(); +- +- return true; +- } +- +- // root(x;0) is 1 (if x!=0) +- x.SetOne(); +- +- if( err ) +- *err = err_ok; +- +- return true; +- } +- +- return false; +- } +- +- +- template +- bool RootCheckIndexOne(const ValueType & index, ErrorCode * err) +- { +- ValueType one; +- one.SetOne(); +- +- if( index == one ) +- { +- //root(x;1) is x +- // we do it because if we used the PowFrac function +- // we would lose the precision +- if( err ) +- *err = err_ok; +- +- return true; +- } +- +- return false; +- } +- +- +- template +- bool RootCheckIndexTwo(ValueType & x, const ValueType & index, ErrorCode * err) +- { +- if( index == 2 ) +- { +- x = Sqrt(x, err); +- +- return true; +- } +- +- return false; +- } +- +- +- template +- bool RootCheckIndexFrac(ValueType & x, const ValueType & index, ErrorCode * err) +- { +- if( !index.IsInteger() ) +- { +- // index must be integer +- if( err ) +- *err = err_improper_argument; +- +- x.SetNan(); +- +- return true; +- } +- +- return false; +- } +- +- +- template +- bool RootCheckXZero(ValueType & x, ErrorCode * err) +- { +- if( x.IsZero() ) +- { +- // root(0;index) is zero (if index!=0) +- // RootCheckIndexZero() must be called beforehand +- x.SetZero(); +- +- if( err ) +- *err = err_ok; +- +- return true; +- } +- +- return false; +- } +- +- +- template +- bool RootCheckIndex(ValueType & x, const ValueType & index, ErrorCode * err, bool * change_sign) +- { +- *change_sign = false; +- +- if( index.Mod2() ) +- { +- // index is odd (1,3,5...) +- if( x.IsSign() ) +- { +- *change_sign = true; +- x.Abs(); +- } +- } +- else +- { +- // index is even +- // x cannot be negative +- if( x.IsSign() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- x.SetNan(); +- +- return true; +- } +- } +- +- return false; +- } +- +- +- template +- uint RootCorrectInteger(ValueType & old_x, ValueType & x, const ValueType & index) +- { +- if( !old_x.IsInteger() || x.IsInteger() || !index.exponent.IsSign() ) +- return 0; +- +- // old_x is integer, +- // x is not integer, +- // index is relatively small (index.exponent<0 or index.exponent<=0) +- // (because we're using a special powering algorithm Big::PowUInt()) +- +- uint c = 0; +- +- ValueType temp(x); +- c += temp.Round(); +- +- ValueType temp_round(temp); +- c += temp.PowUInt(index); +- +- if( temp == old_x ) +- x = temp_round; +- +- return (c==0)? 0 : 1; +- } +- +- +- +- } // namespace auxiliaryfunctions +- +- +- +- /*! +- indexth Root of x +- index must be integer and not negative <0;1;2;3....) +- +- if index==0 the result is one +- if x==0 the result is zero and we assume root(0;0) is not defined +- +- if index is even (2;4;6...) the result is x^(1/index) and x>0 +- if index is odd (1;2;3;...) the result is either +- -(abs(x)^(1/index)) if x<0 or +- x^(1/index)) if x>0 +- +- (for index==1 the result is equal x) +- */ +- template +- ValueType Root(ValueType x, const ValueType & index, ErrorCode * err = 0) +- { +- using namespace auxiliaryfunctions; +- +- if( x.IsNan() || index.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- x.SetNan(); +- +- return x; +- } +- +- if( RootCheckIndexSign(x, index, err) ) return x; +- if( RootCheckIndexZero(x, index, err) ) return x; +- if( RootCheckIndexOne ( index, err) ) return x; +- if( RootCheckIndexTwo (x, index, err) ) return x; +- if( RootCheckIndexFrac(x, index, err) ) return x; +- if( RootCheckXZero (x, err) ) return x; +- +- // index integer and index!=0 +- // x!=0 +- +- ValueType old_x(x); +- bool change_sign; +- +- if( RootCheckIndex(x, index, err, &change_sign ) ) return x; +- +- ValueType temp; +- uint c = 0; +- +- // we're using the formula: root(x ; n) = exp( ln(x) / n ) +- c += temp.Ln(x); +- c += temp.Div(index); +- c += x.Exp(temp); +- +- if( change_sign ) +- { +- // x is different from zero +- x.SetSign(); +- } +- +- c += RootCorrectInteger(old_x, x, index); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return x; +- } +- +- +- +- /*! +- absolute value of x +- e.g. -2 = 2 +- 2 = 2 +- */ +- template +- ValueType Abs(const ValueType & x) +- { +- ValueType result( x ); +- result.Abs(); +- +- return result; +- } +- +- +- /*! +- it returns the sign of the value +- e.g. -2 = -1 +- 0 = 0 +- 10 = 1 +- */ +- template +- ValueType Sgn(ValueType x) +- { +- x.Sgn(); +- +- return x; +- } +- +- +- /*! +- the remainder from a division +- +- e.g. +- mod( 12.6 ; 3) = 0.6 because 12.6 = 3*4 + 0.6 +- mod(-12.6 ; 3) = -0.6 bacause -12.6 = 3*(-4) + (-0.6) +- mod( 12.6 ; -3) = 0.6 +- mod(-12.6 ; -3) = -0.6 +- */ +- template +- ValueType Mod(ValueType a, const ValueType & b, ErrorCode * err = 0) +- { +- if( a.IsNan() || b.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- a.SetNan(); +- +- return a; +- } +- +- uint c = a.Mod(b); +- +- if( err ) +- *err = c ? err_overflow : err_ok; +- +- return a; +- } +- +- +- +- namespace auxiliaryfunctions +- { +- +- /*! +- this function is used to store factorials in a given container +- 'more' means how many values should be added at the end +- +- e.g. +- std::vector fact; +- SetFactorialSequence(fact, 3); +- // now the container has three values: 1 1 2 +- +- SetFactorialSequence(fact, 2); +- // now the container has five values: 1 1 2 6 24 +- */ +- template +- void SetFactorialSequence(std::vector & fact, uint more = 20) +- { +- if( more == 0 ) +- more = 1; +- +- uint start = static_cast(fact.size()); +- fact.resize(fact.size() + more); +- +- if( start == 0 ) +- { +- fact[0] = 1; +- ++start; +- } +- +- for(uint i=start ; i +- ValueType SetBernoulliNumbersSum(CGamma & cgamma, const ValueType & n_, uint m, +- const volatile StopCalculating * stop = 0) +- { +- ValueType k_, temp, temp2, temp3, sum; +- +- sum.SetZero(); +- +- for(uint k=0 ; kWasStopSignal() ) +- return ValueType(); // NaN +- +- if( k>1 && (k & 1) == 1 ) // for that k the Bernoulli number is zero +- continue; +- +- k_ = k; +- +- temp = n_; // n_ is equal 2 +- temp.Pow(k_); +- // temp = 2^k +- +- temp2 = cgamma.fact[m]; +- temp3 = cgamma.fact[k]; +- temp3.Mul(cgamma.fact[m-k]); +- temp2.Div(temp3); +- // temp2 = (m k) = m! / ( k! * (m-k)! ) +- +- temp.Mul(temp2); +- temp.Mul(cgamma.bern[k]); +- +- sum.Add(temp); +- // sum += 2^k * (m k) * B(k) +- +- if( sum.IsNan() ) +- break; +- } +- +- return sum; +- } +- +- +- /*! +- an auxiliary function used to calculate Bernoulli numbers +- start is >= 2 +- +- we use the recurrence formula: +- B(m) = 1 / (2*(1 - 2^m)) * sum(m) +- where sum(m) is calculated by SetBernoulliNumbersSum() +- */ +- template +- bool SetBernoulliNumbersMore(CGamma & cgamma, uint start, const volatile StopCalculating * stop = 0) +- { +- ValueType denominator, temp, temp2, temp3, m_, sum, sum2, n_, k_; +- +- const uint n = 2; +- n_ = n; +- +- // start is >= 2 +- for(uint m=start ; mWasStopSignal() ) +- { +- cgamma.bern.resize(m); // valid numbers are in [0, m-1] +- return false; +- } +- +- cgamma.bern[m].Div(denominator); +- } +- } +- +- return true; +- } +- +- +- /*! +- this function is used to calculate Bernoulli numbers, +- returns false if there was a stop signal, +- 'more' means how many values should be added at the end +- +- e.g. +- typedef Big<1,2> MyBig; +- CGamma cgamma; +- SetBernoulliNumbers(cgamma, 3); +- // now we have three first Bernoulli numbers: 1 -0.5 0.16667 +- +- SetBernoulliNumbers(cgamma, 4); +- // now we have 7 Bernoulli numbers: 1 -0.5 0.16667 0 -0.0333 0 0.0238 +- */ +- template +- bool SetBernoulliNumbers(CGamma & cgamma, uint more = 20, const volatile StopCalculating * stop = 0) +- { +- if( more == 0 ) +- more = 1; +- +- uint start = static_cast(cgamma.bern.size()); +- cgamma.bern.resize(cgamma.bern.size() + more); +- +- if( start == 0 ) +- { +- cgamma.bern[0].SetOne(); +- ++start; +- } +- +- if( cgamma.bern.size() == 1 ) +- return true; +- +- if( start == 1 ) +- { +- cgamma.bern[1].Set05(); +- cgamma.bern[1].ChangeSign(); +- ++start; +- } +- +- // we should have sufficient factorials in cgamma.fact +- if( cgamma.fact.size() < cgamma.bern.size() ) +- SetFactorialSequence(cgamma.fact, static_cast(cgamma.bern.size() - cgamma.fact.size())); +- +- +- return SetBernoulliNumbersMore(cgamma, start, stop); +- } +- +- +- /*! +- an auxiliary function used to calculate the Gamma() function +- +- we calculate a sum: +- sum(n) = sum_{m=2} { B(m) / ( (m^2 - m) * n^(m-1) ) } = 1/(12*n) - 1/(360*n^3) + 1/(1260*n^5) + ... +- B(m) means a mth Bernoulli number +- the sum starts from m=2, we calculate as long as the value will not change after adding a next part +- */ +- template +- ValueType GammaFactorialHighSum(const ValueType & n, CGamma & cgamma, ErrorCode & err, +- const volatile StopCalculating * stop) +- { +- ValueType temp, temp2, denominator, sum, oldsum; +- +- sum.SetZero(); +- +- for(uint m=2 ; mWasStopSignal() ) +- { +- err = err_interrupt; +- return ValueType(); // NaN +- } +- +- temp = (m-1); +- denominator = n; +- denominator.Pow(temp); +- // denominator = n ^ (m-1) +- +- temp = m; +- temp2 = temp; +- temp.Mul(temp2); +- temp.Sub(temp2); +- // temp = m^2 - m +- +- denominator.Mul(temp); +- // denominator = (m^2 - m) * n ^ (m-1) +- +- if( m >= cgamma.bern.size() ) +- { +- if( !SetBernoulliNumbers(cgamma, m - cgamma.bern.size() + 1 + 3, stop) ) // 3 more than needed +- { +- // there was the stop signal +- err = err_interrupt; +- return ValueType(); // NaN +- } +- } +- +- temp = cgamma.bern[m]; +- temp.Div(denominator); +- +- oldsum = sum; +- sum.Add(temp); +- +- if( sum.IsNan() || oldsum==sum ) +- break; +- } +- +- return sum; +- } +- +- +- /*! +- an auxiliary function used to calculate the Gamma() function +- +- we calculate a helper function GammaFactorialHigh() by using Stirling's series: +- n! = (n/e)^n * sqrt(2*pi*n) * exp( sum(n) ) +- where n is a real number (not only an integer) and is sufficient large (greater than TTMATH_GAMMA_BOUNDARY) +- and sum(n) is calculated by GammaFactorialHighSum() +- */ +- template +- ValueType GammaFactorialHigh(const ValueType & n, CGamma & cgamma, ErrorCode & err, +- const volatile StopCalculating * stop) +- { +- ValueType temp, temp2, temp3, denominator, sum; +- +- temp.Set2Pi(); +- temp.Mul(n); +- temp2 = Sqrt(temp); +- // temp2 = sqrt(2*pi*n) +- +- temp = n; +- temp3.SetE(); +- temp.Div(temp3); +- temp.Pow(n); +- // temp = (n/e)^n +- +- sum = GammaFactorialHighSum(n, cgamma, err, stop); +- temp3.Exp(sum); +- // temp3 = exp(sum) +- +- temp.Mul(temp2); +- temp.Mul(temp3); +- +- return temp; +- } +- +- +- /*! +- an auxiliary function used to calculate the Gamma() function +- +- Gamma(x) = GammaFactorialHigh(x-1) +- */ +- template +- ValueType GammaPlusHigh(ValueType n, CGamma & cgamma, ErrorCode & err, const volatile StopCalculating * stop) +- { +- ValueType one; +- +- one.SetOne(); +- n.Sub(one); +- +- return GammaFactorialHigh(n, cgamma, err, stop); +- } +- +- +- /*! +- an auxiliary function used to calculate the Gamma() function +- +- we use this function when n is integer and a small value (from 0 to TTMATH_GAMMA_BOUNDARY] +- we use the formula: +- gamma(n) = (n-1)! = 1 * 2 * 3 * ... * (n-1) +- */ +- template +- ValueType GammaPlusLowIntegerInt(uint n, CGamma & cgamma) +- { +- TTMATH_ASSERT( n > 0 ) +- +- if( n - 1 < static_cast(cgamma.fact.size()) ) +- return cgamma.fact[n - 1]; +- +- ValueType res; +- uint start = 2; +- +- if( cgamma.fact.size() < 2 ) +- { +- res.SetOne(); +- } +- else +- { +- start = static_cast(cgamma.fact.size()); +- res = cgamma.fact[start-1]; +- } +- +- for(uint i=start ; i +- ValueType GammaPlusLowInteger(const ValueType & n, CGamma & cgamma) +- { +- sint n_; +- +- n.ToInt(n_); +- +- return GammaPlusLowIntegerInt(n_, cgamma); +- } +- +- +- /*! +- an auxiliary function used to calculate the Gamma() function +- +- we use this function when n is a small value (from 0 to TTMATH_GAMMA_BOUNDARY] +- we use a recurrence formula: +- gamma(z+1) = z * gamma(z) +- then: gamma(z) = gamma(z+1) / z +- +- e.g. +- gamma(3.89) = gamma(2001.89) / ( 3.89 * 4.89 * 5.89 * ... * 1999.89 * 2000.89 ) +- */ +- template +- ValueType GammaPlusLow(ValueType n, CGamma & cgamma, ErrorCode & err, const volatile StopCalculating * stop) +- { +- ValueType one, denominator, temp, boundary; +- +- if( n.IsInteger() ) +- return GammaPlusLowInteger(n, cgamma); +- +- one.SetOne(); +- denominator = n; +- boundary = TTMATH_GAMMA_BOUNDARY; +- +- while( n < boundary ) +- { +- n.Add(one); +- denominator.Mul(n); +- } +- +- n.Add(one); +- +- // now n is sufficient big +- temp = GammaPlusHigh(n, cgamma, err, stop); +- temp.Div(denominator); +- +- return temp; +- } +- +- +- /*! +- an auxiliary function used to calculate the Gamma() function +- */ +- template +- ValueType GammaPlus(const ValueType & n, CGamma & cgamma, ErrorCode & err, const volatile StopCalculating * stop) +- { +- if( n > TTMATH_GAMMA_BOUNDARY ) +- return GammaPlusHigh(n, cgamma, err, stop); +- +- return GammaPlusLow(n, cgamma, err, stop); +- } +- +- +- /*! +- an auxiliary function used to calculate the Gamma() function +- +- this function is used when n is negative +- we use the reflection formula: +- gamma(1-z) * gamma(z) = pi / sin(pi*z) +- then: gamma(z) = pi / (sin(pi*z) * gamma(1-z)) +- +- */ +- template +- ValueType GammaMinus(const ValueType & n, CGamma & cgamma, ErrorCode & err, const volatile StopCalculating * stop) +- { +- ValueType pi, denominator, temp, temp2; +- +- if( n.IsInteger() ) +- { +- // gamma function is not defined when n is negative and integer +- err = err_improper_argument; +- return temp; // NaN +- } +- +- pi.SetPi(); +- +- temp = pi; +- temp.Mul(n); +- temp2 = Sin(temp); +- // temp2 = sin(pi * n) +- +- temp.SetOne(); +- temp.Sub(n); +- temp = GammaPlus(temp, cgamma, err, stop); +- // temp = gamma(1 - n) +- +- temp.Mul(temp2); +- pi.Div(temp); +- +- return pi; +- } +- +- } // namespace auxiliaryfunctions +- +- +- +- /*! +- this function calculates the Gamma function +- +- it's multithread safe, you should create a CGamma<> object and use it whenever you call the Gamma() +- e.g. +- typedef Big<1,2> MyBig; +- MyBig x=234, y=345.53; +- CGamma cgamma; +- std::cout << Gamma(x, cgamma) << std::endl; +- std::cout << Gamma(y, cgamma) << std::endl; +- in the CGamma<> object the function stores some coefficients (factorials, Bernoulli numbers), +- and they will be reused in next calls to the function +- +- each thread should have its own CGamma<> object, and you can use these objects with Factorial() function too +- */ +- template +- ValueType Gamma(const ValueType & n, CGamma & cgamma, ErrorCode * err = 0, +- const volatile StopCalculating * stop = 0) +- { +- using namespace auxiliaryfunctions; +- +- ValueType result; +- ErrorCode err_tmp; +- +- if( n.IsNan() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- return n; +- } +- +- if( cgamma.history.Get(n, result, err_tmp) ) +- { +- if( err ) +- *err = err_tmp; +- +- return result; +- } +- +- err_tmp = err_ok; +- +- if( n.IsSign() ) +- { +- result = GammaMinus(n, cgamma, err_tmp, stop); +- } +- else +- if( n.IsZero() ) +- { +- err_tmp = err_improper_argument; +- result.SetNan(); +- } +- else +- { +- result = GammaPlus(n, cgamma, err_tmp, stop); +- } +- +- if( result.IsNan() && err_tmp==err_ok ) +- err_tmp = err_overflow; +- +- if( err ) +- *err = err_tmp; +- +- if( stop && !stop->WasStopSignal() ) +- cgamma.history.Add(n, result, err_tmp); +- +- return result; +- } +- +- +- /*! +- this function calculates the Gamma function +- +- note: this function should be used only in a single-thread environment +- */ +- template +- ValueType Gamma(const ValueType & n, ErrorCode * err = 0) +- { +- // warning: this static object is not thread safe +- static CGamma cgamma; +- +- return Gamma(n, cgamma, err); +- } +- +- +- +- namespace auxiliaryfunctions +- { +- +- /*! +- an auxiliary function for calculating the factorial function +- +- we use the formula: +- x! = gamma(x+1) +- */ +- template +- ValueType Factorial2(ValueType x, +- CGamma * cgamma = 0, +- ErrorCode * err = 0, +- const volatile StopCalculating * stop = 0) +- { +- ValueType result, one; +- +- if( x.IsNan() || x.IsSign() || !x.IsInteger() ) +- { +- if( err ) +- *err = err_improper_argument; +- +- x.SetNan(); +- +- return x; +- } +- +- one.SetOne(); +- x.Add(one); +- +- if( cgamma ) +- return Gamma(x, *cgamma, err, stop); +- +- return Gamma(x, err); +- } +- +- } // namespace auxiliaryfunctions +- +- +- +- /*! +- the factorial from given 'x' +- e.g. +- Factorial(4) = 4! = 1*2*3*4 +- +- it's multithread safe, you should create a CGamma<> object and use it whenever you call the Factorial() +- e.g. +- typedef Big<1,2> MyBig; +- MyBig x=234, y=54345; +- CGamma cgamma; +- std::cout << Factorial(x, cgamma) << std::endl; +- std::cout << Factorial(y, cgamma) << std::endl; +- in the CGamma<> object the function stores some coefficients (factorials, Bernoulli numbers), +- and they will be reused in next calls to the function +- +- each thread should have its own CGamma<> object, and you can use these objects with Gamma() function too +- */ +- template +- ValueType Factorial(const ValueType & x, CGamma & cgamma, ErrorCode * err = 0, +- const volatile StopCalculating * stop = 0) +- { +- return auxiliaryfunctions::Factorial2(x, &cgamma, err, stop); +- } +- +- +- /*! +- the factorial from given 'x' +- e.g. +- Factorial(4) = 4! = 1*2*3*4 +- +- note: this function should be used only in a single-thread environment +- */ +- template +- ValueType Factorial(const ValueType & x, ErrorCode * err = 0) +- { +- return auxiliaryfunctions::Factorial2(x, (CGamma*)0, err, 0); +- } +- +- +- /*! +- this method prepares some coefficients: factorials and Bernoulli numbers +- stored in 'fact' and 'bern' objects +- +- we're defining the method here because we're using Gamma() function which +- is not available in ttmathobjects.h +- +- read the doc info in ttmathobjects.h file where CGamma<> struct is declared +- */ +- template +- void CGamma::InitAll() +- { +- ValueType x = TTMATH_GAMMA_BOUNDARY + 1; +- +- // history.Remove(x) removes only one object +- // we must be sure that there are not others objects with the key 'x' +- while( history.Remove(x) ) +- { +- } +- +- // the simplest way to initialize is to call the Gamma function with (TTMATH_GAMMA_BOUNDARY + 1) +- // when x is larger then fewer coefficients we need +- Gamma(x, *this); +- } +- +- +- +-} // namespace +- +- +-#ifdef _MSC_VER +-//warning C4127: conditional expression is constant +-#pragma warning( default: 4127 ) +-//warning C4702: unreachable code +-#pragma warning( default: 4702 ) +-//warning C4800: forcing value to bool 'true' or 'false' (performance warning) +-#pragma warning( default: 4800 ) +-#endif +- +-#endif +diff --git a/extern/ttmath/ttmathint.h b/extern/ttmath/ttmathint.h +deleted file mode 100644 +index 8ad0189f93..0000000000 +--- a/extern/ttmath/ttmathint.h ++++ /dev/null +@@ -1,1917 +0,0 @@ +-/* +- * This file is a part of TTMath Bignum Library +- * and is distributed under the (new) BSD licence. +- * Author: Tomasz Sowa +- */ +- +-/* +- * Copyright (c) 2006-2011, Tomasz Sowa +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * +- * * Redistributions of source code must retain the above copyright notice, +- * this list of conditions and the following disclaimer. +- * +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * +- * * Neither the name Tomasz Sowa nor the names of contributors to this +- * project may be used to endorse or promote products derived +- * from this software without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +- * THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +- +- +-#ifndef headerfilettmathint +-#define headerfilettmathint +- +-/*! +- \file ttmathint.h +- \brief template class Int +-*/ +- +-#include "ttmathuint.h" +- +-namespace ttmath +-{ +- +- +-/*! +- \brief Int implements a big integer value with a sign +- +- value_size - how many bytes specify our value +- on 32bit platforms: value_size=1 -> 4 bytes -> 32 bits +- on 64bit platforms: value_size=1 -> 8 bytes -> 64 bits +- value_size = 1,2,3,4,5,6.... +-*/ +-template +-class Int : public UInt +-{ +-public: +- +- /*! +- this method sets the max value which this class can hold +- (all bits will be one besides the last one) +- */ +- void SetMax() +- { +- UInt::SetMax(); +- UInt::table[value_size-1] = ~ TTMATH_UINT_HIGHEST_BIT; +- } +- +- +- /*! +- this method sets the min value which this class can hold +- (all bits will be zero besides the last one which is one) +- */ +- void SetMin() +- { +- UInt::SetZero(); +- UInt::table[value_size-1] = TTMATH_UINT_HIGHEST_BIT; +- } +- +- +- /*! +- this method sets -1 as the value +- (-1 is equal the max value in an unsigned type) +- */ +- void SetSignOne() +- { +- UInt::SetMax(); +- } +- +- +- /*! +- we change the sign of the value +- +- if it isn't possible to change the sign this method returns 1 +- else return 0 and changing the sign +- */ +- uint ChangeSign() +- { +- /* +- if the value is equal that one which has been returned from SetMin +- (only the highest bit is set) that means we can't change sign +- because the value is too big (bigger about one) +- +- e.g. when value_size = 1 and value is -2147483648 we can't change it to the +- 2147483648 because the max value which can be held is 2147483647 +- +- we don't change the value and we're using this fact somewhere in some methods +- (if we look on our value without the sign we get the correct value +- eg. -2147483648 in Int<1> will be 2147483648 on the UInt<1> type) +- */ +- if( UInt::IsOnlyTheHighestBitSet() ) +- return 1; +- +- UInt temp(*this); +- UInt::SetZero(); +- UInt::Sub(temp); +- +- return 0; +- } +- +- +- +- /*! +- this method sets the sign +- +- e.g. 1 -> -1 +- -2 -> -2 +- +- from a positive value we make a negative value, +- if the value is negative we do nothing +- */ +- void SetSign() +- { +- if( IsSign() ) +- return; +- +- ChangeSign(); +- } +- +- +- +- /*! +- this method returns true if there's the sign +- +- (the highest bit will be converted to the bool) +- */ +- bool IsSign() const +- { +- return UInt::IsTheHighestBitSet(); +- } +- +- +- +- /*! +- it sets an absolute value +- +- it can return carry (1) (look on ChangeSign() for details) +- */ +- uint Abs() +- { +- if( !IsSign() ) +- return 0; +- +- return ChangeSign(); +- } +- +- +- +- +- /*! +- * +- * basic mathematic functions +- * +- */ +- +-private: +- +- uint CorrectCarryAfterAdding(bool p1_is_sign, bool p2_is_sign) +- { +- if( !p1_is_sign && !p2_is_sign ) +- { +- if( UInt::IsTheHighestBitSet() ) +- return 1; +- } +- +- if( p1_is_sign && p2_is_sign ) +- { +- if( ! UInt::IsTheHighestBitSet() ) +- return 1; +- } +- +- return 0; +- } +- +- +-public: +- +- /*! +- this method adds two value with a sign and returns a carry +- +- we're using methods from the base class because values are stored with U2 +- we must only make the carry correction +- +- this = p1(=this) + p2 +- +- when p1>=0 i p2>=0 carry is set when the highest bit of value is set +- when p1<0 i p2<0 carry is set when the highest bit of value is clear +- when p1>=0 i p2<0 carry will never be set +- when p1<0 i p2>=0 carry will never be set +- */ +- uint Add(const Int & ss2) +- { +- bool p1_is_sign = IsSign(); +- bool p2_is_sign = ss2.IsSign(); +- +- UInt::Add(ss2); +- +- return CorrectCarryAfterAdding(p1_is_sign, p2_is_sign); +- } +- +- +- /*! +- this method adds one *unsigned* word (at a specific position) +- and returns a carry (if it was) +- +- look at a description in UInt<>::AddInt(...) +- */ +- uint AddInt(uint value, uint index = 0) +- { +- bool p1_is_sign = IsSign(); +- +- UInt::AddInt(value, index); +- +- return CorrectCarryAfterAdding(p1_is_sign, false); +- } +- +- +- /*! +- this method adds two *unsigned* words to the existing value +- and these words begin on the 'index' position +- +- index should be equal or smaller than value_size-2 (index <= value_size-2) +- x1 - lower word, x2 - higher word +- +- look at a description in UInt<>::AddTwoInts(...) +- */ +- uint AddTwoInts(uint x2, uint x1, uint index) +- { +- bool p1_is_sign = IsSign(); +- +- UInt::AddTwoInts(x2, x1, index); +- +- return CorrectCarryAfterAdding(p1_is_sign, false); +- } +- +-private: +- +- uint CorrectCarryAfterSubtracting(bool p1_is_sign, bool p2_is_sign) +- { +- if( !p1_is_sign && p2_is_sign ) +- { +- if( UInt::IsTheHighestBitSet() ) +- return 1; +- } +- +- if( p1_is_sign && !p2_is_sign ) +- { +- if( ! UInt::IsTheHighestBitSet() ) +- return 1; +- } +- +- return 0; +- } +- +-public: +- +- /*! +- this method subtracts two values with a sign +- +- we don't use the previous Add because the method ChangeSign can +- sometimes return carry +- +- this = p1(=this) - p2 +- +- when p1>=0 i p2>=0 carry will never be set +- when p1<0 i p2<0 carry will never be set +- when p1>=0 i p2<0 carry is set when the highest bit of value is set +- when p1<0 i p2>=0 carry is set when the highest bit of value is clear +- */ +- uint Sub(const Int & ss2) +- { +- bool p1_is_sign = IsSign(); +- bool p2_is_sign = ss2.IsSign(); +- +- UInt::Sub(ss2); +- +- return CorrectCarryAfterSubtracting(p1_is_sign, p2_is_sign); +- } +- +- +- /*! +- this method subtracts one *unsigned* word (at a specific position) +- and returns a carry (if it was) +- */ +- uint SubInt(uint value, uint index = 0) +- { +- bool p1_is_sign = IsSign(); +- +- UInt::SubInt(value, index); +- +- return CorrectCarryAfterSubtracting(p1_is_sign, false); +- } +- +- +- /*! +- this method adds one to the value and returns carry +- */ +- uint AddOne() +- { +- bool p1_is_sign = IsSign(); +- +- UInt::AddOne(); +- +- return CorrectCarryAfterAdding(p1_is_sign, false); +- } +- +- +- /*! +- this method subtracts one from the value and returns carry +- */ +- uint SubOne() +- { +- bool p1_is_sign = IsSign(); +- +- UInt::SubOne(); +- +- return CorrectCarryAfterSubtracting(p1_is_sign, false); +- } +- +- +-private: +- +- +- uint CheckMinCarry(bool ss1_is_sign, bool ss2_is_sign) +- { +- /* +- we have to examine the sign of the result now +- but if the result is with the sign then: +- 1. if the signs were the same that means the result is too big +- (the result must be without a sign) +- 2. if the signs were different that means if the result +- is different from that one which has been returned from SetMin() +- that is carry (result too big) but if the result is equal SetMin() +- there'll be ok (and the next SetSign will has no effect because +- the value is actually negative -- look at description of that case +- in ChangeSign()) +- */ +- if( IsSign() ) +- { +- if( ss1_is_sign != ss2_is_sign ) +- { +- /* +- there can be one case where signs are different and +- the result will be equal the value from SetMin() (only the highest bit is set) +- (this situation is ok) +- */ +- if( !UInt::IsOnlyTheHighestBitSet() ) +- return 1; +- } +- else +- { +- // signs were the same +- return 1; +- } +- } +- +- return 0; +- } +- +- +-public: +- +- +- /*! +- multiplication: this = this * ss2 +- +- it can return a carry +- */ +- uint MulInt(sint ss2) +- { +- bool ss1_is_sign, ss2_is_sign; +- uint c; +- +- ss1_is_sign = IsSign(); +- +- /* +- we don't have to check the carry from Abs (values will be correct +- because next we're using the method MulInt from the base class UInt +- which is without a sign) +- */ +- Abs(); +- +- if( ss2 < 0 ) +- { +- ss2 = -ss2; +- ss2_is_sign = true; +- } +- else +- { +- ss2_is_sign = false; +- } +- +- c = UInt::MulInt((uint)ss2); +- c += CheckMinCarry(ss1_is_sign, ss2_is_sign); +- +- if( ss1_is_sign != ss2_is_sign ) +- SetSign(); +- +- return c; +- } +- +- +- +- /*! +- multiplication this = this * ss2 +- +- it returns carry if the result is too big +- (we're using the method from the base class but we have to make +- one correction in account of signs) +- */ +- uint Mul(Int ss2) +- { +- bool ss1_is_sign, ss2_is_sign; +- uint c; +- +- ss1_is_sign = IsSign(); +- ss2_is_sign = ss2.IsSign(); +- +- /* +- we don't have to check the carry from Abs (values will be correct +- because next we're using the method Mul from the base class UInt +- which is without a sign) +- */ +- Abs(); +- ss2.Abs(); +- +- c = UInt::Mul(ss2); +- c += CheckMinCarry(ss1_is_sign, ss2_is_sign); +- +- if( ss1_is_sign != ss2_is_sign ) +- SetSign(); +- +- return c; +- } +- +- +- /*! +- division this = this / ss2 +- returned values: +- 0 - ok +- 1 - division by zero +- +- for example: (result means 'this') +- 20 / 3 --> result: 6 remainder: 2 +- -20 / 3 --> result: -6 remainder: -2 +- 20 / -3 --> result: -6 remainder: 2 +- -20 / -3 --> result: 6 remainder: -2 +- +- in other words: this(old) = ss2 * this(new)(result) + remainder +- */ +- uint Div(Int ss2, Int * remainder = 0) +- { +- bool ss1_is_sign, ss2_is_sign; +- +- ss1_is_sign = IsSign(); +- ss2_is_sign = ss2.IsSign(); +- +- /* +- we don't have to test the carry from Abs as well as in Mul +- */ +- Abs(); +- ss2.Abs(); +- +- uint c = UInt::Div(ss2, remainder); +- +- if( ss1_is_sign != ss2_is_sign ) +- SetSign(); +- +- if( ss1_is_sign && remainder ) +- remainder->SetSign(); +- +- return c; +- } +- +- uint Div(const Int & ss2, Int & remainder) +- { +- return Div(ss2, &remainder); +- } +- +- +- /*! +- division this = this / ss2 (ss2 is int) +- returned values: +- 0 - ok +- 1 - division by zero +- +- for example: (result means 'this') +- 20 / 3 --> result: 6 remainder: 2 +- -20 / 3 --> result: -6 remainder: -2 +- 20 / -3 --> result: -6 remainder: 2 +- -20 / -3 --> result: 6 remainder: -2 +- +- in other words: this(old) = ss2 * this(new)(result) + remainder +- */ +- uint DivInt(sint ss2, sint * remainder = 0) +- { +- bool ss1_is_sign, ss2_is_sign; +- +- ss1_is_sign = IsSign(); +- +- /* +- we don't have to test the carry from Abs as well as in Mul +- */ +- Abs(); +- +- if( ss2 < 0 ) +- { +- ss2 = -ss2; +- ss2_is_sign = true; +- } +- else +- { +- ss2_is_sign = false; +- } +- +- uint rem; +- uint c = UInt::DivInt((uint)ss2, &rem); +- +- if( ss1_is_sign != ss2_is_sign ) +- SetSign(); +- +- if( remainder ) +- { +- if( ss1_is_sign ) +- *remainder = -sint(rem); +- else +- *remainder = sint(rem); +- } +- +- return c; +- } +- +- +- uint DivInt(sint ss2, sint & remainder) +- { +- return DivInt(ss2, &remainder); +- } +- +- +-private: +- +- +- /*! +- power this = this ^ pow +- this can be negative +- pow is >= 0 +- */ +- uint Pow2(const Int & pow) +- { +- bool was_sign = IsSign(); +- uint c = 0; +- +- if( was_sign ) +- c += Abs(); +- +- uint c_temp = UInt::Pow(pow); +- if( c_temp > 0 ) +- return c_temp; // c_temp can be: 0, 1 or 2 +- +- if( was_sign && (pow.table[0] & 1) == 1 ) +- // negative value to the power of odd number is negative +- c += ChangeSign(); +- +- return (c==0)? 0 : 1; +- } +- +- +-public: +- +- +- /*! +- power this = this ^ pow +- +- return values: +- 0 - ok +- 1 - carry +- 2 - incorrect arguments 0^0 or 0^(-something) +- */ +- uint Pow(Int pow) +- { +- if( !pow.IsSign() ) +- return Pow2(pow); +- +- if( UInt::IsZero() ) +- // if 'pow' is negative then +- // 'this' must be different from zero +- return 2; +- +- if( pow.ChangeSign() ) +- return 1; +- +- Int t(*this); +- uint c_temp = t.Pow2(pow); +- if( c_temp > 0 ) +- return c_temp; +- +- UInt::SetOne(); +- if( Div(t) ) +- return 1; +- +- return 0; +- } +- +- +- +- /*! +- * +- * convertion methods +- * +- */ +-private: +- +- +- /*! +- an auxiliary method for converting both from UInt and Int +- */ +- template +- uint FromUIntOrInt(const UInt & p, bool UInt_type) +- { +- uint min_size = (value_size < argument_size)? value_size : argument_size; +- uint i; +- +- for(i=0 ; i::table[i] = p.table[i]; +- +- +- if( value_size > argument_size ) +- { +- uint fill; +- +- if( UInt_type ) +- fill = 0; +- else +- fill = (p.table[argument_size-1] & TTMATH_UINT_HIGHEST_BIT)? +- TTMATH_UINT_MAX_VALUE : 0; +- +- // 'this' is longer than 'p' +- for( ; i::table[i] = fill; +- } +- else +- { +- uint test = (UInt::table[value_size-1] & TTMATH_UINT_HIGHEST_BIT)? +- TTMATH_UINT_MAX_VALUE : 0; +- +- if( UInt_type && test!=0 ) +- return 1; +- +- for( ; i type into this class +- +- this operation has mainly sense if the value from p +- can be held in this type +- +- it returns a carry if the value 'p' is too big +- */ +- template +- uint FromInt(const Int & p) +- { +- return FromUIntOrInt(p, false); +- } +- +- +- /*! +- this method converts the sint type into this class +- */ +- uint FromInt(sint value) +- { +- uint fill = ( value<0 ) ? TTMATH_UINT_MAX_VALUE : 0; +- +- for(uint i=1 ; i::table[i] = fill; +- +- UInt::table[0] = uint(value); +- +- // there'll never be a carry here +- return 0; +- } +- +- +- /*! +- this method converts UInt into this class +- */ +- template +- uint FromUInt(const UInt & p) +- { +- return FromUIntOrInt(p, true); +- } +- +- +- /*! +- this method converts UInt into this class +- */ +- template +- uint FromInt(const UInt & p) +- { +- return FromUIntOrInt(p, true); +- } +- +- +- /*! +- this method converts the uint type into this class +- */ +- uint FromUInt(uint value) +- { +- for(uint i=1 ; i::table[i] = 0; +- +- UInt::table[0] = value; +- +- // there can be a carry here when the size of this value is equal one word +- // and the 'value' has the highest bit set +- if( value_size==1 && (value & TTMATH_UINT_HIGHEST_BIT)!=0 ) +- return 1; +- +- return 0; +- } +- +- +- /*! +- this method converts the uint type into this class +- */ +- uint FromInt(uint value) +- { +- return FromUInt(value); +- } +- +- +- /*! +- the default assignment operator +- */ +-/* Int & operator=(const Int & p) +- { +- FromInt(p); +- +- return *this; +- } +- */ +- +- /*! +- this operator converts an Int type to this class +- +- it doesn't return a carry +- */ +-/* template +- Int & operator=(const Int & p) +- { +- FromInt(p); +- +- return *this; +- } +- */ +- +- /*! +- this method converts the sint type to this class +- */ +- Int & operator=(sint i) +- { +- FromInt(i); +- +- return *this; +- } +- +- +- /*! +- a constructor for converting the uint to this class +- */ +-/* Int(sint i) +- { +- FromInt(i); +- } +-*/ +- +- /*! +- a copy constructor +- */ +-/* Int(const Int & u) +- { +- FromInt(u); +- } +-*/ +- +- /*! +- a constructor for copying from another types +- */ +-/* template +- Int(const Int & u) +- { +- // look that 'size' we still set as 'value_size' and not as u.value_size +- FromInt(u); +- } +-*/ +- +- +- /*! +- this operator converts an UInt type to this class +- +- it doesn't return a carry +- */ +- template +- Int & operator=(const UInt & p) +- { +- FromUInt(p); +- +- return *this; +- } +- +- +- /*! +- this method converts the Uint type to this class +- */ +- Int & operator=(uint i) +- { +- FromUInt(i); +- +- return *this; +- } +- +- +- /*! +- a constructor for converting the uint to this class +- */ +-/* Int(uint i) +- { +- FromUInt(i); +- } +-*/ +- +- /*! +- a constructor for copying from another types +- */ +-/* template +- Int(const UInt & u) +- { +- // look that 'size' we still set as 'value_size' and not as u.value_size +- FromUInt(u); +- } +-*/ +- +- +-#ifdef TTMATH_PLATFORM32 +- +- +- /*! +- this method converts unsigned 64 bit int type to this class +- ***this method is created only on a 32bit platform*** +- */ +- uint FromUInt(ulint n) +- { +- uint c = UInt::FromUInt(n); +- +- if( c ) +- return 1; +- +- if( value_size == 1 ) +- return ((UInt::table[0] & TTMATH_UINT_HIGHEST_BIT) == 0) ? 0 : 1; +- +- if( value_size == 2 ) +- return ((UInt::table[1] & TTMATH_UINT_HIGHEST_BIT) == 0) ? 0 : 1; +- +- return 0; +- } +- +- +- /*! +- this method converts unsigned 64 bit int type to this class +- ***this method is created only on a 32bit platform*** +- */ +- uint FromInt(ulint n) +- { +- return FromUInt(n); +- } +- +- +- /*! +- this method converts signed 64 bit int type to this class +- ***this method is created only on a 32bit platform*** +- */ +- uint FromInt(slint n) +- { +- uint mask = (n < 0) ? TTMATH_UINT_MAX_VALUE : 0; +- +- UInt::table[0] = (uint)(ulint)n; +- +- if( value_size == 1 ) +- { +- if( uint(ulint(n) >> 32) != mask ) +- return 1; +- +- return ((UInt::table[0] & TTMATH_UINT_HIGHEST_BIT) == (mask & TTMATH_UINT_HIGHEST_BIT)) ? 0 : 1; +- } +- +- UInt::table[1] = (uint)(ulint(n) >> 32); +- +- for(uint i=2 ; i::table[i] = mask; +- +- return 0; +- } +- +- +- /*! +- this operator converts unsigned 64 bit int type to this class +- ***this operator is created only on a 32bit platform*** +- */ +- Int & operator=(ulint n) +- { +- FromUInt(n); +- +- return *this; +- } +- +- +- /*! +- a constructor for converting unsigned 64 bit int to this class +- ***this constructor is created only on a 32bit platform*** +- */ +-/* Int(ulint n) +- { +- FromUInt(n); +- } +-*/ +- +- /*! +- this operator converts signed 64 bit int type to this class +- ***this operator is created only on a 32bit platform*** +- */ +- Int & operator=(slint n) +- { +- FromInt(n); +- +- return *this; +- } +- +- +- /*! +- a constructor for converting signed 64 bit int to this class +- ***this constructor is created only on a 32bit platform*** +- */ +-/* Int(slint n) +- { +- FromInt(n); +- } +-*/ +-#endif +- +- +- +- +-#ifdef TTMATH_PLATFORM64 +- +- /*! +- this method converts 32 bit unsigned int type to this class +- ***this operator is created only on a 64bit platform*** +- */ +- uint FromUInt(unsigned int i) +- { +- return FromUInt(uint(i)); +- } +- +- +- /*! +- this method converts 32 bit unsigned int type to this class +- ***this operator is created only on a 64bit platform*** +- */ +- uint FromInt(unsigned int i) +- { +- return FromUInt(i); +- } +- +- +- /*! +- this method converts 32 bit signed int type to this class +- ***this operator is created only on a 64bit platform*** +- */ +- uint FromInt(signed int i) +- { +- return FromInt(sint(i)); +- } +- +- +- /*! +- this method converts 32 bit unsigned int type to this class +- ***this operator is created only on a 64bit platform*** +- */ +- Int & operator=(unsigned int i) +- { +- FromUInt(i); +- +- return *this; +- } +- +- +- /*! +- a constructor for converting 32 bit unsigned int to this class +- ***this constructor is created only on a 64bit platform*** +- */ +-/* Int(unsigned int i) +- { +- FromUInt(i); +- } +-*/ +- +- /*! +- this operator converts 32 bit signed int type to this class +- ***this operator is created only on a 64bit platform*** +- */ +- Int & operator=(signed int i) +- { +- FromInt(i); +- +- return *this; +- } +- +- +- /*! +- a constructor for converting 32 bit signed int to this class +- ***this constructor is created only on a 64bit platform*** +- */ +-/* Int(signed int i) +- { +- FromInt(i); +- } +-*/ +-#endif +- +- +- +- /*! +- a constructor for converting string to this class (with the base=10) +- */ +-/* Int(const char * s) +- { +- FromString(s); +- } +-*/ +- +- /*! +- a constructor for converting a string to this class (with the base=10) +- */ +-/* Int(const std::string & s) +- { +- FromString( s.c_str() ); +- } +-*/ +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- /*! +- a constructor for converting string to this class (with the base=10) +- */ +- Int(const wchar_t * s) +- { +- FromString(s); +- } +- +- +- /*! +- a constructor for converting a string to this class (with the base=10) +- */ +- Int(const std::wstring & s) +- { +- FromString( s.c_str() ); +- } +- +-#endif +- +- +- /*! +- a default constructor +- +- we don't clear table etc. +- */ +-/* Int() +- { +- } +-*/ +- +- /*! +- the destructor +- */ +-/* ~Int() +- { +- } +-*/ +- +- /*! +- this method returns the lowest value from table with a sign +- +- we must be sure when we using this method whether the value +- will hold in an sint type or not (the rest value from table must be zero or -1) +- */ +- sint ToInt() const +- { +- return sint( UInt::table[0] ); +- } +- +- +- /*! +- this method converts the value to uint type +- can return a carry if the value is too long to store it in uint type +- */ +- uint ToUInt(uint & result) const +- { +- uint c = UInt::ToUInt(result); +- +- if( value_size == 1 ) +- return (result & TTMATH_UINT_HIGHEST_BIT) == 0 ? 0 : 1; +- +- return c; +- } +- +- +- /*! +- this method converts the value to uint type +- can return a carry if the value is too long to store it in uint type +- */ +- uint ToInt(uint & result) const +- { +- return ToUInt(result); +- } +- +- +- /*! +- this method converts the value to sint type +- can return a carry if the value is too long to store it in sint type +- */ +- uint ToInt(sint & result) const +- { +- result = sint( UInt::table[0] ); +- uint mask = IsSign() ? TTMATH_UINT_MAX_VALUE : 0; +- +- if( (result & TTMATH_UINT_HIGHEST_BIT) != (mask & TTMATH_UINT_HIGHEST_BIT) ) +- return 1; +- +- for(uint i=1 ; i::table[i] != mask ) +- return 1; +- +- return 0; +- } +- +- +-#ifdef TTMATH_PLATFORM32 +- +- /*! +- this method converts the value to ulint type (64 bit unsigned integer) +- can return a carry if the value is too long to store it in ulint type +- *** this method is created only on a 32 bit platform *** +- */ +- uint ToUInt(ulint & result) const +- { +- uint c = UInt::ToUInt(result); +- +- if( value_size == 1 ) +- return (UInt::table[0] & TTMATH_UINT_HIGHEST_BIT) == 0 ? 0 : 1; +- +- if( value_size == 2 ) +- return (UInt::table[1] & TTMATH_UINT_HIGHEST_BIT) == 0 ? 0 : 1; +- +- return c; +- } +- +- +- /*! +- this method converts the value to ulint type (64 bit unsigned integer) +- can return a carry if the value is too long to store it in ulint type +- *** this method is created only on a 32 bit platform *** +- */ +- uint ToInt(ulint & result) const +- { +- return ToUInt(result); +- } +- +- +- /*! +- this method converts the value to slint type (64 bit signed integer) +- can return a carry if the value is too long to store it in slint type +- *** this method is created only on a 32 bit platform *** +- */ +- uint ToInt(slint & result) const +- { +- if( value_size == 1 ) +- { +- result = slint(sint(UInt::table[0])); +- } +- else +- { +- uint low = UInt::table[0]; +- uint high = UInt::table[1]; +- +- result = low; +- result |= (ulint(high) << TTMATH_BITS_PER_UINT); +- +- uint mask = IsSign() ? TTMATH_UINT_MAX_VALUE : 0; +- +- if( (high & TTMATH_UINT_HIGHEST_BIT) != (mask & TTMATH_UINT_HIGHEST_BIT) ) +- return 1; +- +- for(uint i=2 ; i::table[i] != mask ) +- return 1; +- } +- +- return 0; +- } +- +-#endif +- +- +- +-#ifdef TTMATH_PLATFORM64 +- +- /*! +- this method converts the value to a 32 bit unsigned integer +- can return a carry if the value is too long to store it in this type +- *** this method is created only on a 64 bit platform *** +- */ +- uint ToUInt(unsigned int & result) const +- { +- uint c = UInt::ToUInt(result); +- +- if( c || IsSign() ) +- return 1; +- +- return 0; +- } +- +- +- /*! +- this method converts the value to a 32 bit unsigned integer +- can return a carry if the value is too long to store it in this type +- *** this method is created only on a 64 bit platform *** +- */ +- uint ToInt(unsigned int & result) const +- { +- return ToUInt(result); +- } +- +- +- /*! +- this method converts the value to a 32 bit signed integer +- can return a carry if the value is too long to store it in this type +- *** this method is created only on a 64 bit platform *** +- */ +- uint ToInt(int & result) const +- { +- uint first = UInt::table[0]; +- +- result = int(first); +- uint mask = IsSign() ? TTMATH_UINT_MAX_VALUE : 0; +- +- if( (first >> 31) != (mask >> 31) ) +- return 1; +- +- for(uint i=1 ; i::table[i] != mask ) +- return 1; +- +- return 0; +- } +- +-#endif +- +- +- +- /*! +- an auxiliary method for converting to a string +- */ +- template +- void ToStringBase(string_type & result, uint b = 10) const +- { +- if( IsSign() ) +- { +- Int temp(*this); +- temp.Abs(); +- temp.UInt::ToStringBase(result, b, true); +- } +- else +- { +- UInt::ToStringBase(result, b, false); +- } +- } +- +- /*! +- this method converts the value to a string with a base equal 'b' +- */ +- void ToString(std::string & result, uint b = 10) const +- { +- return ToStringBase(result, b); +- } +- +- +- /*! +- this method converts the value to a string with a base equal 'b' +- */ +- std::string ToString(uint b = 10) const +- { +- std::string result; +- ToStringBase(result, b); +- +- return result; +- } +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- /*! +- this method converts the value to a string with a base equal 'b' +- */ +- void ToString(std::wstring & result, uint b = 10) const +- { +- return ToStringBase(result, b); +- } +- +- +- /*! +- this method converts the value to a string with a base equal 'b' +- */ +- std::wstring ToWString(uint b = 10) const +- { +- std::wstring result; +- ToStringBase(result, b); +- +- return result; +- } +- +-#endif +- +- +- +-private: +- +- /*! +- an auxiliary method for converting from a string +- */ +- template +- uint FromStringBase(const char_type * s, uint b = 10, const char_type ** after_source = 0, bool * value_read = 0) +- { +- bool is_sign = false; +- +- Misc::SkipWhiteCharacters(s); +- +- if( *s == '-' ) +- { +- is_sign = true; +- Misc::SkipWhiteCharacters(++s); +- } +- else +- if( *s == '+' ) +- { +- Misc::SkipWhiteCharacters(++s); +- } +- +- if( UInt::FromString(s,b,after_source,value_read) ) +- return 1; +- +- if( is_sign ) +- { +- Int mmin; +- +- mmin.SetMin(); +- +- /* +- the reference to mmin will be automatically converted to the reference +- to UInt type +- (this value can be equal mmin -- look at a description in ChangeSign()) +- */ +- if( UInt::operator>( mmin ) ) +- return 1; +- +- /* +- if the value is equal mmin the method ChangeSign() does nothing (only returns 1 but we ignore it) +- */ +- ChangeSign(); +- } +- else +- { +- Int mmax; +- +- mmax.SetMax(); +- +- if( UInt::operator>( mmax ) ) +- return 1; +- } +- +- return 0; +- } +- +- +-public: +- +- /*! +- this method converts a string into its value +- it returns carry=1 if the value will be too big or an incorrect base 'b' is given +- +- string is ended with a non-digit value, for example: +- "-12" will be translated to -12 +- as well as: +- "- 12foo" will be translated to -12 too +- +- existing first white characters will be ommited +- (between '-' and a first digit can be white characters too) +- +- after_source (if exists) is pointing at the end of the parsed string +- +- value_read (if exists) tells whether something has actually been read (at least one digit) +- */ +- uint FromString(const char * s, uint b = 10, const char ** after_source = 0, bool * value_read = 0) +- { +- return FromStringBase(s, b, after_source, value_read); +- } +- +- +- /*! +- this method converts a string into its value +- */ +- uint FromString(const wchar_t * s, uint b = 10, const wchar_t ** after_source = 0, bool * value_read = 0) +- { +- return FromStringBase(s, b, after_source, value_read); +- } +- +- +- /*! +- this method converts a string into its value +- it returns carry=1 if the value will be too big or an incorrect base 'b' is given +- */ +- uint FromString(const std::string & s, uint b = 10) +- { +- return FromString( s.c_str(), b ); +- } +- +- +- /*! +- this operator converts a string into its value (with base = 10) +- */ +- Int & operator=(const char * s) +- { +- FromString(s); +- +- return *this; +- } +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- +- /*! +- this method converts a string into its value +- it returns carry=1 if the value will be too big or an incorrect base 'b' is given +- */ +- uint FromString(const std::wstring & s, uint b = 10) +- { +- return FromString( s.c_str(), b ); +- } +- +- +- /*! +- this operator converts a string into its value (with base = 10) +- */ +- Int & operator=(const wchar_t * s) +- { +- FromString(s); +- +- return *this; +- } +- +- +- /*! +- this operator converts a string into its value (with base = 10) +- */ +- Int & operator=(const std::wstring & s) +- { +- FromString( s.c_str() ); +- +- return *this; +- } +- +-#endif +- +- +- /*! +- this operator converts a string into its value (with base = 10) +- */ +- Int & operator=(const std::string & s) +- { +- FromString( s.c_str() ); +- +- return *this; +- } +- +- +- +- /*! +- * +- * methods for comparing +- * +- * +- */ +- +- bool operator==(const Int & l) const +- { +- return UInt::operator==(l); +- } +- +- bool operator!=(const Int & l) const +- { +- return UInt::operator!=(l); +- } +- +- bool operator<(const Int & l) const +- { +- sint i=value_size-1; +- +- sint a1 = sint(UInt::table[i]); +- sint a2 = sint(l.table[i]); +- +- if( a1 != a2 ) +- return a1 < a2; +- +- +- for(--i ; i>=0 ; --i) +- { +- if( UInt::table[i] != l.table[i] ) +- // comparison as unsigned int +- return UInt::table[i] < l.table[i]; +- } +- +- // they're equal +- return false; +- } +- +- +- bool operator>(const Int & l) const +- { +- sint i=value_size-1; +- +- sint a1 = sint(UInt::table[i]); +- sint a2 = sint(l.table[i]); +- +- if( a1 != a2 ) +- return a1 > a2; +- +- +- for(--i ; i>=0 ; --i) +- { +- if( UInt::table[i] != l.table[i] ) +- // comparison as unsigned int +- return UInt::table[i] > l.table[i]; +- } +- +- // they're equal +- return false; +- } +- +- +- bool operator<=(const Int & l) const +- { +- sint i=value_size-1; +- +- sint a1 = sint(UInt::table[i]); +- sint a2 = sint(l.table[i]); +- +- if( a1 != a2 ) +- return a1 < a2; +- +- +- for(--i ; i>=0 ; --i) +- { +- if( UInt::table[i] != l.table[i] ) +- // comparison as unsigned int +- return UInt::table[i] < l.table[i]; +- } +- +- // they're equal +- return true; +- } +- +- +- bool operator>=(const Int & l) const +- { +- sint i=value_size-1; +- +- sint a1 = sint(UInt::table[i]); +- sint a2 = sint(l.table[i]); +- +- if( a1 != a2 ) +- return a1 > a2; +- +- +- for(--i ; i>=0 ; --i) +- { +- if( UInt::table[i] != l.table[i] ) +- // comparison as unsigned int +- return UInt::table[i] > l.table[i]; +- } +- +- // they're equal +- return true; +- } +- +- +- +- /*! +- * +- * standard mathematical operators +- * +- */ +- +- +- /*! +- an operator for changing the sign +- +- it's not changing 'this' but the changed value will be returned +- */ +- Int operator-() const +- { +- Int temp(*this); +- +- temp.ChangeSign(); +- +- return temp; +- } +- +- +- Int operator-(const Int & p2) const +- { +- Int temp(*this); +- +- temp.Sub(p2); +- +- return temp; +- } +- +- +- Int & operator-=(const Int & p2) +- { +- Sub(p2); +- +- return *this; +- } +- +- +- Int operator+(const Int & p2) const +- { +- Int temp(*this); +- +- temp.Add(p2); +- +- return temp; +- } +- +- +- Int & operator+=(const Int & p2) +- { +- Add(p2); +- +- return *this; +- } +- +- +- Int operator*(const Int & p2) const +- { +- Int temp(*this); +- +- temp.Mul(p2); +- +- return temp; +- } +- +- +- Int & operator*=(const Int & p2) +- { +- Mul(p2); +- +- return *this; +- } +- +- +- Int operator/(const Int & p2) const +- { +- Int temp(*this); +- +- temp.Div(p2); +- +- return temp; +- } +- +- +- Int & operator/=(const Int & p2) +- { +- Div(p2); +- +- return *this; +- } +- +- +- Int operator%(const Int & p2) const +- { +- Int temp(*this); +- Int remainder; +- +- temp.Div(p2, remainder); +- +- return remainder; +- } +- +- +- Int & operator%=(const Int & p2) +- { +- Int remainder; +- +- Div(p2, remainder); +- operator=(remainder); +- +- return *this; +- } +- +- +- /*! +- Prefix operator e.g. ++variable +- */ +- UInt & operator++() +- { +- AddOne(); +- +- return *this; +- } +- +- +- /*! +- Postfix operator e.g. variable++ +- */ +- UInt operator++(int) +- { +- UInt temp( *this ); +- +- AddOne(); +- +- return temp; +- } +- +- +- UInt & operator--() +- { +- SubOne(); +- +- return *this; +- } +- +- +- UInt operator--(int) +- { +- UInt temp( *this ); +- +- SubOne(); +- +- return temp; +- } +- +- +- +- /*! +- * +- * input/output operators for standard streams +- * +- */ +- +-private: +- +- /*! +- an auxiliary method for outputing to standard streams +- */ +- template +- static ostream_type & OutputToStream(ostream_type & s, const Int & l) +- { +- string_type ss; +- +- l.ToString(ss); +- s << ss; +- +- return s; +- } +- +- +- +-public: +- +- +- /*! +- output to standard streams +- */ +- friend std::ostream & operator<<(std::ostream & s, const Int & l) +- { +- return OutputToStream(s, l); +- } +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- /*! +- output to standard streams +- */ +- friend std::wostream & operator<<(std::wostream & s, const Int & l) +- { +- return OutputToStream(s, l); +- } +- +-#endif +- +- +- +-private: +- +- /*! +- an auxiliary method for converting from a string +- */ +- template +- static istream_type & InputFromStream(istream_type & s, Int & l) +- { +- string_type ss; +- +- // char or wchar_t for operator>> +- char_type z; +- +- // operator>> omits white characters if they're set for ommiting +- s >> z; +- +- if( z=='-' || z=='+' ) +- { +- ss += z; +- s >> z; // we're reading a next character (white characters can be ommited) +- } +- +- // we're reading only digits (base=10) +- while( s.good() && Misc::CharToDigit(z, 10)>=0 ) +- { +- ss += z; +- z = static_cast(s.get()); +- } +- +- // we're leaving the last readed character +- // (it's not belonging to the value) +- s.unget(); +- +- l.FromString(ss); +- +- return s; +- } +- +- +-public: +- +- /*! +- input from standard streams +- */ +- friend std::istream & operator>>(std::istream & s, Int & l) +- { +- return InputFromStream(s, l); +- } +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- /*! +- input from standard streams +- */ +- friend std::wistream & operator>>(std::wistream & s, Int & l) +- { +- return InputFromStream(s, l); +- } +-#endif +- +- +-}; +- +-} // namespace +- +-#endif +diff --git a/extern/ttmath/ttmathmisc.h b/extern/ttmath/ttmathmisc.h +deleted file mode 100644 +index 330a43a468..0000000000 +--- a/extern/ttmath/ttmathmisc.h ++++ /dev/null +@@ -1,250 +0,0 @@ +-/* +- * This file is a part of TTMath Bignum Library +- * and is distributed under the (new) BSD licence. +- * Author: Tomasz Sowa +- */ +- +-/* +- * Copyright (c) 2006-2010, Tomasz Sowa +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * +- * * Redistributions of source code must retain the above copyright notice, +- * this list of conditions and the following disclaimer. +- * +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * +- * * Neither the name Tomasz Sowa nor the names of contributors to this +- * project may be used to endorse or promote products derived +- * from this software without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +- * THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +-#ifndef headerfilettmathmisc +-#define headerfilettmathmisc +- +- +-/*! +- \file ttmathmisc.h +- \brief some helpful functions +-*/ +- +- +-#include +- +- +-namespace ttmath +-{ +- +-/*! +- some helpful functions +-*/ +-class Misc +-{ +-public: +- +- +-/* +- * +- * AssignString(result, str) +- * result = str +- * +- */ +- +-/*! +- result = str +-*/ +-static void AssignString(std::string & result, const char * str) +-{ +- result = str; +-} +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +-/*! +- result = str +-*/ +-static void AssignString(std::wstring & result, const char * str) +-{ +- result.clear(); +- +- for( ; *str ; ++str ) +- result += *str; +-} +- +- +-/*! +- result = str +-*/ +-static void AssignString(std::wstring & result, const std::string & str) +-{ +- return AssignString(result, str.c_str()); +-} +- +- +-/*! +- result = str +-*/ +-static void AssignString(std::string & result, const wchar_t * str) +-{ +- result.clear(); +- +- for( ; *str ; ++str ) +- result += static_cast(*str); +-} +- +- +-/*! +- result = str +-*/ +-static void AssignString(std::string & result, const std::wstring & str) +-{ +- return AssignString(result, str.c_str()); +-} +- +-#endif +- +- +-/* +- * +- * AddString(result, str) +- * result += str +- * +- */ +- +- +-/*! +- result += str +-*/ +-static void AddString(std::string & result, const char * str) +-{ +- result += str; +-} +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +-/*! +- result += str +-*/ +-static void AddString(std::wstring & result, const char * str) +-{ +- for( ; *str ; ++str ) +- result += *str; +-} +- +-#endif +- +- +-/* +- this method omits any white characters from the string +- char_type is char or wchar_t +-*/ +-template +-static void SkipWhiteCharacters(const char_type * & c) +-{ +- // 13 is at the end in a DOS text file (\r\n) +- while( (*c==' ' ) || (*c=='\t') || (*c==13 ) || (*c=='\n') ) +- ++c; +-} +- +- +- +- +-/*! +- this static method converts one character into its value +- +- for example: +- 1 -> 1 +- 8 -> 8 +- A -> 10 +- f -> 15 +- +- this method don't check whether c is correct or not +-*/ +-static uint CharToDigit(uint c) +-{ +- if(c>='0' && c<='9') +- return c-'0'; +- +- if(c>='a' && c<='z') +- return c-'a'+10; +- +-return c-'A'+10; +-} +- +- +-/*! +- this method changes a character 'c' into its value +- (if there can't be a correct value it returns -1) +- +- for example: +- c=2, base=10 -> function returns 2 +- c=A, base=10 -> function returns -1 +- c=A, base=16 -> function returns 10 +-*/ +-static sint CharToDigit(uint c, uint base) +-{ +- if( c>='0' && c<='9' ) +- c=c-'0'; +- else +- if( c>='a' && c<='z' ) +- c=c-'a'+10; +- else +- if( c>='A' && c<='Z' ) +- c=c-'A'+10; +- else +- return -1; +- +- +- if( c >= base ) +- return -1; +- +- +-return sint(c); +-} +- +- +- +-/*! +- this method converts a digit into a char +- digit should be from <0,F> +- (we don't have to get a base) +- +- for example: +- 1 -> 1 +- 8 -> 8 +- 10 -> A +- 15 -> F +-*/ +-static uint DigitToChar(uint digit) +-{ +- if( digit < 10 ) +- return digit + '0'; +- +-return digit - 10 + 'A'; +-} +- +- +-}; // struct Misc +- +-} +- +- +-#endif +diff --git a/extern/ttmath/ttmathobjects.h b/extern/ttmath/ttmathobjects.h +deleted file mode 100644 +index c35026bbd0..0000000000 +--- a/extern/ttmath/ttmathobjects.h ++++ /dev/null +@@ -1,809 +0,0 @@ +-/* +- * This file is a part of TTMath Mathematical Library +- * and is distributed under the (new) BSD licence. +- * Author: Tomasz Sowa +- */ +- +-/* +- * Copyright (c) 2006-2010, Tomasz Sowa +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * +- * * Redistributions of source code must retain the above copyright notice, +- * this list of conditions and the following disclaimer. +- * +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * +- * * Neither the name Tomasz Sowa nor the names of contributors to this +- * project may be used to endorse or promote products derived +- * from this software without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +- * THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +- +-#ifndef headerfilettmathobject +-#define headerfilettmathobject +- +-/*! +- \file ttmathobjects.h +- \brief Mathematic functions. +-*/ +- +-#include +-#include +-#include +-#include +- +-#include "ttmathtypes.h" +-#include "ttmathmisc.h" +- +- +-namespace ttmath +-{ +- +-/*! +- objects of this class are used with the mathematical parser +- they hold variables or functions defined by a user +- +- each object has its own table in which we're keeping variables or functions +-*/ +-class Objects +-{ +-public: +- +- +- /*! +- one item (variable or function) +- 'items' will be on the table +- */ +- struct Item +- { +- // name of a variable of a function +- // internally we store variables and funcions as std::string (not std::wstring even when wide characters are used) +- std::string value; +- +- // number of parameters required by the function +- // (if there's a variable this 'param' is ignored) +- int param; +- +- Item() {} +- Item(const std::string & v, int p) : value(v), param(p) {} +- }; +- +- // 'Table' is the type of our table +- typedef std::map Table; +- typedef Table::iterator Iterator; +- typedef Table::const_iterator CIterator; +- +- +- +- /*! +- this method returns true if a character 'c' is a character +- which can be in a name +- +- if 'can_be_digit' is true that means when the 'c' is a digit this +- method returns true otherwise it returns false +- */ +- static bool CorrectCharacter(int c, bool can_be_digit) +- { +- if( (c>='a' && c<='z') || (c>='A' && c<='Z') ) +- return true; +- +- if( can_be_digit && ((c>='0' && c<='9') || c=='_') ) +- return true; +- +- return false; +- } +- +- +- /*! +- this method returns true if the name can be as a name of an object +- */ +- template +- static bool IsNameCorrect(const string_type & name) +- { +- if( name.empty() ) +- return false; +- +- if( !CorrectCharacter(name[0], false) ) +- return false; +- +- typename string_type::const_iterator i = name.begin(); +- +- for(++i ; i!=name.end() ; ++i) +- if( !CorrectCharacter(*i, true) ) +- return false; +- +- return true; +- } +- +- +- /*! +- this method returns true if such an object is defined (name exists) +- */ +- bool IsDefined(const std::string & name) +- { +- Iterator i = table.find(name); +- +- if( i != table.end() ) +- // we have this object in our table +- return true; +- +- return false; +- } +- +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- /*! +- this method returns true if such an object is defined (name exists) +- */ +- bool IsDefined(const std::wstring & name) +- { +- // we should check whether the name (in wide characters) are correct +- // before calling AssignString() function +- if( !IsNameCorrect(name) ) +- return false; +- +- Misc::AssignString(str_tmp1, name); +- +- return IsDefined(str_tmp1); +- } +- +-#endif +- +- +- /*! +- this method adds one object (variable of function) into the table +- */ +- ErrorCode Add(const std::string & name, const std::string & value, int param = 0) +- { +- if( !IsNameCorrect(name) ) +- return err_incorrect_name; +- +- Iterator i = table.find(name); +- +- if( i != table.end() ) +- // we have this object in our table +- return err_object_exists; +- +- table.insert( std::make_pair(name, Item(value, param)) ); +- +- return err_ok; +- } +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- /*! +- this method adds one object (variable of function) into the table +- */ +- ErrorCode Add(const std::wstring & name, const std::wstring & value, int param = 0) +- { +- // we should check whether the name (in wide characters) are correct +- // before calling AssignString() function +- if( !IsNameCorrect(name) ) +- return err_incorrect_name; +- +- Misc::AssignString(str_tmp1, name); +- Misc::AssignString(str_tmp2, value); +- +- return Add(str_tmp1, str_tmp2, param); +- } +- +-#endif +- +- +- /*! +- this method returns 'true' if the table is empty +- */ +- bool Empty() const +- { +- return table.empty(); +- } +- +- +- /*! +- this method clears the table +- */ +- void Clear() +- { +- return table.clear(); +- } +- +- +- /*! +- this method returns 'const_iterator' on the first item on the table +- */ +- CIterator Begin() const +- { +- return table.begin(); +- } +- +- +- /*! +- this method returns 'const_iterator' pointing at the space after last item +- (returns table.end()) +- */ +- CIterator End() const +- { +- return table.end(); +- } +- +- +- /*! +- this method changes the value and the number of parameters for a specific object +- */ +- ErrorCode EditValue(const std::string & name, const std::string & value, int param = 0) +- { +- if( !IsNameCorrect(name) ) +- return err_incorrect_name; +- +- Iterator i = table.find(name); +- +- if( i == table.end() ) +- return err_unknown_object; +- +- i->second.value = value; +- i->second.param = param; +- +- return err_ok; +- } +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- +- /*! +- this method changes the value and the number of parameters for a specific object +- */ +- ErrorCode EditValue(const std::wstring & name, const std::wstring & value, int param = 0) +- { +- // we should check whether the name (in wide characters) are correct +- // before calling AssignString() function +- if( !IsNameCorrect(name) ) +- return err_incorrect_name; +- +- Misc::AssignString(str_tmp1, name); +- Misc::AssignString(str_tmp2, value); +- +- return EditValue(str_tmp1, str_tmp2, param); +- } +- +-#endif +- +- +- /*! +- this method changes the name of a specific object +- */ +- ErrorCode EditName(const std::string & old_name, const std::string & new_name) +- { +- if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) ) +- return err_incorrect_name; +- +- Iterator old_i = table.find(old_name); +- if( old_i == table.end() ) +- return err_unknown_object; +- +- if( old_name == new_name ) +- // the new name is the same as the old one +- // we treat it as a normal situation +- return err_ok; +- +- ErrorCode err = Add(new_name, old_i->second.value, old_i->second.param); +- +- if( err == err_ok ) +- { +- old_i = table.find(old_name); +- TTMATH_ASSERT( old_i != table.end() ) +- +- table.erase(old_i); +- } +- +- return err; +- } +- +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- +- /*! +- this method changes the name of a specific object +- */ +- ErrorCode EditName(const std::wstring & old_name, const std::wstring & new_name) +- { +- // we should check whether the name (in wide characters) are correct +- // before calling AssignString() function +- if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) ) +- return err_incorrect_name; +- +- Misc::AssignString(str_tmp1, old_name); +- Misc::AssignString(str_tmp2, new_name); +- +- return EditName(str_tmp1, str_tmp2); +- } +- +-#endif +- +- +- /*! +- this method deletes an object +- */ +- ErrorCode Delete(const std::string & name) +- { +- if( !IsNameCorrect(name) ) +- return err_incorrect_name; +- +- Iterator i = table.find(name); +- +- if( i == table.end() ) +- return err_unknown_object; +- +- table.erase( i ); +- +- return err_ok; +- } +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- +- /*! +- this method deletes an object +- */ +- ErrorCode Delete(const std::wstring & name) +- { +- // we should check whether the name (in wide characters) are correct +- // before calling AssignString() function +- if( !IsNameCorrect(name) ) +- return err_incorrect_name; +- +- Misc::AssignString(str_tmp1, name); +- +- return Delete(str_tmp1); +- } +- +-#endif +- +- +- /*! +- this method gets the value of a specific object +- */ +- ErrorCode GetValue(const std::string & name, std::string & value) const +- { +- if( !IsNameCorrect(name) ) +- return err_incorrect_name; +- +- CIterator i = table.find(name); +- +- if( i == table.end() ) +- { +- value.clear(); +- return err_unknown_object; +- } +- +- value = i->second.value; +- +- return err_ok; +- } +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- /*! +- this method gets the value of a specific object +- */ +- ErrorCode GetValue(const std::wstring & name, std::wstring & value) +- { +- // we should check whether the name (in wide characters) are correct +- // before calling AssignString() function +- if( !IsNameCorrect(name) ) +- return err_incorrect_name; +- +- Misc::AssignString(str_tmp1, name); +- ErrorCode err = GetValue(str_tmp1, str_tmp2); +- Misc::AssignString(value, str_tmp2); +- +- return err; +- } +- +-#endif +- +- +- /*! +- this method gets the value of a specific object +- (this version is used for not copying the whole string) +- */ +- ErrorCode GetValue(const std::string & name, const char ** value) const +- { +- if( !IsNameCorrect(name) ) +- return err_incorrect_name; +- +- CIterator i = table.find(name); +- +- if( i == table.end() ) +- { +- *value = 0; +- return err_unknown_object; +- } +- +- *value = i->second.value.c_str(); +- +- return err_ok; +- } +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- /*! +- this method gets the value of a specific object +- (this version is used for not copying the whole string) +- */ +- ErrorCode GetValue(const std::wstring & name, const char ** value) +- { +- // we should check whether the name (in wide characters) are correct +- // before calling AssignString() function +- if( !IsNameCorrect(name) ) +- return err_incorrect_name; +- +- Misc::AssignString(str_tmp1, name); +- +- return GetValue(str_tmp1, value); +- } +- +-#endif +- +- +- /*! +- this method gets the value and the number of parameters +- of a specific object +- */ +- ErrorCode GetValueAndParam(const std::string & name, std::string & value, int * param) const +- { +- if( !IsNameCorrect(name) ) +- return err_incorrect_name; +- +- CIterator i = table.find(name); +- +- if( i == table.end() ) +- { +- value.empty(); +- *param = 0; +- return err_unknown_object; +- } +- +- value = i->second.value; +- *param = i->second.param; +- +- return err_ok; +- } +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- /*! +- this method gets the value and the number of parameters +- of a specific object +- */ +- ErrorCode GetValueAndParam(const std::wstring & name, std::wstring & value, int * param) +- { +- // we should check whether the name (in wide characters) are correct +- // before calling AssignString() function +- if( !IsNameCorrect(name) ) +- return err_incorrect_name; +- +- Misc::AssignString(str_tmp1, name); +- ErrorCode err = GetValueAndParam(str_tmp1, str_tmp2, param); +- Misc::AssignString(value, str_tmp2); +- +- return err; +- } +- +-#endif +- +- +- /*! +- this method sets the value and the number of parameters +- of a specific object +- (this version is used for not copying the whole string) +- */ +- ErrorCode GetValueAndParam(const std::string & name, const char ** value, int * param) const +- { +- if( !IsNameCorrect(name) ) +- return err_incorrect_name; +- +- CIterator i = table.find(name); +- +- if( i == table.end() ) +- { +- *value = 0; +- *param = 0; +- return err_unknown_object; +- } +- +- *value = i->second.value.c_str(); +- *param = i->second.param; +- +- return err_ok; +- } +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- +- /*! +- this method sets the value and the number of parameters +- of a specific object +- (this version is used for not copying the whole string +- but in fact we make one copying during AssignString()) +- */ +- ErrorCode GetValueAndParam(const std::wstring & name, const char ** value, int * param) +- { +- // we should check whether the name (in wide characters) are correct +- // before calling AssignString() function +- if( !IsNameCorrect(name) ) +- return err_incorrect_name; +- +- Misc::AssignString(str_tmp1, name); +- +- return GetValueAndParam(str_tmp1, value, param); +- } +- +- +-#endif +- +- +- /*! +- this method returns a pointer into the table +- */ +- Table * GetTable() +- { +- return &table; +- } +- +- +-private: +- +- Table table; +- std::string str_tmp1, str_tmp2; +- +-}; // end of class Objects +- +- +- +- +- +- +- +-/*! +- objects of the class History are used to keep values in functions +- which take a lot of time during calculating, for instance in the +- function Factorial(x) +- +- it means that when we're calculating e.g. Factorial(1000) and the +- Factorial finds that we have calculated it before, the value (result) +- is taken from the history +-*/ +-template +-class History +-{ +- /*! +- one item in the History's object holds a key, a value for the key +- and a corresponding error code +- */ +- struct Item +- { +- ValueType key, value; +- ErrorCode err; +- }; +- +- +- /*! +- we use std::list for simply deleting the first item +- but because we're searching through the whole container +- (in the method Get) the container should not be too big +- (linear time of searching) +- */ +- typedef std::list buffer_type; +- buffer_type buffer; +- typename buffer_type::size_type buffer_max_size; +- +-public: +- +- /*! +- default constructor +- default max size of the History's container is 15 items +- */ +- History() +- { +- buffer_max_size = 15; +- } +- +- +- /*! +- a constructor which takes another value of the max size +- of the History's container +- */ +- History(typename buffer_type::size_type new_size) +- { +- buffer_max_size = new_size; +- } +- +- +- /*! +- this method adds one item into the History +- if the size of the container is greater than buffer_max_size +- the first item will be removed +- */ +- void Add(const ValueType & key, const ValueType & value, ErrorCode err) +- { +- Item item; +- item.key = key; +- item.value = value; +- item.err = err; +- +- buffer.insert( buffer.end(), item ); +- +- if( buffer.size() > buffer_max_size ) +- buffer.erase(buffer.begin()); +- } +- +- +- /*! +- this method checks whether we have an item which has the key equal 'key' +- +- if there's such item the method sets the 'value' and the 'err' +- and returns true otherwise it returns false and 'value' and 'err' +- remain unchanged +- */ +- bool Get(const ValueType & key, ValueType & value, ErrorCode & err) +- { +- typename buffer_type::iterator i = buffer.begin(); +- +- for( ; i != buffer.end() ; ++i ) +- { +- if( i->key == key ) +- { +- value = i->value; +- err = i->err; +- return true; +- } +- } +- +- return false; +- } +- +- +- /*! +- this methods deletes an item +- +- we assume that there is only one item with the 'key' +- (this methods removes the first one) +- */ +- bool Remove(const ValueType & key) +- { +- typename buffer_type::iterator i = buffer.begin(); +- +- for( ; i != buffer.end() ; ++i ) +- { +- if( i->key == key ) +- { +- buffer.erase(i); +- return true; +- } +- } +- +- return false; +- } +- +- +-}; // end of class History +- +- +- +-/*! +- this is an auxiliary class used when calculating Gamma() or Factorial() +- +- in multithreaded environment you can provide an object of this class to +- the Gamma() or Factorial() function, e.g; +- typedef Big<1, 3> MyBig; +- MyBig x = 123456; +- CGamma cgamma; +- std::cout << Gamma(x, cgamma); +- each thread should have its own CGamma<> object +- +- in a single-thread environment a CGamma<> object is a static variable +- in a second version of Gamma() and you don't have to explicitly use it, e.g. +- typedef Big<1, 3> MyBig; +- MyBig x = 123456; +- std::cout << Gamma(x); +-*/ +-template +-struct CGamma +-{ +- /*! +- this table holds factorials +- 1 +- 1 +- 2 +- 6 +- 24 +- 120 +- 720 +- ....... +- */ +- std::vector fact; +- +- +- /*! +- this table holds Bernoulli numbers +- 1 +- -0.5 +- 0.166666666666666666666666667 +- 0 +- -0.0333333333333333333333333333 +- 0 +- 0.0238095238095238095238095238 +- 0 +- -0.0333333333333333333333333333 +- 0 +- 0.075757575757575757575757576 +- ..... +- */ +- std::vector bern; +- +- +- /*! +- here we store some calculated values +- (this is for speeding up, if the next argument of Gamma() or Factorial() +- is in the 'history' then the result we are not calculating but simply +- return from the 'history' object) +- */ +- History history; +- +- +- /*! +- this method prepares some coefficients: factorials and Bernoulli numbers +- stored in 'fact' and 'bern' objects +- +- how many values should be depends on the size of the mantissa - if +- the mantissa is larger then we must calculate more values +- for a mantissa which consists of 256 bits (8 words on a 32bit platform) +- we have to calculate about 30 values (the size of fact and bern will be 30), +- and for a 2048 bits mantissa we have to calculate 306 coefficients +- +- you don't have to call this method, these coefficients will be automatically calculated +- when they are needed +- +- you must note that calculating these coefficients is a little time-consuming operation, +- (especially when the mantissa is large) and first call to Gamma() or Factorial() +- can take more time than next calls, and in the end this is the point when InitAll() +- comes in handy: you can call this method somewhere at the beginning of your program +- */ +- void InitAll(); +- // definition is in ttmath.h +-}; +- +- +- +- +-} // namespace +- +-#endif +diff --git a/extern/ttmath/ttmaththreads.h b/extern/ttmath/ttmaththreads.h +deleted file mode 100644 +index 586227f2fc..0000000000 +--- a/extern/ttmath/ttmaththreads.h ++++ /dev/null +@@ -1,250 +0,0 @@ +-/* +- * This file is a part of TTMath Bignum Library +- * and is distributed under the (new) BSD licence. +- * Author: Tomasz Sowa +- */ +- +-/* +- * Copyright (c) 2006-2009, Tomasz Sowa +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * +- * * Redistributions of source code must retain the above copyright notice, +- * this list of conditions and the following disclaimer. +- * +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * +- * * Neither the name Tomasz Sowa nor the names of contributors to this +- * project may be used to endorse or promote products derived +- * from this software without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +- * THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +- +- +-#ifndef headerfilettmaththreads +-#define headerfilettmaththreads +- +-#include "ttmathtypes.h" +- +-#ifdef TTMATH_WIN32_THREADS +-#include +-#include +-#endif +- +-#ifdef TTMATH_POSIX_THREADS +-#include +-#endif +- +- +- +-/*! +- \file ttmaththreads.h +- \brief Some objects used in multithreads environment +-*/ +- +- +-/* +- this is a simple skeleton of a program in multithreads environment: +- +- #define TTMATH_MULTITHREADS +- #include +- +- TTMATH_MULTITHREADS_HELPER +- +- int main() +- { +- [...] +- } +- +- make sure that macro TTMATH_MULTITHREADS is defined and (somewhere in *.cpp file) +- use TTMATH_MULTITHREADS_HELPER macro (outside of any classes/functions/namespaces scope) +-*/ +- +- +-namespace ttmath +-{ +- +- +-#ifdef TTMATH_WIN32_THREADS +- +- /* +- we use win32 threads +- */ +- +- +- /*! +- in multithreads environment you should use TTMATH_MULTITHREADS_HELPER macro +- somewhere in *.cpp file +- +- (at the moment in win32 this macro does nothing) +- */ +- #define TTMATH_MULTITHREADS_HELPER +- +- +- /*! +- objects of this class are used to synchronize +- */ +- class ThreadLock +- { +- HANDLE mutex_handle; +- +- +- void CreateName(char * buffer) const +- { +- #ifdef _MSC_VER +- #pragma warning (disable : 4996) +- // warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. +- #endif +- +- sprintf(buffer, "TTMATH_LOCK_%ul", (unsigned long)GetCurrentProcessId()); +- +- #ifdef _MSC_VER +- #pragma warning (default : 4996) +- #endif +- } +- +- +- public: +- +- bool Lock() +- { +- char buffer[50]; +- +- CreateName(buffer); +- mutex_handle = CreateMutexA(0, false, buffer); +- +- if( mutex_handle == 0 ) +- return false; +- +- WaitForSingleObject(mutex_handle, INFINITE); +- +- return true; +- } +- +- +- ThreadLock() +- { +- mutex_handle = 0; +- } +- +- +- ~ThreadLock() +- { +- if( mutex_handle != 0 ) +- { +- ReleaseMutex(mutex_handle); +- CloseHandle(mutex_handle); +- } +- } +- }; +- +-#endif // #ifdef TTMATH_WIN32_THREADS +- +- +- +- +- +-#ifdef TTMATH_POSIX_THREADS +- +- /* +- we use posix threads +- */ +- +- +- /*! +- in multithreads environment you should use TTMATH_MULTITHREADS_HELPER macro +- somewhere in *.cpp file +- (this macro defines a pthread_mutex_t object used by TTMath library) +- */ +- #define TTMATH_MULTITHREADS_HELPER \ +- namespace ttmath \ +- { \ +- pthread_mutex_t ttmath_mutex = PTHREAD_MUTEX_INITIALIZER; \ +- } +- +- +- /*! +- ttmath_mutex will be defined by TTMATH_MULTITHREADS_HELPER macro +- */ +- extern pthread_mutex_t ttmath_mutex; +- +- +- /*! +- objects of this class are used to synchronize +- */ +- class ThreadLock +- { +- public: +- +- bool Lock() +- { +- if( pthread_mutex_lock(&ttmath_mutex) != 0 ) +- return false; +- +- return true; +- } +- +- +- ~ThreadLock() +- { +- pthread_mutex_unlock(&ttmath_mutex); +- } +- }; +- +-#endif // #ifdef TTMATH_POSIX_THREADS +- +- +- +- +-#if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS) +- +- /*! +- we don't use win32 and pthreads +- */ +- +- /*! +- */ +- #define TTMATH_MULTITHREADS_HELPER +- +- +- /*! +- objects of this class are used to synchronize +- actually we don't synchronize, the method Lock() returns always 'false' +- */ +- class ThreadLock +- { +- public: +- +- bool Lock() +- { +- return false; +- } +- }; +- +- +-#endif // #if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS) +- +- +- +- +- +-} // namespace +- +-#endif +- +diff --git a/extern/ttmath/ttmathtypes.h b/extern/ttmath/ttmathtypes.h +deleted file mode 100644 +index 3d9ddbe7b0..0000000000 +--- a/extern/ttmath/ttmathtypes.h ++++ /dev/null +@@ -1,676 +0,0 @@ +-/* +- * This file is a part of TTMath Bignum Library +- * and is distributed under the (new) BSD licence. +- * Author: Tomasz Sowa +- */ +- +-/* +- * Copyright (c) 2006-2012, Tomasz Sowa +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * +- * * Redistributions of source code must retain the above copyright notice, +- * this list of conditions and the following disclaimer. +- * +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * +- * * Neither the name Tomasz Sowa nor the names of contributors to this +- * project may be used to endorse or promote products derived +- * from this software without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +- * THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +- +-#ifndef headerfilettmathtypes +-#define headerfilettmathtypes +- +-/*! +- \file ttmathtypes.h +- \brief constants used in the library +- +- As our library is written in header files (templates) we cannot use +- constants like 'const int' etc. because we should have some source files +- *.cpp to define this variables. Only what we can have are constants +- defined by #define preprocessor macros. +- +- All macros are preceded by TTMATH_ prefix +-*/ +- +- +-#include +-#include +-#include +- +-#ifndef _MSC_VER +-#include +-// for uint64_t and int64_t on a 32 bit platform +-#endif +- +- +- +-/*! +- the version of the library +- +- TTMATH_PRERELEASE_VER is either zero or one +- zero means that this is the release version of the library +- (one means something like beta) +-*/ +-#define TTMATH_MAJOR_VER 0 +-#define TTMATH_MINOR_VER 9 +-#define TTMATH_REVISION_VER 3 +- +-#define TTMATH_PRERELEASE_VER 0 +- +- +- +-/*! +- you can define a platform explicitly by defining either +- TTMATH_PLATFORM32 or TTMATH_PLATFORM64 macro +-*/ +-#if !defined TTMATH_PLATFORM32 && !defined TTMATH_PLATFORM64 +- +- #if !defined _M_X64 && !defined __x86_64__ +- +- /* +- other platforms than x86 and amd64 are not recognized at the moment +- so you should set TTMATH_PLATFORMxx manually +- */ +- +- // we're using a 32bit platform +- #define TTMATH_PLATFORM32 +- +- #else +- +- // we're using a 64bit platform +- #define TTMATH_PLATFORM64 +- +- #endif +- +-#endif +- +- +-/*! +- asm version of the library is available by default only for: +- x86 and amd64 platforms and for Microsoft Visual and GCC compilers +- +- but you can force using asm version (the same asm as for Microsoft Visual) +- by defining TTMATH_FORCEASM macro +- you have to be sure that your compiler accept such an asm format +-*/ +-#ifndef TTMATH_FORCEASM +- +- #if !defined __i386__ && !defined _X86_ && !defined _M_IX86 && !defined __x86_64__ && !defined _M_X64 +- /*! +- x86 architecture: +- __i386__ defined by GNU C +- _X86_ defined by MinGW32 +- _M_IX86 defined by Visual Studio, Intel C/C++, Digital Mars and Watcom C/C++ +- +- amd64 architecture: +- __x86_64__ defined by GNU C, CLANG (LLVM) and Sun Studio +- _M_X64 defined by Visual Studio +- +- asm version is available only for x86 or amd64 platforms +- */ +- #define TTMATH_NOASM +- #endif +- +- +- +- #if !defined _MSC_VER && !defined __GNUC__ +- /*! +- another compilers than MS VC or GCC or CLANG (LLVM) by default use no asm version +- (CLANG defines __GNUC__ too) +- */ +- #define TTMATH_NOASM +- #endif +- +-#endif +- +- +-namespace ttmath +-{ +- +- +-#ifdef TTMATH_PLATFORM32 +- +- /*! +- on 32bit platforms one word (uint, sint) will be equal 32bits +- */ +- typedef unsigned int uint; +- typedef signed int sint; +- +- /*! +- on 32 bit platform ulint and slint will be equal 64 bits +- */ +- #ifdef _MSC_VER +- // long long on MS Windows (Visual and GCC mingw compilers) have 64 bits +- // stdint.h is not available on Visual Studio prior to VS 2010 version +- typedef unsigned long long int ulint; +- typedef signed long long int slint; +- #else +- // we do not use 'long' here because there is a difference in unix and windows +- // environments: in unix 'long' has 64 bits but in windows it has only 32 bits +- typedef uint64_t ulint; +- typedef int64_t slint; +- #endif +- +- /*! +- how many bits there are in the uint type +- */ +- #define TTMATH_BITS_PER_UINT 32u +- +- /*! +- the mask for the highest bit in the unsigned 32bit word (2^31) +- */ +- #define TTMATH_UINT_HIGHEST_BIT 2147483648u +- +- /*! +- the max value of the unsigned 32bit word (2^32 - 1) +- (all bits equal one) +- */ +- #define TTMATH_UINT_MAX_VALUE 4294967295u +- +- /*! +- the number of words (32bit words on 32bit platform) +- which are kept in built-in variables for a Big<> type +- (these variables are defined in ttmathbig.h) +- */ +- #define TTMATH_BUILTIN_VARIABLES_SIZE 256u +- +- /*! +- this macro returns the number of machine words +- capable to hold min_bits bits +- e.g. TTMATH_BITS(128) returns 4 +- */ +- #define TTMATH_BITS(min_bits) ((min_bits-1)/32 + 1) +- +-#else +- +- /*! +- on 64bit platforms one word (uint, sint) will be equal 64bits +- */ +- #ifdef _MSC_VER +- /* in VC 'long' type has 32 bits, __int64 is VC extension */ +- typedef unsigned __int64 uint; +- typedef signed __int64 sint; +- #else +- typedef unsigned long uint; +- typedef signed long sint; +- #endif +- +- /*! +- on 64bit platforms we do not define ulint and slint +- */ +- +- /*! +- how many bits there are in the uint type +- */ +- #define TTMATH_BITS_PER_UINT 64ul +- +- /*! +- the mask for the highest bit in the unsigned 64bit word (2^63) +- */ +- #define TTMATH_UINT_HIGHEST_BIT 9223372036854775808ul +- +- /*! +- the max value of the unsigned 64bit word (2^64 - 1) +- (all bits equal one) +- */ +- #define TTMATH_UINT_MAX_VALUE 18446744073709551615ul +- +- /*! +- the number of words (64bit words on 64bit platforms) +- which are kept in built-in variables for a Big<> type +- (these variables are defined in ttmathbig.h) +- */ +- #define TTMATH_BUILTIN_VARIABLES_SIZE 128ul +- +- /*! +- this macro returns the number of machine words +- capable to hold min_bits bits +- e.g. TTMATH_BITS(128) returns 2 +- */ +- #define TTMATH_BITS(min_bits) ((min_bits-1)/64 + 1) +- +-#endif +-} +- +- +-#if defined(TTMATH_MULTITHREADS) && !defined(TTMATH_MULTITHREADS_NOSYNC) +- #if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS) +- +- #if defined(_WIN32) +- #define TTMATH_WIN32_THREADS +- #elif defined(unix) || defined(__unix__) || defined(__unix) +- #define TTMATH_POSIX_THREADS +- #endif +- +- #endif +-#endif +- +- +- +-/*! +- this variable defines how many iterations are performed +- during some kind of calculating when we're making any long formulas +- (for example Taylor series) +- +- it's used in ExpSurrounding0(...), LnSurrounding1(...), Sin0pi05(...), etc. +- +- note! there'll not be so many iterations, iterations are stopped when +- there is no sense to continue calculating (for example when the result +- still remains unchanged after adding next series and we know that the next +- series are smaller than previous ones) +-*/ +-#define TTMATH_ARITHMETIC_MAX_LOOP 10000 +- +- +- +-/*! +- this is a limit when calculating Karatsuba multiplication +- if the size of a vector is smaller than TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE +- the Karatsuba algorithm will use standard schoolbook multiplication +-*/ +-#ifdef TTMATH_DEBUG_LOG +- // if TTMATH_DEBUG_LOG is defined then we should use the same size regardless of the compiler +- #define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 3 +-#else +- #ifdef __GNUC__ +- #define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 3 +- #else +- #define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 5 +- #endif +-#endif +- +- +-/*! +- this is a special value used when calculating the Gamma(x) function +- if x is greater than this value then the Gamma(x) will be calculated using +- some kind of series +- +- don't use smaller values than about 100 +-*/ +-#define TTMATH_GAMMA_BOUNDARY 2000 +- +- +- +- +- +-namespace ttmath +-{ +- +- /*! +- lib type codes: +- asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits) +- asm_gcc_32 - with asm code designed for GCC (32 bits) +- asm_vc_64 - with asm for VC (64 bit) +- asm_gcc_64 - with asm for GCC (64 bit) +- no_asm_32 - pure C++ version (32 bit) - without any asm code +- no_asm_64 - pure C++ version (64 bit) - without any asm code +- */ +- enum LibTypeCode +- { +- asm_vc_32 = 0, +- asm_gcc_32, +- asm_vc_64, +- asm_gcc_64, +- no_asm_32, +- no_asm_64 +- }; +- +- +- /*! +- error codes +- */ +- enum ErrorCode +- { +- err_ok = 0, +- err_nothing_has_read, +- err_unknown_character, +- err_unexpected_final_bracket, +- err_stack_not_clear, +- err_unknown_variable, +- err_division_by_zero, +- err_interrupt, +- err_overflow, +- err_unknown_function, +- err_unknown_operator, +- err_unexpected_semicolon_operator, +- err_improper_amount_of_arguments, +- err_improper_argument, +- err_unexpected_end, +- err_internal_error, +- err_incorrect_name, +- err_incorrect_value, +- err_variable_exists, +- err_variable_loop, +- err_functions_loop, +- err_must_be_only_one_value, +- err_object_exists, +- err_unknown_object, +- err_still_calculating, +- err_in_short_form_used_function, +- err_percent_from +- }; +- +- +- /*! +- this struct is used when converting to/from a string +- /temporarily only in Big::ToString() and Big::FromString()/ +- */ +- struct Conv +- { +- /*! +- base (radix) on which the value will be shown (or read) +- default: 10 +- */ +- uint base; +- +- +- /*! +- used only in Big::ToString() +- if true the value will be always shown in the scientific mode, e.g: 123e+30 +- default: false +- */ +- bool scient; +- +- +- /*! +- used only in Big::ToString() +- if scient is false then the value will be printed in the scientific mode +- only if the exponent is greater than scien_from +- default: 15 +- */ +- sint scient_from; +- +- +- /*! +- if 'base_round' is true and 'base' is different from 2, 4, 8, or 16 +- and the result value is not an integer then we make an additional rounding +- (after converting the last digit from the result is skipped) +- default: true +- +- e.g. +- Conv c; +- c.base_round = false; +- Big<1, 1> a = "0.1"; // decimal input +- std::cout << a.ToString(c) << std::endl; // the result is: 0.099999999 +- */ +- bool base_round; +- +- +- /*! +- used only in Big::ToString() +- tells how many digits after comma are possible +- default: -1 which means all digits are printed +- +- set it to zero if you want integer value only +- +- for example when the value is: +- 12.345678 and 'round' is 4 +- then the result will be +- 12.3457 (the last digit was rounded) +- */ +- sint round; +- +- +- /*! +- if true that not mattered digits in the mantissa will be cut off +- (zero characters at the end -- after the comma operator) +- e.g. 1234,78000 will be: 1234,78 +- default: true +- */ +- bool trim_zeroes; +- +- +- /*! +- the main comma operator (used when reading and writing) +- default is a dot '.' +- */ +- uint comma; +- +- +- /*! +- additional comma operator (used only when reading) +- if you don't want it just set it to zero +- default is a comma ',' +- +- this allowes you to convert from a value: +- 123.45 as well as from 123,45 +- */ +- uint comma2; +- +- +- /*! +- it sets the character which is used for grouping +- if group=' ' then: 1234,56789 will be printed as: 1 234,567 89 +- +- if you don't want grouping just set it to zero (which is default) +- */ +- uint group; +- +- +- /*! +- how many digits should be grouped (it is used if 'group' is non zero) +- default: 3 +- */ +- uint group_digits; +- +- +- /*! +- */ +- uint group_exp; // not implemented yet +- +- +- +- +- Conv() +- { +- // default values +- base = 10; +- scient = false; +- scient_from = 15; +- base_round = true; +- round = -1; +- trim_zeroes = true; +- comma = '.'; +- comma2 = ','; +- group = 0; +- group_digits = 3; +- group_exp = 0; +- } +- }; +- +- +- +- /*! +- this simple class can be used in multithreading model +- (you can write your own class derived from this one) +- +- for example: in some functions like Factorial() +- /at the moment only Factorial/ you can give a pointer to +- the 'stop object', if the method WasStopSignal() of this +- object returns true that means we should break the calculating +- and return +- */ +- class StopCalculating +- { +- public: +- virtual bool WasStopSignal() const volatile { return false; } +- virtual ~StopCalculating(){} +- }; +- +- +- /*! +- a small class which is useful when compiling with gcc +- +- object of this type holds the name and the line of a file +- in which the macro TTMATH_ASSERT or TTMATH_REFERENCE_ASSERT was used +- */ +- class ExceptionInfo +- { +- const char * file; +- int line; +- +- public: +- ExceptionInfo() : file(0), line(0) {} +- ExceptionInfo(const char * f, int l) : file(f), line(l) {} +- +- std::string Where() const +- { +- if( !file ) +- return "unknown"; +- +- std::ostringstream result; +- result << file << ":" << line; +- +- return result.str(); +- } +- }; +- +- +- /*! +- A small class used for reporting 'reference' errors +- +- In the library is used macro TTMATH_REFERENCE_ASSERT which +- can throw an exception of this type +- +- ** from version 0.9.2 this macro is removed from all methods +- in public interface so you don't have to worry about it ** +- +- If you compile with gcc you can get a small benefit +- from using method Where() (it returns std::string) with +- the name and the line of a file where the macro TTMATH_REFERENCE_ASSERT +- was used) +- */ +- class ReferenceError : public std::logic_error, public ExceptionInfo +- { +- public: +- +- ReferenceError() : std::logic_error("reference error") +- { +- } +- +- ReferenceError(const char * f, int l) : +- std::logic_error("reference error"), ExceptionInfo(f,l) +- { +- } +- +- std::string Where() const +- { +- return ExceptionInfo::Where(); +- } +- }; +- +- +- /*! +- a small class used for reporting errors +- +- in the library is used macro TTMATH_ASSERT which +- (if the condition in it is false) throw an exception +- of this type +- +- if you compile with gcc you can get a small benefit +- from using method Where() (it returns std::string) with +- the name and the line of a file where the macro TTMATH_ASSERT +- was used) +- */ +- class RuntimeError : public std::runtime_error, public ExceptionInfo +- { +- public: +- +- RuntimeError() : std::runtime_error("internal error") +- { +- } +- +- RuntimeError(const char * f, int l) : +- std::runtime_error("internal error"), ExceptionInfo(f,l) +- { +- } +- +- std::string Where() const +- { +- return ExceptionInfo::Where(); +- } +- }; +- +- +- +- /*! +- TTMATH_DEBUG +- this macro enables further testing during writing your code +- you don't have to define it in a release mode +- +- if this macro is set then macros TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT +- are set as well and these macros can throw an exception if a condition in it +- is not fulfilled (look at the definition of TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT) +- +- TTMATH_DEBUG is set automatically if DEBUG or _DEBUG are defined +- */ +- #if defined DEBUG || defined _DEBUG +- #define TTMATH_DEBUG +- #endif +- +- +- #ifdef TTMATH_DEBUG +- +- #if defined(__FILE__) && defined(__LINE__) +- +- #define TTMATH_REFERENCE_ASSERT(expression) \ +- if( &(expression) == this ) throw ttmath::ReferenceError(__FILE__, __LINE__); +- +- #define TTMATH_ASSERT(expression) \ +- if( !(expression) ) throw ttmath::RuntimeError(__FILE__, __LINE__); +- +- #else +- +- #define TTMATH_REFERENCE_ASSERT(expression) \ +- if( &(expression) == this ) throw ReferenceError(); +- +- #define TTMATH_ASSERT(expression) \ +- if( !(expression) ) throw RuntimeError(); +- #endif +- +- #else +- #define TTMATH_REFERENCE_ASSERT(expression) +- #define TTMATH_ASSERT(expression) +- #endif +- +- +- +- #ifdef TTMATH_DEBUG_LOG +- #define TTMATH_LOG(msg) PrintLog(msg, std::cout); +- #define TTMATH_LOGC(msg, carry) PrintLog(msg, carry, std::cout); +- #define TTMATH_VECTOR_LOG(msg, vector, len) PrintVectorLog(msg, std::cout, vector, len); +- #define TTMATH_VECTOR_LOGC(msg, carry, vector, len) PrintVectorLog(msg, carry, std::cout, vector, len); +- #else +- #define TTMATH_LOG(msg) +- #define TTMATH_LOGC(msg, carry) +- #define TTMATH_VECTOR_LOG(msg, vector, len) +- #define TTMATH_VECTOR_LOGC(msg, carry, vector, len) +- #endif +- +- +- +- +-} // namespace +- +- +-#endif +- +diff --git a/extern/ttmath/ttmathuint.h b/extern/ttmath/ttmathuint.h +deleted file mode 100644 +index b9cf67cd11..0000000000 +--- a/extern/ttmath/ttmathuint.h ++++ /dev/null +@@ -1,4126 +0,0 @@ +-/* +- * This file is a part of TTMath Bignum Library +- * and is distributed under the (new) BSD licence. +- * Author: Tomasz Sowa +- */ +- +-/* +- * Copyright (c) 2006-2011, Tomasz Sowa +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * +- * * Redistributions of source code must retain the above copyright notice, +- * this list of conditions and the following disclaimer. +- * +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * +- * * Neither the name Tomasz Sowa nor the names of contributors to this +- * project may be used to endorse or promote products derived +- * from this software without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +- * THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +- +- +-#ifndef headerfilettmathuint +-#define headerfilettmathuint +- +- +-/*! +- \file ttmathuint.h +- \brief template class UInt +-*/ +- +-#include +-#include +- +- +-#include "ttmathtypes.h" +-#include "ttmathmisc.h" +- +- +- +-/*! +- \brief a namespace for the TTMath library +-*/ +-namespace ttmath +-{ +- +-/*! +- \brief UInt implements a big integer value without a sign +- +- value_size - how many bytes specify our value +- on 32bit platforms: value_size=1 -> 4 bytes -> 32 bits +- on 64bit platforms: value_size=1 -> 8 bytes -> 64 bits +- value_size = 1,2,3,4,5,6.... +-*/ +-template +-class UInt +-{ +-public: +- +- /*! +- buffer for the integer value +- table[0] - the lowest word of the value +- */ +- uint table[value_size]; +- +- +- +- /*! +- some methods used for debugging purposes +- */ +- +- +- /*! +- this method is used when macro TTMATH_DEBUG_LOG is defined +- */ +- template +- static void PrintVectorLog(const char_type * msg, ostream_type & output, const uint * vector, uint vector_len) +- { +- output << msg << std::endl; +- +- for(uint i=0 ; i +- static void PrintVectorLog(const char_type * msg, uint carry, ostream_type & output, const uint * vector, uint vector_len) +- { +- PrintVectorLog(msg, output, vector, vector_len); +- output << " carry: " << carry << std::endl; +- } +- +- +- /*! +- this method is used when macro TTMATH_DEBUG_LOG is defined +- */ +- template +- void PrintLog(const char_type * msg, ostream_type & output) const +- { +- PrintVectorLog(msg, output, table, value_size); +- } +- +- +- /*! +- this method is used when macro TTMATH_DEBUG_LOG is defined +- */ +- template +- void PrintLog(const char_type * msg, uint carry, ostream_type & output) const +- { +- PrintVectorLog(msg, output, table, value_size); +- output << " carry: " << carry << std::endl; +- } +- +- +- /*! +- this method returns the size of the table +- */ +- uint Size() const +- { +- return value_size; +- } +- +- +- /*! +- this method sets zero +- */ +- void SetZero() +- { +- // in the future here can be 'memset' +- +- for(uint i=0 ; i & ss2) +- { +- for(uint i=0 ; i=0 && temp_table_index=0 ; --i) +- table[i] = 0; +- +- +- TTMATH_LOG("UInt::SetFromTable") +- } +- +-#endif +- +- +-#ifdef TTMATH_PLATFORM64 +- /*! +- this method copies the value stored in an another table +- (warning: first values in temp_table are the highest words -- it's different +- from our table) +- +- ***this method is created only on a 64bit platform*** +- +- we copy as many words as it is possible +- +- if temp_table_len is bigger than value_size we'll try to round +- the lowest word from table depending on the last not used bit in temp_table +- (this rounding isn't a perfect rounding -- look at the description below) +- +- and if temp_table_len is smaller than value_size we'll clear the rest words +- in the table +- +- warning: we're using 'temp_table' as a pointer at 32bit words +- */ +- void SetFromTable(const unsigned int * temp_table, uint temp_table_len) +- { +- uint temp_table_index = 0; +- sint i; // 'i' with a sign +- +- for(i=value_size-1 ; i>=0 && temp_table_index= 0 ; --i) +- table[i] = 0; +- +- TTMATH_LOG("UInt::SetFromTable") +- } +- +-#endif +- +- +- +- +- +- /*! +- * +- * basic mathematic functions +- * +- */ +- +- +- +- +- /*! +- this method adds one to the existing value +- */ +- uint AddOne() +- { +- return AddInt(1); +- } +- +- +- /*! +- this method subtracts one from the existing value +- */ +- uint SubOne() +- { +- return SubInt(1); +- } +- +- +-private: +- +- +- /*! +- an auxiliary method for moving bits into the left hand side +- +- this method moves only words +- */ +- void RclMoveAllWords(uint & rest_bits, uint & last_c, uint bits, uint c) +- { +- rest_bits = bits % TTMATH_BITS_PER_UINT; +- uint all_words = bits / TTMATH_BITS_PER_UINT; +- uint mask = ( c ) ? TTMATH_UINT_MAX_VALUE : 0; +- +- +- if( all_words >= value_size ) +- { +- if( all_words == value_size && rest_bits == 0 ) +- last_c = table[0] & 1; +- // else: last_c is default set to 0 +- +- // clearing +- for(uint i = 0 ; i 0 ) +- { +- // 0 < all_words < value_size +- +- sint first, second; +- last_c = table[value_size - all_words] & 1; // all_words is greater than 0 +- +- // copying the first part of the value +- for(first = value_size-1, second=first-all_words ; second>=0 ; --first, --second) +- table[first] = table[second]; +- +- // setting the rest to 'c' +- for( ; first>=0 ; --first ) +- table[first] = mask; +- } +- +- TTMATH_LOG("UInt::RclMoveAllWords") +- } +- +-public: +- +- /*! +- moving all bits into the left side 'bits' times +- return value <- this <- C +- +- bits is from a range of <0, man * TTMATH_BITS_PER_UINT> +- or it can be even bigger then all bits will be set to 'c' +- +- the value c will be set into the lowest bits +- and the method returns state of the last moved bit +- */ +- uint Rcl(uint bits, uint c=0) +- { +- uint last_c = 0; +- uint rest_bits = bits; +- +- if( bits == 0 ) +- return 0; +- +- if( bits >= TTMATH_BITS_PER_UINT ) +- RclMoveAllWords(rest_bits, last_c, bits, c); +- +- if( rest_bits == 0 ) +- { +- TTMATH_LOG("UInt::Rcl") +- return last_c; +- } +- +- // rest_bits is from 1 to TTMATH_BITS_PER_UINT-1 now +- if( rest_bits == 1 ) +- { +- last_c = Rcl2_one(c); +- } +- else if( rest_bits == 2 ) +- { +- // performance tests showed that for rest_bits==2 it's better to use Rcl2_one twice instead of Rcl2(2,c) +- Rcl2_one(c); +- last_c = Rcl2_one(c); +- } +- else +- { +- last_c = Rcl2(rest_bits, c); +- } +- +- TTMATH_LOGC("UInt::Rcl", last_c) +- +- return last_c; +- } +- +-private: +- +- /*! +- an auxiliary method for moving bits into the right hand side +- +- this method moves only words +- */ +- void RcrMoveAllWords(uint & rest_bits, uint & last_c, uint bits, uint c) +- { +- rest_bits = bits % TTMATH_BITS_PER_UINT; +- uint all_words = bits / TTMATH_BITS_PER_UINT; +- uint mask = ( c ) ? TTMATH_UINT_MAX_VALUE : 0; +- +- +- if( all_words >= value_size ) +- { +- if( all_words == value_size && rest_bits == 0 ) +- last_c = (table[value_size-1] & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0; +- // else: last_c is default set to 0 +- +- // clearing +- for(uint i = 0 ; i 0 ) +- { +- // 0 < all_words < value_size +- +- uint first, second; +- last_c = (table[all_words - 1] & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0; // all_words is > 0 +- +- // copying the first part of the value +- for(first=0, second=all_words ; second this -> return value +- +- bits is from a range of <0, man * TTMATH_BITS_PER_UINT> +- or it can be even bigger then all bits will be set to 'c' +- +- the value c will be set into the highest bits +- and the method returns state of the last moved bit +- */ +- uint Rcr(uint bits, uint c=0) +- { +- uint last_c = 0; +- uint rest_bits = bits; +- +- if( bits == 0 ) +- return 0; +- +- if( bits >= TTMATH_BITS_PER_UINT ) +- RcrMoveAllWords(rest_bits, last_c, bits, c); +- +- if( rest_bits == 0 ) +- { +- TTMATH_LOG("UInt::Rcr") +- return last_c; +- } +- +- // rest_bits is from 1 to TTMATH_BITS_PER_UINT-1 now +- if( rest_bits == 1 ) +- { +- last_c = Rcr2_one(c); +- } +- else if( rest_bits == 2 ) +- { +- // performance tests showed that for rest_bits==2 it's better to use Rcr2_one twice instead of Rcr2(2,c) +- Rcr2_one(c); +- last_c = Rcr2_one(c); +- } +- else +- { +- last_c = Rcr2(rest_bits, c); +- } +- +- TTMATH_LOGC("UInt::Rcr", last_c) +- +- return last_c; +- } +- +- +- /*! +- this method moves all bits into the left side +- (it returns value how many bits have been moved) +- */ +- uint CompensationToLeft() +- { +- uint moving = 0; +- +- // a - index a last word which is different from zero +- sint a; +- for(a=value_size-1 ; a>=0 && table[a]==0 ; --a); +- +- if( a < 0 ) +- return moving; // all words in table have zero +- +- if( a != value_size-1 ) +- { +- moving += ( value_size-1 - a ) * TTMATH_BITS_PER_UINT; +- +- // moving all words +- sint i; +- for(i=value_size-1 ; a>=0 ; --i, --a) +- table[i] = table[a]; +- +- // setting the rest word to zero +- for(; i>=0 ; --i) +- table[i] = 0; +- } +- +- uint moving2 = FindLeadingBitInWord( table[value_size-1] ); +- // moving2 is different from -1 because the value table[value_size-1] +- // is not zero +- +- moving2 = TTMATH_BITS_PER_UINT - moving2 - 1; +- Rcl(moving2); +- +- TTMATH_LOG("UInt::CompensationToLeft") +- +- return moving + moving2; +- } +- +- +- /*! +- this method looks for the highest set bit +- +- result: +- if 'this' is not zero: +- return value - true +- 'table_id' - the index of a word <0..value_size-1> +- 'index' - the index of this set bit in the word <0..TTMATH_BITS_PER_UINT) +- +- if 'this' is zero: +- return value - false +- both 'table_id' and 'index' are zero +- */ +- bool FindLeadingBit(uint & table_id, uint & index) const +- { +- for(table_id=value_size-1 ; table_id!=0 && table[table_id]==0 ; --table_id); +- +- if( table_id==0 && table[table_id]==0 ) +- { +- // is zero +- index = 0; +- +- return false; +- } +- +- // table[table_id] is different from 0 +- index = FindLeadingBitInWord( table[table_id] ); +- +- return true; +- } +- +- +- /*! +- this method looks for the smallest set bit +- +- result: +- if 'this' is not zero: +- return value - true +- 'table_id' - the index of a word <0..value_size-1> +- 'index' - the index of this set bit in the word <0..TTMATH_BITS_PER_UINT) +- +- if 'this' is zero: +- return value - false +- both 'table_id' and 'index' are zero +- */ +- bool FindLowestBit(uint & table_id, uint & index) const +- { +- for(table_id=0 ; table_id= value_size ) +- { +- // is zero +- index = 0; +- table_id = 0; +- +- return false; +- } +- +- // table[table_id] is different from 0 +- index = FindLowestBitInWord( table[table_id] ); +- +- return true; +- } +- +- +- /*! +- getting the 'bit_index' bit +- +- bit_index bigger or equal zero +- */ +- uint GetBit(uint bit_index) const +- { +- TTMATH_ASSERT( bit_index < value_size * TTMATH_BITS_PER_UINT ) +- +- uint index = bit_index / TTMATH_BITS_PER_UINT; +- uint bit = bit_index % TTMATH_BITS_PER_UINT; +- +- uint temp = table[index]; +- uint res = SetBitInWord(temp, bit); +- +- return res; +- } +- +- +- /*! +- setting the 'bit_index' bit +- and returning the last state of the bit +- +- bit_index bigger or equal zero +- */ +- uint SetBit(uint bit_index) +- { +- TTMATH_ASSERT( bit_index < value_size * TTMATH_BITS_PER_UINT ) +- +- uint index = bit_index / TTMATH_BITS_PER_UINT; +- uint bit = bit_index % TTMATH_BITS_PER_UINT; +- uint res = SetBitInWord(table[index], bit); +- +- TTMATH_LOG("UInt::SetBit") +- +- return res; +- } +- +- +- /*! +- this method performs a bitwise operation AND +- */ +- void BitAnd(const UInt & ss2) +- { +- for(uint x=0 ; x & ss2) +- { +- for(uint x=0 ; x & ss2) +- { +- for(uint x=0 ; x +- +- for example: +- BitNot2(8) = BitNot2( 1000(bin) ) = 111(bin) = 7 +- */ +- void BitNot2() +- { +- uint table_id, index; +- +- if( FindLeadingBit(table_id, index) ) +- { +- for(uint x=0 ; x>= shift; +- +- table[table_id] ^= mask; +- } +- else +- table[0] = 1; +- +- +- TTMATH_LOG("UInt::BitNot2") +- } +- +- +- +- /*! +- * +- * Multiplication +- * +- * +- */ +- +-public: +- +- /*! +- multiplication: this = this * ss2 +- +- it can return a carry +- */ +- uint MulInt(uint ss2) +- { +- uint r1, r2, x1; +- uint c = 0; +- +- UInt u(*this); +- SetZero(); +- +- if( ss2 == 0 ) +- { +- TTMATH_LOGC("UInt::MulInt(uint)", 0) +- return 0; +- } +- +- for(x1=0 ; x1 +- void MulInt(uint ss2, UInt & result) const +- { +- TTMATH_ASSERT( result_size > value_size ) +- +- uint r2,r1; +- uint x1size=value_size; +- uint x1start=0; +- +- result.SetZero(); +- +- if( ss2 == 0 ) +- { +- TTMATH_VECTOR_LOG("UInt::MulInt(uint, UInt<>)", result.table, result_size) +- return; +- } +- +- if( value_size > 2 ) +- { +- // if the value_size is smaller than or equal to 2 +- // there is no sense to set x1size and x1start to another values +- +- for(x1size=value_size ; x1size>0 && table[x1size-1]==0 ; --x1size); +- +- if( x1size == 0 ) +- { +- TTMATH_VECTOR_LOG("UInt::MulInt(uint, UInt<>)", result.table, result_size) +- return; +- } +- +- for(x1start=0 ; x1start)", result.table, result_size) +- +- return; +- } +- +- +- +- /*! +- the multiplication 'this' = 'this' * ss2 +- +- algorithm: 100 - means automatically choose the fastest algorithm +- */ +- uint Mul(const UInt & ss2, uint algorithm = 100) +- { +- switch( algorithm ) +- { +- case 1: +- return Mul1(ss2); +- +- case 2: +- return Mul2(ss2); +- +- case 3: +- return Mul3(ss2); +- +- case 100: +- default: +- return MulFastest(ss2); +- } +- } +- +- +- /*! +- the multiplication 'result' = 'this' * ss2 +- +- since the 'result' is twice bigger than 'this' and 'ss2' +- this method never returns a carry +- +- algorithm: 100 - means automatically choose the fastest algorithm +- */ +- void MulBig(const UInt & ss2, +- UInt & result, +- uint algorithm = 100) +- { +- switch( algorithm ) +- { +- case 1: +- return Mul1Big(ss2, result); +- +- case 2: +- return Mul2Big(ss2, result); +- +- case 3: +- return Mul3Big(ss2, result); +- +- case 100: +- default: +- return MulFastestBig(ss2, result); +- } +- } +- +- +- +- /*! +- the first version of the multiplication algorithm +- */ +- +-private: +- +- /*! +- multiplication: this = this * ss2 +- +- it returns carry if it has been +- */ +- uint Mul1Ref(const UInt & ss2) +- { +- TTMATH_REFERENCE_ASSERT( ss2 ) +- +- UInt ss1( *this ); +- SetZero(); +- +- for(uint i=0; i < value_size*TTMATH_BITS_PER_UINT ; ++i) +- { +- if( Add(*this) ) +- { +- TTMATH_LOGC("UInt::Mul1", 1) +- return 1; +- } +- +- if( ss1.Rcl(1) ) +- if( Add(ss2) ) +- { +- TTMATH_LOGC("UInt::Mul1", 1) +- return 1; +- } +- } +- +- TTMATH_LOGC("UInt::Mul1", 0) +- +- return 0; +- } +- +- +-public: +- +- /*! +- multiplication: this = this * ss2 +- can return carry +- */ +- uint Mul1(const UInt & ss2) +- { +- if( this == &ss2 ) +- { +- UInt copy_ss2(ss2); +- return Mul1Ref(copy_ss2); +- } +- else +- { +- return Mul1Ref(ss2); +- } +- } +- +- +- /*! +- multiplication: result = this * ss2 +- +- result is twice bigger than 'this' and 'ss2' +- this method never returns carry +- */ +- void Mul1Big(const UInt & ss2_, UInt & result) +- { +- UInt ss2; +- uint i; +- +- // copying *this into result and ss2_ into ss2 +- for(i=0 ; i & ss2) +- { +- UInt result; +- uint i, c = 0; +- +- Mul2Big(ss2, result); +- +- // copying result +- for(i=0 ; i & ss2, UInt & result) +- { +- Mul2Big2(table, ss2.table, result); +- +- TTMATH_LOG("UInt::Mul2Big") +- } +- +- +-private: +- +- /*! +- an auxiliary method for calculating the multiplication +- +- arguments we're taking as pointers (this is to improve the Mul3Big2()- avoiding +- unnecessary copying objects), the result should be taken as a pointer too, +- but at the moment there is no method AddTwoInts() which can operate on pointers +- */ +- template +- void Mul2Big2(const uint * ss1, const uint * ss2, UInt & result) +- { +- uint x1size = ss_size, x2size = ss_size; +- uint x1start = 0, x2start = 0; +- +- if( ss_size > 2 ) +- { +- // if the ss_size is smaller than or equal to 2 +- // there is no sense to set x1size (and others) to another values +- +- for(x1size=ss_size ; x1size>0 && ss1[x1size-1]==0 ; --x1size); +- for(x2size=ss_size ; x2size>0 && ss2[x2size-1]==0 ; --x2size); +- +- for(x1start=0 ; x1start(ss1, ss2, result, x1start, x1size, x2start, x2size); +- } +- +- +- +- /*! +- an auxiliary method for calculating the multiplication +- */ +- template +- void Mul2Big3(const uint * ss1, const uint * ss2, UInt & result, uint x1start, uint x1size, uint x2start, uint x2size) +- { +- uint r2, r1; +- +- result.SetZero(); +- +- if( x1size==0 || x2size==0 ) +- return; +- +- for(uint x1=x1start ; x1 & ss2) +- { +- UInt result; +- uint i, c = 0; +- +- Mul3Big(ss2, result); +- +- // copying result +- for(i=0 ; i & ss2, UInt & result) +- { +- Mul3Big2(table, ss2.table, result.table); +- +- TTMATH_LOG("UInt::Mul3Big") +- } +- +- +- +-private: +- +- /*! +- an auxiliary method for calculating the Karatsuba multiplication +- +- result_size is equal ss_size*2 +- */ +- template +- void Mul3Big2(const uint * ss1, const uint * ss2, uint * result) +- { +- const uint * x1, * x0, * y1, * y0; +- +- +- if( ss_size>1 && ss_size res; +- Mul2Big2(ss1, ss2, res); +- +-#ifdef __clang__ +-#pragma clang diagnostic push +-#pragma clang diagnostic ignored "-Wtautological-compare" +-#endif +- +- for(uint i=0 ; i(x1, x0, y1, y0, result); +- } +- else +- { +- // ss_size is even +- x0 = ss1; +- y0 = ss2; +- x1 = ss1 + ss_size / 2; +- y1 = ss2 + ss_size / 2; +- +- // all four vectors (x0 x1 y0 y1) are equal in size +- Mul3Big3(x1, x0, y1, y0, result); +- } +- } +- +- +- +-#ifdef _MSC_VER +-#pragma warning (disable : 4717) +-//warning C4717: recursive on all control paths, function will cause runtime stack overflow +-//we have the stop point in Mul3Big2() method +-#endif +- +- +- /*! +- an auxiliary method for calculating the Karatsuba multiplication +- +- x = x1*B^m + x0 +- y = y1*B^m + y0 +- +- first_size - is the size of vectors: x0 and y0 +- second_size - is the size of vectors: x1 and y1 (can be either equal first_size or smaller about one from first_size) +- +- x*y = (x1*B^m + x0)(y1*B^m + y0) = z2*B^(2m) + z1*B^m + z0 +- where +- z0 = x0*y0 +- z2 = x1*y1 +- z1 = (x1 + x0)*(y1 + y0) - z2 - z0 +- */ +- template +- uint Mul3Big3(const uint * x1, const uint * x0, const uint * y1, const uint * y0, uint * result) +- { +- uint i, c, xc, yc; +- +- UInt temp, temp2; +- UInt z1; +- +- // z0 and z2 we store directly in the result (we don't use any temporary variables) +- Mul3Big2(x0, y0, result); // z0 +- Mul3Big2(x1, y1, result+first_size*2); // z2 +- +- // now we calculate z1 +- // temp = (x0 + x1) +- // temp2 = (y0 + y1) +- // we're using temp and temp2 with UInt, although there can be a carry but +- // we simple remember it in xc and yc (xc and yc can be either 0 or 1), +- // and (x0 + x1)*(y0 + y1) we calculate in this way (schoolbook algorithm): +- // +- // xc | temp +- // yc | temp2 +- // -------------------- +- // (temp * temp2) +- // xc*temp2 | +- // yc*temp | +- // xc*yc | +- // ---------- z1 -------- +- // +- // and the result is never larger in size than 3*first_size +- +- xc = AddVector(x0, x1, first_size, second_size, temp.table); +- yc = AddVector(y0, y1, first_size, second_size, temp2.table); +- +- Mul3Big2(temp.table, temp2.table, z1.table); +- +-#ifdef __clang__ +-#pragma clang diagnostic push +-#pragma clang diagnostic ignored "-Wtautological-compare" +-#endif +- +- // clearing the rest of z1 +- for(i=first_size*2 ; i second_size ) +- { +- uint z1_size = result_size - first_size; +- TTMATH_ASSERT( z1_size <= first_size*3 ) +- +-#ifdef __clang__ +-#pragma clang diagnostic push +-#pragma clang diagnostic ignored "-Wtautological-compare" +-#endif +- +- for(i=z1_size ; i & ss2) +- { +- UInt result; +- uint i, c = 0; +- +- MulFastestBig(ss2, result); +- +- // copying result +- for(i=0 ; i & ss2, UInt & result) +- { +- if( value_size < TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE ) +- return Mul2Big(ss2, result); +- +- uint x1size = value_size, x2size = value_size; +- uint x1start = 0, x2start = 0; +- +- for(x1size=value_size ; x1size>0 && table[x1size-1]==0 ; --x1size); +- for(x2size=value_size ; x2size>0 && ss2.table[x2size-1]==0 ; --x2size); +- +- if( x1size==0 || x2size==0 ) +- { +- // either 'this' or 'ss2' is equal zero - the result is zero too +- result.SetZero(); +- return; +- } +- +- for(x1start=0 ; x1start(table, ss2.table, result, x1start, x1size, x2start, x2size); +- +- +- // Karatsuba multiplication +- Mul3Big(ss2, result); +- +- TTMATH_LOG("UInt::MulFastestBig") +- } +- +- +- /*! +- * +- * Division +- * +- * +- */ +- +-public: +- +- +- /*! +- division by one unsigned word +- +- returns 1 when divisor is zero +- */ +- uint DivInt(uint divisor, uint * remainder = 0) +- { +- if( divisor == 0 ) +- { +- if( remainder ) +- *remainder = 0; // this is for convenience, without it the compiler can report that 'remainder' is uninitialized +- +- TTMATH_LOG("UInt::DivInt") +- +- return 1; +- } +- +- if( divisor == 1 ) +- { +- if( remainder ) +- *remainder = 0; +- +- TTMATH_LOG("UInt::DivInt") +- +- return 0; +- } +- +- UInt dividend(*this); +- SetZero(); +- +- sint i; // i must be with a sign +- uint r = 0; +- +- // we're looking for the last word in ss1 +- for(i=value_size-1 ; i>0 && dividend.table[i]==0 ; --i); +- +- for( ; i>=0 ; --i) +- DivTwoWords(r, dividend.table[i], divisor, &table[i], &r); +- +- if( remainder ) +- *remainder = r; +- +- TTMATH_LOG("UInt::DivInt") +- +- return 0; +- } +- +- uint DivInt(uint divisor, uint & remainder) +- { +- return DivInt(divisor, &remainder); +- } +- +- +- +- /*! +- division this = this / ss2 +- +- return values: +- 0 - ok +- 1 - division by zero +- 'this' will be the quotient +- 'remainder' - remainder +- */ +- uint Div( const UInt & divisor, +- UInt * remainder = 0, +- uint algorithm = 3) +- { +- switch( algorithm ) +- { +- case 1: +- return Div1(divisor, remainder); +- +- case 2: +- return Div2(divisor, remainder); +- +- case 3: +- default: +- return Div3(divisor, remainder); +- } +- } +- +- uint Div(const UInt & divisor, UInt & remainder, uint algorithm = 3) +- { +- return Div(divisor, &remainder, algorithm); +- } +- +- +- +-private: +- +- /*! +- return values: +- 0 - none has to be done +- 1 - division by zero +- 2 - division should be made +- */ +- uint Div_StandardTest( const UInt & v, +- uint & m, uint & n, +- UInt * remainder = 0) +- { +- switch( Div_CalculatingSize(v, m, n) ) +- { +- case 4: // 'this' is equal v +- if( remainder ) +- remainder->SetZero(); +- +- SetOne(); +- TTMATH_LOG("UInt::Div_StandardTest") +- return 0; +- +- case 3: // 'this' is smaller than v +- if( remainder ) +- *remainder = *this; +- +- SetZero(); +- TTMATH_LOG("UInt::Div_StandardTest") +- return 0; +- +- case 2: // 'this' is zero +- if( remainder ) +- remainder->SetZero(); +- +- SetZero(); +- TTMATH_LOG("UInt::Div_StandardTest") +- return 0; +- +- case 1: // v is zero +- TTMATH_LOG("UInt::Div_StandardTest") +- return 1; +- } +- +- TTMATH_LOG("UInt::Div_StandardTest") +- +- return 2; +- } +- +- +- +- /*! +- return values: +- 0 - ok +- 'm' - is the index (from 0) of last non-zero word in table ('this') +- 'n' - is the index (from 0) of last non-zero word in v.table +- 1 - v is zero +- 2 - 'this' is zero +- 3 - 'this' is smaller than v +- 4 - 'this' is equal v +- +- if the return value is different than zero the 'm' and 'n' are undefined +- */ +- uint Div_CalculatingSize(const UInt & v, uint & m, uint & n) +- { +- m = n = value_size-1; +- +- for( ; n!=0 && v.table[n]==0 ; --n); +- +- if( n==0 && v.table[n]==0 ) +- return 1; +- +- for( ; m!=0 && table[m]==0 ; --m); +- +- if( m==0 && table[m]==0 ) +- return 2; +- +- if( m < n ) +- return 3; +- else +- if( m == n ) +- { +- uint i; +- for(i = n ; i!=0 && table[i]==v.table[i] ; --i); +- +- if( table[i] < v.table[i] ) +- return 3; +- else +- if (table[i] == v.table[i] ) +- return 4; +- } +- +- return 0; +- } +- +- +-public: +- +- /*! +- the first division algorithm +- radix 2 +- */ +- uint Div1(const UInt & divisor, UInt * remainder = 0) +- { +- uint m,n, test; +- +- test = Div_StandardTest(divisor, m, n, remainder); +- if( test < 2 ) +- return test; +- +- if( !remainder ) +- { +- UInt rem; +- +- return Div1_Calculate(divisor, rem); +- } +- +- return Div1_Calculate(divisor, *remainder); +- } +- +- +- /*! +- the first division algorithm +- radix 2 +- */ +- uint Div1(const UInt & divisor, UInt & remainder) +- { +- return Div1(divisor, &remainder); +- } +- +- +-private: +- +- uint Div1_Calculate(const UInt & divisor, UInt & rest) +- { +- if( this == &divisor ) +- { +- UInt divisor_copy(divisor); +- return Div1_CalculateRef(divisor_copy, rest); +- } +- else +- { +- return Div1_CalculateRef(divisor, rest); +- } +- } +- +- +- uint Div1_CalculateRef(const UInt & divisor, UInt & rest) +- { +- TTMATH_REFERENCE_ASSERT( divisor ) +- +- sint loop; +- sint c; +- +- rest.SetZero(); +- loop = value_size * TTMATH_BITS_PER_UINT; +- c = 0; +- +- +- div_a: +- c = Rcl(1, c); +- c = rest.Add(rest,c); +- c = rest.Sub(divisor,c); +- +- c = !c; +- +- if(!c) +- goto div_d; +- +- +- div_b: +- --loop; +- if(loop) +- goto div_a; +- +- c = Rcl(1, c); +- TTMATH_LOG("UInt::Div1_Calculate") +- return 0; +- +- +- div_c: +- c = Rcl(1, c); +- c = rest.Add(rest,c); +- c = rest.Add(divisor); +- +- if(c) +- goto div_b; +- +- +- div_d: +- --loop; +- if(loop) +- goto div_c; +- +- c = Rcl(1, c); +- c = rest.Add(divisor); +- +- TTMATH_LOG("UInt::Div1_Calculate") +- +- return 0; +- } +- +- +-public: +- +- /*! +- the second division algorithm +- +- return values: +- 0 - ok +- 1 - division by zero +- */ +- uint Div2(const UInt & divisor, UInt * remainder = 0) +- { +- if( this == &divisor ) +- { +- UInt divisor_copy(divisor); +- return Div2Ref(divisor_copy, remainder); +- } +- else +- { +- return Div2Ref(divisor, remainder); +- } +- } +- +- +- /*! +- the second division algorithm +- +- return values: +- 0 - ok +- 1 - division by zero +- */ +- uint Div2(const UInt & divisor, UInt & remainder) +- { +- return Div2(divisor, &remainder); +- } +- +- +-private: +- +- /*! +- the second division algorithm +- +- return values: +- 0 - ok +- 1 - division by zero +- */ +- uint Div2Ref(const UInt & divisor, UInt * remainder = 0) +- { +- uint bits_diff; +- uint status = Div2_Calculate(divisor, remainder, bits_diff); +- if( status < 2 ) +- return status; +- +- if( CmpBiggerEqual(divisor) ) +- { +- Div2(divisor, remainder); +- SetBit(bits_diff); +- } +- else +- { +- if( remainder ) +- *remainder = *this; +- +- SetZero(); +- SetBit(bits_diff); +- } +- +- TTMATH_LOG("UInt::Div2") +- +- return 0; +- } +- +- +- /*! +- return values: +- 0 - we've calculated the division +- 1 - division by zero +- 2 - we have to still calculate +- +- */ +- uint Div2_Calculate(const UInt & divisor, UInt * remainder, +- uint & bits_diff) +- { +- uint table_id, index; +- uint divisor_table_id, divisor_index; +- +- uint status = Div2_FindLeadingBitsAndCheck( divisor, remainder, +- table_id, index, +- divisor_table_id, divisor_index); +- +- if( status < 2 ) +- { +- TTMATH_LOG("UInt::Div2_Calculate") +- return status; +- } +- +- // here we know that 'this' is greater than divisor +- // then 'index' is greater or equal 'divisor_index' +- bits_diff = index - divisor_index; +- +- UInt divisor_copy(divisor); +- divisor_copy.Rcl(bits_diff, 0); +- +- if( CmpSmaller(divisor_copy, table_id) ) +- { +- divisor_copy.Rcr(1); +- --bits_diff; +- } +- +- Sub(divisor_copy, 0); +- +- TTMATH_LOG("UInt::Div2_Calculate") +- +- return 2; +- } +- +- +- /*! +- return values: +- 0 - we've calculated the division +- 1 - division by zero +- 2 - we have to still calculate +- */ +- uint Div2_FindLeadingBitsAndCheck( const UInt & divisor, +- UInt * remainder, +- uint & table_id, uint & index, +- uint & divisor_table_id, uint & divisor_index) +- { +- if( !divisor.FindLeadingBit(divisor_table_id, divisor_index) ) +- { +- // division by zero +- TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck") +- return 1; +- } +- +- if( !FindLeadingBit(table_id, index) ) +- { +- // zero is divided by something +- +- SetZero(); +- +- if( remainder ) +- remainder->SetZero(); +- +- TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck") +- +- return 0; +- } +- +- divisor_index += divisor_table_id * TTMATH_BITS_PER_UINT; +- index += table_id * TTMATH_BITS_PER_UINT; +- +- if( divisor_table_id == 0 ) +- { +- // dividor has only one 32-bit word +- +- uint r; +- DivInt(divisor.table[0], &r); +- +- if( remainder ) +- { +- remainder->SetZero(); +- remainder->table[0] = r; +- } +- +- TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck") +- +- return 0; +- } +- +- +- if( Div2_DivisorGreaterOrEqual( divisor, remainder, +- table_id, index, +- divisor_index) ) +- { +- TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck") +- return 0; +- } +- +- +- TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck") +- +- return 2; +- } +- +- +- /*! +- return values: +- true if divisor is equal or greater than 'this' +- */ +- bool Div2_DivisorGreaterOrEqual( const UInt & divisor, +- UInt * remainder, +- uint table_id, uint index, +- uint divisor_index ) +- { +- if( divisor_index > index ) +- { +- // divisor is greater than this +- +- if( remainder ) +- *remainder = *this; +- +- SetZero(); +- +- TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual") +- +- return true; +- } +- +- if( divisor_index == index ) +- { +- // table_id == divisor_table_id as well +- +- uint i; +- for(i = table_id ; i!=0 && table[i]==divisor.table[i] ; --i); +- +- if( table[i] < divisor.table[i] ) +- { +- // divisor is greater than 'this' +- +- if( remainder ) +- *remainder = *this; +- +- SetZero(); +- +- TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual") +- +- return true; +- } +- else +- if( table[i] == divisor.table[i] ) +- { +- // divisor is equal 'this' +- +- if( remainder ) +- remainder->SetZero(); +- +- SetOne(); +- +- TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual") +- +- return true; +- } +- } +- +- TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual") +- +- return false; +- } +- +- +-public: +- +- /*! +- the third division algorithm +- */ +- uint Div3(const UInt & ss2, UInt * remainder = 0) +- { +- if( this == &ss2 ) +- { +- UInt copy_ss2(ss2); +- return Div3Ref(copy_ss2, remainder); +- } +- else +- { +- return Div3Ref(ss2, remainder); +- } +- } +- +- +- /*! +- the third division algorithm +- */ +- uint Div3(const UInt & ss2, UInt & remainder) +- { +- return Div3(ss2, &remainder); +- } +- +- +-private: +- +- /*! +- the third division algorithm +- +- this algorithm is described in the following book: +- "The art of computer programming 2" (4.3.1 page 272) +- Donald E. Knuth +- !! give the description here (from the book) +- */ +- uint Div3Ref(const UInt & v, UInt * remainder = 0) +- { +- uint m,n, test; +- +- test = Div_StandardTest(v, m, n, remainder); +- if( test < 2 ) +- return test; +- +- if( n == 0 ) +- { +- uint r; +- DivInt( v.table[0], &r ); +- +- if( remainder ) +- { +- remainder->SetZero(); +- remainder->table[0] = r; +- } +- +- TTMATH_LOG("UInt::Div3") +- +- return 0; +- } +- +- +- // we can only use the third division algorithm when +- // the divisor is greater or equal 2^32 (has more than one 32-bit word) +- ++m; +- ++n; +- m = m - n; +- Div3_Division(v, remainder, m, n); +- +- TTMATH_LOG("UInt::Div3") +- +- return 0; +- } +- +- +- +-private: +- +- +- void Div3_Division(UInt v, UInt * remainder, uint m, uint n) +- { +- TTMATH_ASSERT( n>=2 ) +- +- UInt uu, vv; +- UInt q; +- uint d, u_value_size, u0, u1, u2, v1, v0, j=m; +- +- u_value_size = Div3_Normalize(v, n, d); +- +- if( j+n == value_size ) +- u2 = u_value_size; +- else +- u2 = table[j+n]; +- +- Div3_MakeBiggerV(v, vv); +- +- for(uint i = j+1 ; i & uu, uint j, uint n, uint u_max) +- { +- uint i; +- +- for(i=0 ; i so and 'i' is from <0..value_size> +- // then table[i] is always correct (look at the declaration of 'uu') +- uu.table[i] = u_max; +- +- for( ++i ; i & uu, uint j, uint n) +- { +- uint i; +- +- for(i=0 ; i & v, UInt & vv) +- { +- for(uint i=0 ; i & v, uint n, uint & d) +- { +- // v.table[n-1] is != 0 +- +- uint bit = (uint)FindLeadingBitInWord(v.table[n-1]); +- uint move = (TTMATH_BITS_PER_UINT - bit - 1); +- uint res = table[value_size-1]; +- d = move; +- +- if( move > 0 ) +- { +- v.Rcl(move, 0); +- Rcl(move, 0); +- res = res >> (bit + 1); +- } +- else +- { +- res = 0; +- } +- +- TTMATH_LOG("UInt::Div3_Normalize") +- +- return res; +- } +- +- +- void Div3_Unnormalize(UInt * remainder, uint n, uint d) +- { +- for(uint i=n ; i u_temp; +- uint rp; +- bool next_test; +- +- TTMATH_ASSERT( v1 != 0 ) +- +- u_temp.table[1] = u2; +- u_temp.table[0] = u1; +- u_temp.DivInt(v1, &rp); +- +- TTMATH_ASSERT( u_temp.table[1]==0 || u_temp.table[1]==1 ) +- +- do +- { +- bool decrease = false; +- +- if( u_temp.table[1] == 1 ) +- decrease = true; +- else +- { +- UInt<2> temp1, temp2; +- +- UInt<2>::MulTwoWords(u_temp.table[0], v0, temp1.table+1, temp1.table); +- temp2.table[1] = rp; +- temp2.table[0] = u0; +- +- if( temp1 > temp2 ) +- decrease = true; +- } +- +- next_test = false; +- +- if( decrease ) +- { +- u_temp.SubOne(); +- +- rp += v1; +- +- if( rp >= v1 ) // it means that there wasn't a carry (r & uu, +- const UInt & vv, uint & qp) +- { +- // D4 (in the book) +- +- UInt vv_temp(vv); +- vv_temp.MulInt(qp); +- +- if( uu.Sub(vv_temp) ) +- { +- // there was a carry +- +- // +- // !!! this part of code was not tested +- // +- +- --qp; +- uu.Add(vv); +- +- // can be a carry from this additions but it should be ignored +- // because it cancels with the borrow from uu.Sub(vv_temp) +- } +- +- TTMATH_LOG("UInt::Div3_MultiplySubtract") +- } +- +- +- +- +- +- +-public: +- +- +- /*! +- power this = this ^ pow +- binary algorithm (r-to-l) +- +- return values: +- 0 - ok +- 1 - carry +- 2 - incorrect argument (0^0) +- */ +- uint Pow(UInt pow) +- { +- if(pow.IsZero() && IsZero()) +- // we don't define zero^zero +- return 2; +- +- UInt start(*this); +- UInt result; +- result.SetOne(); +- uint c = 0; +- +- while( !c ) +- { +- if( pow.table[0] & 1 ) +- c += result.Mul(start); +- +- pow.Rcr2_one(0); +- if( pow.IsZero() ) +- break; +- +- c += start.Mul(start); +- } +- +- *this = result; +- +- TTMATH_LOGC("UInt::Pow(UInt<>)", c) +- +- return (c==0)? 0 : 1; +- } +- +- +- /*! +- square root +- e.g. Sqrt(9) = 3 +- ('digit-by-digit' algorithm) +- */ +- void Sqrt() +- { +- UInt bit, temp; +- +- if( IsZero() ) +- return; +- +- UInt value(*this); +- +- SetZero(); +- bit.SetZero(); +- bit.table[value_size-1] = (TTMATH_UINT_HIGHEST_BIT >> 1); +- +- while( bit > value ) +- bit.Rcr(2); +- +- while( !bit.IsZero() ) +- { +- temp = *this; +- temp.Add(bit); +- +- if( value >= temp ) +- { +- value.Sub(temp); +- Rcr(1); +- Add(bit); +- } +- else +- { +- Rcr(1); +- } +- +- bit.Rcr(2); +- } +- +- TTMATH_LOG("UInt::Sqrt") +- } +- +- +- +- /*! +- this method sets n first bits to value zero +- +- For example: +- let n=2 then if there's a value 111 (bin) there'll be '100' (bin) +- */ +- void ClearFirstBits(uint n) +- { +- if( n >= value_size*TTMATH_BITS_PER_UINT ) +- { +- SetZero(); +- TTMATH_LOG("UInt::ClearFirstBits") +- return; +- } +- +- uint * p = table; +- +- // first we're clearing the whole words +- while( n >= TTMATH_BITS_PER_UINT ) +- { +- *p++ = 0; +- n -= TTMATH_BITS_PER_UINT; +- } +- +- if( n == 0 ) +- { +- TTMATH_LOG("UInt::ClearFirstBits") +- return; +- } +- +- // and then we're clearing one word which has left +- // mask -- all bits are set to one +- uint mask = TTMATH_UINT_MAX_VALUE; +- +- mask = mask << n; +- +- (*p) &= mask; +- +- TTMATH_LOG("UInt::ClearFirstBits") +- } +- +- +- /*! +- this method returns true if the highest bit of the value is set +- */ +- bool IsTheHighestBitSet() const +- { +- return (table[value_size-1] & TTMATH_UINT_HIGHEST_BIT) != 0; +- } +- +- +- /*! +- this method returns true if the lowest bit of the value is set +- */ +- bool IsTheLowestBitSet() const +- { +- return (*table & 1) != 0; +- } +- +- +- /*! +- returning true if only the highest bit is set +- */ +- bool IsOnlyTheHighestBitSet() const +- { +-#ifdef __clang__ +-#pragma clang diagnostic push +-#pragma clang diagnostic ignored "-Wtautological-compare" +-#endif +- +- for(uint i=0 ; i> (TTMATH_BITS_PER_UINT - rest); +- +- return (table[i] & mask) == 0; +- } +- +- +- +- /*! +- * +- * conversion methods +- * +- */ +- +- +- +- /*! +- this method converts an UInt type to this class +- +- this operation has mainly sense if the value from p is +- equal or smaller than that one which is returned from UInt::SetMax() +- +- it returns a carry if the value 'p' is too big +- */ +- template +- uint FromUInt(const UInt & p) +- { +- uint min_size = (value_size < argument_size)? value_size : argument_size; +- uint i; +- +- for(i=0 ; i argument_size ) +- { +- // 'this' is longer than 'p' +- +- for( ; i)", 1) +- return 1; +- } +- } +- +- TTMATH_LOGC("UInt::FromUInt(UInt<>)", 0) +- +- return 0; +- } +- +- +- /*! +- this method converts an UInt type to this class +- +- this operation has mainly sense if the value from p is +- equal or smaller than that one which is returned from UInt::SetMax() +- +- it returns a carry if the value 'p' is too big +- */ +- template +- uint FromInt(const UInt & p) +- { +- return FromUInt(p); +- } +- +- +- /*! +- this method converts the uint type to this class +- */ +- uint FromUInt(uint value) +- { +- for(uint i=1 ; i type to this class +- +- it doesn't return a carry +- */ +-/* template +- UInt & operator=(const UInt & p) +- { +- FromUInt(p); +- +- return *this; +- } +-*/ +- +- /*! +- the assignment operator +- */ +-/* UInt & operator=(const UInt & p) +- { +- for(uint i=0 ; i)") +- +- return *this; +- } +-*/ +- +- /*! +- this method converts the uint type to this class +- */ +- UInt & operator=(uint i) +- { +- FromUInt(i); +- +- return *this; +- } +- +- +- /*! +- a constructor for converting the uint to this class +- */ +-/* UInt(uint i) +- { +- FromUInt(i); +- } +-*/ +- +- /*! +- this method converts the sint type to this class +- */ +- UInt & operator=(sint i) +- { +- FromInt(i); +- +- return *this; +- } +- +- +- /*! +- a constructor for converting the sint to this class +- +- look at the description of UInt::operator=(sint) +- */ +-/* UInt(sint i) +- { +- FromInt(i); +- } +-*/ +- +-#ifdef TTMATH_PLATFORM32 +- +- +- /*! +- this method converts unsigned 64 bit int type to this class +- ***this method is created only on a 32bit platform*** +- */ +- uint FromUInt(ulint n) +- { +- table[0] = (uint)n; +- +- if( value_size == 1 ) +- { +- uint c = ((n >> TTMATH_BITS_PER_UINT) == 0) ? 0 : 1; +- +- TTMATH_LOGC("UInt::FromUInt(ulint)", c) +- return c; +- } +- +- table[1] = (uint)(n >> TTMATH_BITS_PER_UINT); +- +- for(uint i=2 ; i & operator=(ulint n) +- { +- FromUInt(n); +- +- return *this; +- } +- +- +- /*! +- a constructor for converting unsigned 64 bit int to this class +- ***this constructor is created only on a 32bit platform*** +- */ +-/* UInt(ulint n) +- { +- FromUInt(n); +- } +-*/ +- +- /*! +- this operator converts signed 64 bit int type to this class +- ***this operator is created only on a 32bit platform*** +- */ +- UInt & operator=(slint n) +- { +- FromInt(n); +- +- return *this; +- } +- +- +- /*! +- a constructor for converting signed 64 bit int to this class +- ***this constructor is created only on a 32bit platform*** +- */ +-/* UInt(slint n) +- { +- FromInt(n); +- } +-*/ +-#endif +- +- +- +-#ifdef TTMATH_PLATFORM64 +- +- +- /*! +- this method converts 32 bit unsigned int type to this class +- ***this operator is created only on a 64bit platform*** +- */ +- uint FromUInt(unsigned int i) +- { +- return FromUInt(uint(i)); +- } +- +- /*! +- this method converts 32 bit unsigned int type to this class +- ***this operator is created only on a 64bit platform*** +- */ +- uint FromInt(unsigned int i) +- { +- return FromUInt(uint(i)); +- } +- +- +- /*! +- this method converts 32 bit signed int type to this class +- ***this operator is created only on a 64bit platform*** +- */ +- uint FromInt(signed int i) +- { +- return FromInt(sint(i)); +- } +- +- +- /*! +- this operator converts 32 bit unsigned int type to this class +- ***this operator is created only on a 64bit platform*** +- */ +- UInt & operator=(unsigned int i) +- { +- FromUInt(i); +- +- return *this; +- } +- +- +- /*! +- a constructor for converting 32 bit unsigned int to this class +- ***this constructor is created only on a 64bit platform*** +- */ +-/* UInt(unsigned int i) +- { +- FromUInt(i); +- } +-*/ +- +- /*! +- an operator for converting 32 bit signed int to this class +- ***this constructor is created only on a 64bit platform*** +- */ +- UInt & operator=(signed int i) +- { +- FromInt(i); +- +- return *this; +- } +- +- +- /*! +- a constructor for converting 32 bit signed int to this class +- ***this constructor is created only on a 64bit platform*** +- */ +-/* UInt(signed int i) +- { +- FromInt(i); +- } +-*/ +- +-#endif +- +- +- +- +- +- /*! +- a constructor for converting a string to this class (with the base=10) +- */ +-/* UInt(const char * s) +- { +- FromString(s); +- } +-*/ +- +- /*! +- a constructor for converting a string to this class (with the base=10) +- */ +-/* UInt(const std::string & s) +- { +- FromString( s.c_str() ); +- } +-*/ +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- /*! +- a constructor for converting a string to this class (with the base=10) +- */ +- UInt(const wchar_t * s) +- { +- FromString(s); +- } +- +- +- /*! +- a constructor for converting a string to this class (with the base=10) +- */ +- UInt(const std::wstring & s) +- { +- FromString( s.c_str() ); +- } +- +-#endif +- +- +- +- +- /*! +- a default constructor +- +- we don't clear the table +- */ +-/* UInt() +- { +- // when macro TTMATH_DEBUG_LOG is defined +- // we set special values to the table +- // in order to be everywhere the same value of the UInt object +- // without this it would be difficult to analyse the log file +- #ifdef TTMATH_DEBUG_LOG +- #ifdef TTMATH_PLATFORM32 +- for(uint i=0 ; i & u) +- { +- for(uint i=0 ; i)") +- } +-*/ +- +- +- /*! +- a template for producting constructors for copying from another types +- */ +-/* template +- UInt(const UInt & u) +- { +- // look that 'size' we still set as 'value_size' and not as u.value_size +- FromUInt(u); +- } +-*/ +- +- +- +- /*! +- a destructor +- */ +-/* ~UInt() +- { +- } +-*/ +- +- /*! +- this method returns the lowest value from table +- +- we must be sure when we using this method whether the value +- will hold in an uint type or not (the rest value from the table must be zero) +- */ +- uint ToUInt() const +- { +- return table[0]; +- } +- +- +- /*! +- this method converts the value to uint type +- can return a carry if the value is too long to store it in uint type +- */ +- uint ToUInt(uint & result) const +- { +- result = table[0]; +- +- for(uint i=1 ; i> 32) != 0 ) +- return 1; +- +- for(uint i=1 ; i +- */ +- double ToStringLog2(uint x) const +- { +- static double log_tab[] = { +- 1.000000000000000000, +- 0.630929753571457437, +- 0.500000000000000000, +- 0.430676558073393050, +- 0.386852807234541586, +- 0.356207187108022176, +- 0.333333333333333333, +- 0.315464876785728718, +- 0.301029995663981195, +- 0.289064826317887859, +- 0.278942945651129843, +- 0.270238154427319741, +- 0.262649535037193547, +- 0.255958024809815489, +- 0.250000000000000000 +- }; +- +- if( x<2 || x>16 ) +- return 0; +- +- return log_tab[x-2]; +- } +- +- +-public: +- +- +- /*! +- an auxiliary method for converting to a string +- it's used from Int::ToString() too (negative is set true then) +- */ +- template +- void ToStringBase(string_type & result, uint b = 10, bool negative = false) const +- { +- UInt temp(*this); +- uint rest, table_id, index, digits; +- double digits_d; +- char character; +- +- result.clear(); +- +- if( b<2 || b>16 ) +- return; +- +- if( !FindLeadingBit(table_id, index) ) +- { +- result = '0'; +- return; +- } +- +- if( negative ) +- result = '-'; +- +- digits_d = table_id; // for not making an overflow in uint type +- digits_d *= TTMATH_BITS_PER_UINT; +- digits_d += index + 1; +- digits_d *= ToStringLog2(b); +- digits = static_cast(digits_d) + 3; // plus some epsilon +- +- if( result.capacity() < digits ) +- result.reserve(digits); +- +- do +- { +- temp.DivInt(b, &rest); +- character = static_cast(Misc::DigitToChar(rest)); +- result.insert(result.end(), character); +- } +- while( !temp.IsZero() ); +- +- size_t i1 = negative ? 1 : 0; // the first is a hyphen (when negative is true) +- size_t i2 = result.size() - 1; +- +- for( ; i1 < i2 ; ++i1, --i2 ) +- { +- char tempc = static_cast(result[i1]); +- result[i1] = result[i2]; +- result[i2] = tempc; +- } +- } +- +- +- +- /*! +- this method converts the value to a string with a base equal 'b' +- */ +- void ToString(std::string & result, uint b = 10) const +- { +- return ToStringBase(result, b); +- } +- +- +- std::string ToString(uint b = 10) const +- { +- std::string result; +- ToStringBase(result, b); +- +- return result; +- } +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- void ToString(std::wstring & result, uint b = 10) const +- { +- return ToStringBase(result, b); +- } +- +- std::wstring ToWString(uint b = 10) const +- { +- std::wstring result; +- ToStringBase(result, b); +- +- return result; +- } +- +-#endif +- +- +- +-private: +- +- /*! +- an auxiliary method for converting from a string +- */ +- template +- uint FromStringBase(const char_type * s, uint b = 10, const char_type ** after_source = 0, bool * value_read = 0) +- { +- UInt base; +- base.FromUInt( b ); +- UInt temp; +- sint z; +- uint c = 0; +- +- SetZero(); +- temp.SetZero(); +- Misc::SkipWhiteCharacters(s); +- +- if( after_source ) +- *after_source = s; +- +- if( value_read ) +- *value_read = false; +- +- if( b<2 || b>16 ) +- return 1; +- +- +- for( ; (z=Misc::CharToDigit(*s, b)) != -1 ; ++s) +- { +- if( value_read ) +- *value_read = true; +- +- if( c == 0 ) +- { +- temp.table[0] = z; +- +- c += Mul(base); // !! IMPROVE ME: there can be used MulInt here +- c += Add(temp); +- } +- } +- +- if( after_source ) +- *after_source = s; +- +- TTMATH_LOGC("UInt::FromString", c) +- +- return (c==0)? 0 : 1; +- } +- +- +-public: +- +- +- /*! +- this method converts a string into its value +- it returns carry=1 if the value will be too big or an incorrect base 'b' is given +- +- string is ended with a non-digit value, for example: +- "12" will be translated to 12 +- as well as: +- "12foo" will be translated to 12 too +- +- existing first white characters will be ommited +- +- if the value from s is too large the rest digits will be skipped +- +- after_source (if exists) is pointing at the end of the parsed string +- +- value_read (if exists) tells whether something has actually been read (at least one digit) +- */ +- uint FromString(const char * s, uint b = 10, const char ** after_source = 0, bool * value_read = 0) +- { +- return FromStringBase(s, b, after_source, value_read); +- } +- +- +- /*! +- this method converts a string into its value +- +- (it returns carry=1 if the value will be too big or an incorrect base 'b' is given) +- */ +- uint FromString(const std::string & s, uint b = 10) +- { +- return FromString( s.c_str(), b ); +- } +- +- +- /*! +- this operator converts a string into its value (with base = 10) +- */ +- UInt & operator=(const char * s) +- { +- FromString(s); +- +- return *this; +- } +- +- +- /*! +- this operator converts a string into its value (with base = 10) +- */ +- UInt & operator=(const std::string & s) +- { +- FromString( s.c_str() ); +- +- return *this; +- } +- +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- /*! +- this method converts a string into its value +- */ +- uint FromString(const wchar_t * s, uint b = 10, const wchar_t ** after_source = 0, bool * value_read = 0) +- { +- return FromStringBase(s, b, after_source, value_read); +- } +- +- +- /*! +- this method converts a string into its value +- +- (it returns carry=1 if the value will be too big or an incorrect base 'b' is given) +- */ +- uint FromString(const std::wstring & s, uint b = 10) +- { +- return FromString( s.c_str(), b ); +- } +- +- +- /*! +- this operator converts a string into its value (with base = 10) +- */ +- UInt & operator=(const wchar_t * s) +- { +- FromString(s); +- +- return *this; +- } +- +- +- /*! +- this operator converts a string into its value (with base = 10) +- */ +- UInt & operator=(const std::wstring & s) +- { +- FromString( s.c_str() ); +- +- return *this; +- } +- +-#endif +- +- +- /*! +- * +- * methods for comparing +- * +- */ +- +- +- /*! +- this method returns true if 'this' is smaller than 'l' +- +- 'index' is an index of the first word from will be the comparison performed +- (note: we start the comparison from back - from the last word, when index is -1 /default/ +- it is automatically set into the last word) +- I introduced it for some kind of optimization made in the second division algorithm (Div2) +- */ +- bool CmpSmaller(const UInt & l, sint index = -1) const +- { +- sint i; +- +- if( index==-1 || index>=sint(value_size) ) +- i = value_size - 1; +- else +- i = index; +- +- +- for( ; i>=0 ; --i) +- { +- if( table[i] != l.table[i] ) +- return table[i] < l.table[i]; +- } +- +- // they're equal +- return false; +- } +- +- +- +- /*! +- this method returns true if 'this' is bigger than 'l' +- +- 'index' is an index of the first word from will be the comparison performed +- (note: we start the comparison from back - from the last word, when index is -1 /default/ +- it is automatically set into the last word) +- +- I introduced it for some kind of optimization made in the second division algorithm (Div2) +- */ +- bool CmpBigger(const UInt & l, sint index = -1) const +- { +- sint i; +- +- if( index==-1 || index>=sint(value_size) ) +- i = value_size - 1; +- else +- i = index; +- +- +- for( ; i>=0 ; --i) +- { +- if( table[i] != l.table[i] ) +- return table[i] > l.table[i]; +- } +- +- // they're equal +- return false; +- } +- +- +- /*! +- this method returns true if 'this' is equal 'l' +- +- 'index' is an index of the first word from will be the comparison performed +- (note: we start the comparison from back - from the last word, when index is -1 /default/ +- it is automatically set into the last word) +- */ +- bool CmpEqual(const UInt & l, sint index = -1) const +- { +- sint i; +- +- if( index==-1 || index>=sint(value_size) ) +- i = value_size - 1; +- else +- i = index; +- +- +- for( ; i>=0 ; --i) +- if( table[i] != l.table[i] ) +- return false; +- +- return true; +- } +- +- +- +- /*! +- this method returns true if 'this' is smaller than or equal 'l' +- +- 'index' is an index of the first word from will be the comparison performed +- (note: we start the comparison from back - from the last word, when index is -1 /default/ +- it is automatically set into the last word) +- */ +- bool CmpSmallerEqual(const UInt & l, sint index=-1) const +- { +- sint i; +- +- if( index==-1 || index>=sint(value_size) ) +- i = value_size - 1; +- else +- i = index; +- +- +- for( ; i>=0 ; --i) +- { +- if( table[i] != l.table[i] ) +- return table[i] < l.table[i]; +- } +- +- // they're equal +- return true; +- } +- +- +- +- /*! +- this method returns true if 'this' is bigger than or equal 'l' +- +- 'index' is an index of the first word from will be the comparison performed +- (note: we start the comparison from back - from the last word, when index is -1 /default/ +- it is automatically set into the last word) +- */ +- bool CmpBiggerEqual(const UInt & l, sint index=-1) const +- { +- sint i; +- +- if( index==-1 || index>=sint(value_size) ) +- i = value_size - 1; +- else +- i = index; +- +- +- for( ; i>=0 ; --i) +- { +- if( table[i] != l.table[i] ) +- return table[i] > l.table[i]; +- } +- +- // they're equal +- return true; +- } +- +- +- /* +- operators for comparising +- */ +- +- bool operator<(const UInt & l) const +- { +- return CmpSmaller(l); +- } +- +- +- bool operator>(const UInt & l) const +- { +- return CmpBigger(l); +- } +- +- +- bool operator==(const UInt & l) const +- { +- return CmpEqual(l); +- } +- +- +- bool operator!=(const UInt & l) const +- { +- return !operator==(l); +- } +- +- +- bool operator<=(const UInt & l) const +- { +- return CmpSmallerEqual(l); +- } +- +- bool operator>=(const UInt & l) const +- { +- return CmpBiggerEqual(l); +- } +- +- +- /*! +- * +- * standard mathematical operators +- * +- */ +- +- UInt operator-(const UInt & p2) const +- { +- UInt temp(*this); +- +- temp.Sub(p2); +- +- return temp; +- } +- +- UInt & operator-=(const UInt & p2) +- { +- Sub(p2); +- +- return *this; +- } +- +- UInt operator+(const UInt & p2) const +- { +- UInt temp(*this); +- +- temp.Add(p2); +- +- return temp; +- } +- +- UInt & operator+=(const UInt & p2) +- { +- Add(p2); +- +- return *this; +- } +- +- +- UInt operator*(const UInt & p2) const +- { +- UInt temp(*this); +- +- temp.Mul(p2); +- +- return temp; +- } +- +- +- UInt & operator*=(const UInt & p2) +- { +- Mul(p2); +- +- return *this; +- } +- +- +- UInt operator/(const UInt & p2) const +- { +- UInt temp(*this); +- +- temp.Div(p2); +- +- return temp; +- } +- +- +- UInt & operator/=(const UInt & p2) +- { +- Div(p2); +- +- return *this; +- } +- +- +- UInt operator%(const UInt & p2) const +- { +- UInt temp(*this); +- UInt remainder; +- +- temp.Div( p2, remainder ); +- +- return remainder; +- } +- +- +- UInt & operator%=(const UInt & p2) +- { +- UInt remainder; +- +- Div( p2, remainder ); +- operator=(remainder); +- +- return *this; +- } +- +- +- /*! +- Prefix operator e.g ++variable +- */ +- UInt & operator++() +- { +- AddOne(); +- +- return *this; +- } +- +- +- /*! +- Postfix operator e.g variable++ +- */ +- UInt operator++(int) +- { +- UInt temp( *this ); +- +- AddOne(); +- +- return temp; +- } +- +- +- UInt & operator--() +- { +- SubOne(); +- +- return *this; +- } +- +- +- UInt operator--(int) +- { +- UInt temp( *this ); +- +- SubOne(); +- +- return temp; +- } +- +- +- +- /*! +- * +- * bitwise operators +- * +- */ +- +- UInt operator~() const +- { +- UInt temp( *this ); +- +- temp.BitNot(); +- +- return temp; +- } +- +- +- UInt operator&(const UInt & p2) const +- { +- UInt temp( *this ); +- +- temp.BitAnd(p2); +- +- return temp; +- } +- +- +- UInt & operator&=(const UInt & p2) +- { +- BitAnd(p2); +- +- return *this; +- } +- +- +- UInt operator|(const UInt & p2) const +- { +- UInt temp( *this ); +- +- temp.BitOr(p2); +- +- return temp; +- } +- +- +- UInt & operator|=(const UInt & p2) +- { +- BitOr(p2); +- +- return *this; +- } +- +- +- UInt operator^(const UInt & p2) const +- { +- UInt temp( *this ); +- +- temp.BitXor(p2); +- +- return temp; +- } +- +- +- UInt & operator^=(const UInt & p2) +- { +- BitXor(p2); +- +- return *this; +- } +- +- +- UInt operator>>(int move) const +- { +- UInt temp( *this ); +- +- temp.Rcr(move); +- +- return temp; +- } +- +- +- UInt & operator>>=(int move) +- { +- Rcr(move); +- +- return *this; +- } +- +- +- UInt operator<<(int move) const +- { +- UInt temp( *this ); +- +- temp.Rcl(move); +- +- return temp; +- } +- +- +- UInt & operator<<=(int move) +- { +- Rcl(move); +- +- return *this; +- } +- +- +- /*! +- * +- * input/output operators for standard streams +- * +- * (they are very simple, in the future they should be changed) +- * +- */ +- +- +-private: +- +- +- /*! +- an auxiliary method for outputing to standard streams +- */ +- template +- static ostream_type & OutputToStream(ostream_type & s, const UInt & l) +- { +- string_type ss; +- +- l.ToString(ss); +- s << ss; +- +- return s; +- } +- +- +-public: +- +- +- /*! +- output to standard streams +- */ +- friend std::ostream & operator<<(std::ostream & s, const UInt & l) +- { +- return OutputToStream(s, l); +- } +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- /*! +- output to standard streams +- */ +- friend std::wostream & operator<<(std::wostream & s, const UInt & l) +- { +- return OutputToStream(s, l); +- } +- +-#endif +- +- +- +-private: +- +- /*! +- an auxiliary method for reading from standard streams +- */ +- template +- static istream_type & InputFromStream(istream_type & s, UInt & l) +- { +- string_type ss; +- +- // char or wchar_t for operator>> +- char_type z; +- +- // operator>> omits white characters if they're set for ommiting +- s >> z; +- +- // we're reading only digits (base=10) +- while( s.good() && Misc::CharToDigit(z, 10)>=0 ) +- { +- ss += z; +- z = static_cast(s.get()); +- } +- +- // we're leaving the last read character +- // (it's not belonging to the value) +- s.unget(); +- +- l.FromString(ss); +- +- return s; +- } +- +-public: +- +- +- /*! +- input from standard streams +- */ +- friend std::istream & operator>>(std::istream & s, UInt & l) +- { +- return InputFromStream(s, l); +- } +- +- +-#ifndef TTMATH_DONT_USE_WCHAR +- +- /*! +- input from standard streams +- */ +- friend std::wistream & operator>>(std::wistream & s, UInt & l) +- { +- return InputFromStream(s, l); +- } +- +-#endif +- +- +- /* +- Following methods are defined in: +- ttmathuint_x86.h +- ttmathuint_x86_64.h +- ttmathuint_noasm.h +- */ +- +-#ifdef TTMATH_NOASM +- static uint AddTwoWords(uint a, uint b, uint carry, uint * result); +- static uint SubTwoWords(uint a, uint b, uint carry, uint * result); +- +-#ifdef TTMATH_PLATFORM64 +- +- union uint_ +- { +- struct +- { +- unsigned int low; // 32 bit +- unsigned int high; // 32 bit +- } u_; +- +- uint u; // 64 bit +- }; +- +- +- static void DivTwoWords2(uint a,uint b, uint c, uint * r, uint * rest); +- static uint DivTwoWordsNormalize(uint_ & a_, uint_ & b_, uint_ & c_); +- static uint DivTwoWordsUnnormalize(uint u, uint d); +- static unsigned int DivTwoWordsCalculate(uint_ u_, unsigned int u3, uint_ v_); +- static void MultiplySubtract(uint_ & u_, unsigned int & u3, unsigned int & q, uint_ v_); +- +-#endif // TTMATH_PLATFORM64 +-#endif // TTMATH_NOASM +- +- +-private: +- uint Rcl2_one(uint c); +- uint Rcr2_one(uint c); +- uint Rcl2(uint bits, uint c); +- uint Rcr2(uint bits, uint c); +- +-public: +- static const char * LibTypeStr(); +- static LibTypeCode LibType(); +- uint Add(const UInt & ss2, uint c=0); +- uint AddInt(uint value, uint index = 0); +- uint AddTwoInts(uint x2, uint x1, uint index); +- static uint AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result); +- uint Sub(const UInt & ss2, uint c=0); +- uint SubInt(uint value, uint index = 0); +- static uint SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result); +- static sint FindLeadingBitInWord(uint x); +- static sint FindLowestBitInWord(uint x); +- static uint SetBitInWord(uint & value, uint bit); +- static void MulTwoWords(uint a, uint b, uint * result_high, uint * result_low); +- static void DivTwoWords(uint a,uint b, uint c, uint * r, uint * rest); +- +-}; +- +- +- +-/*! +- this specialization is needed in order to not confused the compiler "error: ISO C++ forbids zero-size array" +- when compiling Mul3Big2() method +-*/ +-template<> +-class UInt<0> +-{ +-public: +- uint table[1]; +- +- void Mul2Big(const UInt<0> &, UInt<0> &) { TTMATH_ASSERT(false) }; +- void SetZero() { TTMATH_ASSERT(false) }; +- uint AddTwoInts(uint, uint, uint) { TTMATH_ASSERT(false) return 0; }; +-}; +- +- +-} //namespace +- +- +-#include "ttmathuint_x86.h" +-#include "ttmathuint_x86_64.h" +-#include "ttmathuint_noasm.h" +- +-#endif +diff --git a/extern/ttmath/ttmathuint_noasm.h b/extern/ttmath/ttmathuint_noasm.h +deleted file mode 100644 +index 07c73fc499..0000000000 +--- a/extern/ttmath/ttmathuint_noasm.h ++++ /dev/null +@@ -1,1017 +0,0 @@ +-/* +- * This file is a part of TTMath Bignum Library +- * and is distributed under the (new) BSD licence. +- * Author: Tomasz Sowa +- */ +- +-/* +- * Copyright (c) 2006-2010, Tomasz Sowa +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * +- * * Redistributions of source code must retain the above copyright notice, +- * this list of conditions and the following disclaimer. +- * +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * +- * * Neither the name Tomasz Sowa nor the names of contributors to this +- * project may be used to endorse or promote products derived +- * from this software without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +- * THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +-#ifndef headerfilettmathuint_noasm +-#define headerfilettmathuint_noasm +- +- +-#ifdef TTMATH_NOASM +- +-/*! +- \file ttmathuint_noasm.h +- \brief template class UInt with methods without any assembler code +- +- this file is included at the end of ttmathuint.h +-*/ +- +- +-namespace ttmath +-{ +- +- /*! +- returning the string represents the currect type of the library +- we have following types: +- asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits) +- asm_gcc_32 - with asm code designed for GCC (32 bits) +- asm_vc_64 - with asm for VC (64 bit) +- asm_gcc_64 - with asm for GCC (64 bit) +- no_asm_32 - pure C++ version (32 bit) - without any asm code +- no_asm_64 - pure C++ version (64 bit) - without any asm code +- */ +- template +- const char * UInt::LibTypeStr() +- { +- #ifdef TTMATH_PLATFORM32 +- static const char info[] = "no_asm_32"; +- #endif +- +- #ifdef TTMATH_PLATFORM64 +- static const char info[] = "no_asm_64"; +- #endif +- +- return info; +- } +- +- +- /*! +- returning the currect type of the library +- */ +- template +- LibTypeCode UInt::LibType() +- { +- #ifdef TTMATH_PLATFORM32 +- LibTypeCode info = no_asm_32; +- #endif +- +- #ifdef TTMATH_PLATFORM64 +- LibTypeCode info = no_asm_64; +- #endif +- +- return info; +- } +- +- +- /*! +- this method adds two words together +- returns carry +- +- this method is created only when TTMATH_NOASM macro is defined +- */ +- template +- uint UInt::AddTwoWords(uint a, uint b, uint carry, uint * result) +- { +- uint temp; +- +- if( carry == 0 ) +- { +- temp = a + b; +- +- if( temp < a ) +- carry = 1; +- } +- else +- { +- carry = 1; +- temp = a + b + carry; +- +- if( temp > a ) // !(temp<=a) +- carry = 0; +- } +- +- *result = temp; +- +- return carry; +- } +- +- +- +- /*! +- this method adding ss2 to the this and adding carry if it's defined +- (this = this + ss2 + c) +- +- c must be zero or one (might be a bigger value than 1) +- function returns carry (1) (if it was) +- */ +- +- template +- uint UInt::Add(const UInt & ss2, uint c) +- { +- uint i; +- +- for(i=0 ; i +- uint UInt::AddInt(uint value, uint index) +- { +- uint i, c; +- +- TTMATH_ASSERT( index < value_size ) +- +- +- c = AddTwoWords(table[index], value, 0, &table[index]); +- +- for(i=index+1 ; i +- uint UInt::AddTwoInts(uint x2, uint x1, uint index) +- { +- uint i, c; +- +- TTMATH_ASSERT( index < value_size - 1 ) +- +- +- c = AddTwoWords(table[index], x1, 0, &table[index]); +- c = AddTwoWords(table[index+1], x2, c, &table[index+1]); +- +- for(i=index+2 ; i +- uint UInt::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) +- { +- uint i, c = 0; +- +- TTMATH_ASSERT( ss1_size >= ss2_size ) +- +- for(i=0 ; i +- uint UInt::SubTwoWords(uint a, uint b, uint carry, uint * result) +- { +- if( carry == 0 ) +- { +- *result = a - b; +- +- if( a < b ) +- carry = 1; +- } +- else +- { +- carry = 1; +- *result = a - b - carry; +- +- if( a > b ) // !(a <= b ) +- carry = 0; +- } +- +- return carry; +- } +- +- +- +- +- /*! +- this method's subtracting ss2 from the 'this' and subtracting +- carry if it has been defined +- (this = this - ss2 - c) +- +- c must be zero or one (might be a bigger value than 1) +- function returns carry (1) (if it was) +- */ +- template +- uint UInt::Sub(const UInt & ss2, uint c) +- { +- uint i; +- +- for(i=0 ; i +- uint UInt::SubInt(uint value, uint index) +- { +- uint i, c; +- +- TTMATH_ASSERT( index < value_size ) +- +- +- c = SubTwoWords(table[index], value, 0, &table[index]); +- +- for(i=index+1 ; i +- uint UInt::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) +- { +- uint i, c = 0; +- +- TTMATH_ASSERT( ss1_size >= ss2_size ) +- +- for(i=0 ; i +- uint UInt::Rcl2_one(uint c) +- { +- uint i, new_c; +- +- if( c != 0 ) +- c = 1; +- +- for(i=0 ; i this -> return value +- +- the highest *bit* will be held the 'c' and +- the state of one additional bit (on the right hand side) +- will be returned +- +- for example: +- let this is 000000010 +- after Rcr2_one(1) there'll be 100000001 and Rcr2_one returns 0 +- */ +- template +- uint UInt::Rcr2_one(uint c) +- { +- sint i; // signed i +- uint new_c; +- +- if( c != 0 ) +- c = TTMATH_UINT_HIGHEST_BIT; +- +- for(i=sint(value_size)-1 ; i>=0 ; --i) +- { +- new_c = (table[i] & 1) ? TTMATH_UINT_HIGHEST_BIT : 0; +- table[i] = (table[i] >> 1) | c; +- c = new_c; +- } +- +- c = (c != 0)? 1 : 0; +- +- TTMATH_LOGC("UInt::Rcr2_one", c) +- +- return c; +- } +- +- +- +- +- /*! +- this method moves all bits into the left hand side +- return value <- this <- c +- +- the lowest *bits* will be held the 'c' and +- the state of one additional bit (on the left hand side) +- will be returned +- +- for example: +- let this is 001010000 +- after Rcl2(3, 1) there'll be 010000111 and Rcl2 returns 1 +- */ +- template +- uint UInt::Rcl2(uint bits, uint c) +- { +- TTMATH_ASSERT( bits>0 && bits> move; +- +- for(i=0 ; i> move; +- table[i] = (table[i] << bits) | c; +- c = new_c; +- } +- +- TTMATH_LOGC("UInt::Rcl2", (c & 1)) +- +- return (c & 1); +- } +- +- +- +- +- /*! +- this method moves all bits into the right hand side +- C -> this -> return value +- +- the highest *bits* will be held the 'c' and +- the state of one additional bit (on the right hand side) +- will be returned +- +- for example: +- let this is 000000010 +- after Rcr2(2, 1) there'll be 110000000 and Rcr2 returns 1 +- */ +- template +- uint UInt::Rcr2(uint bits, uint c) +- { +- TTMATH_ASSERT( bits>0 && bits=0 ; --i) +- { +- new_c = table[i] << move; +- table[i] = (table[i] >> bits) | c; +- c = new_c; +- } +- +- c = (c & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0; +- +- TTMATH_LOGC("UInt::Rcr2", c) +- +- return c; +- } +- +- +- +- +- /*! +- this method returns the number of the highest set bit in x +- if the 'x' is zero this method returns '-1' +- */ +- template +- sint UInt::FindLeadingBitInWord(uint x) +- { +- if( x == 0 ) +- return -1; +- +- uint bit = TTMATH_BITS_PER_UINT - 1; +- +- while( (x & TTMATH_UINT_HIGHEST_BIT) == 0 ) +- { +- x = x << 1; +- --bit; +- } +- +- return bit; +- } +- +- +- +- /*! +- this method returns the number of the highest set bit in x +- if the 'x' is zero this method returns '-1' +- */ +- template +- sint UInt::FindLowestBitInWord(uint x) +- { +- if( x == 0 ) +- return -1; +- +- uint bit = 0; +- +- while( (x & 1) == 0 ) +- { +- x = x >> 1; +- ++bit; +- } +- +- return bit; +- } +- +- +- +- /*! +- this method sets a special bit in the 'value' +- and returns the last state of the bit (zero or one) +- +- bit is from <0,TTMATH_BITS_PER_UINT-1> +- +- e.g. +- uint x = 100; +- uint bit = SetBitInWord(x, 3); +- now: x = 108 and bit = 0 +- */ +- template +- uint UInt::SetBitInWord(uint & value, uint bit) +- { +- TTMATH_ASSERT( bit < TTMATH_BITS_PER_UINT ) +- +- uint mask = 1; +- +- if( bit > 0 ) +- mask = mask << bit; +- +- uint last = value & mask; +- value = value | mask; +- +- return (last != 0) ? 1 : 0; +- } +- +- +- +- +- +- +- /*! +- * +- * Multiplication +- * +- * +- */ +- +- +- /*! +- multiplication: result_high:result_low = a * b +- result_high - higher word of the result +- result_low - lower word of the result +- +- this methos never returns a carry +- this method is used in the second version of the multiplication algorithms +- */ +- template +- void UInt::MulTwoWords(uint a, uint b, uint * result_high, uint * result_low) +- { +- #ifdef TTMATH_PLATFORM32 +- +- /* +- on 32bit platforms we have defined 'unsigned long long int' type known as 'ulint' in ttmath namespace +- this type has 64 bits, then we're using only one multiplication: 32bit * 32bit = 64bit +- */ +- +- union uint_ +- { +- struct +- { +- uint low; // 32 bits +- uint high; // 32 bits +- } u_; +- +- ulint u; // 64 bits +- } res; +- +- res.u = ulint(a) * ulint(b); // multiply two 32bit words, the result has 64 bits +- +- *result_high = res.u_.high; +- *result_low = res.u_.low; +- +- #else +- +- /* +- 64 bits platforms +- +- we don't have a native type which has 128 bits +- then we're splitting 'a' and 'b' to 4 parts (high and low halves) +- and using 4 multiplications (with additions and carry correctness) +- */ +- +- uint_ a_; +- uint_ b_; +- uint_ res_high1, res_high2; +- uint_ res_low1, res_low2; +- +- a_.u = a; +- b_.u = b; +- +- /* +- the multiplication is as follows (schoolbook algorithm with O(n^2) ): +- +- 32 bits 32 bits +- +- +--------------------------------+ +- | a_.u_.high | a_.u_.low | +- +--------------------------------+ +- | b_.u_.high | b_.u_.low | +- +--------------------------------+--------------------------------+ +- | res_high1.u | res_low1.u | +- +--------------------------------+--------------------------------+ +- | res_high2.u | res_low2.u | +- +--------------------------------+--------------------------------+ +- +- 64 bits 64 bits +- */ +- +- +- uint_ temp; +- +- res_low1.u = uint(b_.u_.low) * uint(a_.u_.low); +- +- temp.u = uint(res_low1.u_.high) + uint(b_.u_.low) * uint(a_.u_.high); +- res_low1.u_.high = temp.u_.low; +- res_high1.u_.low = temp.u_.high; +- res_high1.u_.high = 0; +- +- res_low2.u_.low = 0; +- temp.u = uint(b_.u_.high) * uint(a_.u_.low); +- res_low2.u_.high = temp.u_.low; +- +- res_high2.u = uint(b_.u_.high) * uint(a_.u_.high) + uint(temp.u_.high); +- +- uint c = AddTwoWords(res_low1.u, res_low2.u, 0, &res_low2.u); +- AddTwoWords(res_high1.u, res_high2.u, c, &res_high2.u); // there is no carry from here +- +- *result_high = res_high2.u; +- *result_low = res_low2.u; +- +- #endif +- } +- +- +- +- +- /*! +- * +- * Division +- * +- * +- */ +- +- +- /*! +- this method calculates 64bits word a:b / 32bits c (a higher, b lower word) +- r = a:b / c and rest - remainder +- +- * +- * WARNING: +- * the c has to be suitably large for the result being keeped in one word, +- * if c is equal zero there'll be a hardware interruption (0) +- * and probably the end of your program +- * +- */ +- template +- void UInt::DivTwoWords(uint a, uint b, uint c, uint * r, uint * rest) +- { +- // (a < c ) for the result to be one word +- TTMATH_ASSERT( c != 0 && a < c ) +- +- #ifdef TTMATH_PLATFORM32 +- +- union +- { +- struct +- { +- uint low; // 32 bits +- uint high; // 32 bits +- } u_; +- +- ulint u; // 64 bits +- } ab; +- +- ab.u_.high = a; +- ab.u_.low = b; +- +- *r = uint(ab.u / c); +- *rest = uint(ab.u % c); +- +- #else +- +- uint_ c_; +- c_.u = c; +- +- +- if( a == 0 ) +- { +- *r = b / c; +- *rest = b % c; +- } +- else +- if( c_.u_.high == 0 ) +- { +- // higher half of 'c' is zero +- // then higher half of 'a' is zero too (look at the asserts at the beginning - 'a' is smaller than 'c') +- uint_ a_, b_, res_, temp1, temp2; +- +- a_.u = a; +- b_.u = b; +- +- temp1.u_.high = a_.u_.low; +- temp1.u_.low = b_.u_.high; +- +- res_.u_.high = (unsigned int)(temp1.u / c); +- temp2.u_.high = (unsigned int)(temp1.u % c); +- temp2.u_.low = b_.u_.low; +- +- res_.u_.low = (unsigned int)(temp2.u / c); +- *rest = temp2.u % c; +- +- *r = res_.u; +- } +- else +- { +- return DivTwoWords2(a, b, c, r, rest); +- } +- +- #endif +- } +- +- +-#ifdef TTMATH_PLATFORM64 +- +- +- /*! +- this method is available only on 64bit platforms +- +- the same algorithm like the third division algorithm in ttmathuint.h +- but now with the radix=2^32 +- */ +- template +- void UInt::DivTwoWords2(uint a, uint b, uint c, uint * r, uint * rest) +- { +- // a is not zero +- // c_.u_.high is not zero +- +- uint_ a_, b_, c_, u_, q_; +- unsigned int u3; // 32 bit +- +- a_.u = a; +- b_.u = b; +- c_.u = c; +- +- // normalizing +- uint d = DivTwoWordsNormalize(a_, b_, c_); +- +- // loop from j=1 to j=0 +- // the first step (for j=2) is skipped because our result is only in one word, +- // (first 'q' were 0 and nothing would be changed) +- u_.u_.high = a_.u_.high; +- u_.u_.low = a_.u_.low; +- u3 = b_.u_.high; +- q_.u_.high = DivTwoWordsCalculate(u_, u3, c_); +- MultiplySubtract(u_, u3, q_.u_.high, c_); +- +- u_.u_.high = u_.u_.low; +- u_.u_.low = u3; +- u3 = b_.u_.low; +- q_.u_.low = DivTwoWordsCalculate(u_, u3, c_); +- MultiplySubtract(u_, u3, q_.u_.low, c_); +- +- *r = q_.u; +- +- // unnormalizing for the remainder +- u_.u_.high = u_.u_.low; +- u_.u_.low = u3; +- *rest = DivTwoWordsUnnormalize(u_.u, d); +- } +- +- +- +- +- template +- uint UInt::DivTwoWordsNormalize(uint_ & a_, uint_ & b_, uint_ & c_) +- { +- uint d = 0; +- +- for( ; (c_.u & TTMATH_UINT_HIGHEST_BIT) == 0 ; ++d ) +- { +- c_.u = c_.u << 1; +- +- uint bc = b_.u & TTMATH_UINT_HIGHEST_BIT; // carry from 'b' +- +- b_.u = b_.u << 1; +- a_.u = a_.u << 1; // carry bits from 'a' are simply skipped +- +- if( bc ) +- a_.u = a_.u | 1; +- } +- +- return d; +- } +- +- +- template +- uint UInt::DivTwoWordsUnnormalize(uint u, uint d) +- { +- if( d == 0 ) +- return u; +- +- u = u >> d; +- +- return u; +- } +- +- +- template +- unsigned int UInt::DivTwoWordsCalculate(uint_ u_, unsigned int u3, uint_ v_) +- { +- bool next_test; +- uint_ qp_, rp_, temp_; +- +- qp_.u = u_.u / uint(v_.u_.high); +- rp_.u = u_.u % uint(v_.u_.high); +- +- TTMATH_ASSERT( qp_.u_.high==0 || qp_.u_.high==1 ) +- +- do +- { +- bool decrease = false; +- +- if( qp_.u_.high == 1 ) +- decrease = true; +- else +- { +- temp_.u_.high = rp_.u_.low; +- temp_.u_.low = u3; +- +- if( qp_.u * uint(v_.u_.low) > temp_.u ) +- decrease = true; +- } +- +- next_test = false; +- +- if( decrease ) +- { +- --qp_.u; +- rp_.u += v_.u_.high; +- +- if( rp_.u_.high == 0 ) +- next_test = true; +- } +- } +- while( next_test ); +- +- return qp_.u_.low; +- } +- +- +- template +- void UInt::MultiplySubtract(uint_ & u_, unsigned int & u3, unsigned int & q, uint_ v_) +- { +- uint_ temp_; +- +- uint res_high; +- uint res_low; +- +- MulTwoWords(v_.u, q, &res_high, &res_low); +- +- uint_ sub_res_high_; +- uint_ sub_res_low_; +- +- temp_.u_.high = u_.u_.low; +- temp_.u_.low = u3; +- +- uint c = SubTwoWords(temp_.u, res_low, 0, &sub_res_low_.u); +- +- temp_.u_.high = 0; +- temp_.u_.low = u_.u_.high; +- c = SubTwoWords(temp_.u, res_high, c, &sub_res_high_.u); +- +- if( c ) +- { +- --q; +- +- c = AddTwoWords(sub_res_low_.u, v_.u, 0, &sub_res_low_.u); +- AddTwoWords(sub_res_high_.u, 0, c, &sub_res_high_.u); +- } +- +- u_.u_.high = sub_res_high_.u_.low; +- u_.u_.low = sub_res_low_.u_.high; +- u3 = sub_res_low_.u_.low; +- } +- +-#endif // #ifdef TTMATH_PLATFORM64 +- +- +- +-} //namespace +- +- +-#endif //ifdef TTMATH_NOASM +-#endif +- +- +- +- +diff --git a/extern/ttmath/ttmathuint_x86.h b/extern/ttmath/ttmathuint_x86.h +deleted file mode 100644 +index 1dd087f524..0000000000 +--- a/extern/ttmath/ttmathuint_x86.h ++++ /dev/null +@@ -1,1602 +0,0 @@ +-/* +- * This file is a part of TTMath Bignum Library +- * and is distributed under the (new) BSD licence. +- * Author: Tomasz Sowa +- */ +- +-/* +- * Copyright (c) 2006-2009, Tomasz Sowa +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * +- * * Redistributions of source code must retain the above copyright notice, +- * this list of conditions and the following disclaimer. +- * +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * +- * * Neither the name Tomasz Sowa nor the names of contributors to this +- * project may be used to endorse or promote products derived +- * from this software without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +- * THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +- +- +-#ifndef headerfilettmathuint_x86 +-#define headerfilettmathuint_x86 +- +- +-#ifndef TTMATH_NOASM +-#ifdef TTMATH_PLATFORM32 +- +- +-/*! +- \file ttmathuint_x86.h +- \brief template class UInt with assembler code for 32bit x86 processors +- +- this file is included at the end of ttmathuint.h +-*/ +- +- +- +-/*! +- \brief a namespace for the TTMath library +-*/ +-namespace ttmath +-{ +- +- /*! +- returning the string represents the currect type of the library +- we have following types: +- asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits) +- asm_gcc_32 - with asm code designed for GCC (32 bits) +- asm_vc_64 - with asm for VC (64 bit) +- asm_gcc_64 - with asm for GCC (64 bit) +- no_asm_32 - pure C++ version (32 bit) - without any asm code +- no_asm_64 - pure C++ version (64 bit) - without any asm code +- */ +- template +- const char * UInt::LibTypeStr() +- { +- #ifndef __GNUC__ +- static const char info[] = "asm_vc_32"; +- #endif +- +- #ifdef __GNUC__ +- static const char info[] = "asm_gcc_32"; +- #endif +- +- return info; +- } +- +- +- /*! +- returning the currect type of the library +- */ +- template +- LibTypeCode UInt::LibType() +- { +- #ifndef __GNUC__ +- LibTypeCode info = asm_vc_32; +- #endif +- +- #ifdef __GNUC__ +- LibTypeCode info = asm_gcc_32; +- #endif +- +- return info; +- } +- +- +- +- /*! +- * +- * basic mathematic functions +- * +- */ +- +- +- /*! +- adding ss2 to the this and adding carry if it's defined +- (this = this + ss2 + c) +- +- c must be zero or one (might be a bigger value than 1) +- function returns carry (1) (if it has been) +- */ +- template +- uint UInt::Add(const UInt & ss2, uint c) +- { +- uint b = value_size; +- uint * p1 = table; +- uint * p2 = const_cast(ss2.table); +- +- // we don't have to use TTMATH_REFERENCE_ASSERT here +- // this algorithm doesn't require it +- +- #ifndef __GNUC__ +- +- // this part might be compiled with for example visual c +- +- __asm +- { +- push eax +- push ebx +- push ecx +- push edx +- push esi +- +- mov ecx,[b] +- +- mov ebx,[p1] +- mov esi,[p2] +- +- xor edx,edx // edx=0 +- mov eax,[c] +- neg eax // CF=1 if rax!=0 , CF=0 if rax==0 +- +- ttmath_loop: +- mov eax,[esi+edx*4] +- adc [ebx+edx*4],eax +- +- inc edx +- dec ecx +- jnz ttmath_loop +- +- adc ecx, ecx +- mov [c], ecx +- +- pop esi +- pop edx +- pop ecx +- pop ebx +- pop eax +- } +- +- +- +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy, dummy2; +- // this part should be compiled with gcc +- +- __asm__ __volatile__( +- +- "xorl %%edx, %%edx \n" +- "negl %%eax \n" // CF=1 if rax!=0 , CF=0 if rax==0 +- +- "1: \n" +- "movl (%%esi,%%edx,4), %%eax \n" +- "adcl %%eax, (%%ebx,%%edx,4) \n" +- +- "incl %%edx \n" +- "decl %%ecx \n" +- "jnz 1b \n" +- +- "adc %%ecx, %%ecx \n" +- +- : "=c" (c), "=a" (dummy), "=d" (dummy2) +- : "0" (b), "1" (c), "b" (p1), "S" (p2) +- : "cc", "memory" ); +- #endif +- +- TTMATH_LOGC("UInt::Add", c) +- +- return c; +- } +- +- +- +- /*! +- adding one word (at a specific position) +- and returning a carry (if it has been) +- +- e.g. +- +- if we've got (value_size=3): +- table[0] = 10; +- table[1] = 30; +- table[2] = 5; +- and we call: +- AddInt(2,1) +- then it'll be: +- table[0] = 10; +- table[1] = 30 + 2; +- table[2] = 5; +- +- of course if there was a carry from table[2] it would be returned +- */ +- template +- uint UInt::AddInt(uint value, uint index) +- { +- uint b = value_size; +- uint * p1 = table; +- uint c; +- +- TTMATH_ASSERT( index < value_size ) +- +- #ifndef __GNUC__ +- +- __asm +- { +- push eax +- push ebx +- push ecx +- push edx +- +- mov ecx, [b] +- sub ecx, [index] +- +- mov edx, [index] +- mov ebx, [p1] +- +- mov eax, [value] +- +- ttmath_loop: +- add [ebx+edx*4], eax +- jnc ttmath_end +- +- mov eax, 1 +- inc edx +- dec ecx +- jnz ttmath_loop +- +- ttmath_end: +- setc al +- movzx edx, al +- mov [c], edx +- +- pop edx +- pop ecx +- pop ebx +- pop eax +- } +- +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy, dummy2; +- +- __asm__ __volatile__( +- +- "subl %%edx, %%ecx \n" +- +- "1: \n" +- "addl %%eax, (%%ebx,%%edx,4) \n" +- "jnc 2f \n" +- +- "movl $1, %%eax \n" +- "incl %%edx \n" +- "decl %%ecx \n" +- "jnz 1b \n" +- +- "2: \n" +- "setc %%al \n" +- "movzx %%al, %%edx \n" +- +- : "=d" (c), "=a" (dummy), "=c" (dummy2) +- : "0" (index), "1" (value), "2" (b), "b" (p1) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_LOGC("UInt::AddInt", c) +- +- return c; +- } +- +- +- +- +- /*! +- adding only two unsigned words to the existing value +- and these words begin on the 'index' position +- (it's used in the multiplication algorithm 2) +- +- index should be equal or smaller than value_size-2 (index <= value_size-2) +- x1 - lower word, x2 - higher word +- +- for example if we've got value_size equal 4 and: +- table[0] = 3 +- table[1] = 4 +- table[2] = 5 +- table[3] = 6 +- then let +- x1 = 10 +- x2 = 20 +- and +- index = 1 +- +- the result of this method will be: +- table[0] = 3 +- table[1] = 4 + x1 = 14 +- table[2] = 5 + x2 = 25 +- table[3] = 6 +- +- and no carry at the end of table[3] +- +- (of course if there was a carry in table[2](5+20) then +- this carry would be passed to the table[3] etc.) +- */ +- template +- uint UInt::AddTwoInts(uint x2, uint x1, uint index) +- { +- uint b = value_size; +- uint * p1 = table; +- uint c; +- +- TTMATH_ASSERT( index < value_size - 1 ) +- +- #ifndef __GNUC__ +- __asm +- { +- push eax +- push ebx +- push ecx +- push edx +- +- mov ecx, [b] +- sub ecx, [index] +- +- mov ebx, [p1] +- mov edx, [index] +- +- mov eax, [x1] +- add [ebx+edx*4], eax +- inc edx +- dec ecx +- +- mov eax, [x2] +- +- ttmath_loop: +- adc [ebx+edx*4], eax +- jnc ttmath_end +- +- mov eax, 0 +- inc edx +- dec ecx +- jnz ttmath_loop +- +- ttmath_end: +- setc al +- movzx edx, al +- mov [c], edx +- +- pop edx +- pop ecx +- pop ebx +- pop eax +- +- } +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy, dummy2; +- +- __asm__ __volatile__( +- +- "subl %%edx, %%ecx \n" +- +- "addl %%esi, (%%ebx,%%edx,4) \n" +- "incl %%edx \n" +- "decl %%ecx \n" +- +- "1: \n" +- "adcl %%eax, (%%ebx,%%edx,4) \n" +- "jnc 2f \n" +- +- "mov $0, %%eax \n" +- "incl %%edx \n" +- "decl %%ecx \n" +- "jnz 1b \n" +- +- "2: \n" +- "setc %%al \n" +- "movzx %%al, %%eax \n" +- +- : "=a" (c), "=c" (dummy), "=d" (dummy2) +- : "0" (x2), "1" (b), "2" (index), "b" (p1), "S" (x1) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_LOGC("UInt::AddTwoInts", c) +- +- return c; +- } +- +- +- +- /*! +- this static method addes one vector to the other +- 'ss1' is larger in size or equal to 'ss2' +- +- ss1 points to the first (larger) vector +- ss2 points to the second vector +- ss1_size - size of the ss1 (and size of the result too) +- ss2_size - size of the ss2 +- result - is the result vector (which has size the same as ss1: ss1_size) +- +- Example: ss1_size is 5, ss2_size is 3 +- ss1: ss2: result (output): +- 5 1 5+1 +- 4 3 4+3 +- 2 7 2+7 +- 6 6 +- 9 9 +- of course the carry is propagated and will be returned from the last item +- (this method is used by the Karatsuba multiplication algorithm) +- */ +- template +- uint UInt::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) +- { +- TTMATH_ASSERT( ss1_size >= ss2_size ) +- +- uint rest = ss1_size - ss2_size; +- uint c; +- +- #ifndef __GNUC__ +- +- // this part might be compiled with for example visual c +- __asm +- { +- pushad +- +- mov ecx, [ss2_size] +- xor edx, edx // edx = 0, cf = 0 +- +- mov esi, [ss1] +- mov ebx, [ss2] +- mov edi, [result] +- +- ttmath_loop: +- mov eax, [esi+edx*4] +- adc eax, [ebx+edx*4] +- mov [edi+edx*4], eax +- +- inc edx +- dec ecx +- jnz ttmath_loop +- +- adc ecx, ecx // ecx has the cf state +- +- mov ebx, [rest] +- or ebx, ebx +- jz ttmath_end +- +- xor ebx, ebx // ebx = 0 +- neg ecx // setting cf from ecx +- mov ecx, [rest] // ecx is != 0 +- +- ttmath_loop2: +- mov eax, [esi+edx*4] +- adc eax, ebx +- mov [edi+edx*4], eax +- +- inc edx +- dec ecx +- jnz ttmath_loop2 +- +- adc ecx, ecx +- +- ttmath_end: +- mov [c], ecx +- +- popad +- } +- +- #endif +- +- +- #ifdef __GNUC__ +- +- // this part should be compiled with gcc +- uint dummy1, dummy2, dummy3; +- +- __asm__ __volatile__( +- "push %%edx \n" +- "xor %%edx, %%edx \n" // edx = 0, cf = 0 +- "1: \n" +- "mov (%%esi,%%edx,4), %%eax \n" +- "adc (%%ebx,%%edx,4), %%eax \n" +- "mov %%eax, (%%edi,%%edx,4) \n" +- +- "inc %%edx \n" +- "dec %%ecx \n" +- "jnz 1b \n" +- +- "adc %%ecx, %%ecx \n" // ecx has the cf state +- "pop %%eax \n" // eax = rest +- +- "or %%eax, %%eax \n" +- "jz 3f \n" +- +- "xor %%ebx, %%ebx \n" // ebx = 0 +- "neg %%ecx \n" // setting cf from ecx +- "mov %%eax, %%ecx \n" // ecx=rest and is != 0 +- "2: \n" +- "mov (%%esi, %%edx, 4), %%eax \n" +- "adc %%ebx, %%eax \n" +- "mov %%eax, (%%edi, %%edx, 4) \n" +- +- "inc %%edx \n" +- "dec %%ecx \n" +- "jnz 2b \n" +- +- "adc %%ecx, %%ecx \n" +- "3: \n" +- +- : "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3) +- : "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_VECTOR_LOGC("UInt::AddVector", c, result, ss1_size) +- +- return c; +- } +- +- +- /*! +- subtracting ss2 from the 'this' and subtracting +- carry if it has been defined +- (this = this - ss2 - c) +- +- c must be zero or one (might be a bigger value than 1) +- function returns carry (1) (if it has been) +- */ +- template +- uint UInt::Sub(const UInt & ss2, uint c) +- { +- uint b = value_size; +- uint * p1 = table; +- uint * p2 = const_cast(ss2.table); +- +- // we don't have to use TTMATH_REFERENCE_ASSERT here +- // this algorithm doesn't require it +- +- #ifndef __GNUC__ +- +- __asm +- { +- push eax +- push ebx +- push ecx +- push edx +- push esi +- +- mov ecx,[b] +- +- mov ebx,[p1] +- mov esi,[p2] +- +- xor edx,edx // edx=0 +- mov eax,[c] +- neg eax // CF=1 if rax!=0 , CF=0 if rax==0 +- +- ttmath_loop: +- mov eax,[esi+edx*4] +- sbb [ebx+edx*4],eax +- +- inc edx +- dec ecx +- jnz ttmath_loop +- +- adc ecx, ecx +- mov [c], ecx +- +- pop esi +- pop edx +- pop ecx +- pop ebx +- pop eax +- } +- +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy, dummy2; +- +- __asm__ __volatile__( +- +- "xorl %%edx, %%edx \n" +- "negl %%eax \n" // CF=1 if rax!=0 , CF=0 if rax==0 +- +- "1: \n" +- "movl (%%esi,%%edx,4), %%eax \n" +- "sbbl %%eax, (%%ebx,%%edx,4) \n" +- +- "incl %%edx \n" +- "decl %%ecx \n" +- "jnz 1b \n" +- +- "adc %%ecx, %%ecx \n" +- +- : "=c" (c), "=a" (dummy), "=d" (dummy2) +- : "0" (b), "1" (c), "b" (p1), "S" (p2) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_LOGC("UInt::Sub", c) +- +- return c; +- } +- +- +- +- +- /*! +- this method subtracts one word (at a specific position) +- and returns a carry (if it was) +- +- e.g. +- +- if we've got (value_size=3): +- table[0] = 10; +- table[1] = 30; +- table[2] = 5; +- and we call: +- SubInt(2,1) +- then it'll be: +- table[0] = 10; +- table[1] = 30 - 2; +- table[2] = 5; +- +- of course if there was a carry from table[2] it would be returned +- */ +- template +- uint UInt::SubInt(uint value, uint index) +- { +- uint b = value_size; +- uint * p1 = table; +- uint c; +- +- TTMATH_ASSERT( index < value_size ) +- +- #ifndef __GNUC__ +- +- __asm +- { +- push eax +- push ebx +- push ecx +- push edx +- +- mov ecx, [b] +- sub ecx, [index] +- +- mov edx, [index] +- mov ebx, [p1] +- +- mov eax, [value] +- +- ttmath_loop: +- sub [ebx+edx*4], eax +- jnc ttmath_end +- +- mov eax, 1 +- inc edx +- dec ecx +- jnz ttmath_loop +- +- ttmath_end: +- setc al +- movzx edx, al +- mov [c], edx +- +- pop edx +- pop ecx +- pop ebx +- pop eax +- } +- +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy, dummy2; +- +- __asm__ __volatile__( +- +- "subl %%edx, %%ecx \n" +- +- "1: \n" +- "subl %%eax, (%%ebx,%%edx,4) \n" +- "jnc 2f \n" +- +- "movl $1, %%eax \n" +- "incl %%edx \n" +- "decl %%ecx \n" +- "jnz 1b \n" +- +- "2: \n" +- "setc %%al \n" +- "movzx %%al, %%edx \n" +- +- : "=d" (c), "=a" (dummy), "=c" (dummy2) +- : "0" (index), "1" (value), "2" (b), "b" (p1) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_LOGC("UInt::SubInt", c) +- +- return c; +- } +- +- +- +- /*! +- this static method subtractes one vector from the other +- 'ss1' is larger in size or equal to 'ss2' +- +- ss1 points to the first (larger) vector +- ss2 points to the second vector +- ss1_size - size of the ss1 (and size of the result too) +- ss2_size - size of the ss2 +- result - is the result vector (which has size the same as ss1: ss1_size) +- +- Example: ss1_size is 5, ss2_size is 3 +- ss1: ss2: result (output): +- 5 1 5-1 +- 4 3 4-3 +- 2 7 2-7 +- 6 6-1 (the borrow from previous item) +- 9 9 +- return (carry): 0 +- of course the carry (borrow) is propagated and will be returned from the last item +- (this method is used by the Karatsuba multiplication algorithm) +- */ +- template +- uint UInt::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) +- { +- TTMATH_ASSERT( ss1_size >= ss2_size ) +- +- uint rest = ss1_size - ss2_size; +- uint c; +- +- #ifndef __GNUC__ +- +- // this part might be compiled with for example visual c +- +- /* +- the asm code is nearly the same as in AddVector +- only two instructions 'adc' are changed to 'sbb' +- */ +- __asm +- { +- pushad +- +- mov ecx, [ss2_size] +- xor edx, edx // edx = 0, cf = 0 +- +- mov esi, [ss1] +- mov ebx, [ss2] +- mov edi, [result] +- +- ttmath_loop: +- mov eax, [esi+edx*4] +- sbb eax, [ebx+edx*4] +- mov [edi+edx*4], eax +- +- inc edx +- dec ecx +- jnz ttmath_loop +- +- adc ecx, ecx // ecx has the cf state +- +- mov ebx, [rest] +- or ebx, ebx +- jz ttmath_end +- +- xor ebx, ebx // ebx = 0 +- neg ecx // setting cf from ecx +- mov ecx, [rest] // ecx is != 0 +- +- ttmath_loop2: +- mov eax, [esi+edx*4] +- sbb eax, ebx +- mov [edi+edx*4], eax +- +- inc edx +- dec ecx +- jnz ttmath_loop2 +- +- adc ecx, ecx +- +- ttmath_end: +- mov [c], ecx +- +- popad +- } +- +- #endif +- +- +- #ifdef __GNUC__ +- +- // this part should be compiled with gcc +- uint dummy1, dummy2, dummy3; +- +- __asm__ __volatile__( +- "push %%edx \n" +- "xor %%edx, %%edx \n" // edx = 0, cf = 0 +- "1: \n" +- "mov (%%esi,%%edx,4), %%eax \n" +- "sbb (%%ebx,%%edx,4), %%eax \n" +- "mov %%eax, (%%edi,%%edx,4) \n" +- +- "inc %%edx \n" +- "dec %%ecx \n" +- "jnz 1b \n" +- +- "adc %%ecx, %%ecx \n" // ecx has the cf state +- "pop %%eax \n" // eax = rest +- +- "or %%eax, %%eax \n" +- "jz 3f \n" +- +- "xor %%ebx, %%ebx \n" // ebx = 0 +- "neg %%ecx \n" // setting cf from ecx +- "mov %%eax, %%ecx \n" // ecx=rest and is != 0 +- "2: \n" +- "mov (%%esi, %%edx, 4), %%eax \n" +- "sbb %%ebx, %%eax \n" +- "mov %%eax, (%%edi, %%edx, 4) \n" +- +- "inc %%edx \n" +- "dec %%ecx \n" +- "jnz 2b \n" +- +- "adc %%ecx, %%ecx \n" +- "3: \n" +- +- : "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3) +- : "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_VECTOR_LOGC("UInt::SubVector", c, result, ss1_size) +- +- return c; +- } +- +- +- +- /*! +- this method moves all bits into the left hand side +- return value <- this <- c +- +- the lowest *bit* will be held the 'c' and +- the state of one additional bit (on the left hand side) +- will be returned +- +- for example: +- let this is 001010000 +- after Rcl2_one(1) there'll be 010100001 and Rcl2_one returns 0 +- */ +- template +- uint UInt::Rcl2_one(uint c) +- { +- uint b = value_size; +- uint * p1 = table; +- +- #ifndef __GNUC__ +- __asm +- { +- push ebx +- push ecx +- push edx +- +- mov ebx, [p1] +- xor edx, edx +- mov ecx, [c] +- neg ecx +- mov ecx, [b] +- +- ttmath_loop: +- rcl dword ptr [ebx+edx*4], 1 +- +- inc edx +- dec ecx +- jnz ttmath_loop +- +- adc ecx, ecx +- mov [c], ecx +- +- pop edx +- pop ecx +- pop ebx +- } +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy, dummy2; +- +- __asm__ __volatile__( +- +- "xorl %%edx, %%edx \n" // edx=0 +- "negl %%eax \n" // CF=1 if eax!=0 , CF=0 if eax==0 +- +- "1: \n" +- "rcll $1, (%%ebx, %%edx, 4) \n" +- +- "incl %%edx \n" +- "decl %%ecx \n" +- "jnz 1b \n" +- +- "adcl %%ecx, %%ecx \n" +- +- : "=c" (c), "=a" (dummy), "=d" (dummy2) +- : "0" (b), "1" (c), "b" (p1) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_LOGC("UInt::Rcl2_one", c) +- +- return c; +- } +- +- +- +- /*! +- this method moves all bits into the right hand side +- c -> this -> return value +- +- the highest *bit* will be held the 'c' and +- the state of one additional bit (on the right hand side) +- will be returned +- +- for example: +- let this is 000000010 +- after Rcr2_one(1) there'll be 100000001 and Rcr2_one returns 0 +- */ +- template +- uint UInt::Rcr2_one(uint c) +- { +- uint b = value_size; +- uint * p1 = table; +- +- #ifndef __GNUC__ +- __asm +- { +- push ebx +- push ecx +- +- mov ebx, [p1] +- mov ecx, [c] +- neg ecx +- mov ecx, [b] +- +- ttmath_loop: +- rcr dword ptr [ebx+ecx*4-4], 1 +- +- dec ecx +- jnz ttmath_loop +- +- adc ecx, ecx +- mov [c], ecx +- +- pop ecx +- pop ebx +- } +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy; +- +- __asm__ __volatile__( +- +- "negl %%eax \n" // CF=1 if eax!=0 , CF=0 if eax==0 +- +- "1: \n" +- "rcrl $1, -4(%%ebx, %%ecx, 4) \n" +- +- "decl %%ecx \n" +- "jnz 1b \n" +- +- "adcl %%ecx, %%ecx \n" +- +- : "=c" (c), "=a" (dummy) +- : "0" (b), "1" (c), "b" (p1) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_LOGC("UInt::Rcr2_one", c) +- +- return c; +- } +- +- +- +-#ifdef _MSC_VER +-#pragma warning (disable : 4731) +-//warning C4731: frame pointer register 'ebp' modified by inline assembly code +-#endif +- +- +- +- /*! +- this method moves all bits into the left hand side +- return value <- this <- c +- +- the lowest *bits* will be held the 'c' and +- the state of one additional bit (on the left hand side) +- will be returned +- +- for example: +- let this is 001010000 +- after Rcl2(3, 1) there'll be 010000111 and Rcl2 returns 1 +- */ +- template +- uint UInt::Rcl2(uint bits, uint c) +- { +- TTMATH_ASSERT( bits>0 && bits edx -> cf) (cl times) +- "movl %%edx, %%ebp \n" // ebp = edx = mask +- "movl %%esi, %%ecx \n" +- +- "xorl %%edx, %%edx \n" +- "movl %%edx, %%esi \n" +- "orl %%eax, %%eax \n" +- "cmovnz %%ebp, %%esi \n" // if(c) esi=mask else esi=0 +- +- "1: \n" +- "roll %%cl, (%%ebx,%%edx,4) \n" +- +- "movl (%%ebx,%%edx,4), %%eax \n" +- "andl %%ebp, %%eax \n" +- "xorl %%eax, (%%ebx,%%edx,4) \n" +- "orl %%esi, (%%ebx,%%edx,4) \n" +- "movl %%eax, %%esi \n" +- +- "incl %%edx \n" +- "decl %%edi \n" +- "jnz 1b \n" +- +- "and $1, %%eax \n" +- +- "pop %%ebp \n" +- +- : "=a" (c), "=D" (dummy), "=S" (dummy2), "=d" (dummy3) +- : "0" (c), "1" (b), "b" (p1), "c" (bits) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_LOGC("UInt::Rcl2", c) +- +- return c; +- } +- +- +- +- +- /*! +- this method moves all bits into the right hand side +- C -> this -> return value +- +- the highest *bits* will be held the 'c' and +- the state of one additional bit (on the right hand side) +- will be returned +- +- for example: +- let this is 000000010 +- after Rcr2(2, 1) there'll be 110000000 and Rcr2 returns 1 +- */ +- template +- uint UInt::Rcr2(uint bits, uint c) +- { +- TTMATH_ASSERT( bits>0 && bits +- sint UInt::FindLeadingBitInWord(uint x) +- { +- sint result; +- +- #ifndef __GNUC__ +- __asm +- { +- push eax +- push edx +- +- mov edx,-1 +- bsr eax,[x] +- cmovz eax,edx +- mov [result], eax +- +- pop edx +- pop eax +- } +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy; +- +- __asm__ ( +- +- "movl $-1, %1 \n" +- "bsrl %2, %0 \n" +- "cmovz %1, %0 \n" +- +- : "=r" (result), "=&r" (dummy) +- : "r" (x) +- : "cc" ); +- +- #endif +- +- return result; +- } +- +- +- +- /* +- this method returns the number of the smallest set bit in one 32-bit word +- if the 'x' is zero this method returns '-1' +- */ +- template +- sint UInt::FindLowestBitInWord(uint x) +- { +- sint result; +- +- #ifndef __GNUC__ +- __asm +- { +- push eax +- push edx +- +- mov edx,-1 +- bsf eax,[x] +- cmovz eax,edx +- mov [result], eax +- +- pop edx +- pop eax +- } +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy; +- +- __asm__ ( +- +- "movl $-1, %1 \n" +- "bsfl %2, %0 \n" +- "cmovz %1, %0 \n" +- +- : "=r" (result), "=&r" (dummy) +- : "r" (x) +- : "cc" ); +- +- #endif +- +- return result; +- } +- +- +- +- /*! +- this method sets a special bit in the 'value' +- and returns the last state of the bit (zero or one) +- +- bit is from <0,31> +- e.g. +- uint x = 100; +- uint bit = SetBitInWord(x, 3); +- now: x = 108 and bit = 0 +- */ +- template +- uint UInt::SetBitInWord(uint & value, uint bit) +- { +- TTMATH_ASSERT( bit < TTMATH_BITS_PER_UINT ) +- +- uint old_bit; +- uint v = value; +- +- #ifndef __GNUC__ +- __asm +- { +- push ebx +- push eax +- +- mov eax, [v] +- mov ebx, [bit] +- bts eax, ebx +- mov [v], eax +- +- setc bl +- movzx ebx, bl +- mov [old_bit], ebx +- +- pop eax +- pop ebx +- } +- #endif +- +- +- #ifdef __GNUC__ +- __asm__ ( +- +- "btsl %%ebx, %%eax \n" +- "setc %%bl \n" +- "movzx %%bl, %%ebx \n" +- +- : "=a" (v), "=b" (old_bit) +- : "0" (v), "1" (bit) +- : "cc" ); +- +- #endif +- +- value = v; +- +- return old_bit; +- } +- +- +- +- +- /*! +- multiplication: result_high:result_low = a * b +- result_high - higher word of the result +- result_low - lower word of the result +- +- this methos never returns a carry +- this method is used in the second version of the multiplication algorithms +- */ +- template +- void UInt::MulTwoWords(uint a, uint b, uint * result_high, uint * result_low) +- { +- /* +- we must use these temporary variables in order to inform the compilator +- that value pointed with result1 and result2 has changed +- +- this has no effect in visual studio but it's useful when +- using gcc and options like -Ox +- */ +- uint result1_; +- uint result2_; +- +- #ifndef __GNUC__ +- +- __asm +- { +- push eax +- push edx +- +- mov eax, [a] +- mul dword ptr [b] +- +- mov [result2_], edx +- mov [result1_], eax +- +- pop edx +- pop eax +- } +- +- #endif +- +- +- #ifdef __GNUC__ +- +- __asm__ ( +- +- "mull %%edx \n" +- +- : "=a" (result1_), "=d" (result2_) +- : "0" (a), "1" (b) +- : "cc" ); +- +- #endif +- +- +- *result_low = result1_; +- *result_high = result2_; +- } +- +- +- +- +- +- /*! +- * +- * Division +- * +- * +- */ +- +- +- +- +- /*! +- this method calculates 64bits word a:b / 32bits c (a higher, b lower word) +- r = a:b / c and rest - remainder +- +- * +- * WARNING: +- * if r (one word) is too small for the result or c is equal zero +- * there'll be a hardware interruption (0) +- * and probably the end of your program +- * +- */ +- template +- void UInt::DivTwoWords(uint a, uint b, uint c, uint * r, uint * rest) +- { +- uint r_; +- uint rest_; +- /* +- these variables have similar meaning like those in +- the multiplication algorithm MulTwoWords +- */ +- +- TTMATH_ASSERT( c != 0 ) +- +- #ifndef __GNUC__ +- __asm +- { +- push eax +- push edx +- +- mov edx, [a] +- mov eax, [b] +- div dword ptr [c] +- +- mov [r_], eax +- mov [rest_], edx +- +- pop edx +- pop eax +- } +- #endif +- +- +- #ifdef __GNUC__ +- +- __asm__ ( +- +- "divl %%ecx \n" +- +- : "=a" (r_), "=d" (rest_) +- : "0" (b), "1" (a), "c" (c) +- : "cc" ); +- +- #endif +- +- +- *r = r_; +- *rest = rest_; +- +- } +- +- +- +-} //namespace +- +- +- +-#endif //ifdef TTMATH_PLATFORM32 +-#endif //ifndef TTMATH_NOASM +-#endif +diff --git a/extern/ttmath/ttmathuint_x86_64.h b/extern/ttmath/ttmathuint_x86_64.h +deleted file mode 100644 +index 188fc5e7bd..0000000000 +--- a/extern/ttmath/ttmathuint_x86_64.h ++++ /dev/null +@@ -1,1146 +0,0 @@ +-/* +- * This file is a part of TTMath Bignum Library +- * and is distributed under the (new) BSD licence. +- * Author: Tomasz Sowa +- */ +- +-/* +- * Copyright (c) 2006-2010, Tomasz Sowa +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * +- * * Redistributions of source code must retain the above copyright notice, +- * this list of conditions and the following disclaimer. +- * +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * +- * * Neither the name Tomasz Sowa nor the names of contributors to this +- * project may be used to endorse or promote products derived +- * from this software without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +- * THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +- +-#ifndef headerfilettmathuint_x86_64 +-#define headerfilettmathuint_x86_64 +- +- +-#ifndef TTMATH_NOASM +-#ifdef TTMATH_PLATFORM64 +- +- +-/*! +- \file ttmathuint_x86_64.h +- \brief template class UInt with assembler code for 64bit x86_64 processors +- +- this file is included at the end of ttmathuint.h +-*/ +- +-#ifndef __GNUC__ +-#include +-#endif +- +- +-namespace ttmath +-{ +- +- #ifndef __GNUC__ +- +- extern "C" +- { +- uint __fastcall ttmath_adc_x64(uint* p1, const uint* p2, uint nSize, uint c); +- uint __fastcall ttmath_addindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue); +- uint __fastcall ttmath_addindexed2_x64(uint* p1, uint nSize, uint nPos, uint nValue1, uint nValue2); +- uint __fastcall ttmath_addvector_x64(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result); +- uint __fastcall ttmath_sbb_x64(uint* p1, const uint* p2, uint nSize, uint c); +- uint __fastcall ttmath_subindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue); +- uint __fastcall ttmath_subvector_x64(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result); +- uint __fastcall ttmath_rcl_x64(uint* p1, uint nSize, uint nLowestBit); +- uint __fastcall ttmath_rcr_x64(uint* p1, uint nSize, uint nLowestBit); +- uint __fastcall ttmath_div_x64(uint* pnValHi, uint* pnValLo, uint nDiv); +- uint __fastcall ttmath_rcl2_x64(uint* p1, uint nSize, uint nBits, uint c); +- uint __fastcall ttmath_rcr2_x64(uint* p1, uint nSize, uint nBits, uint c); +- }; +- #endif +- +- +- /*! +- returning the string represents the currect type of the library +- we have following types: +- asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits) +- asm_gcc_32 - with asm code designed for GCC (32 bits) +- asm_vc_64 - with asm for VC (64 bit) +- asm_gcc_64 - with asm for GCC (64 bit) +- no_asm_32 - pure C++ version (32 bit) - without any asm code +- no_asm_64 - pure C++ version (64 bit) - without any asm code +- */ +- template +- const char * UInt::LibTypeStr() +- { +- #ifndef __GNUC__ +- static const char info[] = "asm_vc_64"; +- #endif +- +- #ifdef __GNUC__ +- static const char info[] = "asm_gcc_64"; +- #endif +- +- return info; +- } +- +- +- /*! +- returning the currect type of the library +- */ +- template +- LibTypeCode UInt::LibType() +- { +- #ifndef __GNUC__ +- LibTypeCode info = asm_vc_64; +- #endif +- +- #ifdef __GNUC__ +- LibTypeCode info = asm_gcc_64; +- #endif +- +- return info; +- } +- +- +- /*! +- * +- * basic mathematic functions +- * +- */ +- +- +- +- /*! +- this method adding ss2 to the this and adding carry if it's defined +- (this = this + ss2 + c) +- +- ***this method is created only on a 64bit platform*** +- +- c must be zero or one (might be a bigger value than 1) +- function returns carry (1) (if it was) +- */ +- template +- uint UInt::Add(const UInt & ss2, uint c) +- { +- uint b = value_size; +- uint * p1 = table; +- const uint * p2 = ss2.table; +- +- // we don't have to use TTMATH_REFERENCE_ASSERT here +- // this algorithm doesn't require it +- +- #ifndef __GNUC__ +- c = ttmath_adc_x64(p1,p2,b,c); +- #endif +- +- #ifdef __GNUC__ +- uint dummy, dummy2; +- +- /* +- this part should be compiled with gcc +- */ +- __asm__ __volatile__( +- +- "xorq %%rdx, %%rdx \n" +- "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 +- +- "1: \n" +- "movq (%%rsi,%%rdx,8), %%rax \n" +- "adcq %%rax, (%%rbx,%%rdx,8) \n" +- +- "incq %%rdx \n" +- "decq %%rcx \n" +- "jnz 1b \n" +- +- "adcq %%rcx, %%rcx \n" +- +- : "=c" (c), "=a" (dummy), "=d" (dummy2) +- : "0" (b), "1" (c), "b" (p1), "S" (p2) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_LOGC("UInt::Add", c) +- +- return c; +- } +- +- +- +- /*! +- this method adds one word (at a specific position) +- and returns a carry (if it was) +- +- ***this method is created only on a 64bit platform*** +- +- +- if we've got (value_size=3): +- table[0] = 10; +- table[1] = 30; +- table[2] = 5; +- and we call: +- AddInt(2,1) +- then it'll be: +- table[0] = 10; +- table[1] = 30 + 2; +- table[2] = 5; +- +- of course if there was a carry from table[2] it would be returned +- */ +- template +- uint UInt::AddInt(uint value, uint index) +- { +- uint b = value_size; +- uint * p1 = table; +- uint c; +- +- TTMATH_ASSERT( index < value_size ) +- +- #ifndef __GNUC__ +- c = ttmath_addindexed_x64(p1,b,index,value); +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy, dummy2; +- +- __asm__ __volatile__( +- +- "subq %%rdx, %%rcx \n" +- +- "1: \n" +- "addq %%rax, (%%rbx,%%rdx,8) \n" +- "jnc 2f \n" +- +- "movq $1, %%rax \n" +- "incq %%rdx \n" +- "decq %%rcx \n" +- "jnz 1b \n" +- +- "2: \n" +- "setc %%al \n" +- "movzx %%al, %%rdx \n" +- +- : "=d" (c), "=a" (dummy), "=c" (dummy2) +- : "0" (index), "1" (value), "2" (b), "b" (p1) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_LOGC("UInt::AddInt", c) +- +- return c; +- } +- +- +- +- /*! +- this method adds only two unsigned words to the existing value +- and these words begin on the 'index' position +- (it's used in the multiplication algorithm 2) +- +- ***this method is created only on a 64bit platform*** +- +- index should be equal or smaller than value_size-2 (index <= value_size-2) +- x1 - lower word, x2 - higher word +- +- for example if we've got value_size equal 4 and: +- table[0] = 3 +- table[1] = 4 +- table[2] = 5 +- table[3] = 6 +- then let +- x1 = 10 +- x2 = 20 +- and +- index = 1 +- +- the result of this method will be: +- table[0] = 3 +- table[1] = 4 + x1 = 14 +- table[2] = 5 + x2 = 25 +- table[3] = 6 +- +- and no carry at the end of table[3] +- +- (of course if there was a carry in table[2](5+20) then +- this carry would be passed to the table[3] etc.) +- */ +- template +- uint UInt::AddTwoInts(uint x2, uint x1, uint index) +- { +- uint b = value_size; +- uint * p1 = table; +- uint c; +- +- TTMATH_ASSERT( index < value_size - 1 ) +- +- #ifndef __GNUC__ +- c = ttmath_addindexed2_x64(p1,b,index,x1,x2); +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy, dummy2; +- +- __asm__ __volatile__( +- +- "subq %%rdx, %%rcx \n" +- +- "addq %%rsi, (%%rbx,%%rdx,8) \n" +- "incq %%rdx \n" +- "decq %%rcx \n" +- +- "1: \n" +- "adcq %%rax, (%%rbx,%%rdx,8) \n" +- "jnc 2f \n" +- +- "mov $0, %%rax \n" +- "incq %%rdx \n" +- "decq %%rcx \n" +- "jnz 1b \n" +- +- "2: \n" +- "setc %%al \n" +- "movzx %%al, %%rax \n" +- +- : "=a" (c), "=c" (dummy), "=d" (dummy2) +- : "0" (x2), "1" (b), "2" (index), "b" (p1), "S" (x1) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_LOGC("UInt::AddTwoInts", c) +- +- return c; +- } +- +- +- +- /*! +- this static method addes one vector to the other +- 'ss1' is larger in size or equal to 'ss2' +- +- ss1 points to the first (larger) vector +- ss2 points to the second vector +- ss1_size - size of the ss1 (and size of the result too) +- ss2_size - size of the ss2 +- result - is the result vector (which has size the same as ss1: ss1_size) +- +- Example: ss1_size is 5, ss2_size is 3 +- ss1: ss2: result (output): +- 5 1 5+1 +- 4 3 4+3 +- 2 7 2+7 +- 6 6 +- 9 9 +- of course the carry is propagated and will be returned from the last item +- (this method is used by the Karatsuba multiplication algorithm) +- */ +- template +- uint UInt::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) +- { +- TTMATH_ASSERT( ss1_size >= ss2_size ) +- +- uint c; +- +- #ifndef __GNUC__ +- c = ttmath_addvector_x64(ss1, ss2, ss1_size, ss2_size, result); +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy1, dummy2, dummy3; +- uint rest = ss1_size - ss2_size; +- +- // this part should be compiled with gcc +- +- __asm__ __volatile__( +- "mov %%rdx, %%r8 \n" +- "xor %%rdx, %%rdx \n" // rdx = 0, cf = 0 +- "1: \n" +- "mov (%%rsi,%%rdx,8), %%rax \n" +- "adc (%%rbx,%%rdx,8), %%rax \n" +- "mov %%rax, (%%rdi,%%rdx,8) \n" +- +- "inc %%rdx \n" +- "dec %%rcx \n" +- "jnz 1b \n" +- +- "adc %%rcx, %%rcx \n" // rcx has the cf state +- +- "or %%r8, %%r8 \n" +- "jz 3f \n" +- +- "xor %%rbx, %%rbx \n" // ebx = 0 +- "neg %%rcx \n" // setting cf from rcx +- "mov %%r8, %%rcx \n" // rcx=rest and is != 0 +- "2: \n" +- "mov (%%rsi, %%rdx, 8), %%rax \n" +- "adc %%rbx, %%rax \n" +- "mov %%rax, (%%rdi, %%rdx, 8) \n" +- +- "inc %%rdx \n" +- "dec %%rcx \n" +- "jnz 2b \n" +- +- "adc %%rcx, %%rcx \n" +- "3: \n" +- +- : "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3) +- : "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result) +- : "%r8", "cc", "memory" ); +- +- #endif +- +- TTMATH_VECTOR_LOGC("UInt::AddVector", c, result, ss1_size) +- +- return c; +- } +- +- +- +- /*! +- this method's subtracting ss2 from the 'this' and subtracting +- carry if it has been defined +- (this = this - ss2 - c) +- +- ***this method is created only on a 64bit platform*** +- +- c must be zero or one (might be a bigger value than 1) +- function returns carry (1) (if it was) +- */ +- template +- uint UInt::Sub(const UInt & ss2, uint c) +- { +- uint b = value_size; +- uint * p1 = table; +- const uint * p2 = ss2.table; +- +- // we don't have to use TTMATH_REFERENCE_ASSERT here +- // this algorithm doesn't require it +- +- #ifndef __GNUC__ +- c = ttmath_sbb_x64(p1,p2,b,c); +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy, dummy2; +- +- __asm__ __volatile__( +- +- "xorq %%rdx, %%rdx \n" +- "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 +- +- "1: \n" +- "movq (%%rsi,%%rdx,8), %%rax \n" +- "sbbq %%rax, (%%rbx,%%rdx,8) \n" +- +- "incq %%rdx \n" +- "decq %%rcx \n" +- "jnz 1b \n" +- +- "adcq %%rcx, %%rcx \n" +- +- : "=c" (c), "=a" (dummy), "=d" (dummy2) +- : "0" (b), "1" (c), "b" (p1), "S" (p2) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_LOGC("UInt::Sub", c) +- +- return c; +- } +- +- +- +- /*! +- this method subtracts one word (at a specific position) +- and returns a carry (if it was) +- +- ***this method is created only on a 64bit platform*** +- +- if we've got (value_size=3): +- table[0] = 10; +- table[1] = 30; +- table[2] = 5; +- and we call: +- SubInt(2,1) +- then it'll be: +- table[0] = 10; +- table[1] = 30 - 2; +- table[2] = 5; +- +- of course if there was a carry from table[2] it would be returned +- */ +- template +- uint UInt::SubInt(uint value, uint index) +- { +- uint b = value_size; +- uint * p1 = table; +- uint c; +- +- TTMATH_ASSERT( index < value_size ) +- +- #ifndef __GNUC__ +- c = ttmath_subindexed_x64(p1,b,index,value); +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy, dummy2; +- +- __asm__ __volatile__( +- +- "subq %%rdx, %%rcx \n" +- +- "1: \n" +- "subq %%rax, (%%rbx,%%rdx,8) \n" +- "jnc 2f \n" +- +- "movq $1, %%rax \n" +- "incq %%rdx \n" +- "decq %%rcx \n" +- "jnz 1b \n" +- +- "2: \n" +- "setc %%al \n" +- "movzx %%al, %%rdx \n" +- +- : "=d" (c), "=a" (dummy), "=c" (dummy2) +- : "0" (index), "1" (value), "2" (b), "b" (p1) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_LOGC("UInt::SubInt", c) +- +- return c; +- } +- +- +- /*! +- this static method subtractes one vector from the other +- 'ss1' is larger in size or equal to 'ss2' +- +- ss1 points to the first (larger) vector +- ss2 points to the second vector +- ss1_size - size of the ss1 (and size of the result too) +- ss2_size - size of the ss2 +- result - is the result vector (which has size the same as ss1: ss1_size) +- +- Example: ss1_size is 5, ss2_size is 3 +- ss1: ss2: result (output): +- 5 1 5-1 +- 4 3 4-3 +- 2 7 2-7 +- 6 6-1 (the borrow from previous item) +- 9 9 +- return (carry): 0 +- of course the carry (borrow) is propagated and will be returned from the last item +- (this method is used by the Karatsuba multiplication algorithm) +- */ +- template +- uint UInt::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) +- { +- TTMATH_ASSERT( ss1_size >= ss2_size ) +- +- uint c; +- +- #ifndef __GNUC__ +- c = ttmath_subvector_x64(ss1, ss2, ss1_size, ss2_size, result); +- #endif +- +- +- #ifdef __GNUC__ +- +- // the asm code is nearly the same as in AddVector +- // only two instructions 'adc' are changed to 'sbb' +- +- uint dummy1, dummy2, dummy3; +- uint rest = ss1_size - ss2_size; +- +- __asm__ __volatile__( +- "mov %%rdx, %%r8 \n" +- "xor %%rdx, %%rdx \n" // rdx = 0, cf = 0 +- "1: \n" +- "mov (%%rsi,%%rdx,8), %%rax \n" +- "sbb (%%rbx,%%rdx,8), %%rax \n" +- "mov %%rax, (%%rdi,%%rdx,8) \n" +- +- "inc %%rdx \n" +- "dec %%rcx \n" +- "jnz 1b \n" +- +- "adc %%rcx, %%rcx \n" // rcx has the cf state +- +- "or %%r8, %%r8 \n" +- "jz 3f \n" +- +- "xor %%rbx, %%rbx \n" // ebx = 0 +- "neg %%rcx \n" // setting cf from rcx +- "mov %%r8, %%rcx \n" // rcx=rest and is != 0 +- "2: \n" +- "mov (%%rsi, %%rdx, 8), %%rax \n" +- "sbb %%rbx, %%rax \n" +- "mov %%rax, (%%rdi, %%rdx, 8) \n" +- +- "inc %%rdx \n" +- "dec %%rcx \n" +- "jnz 2b \n" +- +- "adc %%rcx, %%rcx \n" +- "3: \n" +- +- : "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3) +- : "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result) +- : "%r8", "cc", "memory" ); +- +- #endif +- +- TTMATH_VECTOR_LOGC("UInt::SubVector", c, result, ss1_size) +- +- return c; +- } +- +- +- /*! +- this method moves all bits into the left hand side +- return value <- this <- c +- +- the lowest *bit* will be held the 'c' and +- the state of one additional bit (on the left hand side) +- will be returned +- +- for example: +- let this is 001010000 +- after Rcl2_one(1) there'll be 010100001 and Rcl2_one returns 0 +- +- ***this method is created only on a 64bit platform*** +- */ +- template +- uint UInt::Rcl2_one(uint c) +- { +- sint b = value_size; +- uint * p1 = table; +- +- +- #ifndef __GNUC__ +- c = ttmath_rcl_x64(p1,b,c); +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy, dummy2; +- +- __asm__ __volatile__( +- +- "xorq %%rdx, %%rdx \n" // rdx=0 +- "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 +- +- "1: \n" +- "rclq $1, (%%rbx, %%rdx, 8) \n" +- +- "incq %%rdx \n" +- "decq %%rcx \n" +- "jnz 1b \n" +- +- "adcq %%rcx, %%rcx \n" +- +- : "=c" (c), "=a" (dummy), "=d" (dummy2) +- : "0" (b), "1" (c), "b" (p1) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_LOGC("UInt::Rcl2_one", c) +- +- return c; +- } +- +- +- /*! +- this method moves all bits into the right hand side +- c -> this -> return value +- +- the highest *bit* will be held the 'c' and +- the state of one additional bit (on the right hand side) +- will be returned +- +- for example: +- let this is 000000010 +- after Rcr2_one(1) there'll be 100000001 and Rcr2_one returns 0 +- +- ***this method is created only on a 64bit platform*** +- */ +- template +- uint UInt::Rcr2_one(uint c) +- { +- sint b = value_size; +- uint * p1 = table; +- +- +- #ifndef __GNUC__ +- c = ttmath_rcr_x64(p1,b,c); +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy; +- +- __asm__ __volatile__( +- +- "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 +- +- "1: \n" +- "rcrq $1, -8(%%rbx, %%rcx, 8) \n" +- +- "decq %%rcx \n" +- "jnz 1b \n" +- +- "adcq %%rcx, %%rcx \n" +- +- : "=c" (c), "=a" (dummy) +- : "0" (b), "1" (c), "b" (p1) +- : "cc", "memory" ); +- +- #endif +- +- TTMATH_LOGC("UInt::Rcr2_one", c) +- +- return c; +- } +- +- +- +- /*! +- this method moves all bits into the left hand side +- return value <- this <- c +- +- the lowest *bits* will be held the 'c' and +- the state of one additional bit (on the left hand side) +- will be returned +- +- for example: +- let this is 001010000 +- after Rcl2(3, 1) there'll be 010000111 and Rcl2 returns 1 +- +- ***this method is created only on a 64bit platform*** +- */ +- template +- uint UInt::Rcl2(uint bits, uint c) +- { +- TTMATH_ASSERT( bits>0 && bits this -> return value +- +- the highest *bits* will be held the 'c' and +- the state of one additional bit (on the right hand side) +- will be returned +- +- for example: +- let this is 000000010 +- after Rcr2(2, 1) there'll be 110000000 and Rcr2 returns 1 +- +- ***this method is created only on a 64bit platform*** +- */ +- template +- uint UInt::Rcr2(uint bits, uint c) +- { +- TTMATH_ASSERT( bits>0 && bits +- sint UInt::FindLeadingBitInWord(uint x) +- { +- sint result; +- +- +- #ifndef __GNUC__ +- +- unsigned long nIndex = 0; +- +- if( _BitScanReverse64(&nIndex,x) == 0 ) +- result = -1; +- else +- result = nIndex; +- +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy; +- +- __asm__ ( +- +- "movq $-1, %1 \n" +- "bsrq %2, %0 \n" +- "cmovz %1, %0 \n" +- +- : "=r" (result), "=&r" (dummy) +- : "r" (x) +- : "cc" ); +- +- #endif +- +- +- return result; +- } +- +- +- /* +- this method returns the number of the highest set bit in one 64-bit word +- if the 'x' is zero this method returns '-1' +- +- ***this method is created only on a 64bit platform*** +- */ +- template +- sint UInt::FindLowestBitInWord(uint x) +- { +- sint result; +- +- +- #ifndef __GNUC__ +- +- unsigned long nIndex = 0; +- +- if( _BitScanForward64(&nIndex,x) == 0 ) +- result = -1; +- else +- result = nIndex; +- +- #endif +- +- +- #ifdef __GNUC__ +- uint dummy; +- +- __asm__ ( +- +- "movq $-1, %1 \n" +- "bsfq %2, %0 \n" +- "cmovz %1, %0 \n" +- +- : "=r" (result), "=&r" (dummy) +- : "r" (x) +- : "cc" ); +- +- #endif +- +- +- return result; +- } +- +- +- /*! +- this method sets a special bit in the 'value' +- and returns the last state of the bit (zero or one) +- +- ***this method is created only on a 64bit platform*** +- +- bit is from <0,63> +- +- e.g. +- uint x = 100; +- uint bit = SetBitInWord(x, 3); +- now: x = 108 and bit = 0 +- */ +- template +- uint UInt::SetBitInWord(uint & value, uint bit) +- { +- TTMATH_ASSERT( bit < TTMATH_BITS_PER_UINT ) +- +- uint old_bit; +- uint v = value; +- +- +- #ifndef __GNUC__ +- old_bit = _bittestandset64((__int64*)&value,bit) != 0; +- #endif +- +- +- #ifdef __GNUC__ +- +- __asm__ ( +- +- "btsq %%rbx, %%rax \n" +- "setc %%bl \n" +- "movzx %%bl, %%rbx \n" +- +- : "=a" (v), "=b" (old_bit) +- : "0" (v), "1" (bit) +- : "cc" ); +- +- #endif +- +- value = v; +- +- return old_bit; +- } +- +- +- /*! +- * +- * Multiplication +- * +- * +- */ +- +- +- /*! +- multiplication: result_high:result_low = a * b +- result_high - higher word of the result +- result_low - lower word of the result +- +- this methos never returns a carry +- this method is used in the second version of the multiplication algorithms +- +- ***this method is created only on a 64bit platform*** +- */ +- template +- void UInt::MulTwoWords(uint a, uint b, uint * result_high, uint * result_low) +- { +- /* +- we must use these temporary variables in order to inform the compilator +- that value pointed with result1 and result2 has changed +- +- this has no effect in visual studio but it's usefull when +- using gcc and options like -O +- */ +- uint result1_; +- uint result2_; +- +- +- #ifndef __GNUC__ +- result1_ = _umul128(a,b,&result2_); +- #endif +- +- +- #ifdef __GNUC__ +- +- __asm__ ( +- +- "mulq %%rdx \n" +- +- : "=a" (result1_), "=d" (result2_) +- : "0" (a), "1" (b) +- : "cc" ); +- +- #endif +- +- +- *result_low = result1_; +- *result_high = result2_; +- } +- +- +- +- +- /*! +- * +- * Division +- * +- * +- */ +- +- +- /*! +- this method calculates 64bits word a:b / 32bits c (a higher, b lower word) +- r = a:b / c and rest - remainder +- +- ***this method is created only on a 64bit platform*** +- +- * +- * WARNING: +- * if r (one word) is too small for the result or c is equal zero +- * there'll be a hardware interruption (0) +- * and probably the end of your program +- * +- */ +- template +- void UInt::DivTwoWords(uint a,uint b, uint c, uint * r, uint * rest) +- { +- uint r_; +- uint rest_; +- /* +- these variables have similar meaning like those in +- the multiplication algorithm MulTwoWords +- */ +- +- TTMATH_ASSERT( c != 0 ) +- +- +- #ifndef __GNUC__ +- +- ttmath_div_x64(&a,&b,c); +- r_ = a; +- rest_ = b; +- +- #endif +- +- +- #ifdef __GNUC__ +- +- __asm__ ( +- +- "divq %%rcx \n" +- +- : "=a" (r_), "=d" (rest_) +- : "d" (a), "a" (b), "c" (c) +- : "cc" ); +- +- #endif +- +- +- *r = r_; +- *rest = rest_; +- } +- +-} //namespace +- +- +-#endif //ifdef TTMATH_PLATFORM64 +-#endif //ifndef TTMATH_NOASM +-#endif +- +- +diff --git a/extern/ttmath/ttmathuint_x86_64_msvc.asm b/extern/ttmath/ttmathuint_x86_64_msvc.asm +deleted file mode 100644 +index aae113f636..0000000000 +--- a/extern/ttmath/ttmathuint_x86_64_msvc.asm ++++ /dev/null +@@ -1,548 +0,0 @@ +-; +-; This file is a part of TTMath Bignum Library +-; and is distributed under the (new) BSD licence. +-; Author: Christian Kaiser +-; +- +-; +-; Copyright (c) 2009, Christian Kaiser +-; All rights reserved. +-; +-; Redistribution and use in source and binary forms, with or without +-; modification, are permitted provided that the following conditions are met: +-; +-; * Redistributions of source code must retain the above copyright notice, +-; this list of conditions and the following disclaimer. +-; +-; * Redistributions in binary form must reproduce the above copyright +-; notice, this list of conditions and the following disclaimer in the +-; documentation and/or other materials provided with the distribution. +-; +-; * Neither the name Christian Kaiser nor the names of contributors to this +-; project may be used to endorse or promote products derived +-; from this software without specific prior written permission. +-; +-; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +-; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +-; ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +-; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +-; THE POSSIBILITY OF SUCH DAMAGE. +-; +- +-; +-; compile with debug info: ml64.exe /c /Zd /Zi ttmathuint_x86_64_msvc.asm +-; compile without debug info: ml64.exe /c ttmathuint_x86_64_msvc.asm +-; this creates ttmathuint_x86_64_msvc.obj file which can be linked with your program +-; +- +-PUBLIC ttmath_adc_x64 +-PUBLIC ttmath_addindexed_x64 +-PUBLIC ttmath_addindexed2_x64 +-PUBLIC ttmath_addvector_x64 +- +-PUBLIC ttmath_sbb_x64 +-PUBLIC ttmath_subindexed_x64 +-PUBLIC ttmath_subvector_x64 +- +-PUBLIC ttmath_rcl_x64 +-PUBLIC ttmath_rcr_x64 +- +-PUBLIC ttmath_rcl2_x64 +-PUBLIC ttmath_rcr2_x64 +- +-PUBLIC ttmath_div_x64 +- +-; +-; Microsoft x86_64 convention: http://msdn.microsoft.com/en-us/library/9b372w95.aspx +-; +-; "rax, rcx, rdx, r8-r11 are volatile." +-; "rbx, rbp, rdi, rsi, r12-r15 are nonvolatile." +-; +- +- +-.CODE +- +- +- ALIGN 8 +- +-;---------------------------------------- +- +-ttmath_adc_x64 PROC +- ; rcx = p1 +- ; rdx = p2 +- ; r8 = nSize +- ; r9 = nCarry +- +- xor rax, rax +- xor r11, r11 +- sub rax, r9 ; sets CARRY if r9 != 0 +- +- ALIGN 16 +- loop1: +- mov rax,qword ptr [rdx + r11 * 8] +- adc qword ptr [rcx + r11 * 8], rax +- lea r11, [r11+1] +- dec r8 +- jnz loop1 +- +- setc al +- movzx rax, al +- +- ret +- +-ttmath_adc_x64 ENDP +- +-;---------------------------------------- +- +- ALIGN 8 +- +-;---------------------------------------- +- +-ttmath_addindexed_x64 PROC +- +- ; rcx = p1 +- ; rdx = nSize +- ; r8 = nPos +- ; r9 = nValue +- +- xor rax, rax ; rax = result +- sub rdx, r8 ; rdx = remaining count of uints +- +- add qword ptr [rcx + r8 * 8], r9 +- jc next1 +- +- ret +- +-next1: +- mov r9, 1 +- +- ALIGN 16 +-loop1: +- dec rdx +- jz done_with_cy +- lea r8, [r8+1] +- add qword ptr [rcx + r8 * 8], r9 +- jc loop1 +- +- ret +- +-done_with_cy: +- lea rax, [rax+1] ; rax = 1 +- +- ret +- +-ttmath_addindexed_x64 ENDP +- +-;---------------------------------------- +- +- ALIGN 8 +- +-;---------------------------------------- +- +-ttmath_addindexed2_x64 PROC +- +- ; rcx = p1 (pointer) +- ; rdx = b (value size) +- ; r8 = nPos +- ; r9 = nValue1 +- ; [rsp+0x28] = nValue2 +- +- xor rax, rax ; return value +- mov r11, rcx ; table +- sub rdx, r8 ; rdx = remaining count of uints +- mov r10, [rsp+028h] ; r10 = nValue2 +- +- add qword ptr [r11 + r8 * 8], r9 +- lea r8, [r8+1] +- lea rdx, [rdx-1] +- adc qword ptr [r11 + r8 * 8], r10 +- jc next +- ret +- +- ALIGN 16 +-loop1: +- lea r8, [r8+1] +- add qword ptr [r11 + r8 * 8], 1 +- jc next +- ret +- +-next: +- dec rdx ; does not modify CY too... +- jnz loop1 +- lea rax, [rax+1] +- ret +- +-ttmath_addindexed2_x64 ENDP +- +- +- +-;---------------------------------------- +- +- ALIGN 8 +- +-;---------------------------------------- +- +- +-ttmath_addvector_x64 PROC +- ; rcx = ss1 +- ; rdx = ss2 +- ; r8 = ss1_size +- ; r9 = ss2_size +- ; [rsp+0x28] = result +- +- mov r10, [rsp+028h] +- sub r8, r9 +- xor r11, r11 ; r11=0, cf=0 +- +- ALIGN 16 +- loop1: +- mov rax, qword ptr [rcx + r11 * 8] +- adc rax, qword ptr [rdx + r11 * 8] +- mov qword ptr [r10 + r11 * 8], rax +- inc r11 +- dec r9 +- jnz loop1 +- +- adc r9, r9 ; r9 has the cf state +- +- or r8, r8 +- jz done +- +- neg r9 ; setting cf from r9 +- mov r9, 0 ; don't use xor here (cf is used) +- loop2: +- mov rax, qword ptr [rcx + r11 * 8] +- adc rax, r9 +- mov qword ptr [r10 + r11 * 8], rax +- inc r11 +- dec r8 +- jnz loop2 +- +- adc r8, r8 +- mov rax, r8 +- +- ret +- +-done: +- mov rax, r9 +- ret +- +-ttmath_addvector_x64 ENDP +- +- +-;---------------------------------------- +- +- ALIGN 8 +- +-;---------------------------------------- +- +-ttmath_sbb_x64 PROC +- +- ; rcx = p1 +- ; rdx = p2 +- ; r8 = nCount +- ; r9 = nCarry +- +- xor rax, rax +- xor r11, r11 +- sub rax, r9 ; sets CARRY if r9 != 0 +- +- ALIGN 16 +- loop1: +- mov rax,qword ptr [rdx + r11 * 8] +- sbb qword ptr [rcx + r11 * 8], rax +- lea r11, [r11+1] +- dec r8 +- jnz loop1 +- +- setc al +- movzx rax, al +- +- ret +- +-ttmath_sbb_x64 ENDP +- +-;---------------------------------------- +- +- ALIGN 8 +- +-;---------------------------------------- +- +-ttmath_subindexed_x64 PROC +- ; rcx = p1 +- ; rdx = nSize +- ; r8 = nPos +- ; r9 = nValue +- +- sub rdx, r8 ; rdx = remaining count of uints +- +- ALIGN 16 +-loop1: +- sub qword ptr [rcx + r8 * 8], r9 +- jnc done +- +- lea r8, [r8+1] +- mov r9, 1 +- dec rdx +- jnz loop1 +- +- mov rax, 1 +- ret +- +-done: +- xor rax, rax +- ret +- +-ttmath_subindexed_x64 ENDP +- +- +- +-;---------------------------------------- +- +- ALIGN 8 +- +-;---------------------------------------- +- +-; the same asm code as in addvector_x64 only two instructions 'adc' changed to 'sbb' +- +-ttmath_subvector_x64 PROC +- ; rcx = ss1 +- ; rdx = ss2 +- ; r8 = ss1_size +- ; r9 = ss2_size +- ; [rsp+0x28] = result +- +- mov r10, [rsp+028h] +- sub r8, r9 +- xor r11, r11 ; r11=0, cf=0 +- +- ALIGN 16 +- loop1: +- mov rax, qword ptr [rcx + r11 * 8] +- sbb rax, qword ptr [rdx + r11 * 8] +- mov qword ptr [r10 + r11 * 8], rax +- inc r11 +- dec r9 +- jnz loop1 +- +- adc r9, r9 ; r9 has the cf state +- +- or r8, r8 +- jz done +- +- neg r9 ; setting cf from r9 +- mov r9, 0 ; don't use xor here (cf is used) +- loop2: +- mov rax, qword ptr [rcx + r11 * 8] +- sbb rax, r9 +- mov qword ptr [r10 + r11 * 8], rax +- inc r11 +- dec r8 +- jnz loop2 +- +- adc r8, r8 +- mov rax, r8 +- +- ret +- +-done: +- mov rax, r9 +- ret +- +-ttmath_subvector_x64 ENDP +- +- +- +- +-;---------------------------------------- +- +- ALIGN 8 +- +-;---------------------------------------- +- +-ttmath_rcl_x64 PROC +- ; rcx = p1 +- ; rdx = b +- ; r8 = nLowestBit +- +- mov r11, rcx ; table +- xor r10, r10 +- neg r8 ; CY set if r8 <> 0 +- +- ALIGN 16 +-loop1: +- rcl qword ptr [r11 + r10 * 8], 1 +- lea r10, [r10+1] +- dec rdx +- jnz loop1 +- +- setc al +- movzx rax, al +- +- ret +- +-ttmath_rcl_x64 ENDP +- +-;---------------------------------------- +- +- ALIGN 8 +- +-;---------------------------------------- +- +-ttmath_rcr_x64 PROC +- ; rcx = p1 +- ; rdx = nSize +- ; r8 = nLowestBit +- +- xor r10, r10 +- neg r8 ; CY set if r8 <> 0 +- +- ALIGN 16 +-loop1: +- rcr qword ptr -8[rcx + rdx * 8], 1 +- dec rdx +- jnz loop1 +- +- setc al +- movzx rax, al +- +- ret +- +-ttmath_rcr_x64 ENDP +- +-;---------------------------------------- +- +- ALIGN 8 +- +-;---------------------------------------- +- +-ttmath_div_x64 PROC +- +- ; rcx = &Hi +- ; rdx = &Lo +- ; r8 = nDiv +- +- mov r11, rcx +- mov r10, rdx +- +- mov rdx, qword ptr [r11] +- mov rax, qword ptr [r10] +- div r8 +- mov qword ptr [r10], rdx ; remainder +- mov qword ptr [r11], rax ; value +- +- ret +- +-ttmath_div_x64 ENDP +- +-;---------------------------------------- +- +- ALIGN 8 +- +-;---------------------------------------- +- +-ttmath_rcl2_x64 PROC +- ; rcx = p1 +- ; rdx = nSize +- ; r8 = bits +- ; r9 = c +- +- push rbx +- +- mov r10, rcx ; r10 = p1 +- xor rax, rax +- +- mov rcx, 64 +- sub rcx, r8 +- +- mov r11, -1 +- shr r11, cl ; r11 = mask +- +- mov rcx, r8 ; rcx = count of bits +- +- mov rbx, rax ; rbx = old value = 0 +- or r9, r9 +- cmovnz rbx, r11 ; if (c) then old value = mask +- +- mov r9, rax ; r9 = index (0..nSize-1) +- +- ALIGN 16 +-loop1: +- rol qword ptr [r10+r9*8], cl +- mov rax, qword ptr [r10+r9*8] +- and rax, r11 +- xor qword ptr [r10+r9*8], rax +- or qword ptr [r10+r9*8], rbx +- mov rbx, rax +- +- lea r9, [r9+1] +- dec rdx +- +- jnz loop1 +- +- and rax, 1 +- pop rbx +- ret +- +-ttmath_rcl2_x64 ENDP +- +-;---------------------------------------- +- +- ALIGN 8 +- +-;---------------------------------------- +- +-ttmath_rcr2_x64 PROC +- ; rcx = p1 +- ; rdx = nSize +- ; r8 = bits +- ; r9 = c +- +- push rbx +- mov r10, rcx ; r10 = p1 +- xor rax, rax +- +- mov rcx, 64 +- sub rcx, r8 +- +- mov r11, -1 +- shl r11, cl ; r11 = mask +- +- mov rcx, r8 ; rcx = count of bits +- +- mov rbx, rax ; rbx = old value = 0 +- or r9, r9 +- cmovnz rbx, r11 ; if (c) then old value = mask +- +- mov r9, rdx ; r9 = index (0..nSize-1) +- lea r9, [r9-1] +- +- ALIGN 16 +-loop1: +- ror qword ptr [r10+r9*8], cl +- mov rax, qword ptr [r10+r9*8] +- and rax, r11 +- xor qword ptr [r10+r9*8], rax +- or qword ptr [r10+r9*8], rbx +- mov rbx, rax +- +- lea r9, [r9-1] +- dec rdx +- +- jnz loop1 +- +- rol rax, 1 +- and rax, 1 +- pop rbx +- +- ret +- +-ttmath_rcr2_x64 ENDP +- +-END +diff --git a/src/common/Int128.cpp b/src/common/Int128.cpp +index d3158dddeb..88414b041d 100644 +--- a/src/common/Int128.cpp ++++ b/src/common/Int128.cpp +@@ -56,60 +56,18 @@ const CInt128 minus1(-1); + + namespace Firebird { + +-Int128 Int128::set(SLONG value, int scale) +-{ +- v = ttmath::sint(value); +- setScale(scale); +- return *this; +-} +- +-Int128 Int128::set(SINT64 value, int scale) +-{ +-#ifdef TTMATH_PLATFORM32 +- v = ttmath::slint(value); +-#else +- v = ttmath::sint(value); +-#endif +- setScale(scale); +- return *this; +-} +- + Int128 Int128::set(const char* value) + { + // This is simplified method - it does not perform all what's needed for CVT_decompose +- v.FromString(value); +- return *this; +-} +- +-Int128 Int128::set(double value) +-{ +- bool sgn = false; +- if (value < 0.0) +- { +- value = -value; +- sgn = true; +- } +- +- double parts[4]; +- for (int i = 0; i < 4; ++i) ++ for (v = 0; ; ++value) + { +- parts[i] = value; +- value /= p2_32; +- } +- fb_assert(value < 1.0); ++ if (*value < '0' or *value > '9') ++ break; + +- unsigned dwords[4]; +- value = 0.0; +- for (int i = 4; i--;) +- { +- dwords[i] = (parts[i] - value); +- value += p2_32 * dwords[i]; ++ v *= 10; ++ v += (*value - '0'); + } + +- setTable32(dwords); +- if (sgn) +- v.ChangeSign(); +- + return *this; + } + +@@ -122,14 +80,14 @@ Int128 Int128::set(DecimalStatus decSt, Decimal128 value) + value.getBcd(&bcd); + fb_assert(bcd.exp == 0); + +- v.SetZero(); ++ v = 0; + for (unsigned b = 0; b < sizeof(bcd.bcd); ++b) + { +- v.MulInt(10); +- v.AddInt(bcd.bcd[b]); ++ v *= 10; ++ v += bcd.bcd[b]; + } + if (bcd.sign < 0) +- v.ChangeSign(); ++ v = -v; + + return *this; + } +@@ -138,9 +96,13 @@ void Int128::setScale(int scale) + { + if (scale > 0) + { +- ttmath::sint rem = 0; ++ int rem = 0; + while (scale--) +- v.DivInt(10, scale == 0 ? &rem : nullptr); ++ { ++ if (scale == 0) ++ rem = int(v % 10); ++ v /= 10; ++ } + + if (rem > 4) + v++; +@@ -152,21 +114,11 @@ void Int128::setScale(int scale) + while (scale++) { + if (v > i128limit.v || v < -i128limit.v) + (Arg::Gds(isc_arith_except) << Arg::Gds(isc_numeric_out_of_range)).raise(); +- v.MulInt(10); ++ v *= 10; + } + } + } + +-int Int128::toInteger(int scale) const +-{ +- Int128 tmp(*this); +- tmp.setScale(scale); +- int rc; +- if (tmp.v.ToInt(rc)) +- overflow(); +- return rc; +-} +- + void Int128::toString(int scale, unsigned length, char* to) const + { + string buffer; +@@ -181,10 +133,22 @@ void Int128::toString(int scale, unsigned length, char* to) const + + void Int128::toString(int scale, string& to) const + { +- v.ToStringBase(to); +- bool sgn = to[0] == '-'; ++ to.erase(); ++ absl::int128 vv = v; ++ ++ bool sgn = (vv < 0); + if (sgn) +- to.erase(0, 1); ++ vv = -vv; ++ ++ while (vv > 0) ++ { ++ int dig = int(vv % 10); ++ to.insert(string::size_type(0), string::size_type(1), char(dig + '0')); ++ vv /= 10; ++ } ++ ++ if (to.isEmpty()) ++ to = "0"; + + if (scale) + { +@@ -220,78 +184,23 @@ void Int128::toString(int scale, string& to) const + to.insert(0, "-"); + } + +-SINT64 Int128::toInt64(int scale) const +-{ +- Int128 tmp(*this); +- tmp.setScale(scale); +- if (tmp.v < i64min.v || tmp.v > i64max.v) +- overflow(); +- +- unsigned dwords[4]; +- tmp.getTable32(dwords); +- SINT64 rc = int(dwords[1]); +- rc <<= 32; +- rc += dwords[0]; +- +- return rc; +-} +- +-double Int128::toDouble() const +-{ +- unsigned dwords[4]; +- getTable32(dwords); +- double rc = int(dwords[3]); +- for (int i = 3; i--;) +- { +- rc *= p2_32; +- rc += dwords[i]; +- } +- +- return rc; +-} +- +-int Int128::compare(Int128 tgt) const +-{ +- return v < tgt.v ? -1 : v > tgt.v ? 1 : 0; +-} +- + Int128 Int128::abs() const + { +- Int128 rc(*this); +- if (rc.v.Abs()) ++ if (compare(MIN_Int128) == 0) + overflow(); +- return rc; +-} + +-Int128 Int128::neg() const +-{ +- Int128 rc(*this); +- if (rc.v.ChangeSign()) +- overflow(); +- return rc; +-} +- +-Int128 Int128::add(Int128 op2) const +-{ +- Int128 rc(*this); +- if (rc.v.Add(op2.v)) +- overflow(); ++ Int128 rc; ++ rc.v = v < 0 ? -v : v; + return rc; + } + +-Int128 Int128::sub(Int128 op2) const ++Int128 Int128::neg() const + { +- Int128 rc(*this); +- if (rc.v.Sub(op2.v)) ++ if (compare(MIN_Int128) == 0) + overflow(); +- return rc; +-} + +-Int128 Int128::mul(Int128 op2) const +-{ +- Int128 rc(*this); +- if (rc.v.Mul(op2.v)) +- overflow(); ++ Int128 rc; ++ rc.v = -v; + return rc; + } + +@@ -300,210 +209,37 @@ Int128 Int128::div(Int128 op2, int scale) const + if (compare(MIN_Int128) == 0 && op2.compare(minus1) == 0) + Arg::Gds(isc_exception_integer_overflow).raise(); + ++ if (op2.v == 0) ++ zerodivide(); ++ + static const CInt128 MIN_BY10(MIN_Int128 / 10); + static const CInt128 MAX_BY10(MAX_Int128 / 10); + + // Scale op1 by as many of the needed powers of 10 as possible without an overflow. +- CInt128 op1(*this); ++ Int128 op1(*this); + int sign1 = op1.sign(); + while ((scale < 0) && (sign1 >= 0 ? op1.compare(MAX_BY10) <= 0 : op1.compare(MIN_BY10) >= 0)) + { +- op1 *= 10; ++ op1.v *= 10; + ++scale; + } + + // Scale op2 shifting it to the right as long as only zeroes are thrown away. +- CInt128 tmp(op2); + while (scale < 0) + { +- ttmath::sint rem = 0; +- tmp.v.DivInt(10, &rem); ++ int rem = int(v % 10); + if (rem) + break; +- op2 = tmp; ++ op2.v /= 10; + ++scale; + } + +- if (op1.v.Div(op2.v)) +- zerodivide(); ++ op1.v /= op2.v; + + op1.setScale(scale); + return op1; + } + +-Int128 Int128::mod(Int128 op2) const +-{ +- Int128 tmp(*this); +- Int128 rc; +- if (tmp.v.Div(op2.v, rc.v)) +- zerodivide(); +- return rc; +-} +- +-int Int128::sign() const +-{ +- return v.IsSign() ? -1 : v.IsZero() ? 0 : 1; +-} +- +-UCHAR* Int128::getBytes() +-{ +- return (UCHAR*)(v.table); +-} +- +-void Int128::getTable32(unsigned* dwords) const +-{ +- static_assert((sizeof(v.table[0]) == 4) || (sizeof(v.table[0]) == 8), +- "Unsupported size of integer in ttmath"); +- +- if (sizeof(v.table[0]) == 4) +- { +- for (int i = 0; i < 4; ++i) +- dwords[i] = v.table[i]; +- } +- else if (sizeof(v.table[0]) == 8) +- { +- for (int i = 0; i < 2; ++i) +- { +- dwords[i * 2] = v.table[i] & 0xFFFFFFFF; +- dwords[i * 2 + 1] = (v.table[i] >> 32) & 0xFFFFFFFF; +- } +- } +-} +- +-void Int128::setTable32(const unsigned* dwords) +-{ +- static_assert((sizeof(v.table[0]) == 4) || (sizeof(v.table[0]) == 8), +- "Unsupported size of integer in ttmath"); +- +- if (sizeof(v.table[0]) == 4) +- { +- for (int i = 0; i < 4; ++i) +- v.table[i] = dwords[i]; +- } +- else if (sizeof(v.table[0]) == 8) +- { +- for (int i = 0; i < 2; ++i) +- { +- v.table[i] = dwords[i * 2 + 1]; +- v.table[i] <<= 32; +- v.table[i] += dwords[i * 2]; +- } +- } +-} +- +-Int128 Int128::operator&=(FB_UINT64 mask) +-{ +- v.table[0] &= mask; +- unsigned i = 1; +- if (sizeof(v.table[0]) == 4) +- { +- i = 2; +- v.table[1] &= (mask >> 32); +- } +- +- for (; i < FB_NELEM(v.table); ++i) +- v.table[i] = 0; +- return *this; +-} +- +-Int128 Int128::operator&=(ULONG mask) +-{ +- v.table[0] &= mask; +- +- for (unsigned i = 1; i < FB_NELEM(v.table); ++i) +- v.table[i] = 0; +- return *this; +-} +- +-Int128 Int128::operator/(unsigned value) const +-{ +- Int128 rc(*this); +- rc.v.DivInt(value); +- return rc; +-} +- +-Int128 Int128::operator<<(int value) const +-{ +- Int128 rc(*this); +- rc.v <<= value; +- return rc; +-} +- +-Int128 Int128::operator>>(int value) const +-{ +- Int128 rc(*this); +- rc.v >>= value; +- return rc; +-} +- +-Int128 Int128::operator&=(Int128 value) +-{ +- v &= value.v; +- return *this; +-} +- +-Int128 Int128::operator|=(Int128 value) +-{ +- v |= value.v; +- return *this; +-} +- +-Int128 Int128::operator^=(Int128 value) +-{ +- v ^= value.v; +- return *this; +-} +- +-Int128 Int128::operator~() const +-{ +- Int128 rc(*this); +- rc.v.BitNot(); +- return rc; +-} +- +-Int128 Int128::operator-() const +-{ +- return neg(); +-} +- +-Int128 Int128::operator+=(unsigned value) +-{ +- v.AddInt(value); +- return *this; +-} +- +-Int128 Int128::operator-=(unsigned value) +-{ +- v.SubInt(value); +- return *this; +-} +- +-Int128 Int128::operator*=(unsigned value) +-{ +- v.MulInt(value); +- return *this; +-} +- +-bool Int128::operator>(Int128 value) const +-{ +- return v > value.v; +-} +- +-bool Int128::operator>=(Int128 value) const +-{ +- return v >= value.v; +-} +- +-bool Int128::operator==(Int128 value) const +-{ +- return v == value.v; +-} +- +-bool Int128::operator!=(Int128 value) const +-{ +- return v != value.v; +-} +- + void Int128::zerodivide() + { + (Arg::Gds(isc_arith_except) << Arg::Gds(isc_exception_integer_divide_by_zero)).raise(); +@@ -533,10 +269,10 @@ CInt128::CInt128(minmax mm) + switch(mm) + { + case MkMax: +- v.SetMax(); ++ v = absl::Int128Max(); + break; + case MkMin: +- v.SetMin(); ++ v = absl::Int128Min(); + break; + } + } +diff --git a/src/common/Int128.h b/src/common/Int128.h +index 5fde931ff9..432023d176 100644 +--- a/src/common/Int128.h ++++ b/src/common/Int128.h +@@ -36,7 +36,7 @@ + + #include "classes/fb_string.h" + +-#include "../../extern/ttmath/ttmath.h" ++#include "absl/numeric/int128.h" + + namespace Firebird { + +@@ -53,10 +53,29 @@ public: + return set(SLONG(value), scale); + } + #endif +- Int128 set(SLONG value, int scale); +- Int128 set(SINT64 value, int scale); +- Int128 set(double value); ++ ++ Int128 set(SLONG value, int scale) ++ { ++ v = value; ++ setScale(scale); ++ return *this; ++ } ++ ++ Int128 set(SINT64 value, int scale) ++ { ++ v = value; ++ setScale(scale); ++ return *this; ++ } ++ ++ Int128 set(double value) ++ { ++ v = absl::int128(value); ++ return *this; ++ } ++ + Int128 set(DecimalStatus decSt, Decimal128 value); ++ + Int128 set(Int128 value) + { + v = value.v; +@@ -73,49 +92,217 @@ public: + const char* show(); + #endif + +- int toInteger(int scale) const; +- SINT64 toInt64(int scale) const; ++ int toInteger(int scale) const ++ { ++ Int128 tmp(*this); ++ tmp.setScale(scale); ++ int rc = int(tmp.v); ++ if (tmp.v != rc) ++ overflow(); ++ return rc; ++ } ++ ++ SINT64 toInt64(int scale) const ++ { ++ Int128 tmp(*this); ++ tmp.setScale(scale); ++ SINT64 rc = SINT64(tmp.v); ++ if (tmp.v != rc) ++ overflow(); ++ return rc; ++ } ++ + void toString(int scale, unsigned length, char* to) const; + void toString(int scale, string& to) const; +- double toDouble() const; +- +- Int128 operator&=(FB_UINT64 mask); +- Int128 operator&=(ULONG mask); +- Int128 operator-() const; +- Int128 operator/(unsigned value) const; +- Int128 operator+=(unsigned value); +- Int128 operator-=(unsigned value); +- Int128 operator*=(unsigned value); +- +- Int128 operator<<(int value) const; +- Int128 operator>>(int value) const; +- +- int compare(Int128 tgt) const; +- bool operator>(Int128 value) const; +- bool operator>=(Int128 value) const; +- bool operator==(Int128 value) const; +- bool operator!=(Int128 value) const; +- Int128 operator&=(Int128 value); +- Int128 operator|=(Int128 value); +- Int128 operator^=(Int128 value); +- Int128 operator~() const; +- int sign() const; ++ ++ double toDouble() const ++ { ++ return double(v); ++ } ++ ++ Int128 operator&=(FB_UINT64 mask) ++ { ++ v &= mask; ++ return *this; ++ } ++ ++ Int128 operator&=(ULONG mask) ++ { ++ v &= mask; ++ return *this; ++ } ++ ++ Int128 operator-() const ++ { ++ Int128 rc; ++ rc.v = -v; ++ return rc; ++ } ++ ++ Int128 operator/(unsigned value) const ++ { ++ Int128 rc; ++ rc.v = v / value; ++ return rc; ++ } ++ ++ Int128 operator+=(unsigned value) ++ { ++ v += value; ++ return *this; ++ } ++ ++ Int128 operator-=(unsigned value) ++ { ++ v -= value; ++ return *this; ++ } ++ ++ Int128 operator*=(unsigned value) ++ { ++ v *= value; ++ return *this; ++ } ++ ++ Int128 operator<<(int value) const ++ { ++ Int128 rc; ++ rc.v = v << value; ++ return rc; ++ } ++ ++ Int128 operator>>(int value) const ++ { ++ Int128 rc; ++ rc.v = v >> value; ++ return rc; ++ } ++ ++ int compare(Int128 tgt) const ++ { ++ return v < tgt.v ? -1 : v > tgt.v ? 1 : 0; ++ } ++ ++ bool operator>(Int128 value) const ++ { ++ return v > value.v; ++ } ++ ++ bool operator>=(Int128 value) const ++ { ++ return v >= value.v; ++ } ++ ++ bool operator==(Int128 value) const ++ { ++ return v == value.v; ++ } ++ ++ bool operator!=(Int128 value) const ++ { ++ return v != value.v; ++ } ++ ++ Int128 operator&=(Int128 value) ++ { ++ v &= value.v; ++ return *this; ++ } ++ ++ Int128 operator|=(Int128 value) ++ { ++ v |= value.v; ++ return *this; ++ } ++ ++ Int128 operator^=(Int128 value) ++ { ++ v ^= value.v; ++ return *this; ++ } ++ ++ Int128 operator~() const ++ { ++ Int128 rc; ++ rc.v = ~v; ++ return rc; ++ } ++ ++ int sign() const ++ { ++ return v < 0 ? -1 : v == 0 ? 0 : 1; ++ } + + Int128 abs() const; + Int128 neg() const; +- Int128 add(Int128 op2) const; +- Int128 sub(Int128 op2) const; +- Int128 mul(Int128 op2) const; ++ ++ Int128 add(Int128 op2) const ++ { ++ Int128 rc; ++ rc.v = v + op2.v; ++ ++ // see comment ArithmeticNode::add2() ++ if (sign() == op2.sign() && op2.sign() != rc.sign()) ++ overflow(); ++ ++ return rc; ++ } ++ ++ Int128 sub(Int128 op2) const ++ { ++ Int128 rc; ++ rc.v = v - op2.v; ++ ++ // see comment ArithmeticNode::add2() ++ if (sign() != op2.sign() && op2.sign() == rc.sign()) ++ overflow(); ++ ++ return rc; ++ } ++ ++ Int128 mul(Int128 op2) const ++ { ++ Int128 rc; ++ rc.v = v * op2.v; ++ ++ if (rc.v / v != op2.v) ++ overflow(); ++ ++ return rc; ++ } ++ + Int128 div(Int128 op2, int scale) const; +- Int128 mod(Int128 op2) const; + +- void getTable32(unsigned* dwords) const; // internal data in per-32bit form +- void setTable32(const unsigned* dwords); ++ Int128 mod(Int128 op2) const ++ { ++ if (op2.v == 0) ++ zerodivide(); ++ ++ Int128 rc; ++ rc.v = v % op2.v; ++ return rc; ++ } ++ ++ // returns internal data in per-32bit form ++ void getTable32(unsigned* dwords) const ++ { ++ absl::int128 vv = v; ++ for (int i = 0; i < 4; ++i) ++ { ++ dwords[i] = unsigned(vv); ++ vv >>= 32; ++ } ++ } ++ + void setScale(int scale); +- UCHAR* getBytes(); ++ ++ UCHAR* getBytes() ++ { ++ return (UCHAR*)(&v); ++ } + + protected: +- ttmath::Int v; ++ absl::int128 v; + + static void overflow(); + static void zerodivide(); +@@ -143,10 +330,10 @@ class I128limit : public Int128 + public: + I128limit() + { +- v.SetOne(); ++ v = 1; + for (int i = 0; i < 126; ++i) +- v.MulInt(2); +- v.DivInt(5); ++ v *= 2; ++ v *= 5; + } + }; + +diff --git a/src/jrd/align.h b/src/jrd/align.h +index aa4631488d..c94f0f4da3 100644 +--- a/src/jrd/align.h ++++ b/src/jrd/align.h +@@ -114,7 +114,7 @@ static const USHORT type_alignments[DTYPE_TYPE_MAX] = + sizeof(UCHAR), /* dtype_boolean */ + sizeof(Firebird::Decimal64),/* dtype_dec64 */ + sizeof(Firebird::Decimal64),/* dtype_dec128 */ +- sizeof(Firebird::Decimal64),/* dtype_int128 */ ++ sizeof(SINT64), /* dtype_int128 */ + sizeof(GDS_TIME), /* dtype_sql_time_tz */ + sizeof(GDS_DATE), /* dtype_timestamp_tz */ + sizeof(GDS_TIME), /* dtype_ex_time_tz */ From 813c88f6d2b5febc39f046660f50539176f77499 Mon Sep 17 00:00:00 2001 From: Kalev Lember Date: Fri, 8 Oct 2021 03:57:02 +0200 Subject: [PATCH 27/51] BuildRequire systemd-rpm-macros instead of systemd-units The package that ships %systemd_post/postun/preun macros is systemd-rpm-macros. --- firebird.spec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/firebird.spec b/firebird.spec index 3d841aa..979325d 100644 --- a/firebird.spec +++ b/firebird.spec @@ -10,7 +10,7 @@ Name: firebird Version: %{upversion} -Release: 3%{?dist} +Release: 4%{?dist} Summary: SQL relational database management system License: Interbase @@ -44,7 +44,7 @@ BuildRequires: libicu-devel BuildRequires: libedit-devel BuildRequires: gcc-c++ BuildRequires: libstdc++-static -BuildRequires: systemd-units +BuildRequires: systemd-rpm-macros BuildRequires: chrpath BuildRequires: zlib-devel BuildRequires: procmail @@ -379,6 +379,9 @@ fi %changelog +* Fri Oct 08 2021 Kalev Lember - 4.0.0.2496-4 +- BuildRequire systemd-rpm-macros instead of systemd-units + * Fri Aug 20 2021 Philippe Makowski - 4.0.0.2496-3 - Fix build on s390x (#1969393) From f852ddf23c4f8a70c661bdd7a9cdda42b6279b73 Mon Sep 17 00:00:00 2001 From: Kalev Lember Date: Fri, 8 Oct 2021 04:01:12 +0200 Subject: [PATCH 28/51] Remove requires on systemd-units as per updated guidelines There is no need to have them as systemd correctly handles reloading depending on the transaction ordering (even if systemd is installed _after_ the package that installs the unit file). --- firebird.spec | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/firebird.spec b/firebird.spec index 979325d..a696978 100644 --- a/firebird.spec +++ b/firebird.spec @@ -57,9 +57,6 @@ Requires(postun): /usr/sbin/userdel Requires(postun): /usr/sbin/groupdel Requires(pre): /usr/sbin/groupadd Requires(pre): /usr/sbin/useradd -Requires(post): systemd-units -Requires(preun): systemd-units -Requires(postun): systemd-units Requires: logrotate Requires: libfbclient2 = %{version}-%{release} Requires: libib-util = %{version}-%{release} @@ -381,6 +378,7 @@ fi %changelog * Fri Oct 08 2021 Kalev Lember - 4.0.0.2496-4 - BuildRequire systemd-rpm-macros instead of systemd-units +- Remove requires on systemd-units as per updated guidelines * Fri Aug 20 2021 Philippe Makowski - 4.0.0.2496-3 - Fix build on s390x (#1969393) From 861f86033b2722997a2dbdc080663c23f4fbdbba Mon Sep 17 00:00:00 2001 From: Kalev Lember Date: Sun, 10 Oct 2021 15:50:10 +0200 Subject: [PATCH 29/51] Recommend logrotate rather than hard requiring This makes it possible for the flatpak module builds (libreoffice flatpak) to avoid logrotate dep that doesn't make sense inside flatpak containers. Using Recommends instead of Requires still means that it gets pulled in by default for regular fedora rpm installs, but users can exclude the package if they have to. --- firebird.spec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/firebird.spec b/firebird.spec index a696978..6aab399 100644 --- a/firebird.spec +++ b/firebird.spec @@ -10,7 +10,7 @@ Name: firebird Version: %{upversion} -Release: 4%{?dist} +Release: 5%{?dist} Summary: SQL relational database management system License: Interbase @@ -57,7 +57,7 @@ Requires(postun): /usr/sbin/userdel Requires(postun): /usr/sbin/groupdel Requires(pre): /usr/sbin/groupadd Requires(pre): /usr/sbin/useradd -Requires: logrotate +Recommends: logrotate Requires: libfbclient2 = %{version}-%{release} Requires: libib-util = %{version}-%{release} Requires: %{name}-utils = %{version}-%{release} @@ -376,6 +376,9 @@ fi %changelog +* Sun Oct 10 2021 Kalev Lember - 4.0.0.2496-5 +- Recommend logrotate rather than hard requiring + * Fri Oct 08 2021 Kalev Lember - 4.0.0.2496-4 - BuildRequire systemd-rpm-macros instead of systemd-units - Remove requires on systemd-units as per updated guidelines From 6281e568ac5443e5a6ca106bccb29b985bab3f33 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Thu, 20 Jan 2022 03:01:19 +0000 Subject: [PATCH 30/51] - Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild Signed-off-by: Fedora Release Engineering --- firebird.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/firebird.spec b/firebird.spec index 6aab399..a8a2bef 100644 --- a/firebird.spec +++ b/firebird.spec @@ -10,7 +10,7 @@ Name: firebird Version: %{upversion} -Release: 5%{?dist} +Release: 6%{?dist} Summary: SQL relational database management system License: Interbase @@ -376,6 +376,9 @@ fi %changelog +* Thu Jan 20 2022 Fedora Release Engineering - 4.0.0.2496-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild + * Sun Oct 10 2021 Kalev Lember - 4.0.0.2496-5 - Recommend logrotate rather than hard requiring From 2026ffed7adb556bad067532e0406cd87ef1c046 Mon Sep 17 00:00:00 2001 From: Philippe Makowski Date: Fri, 13 May 2022 09:40:32 +0200 Subject: [PATCH 31/51] Remove Standard output type syslog (#2035798) --- firebird-superserver.service | 15 --------------- firebird.service | 1 - firebird.spec | 5 ++++- 3 files changed, 4 insertions(+), 17 deletions(-) delete mode 100644 firebird-superserver.service diff --git a/firebird-superserver.service b/firebird-superserver.service deleted file mode 100644 index 50442e6..0000000 --- a/firebird-superserver.service +++ /dev/null @@ -1,15 +0,0 @@ -[Unit] -Description=Firebird Database Server ( SuperServer ) -After=network.target -Conflicts=firebird-classic.socket - -[Service] -User=firebird -Group=firebird -ExecStart=/usr/sbin/fbguard -forever -StandardError=syslog -RuntimeDirectory=firebird -RuntimeDirectoryMode=0775 - -[Install] -WantedBy=multi-user.target diff --git a/firebird.service b/firebird.service index bd48870..ecd4cf4 100644 --- a/firebird.service +++ b/firebird.service @@ -7,7 +7,6 @@ Conflicts=firebird-classic.socket User=firebird Group=firebird ExecStart=/usr/sbin/fbguard -forever -StandardError=syslog RuntimeDirectory=firebird RuntimeDirectoryMode=0775 diff --git a/firebird.spec b/firebird.spec index a8a2bef..d6802c0 100644 --- a/firebird.spec +++ b/firebird.spec @@ -10,7 +10,7 @@ Name: firebird Version: %{upversion} -Release: 6%{?dist} +Release: 7%{?dist} Summary: SQL relational database management system License: Interbase @@ -376,6 +376,9 @@ fi %changelog +* Fri May 13 2022 Philippe Makowski - 4.0.0.2496-7 +- Remove Standard output type syslog (#2035798) + * Thu Jan 20 2022 Fedora Release Engineering - 4.0.0.2496-6 - Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild From 0778c670a00d2048753d21f00db8bd374c5fac06 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Thu, 21 Jul 2022 03:11:33 +0000 Subject: [PATCH 32/51] Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild Signed-off-by: Fedora Release Engineering --- firebird.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/firebird.spec b/firebird.spec index d6802c0..8ee9ca7 100644 --- a/firebird.spec +++ b/firebird.spec @@ -10,7 +10,7 @@ Name: firebird Version: %{upversion} -Release: 7%{?dist} +Release: 8%{?dist} Summary: SQL relational database management system License: Interbase @@ -376,6 +376,9 @@ fi %changelog +* Thu Jul 21 2022 Fedora Release Engineering - 4.0.0.2496-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild + * Fri May 13 2022 Philippe Makowski - 4.0.0.2496-7 - Remove Standard output type syslog (#2035798) From 2c3b833ae8528a1984d72b369df79c3a07de496b Mon Sep 17 00:00:00 2001 From: Philippe Makowski Date: Fri, 12 Aug 2022 16:00:39 +0200 Subject: [PATCH 33/51] Update to 4.0.2 (#2033945) --- .gitignore | 1 + btyacc-honour-build-flags.patch | 12 ++++++ cloop-honour-build-flags.patch | 72 ++++++++++++++++++++------------- firebird.spec | 12 ++++-- no-copy-from-icu.patch | 29 +++++++------ sources | 2 +- 6 files changed, 81 insertions(+), 47 deletions(-) create mode 100644 btyacc-honour-build-flags.patch diff --git a/.gitignore b/.gitignore index c242f8c..a5eacde 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ Firebird-2.1.3.18185-0.RC2.tar.bz2 /Firebird-3.0.6.33328-0.tar.bz2 /Firebird-3.0.7.33374-0.tar.bz2 /Firebird-4.0.0.2496-0.tar.xz +/Firebird-4.0.2.2816-0.tar.xz diff --git a/btyacc-honour-build-flags.patch b/btyacc-honour-build-flags.patch new file mode 100644 index 0000000..cb9f38c --- /dev/null +++ b/btyacc-honour-build-flags.patch @@ -0,0 +1,12 @@ +--- a/extern/btyacc/Makefile 2022-08-12 15:24:40.846774310 +0200 ++++ a/extern/btyacc/Makefile 2022-08-12 15:26:20.954809720 +0200 +@@ -12,7 +12,7 @@ + # across all of our supported compilers/platforms. + + # Vanilla CFLAGS +-CFLAGS= ++CFLAGS=-fPIC -pie + + # No LDFLAGS + #LDFLAGS= + diff --git a/cloop-honour-build-flags.patch b/cloop-honour-build-flags.patch index b854300..3ce2e2f 100644 --- a/cloop-honour-build-flags.patch +++ b/cloop-honour-build-flags.patch @@ -1,38 +1,54 @@ -diff --git a/extern/cloop/Makefile b/extern/cloop/Makefile -index 08516c2..1573dc2 100644 +Description: make cloop build honor compiler/linker flags from the environment +Author: Damyan Ivanov +Forwarded: no + --- a/extern/cloop/Makefile +++ b/extern/cloop/Makefile -@@ -6,7 +6,7 @@ TARGET := release - - CC := $(CC) - CXX := $(CXX) --LD := $(CXX) -+LD := $(CXX) $(LDFLAGS) - - SRC_DIR := src - BUILD_DIR := build -@@ -27,8 +27,9 @@ SRCS_CPP := $(foreach sdir,$(SRC_DIRS),$(wildcard $(sdir)/*.cpp)) +@@ -27,8 +27,8 @@ SRCS_CPP := $(foreach sdir,$(SRC_DIRS),$ OBJS_C := $(patsubst $(SRC_DIR)/%.c,$(OBJ_DIR)/%.o,$(SRCS_C)) OBJS_CPP := $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(SRCS_CPP)) -C_FLAGS := -ggdb -fPIC -MMD -MP -W -Wall -Wno-unused-parameter --CXX_FLAGS := $(C_FLAGS) -+COMMON_C_FLAGS := -ggdb -fPIC -MMD -MP -W -Wall -Wno-unused-parameter -+C_FLAGS := $(COMMON_C_FLAGS) $(CFLAGS) $(CPPFLAGS) -+CXX_FLAGS := $(COMMON_C_FLAGS) $(CXXFLAGS) $(CPPFLAGS) - FPC_FLAGS := -Mdelphi +-CXX_FLAGS := $(C_FLAGS) -std=c++11 ++C_FLAGS := -ggdb -fPIC -MMD -MP -W -Wall -Wno-unused-parameter $(CPPFLAGS) $(CFLAGS) ++CXX_FLAGS := $(C_FLAGS) $(CXXFLAGS) -std=c++11 + FPC_FLAGS := -Mdelphi -Cg ifeq ($(shell uname),FreeBSD) -diff --git a/extern/btyacc/Makefile b/extern/btyacc/Makefile -index f432965..52d8443 100644 ---- a/extern/btyacc/Makefile -+++ b/extern/btyacc/Makefile -@@ -12,7 +12,7 @@ HDRS = defs.h mstring.h - # across all of our supported compilers/platforms. +@@ -94,7 +94,7 @@ $(BIN_DIR)/cloop: \ + $(OBJ_DIR)/cloop/Main.o \ + | $(BIN_DIR) - # Vanilla CFLAGS --CFLAGS= -+CFLAGS=-fPIE +- $(LD) $^ -o $@ $(LIBS) ++ $(LD) $(LDFLAGS) $^ -o $@ $(LIBS) - # No LDFLAGS - #LDFLAGS= + $(SRC_DIR)/tests/test1/CalcCApi.h: $(BIN_DIR)/cloop $(SRC_DIR)/tests/test1/Interface.idl + $(BIN_DIR)/cloop $(SRC_DIR)/tests/test1/Interface.idl c-header $@ CALC_C_API_H CALC_I +@@ -121,23 +121,23 @@ $(BIN_DIR)/test1-c$(SHRLIB_EXT): \ + $(OBJ_DIR)/tests/test1/CalcCApi.o \ + $(OBJ_DIR)/tests/test1/CTest.o \ + +- $(LD) $^ -shared $(DL_LIB) -o $@ $(LIBS) ++ $(LD) $(LDFLAGS) $^ -shared $(DL_LIB) -o $@ $(LIBS) + + $(BIN_DIR)/test1-c$(EXE_EXT): \ + $(OBJ_DIR)/tests/test1/CalcCApi.o \ + $(OBJ_DIR)/tests/test1/CTest.o \ + +- $(LD) $^ $(DL_LIB) -o $@ $(LIBS) ++ $(LD) $(LDFLAGS) $^ $(DL_LIB) -o $@ $(LIBS) + + $(BIN_DIR)/test1-cpp$(SHRLIB_EXT): \ + $(OBJ_DIR)/tests/test1/CppTest.o \ + +- $(LD) $^ -shared $(DL_LIB) -o $@ $(LIBS) ++ $(LD) $(LDFLAGS) $^ -shared $(DL_LIB) -o $@ $(LIBS) + + $(BIN_DIR)/test1-cpp$(EXE_EXT): \ + $(OBJ_DIR)/tests/test1/CppTest.o \ + +- $(LD) $^ $(DL_LIB) -o $@ $(LIBS) ++ $(LD) $(LDFLAGS) $^ $(DL_LIB) -o $@ $(LIBS) + + $(BIN_DIR)/test1-pascal$(SHRLIB_EXT): \ + $(SRC_DIR)/tests/test1/PascalClasses.pas \ diff --git a/firebird.spec b/firebird.spec index 8ee9ca7..d74e792 100644 --- a/firebird.spec +++ b/firebird.spec @@ -1,4 +1,4 @@ -%global upversion 4.0.0.2496 +%global upversion 4.0.2.2816 %global pkgversion Firebird-%{upversion}-0 %global major 4.0 @@ -10,13 +10,13 @@ Name: firebird Version: %{upversion} -Release: 8%{?dist} +Release: 1%{?dist} Summary: SQL relational database management system License: Interbase URL: http://www.firebirdsql.org/ -Source0: https://github.com/FirebirdSQL/firebird/releases/download/v4.0.0/%{pkgversion}.tar.xz +Source0: https://github.com/FirebirdSQL/firebird/releases/download/v4.0.2/%{pkgversion}.tar.xz Source1: firebird-logrotate Source2: README.Fedora Source3: firebird.service @@ -35,6 +35,8 @@ Patch302: noexcept.patch Patch303: fix_build_on_big_endian_platforms.patch Patch304: ttmath-abseil.4.0.0.patch +Patch401: btyacc-honour-build-flags.patch + BuildRequires: autoconf BuildRequires: automake BuildRequires: libtommath-devel @@ -197,6 +199,7 @@ in production systems, under a variety of names, since 1981. %patch205 -p1 %patch301 -p1 %patch302 -p1 +%patch401 -p1 %ifarch s390x %patch303 -p1 %patch304 -p1 @@ -376,6 +379,9 @@ fi %changelog +* Fri Aug 12 2022 Philippe Makowski - 4.0.2.2816-1 +- Update to 4.0.2 (#2033945) + * Thu Jul 21 2022 Fedora Release Engineering - 4.0.0.2496-8 - Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild diff --git a/no-copy-from-icu.patch b/no-copy-from-icu.patch index 7f84e0b..3dfbd6d 100644 --- a/no-copy-from-icu.patch +++ b/no-copy-from-icu.patch @@ -1,18 +1,6 @@ -diff --git a/builds/posix/Makefile.in b/builds/posix/Makefile.in -index bb4ceb1..87e75a2 100644 ---- a/builds/posix/Makefile.in -+++ b/builds/posix/Makefile.in -@@ -534,7 +534,7 @@ $(GSTAT): $(GSTAT_Objects) $(COMMON_LIB) - isql: $(ISQL) - - $(ISQL): $(ISQL_Objects) $(COMMON_LIB) -- $(EXE_LINK) $(EXE_LINK_OPTIONS) $^ -o $@ $(FIREBIRD_LIBRARY_LINK) $(LIBEDITLINE) $(TERMLIB) $(LINK_LIBS) $(call LINK_DARWIN_RPATH,..) -+ $(EXE_LINK) $(EXE_LINK_OPTIONS) $^ -o $@ $(FIREBIRD_LIBRARY_LINK) $(LIBEDITLINE) $(TERMLIB) $(LINK_LIBS) $(ICU_LIBS) $(call LINK_DARWIN_RPATH,..) - - nbackup: $(NBACKUP) - -diff --git a/src/isql/isql.epp b/src/isql/isql.epp -index 79da1f7..4554252 100644 +Description: Link isql with ICU instead of embedding part of it in the source +Author: Damyan Ivanov + --- a/src/isql/isql.epp +++ b/src/isql/isql.epp @@ -173,34 +173,6 @@ const char* UNKNOWN = "*unknown*"; @@ -50,3 +38,14 @@ index 79da1f7..4554252 100644 // Return the number of characters of a string. static unsigned charLength(SSHORT charset, unsigned len, const char* str) { +--- a/builds/posix/Makefile.in ++++ b/builds/posix/Makefile.in +@@ -543,7 +543,7 @@ $(GSTAT): $(GSTAT_Objects) $(COMMON_LIB + isql: $(ISQL) + + $(ISQL): $(ISQL_Objects) $(COMMON_LIB) +- $(EXE_LINK) $(EXE_LINK_OPTIONS) $^ -o $@ $(FIREBIRD_LIBRARY_LINK) $(LIBEDITLINE) $(TERMLIB) $(LINK_LIBS) ++ $(EXE_LINK) $(EXE_LINK_OPTIONS) $^ -o $@ $(FIREBIRD_LIBRARY_LINK) $(LIBEDITLINE) $(TERMLIB) $(LINK_LIBS) $(ICU_LIBS) + + nbackup: $(NBACKUP) + diff --git a/sources b/sources index b4b3596..ca4aa18 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (Firebird-4.0.0.2496-0.tar.xz) = 110f1e9b245631ba04fb1f3f3fe16209e432157615c5c23046a277f3e6a164a2142c6732e793d9cc6650d65239a0da8bf37a74329134bd006b7d2cb070812bd6 +SHA512 (Firebird-4.0.2.2816-0.tar.xz) = c7326d3fbf8c7eddf72ba7ae5b2a9615061158df80326265107a798e75039059b6eac5396d0ea9f8fa641f8a242d6a042188d9e5e559034713eaafba68c6dd66 From 4ecb51a558d49c6e85613e3f47ec6fa9557b100c Mon Sep 17 00:00:00 2001 From: Philippe Makowski Date: Fri, 12 Aug 2022 16:23:33 +0200 Subject: [PATCH 34/51] remove patchs --- firebird.spec | 6 ------ 1 file changed, 6 deletions(-) diff --git a/firebird.spec b/firebird.spec index d74e792..44ce9c4 100644 --- a/firebird.spec +++ b/firebird.spec @@ -32,8 +32,6 @@ Patch205: cloop-honour-build-flags.patch # from upstream Patch301: c++17.patch Patch302: noexcept.patch -Patch303: fix_build_on_big_endian_platforms.patch -Patch304: ttmath-abseil.4.0.0.patch Patch401: btyacc-honour-build-flags.patch @@ -200,10 +198,6 @@ in production systems, under a variety of names, since 1981. %patch301 -p1 %patch302 -p1 %patch401 -p1 -%ifarch s390x -%patch303 -p1 -%patch304 -p1 -%endif %build From e98569fbdbcf7cb19ab6abe9ecacef0c5ddb281f Mon Sep 17 00:00:00 2001 From: Philippe Makowski Date: Fri, 12 Aug 2022 16:25:00 +0200 Subject: [PATCH 35/51] remove patchs --- fix_build_on_big_endian_platforms.patch | 36 - ttmath-abseil.4.0.0.patch | 21255 ---------------------- 2 files changed, 21291 deletions(-) delete mode 100644 fix_build_on_big_endian_platforms.patch delete mode 100644 ttmath-abseil.4.0.0.patch diff --git a/fix_build_on_big_endian_platforms.patch b/fix_build_on_big_endian_platforms.patch deleted file mode 100644 index 73be27b..0000000 --- a/fix_build_on_big_endian_platforms.patch +++ /dev/null @@ -1,36 +0,0 @@ -From cd0682bc55eb01d53278d09edc1e9e2e9bfb9983 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Dan=20Hor=C3=A1k?= -Date: Fri, 11 Jun 2021 12:39:31 +0200 -Subject: [PATCH] fix build on big endian platforms (#6852) - -* fix missing declaration of type_alignments[] for big endian platforms -* add missing definition of lwp for big endian platforms ---- - src/jrd/sort.cpp | 1 + - src/jrd/sort.h | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/src/jrd/sort.cpp b/src/jrd/sort.cpp -index 37f5f816407..77ca69c2536 100644 ---- a/src/jrd/sort.cpp -+++ b/src/jrd/sort.cpp -@@ -713,6 +713,7 @@ void Sort::diddleKey(UCHAR* record, bool direction, bool duplicateHandling) - for (sort_key_def* key = m_description.begin(), *end = m_description.end(); key < end; key++) - { - UCHAR* p = record + key->getSkdOffset(); -+ SORTP* lwp = (SORTP*) p; - USHORT n = key->getSkdLength(); - USHORT complement = key->skd_flags & SKD_descending; - -diff --git a/src/jrd/sort.h b/src/jrd/sort.h -index 8e23e70ccc5..e3bbbb7779c 100644 ---- a/src/jrd/sort.h -+++ b/src/jrd/sort.h -@@ -27,6 +27,7 @@ - #include "../include/fb_blk.h" - #include "../common/DecFloat.h" - #include "../jrd/TempSpace.h" -+#include "../jrd/align.h" - - namespace Jrd { - diff --git a/ttmath-abseil.4.0.0.patch b/ttmath-abseil.4.0.0.patch deleted file mode 100644 index ee98e95..0000000 --- a/ttmath-abseil.4.0.0.patch +++ /dev/null @@ -1,21255 +0,0 @@ -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 */ From 548bb23690981de6bef52713ec38b082aba5dfe3 Mon Sep 17 00:00:00 2001 From: Philippe Makowski Date: Thu, 24 Nov 2022 15:27:14 +0100 Subject: [PATCH 36/51] Patch for autoconf 2.72 (#2144802) --- autoconf.patch | 24 ++++++++++++++++++++++++ firebird.spec | 8 ++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 autoconf.patch diff --git a/autoconf.patch b/autoconf.patch new file mode 100644 index 0000000..e058262 --- /dev/null +++ b/autoconf.patch @@ -0,0 +1,24 @@ +From 3fe8f6510de79689a26868e244840b24dcb19567 Mon Sep 17 00:00:00 2001 +From: AlexPeshkoff +Date: Wed, 23 Nov 2022 20:30:03 +0300 +Subject: [PATCH] Fixed #7394: autoconf 2.72 support + +--- + configure.ac | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index 75af92e862c..800453d25fa 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -696,8 +696,9 @@ if test "$STD_EDITLINE" = "true"; then + AC_CHECK_LIB(readline, readline, [READLINE=readline EDITLINE_FLG=Y], + [STD_EDITLINE=false + if test "$EDITLINE_FLG" = "Y"; then +- AC_MSG_WARN([[[--with-system-editline specified, not found. Using bundled editline]]])]))) ++ AC_MSG_WARN([[[--with-system-editline specified, not found. Using bundled editline]]]) + fi ++ ]))) + fi + XE_RESTORE_ENV() + diff --git a/firebird.spec b/firebird.spec index 44ce9c4..eb1912a 100644 --- a/firebird.spec +++ b/firebird.spec @@ -10,7 +10,7 @@ Name: firebird Version: %{upversion} -Release: 1%{?dist} +Release: 2%{?dist} Summary: SQL relational database management system License: Interbase @@ -32,7 +32,7 @@ Patch205: cloop-honour-build-flags.patch # from upstream Patch301: c++17.patch Patch302: noexcept.patch - +Patch303: autoconf.patch Patch401: btyacc-honour-build-flags.patch BuildRequires: autoconf @@ -197,6 +197,7 @@ in production systems, under a variety of names, since 1981. %patch205 -p1 %patch301 -p1 %patch302 -p1 +%patch303 -p1 %patch401 -p1 @@ -373,6 +374,9 @@ fi %changelog +* Thu Nov 24 2022 Philippe Makowski - 4.0.2.2816-2 +- Patch for autoconf 2.72 (#2144802) + * Fri Aug 12 2022 Philippe Makowski - 4.0.2.2816-1 - Update to 4.0.2 (#2033945) From bc46796aca3c109ddd64eb757b0768734fab9e46 Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Thu, 1 Dec 2022 18:29:41 +0100 Subject: [PATCH 37/51] Port configure script to C99 Related to: --- firebird-configure-c99.patch | 45 ++++++++++++++++++++++++++++++++++++ firebird.spec | 7 +++++- 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 firebird-configure-c99.patch diff --git a/firebird-configure-c99.patch b/firebird-configure-c99.patch new file mode 100644 index 0000000..f24ba4a --- /dev/null +++ b/firebird-configure-c99.patch @@ -0,0 +1,45 @@ +Add missing int return types for main in the configure script. +Implicit ints are a language feature that was removed in C99. + +Submitted upstream: + +diff --git a/configure.ac b/configure.ac +index 05edb5ec9410ff50..0474dc850dfd04bc 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1038,7 +1038,7 @@ AC_CHECK_FUNCS(sem_init) + if test "$ac_cv_func_sem_init" = "yes"; then + AC_MSG_CHECKING(for working sem_init()) + AC_RUN_IFELSE([AC_LANG_SOURCE([[#include +- main () { ++ int main () { + sem_t s; + return sem_init(&s,0,0); + } +@@ -1079,7 +1079,7 @@ AC_SYS_LARGEFILE + if test "$ac_cv_sys_file_offset_bits" = "no"; then + AC_MSG_CHECKING(for native large file support) + AC_RUN_IFELSE([AC_LANG_SOURCE([[#include +- main () { ++ int main () { + return !(sizeof(off_t) == 8); + }]])],[ac_cv_sys_file_offset_bits=64; AC_DEFINE(_FILE_OFFSET_BITS,64) + AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no)],[]) +@@ -1126,7 +1126,7 @@ dnl EKU: try to determine the alignment of long and double + dnl replaces FB_ALIGNMENT and FB_DOUBLE_ALIGN in src/jrd/common.h + AC_MSG_CHECKING(alignment of long) + AC_RUN_IFELSE([AC_LANG_SOURCE([[#include +-main () { ++int main () { + struct s { + char a; + union { long long x; sem_t y; } b; +@@ -1137,7 +1137,7 @@ AC_MSG_RESULT($ac_cv_c_alignment) + AC_DEFINE_UNQUOTED(FB_ALIGNMENT, $ac_cv_c_alignment, [Alignment of long]) + + AC_MSG_CHECKING(alignment of double) +-AC_RUN_IFELSE([AC_LANG_SOURCE([[main () { ++AC_RUN_IFELSE([AC_LANG_SOURCE([[int main () { + struct s { + char a; + double b; diff --git a/firebird.spec b/firebird.spec index eb1912a..129a0f0 100644 --- a/firebird.spec +++ b/firebird.spec @@ -10,7 +10,7 @@ Name: firebird Version: %{upversion} -Release: 2%{?dist} +Release: 3%{?dist} Summary: SQL relational database management system License: Interbase @@ -34,6 +34,7 @@ Patch301: c++17.patch Patch302: noexcept.patch Patch303: autoconf.patch Patch401: btyacc-honour-build-flags.patch +Patch402: firebird-configure-c99.patch BuildRequires: autoconf BuildRequires: automake @@ -199,6 +200,7 @@ in production systems, under a variety of names, since 1981. %patch302 -p1 %patch303 -p1 %patch401 -p1 +%patch402 -p1 %build @@ -374,6 +376,9 @@ fi %changelog +* Thu Dec 1 2022 Florian Weimer - 4.0.2.2816-3 +- Port configure script to C99 + * Thu Nov 24 2022 Philippe Makowski - 4.0.2.2816-2 - Patch for autoconf 2.72 (#2144802) From ea36e598d27af849b7701a1f90b0d24e9a19652f Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Thu, 19 Jan 2023 03:27:41 +0000 Subject: [PATCH 38/51] Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild Signed-off-by: Fedora Release Engineering --- firebird.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/firebird.spec b/firebird.spec index 129a0f0..6b76229 100644 --- a/firebird.spec +++ b/firebird.spec @@ -10,7 +10,7 @@ Name: firebird Version: %{upversion} -Release: 3%{?dist} +Release: 4%{?dist} Summary: SQL relational database management system License: Interbase @@ -376,6 +376,9 @@ fi %changelog +* Thu Jan 19 2023 Fedora Release Engineering - 4.0.2.2816-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild + * Thu Dec 1 2022 Florian Weimer - 4.0.2.2816-3 - Port configure script to C99 From 945bf8d529f954671e60cb1ca9d73fd119984598 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Wed, 19 Jul 2023 19:43:30 +0000 Subject: [PATCH 39/51] Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild Signed-off-by: Fedora Release Engineering --- firebird.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/firebird.spec b/firebird.spec index 6b76229..026ca8f 100644 --- a/firebird.spec +++ b/firebird.spec @@ -10,7 +10,7 @@ Name: firebird Version: %{upversion} -Release: 4%{?dist} +Release: 5%{?dist} Summary: SQL relational database management system License: Interbase @@ -376,6 +376,9 @@ fi %changelog +* Wed Jul 19 2023 Fedora Release Engineering - 4.0.2.2816-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild + * Thu Jan 19 2023 Fedora Release Engineering - 4.0.2.2816-4 - Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild From 34dc32d7f4a0fc8c785f0e5a020259d43972ec04 Mon Sep 17 00:00:00 2001 From: Philippe Makowski Date: Tue, 8 Aug 2023 15:20:57 +0200 Subject: [PATCH 40/51] Update to 4.0.3 (#2228171) --- .gitignore | 1 + firebird.spec | 9 ++++++--- sources | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index a5eacde..4b15326 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ Firebird-2.1.3.18185-0.RC2.tar.bz2 /Firebird-3.0.7.33374-0.tar.bz2 /Firebird-4.0.0.2496-0.tar.xz /Firebird-4.0.2.2816-0.tar.xz +/Firebird-4.0.3.2975-0.tar.xz diff --git a/firebird.spec b/firebird.spec index 026ca8f..13e8a55 100644 --- a/firebird.spec +++ b/firebird.spec @@ -1,4 +1,4 @@ -%global upversion 4.0.2.2816 +%global upversion 4.0.3.2975 %global pkgversion Firebird-%{upversion}-0 %global major 4.0 @@ -10,13 +10,13 @@ Name: firebird Version: %{upversion} -Release: 5%{?dist} +Release: 1%{?dist} Summary: SQL relational database management system License: Interbase URL: http://www.firebirdsql.org/ -Source0: https://github.com/FirebirdSQL/firebird/releases/download/v4.0.2/%{pkgversion}.tar.xz +Source0: https://github.com/FirebirdSQL/firebird/releases/download/v4.0.3/%{pkgversion}.tar.xz Source1: firebird-logrotate Source2: README.Fedora Source3: firebird.service @@ -376,6 +376,9 @@ fi %changelog +* Tue Aug 08 2023 Philippe Makowski - 4.0.3.2975-0 +- Update to 4.0.3 (#2228171) + * Wed Jul 19 2023 Fedora Release Engineering - 4.0.2.2816-5 - Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild diff --git a/sources b/sources index ca4aa18..71d1c20 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (Firebird-4.0.2.2816-0.tar.xz) = c7326d3fbf8c7eddf72ba7ae5b2a9615061158df80326265107a798e75039059b6eac5396d0ea9f8fa641f8a242d6a042188d9e5e559034713eaafba68c6dd66 +SHA512 (Firebird-4.0.3.2975-0.tar.xz) = 9fc5b659effab50b3e9802bc7c0a203a8666902c7a0aafe2ed276a7a879937e3449f9f18988d484635e5113407b5f337e73f0eb2455e18b2d2b4755c5fd21046 From 956fde06ed5d7b719ab08cbb23ba959fe1bc7f99 Mon Sep 17 00:00:00 2001 From: Yaakov Selkowitz Date: Fri, 3 Nov 2023 15:45:05 -0400 Subject: [PATCH 41/51] Respect build flags in examples This is particularly needed for flatpak builds (for libreoffice), without which libtomcrypt/libtommath are not found. --- examples-honour-build-flags.patch | 28 ++++++++++++++++++++++++++++ firebird.spec | 4 ++++ 2 files changed, 32 insertions(+) create mode 100644 examples-honour-build-flags.patch diff --git a/examples-honour-build-flags.patch b/examples-honour-build-flags.patch new file mode 100644 index 0000000..fc7ebd9 --- /dev/null +++ b/examples-honour-build-flags.patch @@ -0,0 +1,28 @@ +diff --git a/builds/posix/Makefile.in.plugins_examples b/builds/posix/Makefile.in.plugins_examples +index 989e80d..344f487 100644 +--- a/builds/posix/Makefile.in.plugins_examples ++++ b/builds/posix/Makefile.in.plugins_examples +@@ -101,7 +101,7 @@ AllObjects += $(CA_Objects) + crypt_app: $(CRYPT_APP) + + $(CRYPT_APP): $(CA_Objects) +- $(EXE_LINK) $(LSB_UNDEF) $^ -o $@ $(FIREBIRD_LIBRARY_LINK) ++ $(EXE_LINK) $(EXE_LINK_OPTIONS) $(LSB_UNDEF) $^ -o $@ $(FIREBIRD_LIBRARY_LINK) + + + include $(ROOT)/gen/make.shared.targets +diff --git a/examples/extauth/Makefile b/examples/extauth/Makefile +index 3c8b878..7de22a8 100644 +--- a/examples/extauth/Makefile ++++ b/examples/extauth/Makefile +@@ -61,8 +61,8 @@ KEYGEN_objects=$(INTERMED)/keygen.o + TCWRAP_objects=$(INTERMED)/TcWrapper.o + KEY_AUTH_objects=$(INTERMED)/ExtAuth.o + +-CXXFLAGS=-std=c++17 -pthread -I$(ROOT)/include -fPIC $(TOMCRYPT_COMPILE) +-LDFLAGS=-pthread -L$(LIB) -Wl,-rpath,'$$ORIGIN/../lib' $(TOMCRYPT_LINK) ++CXXFLAGS+=-std=c++17 -pthread -I$(ROOT)/include -fPIC $(TOMCRYPT_COMPILE) ++LDFLAGS+=-pthread -L$(LIB) -Wl,-rpath,'$$ORIGIN/../lib' $(TOMCRYPT_LINK) + + LINK_LIBS=-lfbclient -ltomcrypt -ltommath + diff --git a/firebird.spec b/firebird.spec index 13e8a55..52d3892 100644 --- a/firebird.spec +++ b/firebird.spec @@ -36,6 +36,9 @@ Patch303: autoconf.patch Patch401: btyacc-honour-build-flags.patch Patch402: firebird-configure-c99.patch +# not yet upstream +Patch501: examples-honour-build-flags.patch + BuildRequires: autoconf BuildRequires: automake BuildRequires: libtommath-devel @@ -201,6 +204,7 @@ in production systems, under a variety of names, since 1981. %patch303 -p1 %patch401 -p1 %patch402 -p1 +%patch -P501 -p1 %build From f4a59a8e8cbc9f022de671d8ccaf8b0ea47252d3 Mon Sep 17 00:00:00 2001 From: Philippe Makowski Date: Thu, 9 Nov 2023 09:38:14 +0100 Subject: [PATCH 42/51] Update to 4.0.4 (#2247832) --- .gitignore | 1 + firebird.spec | 21 ++++++++++++--------- sources | 2 +- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 4b15326..8f1d1c3 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ Firebird-2.1.3.18185-0.RC2.tar.bz2 /Firebird-4.0.0.2496-0.tar.xz /Firebird-4.0.2.2816-0.tar.xz /Firebird-4.0.3.2975-0.tar.xz +/Firebird-4.0.4.3010-0.tar.xz diff --git a/firebird.spec b/firebird.spec index 52d3892..503ce72 100644 --- a/firebird.spec +++ b/firebird.spec @@ -1,4 +1,4 @@ -%global upversion 4.0.3.2975 +%global upversion 4.0.4.3010 %global pkgversion Firebird-%{upversion}-0 %global major 4.0 @@ -196,14 +196,14 @@ in production systems, under a variety of names, since 1981. %prep %setup -q -n %{pkgversion} -%patch101 -p1 -%patch203 -p1 -%patch205 -p1 -%patch301 -p1 -%patch302 -p1 -%patch303 -p1 -%patch401 -p1 -%patch402 -p1 +%patch -P101 -p1 +%patch -P203 -p1 +%patch -P205 -p1 +%patch -P301 -p1 +%patch -P302 -p1 +%patch -P303 -p1 +%patch -P401 -p1 +%patch -P402 -p1 %patch -P501 -p1 @@ -380,6 +380,9 @@ fi %changelog +* Thu Nov 09 2023 Philippe Makowski - 4.0.4.3010-0 +- Update to 4.0.4 (#2247832) + * Tue Aug 08 2023 Philippe Makowski - 4.0.3.2975-0 - Update to 4.0.3 (#2228171) diff --git a/sources b/sources index 71d1c20..35b2432 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (Firebird-4.0.3.2975-0.tar.xz) = 9fc5b659effab50b3e9802bc7c0a203a8666902c7a0aafe2ed276a7a879937e3449f9f18988d484635e5113407b5f337e73f0eb2455e18b2d2b4755c5fd21046 +SHA512 (Firebird-4.0.4.3010-0.tar.xz) = a3bba5fd28ccae67f0f040be61763d14f97c63ad381bbbaf359e09117f11ab5c54a965c1ed14c2092d60a145373743e12202b0d8e80ec7b456d32ab00c8f1b08 From 9ea2d6655518c0aff03cbb1801c39ddb5a2a95b1 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Fri, 19 Jan 2024 19:20:48 +0000 Subject: [PATCH 43/51] Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild --- firebird.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/firebird.spec b/firebird.spec index 503ce72..4e703c2 100644 --- a/firebird.spec +++ b/firebird.spec @@ -10,7 +10,7 @@ Name: firebird Version: %{upversion} -Release: 1%{?dist} +Release: 2%{?dist} Summary: SQL relational database management system License: Interbase @@ -380,6 +380,9 @@ fi %changelog +* Fri Jan 19 2024 Fedora Release Engineering - 4.0.4.3010-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + * Thu Nov 09 2023 Philippe Makowski - 4.0.4.3010-0 - Update to 4.0.4 (#2247832) From e7f9a8fc4644e49046cd7e30decae882e67f3d17 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Wed, 24 Jan 2024 11:35:33 +0000 Subject: [PATCH 44/51] Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild --- firebird.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/firebird.spec b/firebird.spec index 4e703c2..8874cb7 100644 --- a/firebird.spec +++ b/firebird.spec @@ -10,7 +10,7 @@ Name: firebird Version: %{upversion} -Release: 2%{?dist} +Release: 3%{?dist} Summary: SQL relational database management system License: Interbase @@ -380,6 +380,9 @@ fi %changelog +* Wed Jan 24 2024 Fedora Release Engineering - 4.0.4.3010-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + * Fri Jan 19 2024 Fedora Release Engineering - 4.0.4.3010-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild From c1190948a5b35f9c268f888c1880f87a32591dd0 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Wed, 17 Jul 2024 23:09:47 +0000 Subject: [PATCH 45/51] Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild --- firebird.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/firebird.spec b/firebird.spec index 8874cb7..28069c5 100644 --- a/firebird.spec +++ b/firebird.spec @@ -10,7 +10,7 @@ Name: firebird Version: %{upversion} -Release: 3%{?dist} +Release: 4%{?dist} Summary: SQL relational database management system License: Interbase @@ -380,6 +380,9 @@ fi %changelog +* Wed Jul 17 2024 Fedora Release Engineering - 4.0.4.3010-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild + * Wed Jan 24 2024 Fedora Release Engineering - 4.0.4.3010-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild From 486a7272e810d4b98c170f461dd1972c9b75c67c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Such=C3=BD?= Date: Wed, 7 Aug 2024 09:27:50 +0200 Subject: [PATCH 46/51] convert license to SPDX This is part of https://fedoraproject.org/wiki/Changes/SPDX_Licenses_Phase_4 --- firebird.spec | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/firebird.spec b/firebird.spec index 28069c5..e0032b6 100644 --- a/firebird.spec +++ b/firebird.spec @@ -10,10 +10,11 @@ Name: firebird Version: %{upversion} -Release: 4%{?dist} +Release: 5%{?dist} Summary: SQL relational database management system -License: Interbase +# Automatically converted from old format: Interbase - review is highly recommended. +License: Interbase-1.0 URL: http://www.firebirdsql.org/ Source0: https://github.com/FirebirdSQL/firebird/releases/download/v4.0.3/%{pkgversion}.tar.xz @@ -380,6 +381,9 @@ fi %changelog +* Wed Aug 07 2024 Miroslav Suchý - 4.0.4.3010-5 +- convert license to SPDX + * Wed Jul 17 2024 Fedora Release Engineering - 4.0.4.3010-4 - Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild From 1ad5b3f7bfe457827ea77e1148069b5e223ae9b1 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Thu, 16 Jan 2025 18:18:42 +0000 Subject: [PATCH 47/51] Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild --- firebird.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/firebird.spec b/firebird.spec index e0032b6..4344e79 100644 --- a/firebird.spec +++ b/firebird.spec @@ -10,7 +10,7 @@ Name: firebird Version: %{upversion} -Release: 5%{?dist} +Release: 6%{?dist} Summary: SQL relational database management system # Automatically converted from old format: Interbase - review is highly recommended. @@ -381,6 +381,9 @@ fi %changelog +* Thu Jan 16 2025 Fedora Release Engineering - 4.0.4.3010-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild + * Wed Aug 07 2024 Miroslav Suchý - 4.0.4.3010-5 - convert license to SPDX From 425f1bc7f645bc6b364c175635b5cd7196898adc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 11 Feb 2025 15:35:16 +0100 Subject: [PATCH 48/51] Add sysusers.d config file to allow rpm to create users/groups automatically See https://fedoraproject.org/wiki/Changes/RPMSuportForSystemdSysusers. --- firebird.spec | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/firebird.spec b/firebird.spec index 4344e79..8d65fab 100644 --- a/firebird.spec +++ b/firebird.spec @@ -10,7 +10,7 @@ Name: firebird Version: %{upversion} -Release: 6%{?dist} +Release: 7%{?dist} Summary: SQL relational database management system # Automatically converted from old format: Interbase - review is highly recommended. @@ -60,8 +60,6 @@ BuildRequires: sed Requires(postun): /usr/sbin/userdel Requires(postun): /usr/sbin/groupdel -Requires(pre): /usr/sbin/groupadd -Requires(pre): /usr/sbin/useradd Recommends: logrotate Requires: libfbclient2 = %{version}-%{release} Requires: libib-util = %{version}-%{release} @@ -207,6 +205,11 @@ in production systems, under a variety of names, since 1981. %patch -P402 -p1 %patch -P501 -p1 +# Create a sysusers.d config file +cat >firebird.sysusers.conf < /dev/null || /usr/sbin/groupadd -r %{name} -getent passwd %{name} >/dev/null || /usr/sbin/useradd -d / -g %{name} -s /sbin/nologin -r %{name} - # Add gds_db to /etc/services if needed FileName=/etc/services newLine="gds_db 3050/tcp # Firebird SQL Database Remote Protocol" @@ -333,6 +333,7 @@ fi %config(noreplace) %attr(0644,root,root) %{_sysconfdir}/logrotate.d/%{name} %attr(0644,root,root) %{_unitdir}/%{name}.service +%{_sysusersdir}/firebird.conf %files devel @@ -381,6 +382,9 @@ fi %changelog +* Tue Feb 11 2025 Zbigniew Jędrzejewski-Szmek - 4.0.4.3010-7 +- Add sysusers.d config file to allow rpm to create users/groups automatically + * Thu Jan 16 2025 Fedora Release Engineering - 4.0.4.3010-6 - Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild From 799921c421d27c2744c7a4767223f193eab20602 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Wed, 23 Jul 2025 20:32:23 +0000 Subject: [PATCH 49/51] Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild --- firebird.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/firebird.spec b/firebird.spec index 8d65fab..9d1c42c 100644 --- a/firebird.spec +++ b/firebird.spec @@ -10,7 +10,7 @@ Name: firebird Version: %{upversion} -Release: 7%{?dist} +Release: 8%{?dist} Summary: SQL relational database management system # Automatically converted from old format: Interbase - review is highly recommended. @@ -382,6 +382,9 @@ fi %changelog +* Wed Jul 23 2025 Fedora Release Engineering - 4.0.4.3010-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild + * Tue Feb 11 2025 Zbigniew Jędrzejewski-Szmek - 4.0.4.3010-7 - Add sysusers.d config file to allow rpm to create users/groups automatically From 8c97c25830046efccf9b82d5227c84b945d91d8a Mon Sep 17 00:00:00 2001 From: Gwyn Ciesla Date: Thu, 25 Sep 2025 11:23:32 -0500 Subject: [PATCH 50/51] 4.0.6.3221 --- .gitignore | 1 + autoconf.patch | 24 ------------------- c++17.patch | 24 +++++++++---------- firebird-configure-c99.patch | 45 ------------------------------------ firebird.spec | 19 +++++++-------- sources | 2 +- 6 files changed, 21 insertions(+), 94 deletions(-) delete mode 100644 autoconf.patch delete mode 100644 firebird-configure-c99.patch diff --git a/.gitignore b/.gitignore index 8f1d1c3..071d71f 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ Firebird-2.1.3.18185-0.RC2.tar.bz2 /Firebird-4.0.2.2816-0.tar.xz /Firebird-4.0.3.2975-0.tar.xz /Firebird-4.0.4.3010-0.tar.xz +/Firebird-4.0.6.3221-0.tar.xz diff --git a/autoconf.patch b/autoconf.patch deleted file mode 100644 index e058262..0000000 --- a/autoconf.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 3fe8f6510de79689a26868e244840b24dcb19567 Mon Sep 17 00:00:00 2001 -From: AlexPeshkoff -Date: Wed, 23 Nov 2022 20:30:03 +0300 -Subject: [PATCH] Fixed #7394: autoconf 2.72 support - ---- - configure.ac | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/configure.ac b/configure.ac -index 75af92e862c..800453d25fa 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -696,8 +696,9 @@ if test "$STD_EDITLINE" = "true"; then - AC_CHECK_LIB(readline, readline, [READLINE=readline EDITLINE_FLG=Y], - [STD_EDITLINE=false - if test "$EDITLINE_FLG" = "Y"; then -- AC_MSG_WARN([[[--with-system-editline specified, not found. Using bundled editline]]])]))) -+ AC_MSG_WARN([[[--with-system-editline specified, not found. Using bundled editline]]]) - fi -+ ]))) - fi - XE_RESTORE_ENV() - diff --git a/c++17.patch b/c++17.patch index 76cd4e2..282195b 100644 --- a/c++17.patch +++ b/c++17.patch @@ -36,19 +36,6 @@ index 620fd032af4..5f336efd611 100644 if (NOT CMAKE_CROSSCOMPILING) set(LIB_readline readline) -diff --git a/builds/posix/make.defaults b/builds/posix/make.defaults -index d96e89053fa..57bbb006865 100755 ---- a/builds/posix/make.defaults -+++ b/builds/posix/make.defaults -@@ -103,7 +103,7 @@ GLOB_OPTIONS:= - #____________________________________________________________________________ - - # Global c++ flags: firebird needs no RTTI, choose build standard --PLUSPLUS_FLAGS:= -fno-rtti -std=c++11 -+PLUSPLUS_FLAGS:= -fno-rtti -std=c++17 - - # If this is defined then we use special rules useful for developers only - IsDeveloper = @DEVEL_FLG@ diff --git a/builds/posix/prefix.freebsd_amd64 b/builds/posix/prefix.freebsd_amd64 index f27567a2715..0736d87e935 100644 --- a/builds/posix/prefix.freebsd_amd64 @@ -142,3 +129,14 @@ index a8b56024aae..6e7d9c5f5c8 100755 --enable-static \ --enable-shared=no \ --enable-extras=no \ +--- Firebird-4.0.6.3221-0/builds/posix/make.defaults~ 2025-07-14 02:27:01.000000000 -0500 ++++ Firebird-4.0.6.3221-0/builds/posix/make.defaults 2025-09-25 08:37:36.864575311 -0500 +@@ -104,7 +104,7 @@ + #____________________________________________________________________________ + + # Global c++ flags: firebird needs no RTTI, choose build standard, make it build with icu-76.1 +-PLUSPLUS_FLAGS:= -fno-rtti -std=c++11 -DU_SHOW_CPLUSPLUS_API=0 -DU_SHOW_CPLUSPLUS_HEADER_API=0 ++PLUSPLUS_FLAGS:= -fno-rtti -std=c++17 -DU_SHOW_CPLUSPLUS_API=0 -DU_SHOW_CPLUSPLUS_HEADER_API=0 + + # If this is defined then we use special rules useful for developers only + IsDeveloper = @DEVEL_FLG@ diff --git a/firebird-configure-c99.patch b/firebird-configure-c99.patch deleted file mode 100644 index f24ba4a..0000000 --- a/firebird-configure-c99.patch +++ /dev/null @@ -1,45 +0,0 @@ -Add missing int return types for main in the configure script. -Implicit ints are a language feature that was removed in C99. - -Submitted upstream: - -diff --git a/configure.ac b/configure.ac -index 05edb5ec9410ff50..0474dc850dfd04bc 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -1038,7 +1038,7 @@ AC_CHECK_FUNCS(sem_init) - if test "$ac_cv_func_sem_init" = "yes"; then - AC_MSG_CHECKING(for working sem_init()) - AC_RUN_IFELSE([AC_LANG_SOURCE([[#include -- main () { -+ int main () { - sem_t s; - return sem_init(&s,0,0); - } -@@ -1079,7 +1079,7 @@ AC_SYS_LARGEFILE - if test "$ac_cv_sys_file_offset_bits" = "no"; then - AC_MSG_CHECKING(for native large file support) - AC_RUN_IFELSE([AC_LANG_SOURCE([[#include -- main () { -+ int main () { - return !(sizeof(off_t) == 8); - }]])],[ac_cv_sys_file_offset_bits=64; AC_DEFINE(_FILE_OFFSET_BITS,64) - AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no)],[]) -@@ -1126,7 +1126,7 @@ dnl EKU: try to determine the alignment of long and double - dnl replaces FB_ALIGNMENT and FB_DOUBLE_ALIGN in src/jrd/common.h - AC_MSG_CHECKING(alignment of long) - AC_RUN_IFELSE([AC_LANG_SOURCE([[#include --main () { -+int main () { - struct s { - char a; - union { long long x; sem_t y; } b; -@@ -1137,7 +1137,7 @@ AC_MSG_RESULT($ac_cv_c_alignment) - AC_DEFINE_UNQUOTED(FB_ALIGNMENT, $ac_cv_c_alignment, [Alignment of long]) - - AC_MSG_CHECKING(alignment of double) --AC_RUN_IFELSE([AC_LANG_SOURCE([[main () { -+AC_RUN_IFELSE([AC_LANG_SOURCE([[int main () { - struct s { - char a; - double b; diff --git a/firebird.spec b/firebird.spec index 9d1c42c..3521f4a 100644 --- a/firebird.spec +++ b/firebird.spec @@ -1,4 +1,4 @@ -%global upversion 4.0.4.3010 +%global upversion 4.0.6.3221 %global pkgversion Firebird-%{upversion}-0 %global major 4.0 @@ -10,14 +10,14 @@ Name: firebird Version: %{upversion} -Release: 8%{?dist} +Release: 1%{?dist} Summary: SQL relational database management system # Automatically converted from old format: Interbase - review is highly recommended. License: Interbase-1.0 URL: http://www.firebirdsql.org/ -Source0: https://github.com/FirebirdSQL/firebird/releases/download/v4.0.3/%{pkgversion}.tar.xz +Source0: https://github.com/FirebirdSQL/firebird/releases/download/v4.0.6/%{pkgversion}.tar.xz Source1: firebird-logrotate Source2: README.Fedora Source3: firebird.service @@ -33,9 +33,7 @@ Patch205: cloop-honour-build-flags.patch # from upstream Patch301: c++17.patch Patch302: noexcept.patch -Patch303: autoconf.patch Patch401: btyacc-honour-build-flags.patch -Patch402: firebird-configure-c99.patch # not yet upstream Patch501: examples-honour-build-flags.patch @@ -200,9 +198,7 @@ in production systems, under a variety of names, since 1981. %patch -P205 -p1 %patch -P301 -p1 %patch -P302 -p1 -%patch -P303 -p1 %patch -P401 -p1 -%patch -P402 -p1 %patch -P501 -p1 # Create a sysusers.d config file @@ -299,9 +295,7 @@ fi %files -%{_docdir}/%{name}/IDPLicense.txt -%{_docdir}/%{name}/IPLicense.txt -%{_docdir}/%{name}/README.Fedora +%{_docdir}/%{name}/ %{_bindir}/fbtracemgr %{_sbindir}/firebird %{_sbindir}/fbguard @@ -357,7 +351,7 @@ fi %files doc -%{_docdir}/%{name} +%{_docdir}/%{name}/ %exclude %{_docdir}/%{name}/sample %exclude %{_docdir}/%{name}/IDPLicense.txt %exclude %{_docdir}/%{name}/IPLicense.txt @@ -382,6 +376,9 @@ fi %changelog +* Thu Sep 25 2025 Gwyn Ciesla - 4.0.6.3221-1 +- 4.0.6.3221 + * Wed Jul 23 2025 Fedora Release Engineering - 4.0.4.3010-8 - Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild diff --git a/sources b/sources index 35b2432..186b123 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (Firebird-4.0.4.3010-0.tar.xz) = a3bba5fd28ccae67f0f040be61763d14f97c63ad381bbbaf359e09117f11ab5c54a965c1ed14c2092d60a145373743e12202b0d8e80ec7b456d32ab00c8f1b08 +SHA512 (Firebird-4.0.6.3221-0.tar.xz) = 9d2b5970e401fb6e0eef9bd91051bfc02ee90d2388227ac0bf5230a59f434da2d89fd50ea69b5e4a817772c342b0134a06100b772a9b87de3986f39a75ced3b6 From 4525462e5fa1668b8f9c934dc599050a3d8957d9 Mon Sep 17 00:00:00 2001 From: Gwyn Ciesla Date: Mon, 29 Sep 2025 14:33:20 -0500 Subject: [PATCH 51/51] Firebird 5.x --- .gitignore | 1 + add-pkgconfig-files.patch | 10 +- c++17.patch | 142 -------- firebird.spec | 39 +-- noexcept.patch | 664 -------------------------------------- sources | 2 +- 6 files changed, 17 insertions(+), 841 deletions(-) delete mode 100644 c++17.patch delete mode 100644 noexcept.patch diff --git a/.gitignore b/.gitignore index 071d71f..0e5122a 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ Firebird-2.1.3.18185-0.RC2.tar.bz2 /Firebird-4.0.3.2975-0.tar.xz /Firebird-4.0.4.3010-0.tar.xz /Firebird-4.0.6.3221-0.tar.xz +/Firebird-5.0.3.1683-0-source.tar.xz diff --git a/add-pkgconfig-files.patch b/add-pkgconfig-files.patch index 981afe2..e9fbb3f 100644 --- a/add-pkgconfig-files.patch +++ b/add-pkgconfig-files.patch @@ -14,15 +14,13 @@ index 0000000..d49fdc5 +Version: @FIREBIRD_VERSION@ +Cflags: -I${includedir}/firebird +Libs: -L${libdir} -lfbclient -diff --git a/configure.ac b/configure.ac -index 0a3de36..922c778 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -1307,6 +1307,7 @@ case "$PLATFORM" in +--- Firebird-5.0.3.1683-0-source/configure.ac~ 2025-07-14 01:33:58.000000000 -0500 ++++ Firebird-5.0.3.1683-0-source/configure.ac 2025-09-26 10:42:45.022624859 -0500 +@@ -1540,6 +1540,7 @@ gen/install/misc/firebird.init.d.gentoo:builds/install/arch-specific/linux/firebird.init.d.gentoo.in gen/install/misc/firebird.init.d.slackware:builds/install/arch-specific/linux/firebird.init.d.slackware.in gen/install/misc/rc.config.firebird:builds/install/arch-specific/linux/rc.config.firebird.in + gen/install/misc/fbclient.pc:builds/install/arch-specific/linux/misc/fbclient.pc.in - gen/Release/firebird/bin/linuxLibrary.sh:builds/install/arch-specific/linux/linuxLibrary.sh.in gen/install/misc/firebird.service:builds/install/arch-specific/linux/firebird.service.in ], + [chmod a+x gen/install/*sh 2>/dev/null]) diff --git a/c++17.patch b/c++17.patch deleted file mode 100644 index 282195b..0000000 --- a/c++17.patch +++ /dev/null @@ -1,142 +0,0 @@ -From ff49d71b0cdbab75f8a22717c4f88343a5961868 Mon Sep 17 00:00:00 2001 -From: Adriano dos Santos Fernandes -Date: Mon, 31 May 2021 08:55:26 -0300 -Subject: [PATCH] Set POSIX build to use C++17. - ---- - CMakeLists.txt | 4 ++-- - builds/posix/make.defaults | 2 +- - builds/posix/prefix.freebsd_amd64 | 2 +- - configure.ac | 2 +- - examples/extauth/Makefile | 2 +- - examples/interfaces/makefile | 2 +- - extern/icu/android/aarch64/config.sh | 2 +- - extern/icu/android/armv7a/config.sh | 4 ++-- - extern/icu/android/linux/config.sh | 2 +- - 9 files changed, 11 insertions(+), 11 deletions(-) - -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 620fd032af4..5f336efd611 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -206,14 +206,14 @@ if (MINGW) - set(CMAKE_STATIC_LIBRARY_PREFIX) - - add_definitions(-D_WIN32_WINNT=0x0600) -- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4 -std=c++11") -+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4 -std=c++17") - endif() - - if (UNIX) - set(OS_DIR posix) - - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") -- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -msse4 -std=c++11") -+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -msse4 -std=c++17") - - if (NOT CMAKE_CROSSCOMPILING) - set(LIB_readline readline) -diff --git a/builds/posix/prefix.freebsd_amd64 b/builds/posix/prefix.freebsd_amd64 -index f27567a2715..0736d87e935 100644 ---- a/builds/posix/prefix.freebsd_amd64 -+++ b/builds/posix/prefix.freebsd_amd64 -@@ -26,4 +26,4 @@ DEV_FLAGS=-ggdb -DFREEBSD -DAMD64 -pipe -MMD -p -fPIC -Wall -Wno-non-virtual-dto - # This file must be compiled with SSE4.2 support - %/CRC32C.o: CXXFLAGS += -msse4 - --CXXFLAGS := $(CXXFLAGS) -std=c++11 -+CXXFLAGS := $(CXXFLAGS) -std=c++17 -diff --git a/configure.ac b/configure.ac -index 9b40be43101..e4a83cf8d3b 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -899,7 +899,7 @@ dnl if 64-bit mode, then archive tool, ar, needs -X64 option - fi - - XE_SAVE_ENV() --CXXFLAGS="$CXXFLAGS -std=c++11" -+CXXFLAGS="$CXXFLAGS -std=c++17" - AC_CACHE_CHECK([whether the C++ compiler understands noexcept], [ac_cv_cxx_noexcept], [ - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[int f(int x) noexcept { return x + 1; }]], [[]])], - [ac_cv_cxx_noexcept=yes], [ac_cv_cxx_noexcept=no])]) -diff --git a/examples/extauth/Makefile b/examples/extauth/Makefile -index 9da7bbd357f..3c8b878d225 100644 ---- a/examples/extauth/Makefile -+++ b/examples/extauth/Makefile -@@ -61,7 +61,7 @@ KEYGEN_objects=$(INTERMED)/keygen.o - TCWRAP_objects=$(INTERMED)/TcWrapper.o - KEY_AUTH_objects=$(INTERMED)/ExtAuth.o - --CXXFLAGS=-std=c++11 -pthread -I$(ROOT)/include -fPIC $(TOMCRYPT_COMPILE) -+CXXFLAGS=-std=c++17 -pthread -I$(ROOT)/include -fPIC $(TOMCRYPT_COMPILE) - LDFLAGS=-pthread -L$(LIB) -Wl,-rpath,'$$ORIGIN/../lib' $(TOMCRYPT_LINK) - - LINK_LIBS=-lfbclient -ltomcrypt -ltommath -diff --git a/examples/interfaces/makefile b/examples/interfaces/makefile -index 153c3d558dc..b65dba90a7d 100644 ---- a/examples/interfaces/makefile -+++ b/examples/interfaces/makefile -@@ -33,7 +33,7 @@ FBCLIENT = $(FIREBIRD)/lib/libfbclient.so - # General Compiler and linker Defines for Linux - # --------------------------------------------------------------------- - CXX = c++ --CXXFLAGS= -c -Wall -g3 -std=c++11 -fno-rtti $(INCLUDE) -+CXXFLAGS= -c -Wall -g3 -std=c++17 -fno-rtti $(INCLUDE) - RM = rm -f - - # -diff --git a/extern/icu/android/aarch64/config.sh b/extern/icu/android/aarch64/config.sh -index 51ef623a3c5..f464d930ec2 100755 ---- a/extern/icu/android/aarch64/config.sh -+++ b/extern/icu/android/aarch64/config.sh -@@ -18,7 +18,7 @@ - --enable-dyload \ - --with-cross-build=$CROSS_BUILD_DIR \ - CFLAGS='-Os' \ -- CXXFLAGS='--std=c++11' \ -+ CXXFLAGS='--std=c++17' \ - LDFLAGS='-static-libstdc++' \ - CC=aarch64-linux-android24-clang \ - CXX=aarch64-linux-android24-clang++ \ -diff --git a/extern/icu/android/armv7a/config.sh b/extern/icu/android/armv7a/config.sh -index fe1bd037456..0e458c690e7 100755 ---- a/extern/icu/android/armv7a/config.sh -+++ b/extern/icu/android/armv7a/config.sh -@@ -18,10 +18,10 @@ - --enable-dyload \ - --with-cross-build=$CROSS_BUILD_DIR \ - CFLAGS='-Os -march=armv7-a -mfloat-abi=softfp -mfpu=neon' \ -- CXXFLAGS='--std=c++11 -march=armv7-a -mfloat-abi=softfp -mfpu=neon' \ -+ CXXFLAGS='--std=c++17 -march=armv7-a -mfloat-abi=softfp -mfpu=neon' \ - LDFLAGS='-static-libstdc++ -march=armv7-a -Wl,--fix-cortex-a8' \ - CC=arm-linux-androideabi-clang \ - CXX=arm-linux-androideabi-clang++ \ - AR=arm-linux-androideabi-ar \ - RANLIB=arm-linux-androideabi-ranlib \ -- --with-data-packaging=archive -\ No newline at end of file -+ --with-data-packaging=archive -diff --git a/extern/icu/android/linux/config.sh b/extern/icu/android/linux/config.sh -index a8b56024aae..6e7d9c5f5c8 100755 ---- a/extern/icu/android/linux/config.sh -+++ b/extern/icu/android/linux/config.sh -@@ -1,7 +1,7 @@ - #!/bin/sh - ../source/runConfigureICU Linux --prefix=$PWD/prebuilt \ - CFLAGS="-Os" \ -- CXXFLAGS="--std=c++11" \ -+ CXXFLAGS="--std=c++17" \ - --enable-static \ - --enable-shared=no \ - --enable-extras=no \ ---- Firebird-4.0.6.3221-0/builds/posix/make.defaults~ 2025-07-14 02:27:01.000000000 -0500 -+++ Firebird-4.0.6.3221-0/builds/posix/make.defaults 2025-09-25 08:37:36.864575311 -0500 -@@ -104,7 +104,7 @@ - #____________________________________________________________________________ - - # Global c++ flags: firebird needs no RTTI, choose build standard, make it build with icu-76.1 --PLUSPLUS_FLAGS:= -fno-rtti -std=c++11 -DU_SHOW_CPLUSPLUS_API=0 -DU_SHOW_CPLUSPLUS_HEADER_API=0 -+PLUSPLUS_FLAGS:= -fno-rtti -std=c++17 -DU_SHOW_CPLUSPLUS_API=0 -DU_SHOW_CPLUSPLUS_HEADER_API=0 - - # If this is defined then we use special rules useful for developers only - IsDeveloper = @DEVEL_FLG@ diff --git a/firebird.spec b/firebird.spec index 3521f4a..a98162d 100644 --- a/firebird.spec +++ b/firebird.spec @@ -1,7 +1,7 @@ -%global upversion 4.0.6.3221 +%global upversion 5.0.3.1683 %global pkgversion Firebird-%{upversion}-0 -%global major 4.0 +%global major 5.0 %global _hardened_build 1 # firebird is mis-compiled when LTO is enabled. A root # cause analysis has not yet been completed. Reported upstream. @@ -17,7 +17,7 @@ Summary: SQL relational database management system License: Interbase-1.0 URL: http://www.firebirdsql.org/ -Source0: https://github.com/FirebirdSQL/firebird/releases/download/v4.0.6/%{pkgversion}.tar.xz +Source0: https://github.com/FirebirdSQL/firebird/releases/download/v5.0.3/%{pkgversion}-source.tar.xz Source1: firebird-logrotate Source2: README.Fedora Source3: firebird.service @@ -31,8 +31,6 @@ Patch203: no-copy-from-icu.patch Patch205: cloop-honour-build-flags.patch # from upstream -Patch301: c++17.patch -Patch302: noexcept.patch Patch401: btyacc-honour-build-flags.patch # not yet upstream @@ -55,6 +53,7 @@ BuildRequires: make BuildRequires: libtomcrypt-devel BuildRequires: unzip BuildRequires: sed +BuildRequires: cmake Requires(postun): /usr/sbin/userdel Requires(postun): /usr/sbin/groupdel @@ -63,19 +62,6 @@ Requires: libfbclient2 = %{version}-%{release} Requires: libib-util = %{version}-%{release} Requires: %{name}-utils = %{version}-%{release} -Obsoletes: firebird-arch < 4.0 -Obsoletes: firebird-filesystem < 4.0 -Obsoletes: firebird-classic-common < 4.0 -Obsoletes: firebird-classic < 4.0 -Obsoletes: firebird-superclassic < 4.0 -Obsoletes: firebird-superserver < 4.0 -Conflicts: firebird-arch < 4.0 -Conflicts: firebird-filesystem < 4.0 -Conflicts: firebird-classic-common < 4.0 -Conflicts: firebird-classic < 4.0 -Conflicts: firebird-superclassic < 4.0 -Conflicts: firebird-superserver < 4.0 - %description Firebird is a relational database offering many ANSI SQL standard @@ -117,9 +103,6 @@ in production systems, under a variety of names, since 1981. %package -n libfbclient2 Summary: Firebird SQL server client library -Obsoletes: firebird-libfbclient < 4.0 -Conflicts: firebird-libfbclient < 4.0 -Obsoletes: firebird-libfbembed < 4.0 %description -n libfbclient2 Shared client library for Firebird SQL server. @@ -192,12 +175,10 @@ in production systems, under a variety of names, since 1981. %prep -%setup -q -n %{pkgversion} +%setup -q -n %{pkgversion}-source %patch -P101 -p1 %patch -P203 -p1 %patch -P205 -p1 -%patch -P301 -p1 -%patch -P302 -p1 %patch -P401 -p1 %patch -P501 -p1 @@ -316,8 +297,7 @@ fi %dir %attr(0700,%{name},%{name}) %{_localstatedir}/lib/%{name}/data %dir %attr(0755,%{name},%{name}) %{_localstatedir}/lib/%{name}/system %dir %attr(0755,%{name},%{name}) %{_localstatedir}/lib/%{name}/tzdata -%attr(0600,firebird,firebird) %config(noreplace) %{_localstatedir}/lib/%{name}/secdb/security4.fdb -%attr(0644,firebird,firebird) %{_localstatedir}/lib/%{name}/system/help.fdb +%attr(0600,firebird,firebird) %config(noreplace) %{_localstatedir}/lib/%{name}/secdb/security5.fdb %attr(0644,firebird,firebird) %{_localstatedir}/lib/%{name}/system/firebird.msg %attr(0644,firebird,firebird) %{_localstatedir}/lib/%{name}/tzdata/*.res %ghost %dir %attr(0775,%{name},%{name}) /run/%{name} @@ -338,7 +318,8 @@ fi %files -n libfbclient2 -%{_libdir}/libfbclient.so.* +%{_libdir}/libfbclient.so.2 +%{_libdir}/libfbclient.so.%{major}* %files -n libfbclient2-devel @@ -366,7 +347,6 @@ fi %{_bindir}/gsec %{_bindir}/isql-fb %{_bindir}/nbackup -%{_bindir}/qli %{_bindir}/gsplit @@ -376,6 +356,9 @@ fi %changelog +* Fri Sep 26 2025 Gwyn Ciesla - 5.0.3.1683-1 +- 5.0.3.1683 + * Thu Sep 25 2025 Gwyn Ciesla - 4.0.6.3221-1 - 4.0.6.3221 diff --git a/noexcept.patch b/noexcept.patch deleted file mode 100644 index f1a1f48..0000000 --- a/noexcept.patch +++ /dev/null @@ -1,664 +0,0 @@ -From a999f35f0fad27798fdc88a3f5cdf2e3e9041594 Mon Sep 17 00:00:00 2001 -From: Adriano dos Santos Fernandes -Date: Mon, 31 May 2021 08:55:26 -0300 -Subject: [PATCH] Replace FB_NOTHROW by noexcept and remove FB_THROW. - ---- - src/common/classes/alloc.cpp | 128 +++++++++++++++++------------------ - src/common/classes/alloc.h | 74 ++++++++------------ - 2 files changed, 94 insertions(+), 108 deletions(-) - -diff --git a/src/common/classes/alloc.cpp b/src/common/classes/alloc.cpp -index 1bd6ad4f09d..ee91ab89df8 100644 ---- a/src/common/classes/alloc.cpp -+++ b/src/common/classes/alloc.cpp -@@ -68,19 +68,19 @@ - #define VALGRIND_FIX_IT // overrides suspicious valgrind behavior - #endif // USE_VALGRIND - --void* operator new(size_t s ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) -+void* operator new(size_t s ALLOC_PARAMS) - { - return MemoryPool::globalAlloc(s ALLOC_PASS_ARGS); - } --void* operator new[](size_t s ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) -+void* operator new[](size_t s ALLOC_PARAMS) - { - return MemoryPool::globalAlloc(s ALLOC_PASS_ARGS); - } --void operator delete(void* mem ALLOC_PARAMS) FB_NOTHROW -+void operator delete(void* mem ALLOC_PARAMS) noexcept - { - MemoryPool::globalFree(mem); - } --void operator delete[](void* mem ALLOC_PARAMS) FB_NOTHROW -+void operator delete[](void* mem ALLOC_PARAMS) noexcept - { - MemoryPool::globalFree(mem); - } -@@ -109,7 +109,7 @@ static const int GUARD_BYTES = 0; - #endif - - template --T absVal(T n) FB_NOTHROW -+T absVal(T n) noexcept - { - return n < 0 ? -n : n; - } -@@ -160,7 +160,7 @@ struct FailedBlock - FailedBlock* failedList = NULL; - #endif - --void corrupt(const char* text) FB_NOTHROW -+void corrupt(const char* text) noexcept - { - #ifdef DEV_BUILD - fprintf(stderr, "%s\n", text); -@@ -377,7 +377,7 @@ class MemHeader - - #ifdef MEM_DEBUG - void print_contents(bool used, FILE* file, bool used_only, -- const char* filter_path, const size_t filter_len) FB_NOTHROW -+ const char* filter_path, const size_t filter_len) noexcept - { - if (used || !used_only) - { -@@ -406,7 +406,7 @@ class MemHeader - } - #endif - -- void validate(MemPool* p, StatInt& vUse) FB_NOTHROW -+ void validate(MemPool* p, StatInt& vUse) noexcept - { - if (p == pool && !isExtent()) - vUse += getSize(); -@@ -461,7 +461,7 @@ class MemBaseHunk - } - - public: -- void validate(MemPool* pool, size_t hdr, StatInt& vMap, StatInt& vUse) FB_NOTHROW -+ void validate(MemPool* pool, size_t hdr, StatInt& vMap, StatInt& vUse) noexcept - { - if (length >= DEFAULT_ALLOCATION) - { -@@ -526,7 +526,7 @@ class MemSmallHunk : public MemBaseHunk - - #ifdef MEM_DEBUG - void print_contents(FILE* file, MemPool* pool, bool used_only, -- const char* filter_path, const size_t filter_len) FB_NOTHROW -+ const char* filter_path, const size_t filter_len) noexcept - { - UCHAR* m = ((UCHAR*) this) + hdrSize(); - fprintf(file, "Small hunk %p: memory=[%p:%p) spaceRemaining=%" SIZEFORMAT " length=%" SIZEFORMAT "\n", -@@ -598,7 +598,7 @@ class MemMediumHunk : public MemBaseHunk - - #ifdef MEM_DEBUG - void print_contents(FILE* file, MemPool* pool, bool used_only, -- const char* filter_path, const size_t filter_len) FB_NOTHROW -+ const char* filter_path, const size_t filter_len) noexcept - { - UCHAR* m = ((UCHAR*) this) + hdrSize(); - fprintf(file, "Medium hunk %p: memory=[%p:%p) spaceRemaining=%" SIZEFORMAT " length=%" SIZEFORMAT "\n", -@@ -630,7 +630,7 @@ class MemBigHunk - - #ifdef MEM_DEBUG - void print_contents(FILE* file, MemPool* pool, bool used_only, -- const char* filter_path, const size_t filter_len) FB_NOTHROW -+ const char* filter_path, const size_t filter_len) noexcept - { - fprintf(file, "Big hunk %p: memory=%p length=%" SIZEFORMAT "\n", - this, block, length); -@@ -1647,7 +1647,7 @@ class FreeObjects - - ~FreeObjects(); - -- FreeObjPtr allocateBlock(MemPool* pool, size_t from, size_t& size) FB_THROW (OOM_EXCEPTION) -+ FreeObjPtr allocateBlock(MemPool* pool, size_t from, size_t& size) - { - size_t full_size = size + (from ? 0 : ListBuilder::MEM_OVERHEAD); - if (full_size > Limits::TOP_LIMIT) -@@ -1696,7 +1696,7 @@ class FreeObjects - - #ifdef MEM_DEBUG - void print_contents(FILE* file, MemPool* pool, bool used_only, -- const char* filter_path, const size_t filter_len) FB_NOTHROW -+ const char* filter_path, const size_t filter_len) noexcept - { - for (Extent* ext = currentExtent; ext; ext = ext->next) - ext->print_contents(file, pool, used_only, filter_path, filter_len); -@@ -1717,7 +1717,7 @@ class FreeObjects - ListBuilder listBuilder; - Extent* currentExtent; - -- MemBlock* newBlock(MemPool* pool, unsigned slot) FB_THROW (OOM_EXCEPTION); -+ MemBlock* newBlock(MemPool* pool, unsigned slot); - }; - - -@@ -1799,26 +1799,26 @@ class MemPool - }; - #endif // VALIDATE_POOL - -- MemBlock* alloc(size_t from, size_t& length, bool flagRedirect) FB_THROW (OOM_EXCEPTION); -- void releaseBlock(MemBlock *block, bool flagDecr) FB_NOTHROW; -+ MemBlock* alloc(size_t from, size_t& length, bool flagRedirect); -+ void releaseBlock(MemBlock *block, bool flagDecr) noexcept; - - public: -- void* allocate(size_t size ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION); -- MemBlock* allocate2(size_t from, size_t& size ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION); -+ void* allocate(size_t size ALLOC_PARAMS); -+ MemBlock* allocate2(size_t from, size_t& size ALLOC_PARAMS); - - private: -- virtual void memoryIsExhausted(void) FB_THROW (OOM_EXCEPTION); -- void* allocRaw(size_t length) FB_THROW (OOM_EXCEPTION); -- static void releaseMemory(void* block, bool flagExtent) FB_NOTHROW; -- static void releaseRaw(bool destroying, void *block, size_t size, bool use_cache = true) FB_NOTHROW; -- void* getExtent(size_t from, size_t& to) FB_THROW (OOM_EXCEPTION); -+ virtual void memoryIsExhausted(void); -+ void* allocRaw(size_t length); -+ static void releaseMemory(void* block, bool flagExtent) noexcept; -+ static void releaseRaw(bool destroying, void *block, size_t size, bool use_cache = true) noexcept; -+ void* getExtent(size_t from, size_t& to); - - public: -- static void releaseExtent(bool destroying, void *block, size_t size, MemPool* pool) FB_NOTHROW; -+ static void releaseExtent(bool destroying, void *block, size_t size, MemPool* pool) noexcept; - - // pass desired size, return actual extent size - template -- void newExtent(size_t& size, Extent** linkedList) FB_THROW (OOM_EXCEPTION); -+ void newExtent(size_t& size, Extent** linkedList); - - private: - #ifdef USE_VALGRIND -@@ -1830,9 +1830,9 @@ class MemPool - - public: - static void deletePool(MemPool* pool); -- static void globalFree(void* block) FB_NOTHROW; -+ static void globalFree(void* block) noexcept; - -- static void deallocate(void* block) FB_NOTHROW; -+ static void deallocate(void* block) noexcept; - bool validate(char* buf, FB_SIZE_T size); - - // Create memory pool instance -@@ -1840,7 +1840,7 @@ class MemPool - - // Set statistics group for pool. Usage counters will be decremented from - // previously set group and added to new -- void setStatsGroup(MemoryStats& stats) FB_NOTHROW; -+ void setStatsGroup(MemoryStats& stats) noexcept; - - // Initialize and finalize global memory pool - static MemPool* init() -@@ -1893,25 +1893,25 @@ class MemPool - } - - // Statistics -- void increment_usage(size_t size) FB_NOTHROW -+ void increment_usage(size_t size) noexcept - { - stats->increment_usage(size); - used_memory += size; - } - -- void decrement_usage(size_t size) FB_NOTHROW -+ void decrement_usage(size_t size) noexcept - { - stats->decrement_usage(size); - used_memory -= size; - } - -- void increment_mapping(size_t size) FB_NOTHROW -+ void increment_mapping(size_t size) noexcept - { - stats->increment_mapping(size); - mapped_memory += size; - } - -- void decrement_mapping(size_t size) FB_NOTHROW -+ void decrement_mapping(size_t size) noexcept - { - stats->decrement_mapping(size); - mapped_memory -= size; -@@ -1919,9 +1919,9 @@ class MemPool - - #ifdef MEM_DEBUG - // Print out pool contents. This is debugging routine -- void print_contents(FILE*, unsigned flags, const char* filter_path) FB_NOTHROW; -+ void print_contents(FILE*, unsigned flags, const char* filter_path) noexcept; - // The same routine, but more easily callable from the debugger -- void print_contents(const char* filename, unsigned flags, const char* filter_path) FB_NOTHROW; -+ void print_contents(const char* filename, unsigned flags, const char* filter_path) noexcept; - - private: - MemPool* next; -@@ -1961,7 +1961,7 @@ void DoubleLinkedList::decrUsage(MemMediumHunk* hunk, MemPool* pool) - - - template --MemBlock* FreeObjects::newBlock(MemPool* pool, unsigned slot) FB_THROW (OOM_EXCEPTION) -+MemBlock* FreeObjects::newBlock(MemPool* pool, unsigned slot) - { - size_t size = Limits::getSize(slot); - -@@ -2170,7 +2170,7 @@ MemPool::~MemPool(void) - } - - template --void MemPool::newExtent(size_t& size, Extent** linkedList) FB_THROW(OOM_EXCEPTION) -+void MemPool::newExtent(size_t& size, Extent** linkedList) - { - // No large enough block found. We need to extend the pool - void* memory = NULL; -@@ -2214,7 +2214,7 @@ MemoryPool* MemoryPool::createPool(MemoryPool* parentPool, MemoryStats& stats) - return FB_NEW_POOL(*parentPool) MemoryPool(p); - } - --void MemPool::setStatsGroup(MemoryStats& newStats) FB_NOTHROW -+void MemPool::setStatsGroup(MemoryStats& newStats) noexcept - { - MutexLockGuard guard(mutex, "MemPool::setStatsGroup"); - -@@ -2230,12 +2230,12 @@ void MemPool::setStatsGroup(MemoryStats& newStats) FB_NOTHROW - stats->increment_usage(sav_used_memory); - } - --void MemoryPool::setStatsGroup(MemoryStats& newStats) FB_NOTHROW -+void MemoryPool::setStatsGroup(MemoryStats& newStats) noexcept - { - pool->setStatsGroup(newStats); - } - --MemBlock* MemPool::alloc(size_t from, size_t& length, bool flagRedirect) FB_THROW (OOM_EXCEPTION) -+MemBlock* MemPool::alloc(size_t from, size_t& length, bool flagRedirect) - { - MutexEnsureUnlock guard(mutex, "MemPool::alloc"); - guard.enter(); -@@ -2294,7 +2294,7 @@ MemBlock* MemPool::allocate2(size_t from, size_t& size - #ifdef DEBUG_GDS_ALLOC - , const char* fileName, int line - #endif --) FB_THROW (OOM_EXCEPTION) -+) - { - size_t length = from ? size : ROUNDUP(size + VALGRIND_REDZONE, roundingSize) + GUARD_BYTES; - MemBlock* memory = alloc(from, length, true); -@@ -2324,7 +2324,7 @@ MemBlock* MemPool::allocate2(size_t from, size_t& size - } - - --void* MemPool::allocate(size_t size ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) -+void* MemPool::allocate(size_t size ALLOC_PARAMS) - { - #ifdef VALIDATE_POOL - MutexLockGuard guard(mutex, "MemPool::allocate"); -@@ -2339,7 +2339,7 @@ void* MemPool::allocate(size_t size ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) - } - - --void MemPool::releaseMemory(void* object, bool flagExtent) FB_NOTHROW -+void MemPool::releaseMemory(void* object, bool flagExtent) noexcept - { - if (object) - { -@@ -2403,7 +2403,7 @@ void MemPool::releaseMemory(void* object, bool flagExtent) FB_NOTHROW - } - } - --void MemPool::releaseBlock(MemBlock* block, bool decrUsage) FB_NOTHROW -+void MemPool::releaseBlock(MemBlock* block, bool decrUsage) noexcept - { - if (block->pool != this) - corrupt("bad block released"); -@@ -2464,12 +2464,12 @@ void MemPool::releaseBlock(MemBlock* block, bool decrUsage) FB_NOTHROW - releaseRaw(pool_destroying, hunk, hunk->length, false); - } - --void MemPool::memoryIsExhausted(void) FB_THROW (OOM_EXCEPTION) -+void MemPool::memoryIsExhausted(void) - { - Firebird::BadAlloc::raise(); - } - --void* MemPool::allocRaw(size_t size) FB_THROW (OOM_EXCEPTION) -+void* MemPool::allocRaw(size_t size) - { - #ifndef USE_VALGRIND - if (size == DEFAULT_ALLOCATION) -@@ -2549,7 +2549,7 @@ void* MemPool::allocRaw(size_t size) FB_THROW (OOM_EXCEPTION) - } - - --void* MemPool::getExtent(size_t from, size_t& to) FB_THROW(OOM_EXCEPTION) // pass desired minimum size, return actual extent size -+void* MemPool::getExtent(size_t from, size_t& to) // pass desired minimum size, return actual extent size - { - #ifdef VALIDATE_POOL - MutexLockGuard guard(mutex, "MemPool::getExtent"); -@@ -2560,7 +2560,7 @@ void* MemPool::getExtent(size_t from, size_t& to) FB_THROW(OOM_EXCEPTION) // pa - } - - --void MemPool::releaseExtent(bool destroying, void* block, size_t size, MemPool* pool) FB_NOTHROW -+void MemPool::releaseExtent(bool destroying, void* block, size_t size, MemPool* pool) noexcept - { - if (size < DEFAULT_ALLOCATION) - releaseMemory(block, true); -@@ -2573,7 +2573,7 @@ void MemPool::releaseExtent(bool destroying, void* block, size_t size, MemPool* - } - - --void MemPool::releaseRaw(bool destroying, void* block, size_t size, bool use_cache) FB_NOTHROW -+void MemPool::releaseRaw(bool destroying, void* block, size_t size, bool use_cache) noexcept - { - #ifndef USE_VALGRIND - if (use_cache && (size == DEFAULT_ALLOCATION)) -@@ -2666,19 +2666,19 @@ void MemPool::releaseRaw(bool destroying, void* block, size_t size, bool use_cac - } - } - --void MemPool::globalFree(void* block) FB_NOTHROW -+void MemPool::globalFree(void* block) noexcept - { - deallocate(block); - } - --void* MemoryPool::calloc(size_t size ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) -+void* MemoryPool::calloc(size_t size ALLOC_PARAMS) - { - void* block = allocate(size ALLOC_PASS_ARGS); - memset(block, 0, size); - return block; - } - --void MemPool::deallocate(void* block) FB_NOTHROW -+void MemPool::deallocate(void* block) noexcept - { - releaseMemory(block, false); - } -@@ -2720,7 +2720,7 @@ bool MemPool::validate(char* buf, FB_SIZE_T size) - } - - #ifdef MEM_DEBUG --void MemPool::print_contents(const char* filename, unsigned flags, const char* filter_path) FB_NOTHROW -+void MemPool::print_contents(const char* filename, unsigned flags, const char* filter_path) noexcept - { - FILE* out = os_utils::fopen(filename, "w"); - if (!out) -@@ -2731,7 +2731,7 @@ void MemPool::print_contents(const char* filename, unsigned flags, const char* f - } - - // This member function can't be const because there are calls to the mutex. --void MemPool::print_contents(FILE* file, unsigned flags, const char* filter_path) FB_NOTHROW -+void MemPool::print_contents(FILE* file, unsigned flags, const char* filter_path) noexcept - { - bool used_only = flags & MemoryPool::PRINT_USED_ONLY; - -@@ -2818,7 +2818,7 @@ MemoryPool& AutoStorage::getAutoMemoryPool() - } - - #ifdef LIBC_CALLS_NEW --void* MemoryPool::globalAlloc(size_t s ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) -+void* MemoryPool::globalAlloc(size_t s ALLOC_PARAMS) - { - if (!defaultMemoryManager) - { -@@ -2831,17 +2831,17 @@ void* MemoryPool::globalAlloc(size_t s ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) - } - #endif // LIBC_CALLS_NEW - --void MemoryPool::globalFree(void* block) FB_NOTHROW -+void MemoryPool::globalFree(void* block) noexcept - { - MemPool::globalFree(block); - } - --void* MemoryPool::allocate(size_t size ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) -+void* MemoryPool::allocate(size_t size ALLOC_PARAMS) - { - return pool->allocate(size ALLOC_PASS_ARGS); - } - --void MemoryPool::deallocate(void* block) FB_NOTHROW -+void MemoryPool::deallocate(void* block) noexcept - { - pool->deallocate(block); - } -@@ -2870,14 +2870,14 @@ void MemoryPool::deletePool(MemoryPool* pool) - delete pool; - } - --void MemoryPool::print_contents(FILE* file, unsigned flags, const char* filter_path) FB_NOTHROW -+void MemoryPool::print_contents(FILE* file, unsigned flags, const char* filter_path) noexcept - { - #ifdef MEM_DEBUG - pool->print_contents(file, flags, filter_path); - #endif - } - --void MemoryPool::print_contents(const char* filename, unsigned flags, const char* filter_path) FB_NOTHROW -+void MemoryPool::print_contents(const char* filename, unsigned flags, const char* filter_path) noexcept - { - #ifdef MEM_DEBUG - pool->print_contents(filename, flags, filter_path); -@@ -2950,21 +2950,21 @@ void AutoStorage::ProbeStack() const - // in a case when we actually need "new" only with file/line information - // this version should be also present as a pair for "delete". - #ifdef DEBUG_GDS_ALLOC --void* operator new(size_t s) FB_THROW (OOM_EXCEPTION) -+void* operator new(size_t s) - { - return MemoryPool::globalAlloc(s ALLOC_ARGS); - } --void* operator new[](size_t s) FB_THROW (OOM_EXCEPTION) -+void* operator new[](size_t s) - { - return MemoryPool::globalAlloc(s ALLOC_ARGS); - } - --void operator delete(void* mem) FB_NOTHROW -+void operator delete(void* mem) noexcept - { - MemoryPool::globalFree(mem); - } - --void operator delete[](void* mem) FB_NOTHROW -+void operator delete[](void* mem) noexcept - { - MemoryPool::globalFree(mem); - } -diff --git a/src/common/classes/alloc.h b/src/common/classes/alloc.h -index 65f9afbb8a9..44d9e0ea462 100644 ---- a/src/common/classes/alloc.h -+++ b/src/common/classes/alloc.h -@@ -58,20 +58,6 @@ - - #include - --#define OOM_EXCEPTION std::bad_alloc -- --#if __cplusplus >= 201103L --#define FB_NO_THROW_SPECIFIER --#endif -- --#ifdef FB_NO_THROW_SPECIFIER --#define FB_THROW(x) --#define FB_NOTHROW noexcept --#else --#define FB_THROW(x) throw(x) --#define FB_NOTHROW throw() --#endif -- - #ifdef DEBUG_GDS_ALLOC - #define FB_NEW new(__FILE__, __LINE__) - #define FB_NEW_POOL(pool) new(pool, __FILE__, __LINE__) -@@ -106,10 +92,10 @@ class MemoryStats - ~MemoryStats() - {} - -- size_t getCurrentUsage() const FB_NOTHROW { return mst_usage.value(); } -- size_t getMaximumUsage() const FB_NOTHROW { return mst_max_usage; } -- size_t getCurrentMapping() const FB_NOTHROW { return mst_mapped.value(); } -- size_t getMaximumMapping() const FB_NOTHROW { return mst_max_mapped; } -+ size_t getCurrentUsage() const noexcept { return mst_usage.value(); } -+ size_t getMaximumUsage() const noexcept { return mst_max_usage; } -+ size_t getCurrentMapping() const noexcept { return mst_mapped.value(); } -+ size_t getMaximumMapping() const noexcept { return mst_max_mapped; } - - private: - // Forbid copying/assignment -@@ -131,7 +117,7 @@ class MemoryStats - size_t mst_max_mapped; - - // These methods are thread-safe due to usage of atomic counters only -- void increment_usage(size_t size) FB_NOTHROW -+ void increment_usage(size_t size) noexcept - { - for (MemoryStats* statistics = this; statistics; statistics = statistics->mst_parent) - { -@@ -141,7 +127,7 @@ class MemoryStats - } - } - -- void decrement_usage(size_t size) FB_NOTHROW -+ void decrement_usage(size_t size) noexcept - { - for (MemoryStats* statistics = this; statistics; statistics = statistics->mst_parent) - { -@@ -149,7 +135,7 @@ class MemoryStats - } - } - -- void increment_mapping(size_t size) FB_NOTHROW -+ void increment_mapping(size_t size) noexcept - { - for (MemoryStats* statistics = this; statistics; statistics = statistics->mst_parent) - { -@@ -159,7 +145,7 @@ class MemoryStats - } - } - -- void decrement_mapping(size_t size) FB_NOTHROW -+ void decrement_mapping(size_t size) noexcept - { - for (MemoryStats* statistics = this; statistics; statistics = statistics->mst_parent) - { -@@ -205,21 +191,21 @@ class MemoryPool - #define ALLOC_PASS_ARGS - #endif // DEBUG_GDS_ALLOC - -- void* calloc(size_t size ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION); -+ void* calloc(size_t size ALLOC_PARAMS); - - #ifdef LIBC_CALLS_NEW -- static void* globalAlloc(size_t s ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION); -+ static void* globalAlloc(size_t s ALLOC_PARAMS); - #else -- static void* globalAlloc(size_t s ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) -+ static void* globalAlloc(size_t s ALLOC_PARAMS) - { - return defaultMemoryManager->allocate(s ALLOC_PASS_ARGS); - } - #endif // LIBC_CALLS_NEW - -- void* allocate(size_t size ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION); -+ void* allocate(size_t size ALLOC_PARAMS); - -- static void globalFree(void* mem) FB_NOTHROW; -- void deallocate(void* mem) FB_NOTHROW; -+ static void globalFree(void* mem) noexcept; -+ void deallocate(void* mem) noexcept; - - // Set context pool for current thread of execution - static MemoryPool* setContextPool(MemoryPool* newPool); -@@ -229,7 +215,7 @@ class MemoryPool - - // Set statistics group for pool. Usage counters will be decremented from - // previously set group and added to new -- void setStatsGroup(MemoryStats& stats) FB_NOTHROW; -+ void setStatsGroup(MemoryStats& stats) noexcept; - - // Initialize and finalize global memory pool - static void init(); -@@ -241,9 +227,9 @@ class MemoryPool - // Print out pool contents. This is debugging routine - static const unsigned PRINT_USED_ONLY = 0x01; - static const unsigned PRINT_RECURSIVE = 0x02; -- void print_contents(FILE*, unsigned flags = 0, const char* filter_path = 0) FB_NOTHROW; -+ void print_contents(FILE*, unsigned flags = 0, const char* filter_path = 0) noexcept; - // The same routine, but more easily callable from the debugger -- void print_contents(const char* filename, unsigned flags = 0, const char* filter_path = 0) FB_NOTHROW; -+ void print_contents(const char* filename, unsigned flags = 0, const char* filter_path = 0) noexcept; - - public: - struct Finalizer -@@ -298,7 +284,7 @@ class MemoryPool - - } // namespace Firebird - --static inline Firebird::MemoryPool* getDefaultMemoryPool() FB_NOTHROW -+static inline Firebird::MemoryPool* getDefaultMemoryPool() noexcept - { - fb_assert(Firebird::MemoryPool::defaultMemoryManager); - return Firebird::MemoryPool::defaultMemoryManager; -@@ -355,36 +341,36 @@ class SubsystemContextPoolHolder : public ContextPoolHolder - using Firebird::MemoryPool; - - // operators new and delete --extern void* operator new(size_t s ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION); --extern void* operator new[](size_t s ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION); --extern void operator delete(void* mem ALLOC_PARAMS) FB_NOTHROW; --extern void operator delete[](void* mem ALLOC_PARAMS) FB_NOTHROW; -+extern void* operator new(size_t s ALLOC_PARAMS); -+extern void* operator new[](size_t s ALLOC_PARAMS); -+extern void operator delete(void* mem ALLOC_PARAMS) noexcept; -+extern void operator delete[](void* mem ALLOC_PARAMS) noexcept; - - --inline void* operator new(size_t s, Firebird::MemoryPool& pool ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) -+inline void* operator new(size_t s, Firebird::MemoryPool& pool ALLOC_PARAMS) - { - return pool.allocate(s ALLOC_PASS_ARGS); - } --inline void* operator new[](size_t s, Firebird::MemoryPool& pool ALLOC_PARAMS) FB_THROW (OOM_EXCEPTION) -+inline void* operator new[](size_t s, Firebird::MemoryPool& pool ALLOC_PARAMS) - { - return pool.allocate(s ALLOC_PASS_ARGS); - } - --inline void operator delete(void* mem, Firebird::MemoryPool& pool ALLOC_PARAMS) FB_NOTHROW -+inline void operator delete(void* mem, Firebird::MemoryPool& pool ALLOC_PARAMS) noexcept - { - MemoryPool::globalFree(mem); - } --inline void operator delete[](void* mem, Firebird::MemoryPool& pool ALLOC_PARAMS) FB_NOTHROW -+inline void operator delete[](void* mem, Firebird::MemoryPool& pool ALLOC_PARAMS) noexcept - { - MemoryPool::globalFree(mem); - } - - #if __cplusplus >= 201402L --inline void operator delete(void* mem, std::size_t s ALLOC_PARAMS) FB_NOTHROW -+inline void operator delete(void* mem, std::size_t s ALLOC_PARAMS) noexcept - { - MemoryPool::globalFree(mem); - } --inline void operator delete[](void* mem, std::size_t s ALLOC_PARAMS) FB_NOTHROW -+inline void operator delete[](void* mem, std::size_t s ALLOC_PARAMS) noexcept - { - MemoryPool::globalFree(mem); - } -@@ -392,8 +378,8 @@ inline void operator delete[](void* mem, std::size_t s ALLOC_PARAMS) FB_NOTHROW - - #ifdef DEBUG_GDS_ALLOC - --extern void operator delete(void* mem) FB_NOTHROW; --extern void operator delete[](void* mem) FB_NOTHROW; -+extern void operator delete(void* mem) noexcept; -+extern void operator delete[](void* mem) noexcept; - - #endif // DEBUG_GDS_ALLOC - diff --git a/sources b/sources index 186b123..deab017 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (Firebird-4.0.6.3221-0.tar.xz) = 9d2b5970e401fb6e0eef9bd91051bfc02ee90d2388227ac0bf5230a59f434da2d89fd50ea69b5e4a817772c342b0134a06100b772a9b87de3986f39a75ced3b6 +SHA512 (Firebird-5.0.3.1683-0-source.tar.xz) = 3b1d075ced4dfcf099723f06a8a18ac6821aa9fd3c0c9919f44b4bb7126390436dc1a9f61369f0dd7401af5bbac82dff02edf28555046c89cbe33657e26fd937