Re: Has there been historical work done to investigate small integer optimization?

2024-02-11 Thread Marc Glisse

On Sun, 11 Feb 2024, Stefan Koch wrote:


There is a fair amount of recent activity in the c++ world to optimize for
speed by minimizing processor cache misses.  One example is for in the
std::string class there is a concept of "short string optimization".  What
this does is that for shorter strings the data is stored in the string
class itself without need for dynamic memory allocation.   This has two
advantages: it does not need to make a call to dynamic memory allocation,
and the string data is in the same location as the meta data, and so only
in one cache fetch.  Both of which are potentially slow.

When I was looking at the implementation the _mp_d member of __mpz_struct
is 8 bytes, which is also the size of a single limb entry.  (I suspect that
this is common on recent systems, but it is probably not be universal.)  My
thought was that if _mp_alloc is one, then we have one limb needed.  In
that case, the space of _mp_d could serve as the limb itself instead of the
pointer to the limb.  That would eliminate dynamic memory allocation for
all integers under 2^64.

I was coming at this from a computer algebra system standpoint.  I think
(but I really don't know), that much of the arithmetic that is done is done
with integers under 2^64, and so those systems may be much faster if gmp
had a small integer optimization.

This approach will add a check when accessing the limb data for all
accesses but will save accessing potentially non cpu cache data for small
integers.  It may turn out that the small delay is not so noticeable for
large numbers, and the optimization for small numbers makes a large
difference for small numbers.

A second thought is to do the arithmetic if the sources are and result will
fit in a single limb with inline functions or macros. That would eliminate
the function call entirely for small numbers.  It would make the code
longer, and add additional overhead for when the integers are not short,
but is it not clear how much of an impact that is for lager numbers.

Anyway, I know you guys take performance very seriously, so I was wondering
if you had experience with this?
1. Is there real potential for performance improvements in cas systems if
gmp has a small integer optimization?
2. Have you looked at an approach like this in the past?  and if so what
have you found?
3. If you think this is something worth pursuing, do you have any advice?


Several software already wrap GMP using this kind of strategy: a "number" is 
either a 63-bit integer or a pointer to a GMP big integer (this is 
determined by one bit), operations on 63-bit integers are inline.


What is efficient depends on your use case. If you want to use the same 
integer type everywhere, you should definitely optimize for the small 
case. If you use separate types for small vs big, and big integers are 
always big, then you should optimize for the big case.


There is also an intermediate size where numbers occupy just a few limbs, 
where allocation can still dominate computation, and a small-string-like 
optimization can help significantly (see Boost.Multiprecision's cpp_int). 
Again, a one-size-fits-all seems optimistic.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Requests from Microsoft IP Addresses

2023-06-18 Thread Marc Glisse

On Sun, 18 Jun 2023, Niels Möller wrote:


It would be reasonable for any project that wants to pull GMP sources
from 100 machines very often to set up their own mirror, do
*incremental* updates of the mirror rather than a full clone, and do
that at most a few times a day.


I am not disagreeing with that (see my last sentence).


But I don't think it's the GMP project's responsibility to provide such
a mirror.


It shouldn't be your responsibility to not get robbed, yet you lock your 
door when you are away.


I am trying to be realistic. The current trend is an ever more wasteful 
use of resources in continuous integration (why would people bother 
optimizing this as long as it works?). A mirror is probably less work than 
what it saves, and pushes the problem to someone else (github).


Of course that's assuming the current issue is indeed a very wasteful CI 
setup.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Requests from Microsoft IP Addresses

2023-06-17 Thread Marc Glisse
One thing that should be doable is set up a mirror of GMP's repository on 
github, and advertise that one for CI purposes. Any user could do that 
(there are already a few), but if it was advertised on the GMP website, it 
would be more likely to be used by more people. Of course it would be good 
if people didn't set up their CI in such a wasteful way, but the trend 
doesn't make me very optimistic.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: C++ long long

2022-04-19 Thread Marc Glisse
If nobody complains and I don't see something horribly flawed in the 
patch, I am going to push this version, which for now only adds 
initialization and assignment from long long when in C++11 mode (I expect 
we will remove support for C++ compilers without long long in the next 
release, but for now it is conditional).


It doesn't add interoperability for other operations, so z+1LL will still 
fail. Handling all operations can require a lot more code, depending on 
how it is done, and can be done later. Conversions are already quite 
useful for users, in particular they are sufficient to let Eigen use 
mpq_class as a custom scalar type on windows.


--
Marc Glissediff -r 88e4445a72d1 doc/gmp.texi
--- a/doc/gmp.texi	Mon Apr 18 16:19:20 2022 +0200
+++ b/doc/gmp.texi	Tue Apr 19 20:06:00 2022 +0200
@@ -6919,7 +6919,7 @@
 
 @deftypefun {} mpz_class::mpz_class (type @var{n})
 Construct an @code{mpz_class}.  All the standard C++ types may be used, except
-@code{long long} and @code{long double}, and all the GMP C++ classes can be
+@code{long long} (in C++98) and @code{long double}, and all the GMP C++ classes can be
 used, although conversions from @code{mpq_class} and @code{mpf_class} are
 @code{explicit}.  Any necessary conversion follows the corresponding C
 function, for example @code{double} follows @code{mpz_set_d}
@@ -7026,7 +7026,7 @@
 Construct an @code{mpq_class}.  The initial value can be a single value of any
 type (conversion from @code{mpf_class} is @code{explicit}), or a pair of
 integers (@code{mpz_class} or standard C++ integer types) representing a
-fraction, except that @code{long long} and @code{long double} are not
+fraction, except that @code{long long} (in C++98) and @code{long double} are not
 supported.  For example,
 
 @example
@@ -7124,7 +7124,7 @@
 @deftypefun {} mpf_class::mpf_class (type @var{op})
 @deftypefunx {} mpf_class::mpf_class (type @var{op}, mp_bitcnt_t @var{prec})
 Construct an @code{mpf_class}.  Any standard C++ type can be used, except
-@code{long long} and @code{long double}, and any of the GMP C++ classes can be
+@code{long long} (in C++98) and @code{long double}, and any of the GMP C++ classes can be
 used.
 
 If @var{prec} is given, the initial precision is that value, in bits.  If
diff -r 88e4445a72d1 gmpxx.h
--- a/gmpxx.h	Mon Apr 18 16:19:20 2022 +0200
+++ b/gmpxx.h	Tue Apr 19 20:06:00 2022 +0200
@@ -106,6 +106,23 @@
 // Note: we know the high bit of l is 0 so we could do slightly better
 }
 
+#if __GMPXX_USE_CXX11
+inline void __mpz_set_ull_safe(mpz_ptr z, unsigned long long l)
+{
+# if ULONG_MAX == ULLONG_MAX
+  __mpz_set_ui_safe(z, static_cast(l));
+# else
+  mp_limb_t *p = z->_mp_d;
+  while (l != 0)
+  {
+*p++ = static_cast(l & GMP_NUMB_MASK);
+l >>= GMP_NUMB_BITS;
+  }
+  z->_mp_size = p - z->_mp_d;
+# endif
+}
+#endif
+
 // Fake temporary variables
 #define __GMPXX_TMPZ_UI			\
   mpz_t temp;\
@@ -154,6 +171,13 @@
   return l >= 0 ? static_cast(l)
 	  : -static_cast(l);
 }
+#if __GMPXX_USE_CXX11
+inline unsigned long long __gmpxx_abs_ull (signed long long l)
+{
+  return l >= 0 ? static_cast(l)
+ : -static_cast(l);
+}
+#endif
 
 / Function objects /
 /* Any evaluation of a __gmp_expr ends up calling one of these functions
@@ -1511,6 +1535,35 @@
   inline __gmp_expr & fun();  \
   inline __gmp_expr fun(int);
 
+#if __GMPXX_USE_CXX11
+#define __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS		\
+  __gmp_expr(signed char c) { init_si(c); }		\
+  __gmp_expr(unsigned char c) { init_ui(c); }		\
+  __gmp_expr(signed int i) { init_si(i); }		\
+  __gmp_expr(unsigned int i) { init_ui(i); }		\
+  __gmp_expr(signed short int s) { init_si(s); }	\
+  __gmp_expr(unsigned short int s) { init_ui(s); }	\
+  __gmp_expr(signed long int l) { init_si(l); }		\
+  __gmp_expr(unsigned long int l) { init_ui(l); }	\
+  __gmp_expr(signed long long l) { init_sll(l); }	\
+  __gmp_expr(unsigned long long l) { init_ull(l); }	\
+  __gmp_expr(float f) { init_d(f); }			\
+  __gmp_expr(double d) { init_d(d); }
+
+#define __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS		\
+  __gmp_expr & operator=(signed char c) { assign_si(c); return *this; } \
+  __gmp_expr & operator=(unsigned char c) { assign_ui(c); return *this; } \
+  __gmp_expr & operator=(signed int i) { assign_si(i); return *this; } \
+  __gmp_expr & operator=(unsigned int i) { assign_ui(i); return *this; } \
+  __gmp_expr & operator=(signed short int s) { assign_si(s); return *this; } \
+  __gmp_expr & operator=(unsigned short int s) { assign_ui(s); return *this; } \
+  __gmp_expr & operator=(signed long int l) { assign_si(l); return *this; } \
+  __gmp_expr & operator=(unsigned long int l) { assign_ui(l); return *this; } \
+  __gmp_expr & operator=(signed long long l) { assign_sll(l); return *this; } \
+  __gmp_expr & operator=(unsigned long long l) { assign_ull(l); return *this; } \
+  __gmp_expr & operator=(float f) { assign_d(f); return *this; } \
+  __gmp_expr & 

mpq_mul_ui

2022-01-22 Thread Marc Glisse

Hello,

What would you think of adding mpq_mul_ui, mpq_div_ui, mpq_ui_div, and 
also the _z versions?


Something like (untested)

void
mpq_mul_ui (mpq_ptr prod, mpq_srcptr op, unsigned long m)
{
  unsigned long gcd_ui;

  if (SIZ (NUM (op)) == 0 || m == 0)
{
  /* We special case this to simplify allocation logic; gcd(0,x) = x
 is a singular case for the allocations.  */
  SIZ (NUM (prod)) = 0;
  MPZ_NEWALLOC (DEN (prod), 1)[0] = 1;
  SIZ (DEN (prod)) = 1;
  return;
}

#if 0
  if (m == 1)
{
  if (prod != op)
mpq_set (prod, op);
  return;
}
#endif

  gcd_ui = mpz_gcd_ui (0, DEN (op), m);

#if 0
  if (gcd_ui == 1)
{
  mpz_mul_ui (NUM (prod), NUM (op), m);
  if (prod != op)
mpz_set (DEN (prod), DEN (op));
}
#endif

  mpz_mul_ui (NUM (prod), NUM (op), m / gcd_ui);
  mpz_divexact_ui (DEN (prod), DEN (op), gcd_ui);
  // mpz_divexact_gcd (DEN (prod), DEN (op), gcd_z);
}


mpq_add_ui is easy to emulate with mpz_addmul_ui, but mpq_mul_ui is a bit 
harder (3 operations plus the need to handle 0 explicitly).


I can add similar code directly in gmpxx.h, but I first wanted to check if 
a C version was desirable.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Doc tweak

2021-11-06 Thread Marc Glisse

Hello,

someone got confused by the text saying that all the GMP declarations are 
in gmp.h and thought the C++ class interface would be there as well, so 
I'll probably add this patch unless someone has a better proposition.


(shell seems to be missing some packages to build the doc in ps or pdf)

--- a/doc/gmp.texi  Tue Nov 02 02:02:59 2021 +0100
+++ b/doc/gmp.texi  Sat Nov 06 13:32:05 2021 +0100
@@ -1860,7 +1860,9 @@
 @cindex Include files
 @cindex @code{#include}
 All declarations needed to use GMP are collected in the include file
-@file{gmp.h}.  It is designed to work with both C and C++ compilers.
+@file{gmp.h}, except for the @ref{C++ Class Interface} which comes with its
+own separate header @file{gmpxx.h}.  @file{gmp.h} is designed to work with
+both C and C++ compilers.

 @example
 #include 
@@ -1868,7 +1870,7 @@

 @cindex @code{stdio.h}
 Note however that prototypes for GMP functions with @code{FILE *} parameters
-are only provided if @code{} is included too.
+are only provided if @code{} is included before.

 @example
 #include 
@@ -1892,9 +1894,10 @@
 @end example

 @cindex @code{libgmpxx}
-GMP C++ functions are in a separate @file{libgmpxx} library.  This is built
-and installed if C++ support has been enabled (@pxref{Build Options}).  For
-example,
+GMP C++ functions are in a separate @file{libgmpxx} library, including the
+@ref{C++ Class Interface} but also @ref{C++ Formatted Output} for regular
+GMP types.  This is built and installed if C++ support has been enabled
+(@pxref{Build Options}).  For example,

 @example
 g++ mycxxprog.cc -lgmpxx -lgmp


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: gmp-6.2.1 on Tru64 with gcc.

2021-07-16 Thread Marc Glisse

Please check the repository

https://gmplib.org/repo/gmp/rev/37cee5a85875

On Sat, 3 Jul 2021, Jay K wrote:


On OSF/1/Tru64, inttypes.h lacks uint_least32_t and gcc's stdint.h does have 
uint_least32_t.

autoconf says uint_least32_t is there because it includes stdint.h, but then:

#if HAVE_INTTYPES_H  /* for uint_least32_t */
# include 
#else<== the problem
# if HAVE_STDINT_H
#  include 
# endif
#endif

leading to:

../gmp-impl.h:233:1: error: unknown type name 'uint_least32_t'
In file included from hgcd_appr.c:35:0:
../gmp-impl.h:233:1: error: unknown type name 'uint_least32_t'

So please remove the else?
and then whitespace and comment:

diff -u gmp-impl.h.orig  gmp-impl.h
--- gmp-impl.h.orig 2021-07-03 18:23:37 -0400
+++ gmp-impl.h  2021-07-03 18:25:04 -0400
@@ -152,12 +152,12 @@
#endif
#endif

-#if HAVE_INTTYPES_H  /* for uint_least32_t */
+/* uint_least32_t can be in inttypes.h or stdint.h */
+#if HAVE_INTTYPES_H
# include 
-#else
-# if HAVE_STDINT_H
-#  include 
-# endif
+#endif
+#if HAVE_STDINT_H
+# include 
#endif

Thank you,
- Jay
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel



--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: pointers vs arrays

2021-06-11 Thread Marc Glisse

On Fri, 11 Jun 2021, Emmanuel Thomé wrote:


On Thu, Jun 10, 2021 at 03:02:25PM +0200, Marc Glisse wrote:

On Thu, 10 Jun 2021, Emmanuel Thomé wrote:

> And as it turns out, we even discussed that very documentation bit about
> three years ago (here a link to an actual patch -- original discussion
> was in may 2018).
> 
> https://gmplib.org/list-archives/gmp-devel/2019-January/005182.html


The description of mpq_numref is a bit misleading, it does not cast away
constness (as opposed to say the C function strstr), but that's not new with
your patch.

I assume that patch was covered by an assignment to the FSF?


First: a good share of the text is actually Niels's.


Ah, I didn't go far enough back to see that.

Niels, is enough of this text yours that we don't need an assignment from 
Emmanuel? Do you want to commit it yourself, or would you rather I do it?



I haven't filled a copyright assignment, based on the idea that my
contribution is in the ballpark of trivial enough changes. But I don't
object to doing the paperwork if needed.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: pointers vs arrays

2021-06-10 Thread Marc Glisse

On Thu, 10 Jun 2021, Emmanuel Thomé wrote:


And as it turns out, we even discussed that very documentation bit about
three years ago (here a link to an actual patch -- original discussion
was in may 2018).

https://gmplib.org/list-archives/gmp-devel/2019-January/005182.html


The description of mpq_numref is a bit misleading, it does not cast away 
constness (as opposed to say the C function strstr), but that's not new 
with your patch.


I assume that patch was covered by an assignment to the FSF?

Would someone object if I applied that patch, after making sure it still 
compiles?


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: pointers vs arrays

2021-06-09 Thread Marc Glisse

On Wed, 9 Jun 2021, Marco Bodrato wrote:

Il 2021-05-12 15:17 Marc Glisse ha scritto:

the latest version of gcc has a new (questionable) warning that
complains if a function is declared as taking a mpz_t parameter and
redeclared as taking mpz_ptr, or the reverse.

We might as well be consistent and use pointers everywhere, as in the
attached patch. Does someone disagree?


Maybe this will move the warnings on the users side :-/


Maybe, but only if people redeclare the GMP functions themselves in 
addition to including gmp.h, which looks like a strange idea.


I wondered about using gmp_randstate_t instead of gmp_randstate_ptr to 
avoid changing gmp.h, but that would not be consistent with mpz_t, etc. Or 
maybe change all prototypes to use mpz_t instead of mpz_ptr...


To me, the most sensible option for users remains disabling this warning 
globally.


By the way, I think that also the documentation should be updated 
accordingly.


We have never documented mpz_ptr/mpz_srcptr, my patch does not change this 
discrepancy. Maybe this is a new motivation to document it, but that seems 
like a lot of boring work...


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


C++ long long

2021-06-06 Thread Marc Glisse

Hello,

I am tempted to go with something like the attached patch to support long 
long in gmpxx.h. (the patch is not quite ready)
Essentially, it adds a way to build mpz_class from long long, and for all 
other operations, long long is converted to long if it fits and to 
mpz_class otherwise. So z+1LL is turned into z+1L on x86_64-linux and 
z+mpz_class(1LL) on win64.


A possible improvement would be to delay the replacement until evaluation, 
so we can check at runtime if the long long fits a long, instead of just 
checking if the 2 types have the same size. It would also allow using an 
mpz_t pointing to a local buffer to avoid a dynamic allocation. It is a 
bit more code though.


I am tempted to require a compiler that supports long long for gmpxx.h. We 
could require C++11 for that, but just long long is a much weaker 
requirement. I currently use a fake type for C++98 to avoid repeating #if 
all over the place.


Of course this can be updated once GMP itself adds support for long long, 
but I think it can be merged first without causing trouble.


--
Marc Glissediff -r 632506b00743 gmpxx.h
--- a/gmpxx.h	Sat May 08 19:34:05 2021 +0200
+++ b/gmpxx.h	Sun Jun 06 23:37:17 2021 +0200
@@ -65,8 +65,18 @@
 #if __GMPXX_USE_CXX11
 #define __GMPXX_NOEXCEPT noexcept
 #include  // for common_type
+typedef signed long long int __gmp_slli;
+typedef unsigned long long int __gmp_ulli;
 #else
 #define __GMPXX_NOEXCEPT
+// Fake long long to avoid too many #ifdef
+struct __gmp_slli { bool operator<(int) const; };
+struct __gmp_ulli {
+  __gmp_ulli(__gmp_slli);
+  operator unsigned long() const;
+  __gmp_ulli operator-() const;
+  __gmp_ulli operator>>(int) const;
+};
 #endif
 
 // Max allocations for plain types when converted to GMP types
@@ -154,6 +164,11 @@
   return l >= 0 ? static_cast(l)
 	  : -static_cast(l);
 }
