From 9163b39d155370aefed24a640c728be9107727b6 Mon Sep 17 00:00:00 2001 From: Levi Aul Date: Sun, 26 Jan 2020 12:36:23 -0800 Subject: [PATCH 1/2] Add bytea IO functions --- sql/pgmp.pysql | 4 +++- src/pmpz_io.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/sql/pgmp.pysql b/sql/pgmp.pysql index 44160c4..c9ef4f6 100644 --- a/sql/pgmp.pysql +++ b/sql/pgmp.pysql @@ -118,6 +118,7 @@ castfrom('int8', implicit='I') castfrom('float4', implicit='A') castfrom('float8', implicit='A') castfrom('numeric', implicit='A') +castfrom('bytea', implicit='A') def castto(typname, implicit=False): """Create a cast from `base_type` to a different type""" @@ -134,6 +135,7 @@ castto('int4', implicit='A') castto('int2', implicit='A') castto('float4', implicit='A') castto('float8', implicit='A') +castto('bytea', implicit='A') !! PYOFF @@ -288,7 +290,7 @@ CREATE OPERATOR <> ( def bop(sym, fname, comm, neg): """Create an operator on `base_type` returning a bool""" - func('%s_%s' % (base_type, fname), + func('%s_%s' % (base_type, fname), base_type + " " + base_type, argout='boolean') fname1 = fname[0] + 't' diff --git a/src/pmpz_io.c b/src/pmpz_io.c index 0ed2bca..64e2724 100644 --- a/src/pmpz_io.c +++ b/src/pmpz_io.c @@ -390,3 +390,57 @@ PGMP_PG_FUNCTION(pmpz_to_float8) PG_RETURN_FLOAT8((float8)out); } +PGMP_PG_FUNCTION(pmpz_from_bytea) +{ + bytea *data = PG_GETARG_BYTEA_PP(0); + int data_len = VARSIZE_ANY_EXHDR(data); + char *data_body = VARDATA_ANY(data); + mpz_t result_z; + + mpz_init(result_z); + + if(data_len == 0) { + PGMP_RETURN_MPZ(result_z); + } + + if(!(data_len & 7)) { + mpz_import(result_z, data_len / 8, 1, 8, 1, 0, (uint64_t *)data_body); + } else if(!(data_len & 3)) { + mpz_import(result_z, data_len / 4, 1, 4, 1, 0, (uint32_t *)data_body); + } else if(!(data_len & 1)) { + mpz_import(result_z, data_len / 2, 1, 2, 1, 0, (uint16_t *)data_body); + } else { + mpz_import(result_z, data_len, 1, 1, 1, 0, data_body); + } + + PGMP_RETURN_MPZ(result_z); +} + +PGMP_PG_FUNCTION(pmpz_to_bytea) +{ + const mpz_t z; + bytea *result; + char *result_body_u8; + int body_len; + + PGMP_GETARG_MPZ(z, 0); + + body_len = (mpz_sizeinbase(z, 16) + 1) / 2; + + result = malloc(VARHDRSZ + body_len); + result_body_u8 = VARDATA(result); + + if(!(body_len & 7)) { + mpz_export((uint64_t *)result_body_u8, NULL, 1, 8, 1, 0, z); + } else if(!(body_len & 3)) { + mpz_export((uint32_t *)result_body_u8, NULL, 1, 4, 1, 0, z); + } else if(!(body_len & 1)) { + mpz_export((uint16_t *)result_body_u8, NULL, 1, 2, 1, 0, z); + } else { + mpz_export(result_body_u8, NULL, 1, 1, 1, 0, z); + } + + SET_VARSIZE(result, VARHDRSZ + body_len); + + PG_RETURN_BYTEA_P(result); +} From 91b6e740945455c108da47c5955c8e7066d0fb9b Mon Sep 17 00:00:00 2001 From: Levi Aul Date: Mon, 7 Jun 2021 11:59:17 -0700 Subject: [PATCH 2/2] Add 2c-signed bytea import function --- sql/pgmp.pysql | 2 ++ src/pmpz_io.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/sql/pgmp.pysql b/sql/pgmp.pysql index c9ef4f6..2841823 100644 --- a/sql/pgmp.pysql +++ b/sql/pgmp.pysql @@ -91,6 +91,8 @@ CREATE TYPE mpz ( func('mpz', 'text int4', 'mpz', cname='pmpz_in_base') func('text', 'mpz int4', 'cstring', cname='pmpz_out_base') +func('mpz_2c', 'bytea', 'mpz', cname='pmpz_from_bytea_signed') + !! PYOFF diff --git a/src/pmpz_io.c b/src/pmpz_io.c index 64e2724..e5faf41 100644 --- a/src/pmpz_io.c +++ b/src/pmpz_io.c @@ -416,6 +416,76 @@ PGMP_PG_FUNCTION(pmpz_from_bytea) PGMP_RETURN_MPZ(result_z); } +PGMP_PG_FUNCTION(pmpz_from_bytea_signed) +{ + bytea *data = PG_GETARG_BYTEA_PP(0); + int data_len = VARSIZE_ANY_EXHDR(data); + char *data_body = VARDATA_ANY(data); + char *data_buf; + bool is_neg; + mpz_t result_z; + + mpz_init(result_z); + + if(data_len == 0) { + PGMP_RETURN_MPZ(result_z); + } + + is_neg = data_body[0] & 0x80; + + if(is_neg) { + data_buf = palloc(data_len); + + if(!(data_len & 7)) { + size_t limbs_count = data_len / 8; + uint64_t *limbs_in = (uint64_t *)data_body; + uint64_t *limbs_out = (uint64_t *)data_buf; + for(size_t i = 0; i < limbs_count; i++) { + limbs_out[i] = ~(limbs_in[i]); + } + } else if(!(data_len & 3)) { + size_t limbs_count = data_len / 4; + uint32_t *limbs_in = (uint32_t *)data_body; + uint32_t *limbs_out = (uint32_t *)data_buf; + for(size_t i = 0; i < limbs_count; i++) { + limbs_out[i] = ~(limbs_in[i]); + } + } else if(!(data_len & 1)) { + size_t limbs_count = data_len / 2; + uint16_t *limbs_in = (uint16_t *)data_body; + uint16_t *limbs_out = (uint16_t *)data_buf; + for(size_t i = 0; i < limbs_count; i++) { + limbs_out[i] = ~(limbs_in[i]); + } + } else { + for(size_t i = 0; i < data_len; i++) { + data_buf[i] = ~(data_body[i]); + } + } + } else { + data_buf = data_body; + } + + if(!(data_len & 7)) { + mpz_import(result_z, data_len / 8, 1, 8, 1, 0, (uint64_t *)data_buf); + } else if(!(data_len & 3)) { + mpz_import(result_z, data_len / 4, 1, 4, 1, 0, (uint32_t *)data_buf); + } else if(!(data_len & 1)) { + mpz_import(result_z, data_len / 2, 1, 2, 1, 0, (uint16_t *)data_buf); + } else { + mpz_import(result_z, data_len, 1, 1, 1, 0, data_buf); + } + + if (is_neg) { + pfree(data_buf); + + mpz_add_ui(result_z, result_z, 1); + mpz_neg(result_z, result_z); + } + + PGMP_RETURN_MPZ(result_z); +} + PGMP_PG_FUNCTION(pmpz_to_bytea) { const mpz_t z;