1
// ---------------------------------------------------------------------------
3
// - standard object library - relatif big number class implementation -
4
// ---------------------------------------------------------------------------
5
// - This program is free software; you can redistribute it and/or modify -
6
// - it provided that this copyright notice is kept intact. -
8
// - This program is distributed in the hope that it will be useful, but -
9
// - without any warranty; without even the implied warranty of -
10
// - merchantability or fitness for a particular purpose. In no event shall -
11
// - the copyright holder be liable for any direct, indirect, incidental or -
12
// - special damages arising in any way out of the use of this software. -
13
// ---------------------------------------------------------------------------
14
// - copyright (c) 1999-2011 amaury darsch -
15
// ---------------------------------------------------------------------------
21
#include "Utility.hpp"
22
#include "Integer.hpp"
23
#include "Boolean.hpp"
24
#include "Relatif.hpp"
25
#include "Runnable.hpp"
26
#include "Character.hpp"
27
#include "QuarkZone.hpp"
28
#include "Exception.hpp"
29
#include "InputStream.hpp"
30
#include "OutputStream.hpp"
35
// -------------------------------------------------------------------------
36
// - private section -
37
// -------------------------------------------------------------------------
39
// the 32 bits shift factor
40
const long BIT_QUAD_SHIX = 5;
42
const t_quad MPI_QUAD_PONE = 0x00000001UL;
43
// the 32 bits maximum
44
const t_quad MPI_QUAD_PMAX = 0xFFFFFFFFUL;
45
// the maximum unsigned 32 bits integer
46
const t_octa MAX_OCTA_UVAL = 0x00000000FFFFFFFFULL;
48
const t_octa MPI_QUAD_MASK = 0x00000000FFFFFFFFULL;
50
const t_octa MPI_OCTA_PONE = 0x0000000000000001ULL;
51
// the 64 bits upper one
52
const t_octa MPI_OCTA_HONE = 0x0000000100000000ULL;
53
// the maximum positive 64 bits integer
54
const t_octa MAX_OCTA_PVAL = 0x7FFFFFFFFFFFFFFFULL;
56
// this function computes the maximum of two long integers
57
static inline long max (const long x, const long y) {
61
// this function computes the byte size of a quad
62
static inline long bsq (const t_quad x) {
64
if ((x & 0xFF000000UL) != nilq) return 4;
66
if ((x & 0x00FF0000UL) != nilq) return 3;
68
if ((x & 0x0000FF00UL) != nilq) return 2;
73
// this function sign extend a quad by byte - the number is assumed to be
74
// negative with at least one byte with the msb set to 1
75
static inline t_quad sext (const t_quad x) {
77
if ((result & 0x80000000UL) == nilq) {
78
result |= 0xFF000000UL;
79
if ((result & 0x00800000UL) == nilq) {
80
result |= 0x00FF0000UL;
81
if ((result & 0x000008000UL) == nilq) {
82
result |= 0x0000FF00UL;
83
if ((result & 0x00000080UL) == nilq) {
84
throw Exception ("quad-error", "invalid byte in signed quad");
92
// this function sign extend a byte by bit
93
static inline t_byte sext (const t_byte x) {
94
// check for null first
95
if (x == 0x00) return x;
96
// check for extened already
97
if ((x & 0x80) != 0x00) return x;
98
// initialize bit position
101
for (long i = 0; i < 8; i++) {
103
if ((val & 0x80) != 0x00) break;
106
// check null (should not happen)
107
if (val == 0x00) return 0x00;
109
for (long i = 0; i < pos; i++) {
116
// this function extracts a byte from a quad
117
static inline t_byte getqb (const t_quad x, const long index) {
118
// prepare working quad
121
if (index == 0) return (t_byte) (qval & 0x000000FFUL);
123
if (index == 1) return (t_byte) ((qval >> 8) & 0x000000FFUL);
125
if (index == 2) return (t_byte) ((qval >> 16) & 0x000000FFUL);
127
if (index == 3) return (t_byte) ((qval >> 24) & 0x000000FFUL);
129
throw Exception ("mpi-error", "illegal quad byte index");
132
// this function make a quad from a byte by index
133
static inline t_quad makqb (const t_byte x, const long index) {
134
// prepare quad result
135
t_quad result = (t_quad) x;
150
throw Exception ("mpi-error", "illegal byte quad index");
156
// this function initialize an array of quad
157
static inline void rstdat (const long size, t_quad* data) {
158
for (long i = 0; i < size; i++) data[i] = nilq;
161
// this function compute the msb of a quad
162
static inline long quadmsb (const t_quad x) {
163
// check for null first
164
if (x == 0) return 0;
168
while ((lsb + 1) != msb) {
169
long mid = (lsb + msb) >> 1;
170
if ((x & (MPI_QUAD_PMAX << mid)) != 0)
178
// this function computes the lsb of a quad
179
static inline long quadlsb (const t_quad x) {
180
// check for null first
181
if (x == 0) return 0;
183
for (long i = 0; i < 32; i++) {
184
if (((x >> i) & MPI_QUAD_PONE) == MPI_QUAD_PONE) return (i+1);
189
// this function convert a character according to a base
190
static inline long ctol (const char c, const long base) {
193
if (c == '0') return 0;
194
if (c == '1') return 1;
197
if ((c >= '0') && (c <= '9')) return (long) (c - '0');
200
if ((c >= '0') && (c <= '9')) return (long) (c - '0');
201
if ((c >= 'a') && (c <= 'f')) return ((long) (c - 'a')) + 10;
202
if ((c >= 'A') && (c <= 'F')) return ((long) (c - 'A')) + 10;
205
throw Exception ("format-error", "cannot convert character in base");
208
// this function converts a string to a relatif object
209
static Relatif strtor (const String& s) {
216
// check for size first
217
long len = s.length ();
218
if (len == 0) return result;
219
// process one character
221
result = ctol (s[0], 10);
225
// here we have at least two characters - it can be the sign, the format
226
// or a normal number
229
// check for the sign
241
// check for the format
243
if (s[index] != '0') goto number;
245
if (index >= len) return result;
246
if ((s[index] == 'x') || (s[index] == 'X')) {
249
throw Exception ("format-error", "cannot convert to relatif", s);
253
if ((s[index] == 'b') || (s[index] == 'B')) {
256
throw Exception ("format-error", "cannot convert to relatif", s);
261
// compute the number value
263
// check for the last index
265
if ((s[max] == 'r') || (s[max] == 'R')) max--;
266
// loop in the digits
267
for (long i = max; i >= index ; i--) {
268
result = result + (basval * ctol (s[i], base));
269
basval = basval * base;
271
return (sign) ? -result : result;
274
// the mpi structure - the mpi array is organized in ascending order
275
// quad[0] is the least significand quad while in byte mode rbuf[0] is the
276
// most significand byte (like a string reading from left to right)
289
p_data = new t_quad (0);
292
// create a mpi by exponent and value
293
s_mpi (const long size, const t_quad x) {
296
p_data = new t_quad (nilq);
299
p_data = new t_quad[d_size];
300
for (long i = 0; i < d_size; i++) p_data[i] = nilq;
301
p_data[d_size - 1] = x;
303
// mark the clamp flag
307
// create a mpi by data and size
308
s_mpi (const t_byte* rbuf, const long size) {
309
// preset the buffer arreay
313
// set as an unsigned buffer
314
setubuf (rbuf, size);
317
// create a mpi by data and size
318
s_mpi (t_quad* data, const long size) {
324
// create a mpi by value
325
s_mpi (const t_octa x) {
327
if (x > MAX_OCTA_UVAL) {
329
p_data = new t_quad[2];
334
p_data = new t_quad[1];
340
// copy construct this mpi
341
s_mpi (const s_mpi& that) {
342
d_size = that.d_size;
343
d_cflg = that.d_cflg;
344
p_data = new t_quad[d_size];
345
for (long i = 0; i < d_size; i++) p_data[i] = that.p_data[i];
353
// copy an mpi into this one
354
s_mpi& operator = (const s_mpi& that) {
355
// normal check as usual
356
if (this == &that) return *this;
359
d_size = that.d_size;
360
d_cflg = that.d_cflg;
361
p_data = new t_quad[d_size];
362
for (long i = 0; i < d_size; i++) p_data[i] = that.p_data[i];
366
// grow this mpi by a certain amount
367
void grow (const long size) {
368
// trivial case first
369
if ((size <= 0) || (size <= d_size)) return;
370
// allocate the new array
371
t_quad* data = new t_quad[size];
373
for (long i = 0; i < d_size; i++) data[i] = p_data[i];
374
for (long i = d_size; i < size; i++) data[i] = nilq;
382
// serialize the mpi data
383
void wrstream (OutputStream& os) {
384
Integer size (d_size);
386
// serialize the array
387
for (long i = 0; i < d_size; i++) {
389
c_qhton (p_data[i], bval);
390
os.write ((const char*) bval, 4);
394
// get the mpi size quad size
395
long vsize (void) const {
397
if (d_cflg == true) return d_size;
398
// initialize the size and check
400
for (long i = d_size - 1; i > 0; i--) {
401
if (p_data[i] != nilq) break;
407
// get the mpi byte clamped size
408
long bsize (void) const {
409
// initialize the quad size
410
long size = vsize ();
411
// get the last quad size
412
long result = bsq (p_data[size-1]);
414
result += (size-1) * 4;
419
// clamp this mpi by fixing the size and return true if null
421
// fix the size if not already clamped
422
if (d_cflg == false) {
427
if ((d_size == 1) && (p_data[0] == nilq)) return true;
431
// get a byte by index
432
t_byte getbyte (const long index) const {
433
// extract byte and quad indexes
434
long qidx = index / 4;
435
long bidx = index % 4;
437
if (qidx >= d_size) {
438
throw Exception ("mpi-error", "invalid quad index in byte access");
441
t_quad qval = p_data[qidx];
442
// extract byte value
443
return getqb (qval, bidx);
446
// get a byte by index
447
void setbyte (const t_byte x, const long index) {
448
// extract byte and quad indexes
449
long qidx = index / 4;
450
long bidx = index % 4;
452
if (qidx >= d_size) {
453
throw Exception ("mpi-error", "invalid quad index in byte access");
456
t_quad qval = makqb (x, bidx);
457
// set the quad value
458
p_data[qidx] |= qval;
461
// fill an unsigned buffer representation by size
462
long toubuf (t_byte* rbuf, const long size) const {
463
// get the clamped byte size
464
long cbsz = bsize ();
465
// fill with size range
467
for (long i = 0, j = cbsz-1; i < size; i++, j--) rbuf[i] = getbyte (j);
470
// process large sige
471
for (long i = 0, j = cbsz-1; i < cbsz; i++, j--) rbuf[i] = getbyte (j);
472
for (long i = cbsz; i < size; i++) rbuf[i] = nilc;
476
// fill an unsigned buffer representation by size
477
long tosbuf (t_byte* rbuf, const long size, const bool sgn) const {
478
// get the clamped byte size
479
long cbsz = bsize ();
480
// prepare the signed buffer
483
for (long i = 0; i < cbsz; i++) {
485
t_word bo = ((t_word) ~getbyte (i)) & 0x00FFU;
487
sbuf[i] = (t_byte) ro;
488
cw = (ro >> 8) & 0x0001U;
490
sbuf[i] = getbyte (i);
493
// sign extend and clamp if needed
495
// sign extend the last byte
496
sbuf[cbsz-1] = sext (sbuf[cbsz-1]);
497
// clamp the signed buffer
499
for (long i = cbsz - 1; i > 0; i--) {
500
if ((cbsz == 1) || (sbuf[i] != 0xFF)) break;
501
if ((sbuf[i] == 0xFF) && ((sbuf[i-1] & 0x80) == nilc)) break;
504
// adjust buffer size
507
// fill with size range
509
for (long i = 0, j = cbsz-1; i < size; i++, j--) rbuf[i] = sbuf[j];
512
// process large sige
513
for (long i = 0, j = cbsz-1; i < cbsz; i++, j--) rbuf[i] = sbuf[j];
514
for (long i = cbsz; i < size; i++) rbuf[i] = nilc;
518
// fill a buffer representation by size
519
long tobyte (t_byte* rbuf, const long size) const {
520
// get the clamped byte size
521
long cbsz = bsize ();
522
// fill with size range
524
for (long i = 0, j = size-1; i < size; i++, j--) rbuf[i] = getbyte (j);
527
long dbsz = size - cbsz;
528
for (long i = 0; i < dbsz; i++) rbuf[i] = nilc;
529
for (long i = dbsz, j = cbsz-1; i < size; i++, j--) rbuf[i] = getbyte (j);
533
// return a hexadecimal string value without prefix
534
String tohexa (void) const {
535
// initialize the result string
536
String result = Utility::tohexa (p_data[d_size-1]);
537
// get the clamped size
538
long size = vsize ();
539
for (long i = size - 2; i >= 0; i--) {
540
result += Utility::tohexa (p_data[i], true);
545
// convert this mpi to an octa
546
t_octa toocta (void) const {
548
if (d_size == 0) return 0;
549
// prepare the result
550
t_octa data = p_data[0];
551
if (d_size > 1) data |= (((t_octa) p_data[1]) << 32);
556
// return true if this mpi is zero
557
bool iszero (void) const {
558
// check for single digit clamped
559
if (d_cflg == true) {
560
if ((d_size == 1) && (p_data[0] == nilq)) return true;
562
// get the true size and loop
563
long size = vsize ();
564
for (long i = 0; i < size; i++) {
565
if (p_data[i] != nilq) return false;
570
// return true if this mpi is odd
571
bool isodd (void) const {
572
return (p_data[0] & MPI_QUAD_PONE) == MPI_QUAD_PONE;
575
// return true if this mpi is odd
576
bool iseven (void) const {
577
return (p_data[0] & MPI_QUAD_PONE) == 0UL;
580
// return the msb of this mpi
581
long getmsb (void) const {
582
// start by clamping the size
583
long size = vsize ();
584
if ((size == 1) && (p_data[0] == nilq)) return 0;
586
long mmsb = quadmsb (p_data[size-1]);
588
return ((size - 1) << BIT_QUAD_SHIX) + mmsb;
591
// return the lsb of this mpi
592
long getlsb (void) const {
593
// start by clamping the size
594
long size = vsize ();
595
if ((size == 1) && (p_data[0] == nilq)) return 0;
598
for (long i = 0; i < size; i++) {
599
if (p_data[i] != nilq) break;
602
long mlsb = quadlsb (p_data[qlsb]);
604
return (qlsb << BIT_QUAD_SHIX) + mlsb;
607
// get a bit value by position
608
bool getbit (const long bpos) const {
609
// compute quad index
610
long index = bpos >> BIT_QUAD_SHIX;
611
if (index >= d_size) {
612
throw Exception ("mpi-error", "invalid mpi bit position");
614
// get the quad and bit mark
615
t_quad data = p_data[index];
616
long mark = bpos % 32;
618
t_quad qval = ((mark == 0) ? data : (data >> mark)) & MPI_QUAD_PONE;
620
return (qval == MPI_QUAD_PONE);
623
// set a bit by position
624
void setbit (const long bpos, const bool bval) {
625
// compute quad index
626
long index = bpos >> BIT_QUAD_SHIX;
627
if (index >= d_size) {
628
throw Exception ("mpi-error", "invalid mpi bit position");
630
// get the quad and bit mark
631
t_quad data = p_data[index];
632
long mark = bpos % 32;
634
t_quad mask = (mark == 0) ? MPI_QUAD_PONE : (MPI_QUAD_PONE << mark);
635
// set the quad bit value
636
p_data[index] = bval ? (data | mask) : (data & ~mask);
639
// set the mpi with an unsigned buffer
640
void setubuf (const t_byte* ubuf, const long size) {
641
// clear the old buffer
643
// compute the number of quads
645
if ((size % 4) != 0) d_size++;
646
// allocate the quad array
647
p_data = new t_quad[d_size];
648
// initialize the array
649
rstdat (d_size, p_data);
650
// fill the quad array
651
for (long i = 0, j = size-1; i < size; i++, j--) setbyte (ubuf[i], j);
652
// clear the clamp flag
656
// set the mpi with an signed buffer
657
bool setsbuf (const t_byte* sbuf, const long size) {
658
// consider an unsigned buffer
659
setubuf (sbuf, size);
660
// find the buffer sign
661
bool sign = ((sbuf[0] & 0x80) == 0x80);
662
// process the negative value
664
// sign extend the last quad
665
p_data[d_size-1] = sext (p_data[d_size-1]);
666
// fix the complemented value
667
t_octa co = MPI_OCTA_PONE;
668
for (long i = 0; i < d_size; i++) {
669
t_octa ro = (((t_octa) ~p_data[i]) & MPI_QUAD_MASK) + co;
670
p_data[i] = (t_quad) ro;
671
co = (ro >> 32) & MPI_OCTA_PONE;
677
// radix shift right by a certain amount
678
void rsr (const long rsa) {
680
long size = vsize ();
682
for (long i = 0; i < size; i++) {
684
p_data[i] = (idx < size) ? p_data[idx] : nilq;
691
// this function generates a random mpi upto n bits
692
static s_mpi* mpi_rng (const long bits) {
693
// check for null first
694
if (bits == 0) return new s_mpi;
695
// compute number of quads
696
long size = ((bits - 1) / 32) + 1;
697
t_quad* data = new t_quad[size];
698
for (long i = 0; i < size; i++) data[i] = Utility::quadrnd ();
699
// build the mpi result
700
s_mpi* result = new s_mpi (data, size);
702
long mbit = (((bits - 1) / 32) * 32) + 31;
703
for (long i = bits; i <= mbit; i++) result->setbit (i, false);
706
// here is the result
710
// this function generates a random n bits mpi
711
static s_mpi* mpi_rnd (const long bits) {
712
// check for null first
713
if (bits == 0) return new s_mpi;
714
// compute number of quads
715
long size = ((bits - 1) / 32) + 1;
716
t_quad* data = new t_quad[size];
717
for (long i = 0; i < size; i++) data[i] = Utility::quadrnd ();
718
// build the mpi result
719
s_mpi* result = new s_mpi (data, size);
721
long mbit = (((bits - 1) / 32) * 32) + 31;
722
result->setbit (bits - 1, true);
723
for (long i = bits; i <= mbit; i++) result->setbit (i, false);
726
// here is the result
730
// this function deserialize a stream into a mpi
731
static s_mpi* mpi_rds (InputStream& is) {
732
// deserialize the size
735
long size = sval.tolong ();
736
// deserialize the data
737
t_quad* data = new t_quad[size];
738
for (long i = 0; i < size; i++) {
740
for (long j = 0; j < 4; j++) bval[j] = is.read ();
741
data[i] = c_qntoh (bval);
743
// build the mpi result
744
return new s_mpi (data, size);
747
// this function compare a mpi with an octa
748
static bool mpi_eql (const s_mpi& x, const t_octa y) {
749
// get the maximum size
750
long size = max (x.d_size, 2);
752
for (long i = size - 1; i >= 0; i--) {
753
t_quad xq = (i < x.d_size) ? x.p_data [i] : nilq;
754
t_quad yq = (i == 0) ? (t_quad) y : (i == 1) ? (t_quad) (y >> 32) : 0ULL;
755
if (xq != yq) return false;
757
// here the numbers are equal
761
// this function compare two mpi values
762
static bool mpi_eql (const s_mpi& x, const s_mpi& y) {
763
// get the maximum size
764
long size = max (x.vsize (), y.vsize ());
766
for (long i = size - 1; i >= 0; i--) {
767
t_quad xq = (i < x.d_size) ? x.p_data [i] : nilq;
768
t_quad yq = (i < y.d_size) ? y.p_data [i] : nilq;
769
if (xq != yq) return false;
771
// here the numbers are equal
775
// this function compare a mpi with an octa
776
static bool mpi_gth (const s_mpi& x, const t_octa y) {
777
// get the maximum size
778
long size = max (x.vsize (), 2);
780
for (long i = size - 1; i >= 0; i--) {
781
t_quad xq = (i < x.d_size) ? x.p_data [i] : nilq;
782
t_quad yq = (i == 0) ? (t_quad) y : (i == 1) ? (t_quad) (y >> 32) : 0;
783
if (xq > yq) return true;
784
if (xq < yq) return false;
786
// here the numbers are equal
790
// this function compare two mpi values
791
static bool mpi_gth (const s_mpi& x, const s_mpi& y) {
792
// get the maximum size
793
long size = max (x.vsize (), y.vsize ());
795
for (long i = size - 1; i >= 0; i--) {
796
t_quad xq = (i < x.d_size) ? x.p_data [i] : nilq;
797
t_quad yq = (i < y.d_size) ? y.p_data [i] : nilq;
798
if (xq > yq) return true;
799
if (xq < yq) return false;
801
// here the numbers are equal
805
// this function compares a data array with an octa
806
static bool mpi_geq (const s_mpi& x, const t_octa y) {
807
// get the maximum size
808
long size = max (x.vsize (), 2);
810
for (long i = size - 1; i >= 0; i--) {
811
t_quad xq = (i < x.d_size) ? x.p_data [i] : nilq;
812
t_quad yq = (i == 0) ? (t_quad) y : (i == 1) ? (t_quad) (y >> 32) : 0;
813
if (xq > yq) return true;
814
if (xq < yq) return false;
816
// here the numbers are equal
820
// this function compares a data array with an mpi value
821
static bool mpi_geq (const s_mpi& x, const s_mpi& y) {
822
// get the maximum size
823
long size = max (x.vsize (), y.vsize ());
825
for (long i = size - 1; i >= 0; i--) {
826
t_quad xq = (i < x.d_size) ? x.p_data [i] : nilq;
827
t_quad yq = (i < y.d_size) ? y.p_data [i] : nilq;
828
if (xq > yq) return true;
829
if (xq < yq) return false;
831
// here the numbers are equal
835
// shift left in place a mpi by a certain amount
836
static void mpi_leq (s_mpi& x, const long asl) {
838
if (asl == 0) return;
839
// compute the amount of quad and bit shift
840
long qsl = asl >> BIT_QUAD_SHIX;
842
// compute how much we must grow
843
long msb = x.getmsb ();
844
long max = x.d_size - 1;
845
if (((msb + bsl) > 32) || (qsl > 0)) x.grow (x.d_size + qsl + 1);
847
for (long i = max; i >= 0; i--) {
849
t_octa xo = x.p_data[i];
850
t_octa ro = (xo << bsl);
851
// process upper quad
852
t_quad uq = (t_quad) (ro >> 32);
853
if (uq != nilq) x.p_data[i+qsl+1] |= uq;
854
// process lower quad
855
t_quad lq = (t_quad) ro;
856
x.p_data[i+qsl] = lq;
858
// clean remaining quad
859
for (long i = 0; i < qsl; i++) x.p_data[i] = nilq;
864
// shift right in place a mpi by a certain amount
865
static void mpi_req (s_mpi& x, const long asr) {
867
if (asr == 0) return;
868
// compute the amount of quad and bit shift
869
long qsr = asr >> BIT_QUAD_SHIX;
872
for (long i = 0; i < x.d_size; i++) {
873
long index = i + qsr;
875
t_octa xo = (index < x.d_size) ? x.p_data[index] : 0;
876
t_octa ro = xo << (32 - bsr);
877
// process upper quad
878
t_quad uq = (t_quad) (ro >> 32);
880
// process lower quad
881
t_quad lq = (t_quad) ro;
882
if (i > 0) x.p_data[i-1] |= lq;
888
// shift left a mpi by a certain amount
889
static s_mpi* mpi_shl (const s_mpi& x, const long asl) {
891
if (asl == 0) return new s_mpi (x);
892
// compute the amount of quad and bit shift
893
long qsl = asl >> BIT_QUAD_SHIX;
895
// compute the new size and allocate
896
long size = x.d_size + qsl;
897
t_quad* data = new t_quad[size+1]; rstdat (size+1, data);
898
// initialize the carry
901
for (long i = 0; i < x.d_size; i++) {
903
t_octa xo = x.p_data[i];
904
t_octa ro = (xo << bsl) | cq;
905
// set data and carry
906
data[i+qsl] = (t_quad) ro;
912
return new s_mpi (data, size+1);
915
// shift right a mpi by a certain amount
916
static s_mpi* mpi_shr (const s_mpi& x, const long asr) {
918
if (asr == 0) return new s_mpi (x);
919
// compute the amount of quad and bit shift
920
long qsl = asr >> BIT_QUAD_SHIX;
922
t_quad* data = new t_quad[x.d_size]; rstdat (x.d_size, data);
923
// initialize the borrow
926
for (long i = x.d_size - 1; i >= 0; i--) {
928
t_octa xo = ((t_octa) x.p_data[i]) << 32;
929
t_octa ro = (xo >> bsl) | (bq << 32);
930
// set data and carry
931
bq = ro & MAX_OCTA_UVAL;
933
if (j >= 0) data[j] = ro >> 32;
936
return new s_mpi (data,x.d_size);
939
// forward definitions of in place operations
940
static void mpi_aeq (s_mpi& x, const s_mpi& y);
941
static void mpi_seq (s_mpi& x, const s_mpi& y);
942
static void mpi_meq (s_mpi& x, const s_mpi& y);
943
static void mpi_deq (s_mpi& x, const s_mpi& y, const bool rflg);
945
// this function increments a mpi
946
static s_mpi* mpi_inc (const s_mpi& x) {
947
// compute result size and allocate
948
long size = x.d_size;
949
long dsiz = size + 1;
950
t_quad* data = new t_quad[dsiz];
953
for (long i = 0; i < x.d_size; i++) {
954
t_octa xo = (i < x.d_size) ? x.p_data[i] : 0;
955
t_octa yo = (i == 0) ? MPI_OCTA_PONE : 0;
956
t_octa ro = xo + yo + cq;
957
data[i] = (t_quad) ro;
958
cq = (t_quad) (ro >> 32);
962
// here is the result
963
return new s_mpi (data, dsiz);
966
// this function decrements a mpi
967
static s_mpi* mpi_dec (const s_mpi& x) {
968
// compute result size and allocate
969
t_quad* data = new t_quad[x.d_size];
971
// loop and substract
972
for (long i = 0; i < x.d_size; i++) {
973
t_octa xo = x.p_data[i];
974
t_octa yo = (i == 0) ? MPI_OCTA_PONE : 0;
975
t_octa ro = xo - yo - cq;
976
data[i] = (t_quad) ro;
977
cq = (t_quad) (ro >> 63);
979
// here is the result
980
return new s_mpi (data, x.d_size);
983
// this function adds a mpi with an octa
984
static s_mpi* mpi_add (const s_mpi& x, const t_octa y) {
985
// compute result size and allocate
986
long size = max (x.d_size, 2);
987
long dsiz = size + 1;
988
t_quad* data = new t_quad[dsiz];
991
for (long i = 0; i < size; i++) {
992
t_octa xo = (i < x.d_size) ? x.p_data[i] : 0;
993
t_octa yo = (i == 0) ? y & MPI_QUAD_MASK : (i == 1) ? y >> 32 : 0;
994
t_octa ro = xo + yo + cq;
995
data[i] = (t_quad) ro;
996
cq = (t_quad) (ro >> 32);
1000
// here is the result
1001
return new s_mpi (data,dsiz);
1004
// this function adds two mpi values
1005
static s_mpi* mpi_add (const s_mpi& x, const s_mpi& y) {
1006
// compute result size and allocate
1007
long size = max (x.d_size, y.d_size);
1008
long dsiz = size + 1;
1009
t_quad* data = new t_quad[dsiz];
1012
for (long i = 0; i < size; i++) {
1013
t_octa xo = (i < x.d_size) ? x.p_data[i] : 0;
1014
t_octa yo = (i < y.d_size) ? y.p_data[i] : 0;
1015
t_octa ro = xo + yo + cq;
1016
data[i] = (t_quad) ro;
1017
cq = (t_quad) (ro >> 32);
1021
// here is the result
1022
return new s_mpi (data,dsiz);
1025
// this function substracts a mpi value with an octa assuming x > y
1026
static s_mpi* mpi_sub (const s_mpi& x, const t_octa y) {
1027
// compute result size and allocate
1028
t_quad* data = new t_quad[x.d_size];
1030
// loop and substract
1031
for (long i = 0; i < x.d_size; i++) {
1032
t_octa xo = x.p_data[i];
1033
t_octa yo = (i == 0) ? y & MPI_QUAD_MASK : (i == 1) ? y >> 32 : 0ULL;
1034
t_octa ro = xo - yo - cq;
1035
data[i] = (t_quad) ro;
1036
cq = (t_quad) (ro >> 63);
1038
// here is the result
1039
return new s_mpi (data, x.d_size);
1042
// this function substracts an octa value with a mpi assuming x > y
1043
static s_mpi* mpi_sub (const t_octa x, const s_mpi& y) {
1044
// double check the size
1046
throw Exception ("internal-error", "mpi argument size bigger than 2");
1048
// compute result size and allocate
1049
t_quad* data = new t_quad[2];
1050
// build octa argument
1051
t_octa yq = y.p_data[0];
1052
if (y.d_size > 1) yq += ((t_octa) y.p_data[1]) << 32;
1053
// evaluate result and set
1057
// here is the result
1058
return new s_mpi (data, 2);
1061
// this function substracts two mpi values assuming x > y
1062
static s_mpi* mpi_sub (const s_mpi& x, const s_mpi& y) {
1063
// compute result size and allocate
1064
t_quad* data = new t_quad[x.d_size];
1066
// loop and substract
1067
for (long i = 0; i < x.d_size; i++) {
1068
t_octa xo = x.p_data[i];
1069
t_octa yo = (i < y.d_size) ? y.p_data[i] : 0;
1070
t_octa ro = xo - yo - cq;
1071
data[i] = (t_quad) ro;
1072
cq = (t_quad) (ro >> 63);
1074
// here is the result
1075
return new s_mpi (data, x.d_size);
1078
// this function multiply a mpi with a quad
1079
static s_mpi* mpi_mul (const s_mpi& x, const t_quad y) {
1080
// compute result size and allocate
1081
long size = x.d_size + 1;
1082
t_quad* data = new t_quad[size]; rstdat (size, data);
1085
// loop in the first argument
1086
for (long j = 0; j < x.d_size; j++) {
1087
// initialize line arguments
1088
t_octa ro = data[j];
1089
t_octa xo = x.p_data[j];
1090
// compute local multiplication
1093
data[j] = (t_quad) ro;
1095
cq = (t_quad) (ro >> 32);
1097
data[x.d_size] = cq;
1098
// here is the result
1099
return new s_mpi (data,size);
1102
// this function multiply a mpi with an octa
1103
static s_mpi* mpi_mul (const s_mpi& x, const t_octa y) {
1104
// compute result size and allocate
1105
long size = x.d_size + 2;
1106
t_quad* data = new t_quad[size]; rstdat (size, data);
1107
// loop in the second argument
1108
for (long i = 0; i < 2; i++) {
1111
// loop in the first argument
1112
for (long j = 0; j < x.d_size; j++) {
1113
// initialize line arguments
1114
t_octa ro = data[i+j];
1115
t_octa xo = x.p_data[j];
1116
t_octa yo = (i == 0) ? y & MPI_QUAD_MASK : (i == 1) ? y >> 32 : 0;
1117
// compute local multiplication
1120
data[i+j] = (t_quad) ro;
1122
cq = (t_quad) (ro >> 32);
1124
data[i+x.d_size] = cq;
1126
// here is the result
1127
return new s_mpi (data, size);
1130
// this function multiply two mpi values
1131
static s_mpi* mpi_mul (const s_mpi& x, const s_mpi& y) {
1132
// compute result size and allocate
1133
long size = x.d_size + y.d_size;
1134
t_quad* data = new t_quad[size]; rstdat (size, data);
1135
// loop in the second argument
1136
for (long i = 0; i < y.d_size; i++) {
1139
// loop in the first argument
1140
for (long j = 0; j < x.d_size; j++) {
1141
// initialize line arguments
1142
t_octa ro = data[i+j];
1143
t_octa xo = x.p_data[j];
1144
t_octa yo = y.p_data[i];
1145
// compute local multiplication
1148
data[i+j] = (t_quad) ro;
1150
cq = (t_quad) (ro >> 32);
1152
data[i+x.d_size] = cq;
1154
// here is the result
1155
return new s_mpi (data, size);
1158
// this function divide two mpi values and return the result or the
1159
// reminder depending on the reminder flag
1160
// this function is based on the algorithm described in HAC 14.20 and
1161
// incorporates numerous fixes to the sloppy description
1162
// this function also assumes that x is bigger than y and y is not null
1163
static s_mpi* mpi_div (const s_mpi& x, const s_mpi& y, const bool rflg) {
1164
// normalize x and y in order to have y > b/2
1165
long dbs = y.getmsb () % 32;
1166
if (dbs > 0) dbs = 32 - dbs;
1168
// allocate both dividend and divisor
1169
s_mpi* dx = (dbs == 0) ? new s_mpi (x) : mpi_shl (x, dbs);
1170
s_mpi* dy = (dbs == 0) ? new s_mpi (y) : mpi_shl (y, dbs);
1174
// allocate the quotient
1175
long delta = dx->d_size - dy->d_size;
1179
throw Exception ("size-error", "invalid negative quotient size");
1181
long qsize = delta + 1;
1182
t_quad* qdata = new t_quad[qsize]; rstdat (qsize, qdata);
1186
s_mpi* py = mpi_shl (*dy, delta*32);
1188
// while (dx >= py) {q[n-t] += 1; dx-= py}
1189
while (mpi_geq (*dx, *py) == true) {
1196
// step 3: local variables
1197
// n = dx->d_size - 1;
1198
// t = dy->d_size - 1;
1199
long n = dx->d_size - 1;
1200
long t = dy->d_size - 1;
1202
t_quad* txd = new t_quad[3];
1203
s_mpi* tx = new s_mpi (txd, 3);
1204
// ty = y[t]*b + y[t-1]
1205
t_quad* tyd = new t_quad[2];
1206
tyd[0] = (t == 0) ? nilq : dy->p_data[t-1];
1207
tyd[1] = dy->p_data[t];
1208
s_mpi* ty = new s_mpi (tyd, 2);
1210
// step 3: main loop
1211
for (long i = n; i >= dy->d_size; i--) {
1213
// if (dx[i] == y[t]) (q[i-t-1] = b-1) (q[i-t-1] = x[i]*b+x[i-1]/y[t]
1214
if (dx->p_data[i] == dy->p_data[t]) {
1215
qdata[i-t-1] = MPI_QUAD_PMAX;
1217
t_octa ox = dx->p_data[i]; ox <<= 32;
1218
ox |= dx->p_data[i-1];
1219
ox /= dy->p_data[t];
1220
qdata[i-t-1] = (t_quad) ox;
1223
// while(q[i-t-1]*ty) > (x[i]*b**2+x[i-1]*b+x[i-2])) (q[i-t-1]--)
1227
// fix back quotient
1230
delete tq; tq = nilp;
1231
tq = mpi_mul (*ty, qdata[i-t-1]);
1232
// x[i]*b**2+x[i-1]*b+x[i-2]
1233
tx->p_data[2] = dx->p_data[i];
1234
tx->p_data[1] = ((i - 1) < 0) ? nilq : dx->p_data[i-1];
1235
tx->p_data[0] = ((i - 2) < 0) ? nilq : dx->p_data[i-2];
1236
} while (mpi_gth (*tq, *tx) == true);
1238
// x -= q[i-t-1]*y*b**(i-t-1)
1239
// if (x < 0) {x += y*b**(i-t-1); q[i-t-1]--}
1240
long ybs = (i - t - 1) * 32;
1241
s_mpi* tb = mpi_shl (*dy, ybs);
1242
delete tq; tq = mpi_mul (*tb, qdata[i-t-1]);
1243
if (mpi_geq (*dx, *tq) == true) {
1250
delete tb; tb = nilp;
1251
delete tq; tq = nilp;
1253
// prepare result based on flag
1254
// eventually normalize back the reminder
1255
s_mpi* result = rflg ? mpi_shr (*dx, dbs) : new s_mpi (qdata, qsize);
1261
if (rflg == true) delete [] qdata;
1262
// finally here it is
1266
// this function computes the exponentiation of a mpi
1267
static s_mpi* mpi_pow (const s_mpi& x, const t_octa e) {
1268
// trivial case first
1269
if (e == nilq) return new s_mpi (1);
1270
// initialize temporaries
1271
s_mpi* ta = new s_mpi (1);
1275
while (te != nilq) {
1276
if ((te & MPI_OCTA_PONE) == MPI_OCTA_PONE) mpi_meq (*ta, ts);
1278
if (te != nilq) mpi_meq (ts, ts);
1283
// this function computes the exponentiation of a mpi
1284
static s_mpi* mpi_pow (const s_mpi& x, const s_mpi& e) {
1285
// trivial case first
1286
if (e.iszero () == true) return new s_mpi (1);
1287
// initialize temporaries
1288
s_mpi* ta = new s_mpi (1);
1292
while (te.iszero () == false) {
1293
if (te.isodd () == true) mpi_meq (*ta, ts);
1295
if (te.iszero () == false) mpi_meq (ts, ts);
1300
// this function computes the modular exponentiation of a mpi
1301
static s_mpi* mpi_pow (const s_mpi& x, const t_octa e, const s_mpi& m) {
1302
// trivial case first
1303
if (e == nilq) return new s_mpi (1);
1304
// initialize temporaries
1305
s_mpi* ta = new s_mpi (1);
1309
while (te != nilq) {
1310
if ((te & MPI_OCTA_PONE) == MPI_OCTA_PONE) {
1311
mpi_meq (*ta, ts); ta->clamp ();
1312
if (mpi_geq (*ta, m) == true) {
1313
mpi_deq (*ta, m, true);
1319
mpi_meq (ts, ts); ts.clamp ();
1320
if (mpi_geq (ts, m) == true) {
1321
mpi_deq (ts, m, true);
1329
// this function computes the modular exponentiation of a mpi
1330
static s_mpi* mpi_pow (const s_mpi& x, const s_mpi& e, const s_mpi& m) {
1331
// trivial case first
1332
if (e.iszero () == true) return new s_mpi (1);
1333
// initialize temporaries
1334
s_mpi* ta = new s_mpi (1);
1338
while (te.iszero () == false) {
1339
if (te.isodd () == true) {
1340
mpi_meq (*ta, ts); ta->clamp ();
1341
if (mpi_geq (*ta, m) == true) {
1342
mpi_deq (*ta, m, true);
1347
if (te.iszero () == false) {
1348
mpi_meq (ts, ts); ts.clamp ();
1349
if (mpi_geq (ts, m) == true) {
1350
mpi_deq (ts, m, true);
1358
// this function adds in place two mpi values
1359
static void mpi_aeq (s_mpi& x, const s_mpi& y) {
1360
// compute size and eventually grow
1361
long size = max (x.d_size, y.d_size); x.grow (size);
1364
for (long i = 0; i < size; i++) {
1365
t_octa xo = (i < x.d_size) ? x.p_data[i] : 0;
1366
t_octa yo = (i < y.d_size) ? y.p_data[i] : 0;
1367
t_octa ro = xo + yo + cq;
1368
x.p_data[i] = (t_quad) ro;
1369
cq = (t_quad) (ro >> 32);
1373
x.grow (x.d_size + 1);
1374
x.p_data[x.d_size-1] = cq;
1380
// this function substracts in place two mpi assuming that x > y
1381
static void mpi_seq (s_mpi& x, const s_mpi& y) {
1384
// loop and substract
1385
for (long i = 0; i < x.d_size; i++) {
1386
t_octa xo = x.p_data[i];
1387
t_octa yo = (i < y.d_size) ? y.p_data[i] : 0;
1388
t_octa ro = xo - yo - cq;
1389
x.p_data[i] = (t_quad) ro;
1390
cq = (t_quad) (ro >> 63);
1396
// this function multiply in place two mpi
1397
static void mpi_meq (s_mpi& x, const s_mpi& y) {
1398
// compute multiplication
1399
s_mpi* mpi = mpi_mul (x, y);
1402
x.d_size = mpi->d_size;
1403
x.p_data = mpi->p_data;
1405
// clean temporary mpi
1410
// this function divides in place two mpi
1411
static void mpi_deq (s_mpi& x, const s_mpi& y, const bool rflg) {
1412
// compute multiplication
1413
s_mpi* mpi = mpi_div (x, y, rflg);
1416
x.d_size = mpi->d_size;
1417
x.p_data = mpi->p_data;
1419
// clean temporary mpi
1424
// this function bitwise negate a mpi
1425
static s_mpi* mpi_neg (const s_mpi& x) {
1426
// build the result data
1427
long size = x.d_size;
1428
t_quad* data = new t_quad[size];
1430
for (long i = 0; i < size; i++) data[i] = ~x.p_data[i];
1432
return new s_mpi (data, size);
1435
// this function bitwise and two mpi
1436
static s_mpi* mpi_and (const s_mpi& x, const s_mpi& y) {
1437
// build the result data
1438
long size = max (x.d_size, y.d_size);
1439
t_quad* data = new t_quad[size];
1441
for (long i = 0; i < size; i++) {
1442
t_quad xq = (i < x.d_size) ? x.p_data[i] : nilq;
1443
t_quad yq = (i < y.d_size) ? y.p_data[i] : nilq;
1447
return new s_mpi (data, size);
1450
// this function bitwise or two mpi
1451
static s_mpi* mpi_bor (const s_mpi& x, const s_mpi& y) {
1452
// build the result data
1453
long size = max (x.d_size, y.d_size);
1454
t_quad* data = new t_quad[size];
1456
for (long i = 0; i < size; i++) {
1457
t_quad xq = (i < x.d_size) ? x.p_data[i] : nilq;
1458
t_quad yq = (i < y.d_size) ? y.p_data[i] : nilq;
1462
return new s_mpi (data, size);
1465
// this function bitwise xor two mpi
1466
static s_mpi* mpi_xor (const s_mpi& x, const s_mpi& y) {
1467
// build the result data
1468
long size = max (x.d_size, y.d_size);
1469
t_quad* data = new t_quad[size];
1471
for (long i = 0; i < size; i++) {
1472
t_quad xq = (i < x.d_size) ? x.p_data[i] : nilq;
1473
t_quad yq = (i < y.d_size) ? y.p_data[i] : nilq;
1477
return new s_mpi (data, size);
1480
// this function computes the binary gcd of two mpi
1481
static s_mpi* mpi_gcd (const s_mpi& x, const s_mpi& y) {
1482
// initialize temporaries
1486
// simplify by two and update even coefficient
1487
while ((a.iseven () == true) && (b.iseven () == true)) {
1492
// clamp before looping
1496
while (a.iszero () == false) {
1497
while (a.iseven () == true) mpi_req (a, 1);
1498
while (b.iseven () == true) mpi_req (b, 1);
1499
if (mpi_geq (a, b) == true) {
1512
return mpi_mul (b, g);
1515
// this procedure compute the initial rho factor (also called m')
1516
// suck like m'=-1/m (mod b) - where b is the base radix
1517
// the fast algorithm here is from Tom Saint-Denis
1518
static t_quad mpi_rho (const s_mpi& m) {
1520
t_quad b = m.p_data[0];
1521
// x*a==1 (mod 2**4)
1522
t_quad x = (((b + 2) & 4) << 1) + b;
1523
// x*a==1 (mod 2**8)
1525
// x*a==1 (mod 2**16)
1527
// x*a==1 (mod 2**32)
1529
// rho = -1/m (mod b)
1530
return (t_quad) (MPI_OCTA_HONE - x);
1533
// this procedure compute a radix-based montgomery multiplication
1534
// of two mpi without any verification (HAC 14.36)
1535
// carefull: it is assumed here that m is odd and x,y < m
1536
static s_mpi* mpi_mmm (const s_mpi& x, const s_mpi& y, const s_mpi& m,
1538
// initialize result
1539
s_mpi* z = new s_mpi;
1540
// get modular size and loop
1541
long k = m.vsize ();
1542
for (long i = 0; i < k; i++) {
1543
// ui = ((zo + xi.y0)*rho) mod b
1544
t_octa z0 = z->p_data[0];
1545
t_quad xi = (i < x.d_size) ? x.p_data[i] : nilq;
1546
t_octa y0 = y.p_data[0];
1547
t_quad ui = (z0 + (y0 * xi)) * rho;
1549
s_mpi* tx = mpi_mul (y, xi);
1553
s_mpi* tu = mpi_mul (m, ui);
1556
// divide one radix and clamp
1557
z->rsr (1); z->clamp ();
1559
if (mpi_geq (*z, m) == true) mpi_seq (*z, m);
1563
// this procedure computes a montgomery modular transformation of a mpi
1564
// without any verification
1565
// carefull: it is assumed here that m is odd and x < m
1566
static s_mpi* mpi_mmt (const s_mpi& x, const s_mpi& m, const t_quad rho) {
1567
// get the modular size
1568
long k = m.vsize ();
1569
// compute the exponent r**2 mod m
1570
s_mpi* y = new s_mpi (2*k+1, 1UL);
1571
mpi_deq (*y, m, true); y->clamp ();
1572
// compute the montgomery multiplication
1573
s_mpi* z = mpi_mmm (x, *y, m, rho); z->clamp ();
1578
// this procedure computes a montgomery inverse transformation of a mpi
1579
// without any verification
1580
// carefull: it is assumed here that m is odd and x < m
1581
static s_mpi* mpi_mit (const s_mpi& x, const s_mpi& m, const t_quad rho) {
1582
return mpi_mmm (x, 1, m, rho);
1585
// this procedure computes a montgomery modular exponentiation of a mpi
1586
// without any verification
1587
// carefull: it is assumed here that m is odd and x < m
1588
static s_mpi* mpi_mmp (const s_mpi& x, const s_mpi& e, const s_mpi& m,
1590
// initialize temporaries
1591
s_mpi* tr = mpi_mmt (1, m, rho);
1592
long em = e.getmsb () - 1;
1593
for (long i = em; i >= 0; i--) {
1595
s_mpi* tz = mpi_mmm (*tr, *tr, m, rho);
1596
*tr = *tz; delete tz;
1598
// check for bit set
1599
if (e.getbit (i) == true) {
1600
tz = mpi_mmm (*tr, x, m, rho);
1601
*tr = *tz; delete tz;
1608
// this procedure computes a montgomery modular exponentiation of a mpi
1609
// but unlike the other montgomery procedures, this one does the required
1611
static s_mpi* mpi_mme (const s_mpi& x, const s_mpi& e, const s_mpi& m) {
1612
// verify first that m is odd
1613
if (m.isodd () == false) {
1614
throw Exception ("internal-error",
1615
"montgomery exponentiation called with even modulus");
1617
// get the modulus rho factor
1618
t_quad rho = mpi_rho (m);
1619
// initialize and normalize x
1621
if (mpi_geq (tx, m) == true) mpi_deq (tx, m, true);
1622
// transform tx in the montgomery space
1623
s_mpi* mx = mpi_mmt (tx, m, rho);
1624
// compute the exponentiation
1625
s_mpi* mz = mpi_mmp (*mx, e, m, rho);
1626
// reverse the result
1627
s_mpi* z = mpi_mit (*mz, m, rho);
1628
// clean stuff and return
1634
// -------------------------------------------------------------------------
1635
// - public section -
1636
// -------------------------------------------------------------------------
1638
// compute the gcd of two relatifs
1640
Relatif Relatif::gcd (const Relatif& x, const Relatif& y) {
1645
s_mpi* mpi = mpi_gcd (*x.p_mpi, *y.p_mpi);
1648
Relatif result; delete result.p_mpi; result.p_mpi = nilp;
1650
// unlock and return;
1661
// compute the lcm of two relatifs
1663
Relatif Relatif::lcm (const Relatif& x, const Relatif& y) {
1668
Relatif result = (x * y) / Relatif::gcd (x, y);
1669
result.d_sgn = false;
1670
result.p_mpi->clamp ();
1671
// unlock and return;
1682
// compute the mmi of a relatif
1684
Relatif Relatif::mmi (const Relatif& x, const Relatif& m) {
1685
// check for existence
1686
if ((x.iseven () == true) && (m.iseven () == true)) return 0;
1687
// initialize temporaries
1695
while (u.iszero () == false) {
1696
// process u division
1697
while (u.iseven () == true) {
1699
if ((a.iseven () == true) && (b.iseven () == true)) {
1707
// process v division
1708
while (v.iseven () == true) {
1710
if ((c.iseven () == true) && (d.iseven () == true)) {
1729
if (u.iszero () == true) {
1734
if (v != 1) return 0;
1736
if (a < 0) return m + (a % m);
1740
// compute an optimized modular exponentiation
1742
Relatif Relatif::mme (const Relatif& x, const Relatif& e, const Relatif& m) {
1743
// check for negative exponent
1745
if (e.d_sgn == true) {
1747
throw Exception ("number-error", "invalid negative exponent in pow");
1749
// check for negative modulo
1751
if (m.d_sgn == true) {
1754
throw Exception ("number-error", "invalid negative modulo in pow");
1756
// process trivial case
1762
// lock argument and prepare result
1766
// use the montgomery exponentiation if m is odd
1767
if (m.isodd () == true) {
1769
delete result.p_mpi; result.p_mpi = nilp;
1770
result.p_mpi = mpi_mme (*x.p_mpi, *e.p_mpi, *m.p_mpi);
1772
result.d_sgn = (e.iseven () == true) ? false : x.d_sgn;
1774
if (result.p_mpi->clamp () == true) result.d_sgn = false;
1776
result = x.pow (e, m);
1790
// generate a random n bits relatif number
1792
Relatif Relatif::random (const long bits) {
1793
// check for valid size
1795
throw Exception ("size-error", "invalid random number size");
1798
Relatif result; delete result.p_mpi; result.p_mpi = nilp;
1799
result.p_mpi = mpi_rnd (bits);
1800
// here is the number
1804
// generate a random n bits odd or even relatif number
1806
Relatif Relatif::random (const long bits, const bool oddf) {
1807
// generate a random number
1808
Relatif result = Relatif::random (bits);
1810
if (result.iszero () == false) result.setbit (0, oddf);
1811
// here is the number
1815
// generate a random number upto a maximum
1817
Relatif Relatif::random (const Relatif& mrn) {
1821
if (mrn.d_sgn == true) {
1822
throw Exception ("sign-error", "invalid maximum negative number");
1824
// get the max number of bits
1825
long bits = mrn.p_mpi->getmsb ();
1827
Relatif result; delete result.p_mpi; result.p_mpi = nilp;
1828
result.p_mpi = mpi_rng (bits);
1829
if (mpi_geq (*result.p_mpi, *mrn.p_mpi) == true) {
1830
mpi_req (*result.p_mpi, 1);
1831
result.p_mpi->clamp ();
1834
// here is the number
1842
// change the sign of a relatif
1844
Relatif operator - (const Relatif& x) {
1847
// create an empty result
1848
Relatif result; delete result.p_mpi; result.p_mpi = nilp;
1849
// compute the result
1850
result.d_sgn = !x.d_sgn;
1851
result.p_mpi = new s_mpi (*x.p_mpi);
1853
if (result.p_mpi->clamp () == true) result.d_sgn = false;
1854
// unlock and return
1863
// add a relatif with an integer
1865
Relatif operator + (const Relatif& x, const t_long y) {
1868
// create an empty result
1869
Relatif result; delete result.p_mpi; result.p_mpi = nilp;
1871
bool ysgn = (y < 0);
1872
t_octa yval = ysgn ? -y : y;
1873
// compute the type of operation to do
1874
bool sflg = x.d_sgn ^ ysgn;
1875
// compute the result
1876
if (sflg == false) {
1877
result.p_mpi = mpi_add (*x.p_mpi, yval);
1878
result.d_sgn = x.d_sgn;
1880
bool xflg = mpi_geq (*x.p_mpi, yval);
1882
result.p_mpi = mpi_sub (*x.p_mpi, yval);
1883
result.d_sgn = x.d_sgn;
1885
result.p_mpi = mpi_sub (yval, *x.p_mpi);
1886
result.d_sgn = ysgn;
1890
if (result.p_mpi->clamp () == true) result.d_sgn = false;
1891
// unlock and return
1902
Relatif operator + (const Relatif& x, const Relatif& y) {
1906
// create an empty result
1907
Relatif result; delete result.p_mpi; result.p_mpi = nilp;
1908
// compute the type of operation to do
1909
bool sflg = x.d_sgn ^ y.d_sgn;
1910
// compute the result
1911
if (sflg == false) {
1912
result.p_mpi = mpi_add (*x.p_mpi, *y.p_mpi);
1913
result.d_sgn = x.d_sgn;
1915
bool xflg = mpi_geq (*x.p_mpi, *y.p_mpi);
1917
result.p_mpi = mpi_sub (*x.p_mpi, *y.p_mpi);
1918
result.d_sgn = x.d_sgn;
1920
result.p_mpi = mpi_sub (*y.p_mpi, *x.p_mpi);
1921
result.d_sgn = y.d_sgn;
1925
if (result.p_mpi->clamp () == true) result.d_sgn = false;
1926
// unlock and return
1937
// substract a relatif with an integer
1939
Relatif operator - (const Relatif& x, const t_long y) {
1942
// create an empty result
1943
Relatif result; delete result.p_mpi; result.p_mpi = nilp;
1945
bool ysgn = (y < 0);
1946
t_octa yval = ysgn ? -y : y;
1947
// compute the type of operation to do
1948
bool sflg = x.d_sgn ^ ysgn;
1949
// compute the result
1951
result.p_mpi = mpi_add (*x.p_mpi, yval);
1952
result.d_sgn = x.d_sgn;
1954
bool xflg = mpi_geq (*x.p_mpi, yval);
1956
result.p_mpi = mpi_sub (*x.p_mpi, yval);
1957
result.d_sgn = x.d_sgn;
1959
result.p_mpi = mpi_sub (yval, *x.p_mpi);
1960
result.d_sgn = !x.d_sgn;
1964
if (result.p_mpi->clamp () == true) result.d_sgn = false;
1965
// unlock and return
1974
// substract two relatifs
1976
Relatif operator - (const Relatif& x, const Relatif& y) {
1980
// create an empty result
1981
Relatif result; delete result.p_mpi; result.p_mpi = nilp;
1982
// compute the type of operation to do
1983
bool sflg = x.d_sgn ^ y.d_sgn;
1984
// compute the result
1986
result.p_mpi = mpi_add (*x.p_mpi, *y.p_mpi);
1987
result.d_sgn = x.d_sgn;
1989
bool xflg = mpi_geq (*x.p_mpi, *y.p_mpi);
1991
result.p_mpi = mpi_sub (*x.p_mpi, *y.p_mpi);
1992
result.d_sgn = x.d_sgn;
1994
result.p_mpi = mpi_sub (*y.p_mpi, *x.p_mpi);
1995
result.d_sgn = !x.d_sgn;
1999
if (result.p_mpi->clamp () == true) result.d_sgn = false;
2000
// unlock and return
2011
// multiply a relatif with an integer
2013
Relatif operator * (const Relatif& x, const t_long y) {
2016
// create an empty result
2017
Relatif result; delete result.p_mpi; result.p_mpi = nilp;
2019
bool ysgn = (y < 0);
2020
t_octa yval = ysgn ? -y : y;
2021
// compute the result
2022
result.d_sgn = x.d_sgn ^ ysgn;
2023
result.p_mpi = mpi_mul (*x.p_mpi, yval);
2025
if (result.p_mpi->clamp () == true) result.d_sgn = false;
2026
// unlock and return
2035
// multiply two relatifs
2037
Relatif operator * (const Relatif& x, const Relatif& y) {
2041
// create an empty result
2042
Relatif result; delete result.p_mpi; result.p_mpi = nilp;
2043
// compute the result
2044
result.d_sgn = x.d_sgn ^ y.d_sgn;
2045
result.p_mpi = mpi_mul (*x.p_mpi, *y.p_mpi);
2047
if (result.p_mpi->clamp () == true) result.d_sgn = false;
2048
// unlock and return
2059
// divide a relatif with an integer
2061
Relatif operator / (const Relatif& x, const t_long y) {
2066
throw Exception ("relatif-error", "division by zero");
2069
bool ysgn = (y < 0);
2070
t_octa yval = ysgn ? -y : y;
2071
// create an empty result
2073
// check for trivial case
2074
if (mpi_geq (*x.p_mpi, yval) == false) {
2078
// clean result data
2079
delete result.p_mpi; result.p_mpi = nilp;
2080
// compute the result
2081
result.d_sgn = x.d_sgn ^ ysgn;
2082
result.p_mpi = mpi_div (*x.p_mpi, yval, false);
2084
if (result.p_mpi->clamp () == true) result.d_sgn = false;
2085
// unlock and return
2094
// divide two relatifs
2096
Relatif operator / (const Relatif& x, const Relatif& y) {
2102
throw Exception ("relatif-error", "division by zero");
2104
// create an empty result
2106
// check trivial case
2107
if (mpi_geq (*x.p_mpi, *y.p_mpi) == false) {
2112
// clean result data
2113
delete result.p_mpi; result.p_mpi = nilp;
2114
// compute the result
2115
result.d_sgn = x.d_sgn ^ y.d_sgn;
2116
result.p_mpi = mpi_div (*x.p_mpi, *y.p_mpi, false);
2118
if (result.p_mpi->clamp () == true) result.d_sgn = false;
2119
// unlock and return
2130
// compute the reminder of a relatif with an integer
2132
Relatif operator % (const Relatif& x, const t_long y) {
2137
throw Exception ("relatif-error", "division by zero");
2140
bool ysgn = (y < 0);
2141
t_octa yval = ysgn ? -y : y;
2142
// create an empty result
2144
// check trivial case
2145
if (mpi_geq (*x.p_mpi, yval) == false) {
2150
// clean result data;
2151
delete result.p_mpi; result.p_mpi = nilp;
2152
// compute the result
2153
result.d_sgn = x.d_sgn;
2154
result.p_mpi = mpi_div (*x.p_mpi, yval, true);
2156
if (result.p_mpi->clamp () == true) result.d_sgn = false;
2157
// unlock and return
2166
// compute the reminder of two relatifs
2168
Relatif operator % (const Relatif& x, const Relatif& y) {
2174
throw Exception ("relatif-error", "division by zero");
2176
// create an empty result
2178
// check trivial case
2179
if (mpi_geq (*x.p_mpi, *y.p_mpi) == false) {
2185
// clean result data
2186
delete result.p_mpi; result.p_mpi = nilp;
2187
// compute the result
2188
result.d_sgn = x.d_sgn;
2189
result.p_mpi = mpi_div (*x.p_mpi, *y.p_mpi, true);
2191
if (result.p_mpi->clamp () == true) result.d_sgn = false;
2192
// unlock and return
2203
// bitwise negate a relatif
2205
Relatif operator ~ (const Relatif& x) {
2208
// create an empty result
2209
Relatif result; delete result.p_mpi; result.p_mpi = nilp;
2211
result.d_sgn = x.d_sgn;
2213
result.p_mpi = mpi_neg (*x.p_mpi);
2215
if (result.p_mpi->clamp () == true) result.d_sgn = false;
2216
// unlock and return
2225
// bitwise and two relatifs
2227
Relatif operator & (const Relatif& x, const Relatif& y) {
2231
// create an empty result
2232
Relatif result; delete result.p_mpi; result.p_mpi = nilp;
2234
result.d_sgn = x.d_sgn && y.d_sgn;
2236
result.p_mpi = mpi_and (*x.p_mpi, *y.p_mpi);
2238
if (result.p_mpi->clamp () == true) result.d_sgn = false;
2239
// unlock and return
2250
// bitwise or two relatifs
2252
Relatif operator | (const Relatif& x, const Relatif& y) {
2256
// create an empty result
2257
Relatif result; delete result.p_mpi; result.p_mpi = nilp;
2259
result.d_sgn = x.d_sgn || y.d_sgn;
2261
result.p_mpi = mpi_bor (*x.p_mpi, *y.p_mpi);
2263
if (result.p_mpi->clamp () == true) result.d_sgn = false;
2264
// unlock and return
2275
// bitwise xor two relatifs
2277
Relatif operator ^ (const Relatif& x, const Relatif& y) {
2281
// create an empty result
2282
Relatif result; delete result.p_mpi; result.p_mpi = nilp;
2284
result.d_sgn = x.d_sgn ^ y.d_sgn;
2286
result.p_mpi = mpi_xor (*x.p_mpi, *y.p_mpi);
2288
if (result.p_mpi->clamp () == true) result.d_sgn = false;
2289
// unlock and return
2300
// -------------------------------------------------------------------------
2301
// - class section -
2302
// -------------------------------------------------------------------------
2304
// create a default relatif
2306
Relatif::Relatif (void) {
2311
// create a relatif by value
2313
Relatif::Relatif (const t_long x) {
2316
// convert to unsigned
2317
t_octa data = d_sgn ? -x : x;
2319
p_mpi = new s_mpi (data);
2322
// create a relatif from a string
2324
Relatif::Relatif (const String& s) {
2330
// create a relatif from a byte array
2332
Relatif::Relatif (const t_byte* rbuf, const long size) {
2334
throw Exception ("size-error", "invalid relatif negative byte size");
2341
p_mpi = new s_mpi (rbuf, size); p_mpi->clamp ();
2345
// create a relatif from a byte array in complemented form
2347
Relatif::Relatif (const t_byte* rbuf, const long size, const bool cflg) {
2349
throw Exception ("size-error", "invalid relatif negative byte size");
2355
if (cflg == false) {
2357
p_mpi = new s_mpi (rbuf, size); p_mpi->clamp ();
2360
d_sgn = p_mpi->setsbuf (rbuf, size); p_mpi->clamp ();
2365
// copy construct this relatif
2367
Relatif::Relatif (const Relatif& that) {
2371
p_mpi = new s_mpi (*that.p_mpi);
2372
if (p_mpi->clamp () == true) d_sgn = false;
2380
// destroy this relatif
2382
Relatif::~Relatif (void) {
2386
// return the class name
2388
String Relatif::repr (void) const {
2392
// return a clone of this object
2394
Object* Relatif::clone (void) const {
2395
return new Relatif (*this);
2398
// return a literal representation of this relatif
2400
String Relatif::toliteral (void) const {
2402
String result = tostring () + 'R';
2407
// get a string representation on this relatif
2409
String Relatif::tostring (void) const {
2413
Relatif dval = d_sgn ? -(*this) : (*this);
2415
// loop until we reach 0
2417
Relatif rval = dval % bval;
2418
buffer.pushback ((char) ('0' + rval.tolong ()));
2421
// readjust for sign and null value
2422
if (buffer.length () == 0) {
2427
if (d_sgn == true) result = result + '-';
2428
result = result + buffer.tostring ();
2437
// return the relatif serial code
2439
t_byte Relatif::serialid (void) const {
2440
return SERIAL_RELT_ID;
2443
// serialize this relatif
2445
void Relatif::wrstream (OutputStream& os) const {
2448
// serialize the sign
2449
Boolean sign (d_sgn);
2451
// serialize the mpi
2452
p_mpi->wrstream (os);
2460
// deserialize this relatif
2462
void Relatif::rdstream (InputStream& is) {
2465
// clean the old value
2466
delete p_mpi; p_mpi = nilp;
2467
// deserialize the sign
2470
d_sgn = sign.tobool ();
2471
// deserialize the mpi
2472
p_mpi = mpi_rds (is);
2480
// assign a relatif to this one
2482
Relatif& Relatif::operator = (const Relatif& that) {
2483
// check for same objects
2484
if (this == &that) return *this;
2493
p_mpi = new s_mpi (*that.p_mpi);
2494
if (p_mpi->clamp () == true) d_sgn = false;
2505
// add a relatif to this one
2507
Relatif& Relatif::operator += (const Relatif& x) {
2511
// compute the type of operation to do
2512
bool sflg = d_sgn ^ x.d_sgn;
2513
// compute the result
2514
if (sflg == false) {
2515
s_mpi* mpi = mpi_add (*p_mpi, *x.p_mpi);
2516
delete p_mpi; p_mpi = mpi;
2518
bool xflg = mpi_geq (*p_mpi, *x.p_mpi);
2520
s_mpi* mpi = mpi_sub (*p_mpi, *x.p_mpi);
2521
delete p_mpi; p_mpi = mpi;
2523
s_mpi* mpi = mpi_sub (*x.p_mpi, *p_mpi);
2524
delete p_mpi; p_mpi = mpi;
2529
if (p_mpi->clamp () == true) d_sgn = false;
2530
// unlock and return
2541
// substract a relatif to this one
2543
Relatif& Relatif::operator -= (const Relatif& x) {
2547
// compute the type of operation to do
2548
bool sflg = d_sgn ^ x.d_sgn;
2549
// compute the result
2551
s_mpi* mpi = mpi_add (*p_mpi, *x.p_mpi);
2552
delete p_mpi; p_mpi = mpi;
2554
bool xflg = mpi_geq (*p_mpi, *x.p_mpi);
2556
s_mpi* mpi = mpi_sub (*p_mpi, *x.p_mpi);
2557
delete p_mpi; p_mpi = mpi;
2559
s_mpi* mpi = mpi_sub (*x.p_mpi, *p_mpi);
2560
delete p_mpi; p_mpi = mpi;
2565
if (p_mpi->clamp () == true) d_sgn = false;
2566
// unlock and return
2577
// multiply a relatif with this one
2579
Relatif& Relatif::operator *= (const Relatif& x) {
2583
// compute the result
2584
d_sgn = x.d_sgn ^ x.d_sgn;
2585
s_mpi* mpi = mpi_mul (*p_mpi, *x.p_mpi);
2586
delete p_mpi; p_mpi = mpi;
2588
if (p_mpi->clamp () == true) d_sgn = false;
2589
// unlock and return
2600
// divide a relatif with this one
2602
Relatif& Relatif::operator /= (const Relatif& x) {
2606
// compute the result
2607
d_sgn = x.d_sgn ^ x.d_sgn;
2608
s_mpi* mpi = mpi_div (*p_mpi, *x.p_mpi, false);
2609
delete p_mpi; p_mpi = mpi;
2611
if (p_mpi->clamp () == true) d_sgn = false;
2612
// unlock and return
2623
// prefix increment this relatif
2625
Relatif& Relatif::operator ++ (void) {
2628
// check the sign first
2629
if (d_sgn == false) {
2630
s_mpi* mpi = mpi_inc (*p_mpi);
2631
delete p_mpi; p_mpi = mpi;
2633
if (mpi_gth (*p_mpi, 1) == true) {
2634
s_mpi* mpi = mpi_dec (*p_mpi);
2635
delete p_mpi; p_mpi = mpi;
2637
delete p_mpi; p_mpi = new s_mpi;
2642
if (p_mpi->clamp () == true) d_sgn = false;
2643
// unlock and return
2652
// prefix decrements this relatif
2654
Relatif& Relatif::operator -- (void) {
2657
// check the sign first
2658
if (d_sgn == true) {
2659
s_mpi* mpi = mpi_inc (*p_mpi);
2660
delete p_mpi; p_mpi = mpi;
2662
if (mpi_gth (*p_mpi, 1) == true) {
2663
s_mpi* mpi = mpi_dec (*p_mpi);
2664
delete p_mpi; p_mpi = mpi;
2666
delete p_mpi; p_mpi = new s_mpi;
2671
if (p_mpi->clamp () == true) d_sgn = false;
2672
// unlock and return
2681
// postfix increments this relatif
2683
Relatif Relatif::operator ++ (int) {
2687
Relatif result = *this;
2688
// check the sign first
2689
if (d_sgn == false) {
2690
s_mpi* mpi = mpi_inc (*p_mpi);
2691
delete p_mpi; p_mpi = mpi;
2693
if (mpi_gth (*p_mpi, 1) == true) {
2694
s_mpi* mpi = mpi_dec (*p_mpi);
2695
delete p_mpi; p_mpi = mpi;
2697
delete p_mpi; p_mpi = new s_mpi;
2702
if (p_mpi->clamp () == true) d_sgn = false;
2703
// unlock and return
2712
// postfix decrements this relatif
2714
Relatif Relatif::operator -- (int) {
2718
Relatif result = *this;
2719
// check the sign first
2720
if (d_sgn == true) {
2721
s_mpi* mpi = mpi_inc (*p_mpi);
2722
delete p_mpi; p_mpi = mpi;
2724
if (mpi_gth (*p_mpi, 1) == true) {
2725
s_mpi* mpi = mpi_dec (*p_mpi);
2726
delete p_mpi; p_mpi = mpi;
2728
delete p_mpi; p_mpi = new s_mpi;
2733
if (p_mpi->clamp () == true) d_sgn = false;
2734
// unlock and return
2743
// shift left this relatif by a certain amount
2745
Relatif Relatif::operator << (const long asl) const {
2749
// create an empty result
2750
Relatif result; delete result.p_mpi; result.p_mpi = nilp;
2751
// compute the shifted mpi
2752
result.d_sgn = d_sgn;
2754
result.p_mpi = mpi_shl (*p_mpi, asl);
2756
result.p_mpi = mpi_shr (*p_mpi, -asl);
2759
if (result.p_mpi->clamp () == true) result.d_sgn = false;
2769
// shift right this relatif by a certain amount
2771
Relatif Relatif::operator >> (const long asr) const {
2775
// create an empty result
2776
Relatif result; delete result.p_mpi; result.p_mpi = nilp;
2777
// compute the shifted mpi
2778
result.d_sgn = d_sgn;
2780
result.p_mpi = mpi_shr (*p_mpi, asr);
2782
result.p_mpi = mpi_shl (*p_mpi, -asr);
2785
if (result.p_mpi->clamp () == true) result.d_sgn = false;
2795
// shift left this relatif by a certain amount
2797
Relatif& Relatif::operator <<= (const long asl) {
2802
mpi_leq (*p_mpi, asl);
2804
mpi_req (*p_mpi, -asl);
2807
if (p_mpi->clamp () == true) d_sgn = false;
2817
// shift right this relatif by a certain amount
2819
Relatif& Relatif::operator >>= (const long asr) {
2824
mpi_req (*p_mpi, asr);
2826
mpi_leq (*p_mpi, -asr);
2829
if (p_mpi->clamp () == true) d_sgn = false;
2839
// compare a relatif with an integer
2841
bool Relatif::operator == (const t_long x) const {
2845
bool xsgn = (x < 0);
2846
t_octa xval = xsgn ? -x : x;
2848
bool result = (d_sgn == xsgn);
2849
// check for data equality
2850
if (result == true) result = mpi_eql (*p_mpi, xval);
2851
// unlock and return
2860
// compare two relatifs
2862
bool Relatif::operator == (const Relatif& x) const {
2867
bool result = (d_sgn == x.d_sgn);
2868
// check for data equality
2869
if (result == true) result = mpi_eql (*p_mpi, *x.p_mpi);
2870
// unlock and return
2881
// compare two relatifs
2883
bool Relatif::operator != (const t_long x) const {
2887
bool xsgn = (x < 0);
2888
t_octa xval = xsgn ? -x : x;
2890
bool result = (d_sgn == xsgn);
2891
// check for data equality
2892
if (result == true) result = mpi_eql (*p_mpi, xval);
2893
// unlock and return
2902
// compare two relatifs
2904
bool Relatif::operator != (const Relatif& x) const {
2909
bool result = (d_sgn == x.d_sgn);
2910
// check for data equality
2911
if (result == true) result = mpi_eql (*p_mpi, *x.p_mpi);
2912
// unlock and return
2923
// compare a relatif with an integer
2925
bool Relatif::operator < (const t_long x) const {
2929
bool xsgn = (x < 0);
2930
t_octa xval = xsgn ? -x : x;
2931
// check against sign first
2932
if ((d_sgn == true) && (xsgn == false)) {
2936
if ((d_sgn == false) && (xsgn == true)){
2940
// the number have the same sign
2941
bool result = !mpi_geq (*p_mpi, xval);
2950
// compare two relatifs
2952
bool Relatif::operator < (const Relatif& x) const {
2956
// check against sign first
2957
if ((d_sgn == true) && (x.d_sgn == false)) {
2962
if ((d_sgn == false) && (x.d_sgn == true)){
2967
// the number have the same sign
2968
bool result = !mpi_geq (*p_mpi, *x.p_mpi);
2979
// compare a relatif with an integer
2981
bool Relatif::operator <= (const t_long x) const {
2985
bool xsgn = (x < 0);
2986
t_octa xval = xsgn ? -x : x;
2987
// check against sign first
2988
if ((d_sgn == true) && (xsgn == false)) {
2992
if ((d_sgn == false) && (xsgn == true)){
2996
// the number have the same sign
2997
bool result = !mpi_gth (*p_mpi, xval);
3006
// compare two relatifs
3008
bool Relatif::operator <= (const Relatif& x) const {
3012
// check against sign first
3013
if ((d_sgn == true) && (x.d_sgn == false)) {
3018
if ((d_sgn == false) && (x.d_sgn == true)){
3023
// the number have the same sign
3024
bool result = !mpi_gth (*p_mpi, *x.p_mpi);
3035
// compare a relatif with an integer
3037
bool Relatif::operator > (const t_long x) const {
3041
bool xsgn = (x < 0);
3042
t_octa xval = xsgn ? -x : x;
3043
// check against sign first
3044
if ((d_sgn == true) && (xsgn == false)) {
3048
if ((d_sgn == false) && (xsgn == true)){
3052
// the number have the same sign
3053
bool result = mpi_gth (*p_mpi, xval);
3062
// compare two relatifs
3064
bool Relatif::operator > (const Relatif& x) const {
3068
// check against sign first
3069
if ((d_sgn == true) && (x.d_sgn == false)) {
3074
if ((d_sgn == false) && (x.d_sgn == true)){
3079
// the number have the same sign
3080
bool result = mpi_gth (*p_mpi, *x.p_mpi);
3091
// compare a relatif with an integer
3093
bool Relatif::operator >= (const t_long x) const {
3097
bool xsgn = (x < 0);
3098
t_octa xval = xsgn ? -x : x;
3099
// check against sign first
3100
if ((d_sgn == true) && (xsgn == false)) {
3104
if ((d_sgn == false) && (xsgn == true)){
3108
// the number have the same sign
3109
bool result = mpi_geq (*p_mpi, xval);
3118
// compare two relatifs
3120
bool Relatif::operator >= (const Relatif& x) const {
3124
// check against sign first
3125
if ((d_sgn == true) && (x.d_sgn == false)) {
3130
if ((d_sgn == false) && (x.d_sgn == true)){
3135
// the number have the same sign
3136
bool result = mpi_geq (*p_mpi, *x.p_mpi);
3147
// return true if this relatif is zero
3149
bool Relatif::iszero (void) const {
3153
bool result = p_mpi->iszero ();
3154
// check consistency
3155
if ((d_sgn == true) && (result == true)) {
3156
throw Exception ("internal-error", "inconsistent negative null sign");
3166
// return true if this relatif is even
3168
bool Relatif::iseven (void) const {
3171
bool result = p_mpi->iseven ();
3180
// return true if this relatif is odd
3182
bool Relatif::isodd (void) const {
3185
bool result = p_mpi->isodd ();
3194
// return the absolute value of this relatif
3196
Relatif Relatif::abs (void) const {
3199
// prepare the result
3200
Relatif result = *this;
3202
result.d_sgn = false;
3203
// unlock and return
3212
// compute the power of a relatif
3214
Relatif Relatif::pow (const t_long e) const {
3215
// check for negative exponent
3217
throw Exception ("exponent-error", "invalid negative exponent in pow");
3219
// process trivial case
3226
Relatif result = *this;
3233
Relatif result; delete result.p_mpi; result.p_mpi = nilp;
3234
result.p_mpi = mpi_pow (*p_mpi, e);
3236
result.d_sgn = ((e & 1) == 0) ? false : d_sgn;
3238
if (result.p_mpi->clamp () == true) result.d_sgn = false;
3248
// compute the power of a relatif
3250
Relatif Relatif::pow (const Relatif& e) const {
3251
// check for negative exponent
3253
if (e.d_sgn == true) {
3255
throw Exception ("exponent-error", "invalid negative exponent in pow");
3257
// process trivial case
3264
Relatif result = *this;
3268
// compute the power
3271
Relatif result; delete result.p_mpi; result.p_mpi = nilp;
3272
result.p_mpi = mpi_pow (*p_mpi, *e.p_mpi);
3274
result.d_sgn = (e.iseven () == true) ? false : d_sgn;
3276
if (result.p_mpi->clamp () == true) result.d_sgn = false;
3287
// compute the modular exponentiation of a relatif
3289
Relatif Relatif::pow (const t_long e, const Relatif& m) const {
3290
// check for negative exponent
3292
throw Exception ("exponent-error", "invalid negative exponent in pow");
3294
// check the modulus
3296
if (m.d_sgn == true) {
3298
throw Exception ("modulus-error", "invalid negative modulus in pow");
3300
// process trivial case
3308
Relatif result = *this % m;
3313
// compute the modular exponentiation
3316
Relatif result; delete result.p_mpi; result.p_mpi = nilp;
3317
result.p_mpi = mpi_pow (*p_mpi, e, *m.p_mpi);
3319
result.d_sgn = ((e & 1) == 0) ? false : d_sgn;
3321
if (result.p_mpi->clamp () == true) result.d_sgn = false;
3332
// compute the modular exponentiation of a relatif
3334
Relatif Relatif::pow (const Relatif& e, const Relatif& m) const {
3335
// check for negative exponent
3337
if (e.d_sgn == true) {
3339
throw Exception ("exponent-error", "invalid negative exponent in pow");
3341
// check the modulus
3343
if (m.d_sgn == true) {
3346
throw Exception ("modulus-error", "invalid negative modulus in pow");
3348
// process trivial case
3357
Relatif result = *this % m;
3363
// compute the modular exponentiation
3366
Relatif result; delete result.p_mpi; result.p_mpi = nilp;
3367
result.p_mpi = mpi_pow (*p_mpi, *e.p_mpi, *m.p_mpi);
3369
result.d_sgn = ((e & 1) == 0) ? false : d_sgn;
3371
if (result.p_mpi->clamp () == true) result.d_sgn = false;
3384
// return the lsb of this relatif
3386
long Relatif::getlsb (void) const {
3389
long result = p_mpi->getlsb ();
3398
// return the msb of this relatif
3400
long Relatif::getmsb (void) const {
3403
long result = p_mpi->getmsb ();
3412
// return the relatif bit value by position
3414
bool Relatif::getbit (const long bpos) const {
3415
// check valid position and lock
3417
throw Exception ("position-error", "invalid negative bit position");
3422
bool result = p_mpi->getbit (bpos);
3431
// set the relatif bit value by position
3433
void Relatif::setbit (const long bpos, const bool bval) {
3434
// check valid position and lock
3436
throw Exception ("position-error", "invalid negative bit position");
3441
p_mpi->setbit (bpos, bval);
3449
// get the relatif byte buffer size
3451
long Relatif::getbbs (void) const {
3454
long result = p_mpi->bsize ();
3463
// fill an unsigned buffer representation by size
3465
long Relatif::toubuf (t_byte* rbuf, const long size) const {
3468
// bind the mpi value
3469
long result = p_mpi->toubuf (rbuf, size);
3470
// unlock and return
3479
// fill a signed buffer representation by size
3481
long Relatif::tosbuf (t_byte* rbuf, const long size) const {
3484
// bind the mpi value
3485
long result = p_mpi->tosbuf (rbuf, size, d_sgn);
3486
// unlock and return
3495
// fill a large buffer with an unsigned representation
3497
long Relatif::tobyte (t_byte* rbuf, const long size) const {
3500
// bind the mpi value
3501
long result = p_mpi->tobyte (rbuf, size);
3502
// unlock and return
3511
// convert this relatif into a hexadecimal representation
3513
String Relatif::tohexa (void) const {
3516
// prepare result string
3517
String result = d_sgn ? "-0x" : "0x";
3518
// bind the mpi value
3519
result += p_mpi->tohexa ();
3520
// unlock and return
3529
// convert this relatif into a hexadecimal string
3531
String Relatif::tohstr (void) const {
3534
// bind the mpi value
3535
String result = p_mpi->tohexa ();
3536
// unlock and return
3545
// convert this relatif to an integer
3547
t_long Relatif::tolong (void) const {
3551
t_octa data = p_mpi->toocta ();
3552
// check for overflow
3553
if ((d_sgn == true) && (data > MAX_OCTA_PVAL)) {
3554
throw Exception ("overflow-error", "cannot convert negative number");
3556
// adjust with the sign
3557
t_long result = d_sgn ? - (t_long) data : (t_long) data;
3566
// -------------------------------------------------------------------------
3567
// - object section -
3568
// -------------------------------------------------------------------------
3571
static const long QUARK_ZONE_LENGTH = 30;
3572
static QuarkZone zone (QUARK_ZONE_LENGTH);
3574
// the object supported quarks
3575
static const long QUARK_OR = zone.intern ("or");
3576
static const long QUARK_OPP = zone.intern ("++");
3577
static const long QUARK_OMM = zone.intern ("--");
3578
static const long QUARK_ADD = zone.intern ("+");
3579
static const long QUARK_SUB = zone.intern ("-");
3580
static const long QUARK_MUL = zone.intern ("*");
3581
static const long QUARK_DIV = zone.intern ("/");
3582
static const long QUARK_EQL = zone.intern ("==");
3583
static const long QUARK_NEQ = zone.intern ("!=");
3584
static const long QUARK_LTH = zone.intern ("<");
3585
static const long QUARK_LEQ = zone.intern ("<=");
3586
static const long QUARK_GTH = zone.intern (">");
3587
static const long QUARK_GEQ = zone.intern (">=");
3588
static const long QUARK_AEQ = zone.intern ("+=");
3589
static const long QUARK_SEQ = zone.intern ("-=");
3590
static const long QUARK_MEQ = zone.intern ("*=");
3591
static const long QUARK_DEQ = zone.intern ("/=");
3592
static const long QUARK_ABS = zone.intern ("abs");
3593
static const long QUARK_AND = zone.intern ("and");
3594
static const long QUARK_SHL = zone.intern ("shl");
3595
static const long QUARK_SHR = zone.intern ("shr");
3596
static const long QUARK_XOR = zone.intern ("xor");
3597
static const long QUARK_MOD = zone.intern ("mod");
3598
static const long QUARK_NOT = zone.intern ("not");
3599
static const long QUARK_POW = zone.intern ("pow");
3600
static const long QUARK_MMI = zone.intern ("mmi");
3601
static const long QUARK_ODDP = zone.intern ("odd-p");
3602
static const long QUARK_EVENP = zone.intern ("even-p");
3603
static const long QUARK_ZEROP = zone.intern ("zero-p");
3604
static const long QUARK_GETMSB = zone.intern ("get-msb");
3606
// create a new object in a generic way
3608
Object* Relatif::mknew (Vector* argv) {
3609
if ((argv == nilp) || (argv->length () == 0)) return new Relatif;
3610
if (argv->length () != 1)
3611
throw Exception ("argument-error",
3612
"too many argument with relatif constructor");
3613
// try to map the relatif argument
3614
Object* obj = argv->get (0);
3615
if (obj == nilp) return new Relatif;
3617
// try an integer object
3618
Integer* ival = dynamic_cast <Integer*> (obj);
3619
if (ival != nilp) return new Relatif (ival->tolong ());
3621
// try a relatif object
3622
Relatif* xval = dynamic_cast <Relatif*> (obj);
3623
if (xval != nilp) return new Relatif (*xval);
3625
// try a real object
3626
Real* rval = dynamic_cast <Real*> (obj);
3627
if (rval != nilp) return new Relatif (rval->tolong ());
3629
// try a character object
3630
Character* cval = dynamic_cast <Character*> (obj);
3631
if (cval != nilp) return new Relatif (cval->toquad ());
3633
// try a string object
3634
String* sval = dynamic_cast <String*> (obj);
3635
if (sval != nilp) return new Relatif (*sval);
3638
throw Exception ("type-error", "illegal object with relatif constructor",
3642
// return true if the given quark is defined
3644
bool Relatif::isquark (const long quark, const bool hflg) const {
3646
if (zone.exists (quark) == true) {
3650
bool result = hflg ? Number::isquark (quark, hflg) : false;
3655
// operate this object with another object
3657
Object* Relatif::oper (t_oper type, Object* object) {
3658
Integer* iobj = dynamic_cast <Integer*> (object);
3659
Relatif* robj = dynamic_cast <Relatif*> (object);
3662
if (iobj != nilp) return new Relatif (*this + iobj->tolong ());
3663
if (robj != nilp) return new Relatif (*this + *robj);
3666
if (iobj != nilp) return new Relatif (*this - iobj->tolong ());
3667
if (robj != nilp) return new Relatif (*this - *robj);
3670
if (iobj != nilp) return new Relatif (*this * iobj->tolong ());
3671
if (robj != nilp) return new Relatif (*this * *robj);
3674
if (iobj != nilp) return new Relatif (*this / iobj->tolong ());
3675
if (robj != nilp) return new Relatif (*this / *robj);
3678
return new Relatif (-(*this));
3681
if (iobj != nilp) return new Boolean (*this == iobj->tolong ());
3682
if (robj != nilp) return new Boolean (*this == *robj);
3685
if (iobj != nilp) return new Boolean (*this != iobj->tolong ());
3686
if (robj != nilp) return new Boolean (*this != *robj);
3689
if (iobj != nilp) return new Boolean (*this >= iobj->tolong ());
3690
if (robj != nilp) return new Boolean (*this >= *robj);
3693
if (iobj != nilp) return new Boolean (*this > iobj->tolong ());
3694
if (robj != nilp) return new Boolean (*this > *robj);
3697
if (iobj != nilp) return new Boolean (*this <= iobj->tolong ());
3698
if (robj != nilp) return new Boolean (*this <= *robj);
3701
if (iobj != nilp) return new Boolean (*this < iobj->tolong ());
3702
if (robj != nilp) return new Boolean (*this < *robj);
3705
throw Exception ("type-error", "invalid operand with relatif",
3706
Object::repr (object));
3709
// set an object to this relatif
3711
Object* Relatif::vdef (Runnable* robj, Nameset* nset, Object* object) {
3712
Integer* iobj = dynamic_cast <Integer*> (object);
3714
*this = iobj->tolong ();
3717
Real* fobj = dynamic_cast <Real*> (object);
3719
*this = fobj->tolong ();
3722
Relatif* mobj = dynamic_cast <Relatif*> (object);
3727
throw Exception ("type-error", "invalid object with relatif vdef",
3728
Object::repr (object));
3731
// apply this object with a set of arguments and a quark
3733
Object* Relatif::apply (Runnable* robj, Nameset* nset, const long quark,
3735
// get the number of arguments
3736
long argc = (argv == nilp) ? 0 : argv->length ();
3738
// dispatch 0 argument
3740
if (quark == QUARK_ABS) return new Relatif (abs ());
3741
if (quark == QUARK_EVENP) return new Boolean (iseven ());
3742
if (quark == QUARK_ODDP) return new Boolean (isodd ());
3743
if (quark == QUARK_ZEROP) return new Boolean (iszero ());
3744
if (quark == QUARK_GETMSB) return new Integer (getmsb ());
3745
if (quark == QUARK_OPP) {
3750
if (quark == QUARK_OMM) {
3755
if (quark == QUARK_NOT) {
3756
return new Relatif (~(*this));
3760
// dispatch 1 argument
3762
if (quark == QUARK_ADD) return oper (Object::ADD, argv->get (0));
3763
if (quark == QUARK_SUB) return oper (Object::SUB, argv->get (0));
3764
if (quark == QUARK_MUL) return oper (Object::MUL, argv->get (0));
3765
if (quark == QUARK_DIV) return oper (Object::DIV, argv->get (0));
3766
if (quark == QUARK_EQL) return oper (Object::EQL, argv->get (0));
3767
if (quark == QUARK_NEQ) return oper (Object::NEQ, argv->get (0));
3768
if (quark == QUARK_LTH) return oper (Object::LTH, argv->get (0));
3769
if (quark == QUARK_LEQ) return oper (Object::LEQ, argv->get (0));
3770
if (quark == QUARK_GTH) return oper (Object::GTH, argv->get (0));
3771
if (quark == QUARK_GEQ) return oper (Object::GEQ, argv->get (0));
3773
if (quark == QUARK_AEQ) {
3774
t_long val = argv->getlong (0);
3779
if (quark == QUARK_SEQ) {
3780
t_long val = argv->getlong (0);
3785
if (quark == QUARK_MEQ) {
3786
t_long val = argv->getlong (0);
3791
if (quark == QUARK_DEQ) {
3792
t_long val = argv->getlong (0);
3797
if (quark == QUARK_MOD) {
3798
Object* obj = argv->get (0);
3799
// check for relatif
3800
Relatif* mobj = dynamic_cast <Relatif*> (obj);
3802
Object* result = new Relatif (*this % *mobj);
3805
// check for integer
3806
Integer* iobj = dynamic_cast <Integer*> (obj);
3808
Object* result = new Relatif (*this % iobj->tolong ());
3811
throw Exception ("type-error", "invalid object with mod operator",
3812
Object::repr (obj));
3814
if (quark == QUARK_POW) {
3815
Object* obj = argv->get (0);
3816
// check for relatif
3817
Relatif* mobj = dynamic_cast <Relatif*> (obj);
3819
Object* result = new Relatif (pow (*mobj));
3822
// check for integer
3823
Integer* iobj = dynamic_cast <Integer*> (obj);
3825
Object* result = new Relatif (pow (iobj->tolong ()));
3828
throw Exception ("type-error", "invalid object with pow operator",
3829
Object::repr (obj));
3831
if (quark == QUARK_MMI) {
3832
Object* obj = argv->get (0);
3833
// check for relatif
3834
Relatif* mobj = dynamic_cast <Relatif*> (obj);
3836
Object* result = new Relatif (Relatif::mmi (*this, *mobj));
3839
// check for integer
3840
Integer* iobj = dynamic_cast <Integer*> (obj);
3842
t_long ival = iobj->tolong ();
3843
Object* result = new Relatif (Relatif::mmi (*this, ival));
3846
throw Exception ("type-error", "invalid object with mmi operator",
3847
Object::repr (obj));
3849
if (quark == QUARK_SHL) {
3850
t_long asl = argv->getlong (0);
3851
Object* result = new Relatif (*this << asl);
3854
if (quark == QUARK_SHR) {
3855
t_long asr = argv->getlong (0);
3856
Object* result = new Relatif (*this >> asr);
3859
if (quark == QUARK_XOR) {
3860
Object* obj = argv->get (0);
3861
// check for relatif
3862
Relatif* mobj = dynamic_cast <Relatif*> (obj);
3864
Object* result = new Relatif (*this ^ *mobj);
3867
// check for integer
3868
Integer* iobj = dynamic_cast <Integer*> (obj);
3870
Object* result = new Relatif (*this ^ iobj->tolong ());
3873
throw Exception ("type-error", "invalid object with xor operator",
3874
Object::repr (obj));
3876
if (quark == QUARK_AND) {
3877
Object* obj = argv->get (0);
3878
// check for relatif
3879
Relatif* mobj = dynamic_cast <Relatif*> (obj);
3881
Object* result = new Relatif (*this & *mobj);
3884
// check for integer
3885
Integer* iobj = dynamic_cast <Integer*> (obj);
3887
Object* result = new Relatif (*this & iobj->tolong ());
3890
throw Exception ("type-error", "invalid object with and operator",
3891
Object::repr (obj));
3893
if (quark == QUARK_OR) {
3894
Object* obj = argv->get (0);
3895
// check for relatif
3896
Relatif* mobj = dynamic_cast <Relatif*> (obj);
3898
Object* result = new Relatif (*this | *mobj);
3901
// check for integer
3902
Integer* iobj = dynamic_cast <Integer*> (obj);
3904
Object* result = new Relatif (*this | iobj->tolong ());
3907
throw Exception ("type-error", "invalid object with or operator",
3908
Object::repr (obj));
3911
// dispatch 2 arguments
3913
if (quark == QUARK_POW) {
3914
Object* e = argv->get (0);
3915
Object* m = argv->get (1);
3916
Relatif* mmo = dynamic_cast <Relatif*> (m);
3918
throw Exception ("type-error", "invalid modulus with pow operator",
3921
// check for relatif
3922
Relatif* emo = dynamic_cast <Relatif*> (e);
3924
Object* result = new Relatif (pow (*emo, *mmo));
3927
// check for integer
3928
Integer* eio = dynamic_cast <Integer*> (e);
3930
t_long ie = eio->tolong ();
3931
Object* result = new Relatif (pow (ie, *mmo));
3934
throw Exception ("type-error", "invalid exponent with pow operator",
3938
// call the number method
3939
return Number::apply (robj, nset, quark, argv);