+inline __gmp_ulli __gmpxx_abs_ull (__gmp_slli l)
+{
+  return l < 0 ? -static_cast<__gmp_ulli>(l)
+	  : static_cast<__gmp_ulli>(l);
+}
 
 / Function objects /
 /* Any evaluation of a __gmp_expr ends up calling one of these functions
@@ -1333,6 +1348,9 @@
 template 
 class __gmp_expr;
 
+typedef __gmp_expr mpz_class;
+typedef __gmp_expr mpq_class;
+typedef __gmp_expr mpf_class;
 
 // templates for resolving expression types
 template 
@@ -1411,6 +1429,27 @@
   typedef mpf_t value_type;
 };
 
+// To reduce code bloat, signed char, short and int are cast to long
+// internally, and similarly for unsigned types. long long is cast to long if
+// that has the same size, or mpz_class otherwise.
+template ::is_signed>
+struct __gmpxx_int_canonical
+{
+  typedef mpz_class Type;
+};
+
+template 
+struct __gmpxx_int_canonical
+{
+  typedef long Type;
+};
+
+template 
+struct __gmpxx_int_canonical
+{
+  typedef unsigned long Type;
+};
+
 #if __GMPXX_USE_CXX11
 namespace std {
   template 
@@ -1449,6 +1488,8 @@
   __GMPXX_DECLARE_COMMON_TYPE(unsigned short int);
   __GMPXX_DECLARE_COMMON_TYPE(signed long int);
   __GMPXX_DECLARE_COMMON_TYPE(unsigned long int);
+  __GMPXX_DECLARE_COMMON_TYPE(__gmp_slli);
+  __GMPXX_DECLARE_COMMON_TYPE(__gmp_ulli);
   __GMPXX_DECLARE_COMMON_TYPE(float);
   __GMPXX_DECLARE_COMMON_TYPE(double);
 #undef __GMPXX_DECLARE_COMMON_TYPE
@@ -1496,6 +1537,8 @@
   __gmp_expr & fun(unsigned short int);   \
   __gmp_expr & fun(signed long int);  \
   __gmp_expr & fun(unsigned long int);\
+  __gmp_expr & fun(__gmp_slli); \
+  __gmp_expr & fun(__gmp_ulli);   \
   __gmp_expr & fun(float);\
   __gmp_expr & fun(double);   \
   /* __gmp_expr & fun(long double); */
@@ -1520,6 +1563,8 @@
   __gmp_expr(unsigned short int s) { init_ui(s); }	\
   __gmp_expr(signed long int l) { init_si(l); }		\
   __gmp_expr(unsigned long int l) { init_ui(l); }	\
+  __gmp_expr(__gmp_slli l) { init_sll(l); }	\
+  __gmp_expr(__gmp_ulli l) { init_ull(l); }	\
   __gmp_expr(float f) { init_d(f); }			\
   __gmp_expr(double d) { init_d(d); }
 
@@ -1532,6 +1577,8 @@
   __gmp_expr & operator=(unsigned short int s) { assign_ui(s); return *this; } \
   __gmp_expr & operator=(signed long int l) { assign_si(l); return *this; } \
   __gmp_expr & operator=(unsigned long int l) { assign_ui(l); return *this; } \
+  __gmp_expr & operator=(__gmp_slli l) { assign_sll(l); return *this; } \
+  __gmp_expr & operator=(__gmp_ulli l) { assign_ull(l); return *this; } \
   __gmp_expr & operator=(float f) { assign_d(f); return *this; } \
   __gmp_expr & operator=(double d) { assign_d(d); return *this; }
 
@@ -1544,22 +1591,22 @@
 static inline __gmp_expr >\
 fun(type expr);
 
-#define __GMPNS_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type)  \
-__GMPNN_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type, signed long)
-#define __GMPNU_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type)  \
-__GMPNN_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type, unsigned long)
+#define __GMPNI_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type)  \

pointers vs arrays

2021-05-12 Thread Marc Glisse

Hello,

the latest version of gcc has a new (questionable) warning that complains 
if a function is declared as taking a mpz_t parameter and redeclared as 
taking mpz_ptr, or the reverse.


We might as well be consistent and use pointers everywhere, as in the 
attached patch. Does someone disagree?


--
Marc Glissediff -r 632506b00743 gmp-h.in
--- a/gmp-h.in	Sat May 08 19:34:05 2021 +0200
+++ b/gmp-h.in	Wed May 12 15:07:25 2021 +0200
@@ -227,6 +227,8 @@
 typedef __mpf_struct *mpf_ptr;
 typedef const __mpq_struct *mpq_srcptr;
 typedef __mpq_struct *mpq_ptr;
+typedef __gmp_randstate_struct *gmp_randstate_ptr;
+typedef const __gmp_randstate_struct *gmp_randstate_srcptr;
 
 
 #if __GMP_LIBGMP_DLL
@@ -498,37 +500,37 @@
 
 /* obsolete */
 #define gmp_randinit __gmp_randinit
-__GMP_DECLSPEC void gmp_randinit (gmp_randstate_t, gmp_randalg_t, ...);
+__GMP_DECLSPEC void gmp_randinit (gmp_randstate_ptr, gmp_randalg_t, ...);
 
 #define gmp_randinit_default __gmp_randinit_default
-__GMP_DECLSPEC void gmp_randinit_default (gmp_randstate_t);
+__GMP_DECLSPEC void gmp_randinit_default (gmp_randstate_ptr);
 
 #define gmp_randinit_lc_2exp __gmp_randinit_lc_2exp
-__GMP_DECLSPEC void gmp_randinit_lc_2exp (gmp_randstate_t, mpz_srcptr, unsigned long int, mp_bitcnt_t);
+__GMP_DECLSPEC void gmp_randinit_lc_2exp (gmp_randstate_ptr, mpz_srcptr, unsigned long int, mp_bitcnt_t);
 
 #define gmp_randinit_lc_2exp_size __gmp_randinit_lc_2exp_size
-__GMP_DECLSPEC int gmp_randinit_lc_2exp_size (gmp_randstate_t, mp_bitcnt_t);
+__GMP_DECLSPEC int gmp_randinit_lc_2exp_size (gmp_randstate_ptr, mp_bitcnt_t);
 
 #define gmp_randinit_mt __gmp_randinit_mt
-__GMP_DECLSPEC void gmp_randinit_mt (gmp_randstate_t);
+__GMP_DECLSPEC void gmp_randinit_mt (gmp_randstate_ptr);
 
 #define gmp_randinit_set __gmp_randinit_set
-__GMP_DECLSPEC void gmp_randinit_set (gmp_randstate_t, const __gmp_randstate_struct *);
+__GMP_DECLSPEC void gmp_randinit_set (gmp_randstate_ptr, gmp_randstate_srcptr);
 
 #define gmp_randseed __gmp_randseed
-__GMP_DECLSPEC void gmp_randseed (gmp_randstate_t, mpz_srcptr);
+__GMP_DECLSPEC void gmp_randseed (gmp_randstate_ptr, mpz_srcptr);
 
 #define gmp_randseed_ui __gmp_randseed_ui
-__GMP_DECLSPEC void gmp_randseed_ui (gmp_randstate_t, unsigned long int);
+__GMP_DECLSPEC void gmp_randseed_ui (gmp_randstate_ptr, unsigned long int);
 
 #define gmp_randclear __gmp_randclear
-__GMP_DECLSPEC void gmp_randclear (gmp_randstate_t);
+__GMP_DECLSPEC void gmp_randclear (gmp_randstate_ptr);
 
 #define gmp_urandomb_ui __gmp_urandomb_ui
-__GMP_DECLSPEC unsigned long gmp_urandomb_ui (gmp_randstate_t, unsigned long);
+__GMP_DECLSPEC unsigned long gmp_urandomb_ui (gmp_randstate_ptr, unsigned long);
 
 #define gmp_urandomm_ui __gmp_urandomm_ui
-__GMP_DECLSPEC unsigned long gmp_urandomm_ui (gmp_randstate_t, unsigned long);
+__GMP_DECLSPEC unsigned long gmp_urandomm_ui (gmp_randstate_ptr, unsigned long);
 
 
 / Formatted output routines.  /
@@ -1008,7 +1010,7 @@
 __GMP_DECLSPEC void mpz_rootrem (mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int);
 
 #define mpz_rrandomb __gmpz_rrandomb
-__GMP_DECLSPEC void mpz_rrandomb (mpz_ptr, gmp_randstate_t, mp_bitcnt_t);
+__GMP_DECLSPEC void mpz_rrandomb (mpz_ptr, gmp_randstate_ptr, mp_bitcnt_t);
 
 #define mpz_scan0 __gmpz_scan0
 __GMP_DECLSPEC mp_bitcnt_t mpz_scan0 (mpz_srcptr, mp_bitcnt_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE;
@@ -1108,10 +1110,10 @@
 __GMP_DECLSPEC void mpz_ui_pow_ui (mpz_ptr, unsigned long int, unsigned long int);
 
 #define mpz_urandomb __gmpz_urandomb
-__GMP_DECLSPEC void mpz_urandomb (mpz_ptr, gmp_randstate_t, mp_bitcnt_t);
+__GMP_DECLSPEC void mpz_urandomb (mpz_ptr, gmp_randstate_ptr, mp_bitcnt_t);
 
 #define mpz_urandomm __gmpz_urandomm
-__GMP_DECLSPEC void mpz_urandomm (mpz_ptr, gmp_randstate_t, mpz_srcptr);
+__GMP_DECLSPEC void mpz_urandomm (mpz_ptr, gmp_randstate_ptr, mpz_srcptr);
 
 #define mpz_xor __gmpz_xor
 #define mpz_eor __gmpz_xor
@@ -1457,7 +1459,7 @@
 __GMP_DECLSPEC void mpf_ui_sub (mpf_ptr, unsigned long int, mpf_srcptr);
 
 #define mpf_urandomb __gmpf_urandomb
-__GMP_DECLSPEC void mpf_urandomb (mpf_t, gmp_randstate_t, mp_bitcnt_t);
+__GMP_DECLSPEC void mpf_urandomb (mpf_ptr, gmp_randstate_ptr, mp_bitcnt_t);
 
 
 / Low level positive-integer (i.e. N) routines.  /
diff -r 632506b00743 gmp-impl.h
--- a/gmp-impl.h	Sat May 08 19:34:05 2021 +0200
+++ b/gmp-impl.h	Wed May 12 15:07:25 2021 +0200
@@ -1287,14 +1287,11 @@
   return itch;
 }
 
