Skip to content

Commit 91b6e74

Browse files
committed
Add 2c-signed bytea import function
1 parent 9163b39 commit 91b6e74

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

sql/pgmp.pysql

+2
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ CREATE TYPE mpz (
9191
func('mpz', 'text int4', 'mpz', cname='pmpz_in_base')
9292
func('text', 'mpz int4', 'cstring', cname='pmpz_out_base')
9393

94+
func('mpz_2c', 'bytea', 'mpz', cname='pmpz_from_bytea_signed')
95+
9496
!! PYOFF
9597

9698

src/pmpz_io.c

+70
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,76 @@ PGMP_PG_FUNCTION(pmpz_from_bytea)
416416
PGMP_RETURN_MPZ(result_z);
417417
}
418418

419+
PGMP_PG_FUNCTION(pmpz_from_bytea_signed)
420+
{
421+
bytea *data = PG_GETARG_BYTEA_PP(0);
422+
int data_len = VARSIZE_ANY_EXHDR(data);
423+
char *data_body = VARDATA_ANY(data);
424+
char *data_buf;
425+
bool is_neg;
426+
mpz_t result_z;
427+
428+
mpz_init(result_z);
429+
430+
if(data_len == 0) {
431+
PGMP_RETURN_MPZ(result_z);
432+
}
433+
434+
is_neg = data_body[0] & 0x80;
435+
436+
if(is_neg) {
437+
data_buf = palloc(data_len);
438+
439+
if(!(data_len & 7)) {
440+
size_t limbs_count = data_len / 8;
441+
uint64_t *limbs_in = (uint64_t *)data_body;
442+
uint64_t *limbs_out = (uint64_t *)data_buf;
443+
for(size_t i = 0; i < limbs_count; i++) {
444+
limbs_out[i] = ~(limbs_in[i]);
445+
}
446+
} else if(!(data_len & 3)) {
447+
size_t limbs_count = data_len / 4;
448+
uint32_t *limbs_in = (uint32_t *)data_body;
449+
uint32_t *limbs_out = (uint32_t *)data_buf;
450+
for(size_t i = 0; i < limbs_count; i++) {
451+
limbs_out[i] = ~(limbs_in[i]);
452+
}
453+
} else if(!(data_len & 1)) {
454+
size_t limbs_count = data_len / 2;
455+
uint16_t *limbs_in = (uint16_t *)data_body;
456+
uint16_t *limbs_out = (uint16_t *)data_buf;
457+
for(size_t i = 0; i < limbs_count; i++) {
458+
limbs_out[i] = ~(limbs_in[i]);
459+
}
460+
} else {
461+
for(size_t i = 0; i < data_len; i++) {
462+
data_buf[i] = ~(data_body[i]);
463+
}
464+
}
465+
} else {
466+
data_buf = data_body;
467+
}
468+
469+
if(!(data_len & 7)) {
470+
mpz_import(result_z, data_len / 8, 1, 8, 1, 0, (uint64_t *)data_buf);
471+
} else if(!(data_len & 3)) {
472+
mpz_import(result_z, data_len / 4, 1, 4, 1, 0, (uint32_t *)data_buf);
473+
} else if(!(data_len & 1)) {
474+
mpz_import(result_z, data_len / 2, 1, 2, 1, 0, (uint16_t *)data_buf);
475+
} else {
476+
mpz_import(result_z, data_len, 1, 1, 1, 0, data_buf);
477+
}
478+
479+
if (is_neg) {
480+
pfree(data_buf);
481+
482+
mpz_add_ui(result_z, result_z, 1);
483+
mpz_neg(result_z, result_z);
484+
}
485+
486+
PGMP_RETURN_MPZ(result_z);
487+
}
488+
419489
PGMP_PG_FUNCTION(pmpz_to_bytea)
420490
{
421491
const mpz_t z;

0 commit comments

Comments
 (0)