@@ -459,25 +459,65 @@ import_twos_complement(cass_byte_t* data, size_t size, mpz_t* number)
459
459
460
460
/* negative value */
461
461
if ((data [0 ] & 0x80 ) == 0x80 ) {
462
- /* invert bits */
463
- mpz_com (* number , * number );
464
- /* add one */
465
- mpz_add_ui (* number , * number , 1 );
466
- /* negate the value */
467
- mpz_neg (* number , * number );
462
+ /* mpz_import() imports the two's complement value as an unsigned integer
463
+ * so this needs to subtract 2^(8 * num_bytes) to get the negative value.
464
+ */
465
+ mpz_t temp ;
466
+ mpz_init (temp );
467
+ mpz_set_ui (temp , 1 );
468
+ mpz_mul_2exp (temp , temp , 8 * size );
469
+ mpz_sub (* number , * number , temp );
470
+ mpz_clear (temp );
468
471
}
469
472
}
470
473
471
474
cass_byte_t *
472
475
export_twos_complement (mpz_t number , size_t * size )
473
476
{
474
- /* negative, do two's complement */
475
- if (mpz_sgn (number ) == -1 ) {
476
- /* invert bits */
477
- mpz_com (number , number );
478
- /* add one */
479
- mpz_add_ui (number , number , 1 );
477
+ cass_byte_t * bytes ;
478
+
479
+ if (mpz_sgn (number ) == 0 ) {
480
+ /* mpz_export() returns NULL for 0 */
481
+ bytes = (cass_byte_t * ) malloc (sizeof (cass_byte_t ));
482
+ * bytes = 0 ;
483
+ * size = 1 ;
484
+ } else if (mpz_sgn (number ) == -1 ) {
485
+ /* mpz_export() ignores sign and only exports abs(number)
486
+ * so this needs to convert the number to the two's complement
487
+ * unsigned value.
488
+ */
489
+ size_t n ;
490
+ mpz_t temp ;
491
+
492
+ /* determine the number of bytes used in the two's complement
493
+ * respresentation.
494
+ */
495
+ n = mpz_sizeinbase (number , 2 ) / 8 + 1 ;
496
+
497
+ /* there's a special case for -2^(8 * n) numbers e.g. -128 (1000 0000) and
498
+ * -32768 (100 0000 0000 0000), etc. that can be handled by n - 1 bytes in
499
+ * two's complement.
500
+ */
501
+ if (mpz_scan1 (number , 0 ) == (8 * (n - 1 )) - 1 ) {
502
+ n -- ;
503
+ }
504
+
505
+ /* Add 2^(8 * num_bytes) to get the unsigned value e.g.
506
+ * -1 + 2^8 = 255
507
+ * -128 + 2^8 = 128
508
+ * -129 + 2^16 = 65407
509
+ * -32768 + 2^16 = 32768
510
+ * ...
511
+ */
512
+ mpz_init (temp );
513
+ mpz_set_ui (temp , 1 );
514
+ mpz_mul_2exp (temp , temp , 8 * n );
515
+ mpz_add (temp , number , temp );
516
+ bytes = (cass_byte_t * ) mpz_export (NULL , size , 1 , sizeof (cass_byte_t ), 1 , 0 , temp );
517
+ mpz_clear (temp );
518
+ } else {
519
+ bytes = (cass_byte_t * ) mpz_export (NULL , size , 1 , sizeof (cass_byte_t ), 1 , 0 , number );
480
520
}
481
521
482
- return ( cass_byte_t * ) mpz_export ( NULL , size , 1 , sizeof ( cass_byte_t ), 1 , 0 , number ) ;
522
+ return bytes ;
483
523
}
0 commit comments