-typedef __gmp_randstate_struct *gmp_randstate_ptr;
-typedef const __gmp_randstate_struct *gmp_randstate_srcptr;
-
 /* Pseudo-random number generator function pointers structure.  */
 typedef struct {
-  void (*randseed_fn) (gmp_randstate_t, mpz_srcptr);
-  void (*randget_fn) (gmp_randstate_t, mp_ptr, unsigned long int);
-  void (*randclear_fn) (gmp_randstate_t);
+  void (*randseed_fn) (gmp_randstate_ptr, mpz_srcptr);
+  void (*randget_fn) (gmp_randstate_ptr, mp_ptr, unsigned long int);
+  void 

Re: strange install directory

2021-02-27 Thread Marc Glisse

On Sat, 27 Feb 2021, Paul Zimmermann wrote:


thank you all for your answers. Maybe the solution would be to check for
$prefix/lib64 (and $prefix/lib32) if we don't find libgmp in $prefix/lib.


That would help for this case. Of course, it might end up in 
$prefix/libx32 (X32 ABI on x86_64), $prefix/lib64le (some 64-bit 
little-endian ABI), $prefix/lib/$triplet (debian and derived 
distributions), etc... $prefix/*lib*/ + $prefix/lib/*/ roughly seems to 
cover it for now (I may be missing more). Or you could consider that 
people in this situation should use --with-gmp-lib and avoid guessing. I 
think it could be interesting if you asked on the autoconf list what they 
think.



(I just realized that we can bypass the lib->lib64 renaming by specifying 
libdir with an extra '/' in the name, say at the beginning or the end, 
although that doesn't solve your problem)


With recent GMP, you can also get some information with `pkg-config --libs 
gmp` (or other options than --libs), but that requires that the .pc file 
be in PKG_CONFIG_PATH, which just shifts the issue.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: strange install directory

2021-02-26 Thread Marc Glisse

On Fri, 26 Feb 2021, Niels Möller wrote:


Paul Zimmermann  writes:


on the gcc118 machine from the gcc compile farm, with gmp-6.2.1, make install
puts the libgmp.{a,so} files in $PREFIX/lib64 instead of $PREFIX/lib. Is there
any reason for that?


I don't know about GMP (and this is the first time I hear about
automake's genered install target using a different default than
libdir=${exec_prefix}/lib). Maybe a recent change in autoconf, automake,
(or possibly libtool)? But I've been doing somethignsimilar in Nettle
for years, and the problem case I want to avoid is this:

1. Assume we have a libfoo.so installed in /usr/local/lib, and that this
  is a the directory for 32-bit libraries.

2. User now builds and installs a new version of libfoo.so, for 64-bit
  abi, with default prefix. Say, "./configure CC='gcc -m64' && make &&
  make check && make install". If make install installs in
  /usr/local/lib, it will overwrite a working .so file with a new one
  completely breaking 32-bit programs on the system that depend on that
  32-bit library.

To avoid this kind of breakage one can apply some heuristics to tweak
the default location, depending on the api built for, OS flavor, current
structure under /usr/lib*, etc.

Does it work to override it by explicitly passing --libdir=$PREFIX/lib?


We have CONFIG_SITE=/usr/share/site/aarch64-unknown-linux-gnu by default 
in our environment on this machine, and this file does


# If user did not specify libdir, guess the correct target:
# Use lib64 for 64 bit bi-arch targets, keep the default for the rest.
if test "$libdir" = '${exec_prefix}/lib' ; then
[...]

so it looks like you can override it with anything but what you want (the 
file is sourced by configure after it has set libdir).


Anyway, I think Paul's goal is more once GMP has been installed in lib64, 
how can MPFR, knowing only the prefix, guess the right libdir? Except for 
a hack of creating a dummy project, calling configure with that prefix, 
and checking what libdir is used, I don't see a great way to do that. 
Trying to use CONFIG_SITE directly would be messy. An alternative would be 
to guess that if there is only one subdirectory lib* in prefix, that might 
be it, or try each lib* until one works, hoping that the name never gets 
weirder. You could also complain to SUSE...


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: strange install directory

2021-02-25 Thread Marc Glisse

On Fri, 26 Feb 2021, Paul Zimmermann wrote:


on the gcc118 machine from the gcc compile farm, with gmp-6.2.1, make install
puts the libgmp.{a,so} files in $PREFIX/lib64 instead of $PREFIX/lib. Is there
any reason for that?


/usr/share/site/aarch64-unknown-linux-gnu does it?

--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Funny clang behaviour

2020-02-17 Thread Marc Glisse

On Mon, 17 Feb 2020, Marco Bodrato wrote:


Ciao,

Il 2020-02-17 20:34 Marc Glisse ha scritto:

easiest would be to rename the test from bit to something less common.


Do you mean that we should
$ hg rename tests/mpz/bit.c tests/mpz/t-bit.c
$ sed -i orig 's/ bit / t-bit /' tests/mpz/Makefile.am
?


Yes, I think that's the easiest way to avoid this issue.

--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Funny clang behaviour

2020-02-17 Thread Marc Glisse

On Mon, 17 Feb 2020, Torbjörn Granlund wrote:


Marc Glisse  writes:

 It looks like there is now a standard header called . We also
 have a test bit.c that compiles to bit. And we have a -I flag pointing
 to the location of this second bit file. Now, when clang sees #include
  inside the libc++ headers, it finds this binary file instead of
 the standard header. I think we should fix that on the GMP side. The
 easiest would be to rename the test from bit to something less common.

What you say makes sense, but clang's behaviour does not.

I added broad testing using C++ compilers for GMP now; there are 56
variants.  Only clang 8 on FreeBSD fails.  All gcc versions (at least 6
to 9) and older and newer clang worked fine.

It is possible that it is timing-dependent; if a parallel compile
generates ./bit late enough for other compiles to not see it, things
will work.  But I don't see why all 4 clang8/fbsd compiles fail and all
the other 52 compiles work.


I managed to reproduce on linux (debian) with CC='clang++-10 
-stdlib=libc++'.


For the failure to occur, you need to compile GMP with a C++ compiler (the 
error is in tests/mpz/ which would normally be C), the standard library 
has to be recent enough to have the header , and it needs to include 
 from some other standard header.


Sure, the failure may appear or disappear depending on various factors, 
but in any case it seems like a good idea to avoid having a file with the 
same name as a standard header in a directory with a -I pointing to it.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Funny clang behaviour

2020-02-17 Thread Marc Glisse

On Mon, 17 Feb 2020, Torbjörn Granlund wrote:


We upgraded the FreeBSD GMP test systems from 11.2 to 11.3 and 12.0 to
12.1 and with those upgrades came clang 8.0.

We got some really novel failures when using clang++ for compiling GMP.
It spews out binary error messages which appears to be dumps of its own
RAM!  What clang actually thinks is wromg is anyone's guess.


It looks like there is now a standard header called . We also have a 
test bit.c that compiles to bit. And we have a -I flag pointing to the 
location of this second bit file. Now, when clang sees #include  
inside the libc++ headers, it finds this binary file instead of the 
standard header. I think we should fix that on the GMP side. The easiest 
would be to rename the test from bit to something less common.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Overflow in mpz_cmp

2020-02-11 Thread Marc Glisse

On Tue, 11 Feb 2020, Niels Möller wrote:


Marco Bodrato  writes:


Ciao,

Il 2020-02-10 18:25 Guillaume Melquiond ha scritto:

When the operand sizes do not match, the mpz_cmp function function just
returns the difference of the signed sizes. Unfortunately, this
difference might not fit inside the "int" return type, when the numbers
are of opposite sign.


In mini-gmp we defined a macro:
#define GMP_CMP(a,b) (((a) > (b)) - ((a) < (b)))

We may use the same idea here too. I mean something like the following:

diff -r f5601c2a8b11 mpz/cmp.c
--- a/mpz/cmp.c Sun Feb 09 16:16:19 2020 +0100
+++ b/mpz/cmp.c Tue Feb 11 14:20:39 2020 +0100
@@ -35,15 +35,15 @@
 int
 mpz_cmp (mpz_srcptr u, mpz_srcptr v) __GMP_NOTHROW
 {
-  mp_size_t  usize, vsize, dsize, asize;
+  mp_size_t  usize, vsize, asize;
   mp_srcptr  up, vp;
   intcmp;

   usize = SIZ(u);
   vsize = SIZ(v);
-  dsize = usize - vsize;
-  if (dsize != 0)
-return dsize;
+  cmp = (usize > vsize) - (usize < vsize);
+  if (cmp != 0)
+return cmp;


I would be tempted to keep it simple,

 if (usize != vsize)
   return (usize > vsize) ? 1 : -1;

It's not clear to me if this is worth micro optimizing, and ensure we
get only a single branch.


On x86_64, both gcc and clang optimize (usize > vsize) ? 1 : -1 to 2 * 
(usize > vsize) - 1 (as a single LEA for gcc, 2 ADD for llvm). So the 
generated code may be just as good with the simple code.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: ASSERT and __builtin_unreachable

2019-09-03 Thread Marc Glisse

On Tue, 3 Sep 2019, Niels Möller wrote:


I think we discussed this earlier, but I don't recall the conclusion, if
any. Would it make sense to use ASSERT to guide the compiler, and define
it like

#define ASSERT(expr) do { if (!(expr)) __builtin_unreachable(); } while (0)

(unless building with --enable-assert)?

The idea is to tell the compiler to assume that the asserted expression
is true, and not care what the behavior of the generated code is in case
it nevertheless happens to be false at run time.

As far as I understand, this should aid optimization in some (rare?)
cases. Drawbacks are small: we'd need a configure test for
__builtin_unreachable, and there are a few places with code like

  ASSERT_CODE (char *bp_orig = bp - bytes);
  ...
  ASSERT (bp > bp_orig);

that needs the current definition of ASSERT and have to be updated in
one way or the other.


That seems fine for small assertions, say ASSERT(x>0), but it seems bad 
for more expensive ones, because it becomes an ASSERT_ALWAYS. In ASSERT 
(refmpn_mul_1c (prod, rp, size, divisor, carry) == carry_orig) we may end 
up calling refmpn_mul_1c needlessly, same in ASSERT (mpn_mod_1 (up, n, d) 
== 0). So we may need to introduce ASSERT_EXPENSIVE at the same time.


There are other drawbacks, it may hinder inlining because the tests make 
the functions temporarily bigger than they should be (though 
__builtin_constant_p is much worse in that respect), and it may limit 
other optimizations, but we can probably ignore that unless we notice a 
regression.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Patch for pkg-config file

2019-08-15 Thread Marc Glisse

On Thu, 15 Aug 2019, Niels Möller wrote:


Hugh McMaster  writes:


Generate and install a pkg-config file for the gmp library


This patch looks good to me. I take it you have tested that make install
does install a working gmp.pc in the right place? I'm not very familiar
with what automake does.


Generate and install a pkg-config file for the gmpxx library

[...]

diff -r 93c8fcc2cab4 -r 4b0e794dd777 gmpxx.pc.in
--- /dev/null   Thu Jan 01 00:00:00 1970 +
+++ b/gmpxx.pc.in   Thu Aug 08 23:48:03 2019 +1000
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+includedir=@includedir@
+libdir=@libdir@
+
+Name: @PACKAGE_NAME@ C++
+Description: GNU Multiple Precision Arithmetic Library (C++ bindings)
+URL: https://gmplib.org
+Version: @PACKAGE_VERSION@
+Requires: gmp
+Cflags: -I${includedir}
+Libs: -L${libdir} -lgmpxx


For gmpxx, perhaps -lgmp should be added as well, either

 Libs: -L${libdir} -lgmpxx -lgmp

or

 Libs: -L${libdir} -lgmpxx
 Libs.private: -lgmp

?


I assume that "Requires: gmp" already handles that.

--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Patch for pkg-config file

2019-08-04 Thread Marc Glisse

On Mon, 5 Aug 2019, Niels Möller wrote:


Hugh McMaster  writes:


--- /dev/null   Thu Jan 01 00:00:00 1970 +
+++ b/gmp.pc.in Sun Aug 04 22:35:15 2019 +1000


Should there also be a gmpxx.pc ?


@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+includedir=@includedir@
+libdir=@libdir@
+
+Name: @PACKAGE_NAME@
+Description: GNU Multiple Precision Arithmetic Library
+URL: https://gmplib.org
+Version: @PACKAGE_VERSION@
+Cflags: -I${includedir}
+Libs: -L${libdir} -lgmp
+Libs.private: @LIBM@


@LIBM@ shouldn't be needed. I don't know why configure checks for it,
from comments, possibly libtool-related.


IIRC -lm is used in the build, the tuning, the tests, the demos, but not 
in the library itself.


(the use in tests/cxx looks bad, it does -lm instead of using the result 
of autoconf)


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mini-gmpxx - mini-gmp C++ interface

2019-07-12 Thread Marc Glisse

On Fri, 12 Jul 2019, Vladimir S. FONOV wrote:


I needed a mini version of gmp, to work with C++ inteface, so I created
mini-gmpxx.h (gmpxx.h for mini-gmp) , mostly for the purpose of compiling
cork on macOS without libgmp present, take a look in
https://github.com/vfonov/cork/tree/master/contrib/gmp-6.1.2/mini-gmp , it


Thanks for sharing.


is basically original gmpxx.h with commented out pieces of code that
wouldn't work without mpq and mpf interfaces.


Note that we have a mini-mpq now.


I also had to add couple of defines from omp.h to mini-omp.h , so there are
small changes too.

Maybe it would be of interest to somebody?


I guess if it used some #ifdef instead of commenting out the code, so the 
same file could be user for gmp and mini-gmp, it could be interesting (not 
particularly to me since I never used mini-gmp, but to others). Maybe 
gmpxx.h could check if __MINI_GMP_H__ is defined and in that case not 
include gmp.h and not use anything mpf-related. __MINI_MPQ_H__ could be 
used to conditionally enable mpq if we don't want to enable it by default. 
(I am not saying any of the above is a good idea, just the first things 
that come to mind)


Or we could have a much more simplistic mini C++ wrapper without 
expression templates, if we are going to maintain 2 versions, although I 
am not fond of the idea of maintaining 2 versions.


I don't see a corresponding mini-gmpxx.cc file. That could cause problems 
for numeric_limits at least.


You kept some operator<< that seems unlikely to compile.

--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Documentation patch for mpz_millerrabin

2019-06-16 Thread Marc Glisse

On Sun, 16 Jun 2019, Niels Möller wrote:


Marc Glisse  writes:


https://github.com/sethtroisi/libgmp/pull/5.diff (or .patch for a
different format). AFAIK you have to modify the URL by hand...


But that gives me a sequence of patches, not a single patch ("squashed",
in git terms) representing all the changes.


I thought .patch gave a sequence of patches while .diff gave a single 
patch. The link I gave does look like a single patch to me...


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Documentation patch for mpz_millerrabin

2019-06-16 Thread Marc Glisse

On Sun, 16 Jun 2019, Niels Möller wrote:


Seth Troisi  writes:


I believe this and the jacobi documentation are more accurate than what's
currently committed.
Jacobi patch https://github.com/sethtroisi/libgmp/pull/5


How do I get a complete patch file from github? I'm looking at the
htmlized patch at https://github.com/sethtroisi/libgmp/pull/5/files but
I have difficulty spotting a "download raw patch" link.


https://github.com/sethtroisi/libgmp/pull/5.diff (or .patch for a 
different format). AFAIK you have to modify the URL by hand...


(or you can just use git with the command line instead of going though the 
web interface)


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: GMP and C++11 move constructors

2018-05-23 Thread Marc Glisse

On Wed, 23 May 2018, Marco Bodrato wrote:


From gmp-discuss:

Il Lun, 21 Maggio 2018 12:15 pm, Marc Glisse ha scritto:

If m is a
moved-from object, it is fine to assign a new value to it with m =
whatever. That's even what std::swap does. It should also be fine to
read from it, although you can't rely on any specific value so that's
not very useful.


Should the non specific value be somehow valid?


Preferably, though that's not really important, many types have a state 
where you can only destruct or assign a new value.



With lazy allocation, we should define NaN as an admissible value for mpq,
and use it whenever we init a variable that will immediately be
overwritten.


Ah, as an implementation detail, not a public interface, this avoids a lot 
of trouble.



I did this, internally in mini-mpq:
https://gmplib.org/repo/gmp/rev/8e0a2e94ae5a

The idea might be useful also for some mpq constructor from double, from
string...



if not for move.


Ah, I see where you are going now. That's an interesting idea.


Wile we are looking into this, is there a motivation why we have the
assignment "operator=(mpz_class &)" for mpq_class, but not a constructor
from mpz_class&& ?


Hmm, I forgot to add one? ;-)

--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: _ptr and _srcptr types

2018-05-19 Thread Marc Glisse

On Mon, 14 May 2018, Torbjörn Granlund wrote:


 I've personally always used the mpz_ptr and mpz_srcptr in functions that
 take mpz arguments, taking the liberty to use this undocumented type.

I suppose we could declare these.  I'd like to hear from the rest of the
GMP "core team".


I am in favor of documenting them. I don't think we are losing much by 
exposing those types to the user, it seems hard to modify the 
implementation of mpz_t in a way that would break those types without 
breaking a lot of other things. The main question in my mind is how to 
document them so users don't get too confused about what they should use 
and when.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mpq_get_d [Was: mini-gmp and mpq]

2018-05-19 Thread Marc Glisse

On Tue, 15 May 2018, Marco Bodrato wrote:


Ciao Marc,

Il Lun, 19 Febbraio 2018 5:24 pm, Marc Glisse ha scritto:

On Mon, 19 Feb 2018, Marco Bodrato wrote:

mpq_get_d currently gives a double, but rounded towards zero...


Except when it uses the broken generic code :-(


If you want, you can check the changed generic code,

https://gmplib.org/repo/gmp/rev/89e43a9eab63

to test if it is less broken...


That looks sensible. I didn't test, I assume it is still broken for 
denormals and infinity (it may be doable using DBL_MAX_EXP, DBL_MIN_EXP, 
DBL_HAS_SUBNORM, etc), but it is already a good improvement if it works 
for normal numbers.


(I never use GMP's get_d functions, they don't quite provide what I need)

Thanks,

--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: documentation on internals not up to date

2018-04-27 Thread Marc Glisse

On Fri, 27 Apr 2018, Niels Möller wrote:


Marc Glisse <marc.gli...@inria.fr> writes:


There would be a significant advantage to mpq if we could have a
non-allocated 1 for the denominator. But indeed, with the current code
where only some mpz functions would work, it seems safer to document
that none work.


We could do that internally, even if we don't advertise it for other gmp
users.


We document that users can use the denominator of a mpq_t as a regular 
mpz_t and apply pretty much any mpz_t operation to it. So it seems hard to 
handle just that case internally.



Then mpq_init wouldn't do any allocation, right?


Right.

We could have a single mpq object representing 0/1 with _mp_alloc == 0 
for both parts, and initialize with struct assignment or memcpy.


We would just ensure that mpz realloc keeps supporting thuis case.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: documentation on internals not up to date

2018-04-27 Thread Marc Glisse

On Fri, 27 Apr 2018, Niels Möller wrote:


_mp_alloc == 0 and _mp_size != 0 is a read-only value, _mp_d is neither
written, reallocated or freed by mpz functions. It must not be passed as
destination argument to any mpz function. Should also link to docs for
mpz_roinit_n and MPZ_ROINIT_N.


Currently, if an mpz_t is initialised with _roinit, it can be passed to
_clear or _clears with no errors. Should we document this? I think we
should.

Moreover, the various mpz_set_ functions should work smoothly too.


I'd prefer that we not document any way to pass _roinit values to any
mpz functions taking a non-const mpz_t, even if it happens to work in
the current implementation. Maybe as a later extension, *if* we find
some use cases where it provides a significant advantage.


There would be a significant advantage to mpq if we could have a
non-allocated 1 for the denominator. But indeed, with the current code 
where only some mpz functions would work, it seems safer to document that 
none work.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: C99 and GMP

2018-04-27 Thread Marc Glisse

On Fri, 27 Apr 2018, Marc Glisse wrote:


On Fri, 27 Apr 2018, paul zimmermann wrote:


quite interesting. Why is gmp/mpn not tested in the head coverage?


It is tested. It appears as /var/tmp/lcov/gmp/mpn because it is a set of
symlinks created at build time.


sorry I missed that. I see some of the files are not tested at all
(add_err3_n.c for example), and some have a low coverage (div_qr_1.c
for example). Are there any plans to improve that?


Even for the generic files, the coverage varies per target, maybe add_err3_n 
is better tested on ARM or something (not really answering your question).


Hmm, no, mpn_add_err3_n really seems completely unused. There is a refmpn 
implementation ready for comparisons...


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: C99 and GMP

2018-04-27 Thread Marc Glisse

On Fri, 27 Apr 2018, paul zimmermann wrote:


quite interesting. Why is gmp/mpn not tested in the head coverage?


It is tested. It appears as /var/tmp/lcov/gmp/mpn because it is a set of
symlinks created at build time.


sorry I missed that. I see some of the files are not tested at all
(add_err3_n.c for example), and some have a low coverage (div_qr_1.c
for example). Are there any plans to improve that?


Even for the generic files, the coverage varies per target, maybe 
add_err3_n is better tested on ARM or something (not really answering your 
question).


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: C99 and GMP

2018-04-27 Thread Marc Glisse

On Fri, 27 Apr 2018, paul zimmermann wrote:


https://gmplib.org/devel/lcov/shell/gmp/mini-gmp/mini-mpq.c.gcov.html


quite interesting. Why is gmp/mpn not tested in the head coverage?


It is tested. It appears as /var/tmp/lcov/gmp/mpn because it is a set of 
symlinks created at build time.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: C99 and GMP

2018-04-26 Thread Marc Glisse

On Wed, 4 Apr 2018, Torbjörn Granlund wrote:


I'd suggest to make a 6.2 release of pretty much what we have today.


Marco had a mini-mpq that seemed to be in a working state. I guess it is 
missing tests, so too much work for 6.2. Is that a correct interpretation 
of the status?


(I am trying to think of things lying around that would be easy / safe to 
push)


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mpn_mul is embarrassingly slow

2018-04-20 Thread Marc Glisse

On Fri, 20 Apr 2018, Marc Glisse wrote:


On Fri, 20 Apr 2018, Marc Glisse wrote:


On Fri, 20 Apr 2018, Marc Glisse wrote:


On Fri, 20 Apr 2018, Vincent Lefevre wrote:


On 2018-04-20 04:14:15 +0200, Fredrik Johansson wrote:

For operands with 1-4 limbs, that is; on my machine, mpn_mul takes up to
twice as long as mpn_mul_basecase, and inline assembly for 1x1, 2x1 or 
2x2
multiplication is even faster. The problem is that there are three 
function

calls (mpn_mul -> mpn_mul_n -> mpn_mul_basecase) + branches between the
user code and GMP's lightning fast assembly code.

I was reminded of this old issue when seeing this new paper on arXiv:
https://arxiv.org/abs/1804.07236. Here, the author benchmarked a C++
implementation of bignum arithmetic against mpn_mul for small operand 
sizes

and came to the conclusion that the former approach performs better than
hand-optimized assembly (one wishes that compilers really were that 
clever

about bignum code by now!).

Some advanced GMP users (including myself) know about the issue and 
simply
avoid mpn_mul for performance-critical code with short operands. The 
most

convenient solution is to call mpn_mul_basecase directly instead of
mpn_mul. Unfortunately, mpn_mul_basecase is not public, so this is a bit
iffy to rely on. One feature request would be to simply make
mpn_mul_basecase / mpn_sqr_basecase public.

[...]

I'm wondering... With the current GMP code, does LTO help to avoid
such issues?


mpn_mul and mpn_mul_n are too large to be completely inlined (unless 
that's the only place where they are used, which could happen in a 
microtest, but doesn't seem realistic in an application). What could 
happen is partial inlining of the first test of each. Maybe using LTO+PGO 
(profile-guided optimization)? Still, I am not particularly optimistic.


I just tried (LTO+PGO) on a trivial testcase, and gcc didn't manage to do 
anything clever with it. Doing it by hand to see how much potential gain 
there is, the timings are:


mpn_mul: .56
mpn_mul_n: .36
mpn_mul_basecase: .16


Let me mention here that LLVM does manage to take advantage of LTO to get the 
running time of mpn_mul down to .16 for this trivial example (only call 
mpn_mul, only on 1 limb numbers).



Avec la propagation des constantes, GCC ne peut-il pas en déduire que
tout un tas de choses est du code mort, en tout cas passer directement
à mpn_mul_basecase (p, a, n, b, n) puisque le test BELOW_THRESHOLD (n,
MUL_TOOM22_THRESHOLD) est vrai?


I took a closer look at what gcc is doing. Propagating constants (the
sizes) from one function to another (mpn_mul) means either inlining
(unlikely, the function is very large and has several callers including
itself) or cloning, i.e. creating a similar function that takes fewer
arguments and assumes that the few missing are those constants.

I can see in the logs:

Evaluating opportunities for __gmpn_mul/68.
 - considering value  for param #0 mp_limb_t * (caller_count: 1)
 good_cloning_opportunity_p (time: 2, size: 698, count_sum: 1, scc, 
single_call) -> evaluation: 0, threshold: 500
 good_cloning_opportunity_p (time: 264, size: 59564, count_sum: 1, 
scc, single_call) -> evaluation: 1, threshold: 500
 - considering value  for param #1 const mp_limb_t * (caller_count: 1)
 good_cloning_opportunity_p (time: 2, size: 698, count_sum: 1, scc, 
single_call) -> evaluation: 0, threshold: 500
 good_cloning_opportunity_p (time: 50, size: 12795, count_sum: 1, scc, 
single_call) -> evaluation: 0, threshold: 500
 - considering value 1 for param #2 mp_size_t (caller_count: 1)
 good_cloning_opportunity_p (time: 75, size: 689, count_sum: 1, scc, 
single_call) -> evaluation: 54, threshold: 500
 good_cloning_opportunity_p (time: 721, size: 4091, count_sum: 1, scc, 
single_call) -> evaluation: 89, threshold: 500
 - considering value  for param #3 const mp_limb_t * (caller_count: 3)
 good_cloning_opportunity_p (time: 1, size: 699, count_sum: 1, scc, 
single_call) -> evaluation: 0, threshold: 500
 good_cloning_opportunity_p (time: 49, size: 12796, count_sum: 1, scc, 
single_call) -> evaluation: 0, threshold: 500
 - considering value 1 for param #4 mp_size_t (caller_count: 3)
 good_cloning_opportunity_p (time: 72, size: 123, count_sum: 1, scc, 
single_call) -> evaluation: 298, threshold: 500
 good_cloning_opportunity_p (time: 72, size: 123, count_sum: 1, scc, 
single_call) -> evaluation: 298, threshold: 500

So gcc did consider this optimization, but its heuristics mistakenly
convinced it it wasn't worth the trouble. On simpler examples not using
GMP, I can get gcc to do the transformation, it would be quite some work
to analyse why gcc is not more enthusiastic here.

I tried again with --param ipa-cp-eval-threshold=50 to convince gcc to
clone... and the running time went down to .29. It did clone mpn_mul and
mpn_mul_n, and the clo

Re: mpn_mul is embarrassingly slow

2018-04-20 Thread Marc Glisse

On Fri, 20 Apr 2018, Marco Bodrato wrote:


Il Ven, 20 Aprile 2018 12:39 pm, Marc Glisse ha scritto:

I just tried (LTO+PGO) on a trivial testcase, and gcc didn't manage to do
anything clever with it. Doing it by hand to see how much potential gain
there is, the timings are:

mpn_mul: .56
mpn_mul_n: .36
mpn_mul_basecase: .16


Did you try also the documented function mpn_sec_mul?


.19


If you know in advance that the size of your operand are bounded by some
given sizes, you can preallocate the required scratch space...


I'll admit that since I don't care about the security aspects, it didn't 
even occur to me to look at those functions for performance.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mpn_mul is embarrassingly slow

2018-04-20 Thread Marc Glisse

On Fri, 20 Apr 2018, Marc Glisse wrote:


On Fri, 20 Apr 2018, Marc Glisse wrote:


On Fri, 20 Apr 2018, Vincent Lefevre wrote:


On 2018-04-20 04:14:15 +0200, Fredrik Johansson wrote:

For operands with 1-4 limbs, that is; on my machine, mpn_mul takes up to
twice as long as mpn_mul_basecase, and inline assembly for 1x1, 2x1 or 
2x2
multiplication is even faster. The problem is that there are three 
function

calls (mpn_mul -> mpn_mul_n -> mpn_mul_basecase) + branches between the
user code and GMP's lightning fast assembly code.

I was reminded of this old issue when seeing this new paper on arXiv:
https://arxiv.org/abs/1804.07236. Here, the author benchmarked a C++
implementation of bignum arithmetic against mpn_mul for small operand 
sizes

and came to the conclusion that the former approach performs better than
hand-optimized assembly (one wishes that compilers really were that 
clever

about bignum code by now!).

Some advanced GMP users (including myself) know about the issue and 
simply

avoid mpn_mul for performance-critical code with short operands. The most
convenient solution is to call mpn_mul_basecase directly instead of
mpn_mul. Unfortunately, mpn_mul_basecase is not public, so this is a bit
iffy to rely on. One feature request would be to simply make
mpn_mul_basecase / mpn_sqr_basecase public.

[...]

I'm wondering... With the current GMP code, does LTO help to avoid
such issues?


mpn_mul and mpn_mul_n are too large to be completely inlined (unless that's 
the only place where they are used, which could happen in a microtest, but 
doesn't seem realistic in an application). What could happen is partial 
inlining of the first test of each. Maybe using LTO+PGO (profile-guided 
optimization)? Still, I am not particularly optimistic.


I just tried (LTO+PGO) on a trivial testcase, and gcc didn't manage to do 
anything clever with it. Doing it by hand to see how much potential gain 
there is, the timings are:


mpn_mul: .56
mpn_mul_n: .36
mpn_mul_basecase: .16


Let me mention here that LLVM does manage to take advantage of LTO to get 
the running time of mpn_mul down to .16 for this trivial example (only 
call mpn_mul, only on 1 limb numbers).


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mpn_mul is embarrassingly slow

2018-04-20 Thread Marc Glisse

On Fri, 20 Apr 2018, Marc Glisse wrote:


On Fri, 20 Apr 2018, Vincent Lefevre wrote:


On 2018-04-20 04:14:15 +0200, Fredrik Johansson wrote:

For operands with 1-4 limbs, that is; on my machine, mpn_mul takes up to
twice as long as mpn_mul_basecase, and inline assembly for 1x1, 2x1 or 2x2
multiplication is even faster. The problem is that there are three 
function

calls (mpn_mul -> mpn_mul_n -> mpn_mul_basecase) + branches between the
user code and GMP's lightning fast assembly code.

I was reminded of this old issue when seeing this new paper on arXiv:
https://arxiv.org/abs/1804.07236. Here, the author benchmarked a C++
implementation of bignum arithmetic against mpn_mul for small operand 
sizes

and came to the conclusion that the former approach performs better than
hand-optimized assembly (one wishes that compilers really were that clever
about bignum code by now!).

Some advanced GMP users (including myself) know about the issue and simply
avoid mpn_mul for performance-critical code with short operands. The most
convenient solution is to call mpn_mul_basecase directly instead of
mpn_mul. Unfortunately, mpn_mul_basecase is not public, so this is a bit
iffy to rely on. One feature request would be to simply make
mpn_mul_basecase / mpn_sqr_basecase public.

[...]

I'm wondering... With the current GMP code, does LTO help to avoid
such issues?


mpn_mul and mpn_mul_n are too large to be completely inlined (unless that's 
the only place where they are used, which could happen in a microtest, but 
doesn't seem realistic in an application). What could happen is partial 
inlining of the first test of each. Maybe using LTO+PGO (profile-guided 
optimization)? Still, I am not particularly optimistic.


I just tried (LTO+PGO) on a trivial testcase, and gcc didn't manage to do 
anything clever with it. Doing it by hand to see how much potential gain 
there is, the timings are:


mpn_mul: .56
mpn_mul_n: .36
mpn_mul_basecase: .16

--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mpn_mul is embarrassingly slow

2018-04-20 Thread Marc Glisse

On Fri, 20 Apr 2018, Vincent Lefevre wrote:


On 2018-04-20 04:14:15 +0200, Fredrik Johansson wrote:

For operands with 1-4 limbs, that is; on my machine, mpn_mul takes up to
twice as long as mpn_mul_basecase, and inline assembly for 1x1, 2x1 or 2x2
multiplication is even faster. The problem is that there are three function
calls (mpn_mul -> mpn_mul_n -> mpn_mul_basecase) + branches between the
user code and GMP's lightning fast assembly code.

I was reminded of this old issue when seeing this new paper on arXiv:
https://arxiv.org/abs/1804.07236. Here, the author benchmarked a C++
implementation of bignum arithmetic against mpn_mul for small operand sizes
and came to the conclusion that the former approach performs better than
hand-optimized assembly (one wishes that compilers really were that clever
about bignum code by now!).

Some advanced GMP users (including myself) know about the issue and simply
avoid mpn_mul for performance-critical code with short operands. The most
convenient solution is to call mpn_mul_basecase directly instead of
mpn_mul. Unfortunately, mpn_mul_basecase is not public, so this is a bit
iffy to rely on. One feature request would be to simply make
mpn_mul_basecase / mpn_sqr_basecase public.

[...]

I'm wondering... With the current GMP code, does LTO help to avoid
such issues?


mpn_mul and mpn_mul_n are too large to be completely inlined (unless 
that's the only place where they are used, which could happen in a 
microtest, but doesn't seem realistic in an application). What could 
happen is partial inlining of the first test of each. Maybe using LTO+PGO 
(profile-guided optimization)? Still, I am not particularly optimistic.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Lazy mpz allocation

2018-04-20 Thread Marc Glisse

On Fri, 20 Apr 2018, paul zimmermann wrote:


Only 0 can have lazy allocation, and I think we document that it isn't
legal to put 0 on the denominator.


where is this documented?


That was in a "I think" sentence. Now that I looked a bit more, I don't 
find it... Well, you can't call any mpq function that reads that mpq_t, 
but we don't say you can't write to that mpq_t.



In mpfr_set_q we use the fact that the user can set q to 1/0
for example to represent +Inf.


I didn't remember that MPFR did that, but I did remember that some people 
did that. I'll count it as a vote for Marco's patch.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Lazy mpz allocation

2018-04-20 Thread Marc Glisse

On Fri, 20 Apr 2018, Marco Bodrato wrote:


Ciao,

Il Gio, 19 Aprile 2018 4:37 pm, Marc Glisse ha scritto:

I finally pushed it. It seemed unsafe to keep mpq unaware of lazy
allocation, in case people start swapping the numerator of a rational with
a lazy 0 integer or something like that.


If we fear swaps, then ... what about swapping the deoniminator?


Only 0 can have lazy allocation, and I think we document that it isn't 
legal to put 0 on the denominator.



Should we support a code like:

 mpz_init (saved_denominator);
 mpz_swap (saved_denominator, mpq_denref(rational));
 /* Code overwriting rational*/

?


Hmmm... I don't know. It does seem vaguely possible that someone would do:

mpz_class den;
mpq_class q = some_computation();
den = std::move(q.get_den()); // won't need this value of q anymore
q = other_computation();

(the third line does a swap)

But that seems unlikely and contrived. If testing for this case is costly 
(it is likely cheap enough that I shouldn't worry), I'd be sad to pay for 
it :-( I'd be less negative if we were reaping some benefit from those new 
tests, for instance allowing a lazy denominator of 1.


But safety is a strong argument indeed.


If yes, a larger patch is needed, I attach a proposal.


If yes, then something like that looks right, thanks.

--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Lazy mpz allocation

2018-04-19 Thread Marc Glisse

On Mon, 11 Apr 2016, Marc Glisse wrote:


On Mon, 9 Nov 2015, Marco Bodrato wrote:


Moreover, the mpq layer and mini-gmp need to migrate to lazy allocation
too...


For mpq, the attached seems sufficient to pass make check.


I finally pushed it. It seemed unsafe to keep mpq unaware of lazy 
allocation, in case people start swapping the numerator of a rational with 
a lazy 0 integer or something like that.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: How large are arbitrarily large integers? (Was Re: Bitfield subtlety)

2018-03-29 Thread Marc Glisse

On Thu, 29 Mar 2018, Richard Biener wrote:


On Thu, 29 Mar 2018, Torbjörn Granlund wrote:


Richard Biener <rguent...@suse.de> writes:

  You can also steal low-order bits from the pointer depending on
  alignment...  and depending on the host also some high-order bits.

I will resist those temptations.  :-)

(I have contemplates using the 2-3 low point bits for some other
purposes, most likely to track used allocators.  But I don't think that
will happen.)

  You can also simply off-load the allocation size to the allocated
  area (like to *(size_t)(_mp_d - 8)).  In fact you are already breaking
  the ABI in some sort by re-purposing fields given that the internals
  of __mpz_struct is exposed.

Unfortunately, while that would be desirable, I have the feeling that it
is not 100% portable.


I would be surprised if that wouldn't work everywhere - any reason
you have doubts?  To clarify, allocation would work like

void *ptr = malloc (... + sizeof (size_t));
->_mp_d = (char *)ptr + sizeof (size_t);
size_t *size = ptr;

if you think the pointer arithmetic on _mp_d is problematic you can
always go through uintptr_t ...


IIRC that's roughly what MPFR does.

--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Bitfield subtlety

2018-03-27 Thread Marc Glisse

On Wed, 28 Mar 2018, Torbjörn Granlund wrote:


I am playing with a GMP version which allows greater mpz numbers than
what is currently handled.  The idea is to combine the _mp_size and
_mp_alloc fields such that _mp_size becomes 40 bits while _mp_alloc
becomes a custom float.

I ran into some problems with C and C++ when it comes to bit fields.

In C++, a bit field whose base type is not explicitly signed or unsigned
gets undefined signedness.  It would be desirable to use stdint.h's
int64_t, but while that is signed, it is not guaranteed to be explicitly
so.


ISTR that this has changed (maybe only recently for C++20 though).


In C, at least old C, allows just (signed or unsigned ) int as base
types.  I.e., long is not allowed, and thus int64_t is also not allowed.


Does anybody on this list know if C99 is more tolerant wrt base type? If
so, will implicity signed basetypes result in signed bit fields (unlike
C++)?


C11 still seems to limit bit-fields quite strictly:
"A bit-field shall have a type that is a qualified or unqualified version 
of _Bool, signed int, unsigned int, or some other implementation-defined 
type."



In C++, there is also the strange behavior that long bit-fields are not 
necessarily promoted to long, so g++ happily generates operations on a 
51-bit integer type... (clang does promote IIRC)



I see no nice solution to the C++ rule.  I suppose that if we decide to
go with bit fields here, we will simply not support problematic C++
compilers.  Or we arm autoconf to probe for this too, and stay away from
stdint.h.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mini-gmp mpz_{get,set}_d not fully compatible with GMP

2018-03-17 Thread Marc Glisse

On Sat, 17 Mar 2018, Vincent Lefevre wrote:


On 2018-03-16 22:22:39 +0100, Marc Glisse wrote:

On Fri, 16 Mar 2018, Marco Bodrato wrote:


float.h was defined by C99, right?


I am pretty sure it was already in C89.


Yes, but was DBL_MANT_DIG necessarily an integer constant expression
(in case this is needed) at that time?


Indeed it wasn't (only FLT_RADIX was), but I would be surprised if 
implementations made it non-constant, and we probably don't need to use it 
as a constant anyway.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mini-gmp mpz_{get,set}_d not fully compatible with GMP

2018-03-16 Thread Marc Glisse

On Fri, 16 Mar 2018, Marco Bodrato wrote:


float.h was defined by C99, right?


I am pretty sure it was already in C89.

--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mini-gmp mpz_{get,set}_d not fully compatible with GMP

2018-03-13 Thread Marc Glisse

On Tue, 13 Mar 2018, Niels Möller wrote:


I'd still prefer the simpler way of reying on float.h constants,
though


+1 to that. For mini-gmp, maybe put all the functions using 'double' 
behind some macro or in a separate file so it is easy for a user to remove 
them, and document that they are only supported with a standard float.h 
header. Or just assume that float.h is always available nowadays. Or even 
assume that all double are 64-bit binary IEEE numbers...


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mini-gmp mpz_{get,set}_d not fully compatible with GMP

2018-03-09 Thread Marc Glisse

On Fri, 9 Mar 2018, Torbjörn Granlund wrote:


 For GMP, it's desirable to fix also the non IEEE-version.

That would have some value, I suppose, although non-IEEE formats of
course have become largely obsolete.


This code is mostly used not for non-IEEE formats, but for cases where we 
fail to detect that it *is* IEEE. For instance when compiling to bitcode 
(gcc LTO, LLVM, webassembly, etc). Of course, better IEEE detection would 
help those more than fixing the fallback path.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mini-gmp mpz_{get,set}_d not fully compatible with GMP

2018-03-06 Thread Marc Glisse

On Tue, 6 Mar 2018, Niels Möller wrote:


Marc Glisse <marc.gli...@inria.fr> writes:


On Tue, 6 Mar 2018, Marco Bodrato wrote:


Which solutions do you suggest? I see 3 possible ways:
- removing the non "fully compatible" functions;
- adding them to the "with a few exceptions:" section;
- correct the behaviour of the functions...


As discussed for instance last October, the generic, non-IEEE version
of mpn_get_d has a similar issue. Maybe they could both be fixed at
the same time with the same code?


For mini-gmp, it's highly desirable for the get_d function to be fully
compatible with gmp at least for the common case of standard IEEE
floats. I'm fine with documenting different behavior for obscure
floating point variants.

For GMP, it's desirable to fix also the non IEEE-version.

Can we rely on FLT_RADIX and DBL_MANT_DIG (float.h, see
http://pubs.opengroup.org/onlinepubs/009695399/basedefs/float.h.html),
to get correct rounding at least as long as FLT_RADIX == 2 ?


The code shouldn't be too hard to write using count_leading_zeros and 
DBL_MANT_DIG, but I have no idea how many platforms are missing 
DBL_MANT_DIG. I am not really interested in such platforms...



If I recall earlier discussion correctly, we really need to know the
size of the mantissa, from the compiler or a configure check (and the
latter is not applicable to mini-gmp).


It is also possible to determine it at runtime (comparing 2^n+{0,1,2} for 
instance should work whether we round up, down or to the nearest; 
tests/misc.c compares 2^n+1-2^n to 1, which also looks good), doing it 
once and storing the result somewhere.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mini-gmp mpz_{get,set}_d not fully compatible with GMP

2018-03-06 Thread Marc Glisse

On Tue, 6 Mar 2018, Marco Bodrato wrote:


Which solutions do you suggest? I see 3 possible ways:
- removing the non "fully compatible" functions;
- adding them to the "with a few exceptions:" section;
- correct the behaviour of the functions...


As discussed for instance last October, the generic, non-IEEE version of 
mpn_get_d has a similar issue. Maybe they could both be fixed at the same 
time with the same code?


Obviously this assumes that someone can find time to do it... Otherwise, I 
guess that option 2 could do, until a volunteer appears.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mini-gmp and mpq

2018-02-28 Thread Marc Glisse

On Wed, 28 Feb 2018, Marco Bodrato wrote:


Something like that, yes. But it feels like this is duplicating
functionality that should be elsewhere... Bah, I am probably too picky for
so few lines, feel free to go ahead and commit your patch (I don't


Pushed it.


remember if any of the tests do q+1).


I hope I added them with another patch:
https://gmplib.org/repo/gmp/rev/7cae59f06a21


Yes, I think that works.


In the meanwhile I also pushed some small shortcuts for __gmp_binary_equal
applied to mpq and integers: https://gmplib.org/repo/gmp/rev/a22c11d52f05


Thanks, that's a good idea. If we wanted to, we could also specialize the 
test q == 0 (and q < 0), which is probably common enough, but that's 
independent, and a negligible gain.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mini-gmp and mpq

2018-02-27 Thread Marc Glisse

On Tue, 27 Feb 2018, Marco Bodrato wrote:


Il Mar, 27 Febbraio 2018 8:22 pm, Marc Glisse ha scritto:

If I write q = 1 + 1 / q, gmpxx currently generates:
mpq_inv(q, q);
mpz_addmul_ui(num, den, 1);

Not quite optimal yet :-(


May the following help?


Something like that, yes. But it feels like this is duplicating 
functionality that should be elsewhere... Bah, I am probably too picky for 
so few lines, feel free to go ahead and commit your patch (I don't 
remember if any of the tests do q+1).


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mini-gmp and mpq

2018-02-27 Thread Marc Glisse

On Tue, 27 Feb 2018, Marco Bodrato wrote:


The realway to speed-up that loop is to use the suggestion in gmpxx.h to
compute a rational+1, both for mini-gmp and the full GMP library:

struct __gmp_unary_increment
{
 static void eval(mpz_ptr z) { mpz_add_ui(z, z, 1); }
 static void eval(mpq_ptr q)
 { mpz_add(mpq_numref(q), mpq_numref(q), mpq_denref(q)); }
 static void eval(mpf_ptr f) { mpf_add_ui(f, f, 1); }
};


If I write q = 1 + 1 / q, gmpxx currently generates:
mpq_inv(q, q);
mpz_addmul_ui(num, den, 1);

Not quite optimal yet :-(

--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Why set zero in zero.c rather than use xor_n

2018-02-05 Thread Marc Glisse

On Mon, 5 Feb 2018, Vincent Lefevre wrote:


On 2018-02-05 21:48:47 +0100, Torbjorn Granlund wrote:

I suppose memset is not used as it might come with more overhead for
checking alignment.  I haven't timed it, though.


The compiler knows the alignment from the types.


Quite often it does not, the C type system is too weak.


This is where the optimization should be.


Sadly, I don't think gcc has an optimization like what Niels suggested, 
with multiple memset entry points according to the alignment. Searching a 
bit, it looks like Intel's compiler does (they recommend using 
__assume_aligned on the target of memset).



The GCC manual mentions a __builtin_memset
builtin, though I don't know what it does exactly.


That's how a regular call to memset is encoded internally... For small 
constant sizes, it may be expanded inline, but usually it remains a call 
to memset.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Why set zero in zero.c rather than use xor_n

2018-02-05 Thread Marc Glisse

On Mon, 5 Feb 2018, Niels Möller wrote:


I am not sure it is important enough to write in asm, though.


Probably not. But it might make sense to rewrite as a wrapper for
memset, which I'd expect to be well optimized in gcc and libc.


If you compile the current zero.c with -O3, gcc generates a call to memset 
(protected by a test). If that's what we are getting, we might as well 
write it this way and make the function inline.


Supposedly, for small sizes, mpn_zero can have a smaller overhead than 
memset, since it has more alignment information. But I don't think I've 
ever used mpn_zero...


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Why set zero in zero.c rather than use xor_n

2018-02-05 Thread Marc Glisse

On Mon, 5 Feb 2018, Win C wrote:


int main()
{
int i;
mp_limb_t *pi = malloc(16);


That's not nearly enough, the code crashes for me.


$./zeroing
73491
17651


Try testing xor before zero...

--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mini-gmp

2017-12-06 Thread Marc Glisse

Hello,

I am curious why you are trying to support mini-gmp in mpfr at all. As far 
as I understand, the goal of mini-gmp is that a user can take a copy of 
those 2 files, stick them in his project, and get a self-contained 
program. Unless you provide a similar mini-mpfr, your user is going to 
have to install the mpfr dependency anyway, his project is not 
self-contained, so he might as well install the real GMP.



--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Generic get_d_2exp failures

2017-10-28 Thread Marc Glisse

On Sat, 28 Oct 2017, Niels Möller wrote:


Marc Glisse <marc.gli...@inria.fr> writes:


2) The rounding occurs in the addition in

  weight = 1/MP_BASE_AS_DOUBLE;
  d = up[size - 1];
  for (i = size - 2; i >= 0; i--)
{
  d += up[i] * weight;
  weight /= MP_BASE_AS_DOUBLE;
  if (weight == 0)
break;
}

we could make that code uglier to make sure there is no rounding up,
maybe comparing d+up[i]*weight to d+oldweight, and trying again by
zeroing out an increasing number of low bits of up[i].


It would be nice if we could find a portable way to add two floating
point values without rounding up. Would something like this work?

 s = a + b; /* Assume a > b */
 r = (s - a) - b;  /* No rounding expected here. */
 if (r > 0)
   s -= 2*r;


Not sure where the 2*r is coming from. And I am not very optimistic that 
there is such a simple formula that works for any rounding mode, though I 
could easily be wrong. There is also the question of how portable exactly 
it needs to be. C99 nextafter can be helpful.



But doesn't make the tests pass  in my initial testing. I guess it might
be necessary to isolate the high bit of r (possibly be converting to
mp_limb_t ans usign count_leading_zeros), which should correspond to
the lsb of the mantissa (or if it's half the lsb).

And might also need special handling of the case that s, after rounding,
is a power of two.

The variant I tested:

@@ -368,7 +369,13 @@ mpn_get_d (mp_srcptr up, mp_size_t size,
  d = up[size - 1];
  for (i = size - 2; i >= 0; i--)
{
- d += up[i] * weight;
+ double l, s, r;
+ l = up[i] * weight;
+ s = d + l;
+ r = (s - d) - l;
+ if (r > 0)
+   s -= 2*r;
+ d = s;
  weight /= MP_BASE_AS_DOUBLE;
  if (weight == 0)
break;


It may be easier to assert that FLT_RADIX==2 and use DBL_MANT_DIG to avoid 
any rounding. There is even code in one of the tests to compute 
DBL_MANT_DIG at runtime (preferably once, at startup) if it isn't 
available / reliable at compile-time.



3) Drop the generic path. It hasn't passed the testsuite for a long
time, can't be that important.


If we keep it, we'd need to (i) fix it, and (ii) test it regularly.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mpn_sqrtrem{1,2} - patch for pure C implem

2017-04-01 Thread Marc Glisse

On Sat, 1 Apr 2017, Adrien Prost-Boucle wrote:


On Sat, 2017-04-01 at 18:15 +0200, Marco Bodrato wrote:

Sorry, but even correcting the obvious typos, it doesn't pass the
tests.


I think I have found the error.
The final correction was wrong.

I hope it's OK now, but... I still can't compile GMP with ABI=32.
Like you suggested I launched: ./configure ABI=32 && make && make check
The 5th or 6th source file does not compile:

libtool: compile:  gcc -DHAVE_CONFIG_H -I. -I.. -D__GMP_WITHIN_GMP -I.. 
-DOPERATION_com -m32 -O2 -pedantic -fomit-frame-pointer -mtune=core2 
-march=core2 -c com.c  -fPIC -DPIC -o .libs/com.o
In file included from ../gmp-impl.h:147:0,
 from com.c:31:
../fib_table.h:4:1: warning: data definition has no type or storage class
 Error, error, this data is for 64 bits
 ^


Did you run "make distclean" between the 64-bit build and the 32-bit
build? (doing the build out-of-tree avoids this kind of problem, since
you can easily do the 32-bit build in a different directory)

--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mpn_sqrtrem{1,2}

2017-03-25 Thread Marc Glisse

On Sat, 25 Mar 2017, Torbjörn Granlund wrote:


The sqrtss and sqrtds are SIMD operations, right?  That means that if we
don't initialise all input fields with something, they might contain
special values which triggers exceptional conditions.


I don't think so. sqrtsd computes sqrt of the lower half of the source and 
stores it to the lower half of the destination, it doesn't touch the rest, 
so exceptional condition because of the rest seems unlikely. On the other 
hand, false dependencies are possible and can affect performance.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mpz reuse test takes too much time

2016-12-03 Thread Marc Glisse

On Sat, 3 Dec 2016, Niels Möller wrote:


"Marco Bodrato" <bodr...@mail.dm.unipi.it> writes:


! #define GCDEXT_CHECK2(i1, i2) do {\
!   mpz_gcdext (res1, res2, NULL, i1, i2);  \
!   MPZ_CHECK_FORMAT (res1);\
!   MPZ_CHECK_FORMAT (res2);\
!   if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0) \
! FAIL2 (mpz_gcdext, i1, i2, NULL); \
! } while (0)


Should we check both mpz_gcdext (res1, res2, NULL, i1, i2); and mpz_gcdext
(res1, NULL, res2, i2, i1) in this macro?


Hmm, you changed the code to not only allow G to be NULL, but allow NULL
S too?


That was already the case before my patch. Since s and t may get swapped 
depending on the values of a and b, you cannot really support t==NULL 
without supporting s==NULL. You may prefer not documenting it though...



--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mpz_gcd_ext(NULL, ...)

2016-12-02 Thread Marc Glisse

On Sat, 3 Dec 2016, Marco Bodrato wrote:


The modified manual now says that "If @var{s}, @var{t} or @var{g} is
@code{NULL} then that value is not computed.", but g is computed anyway,
even if it is not returned...


The only change is that it is about g, s and t instead of just t. But that 
was already not quite true before, since depending on a < b or b < a, we 
swap the arguments and the mpn function ends up computing t anyway. We are 
saving the copy, which counts as computation, so the formulation seemed 
good enough to me, and most importantly easy to understand for a user. If 
you want to rewrite it to clarify that the gains aren't much, please go 
ahead...


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Help stabilising mini-gmp

2016-11-25 Thread Marc Glisse

On Fri, 25 Nov 2016, Marc Glisse wrote:


On Mon, 21 Nov 2016, Torbjörn Granlund wrote:


Marc Glisse <marc.gli...@inria.fr> writes:

 On Sun, 20 Nov 2016, Niels Möller wrote:

 > It would make sense to test both gmp and mini-gmp with
 > -fsanitize=undefined.

 If we are not already doing it, yes, I highly recommend it.

It is now running for ivydeb64v9 and ivydeb32v9.

Two errors were triggered for the former, one in mini-gmp (presumably
fixed by nisse) and one on cxx/t-ops2z.  Please take a look, glisse.


Fixed. It was unhappy about (-13) << 2. I am a bit surprised it doesn't 
complain about (-13) >> 2 on the next line, we'll see if it ever becomes 
an issue.


There is something strange with https://gmplib.org/devel/tm/gmp/date.html 
. When I click to get the logs for ivydeb32v9.gmplib.org-dyn-noasm-ubsan, 
the build log is from 26/11, but the check log is from 21/11...



--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Help stabilising mini-gmp

2016-11-25 Thread Marc Glisse

On Fri, 25 Nov 2016, Torbjörn Granlund wrote:


Marc Glisse <marc.gli...@inria.fr> writes:

 Fixed. It was unhappy about (-13) << 2. I am a bit surprised it
 doesn't complain about (-13) >> 2 on the next line, we'll see if it
 ever becomes an issue.

This must be a compiler problem.  At least in C, shifting negative
integers is undefined.  It is a pity that it is, but the standard say
so.

I am less sure about C++.  Some googling did not provide a definitive
answer.

But if left shift of negative integers is undefined, surely right shift
is too!


Surprisingly, shifting negative numbers left is undefined, while
shifting them right it implementation-defined.


The value of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are 
zero-filled. If E1 has an unsigned type, the value of the result is E1 × 2^E2 , 
reduced modulo one more than the maximum value representable in the result type. 
Otherwise, if E1 has a signed type and non-negative value, and E1 × 2^E2 is 
representable in the corresponding unsigned type of the result type, then that value, 
converted to the result type, is the resulting value; otherwise, the behavior is 
undefined.

The value of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an 
unsigned type or if E1 has a signed type and a non-negative value, the value of the 
result is the integral part of the quotient of E1/2^E2 . If E1 has a signed type and 
a negative value, the resulting value is implementation-defined.

--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mpz_gcd_ext(NULL, ...)

2016-11-25 Thread Marc Glisse

On Fri, 25 Nov 2016, Niels Möller wrote:


Marc Glisse <marc.gli...@inria.fr> writes:


a user was asking if we could support calling mpz_gcd_ext with a NULL
first argument (the gcd), since they are only interested in the
coefficients s and t and would like to save the unnecessary
allocation. I doubt it would save that much, but it seems trivial to
add a check if(g!=NULL) similar to the tests for s and t. Does it make
sense to you?


Sounds reasonable to me.


Done.

But then I'd also consider adding a return value, returning one if the 
inputs were coprime (gcd == 1), otherwise zero. Would be useful for 
mpz_invert.


Makes sense. If you want to do it...


It won't save much for the computation, only the final copy. But it's
also a gain to clarity if callers don't have to pass in dummy, unused,
result arguments.


Agreed.

--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Help stabilising mini-gmp

2016-11-24 Thread Marc Glisse

On Mon, 21 Nov 2016, Torbjörn Granlund wrote:


Marc Glisse <marc.gli...@inria.fr> writes:

 On Sun, 20 Nov 2016, Niels Möller wrote:

 > It would make sense to test both gmp and mini-gmp with
 > -fsanitize=undefined.

 If we are not already doing it, yes, I highly recommend it.

It is now running for ivydeb64v9 and ivydeb32v9.

Two errors were triggered for the former, one in mini-gmp (presumably
fixed by nisse) and one on cxx/t-ops2z.  Please take a look, glisse.


Fixed. It was unhappy about (-13) << 2. I am a bit surprised it doesn't 
complain about (-13) >> 2 on the next line, we'll see if it ever becomes 
an issue.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Help stabilising mini-gmp

2016-11-20 Thread Marc Glisse

On Sun, 20 Nov 2016, Niels Möller wrote:

It would make sense to test both gmp and mini-gmp with 
-fsanitize=undefined.


If we are not already doing it, yes, I highly recommend it.

--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Help stabilising mini-gmp

2016-11-20 Thread Marc Glisse

On Sun, 20 Nov 2016, Torbjörn Granlund wrote:


Marc Glisse <marc.gli...@inria.fr> writes:

 After inlining, there are subtractions. check_si is called at least
 once with oi = si + c (c is ±1). gcc simplifies the test si > si - 1

Inlining of check_si?


Of all the functions. (note that I am just speculating, but the warning 
does not surprise me)



If the code becomes undefined by gcc's transformations, that it's a
compiler bug.


That's not at all what I said, the code doesn't become undefined. If it 
was fine, it remains fine. If it was broken, the brokenness may become 
more obvious. Let me rephrase the warning:


"Reminder: computing INT_MIN-1 is forbidden. If you are not doing that, 
you can ignore this message. I am giving you this warning because you are 
computing X-1 and I decided to key the launch of nuclear missiles to the 
value X==INT_MIN. Have a safe day!"


(the computation of X-1 is in try_op_si, but the warning points at the 
location where the compiler inserts the trigger for the nuclear missiles)


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Help stabilising mini-gmp

2016-11-20 Thread Marc Glisse

On Sun, 20 Nov 2016, Niels Möller wrote:


ni...@lysator.liu.se (Niels Möller) writes:


It seems "trivially" reproducible on ppc64 though, both real metal
versions and fake ones like ppceb-debv8 (and ppcel-debv8).


I'll try to debug (if no one else beats me to it), but not today.


I've logged in to ppceb-debv8, and it's easy to reproduce. No gdb
installed, so I'm attempting printf debugging. And then I noticed that
the test succeeds if adding a few debug printouts...

I next tried adding -Wall to the command line flags, and I see

 gcc -std=gnu99 -m64  -mtune=power7 -O3 -Wall -I../.. -c
 /home/nisse/hack/gmp/mini-gmp/tests/t-signed.c -o t-signed.o
 /home/nisse/hack/gmp/mini-gmp/tests/t-signed.c: In function 'testmain':
 /home/nisse/hack/gmp/mini-gmp/tests/t-signed.c:45:26: warning: assuming
 signed overflow does not occur when assuming that (X - c) > X is always
 false [-Wstrict-overflow]
if ((si < oi ? -1 : si > oi) != c)
   ^
 /home/nisse/hack/gmp/mini-gmp/tests/t-signed.c:45:21: warning: assuming
 signed overflow does not occur when assuming that (X + c) >= X is always
 true [-Wstrict-overflow]
if ((si < oi ? -1 : si > oi) != c)
^

I don't quite understand neither what the testcase is doing, nor what the
warning means, since there's no subtraction in there.


After inlining, there are subtractions. check_si is called at least once 
with oi = si + c (c is ±1). gcc simplifies the test si > si - 1 to true, 
and warns that this optimization may break your program if you rely on 
wrapping. The usefulness of such a warning is debatable, and we tend to 
drop some of them from gcc when we think nobody will notice.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Help stabilising mini-gmp

2016-11-19 Thread Marc Glisse

On Sat, 19 Nov 2016, Niels Möller wrote:


I don't think so. But I think the right way is to simply add $(CFLAGS)
to the linker command line. That's the usual way to use it, right?


That's a common hack (that I am ok with), but I don't think I would call 
it "the right way"...



The first failure was also a bit interesting, an internal compiler error
with gcc-6.

In file included from gmp/mini-gmp/tests/testutils.c:24:0:
gmp/mini-gmp/tests/../mini-gmp.c: In function 'mpz_set_d':
gmp/mini-gmp/tests/../mini-gmp.c:1647:3: internal compiler error:
Aborted
  if (x != x || x == x * 0.5)
  ^~

https://gmplib.org/devel/tm/gmp/build/failure/sky.gmplib.org-dyn-fat-fake:64.txt


Strange that it only shows up there, the command line does not have 
anything specific to skylake (no -march or -mtune). I can't reproduce on 
another machine.


(btw, some compilers warn about the trailing comma in enum hex_random_op)

--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Adding support for the Fuchsia OS

2016-11-11 Thread Marc Glisse

On Fri, 4 Nov 2016, Josh Conner wrote:


Hello -

I'd like to add support for fuchsia
(https://github.com/fuchsia-mirror) to libgmp. I believe the change is
trivial (just adding it to the $os conditional). I'm not sure what the
process is for submitting a proposed change to this library -- would
you like me to just send a patch?


Posting a patch to this list seems fine. What kind of special support do 
you need? I would expect most support work to happen in autoconf, libtool, 
config.guess, etc, all things were we can just import a new upstream 
version. If the patch is not a trivial one-liner, we may also need a 
copyright assignment.


Are there easy ways to test GMP on fuchsia? One of the most convenient 
things for developers is when there is a machine (possibly virtual) 
available in the gcc compile farm.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Flurry of GMP check failures

2016-11-05 Thread Marc Glisse

On Sat, 5 Nov 2016, Niels Möller wrote:


Marc Glisse <marc.gli...@inria.fr> writes:


Uh? I have 2 very natural use cases for libgmp.a:

1) to build a static (or at least with few dependencies) executable
that I am going to send to someone else [...]



2) I am rebuilding GMP on my specific platform in order to get the
best possible performance. [...]


I see. In these cases, is it important whether or not libgmp.a uses pic
code?


In the first case, it doesn't matter. In the second case, we would have to 
run benchmarks where one build uses --with-pic and not the other. The PIC 
library is a tiny bit larger (1321280 vs 1319632). GMPbench doesn't really 
see the difference on x86_64 core2 (2117 vs 2124), but it may not be the 
best test for this.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Flurry of GMP check failures

2016-11-05 Thread Marc Glisse

On Sat, 5 Nov 2016, Niels Möller wrote:

At this point in time, I think use-cases involving static libgmp.a (or 
libnettle.a) are somewhat obscure.


Uh? I have 2 very natural use cases for libgmp.a:

1) to build a static (or at least with few dependencies) executable that I 
am going to send to someone else who doesn't have much control over the 
computer he uses (either lack of permission or lack of competence).


2) I am rebuilding GMP on my specific platform in order to get the best 
possible performance. I might as well use a static libgmp to squeeze that 
extra bit of speed out of it (I might even want to use LTO in that case, 
although IIRC it currently causes some trouble in configure).


Note that I do not care about security in either case.

--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: GMP work on symbol visibility

2016-08-31 Thread Marc Glisse

On Wed, 31 Aug 2016, Torbjörn Granlund wrote:


There are several complex issues I need to understand and resolve.  One
issue is how to handle (unit) testing of hidden functions.  I will
probably resolve that with alias symbols such as foo_for_testing as an
alias for foo.


Would that be only in a temporary, testing-only libgmp.so, or also in the 
installed libgmp.so? I am guessing the second, but it seems a bit sad that 
the exported symbol list remains polluted.



Another issue is with libgmpxx.so and its dependency on libgmp.so.  As
separate shared libs, hidden symbols of libgmp.so will not be reachable
from libgmpxx.so, which of course means we cannot hide them.  Also,
there will be no performance wins for any libgmpxx.so references to
libgmp.so.

I see two solutions:

(1) If we really want to discourage external use, arrange an alias to
something wierd, making libgmpxx reach the symbol foo as fuckhead_foo.

(2) Put (allmost) all of libgmp.so in libgmpxx.so.  This gives the best
performance.


Does libgmpxx.so use that many private functions from libgmp.so and are 
they performance critical? To me, libgmpxx.so is very small and only 
contains I/O functions, where the overhead of a few calls shouldn't matter 
that much.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


RE: [PATCH] longlong.h: Fix obsolete ARC asm constraints

2016-08-24 Thread Marc Glisse

On Wed, 24 Aug 2016, Claudiu Zissulescu wrote:

The J-constant was mainly used by Arc 4 architecture for 32-bit integer 
constants. It got obsoleted once we pushed the new ARCompact 
architecture to gcc (GCC5.x+). The replace constraint is the Cal which 
is again a 32 bit constraint fitted for arithmetic ops.



On Wed, 24 Aug 2016, Vlad Zakharov wrote:


I got inspiration from the following gcc patch:
https://gcc.gnu.org/ml/gcc-patches/2016-04/msg01964.html

"J" constraint is rejected with recent gcc, so we have to replace it.



Thanks to both of you. My main concerns were (sorry, I should have stated 
it this way in the first place)


1) Does the patch break things for people using an older compiler? (how 
old?) Is it worth having both versions with an #if on the compiler 
version?


