Permalink
Browse files

Merge branch 'gmp-41-support'

  • Loading branch information...
2 parents a225104 + 7b85bea commit 42e0c32d5f7fc5687f0f88351133c8df6131ab98 @dvarrazzo committed Apr 22, 2011
Showing with 118 additions and 17 deletions.
  1. +13 −1 docs/install.rst
  2. +5 −0 docs/mpq.rst
  3. +11 −0 docs/mpz.rst
  4. +16 −0 src/pgmp-impl.h
  5. +6 −4 src/pmpq_io.c
  6. +15 −1 src/pmpz_arith.c
  7. +3 −0 src/pmpz_bits.c
  8. +6 −4 src/pmpz_io.c
  9. +3 −0 src/pmpz_rand.c
  10. +5 −1 src/pmpz_roots.c
  11. +23 −0 src/pmpz_theor.c
  12. +4 −2 test/expected/mpq.out
  13. +4 −2 test/expected/mpz.out
  14. +2 −1 test/sql/mpq.sql
  15. +2 −1 test/sql/mpz.sql
View
@@ -7,7 +7,12 @@ Prerequisites
`!pgmp` is currently compatible with:
- PostgreSQL from version 8.4
-- GMP from version 4.3 (tested with versions 4.3.2 and 5.0.1)
+- GMP from version 4.1 (tested with versions 4.1.4, 4.2.4, 4.3.2 and 5.0.1)
+
+.. note::
+ GMP 4.1 doesn't implement a few functions (`rootrem()`, `combit()`,
+ `randinit_mt()`) and the maximum base accepted by the I/O functions is
+ 36, not 62.
Building the library
@@ -40,6 +45,13 @@ You can test the installation with:
(adjust the :envvar:`REGRESS_OPTS` variable to select a test database).
+.. note::
+ Because of the missing function in GMP 4.1 (see Prerequisites_), a few
+ tests are expected to fail with this library version. After running the
+ test suite you may check the ``regression.diff`` file to verify that the
+ only tests failed are the ones related to the missing functionalities and
+ the different default random numbers gerenator algorithm.
+
Installing the extension
------------------------
View
@@ -66,6 +66,9 @@ operators. Indexes on `!mpq` columns can be created using the *btree* or the
denominator, so for instance ``0xEF/100`` is 239/100, whereas
``0xEF/0x100`` is 239/256.
+ .. note:: The maximum base accepted by GMP 4.1 is 36, not 62.
+
+
.. function:: text(q)
text(q, base)
@@ -81,6 +84,8 @@ operators. Indexes on `!mpq` columns can be created using the *btree* or the
lower-case letters (in that significance order) are used. If *base* is not
specified, 10 is assumed.
+ .. note:: The maximum base accepted by GMP 4.1 is 36, not 62.
+
`!mpq` conversions
------------------
View
@@ -52,6 +52,9 @@ operators. Indexes on `!mpz` columns can be created using the *btree* or the
16 | 10 | 8 | 2
+ .. note:: The maximum base accepted by GMP 4.1 is 36, not 62.
+
+
.. function:: text(z)
text(z, base)
@@ -64,6 +67,8 @@ operators. Indexes on `!mpz` columns can be created using the *btree* or the
lower-case letters (in that significance order) are used. If *base* is not
specified, 10 is assumed.
+ .. note:: The maximum base accepted by GMP 4.1 is 36, not 62.
+
Arithmetic Operators and Functions
----------------------------------
@@ -308,6 +313,8 @@ Root Extraction Functions
------+-----
3 | 1
+ .. note:: The function is not available on GMP version < 4.2.
+
.. function:: sqrt(op)
Return the truncated integer part of the square root of *op*.
@@ -562,6 +569,8 @@ number 0.
Return *op* with bit *bit_index* complemented.
+ .. note:: The function is not available on GMP version < 4.2.
+
.. function:: tstbit(op, bit_index)
Test bit *bit_index* in *op* and return 0 or 1 accordingly.
@@ -590,6 +599,8 @@ and can be seeded with the `randseed()` function.
.. __: http://en.wikipedia.org/wiki/Mersenne_twister
+ .. note:: The function is not available on GMP version < 4.2.
+
.. function:: randinit_lc_2exp(a, c, e)
View
@@ -145,6 +145,22 @@ do { \
#endif
+/* Not available e.g. on GMP 4.1 */
+#ifndef __GMP_MP_RELEASE
+#define __GMP_MP_RELEASE ( \
+ __GNU_MP_VERSION * 10000 + \
+ __GNU_MP_VERSION_MINOR * 100 + \
+ __GNU_MP_VERSION_PATCHLEVEL)
+#endif
+
+/* The text parsing functions have different range across versions */
+#if __GMP_MP_RELEASE >= 40200
+#define PGMP_MAXBASE_IO 62
+#else
+#define PGMP_MAXBASE_IO 36
+#endif
+
+
#endif /* __PGMP_IMPL_H__ */
View
@@ -63,12 +63,12 @@ PGMP_PG_FUNCTION(pmpq_in_base)
base = PG_GETARG_INT32(1);
- if (!(base == 0 || (2 <= base && base <= 62)))
+ if (!(base == 0 || (2 <= base && base <= PGMP_MAXBASE_IO)))
{
ereport(ERROR, (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid base for mpq input: %d", base),
- errhint("base should be between 2 and 62")));
+ errhint("base should be between 2 and %d", PGMP_MAXBASE_IO)));
}
str = TextDatumGetCString(PG_GETARG_POINTER(0));
@@ -116,12 +116,14 @@ PGMP_PG_FUNCTION(pmpq_out_base)
PGMP_GETARG_MPQ(q, 0);
base = PG_GETARG_INT32(1);
- if (!((-36 <= base && base <= -2) || (2 <= base && base <= 62)))
+ if (!((-36 <= base && base <= -2) ||
+ (2 <= base && base <= PGMP_MAXBASE_IO)))
{
ereport(ERROR, (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid base for mpq output: %d", base),
- errhint("base should be between -36 and -2 or between 2 and 62")));
+ errhint("base should be between -36 and -2 or between 2 and %d",
+ PGMP_MAXBASE_IO)));
}
/* Allocate the output buffer manually - see mpmz_out to know why */
View
@@ -66,7 +66,6 @@ PGMP_PG_FUNCTION(pmpz_ ## op) \
PMPZ_UN(neg, PMPZ_NO_CHECK)
PMPZ_UN(abs, PMPZ_NO_CHECK)
PMPZ_UN(sqrt, PMPZ_CHECK_NONEG)
-PMPZ_UN(nextprime, PMPZ_NO_CHECK)
PMPZ_UN(com, PMPZ_NO_CHECK)
@@ -288,6 +287,13 @@ PGMP_PG_FUNCTION(pmpz_divisible)
PGMP_GETARG_MPZ(n, 0);
PGMP_GETARG_MPZ(d, 1);
+ /* GMP 4.1 doesn't guard for zero */
+#if __GMP_MP_RELEASE < 40200
+ if (UNLIKELY(MPZ_IS_ZERO(d))) {
+ PG_RETURN_BOOL(MPZ_IS_ZERO(n));
+ }
+#endif
+
PG_RETURN_BOOL(mpz_divisible_p(n, d));
}
@@ -312,6 +318,14 @@ PGMP_PG_FUNCTION(pmpz_congruent)
PGMP_GETARG_MPZ(c, 1);
PGMP_GETARG_MPZ(d, 2);
+ /* GMP 4.1 doesn't guard for zero */
+#if __GMP_MP_RELEASE < 40200
+ if (UNLIKELY(MPZ_IS_ZERO(d))) {
+ PG_RETURN_BOOL(0 == mpz_cmp(n, c));
+ }
+#endif
+
+
PG_RETURN_BOOL(mpz_congruent_p(n, c, d));
}
View
@@ -132,7 +132,10 @@ PGMP_PG_FUNCTION(pmpz_ ## f) \
PMPZ_BIT(setbit)
PMPZ_BIT(clrbit)
+
+#if __GMP_MP_RELEASE >= 40200
PMPZ_BIT(combit)
+#endif
PGMP_PG_FUNCTION(pmpz_tstbit)
View
@@ -62,12 +62,12 @@ PGMP_PG_FUNCTION(pmpz_in_base)
base = PG_GETARG_INT32(1);
- if (!(base == 0 || (2 <= base && base <= 62)))
+ if (!(base == 0 || (2 <= base && base <= PGMP_MAXBASE_IO)))
{
ereport(ERROR, (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid base for mpz input: %d", base),
- errhint("base should be between 2 and 62")));
+ errhint("base should be between 2 and %d", PGMP_MAXBASE_IO)));
}
str = TextDatumGetCString(PG_GETARG_POINTER(0));
@@ -112,12 +112,14 @@ PGMP_PG_FUNCTION(pmpz_out_base)
PGMP_GETARG_MPZ(z, 0);
base = PG_GETARG_INT32(1);
- if (!((-36 <= base && base <= -2) || (2 <= base && base <= 62)))
+ if (!((-36 <= base && base <= -2) ||
+ (2 <= base && base <= PGMP_MAXBASE_IO)))
{
ereport(ERROR, (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid base for mpz output: %d", base),
- errhint("base should be between -36 and -2 or between 2 and 62")));
+ errhint("base should be between -36 and -2 or between 2 and %d",
+ PGMP_MAXBASE_IO)));
}
/* Allocate the output buffer manually - see mpmz_out to know why */
View
@@ -94,7 +94,10 @@ PGMP_PG_FUNCTION(pgmp_ ## f) \
#define PGMP_RANDINIT_NOARG(f) gmp_ ## f (*state)
PGMP_RANDINIT(randinit_default, PGMP_RANDINIT_NOARG)
+
+#if __GMP_MP_RELEASE >= 40200
PGMP_RANDINIT(randinit_mt, PGMP_RANDINIT_NOARG)
+#endif
#define PGMP_RANDINIT_ACE(f) \
View
@@ -26,7 +26,9 @@
#include "funcapi.h"
-/* Function with a more generic signature are defined in pmpz.arith.c */
+/* Functions with a more generic signature are defined in pmpz.arith.c */
+
+#if __GMP_MP_RELEASE >= 40200
PGMP_PG_FUNCTION(pmpz_rootrem)
{
@@ -48,6 +50,8 @@ PGMP_PG_FUNCTION(pmpz_rootrem)
PGMP_RETURN_MPZ_MPZ(zroot, zrem);
}
+#endif
+
PGMP_PG_FUNCTION(pmpz_sqrtrem)
{
const mpz_t z1;
View
@@ -39,6 +39,29 @@ PGMP_PG_FUNCTION(pmpz_probab_prime_p)
PG_RETURN_INT32(mpz_probab_prime_p(z1, reps));
}
+PGMP_PG_FUNCTION(pmpz_nextprime)
+{
+ const mpz_t z1;
+ mpz_t zf;
+
+ PGMP_GETARG_MPZ(z1, 0);
+
+ mpz_init(zf);
+
+#if __GMP_MP_RELEASE < 40300
+ if (UNLIKELY(mpz_sgn(z1) < 0)) {
+ mpz_set_ui(zf, 2);
+ }
+ else
+#endif
+ {
+ mpz_nextprime(zf, z1);
+ }
+
+ PGMP_RETURN_MPZ(zf);
+}
+
+
PGMP_PG_FUNCTION(pmpz_gcdext)
{
const mpz_t z1;
View
@@ -108,8 +108,10 @@ SELECT mpq('EF/100', 16);
239/256
SELECT mpq('0xEF/100', 0);
239/100
-SELECT mpq('z', 36), mpq('z', 62), mpq('Z', 36), mpq('Z', 62);
-35|61|35|35
+SELECT mpq('z', 36), mpq('Z', 36);
+35|35
+SELECT mpq('z', 62), mpq('Z', 62);
+61|35
SELECT mpq('1', 1);
ERROR: invalid base for mpq input: 1
HINT: base should be between 2 and 62
View
@@ -52,8 +52,10 @@ SELECT '123456789012345678901234567890123456789012345678901234567890123456789012
-- other bases
SELECT '0x10'::mpz, '010'::mpz, '0b10'::mpz;
16|8|2
-SELECT mpz('10'), mpz('10', 16), mpz('10', 2), mpz('10', 62);
-10|16|2|62
+SELECT mpz('10'), mpz('10', 16), mpz('10', 2);
+10|16|2
+SELECT mpz('10', 62);
+62
SELECT mpz('10', 1);
ERROR: invalid base for mpz input: 1
HINT: base should be between 2 and 62
View
@@ -69,7 +69,8 @@ SELECT mpq('10/30', 10);
SELECT mpq('EF/100', 16);
SELECT mpq('0xEF/100', 0);
-SELECT mpq('z', 36), mpq('z', 62), mpq('Z', 36), mpq('Z', 62);
+SELECT mpq('z', 36), mpq('Z', 36);
+SELECT mpq('z', 62), mpq('Z', 62);
SELECT mpq('1', 1);
SELECT mpq('1', -10);
SELECT mpq('1', 63);
View
@@ -39,7 +39,8 @@ SELECT '123456789012345678901234567890123456789012345678901234567890123456789012
-- other bases
SELECT '0x10'::mpz, '010'::mpz, '0b10'::mpz;
-SELECT mpz('10'), mpz('10', 16), mpz('10', 2), mpz('10', 62);
+SELECT mpz('10'), mpz('10', 16), mpz('10', 2);
+SELECT mpz('10', 62);
SELECT mpz('10', 1);
SELECT mpz('10', 63);
SELECT mpz('10', 0), mpz('0x10', 0), mpz('010', 0), mpz('0b10', 0);

0 comments on commit 42e0c32

Please sign in to comment.