Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: 69c5cb36ba
Fetching contributors…

Cannot retrieve contributors at this time

154 lines (122 sloc) 3.284 kb
/* pmpz_bits -- bit manipulation functions
*
* Copyright (C) 2011 Daniele Varrazzo
*
* This file is part of the PostgreSQL GMP Module
*
* The PostgreSQL GMP Module is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 3 of the License,
* or (at your option) any later version.
*
* The PostgreSQL GMP Module is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the PostgreSQL GMP Module. If not, see
* http://www.gnu.org/licenses/.
*/
#include "pmpz.h"
#include "pgmp-impl.h"
#include "fmgr.h"
#include "funcapi.h"
/* Function with a more generic signature are defined in pmpz.arith.c */
/* Macro to get and return mp_bitcnt_t
*
* the value is defined as unsigned long, so it doesn't fit into an int8 on 64
* bit platform. We'll convert them to/from mpz in SQL.
*/
#define PGMP_GETARG_BITCNT(tgt,n) \
do { \
mpz_t _tmp; \
PGMP_GETARG_MPZ(_tmp, n); \
\
if (!(mpz_fits_ulong_p(_tmp))) { \
ereport(ERROR, ( \
errcode(ERRCODE_INVALID_PARAMETER_VALUE), \
errmsg("argument doesn't fit into a bitcount type") )); \
} \
\
tgt = mpz_get_ui(_tmp); \
} while (0)
#define PGMP_RETURN_BITCNT(n) \
do { \
mpz_t _rv; \
mpz_init_set_ui(_rv, n); \
PGMP_RETURN_MPZ(_rv); \
} while (0)
/* Return the largest possible mp_bitcnt_t. Useful for testing the return
* value of a few other bit manipulation functions as the value depends on the
* server platform.
*/
PGMP_PG_FUNCTION(pgmp_max_bitcnt)
{
mp_bitcnt_t ret;
ret = ~((mp_bitcnt_t)0);
PGMP_RETURN_BITCNT(ret);
}
PGMP_PG_FUNCTION(pmpz_popcount)
{
const mpz_t z;
mp_bitcnt_t ret;
PGMP_GETARG_MPZ(z, 0);
ret = mpz_popcount(z);
PGMP_RETURN_BITCNT(ret);
}
PGMP_PG_FUNCTION(pmpz_hamdist)
{
const mpz_t z1;
const mpz_t z2;
mp_bitcnt_t ret;
PGMP_GETARG_MPZ(z1, 0);
PGMP_GETARG_MPZ(z2, 1);
ret = mpz_hamdist(z1, z2);
PGMP_RETURN_BITCNT(ret);
}
#define PMPZ_SCAN(f) \
\
PGMP_PG_FUNCTION(pmpz_ ## f) \
{ \
const mpz_t z; \
mp_bitcnt_t start; \
\
PGMP_GETARG_MPZ(z, 0); \
PGMP_GETARG_BITCNT(start, 1); \
\
PGMP_RETURN_BITCNT(mpz_ ## f(z, start)); \
}
PMPZ_SCAN(scan0)
PMPZ_SCAN(scan1)
/* inplace bit fiddling operations */
#define PMPZ_BIT(f) \
\
PGMP_PG_FUNCTION(pmpz_ ## f) \
{ \
const mpz_t z; \
mp_bitcnt_t idx; \
mpz_t ret; \
\
PGMP_GETARG_MPZ(z, 0); \
PGMP_GETARG_BITCNT(idx, 1); \
\
mpz_init_set(ret, z); \
mpz_ ## f(ret, idx); \
PGMP_RETURN_MPZ(ret); \
}
PMPZ_BIT(setbit)
PMPZ_BIT(clrbit)
#if __GMP_MP_RELEASE >= 40200
PMPZ_BIT(combit)
#endif
PGMP_PG_FUNCTION(pmpz_tstbit)
{
const mpz_t z;
mp_bitcnt_t idx;
int32 ret;
PGMP_GETARG_MPZ(z, 0);
PGMP_GETARG_BITCNT(idx, 1);
ret = mpz_tstbit(z, idx);
PG_RETURN_INT32(ret);
}
Jump to Line
Something went wrong with that request. Please try again.