2) Do we need to backport the patch if we ever do a 6.1.2 release?

From your messages, it seems clear that the answer to 2) is yes. 1) is not 
quite clear yet though. As far as I can tell from gcc's sources, the 
current ARC port was added for gcc-4.9 and already supported "Cal". A 
previous ARC port was obsoleted in gcc-4.6. That usually means the port 
already didn't work so well in previous releases, so it may indeed be 
unnecessary to support the old syntax.


Does that make sense or did I misunderstand something? I'll probably push 
the patch in a few days, when I get the chance.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: [PATCH] longlong.h: Fix obsolete ARC asm constraints

2016-08-22 Thread Marc Glisse

On Wed, 17 Aug 2016, Vlad Zakharov wrote:


We replace obsolete "J" constraint with "Cal" constraint.


Hello,

could you give a little more information please? In particular, does "Cal" 
work with older versions of gcc? Does "J" still work or is it rejected 
with a recent gcc? Do they mean the same thing?


I trust that you know what you are doing, I just like to understand a 
patch before applying it.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Lazy mpz allocation

2016-05-04 Thread Marc Glisse

On Wed, 4 May 2016, Niels Möller wrote:


Marc Glisse <marc.gli...@inria.fr> writes:


The fact that an mpq is made of 2 mpz that can be accessed directly is
part of the interface. I think following your suggestion would mean
changing that.


