From a14fc2896cbb879c12944c6a1d97d6f618b32ab9 Mon Sep 17 00:00:00 2001
From: Alexey Sheplyakov <asheplyakov@altlinux.org>
Date: Tue, 10 Dec 2019 12:20:50 +0400
Subject: [PATCH] numeric, ex: added constructors taking `long long`. Fixes
 MinGW64 build

Sometimes GiNaC consturcts expressions from std::size_t.
For instance, in ginac/inifcns_nstdsums.cpp:2950:

    return unify(pow(/* some H here */, parameter.nops()));

On 64-bit windows std::size_t is `unsigned long long` (64 bit).
However there is no ex constructor taking (unsigned) long long.
Thus the compiler complains:

/home/asheplyakov/work/ginac/ginac/inifcns_nstdsums.cpp:2950:99:   required from here
/home/asheplyakov/work/ginac/ginac/power.h:123:35: error: call of overloaded 'ex(const long long unsigned int&)' is ambiguous
  return dynallocate<power>(ex(b), ex(e));
                                   ^~~~~
In file included from /home/asheplyakov/work/ginac/ginac/numeric.h:27:0,
                 from /home/asheplyakov/work/ginac/ginac/inifcns.h:26,
                 from /home/asheplyakov/work/ginac/ginac/inifcns_nstdsums.cpp:67:
/home/asheplyakov/work/ginac/ginac/ex.h:294:1: note: candidate: GiNaC::ex::ex(double)
 ex::ex(double const d) : bp(construct_from_double(d))
 ^~
/home/asheplyakov/work/ginac/ginac/ex.h:288:1: note: candidate: GiNaC::ex::ex(long unsigned int)
 ex::ex(unsigned long i) : bp(construct_from_ulong(i))
 ^~
/home/asheplyakov/work/ginac/ginac/ex.h:282:1: note: candidate: GiNaC::ex::ex(long int)
 ex::ex(long i) : bp(construct_from_long(i))
 ^~
/home/asheplyakov/work/ginac/ginac/ex.h:276:1: note: candidate: GiNaC::ex::ex(unsigned int)
 ex::ex(unsigned int i) : bp(construct_from_uint(i))
 ^~
/home/asheplyakov/work/ginac/ginac/ex.h:270:1: note: candidate: GiNaC::ex::ex(int)
 ex::ex(int i) : bp(construct_from_int(i))
 ^~
/home/asheplyakov/work/ginac/ginac/ex.h:72:7: note: candidate: GiNaC::ex::ex(const GiNaC::ex&)
 class ex {
       ^~
/home/asheplyakov/work/ginac/ginac/ex.h:72:7: note: candidate: GiNaC::ex::ex(GiNaC::ex&&)
ginac/CMakeFiles/ginac.dir/build.make:340: recipe for target 'ginac/CMakeFiles/ginac.dir/inifcns_nstdsums.cpp.obj' failed

This patch adds ex and numeric constructors taking `long long`
and `unsigned long long`.

P.S.

On Fri May 4 23:38:05 CEST 2018, Richard Kreckel wrote:

> So on Windows, where unsigned int is the same as unsigned long,
> the two existing overloads of numeric ctor are ambiguous. Bummer.

On i386 (Linux and Windows) unsigned int is also the same as
unsigned long, and there are no ambiguities.
The above mentionded code compiles just fine on i386 since std::size_t
is the same as unsigned long and there's ctor taking unsigned long.
---
 ginac/ex.cpp      | 20 +++++++++++++++++++-
 ginac/ex.h        | 16 ++++++++++++++++
 ginac/numeric.cpp | 11 +++++++++++
 ginac/numeric.h   |  2 ++
 4 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/ginac/ex.cpp b/ginac/ex.cpp
index 73a3ba79..11ae077e 100644
--- a/ginac/ex.cpp
+++ b/ginac/ex.cpp
@@ -530,7 +530,25 @@ basic & ex::construct_from_ulong(unsigned long i)
 		return dynallocate<numeric>(i);
 	}
 }
-	
+
+basic & ex::construct_from_longlong(long long i)
+{
+	if (i >= -12 && i <= 12) {
+		return construct_from_int(static_cast<int>(i));
+	} else {
+		return dynallocate<numeric>(i);
+	}
+}
+
+basic & ex::construct_from_ulonglong(unsigned long long i)
+{
+	if (i <= 12) {
+		return construct_from_uint(static_cast<unsigned>(i));
+	} else {
+		return dynallocate<numeric>(i);
+	}
+}
+
 basic & ex::construct_from_double(double d)
 {
 	return dynallocate<numeric>(d);
diff --git a/ginac/ex.h b/ginac/ex.h
index dd3cfe05..b173650a 100644
--- a/ginac/ex.h
+++ b/ginac/ex.h
@@ -87,6 +87,8 @@ public:
 	ex(unsigned int i);
 	ex(long i);
 	ex(unsigned long i);
+	ex(long long i);
+	ex(unsigned long long i);
 	ex(double const d);
 
 	/** Construct ex from string and a list of symbols. The input grammar is
@@ -236,6 +238,8 @@ private:
 	static basic & construct_from_uint(unsigned int i);
 	static basic & construct_from_long(long i);
 	static basic & construct_from_ulong(unsigned long i);
+	static basic & construct_from_ulonglong(unsigned long long i);
+	static basic & construct_from_longlong(long long i);
 	static basic & construct_from_double(double d);
 	static ptr<basic> construct_from_string_and_lst(const std::string &s, const ex &l);
 	void makewriteable();
@@ -290,6 +294,18 @@ ex::ex(unsigned long i) : bp(construct_from_ulong(i))
 	GINAC_ASSERT(bp->flags & status_flags::dynallocated);
 }
 
+inline
+ex::ex(long long i) : bp(construct_from_longlong(i))
+{
+	GINAC_ASSERT(bp->flags & status_flags::dynallocated);
+}
+
+inline
+ex::ex(unsigned long long i) : bp(construct_from_ulonglong(i))
+{
+	GINAC_ASSERT(bp->flags & status_flags::dynallocated);
+}
+
 inline
 ex::ex(double const d) : bp(construct_from_double(d))
 {
diff --git a/ginac/numeric.cpp b/ginac/numeric.cpp
index 4cfd7e4a..1f87f422 100644
--- a/ginac/numeric.cpp
+++ b/ginac/numeric.cpp
@@ -141,6 +141,17 @@ numeric::numeric(unsigned long i)
 	setflag(status_flags::evaluated | status_flags::expanded);
 }
 
+numeric::numeric(long long i)
+{
+	value = cln::cl_I(i);
+	setflag(status_flags::evaluated | status_flags::expanded);
+}
+
+numeric::numeric(unsigned long long i)
+{
+	value = cln::cl_I(i);
+	setflag(status_flags::evaluated | status_flags::expanded);
+}
 
 /** Constructor for rational numerics a/b.
  *
diff --git a/ginac/numeric.h b/ginac/numeric.h
index da41bd32..654926d8 100644
--- a/ginac/numeric.h
+++ b/ginac/numeric.h
@@ -90,6 +90,8 @@ public:
 	numeric(unsigned int i);
 	numeric(long i);
 	numeric(unsigned long i);
+	numeric(long long i);
+	numeric(unsigned long long i);
 	numeric(long numer, long denom);
 	numeric(double d);
 	numeric(const char *);
-- 
2.17.1