I guess you're right, it would break mpq_denref. Which I guess is also
expected to work on a const mpq_t, so it's not an easy solution to
redefine it to do lazy assignment.

And it's used in quite a lot of places, debian codesearch lists the
following packages:

 python-gmpy, llvm-toolchain-3.8, mpfr4, lcalc, yap, flint-arb, mlgmp,
 ats-lang-anairiats, givaro, parrot, llvm-toolchain-snapshot, librep,
 linbox, python-gmpy2, swi-prolog, libgmpada, isl, polymake, kcalc,
 pynac, flint, pike7.8, apron, cloog, llvm-toolchain-3.7, pike8.0,
 ocamlcreal, qsopt-ex, gambas3, cgal, surf-alggeo, singular, cvc3, gmp,
 regina-normal, gcl, ppl, libaqbanking, gmp-ecm, zimpl, ats2-lang,
 ledger, libalkimia, gfan, guile-1.8, genius, postgresql-pgmp

But I'm not giving up just yet. Would it be possible to initialize the
denominator as

 static const mp_limb_t the_one = 1;

 q->_mp_den._mp_alloc = 0;
 q->_mp_den._mp_size = 1;
 q->_mp_den._mp_d = (mp_limb_t*) _one;

(This kind-of requires that _mp_alloc == 0, _mp_size != 0 is supported
in general for mpz_t, meaning any modification requires new storage, and
that the storage pointed to by _mp_d should not be deallocated by gmp).


That looks pretty much like the copy-on-write thing you and Marco were 
discussing last year


https://gmplib.org/list-archives/gmp-devel/2015-September/004169.html

It should be possible, but it may require changing quite a number of 
places in the code.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Lazy mpz allocation

2016-05-04 Thread Marc Glisse

On Wed, 4 May 2016, Niels Möller wrote:


t...@gmplib.org (Torbjörn Granlund) writes:


I forgot about that we need to have an explicit denominator.
We could surely point that to some static read-only data, but that would
of course incur a cost when "re-allocating".


I'm not familiar with mpq internals, but I guess it might be possible to
get away with leaving the denominator as zero on initialization.

Then one would need to follow the convention that if numerator is zero,
then the denominator is ignored. Or (but I guess that's more cumbersome)
adapt the convention that zero denominator means "this is an integer",
and treated as one.


The fact that an mpq is made of 2 mpz that can be accessed directly is 
part of the interface. I think following your suggestion would mean 
changing that.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Lazy mpz allocation

2016-04-11 Thread Marc Glisse

On Mon, 9 Nov 2015, Marco Bodrato wrote:


Moreover, the mpq layer and mini-gmp need to migrate to lazy allocation
too...


For mpq, the attached seems sufficient to pass make check. Of course, 
without a copy-on-write mechanism for the 1 in the denominator, the gains 
are not comparable to the mpz case, it is more for consistency.


--
Marc Glissediff -r 835f8974ff6e mpq/clear.c
--- a/mpq/clear.c   Thu Apr 07 22:50:07 2016 +0200
+++ b/mpq/clear.c   Mon Apr 11 11:42:59 2016 +0200
@@ -34,6 +34,7 @@
 void
 mpq_clear (mpq_t x)
 {
-  __GMP_FREE_FUNC_LIMBS (PTR(NUM(x)), ALLOC(NUM(x)));
+  if (ALLOC (NUM(x)))
+__GMP_FREE_FUNC_LIMBS (PTR(NUM(x)), ALLOC(NUM(x)));
   __GMP_FREE_FUNC_LIMBS (PTR(DEN(x)), ALLOC(DEN(x)));
 }
diff -r 835f8974ff6e mpq/clears.c
--- a/mpq/clears.c  Thu Apr 07 22:50:07 2016 +0200
+++ b/mpq/clears.c  Mon Apr 11 11:42:59 2016 +0200
@@ -41,7 +41,8 @@
 
   do
 {
-  __GMP_FREE_FUNC_LIMBS (PTR(NUM(x)), ALLOC(NUM(x)));
+  if (ALLOC (NUM(x)))
+   __GMP_FREE_FUNC_LIMBS (PTR(NUM(x)), ALLOC(NUM(x)));
   __GMP_FREE_FUNC_LIMBS (PTR(DEN(x)), ALLOC(DEN(x)));
   x = va_arg (ap, mpq_ptr);
 }
diff -r 835f8974ff6e mpq/init.c
--- a/mpq/init.cThu Apr 07 22:50:07 2016 +0200
+++ b/mpq/init.cMon Apr 11 11:42:59 2016 +0200
@@ -34,8 +34,9 @@
 void
 mpq_init (mpq_t x)
 {
-  ALLOC(NUM(x)) = 1;
-  PTR(NUM(x)) = __GMP_ALLOCATE_FUNC_LIMBS (1);
+  static const mp_limb_t dummy_limb=0xc1a0;
+  ALLOC(NUM(x)) = 0;
+  PTR(NUM(x)) = (mp_ptr) _limb;
   SIZ(NUM(x)) = 0;
   ALLOC(DEN(x)) = 1;
   PTR(DEN(x)) = __GMP_ALLOCATE_FUNC_LIMBS (1);
diff -r 835f8974ff6e mpq/set_si.c
--- a/mpq/set_si.c  Thu Apr 07 22:50:07 2016 +0200
+++ b/mpq/set_si.c  Mon Apr 11 11:42:59 2016 +0200
@@ -56,7 +56,7 @@
 }
   else
 {
-  PTR(NUM(dest))[0] = abs_num;
+  MPZ_NEWALLOC (NUM(dest), 1)[0] = abs_num;
   SIZ(NUM(dest)) = num > 0 ? 1 : -1;
 }
 
diff -r 835f8974ff6e mpq/set_ui.c
--- a/mpq/set_ui.c  Thu Apr 07 22:50:07 2016 +0200
+++ b/mpq/set_ui.c  Mon Apr 11 11:42:59 2016 +0200
@@ -52,7 +52,7 @@
 }
   else
 {
-  PTR(NUM(dest))[0] = num;
+  MPZ_NEWALLOC (NUM(dest), 1)[0] = num;
   SIZ(NUM(dest)) = 1;
 }
 
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Lazy mpz allocation

2016-04-01 Thread Marc Glisse

Hello,

the function mpz_init could now be marked __GMP_NOTHROW. Do we want to do 
it? I could then propagate the change to the C++ wrapper, which would have 
a significant impact on the performance of std::vector for 
instance. On the other hand, this is a promise in the interface, going 
back to a throwing mpz_init would be an ABI break.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: __uint128_t

2016-03-23 Thread Marc Glisse

On Wed, 23 Mar 2016, Victor Shoup wrote:


This may be a bit off topic, but I figure the people on this list
might know something about this.

In some code I've been developing lately (NTL related, of course),
I've been making more use of the __uint128_t type that is available
on gcc (and its clang and icc clones).  It's all ifdef'd properly, so I
only use it when it actually works.

Anyway, I find that on x86-64 machines and recent gcc's, the compiler
does a pretty good job of code generation...much better than I recall
some years ago.  However, I was wondering about the 64-bit ARM
machine.  I don't have access to such a machine, but I tried some code
out at https://gcc.godbolt.org (which is a very convenient site, by the way).
I was somewhat surprised that the code generated there by gcc-4.8 for
64-bit ARM was terrible: a 64x64->128 mul gets mapped to
a  generic128x128->128 function call.


You realize ARM64 barely existed at the time of gcc-4.8? If gcc-5, or 
better yet a snapshot of gcc-6, still generates suboptimal code, please 
report to https://gcc.gnu.org/bugzilla/ with a testcase, and the asm you 
would like gcc to generate instead.



So I'm starting to question whether relying on __uint128_t is such a good idea.
Maybe it would be better for me to isolate all of that code so that I can
just drop in appropriate assembly (as in GMP's longlong.h),
as an alternative.


It is always a compromise...


I could also ask gcc people what their plans for future optimizations
in this area are, but I don't know who or where to ask.


You could ask on g...@gcc.gnu.org, but reporting bugs when you see 
suboptimal code generated seems much more likely to get you answers, and 
by showing constructive interest it may spark further optimizations.


If this is for the development of free software, the GCC compile farm 
includes some aarch64 machines on which you could experiment.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Move -DNO_ASM to config.h?

2016-03-21 Thread Marc Glisse

On Mon, 21 Mar 2016, Vincent Lefevre wrote:


On 2016-03-20 12:14:49 +0100, Marc Glisse wrote:

but it seems likely that a user who went to the trouble of disabling
assembly for GMP doesn't want to use that same assembly in MPFR.


I'm not so sure about that. AFAIK, longlong.h has far less asm code
than the whole GMP. So, it is less likely that a user would want to
disable asm from MPFR's copy of longlong.h.


In https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69134 ( 
https://gcc.gnu.org/ml/gcc-patches/2016-01/msg00127.html ), users 
specifically wanted to disable MPFR's copy ;-)



On the other hand, MPFR could probably add a --disable-assembly
configure flag to define NO_ASM, so the user would just have to pass
the same option to MPFR that he already passed to GMP.


I don't think that such an option would really be useful (unless
there is a demand for it). The user could still pass -DNO_ASM in
CFLAGS. The drawback is that the user won't benefit from the default
CFLAGS, but if he wants -DNO_ASM, this is quite specific so that he
may not need the default CFLAGS anyway.


Ok. I guess I saw --disable-assembly mostly as a way to document this, but 
probably NO_ASM is not worth documenting in MPFR.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Move -DNO_ASM to config.h?

2016-03-20 Thread Marc Glisse

On Sun, 20 Mar 2016, Torbjörn Granlund wrote:


Marc Glisse <marc.gli...@inria.fr> writes:

 One issue with changing it is MPFR: src/mpfr-longlong.h tests for
 NO_ASM, but there is no code to define it. As far as I understand,
 MPFR uses __GMP_CFLAGS by default, in which GMP may have included
 -DNO_ASM. If we move NO_ASM to config.h, that also affects them (not
 that it should necessarily stop us). We could also define NO_ASM both
 in CFLAGS and config.h. It looks like gcc and clang only warn when
 redefining a macro to something different, they don't warn for
 -DNO_ASM with #define NO_ASM 1, so it wouldn't be so bad.

In what way is it relevant to MPFR whether a GMP build included asm or
not?


I am guessing that, just like they want to use the exact same flags as GMP 
to compile (__GMP_CFLAGS), they also want to mimic this part of the build 
process. I don't know if their version of longlong.h is kept in sync with 
GMP's, but it seems likely that a user who went to the trouble of 
disabling assembly for GMP doesn't want to use that same assembly in MPFR. 
On the other hand, MPFR could probably add a --disable-assembly configure 
flag to define NO_ASM, so the user would just have to pass the same option 
to MPFR that he already passed to GMP.


I currently think I'll go with just config.h (no CFLAGS).

--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Move -DNO_ASM to config.h?

2016-03-20 Thread Marc Glisse

On Sun, 20 Mar 2016, Niels Möller wrote:


Marc Glisse <marc.gli...@inria.fr> writes:


when configure wants to define a macro, it usually puts it in
config.h. We do have one exception: NO_ASM, which ends up defined in
CFLAGS. Was there a particular reason for this choice?


I'm greping for its uses, and it is used only in C files as far as I
can see.


I sure hope we don't use NO_ASM inside asm files ;-)
I was wondering if it was useful in the rest of the configure script, but 
it seems to be done late enough that it is unlikely.



Moving it to config.h makes sense to me. If we move it, we have make
sure that config.h is always included before longlong.h. Most files get
config.h via gmp-impl.h. So, e.g., #include "longlong.h" followed by
#include "gmp-impl.h" would break.


longlong.h requires some types like UWtype which we provide in gmp-impl.h, 
so I am hoping that the inclusions are already handled properly.



I think the autoconf manual recommends an explicit include of config.h
(guarded by HAVE_CONFIG_H) first in every C file. We don't have to do it
that way of course, just be aware that we depart from that convention.


Thanks. autoconf is still rather unfamiliar to me (though at least it 
makes more sense than the cmake I am forced to use at work).


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mpz_export to file?

2015-12-09 Thread Marc Glisse

On Wed, 9 Dec 2015, paul zimmermann wrote:


mpz_export() exports an integer to some allocated array. For saving huge
integers to a file, this is not optimal since one has first to allocate a
huge array in memory, "export" the mpz_t to that array, and then copy that
array to memory.


Can't you use mmap for that? (not arguing against your interface, just 
wondering)



Would it be possible to have a function that exports directly to a file
(and of course the corresponding import function)?

void mpz_export_file (FILE *f, mpz_t op);
void mpz_import_file (mpz_t op, FILE *f);

One could imagine a format where several numbers can be exported in the same
file:

  f = fopen ("toto", "w");
  mpz_export_file (f, a);
  mpz_export_file (f, b);
  mpz_export_file (f, c);
  fclose (f);
  ...
  f = fopen ("toto", "r");
  mpz_import_file (a, f);
  mpz_import_file (b, f);
  mpz_import_file (c, f);
  fclose (f);


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


mp_bitcnt_signed_t

2015-08-22 Thread Marc Glisse

Hello,

mpz_get_d_2exp and mpf_get_d_2exp currently take as argument a long*. 
Since we introduced a type mp_bitcnt_t, I guess it would make sense to add 
mp_bitcnt_signed_t and use it there. Any objection?


For the mpz case, the answer should always be nonnegative, so we could use 
an unsigned type if we wanted, but I guess it is better to keep the 
current signed type, which is consistent with the mpf case.


What do you think of introducing 2 typedefs mp_builtin_[su]i (or 
mp_native_[su]i or gmp_[su]i or whatever) and using them in all the 
functions with _si or _ui in their name ? Just trying to clarify why each 
type is used (unsigned long is mp_bitcnt_t in some places, mp_builtin_ui 
in others, etc).


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mpq_cmp_z

2015-08-21 Thread Marc Glisse

On Fri, 21 Aug 2015, Marco Bodrato wrote:


On Thu, August 20, 2015 9:56 am, Marc Glisse wrote:

Is casting an mpz to an mpq, then accessing only the NUM() part of it,
portable?



From what I understand of the aliasing model currently used by gcc, to
be safe, in the function using it, we should have:
mpz_srcptr op2n = NUM(op2);
and then use SIZ(op2n) instead of directly SIZ(NUM(op2)). The reason is



x=op2-_mp_den._mp_size promises that op2 points to a __mpq_struct
while x=op2n-_mp_size only promises a __mpz_struct (and gcc folds *


Maybe we can promise the right type, by adding an explicit cast?
SIZ((mpz_srcptr) NUM(op2))


I think that cast would be ignored, you really want them in separate 
expressions.


Another thing I forgot: computing DEN(op2) could also be illegal unless 
the layout of __mpq_struct is the same as __mpz_struct[2], in which case 
we are computing the past-the-end pointer of the mpz_t, which is ok.


Anyway, I was just trying to think of potential issues with the code, feel 
free to ignore it as long as nobody reports an issue with it.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mpq_cmp_z

2015-08-21 Thread Marc Glisse

On Fri, 21 Aug 2015, Torbjörn Granlund wrote:


Marco Bodrato bodr...@mail.dm.unipi.it writes:

 Maybe we can promise the right type, by adding an explicit cast?
 SIZ((mpz_srcptr) NUM(op2))

Except that we should cast op2, not NUM(ops).

I am not sure Marc's reasoning is accurate, nor am I suggesting it is
not, I've forgotten this level of detail of the C standard.  I am not
too enthusiastic about passing the wrong type, but if we add casts both
when going to mpq and when going back to mpz, I cannot see how that
could break with a conforming compiler.


Good point. I agree that (mpz_srcptr)op2 is a safer way to do the same 
thing as NUM(op2) in this case.


(I am not suggesting changing the gmp-impl implementation of NUM to a 
cast)


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mpq_cmp_z

2015-08-20 Thread Marc Glisse

On Thu, 20 Aug 2015, Marco Bodrato wrote:


Is casting an mpz to an mpq, then accessing only the NUM() part of it,
portable?


From what I understand of the aliasing model currently used by gcc, to be 

safe, in the function using it, we should have:
mpz_srcptr op2n = NUM(op2);
and then use SIZ(op2n) instead of directly SIZ(NUM(op2)). The reason is 
that as long as you are only doing pointer arithmetic (NUM counts as 
pointer arithmetic), the exact type is kind of irrelevant (size matters as 
a multiplicative factor, and alignment because it can make the result 
invalid, but that's it), but as soon as you actually use it (load or 
store), you are making a promise that the type is right. So 
x=op2-_mp_den._mp_size promises that op2 points to a __mpq_struct while 
x=op2n-_mp_size only promises a __mpz_struct (and gcc folds * to 
nothing very early, so it sees SIZ(NUM(op2)) as the first expression). 
Note that my understanding could be wrong, and other compilers could have 
a different model.


In practice, I doubt your code would fail, but with the generalization of 
link-time optimizations, the library and user code are not hidden from 
each other anymore, and surprising things could happen.


The cast itself seems fine: A pointer to a structure object, suitably 
converted, points to its initial member (or if that member is a bit-field, 
then to the unit in which it resides), and vice versa. There may be 
unnamed padding within a structure object, but not at its beginning.


On Thu, 20 Aug 2015, Torbjörn Granlund wrote:


(We might consider adding mpf_cmp_z too, at least in a simple-minded
manner, to keep the GMP interface as orthogonal as possible.)


Adding new mpf_t functions might confuse the message that people should 
use mpfr...


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: GMP and clang bugginess

2015-05-25 Thread Marc Glisse

On Thu, 21 May 2015, Marc Glisse wrote:

On powerpc-linux-gnu, clang complains about the bc+ instruction, and 
indeed I can't find that in IBM's documentation. After removing 
divrem_2.asm, it compiles fine and passes the testsuite.


Now I've found it (and reported 
https://llvm.org/bugs/show_bug.cgi?id=23646 ). Note that the same (?)

instruction is spelled differently in the same file:

bc+ 12, 28, L(9)
vs.
blt+cr7, L(24)

(there is also a mix of using 7 vs cr7)
and llvm is happy with the second form.

--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: GMP and clang bugginess

2015-05-25 Thread Marc Glisse

On Mon, 25 May 2015, Torbjörn Granlund wrote:


Marc Glisse marc.gli...@inria.fr writes:

 Now I've found it (and reported
 https://llvm.org/bugs/show_bug.cgi?id=23646 ). Note that the same (?)
 instruction is spelled differently in the same file:

bc+ 12, 28, L(9)
 vs.
blt+cr7, L(24)

Note that the former form works with clang 3.5 installs.  A 3.6
regression?


Indeed...


 (there is also a mix of using 7 vs cr7)
 and llvm is happy with the second form.

Please point me to the place where 7 is used.


Ah, no, my mistake, I got confused by the preprocessing.

--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: GMP and clang bugginess

2015-05-25 Thread Marc Glisse

On Mon, 25 May 2015, Marc Glisse wrote:


On Mon, 25 May 2015, Torbjörn Granlund wrote:


Marc Glisse marc.gli...@inria.fr writes:

 Now I've found it (and reported
 https://llvm.org/bugs/show_bug.cgi?id=23646 ). Note that the same (?)
 instruction is spelled differently in the same file:

bc+ 12, 28, L(9)
 vs.
blt+cr7, L(24)

Note that the former form works with clang 3.5 installs.  A 3.6
regression?


Indeed...


Er, actually, that's just the time when they enabled the integrated 'as' 
by default, 3.5 was using binutils.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: GMP and clang bugginess

2015-05-21 Thread Marc Glisse

On Thu, 21 May 2015, Torbjörn Granlund wrote:


GMP triggers bugs in clang on every platform where we tried this
compiler.  Some configs work, though.

To see how bad it is, please take a look here:

 https://gmplib.org/devel/tm-date.html

I think we would help our users by making it hard to use clang with the
next release.  What do you think?

My idea is to reject clang with an error message along these lines:

error: clang is not able to correctly compile GMP.  To override, use
--enable-clang.  Make sure to run make check and don't use the library
of this fails.


It is your call, but that seems a bit excessive to me. I just did a few 
tests with clang-3.6. It seems to work fine on x86_64, so probably on 
macs, where it is the default compiler and a large part of the user base 
is.


On powerpc-linux-gnu, clang complains about the bc+ instruction, and 
indeed I can't find that in IBM's documentation. After removing 
divrem_2.asm, it compiles fine and passes the testsuite.


aarch64-linux-gnu and arm-linux-gnueabihf are working fine for me.

powerpc64le-linux-gnu seems broken indeed.

I tend to consider that the usual run the testsuite message is 
sufficient, possibly with extra warnings in the release notes or some such 
place. But again, your call.



--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Adding support for R6 of MIPS architecture

2015-02-02 Thread Marc Glisse

On Mon, 2 Feb 2015, Torbjörn Granlund wrote:


Does MIPS64r6 contain all older architecture revisions as a subset,


Apparently not, the motivation for the patch is that multu has 
disappeared...


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: Additional memory handler features.

2015-01-04 Thread Marc Glisse

On Sun, 4 Jan 2015, Victor Shoup wrote:


But I see mention of itching and scratching: could somebody
describe what that is or provide a link? Sorry for my ignorance.
and sorry for the length of this post


The general idea is to push all operations that may fail or otherwise
require customization to user code. There would be a function
mpn_mul_itch that would tell you how much temporary (scratch) space
mpn_mul may need, and mpn_mul would take as argument a pointer to a
buffer of at least this size. Allocation is the user's responsibility. 
There should already be a few functions or macros with itch in their 
name.



[FULL DISCLOSURE: my own, somewhat narrow and selfish goal
is to see GMP's mpn-level routines throw exceptions, rather
than abort, with no interface changes.  This is what would work
best for my own NTL library]


mpn functions have few reasons to abort. Except for allocation failure,
as long as you checked the operands before passing them to GMP...


[And yet another issue: my understanding is that some OS's actually
have rather weird ways of dealing with out-of-memory errors:
malloc always succeeds and returns a non-null pointer, but
indirecting through that pointer may abort the program.
In such a setting, all of this memory-related error handling
stuff is pointless]


Yes. Memory overcommit can often be disabled or mitigated in various
ways, but it does complicate things (get a better OS ;-)

--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


C++ factorial error reporting

2014-12-27 Thread Marc Glisse

Hello,

I am trying to add factorial to the C++ interface, and since GMP only 
provides mpz_fac_ui, I end up having to check and report errors directly. 
Any preferences?


Calling factorial on a negative integer doesn't make sense, we could have 
assert(number = 0). I am throwing an exception because that seems a 
little friendlier, but I am still choosing one that derives from 
logic_error.


Calling factorial on a number that is a bit too large is a different 
issue. overflow_error is the natural exception when trying to convert an 
mpz_class to an unsigned long if it will not fit. But even if it fits, it 
may still be too big and mpz_fac_ui may fail, in the allocation function, 
which might abort but a natural replacement would throw bad_alloc. I don't 
think it makes that much sense to have a different exception depending on 
who notices that the number is too big, which is why I was also 
considering throwing bad_alloc instead of overflow_error.


We could also pick a single exception and throw it for both negative and 
too-big.


(you can check the list of standard exceptions at 
http://en.cppreference.com/w/cpp/error/exception , defining our own 
exception type doesn't seem worth the trouble)


struct __gmp_factorial_function
{
  static void eval(mpz_ptr z, mpz_srcptr w)
  {
if (mpz_sgn(w)  0)
  throw std::domain_error (factorial(negative));
// There is no point trying to compute such a huge number.
if (!mpz_fits_ulong_p(w))
  throw std::overflow_error (factorial); // or std::bad_alloc()?
eval(z, mpz_get_ui(w));
  }
  static void eval(mpz_ptr z, unsigned long int l) { mpz_fac_ui(z, l); }
  static void eval(mpz_ptr z, signed long int l)
  {
if (l  0)
  throw std::domain_error (factorial(negative));
eval(z, static_castunsigned long(l));
  }
  static void eval(mpz_ptr z, double d)
  {  __GMPXX_TMPZ_D;eval (z, temp); }
};


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


TMP_ALLOC in C++

2014-12-18 Thread Marc Glisse

Hello,

this patch moves deallocation of temporary memory to a destructor when GMP 
is compiled with a C++ compiler. This may not be the final form of the 
patch, but I am interested in comments. Most of the patch is adjustments 
to tests/mpn so that temporary memory is freed before calling tests_end.


(for the tal-debug.c patch, it may be simpler to change the type of block 
to void* in gmp-impl.h)


--
Marc Glissediff --git a/gmp-impl.h b/gmp-impl.h
--- a/gmp-impl.h
+++ b/gmp-impl.h
@@ -5150,16 +5150,53 @@ mpn_toom54_mul_itch (mp_size_t an, mp_si
 #if 0
 #define mpn_fft_mul mpn_mul_fft_full
 #else
 #define mpn_fft_mul mpn_nussbaumer_mul
 #endif
 
 #ifdef __cplusplus
 
+/* Handle C++ exceptions.  */
+#if !WANT_TMP_DEBUG || __cplusplus = 201103L
+struct gmp_tmp_salloc_t {
+  /* May warn in pedantic mode when TMP_SDECL is empty.  */
+  TMP_SDECL;
+  gmp_tmp_salloc_t(){ TMP_SMARK; }
+  void*salloc(size_t n){ return TMP_SALLOC(n); }
+  ~gmp_tmp_salloc_t(){ TMP_SFREE; }
+};
+struct gmp_tmp_alloc_t {
+  TMP_DECL;
+  gmp_tmp_alloc_t(){ TMP_MARK; }
+  void*salloc(size_t n){ return TMP_SALLOC(n); }
+  void*balloc(size_t n){ return TMP_BALLOC(n); }
+  void*alloc(size_t n){ return TMP_ALLOC(n); }
+  ~gmp_tmp_alloc_t(){ TMP_FREE; }
+};
+#undef TMP_SDECL
+#undef TMP_DECL
+#undef TMP_SMARK
+#undef TMP_MARK
+#undef TMP_SALLOC
+#undef TMP_BALLOC
+#undef TMP_ALLOC
+#undef TMP_SFREE
+#undef TMP_FREE
+#define TMP_SDECL
+#define TMP_DECL
+#define TMP_SMARK  gmp_tmp_salloc_t gmp_tmp_alloc
+#define TMP_MARK   gmp_tmp_alloc_t gmp_tmp_alloc
+#define TMP_SALLOC(n)  gmp_tmp_alloc.salloc(n)
+#define TMP_BALLOC(n)  gmp_tmp_alloc.balloc(n)
+#define TMP_ALLOC(n)   gmp_tmp_alloc.alloc(n)
+#define TMP_SFREE
+#define TMP_FREE
+#endif
+
 /* A little helper for a null-terminated __gmp_allocate_func string.
The destructor ensures it's freed even if an exception is thrown.
The len field is needed by the destructor, and can be used by anyone else
to avoid a second strlen pass over the data.
 
Since our input is a C string, using strlen is correct.  Perhaps it'd be
more C++-ish style to use std::char_traitschar::length, but char_traits
isn't available in gcc 2.95.4.  */
diff --git a/mpf/get_str.c b/mpf/get_str.c
--- a/mpf/get_str.c
+++ b/mpf/get_str.c
@@ -175,16 +175,17 @@ mpf_get_str (char *dbuf, mp_exp_t *exp, 
   if (un == 0)
 {
   *exp = 0;
   *dbuf = 0;
   n_digits = 0;
   goto done;
 }
 
+  {
   TMP_MARK;
 
   /* Allocate temporary digit space.  We can't put digits directly in the user
  area, since we generate more digits than requested.  (We allocate
  2 * GMP_LIMB_BITS extra bytes because of the digit block nature of the
  conversion.)  */
   tstr = (unsigned char *) TMP_ALLOC (n_digits + 2 * GMP_LIMB_BITS + 3);
 
@@ -312,16 +313,17 @@ mpf_get_str (char *dbuf, mp_exp_t *exp, 
 
   if (SIZ(u)  0)
 {
   dbuf[0] = '-';
   n_digits++;
 }
 
   TMP_FREE;
+  }
 
  done:
   /* If the string was alloced then resize it down to the actual space
  required.  */
   if (alloc_size != 0)
 {
   __GMP_REALLOCATE_FUNC_MAYBE_TYPE (dbuf, alloc_size, n_digits + 1, char);
 }
diff --git a/tal-debug.c b/tal-debug.c
--- a/tal-debug.c
+++ b/tal-debug.c
@@ -103,17 +103,17 @@ void *
 {
   __gmp_assert_header (file, line);
   fprintf (stderr, GNU MP: TMP_ALLOC without TMP_MARK(%s)\n, decl_name);
   abort ();
 }
 
   p = __GMP_ALLOCATE_FUNC_TYPE (1, struct tmp_debug_entry_t);
   p-size = size;
-  p-block = (*__gmp_allocate_func) (size);
+  p-block = (char*) (*__gmp_allocate_func) (size);
   p-next = mark-list;
   mark-list = p;
   return p-block;
 }
 
 void
 __gmp_tmp_debug_free (const char *file, int line, int dummy,
   struct tmp_debug_t **markp,
diff --git a/tests/mpn/logic.c b/tests/mpn/logic.c
--- a/tests/mpn/logic.c
+++ b/tests/mpn/logic.c
@@ -57,78 +57,80 @@ check_one (mp_srcptr refp, mp_srcptr rp,
 int
 main (int argc, char **argv)
 {
   mpz_t a, b;
   mp_ptr ap, bp, rp, refp;
   mp_size_t max_n, n, i;
   gmp_randstate_ptr rands;
   long test, reps = 1000;
-  TMP_DECL;
-  TMP_MARK;
+  {
+TMP_DECL;
+TMP_MARK;
 
-  tests_start ();
-  TESTS_REPS (reps, argv, argc);
+tests_start ();
+TESTS_REPS (reps, argv, argc);
 
-  mpz_inits (a, b, NULL);
+mpz_inits (a, b, NULL);
 
-  rands = RANDS;   /* FIXME: not used */
+rands = RANDS; /* FIXME: not used */
 
-  max_n = 100;
+max_n = 100;
 
-  rp = TMP_ALLOC_LIMBS (1 + max_n * 8 / GMP_LIMB_BITS);
-  refp = TMP_ALLOC_LIMBS (1 + max_n * 8 / GMP_LIMB_BITS);
+rp = TMP_ALLOC_LIMBS (1 + max_n * 8 / GMP_LIMB_BITS);
+refp = TMP_ALLOC_LIMBS (1 + max_n * 8 / GMP_LIMB_BITS);
 
-  for (test = 0; test  reps; test++)
-{
-  for (i = 1; i = max_n; i++)
-   {
- mpz_rrandomb (a, rands, i * 8);
- mpz_rrandomb (b, rands, i * 8);
- mpz_setbit (a, i * 8 - 1);
- mpz_setbit (b, i * 8 - 1);
- 

Re: Compiling GMP with clang

2014-11-30 Thread Marc Glisse

On Sat, 29 Nov 2014, Torbjörn Granlund wrote:


3. Link errors on some arm32 systems.  We have not investigates this.
  Help is welcome. Failure log:
  
https://gmplib.org/devel/testmachines/build/failure/armv5.gmplib.org-stat-clang-clang++:standard.txt


#include stdexcept
int main(){throw std::invalid_argument(hello);}

$ clang++ -target arm-linux-gnueabi main.cc
$ clang++ -target arm-linux-gnueabi main.cc -O -latomic
$ clang++ -target arm-linux-gnueabi main.cc -O
/tmp/main-d6b7a1.o: In function `main':
main.cc:(.text+0x84): undefined reference to `__atomic_fetch_add_4'

It should be possible to test this in configure.

I don't know how relevant armv5 is to GMP though.

(I also killed lt-reuse after 5 minutes, but it might just be that long)

-stdlib=libc++ testing is complicated because of 
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=771512


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: allocated blocks holding pointers to other allocated blocks

2014-03-06 Thread Marc Glisse

On Wed, 5 Mar 2014, David Warme wrote:


The GMP manual on Custom Allocation contains the following paragraph:

GMP may use allocated blocks to hold pointers to other allocated
blocks.  This will limit the assumptions a conservative garbage
collection scheme can make.

Questions:

1. This seems like a situation that can only exist while certain GMP
  routines are active in the call stack context -- if no GMP function is
  active, then this situation will not exist, correct?


That's not obvious to me.


2. What places within GMP use this technique (pervasive, or hopefully
  just a few places)?


I am surprised google didn't point you to:
https://gmplib.org/list-archives/gmp-discuss/2009-May/003733.html

Apparently, I had only found one at the time, and I doubt we introduced 
many since. But I could have missed other places.


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mpz_limbs interface

2014-02-06 Thread Marc Glisse

On Thu, 6 Feb 2014, Niels Möller wrote:


ni...@lysator.liu.se (Niels Möller) writes:


For mpn_set_d, I think it would make some sense to have it return a
base-2 exponent, and write the mantissa to a few limbs. Number of limbs
would be a constant, part of the ABI, similar to LIMBS_PER_DOUBLE but
renamed for external use.

  mp_bitcnt_t
  mpn_set_d (mp_limb_t rp[LIMBS_PER_BOUBLE], d);


Below is a patch to do this (and return value is long, not mp_bitcnt_t,
since it needs to be signed).


Thanks.


What do you think?


(I haven't looked at it much yet)

Why not return int, since int is what we use for _mp_size?

Is 53 really safe for non-IEEE double? Maybe something based on 
DBL_MANT_DIG, assuming that FLT_RADIX==2?


I don't think we are still supporting gcc-2.8...

From a performance POV, it may not be optimal to split the 
sign/infinity/nan/zero test from the rest, but I agree it makes the 
interface simpler.



+   ASSERT (d != 0.5*d);/* Exclude infinities */


That excludes more than infinities, it might also exclude FLT_TRUE_MIN, 
no?


--
Marc Glisse
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


  1   2   >