~ubuntu-branches/ubuntu/wily/afnix/wily

« back to all changes in this revision

Viewing changes to src/lib/std/shl/Relatif.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Anibal Monsalve Salazar
  • Date: 2011-03-16 21:31:18 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20110316213118-gk4k3ez3e5d2huna
Tags: 2.0.0-1
* QA upload.
* New upstream release
* Debian source format is 3.0 (quilt)
* Fix debhelper-but-no-misc-depends
* Fix ancient-standards-version
* Fix package-contains-linda-override
* debhelper compatibility is 7
* Fix dh-clean-k-is-deprecated

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// ---------------------------------------------------------------------------
 
2
// - Relatif.cpp                                                             -
 
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.                  -
 
7
// -                                                                         -
 
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
// ---------------------------------------------------------------------------
 
16
 
 
17
#include "Real.hpp"
 
18
#include "Vector.hpp"
 
19
#include "Stdsid.hxx"
 
20
#include "Buffer.hpp"
 
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"
 
31
#include "ccnv.hpp"
 
32
 
 
33
namespace afnix {
 
34
 
 
35
  // -------------------------------------------------------------------------
 
36
  // - private section                                                       -
 
37
  // -------------------------------------------------------------------------
 
38
 
 
39
  // the 32 bits shift factor
 
40
  const long   BIT_QUAD_SHIX = 5;
 
41
  // the 32 bits unity
 
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;
 
47
  // the mpi quad mask
 
48
  const t_octa MPI_QUAD_MASK = 0x00000000FFFFFFFFULL;
 
49
  // the 64 bits unity
 
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;
 
55
 
 
56
  // this function computes the maximum of two long integers
 
57
  static inline long max (const long x, const long y) {
 
58
    return x > y ? x : y;
 
59
  }
 
60
 
 
61
  // this function computes the byte size of a quad
 
62
  static inline long bsq (const t_quad x) {
 
63
    // check byte 3
 
64
    if ((x & 0xFF000000UL) != nilq) return 4;
 
65
    // check byte 2
 
66
    if ((x & 0x00FF0000UL) != nilq) return 3;
 
67
    // check byte 1
 
68
    if ((x & 0x0000FF00UL) != nilq) return 2;
 
69
    // only one byte
 
70
    return 1;
 
71
  }
 
72
 
 
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) {
 
76
    t_quad result = 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");
 
85
          }
 
86
        }
 
87
      }
 
88
    }
 
89
    return result;
 
90
  }
 
91
 
 
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
 
99
    long   pos = 1;
 
100
    t_byte val = x;
 
101
    for (long i = 0; i < 8; i++) {
 
102
      val <<= 1;
 
103
      if ((val & 0x80) != 0x00) break;
 
104
      pos++;
 
105
    }
 
106
    // check null (should not happen)
 
107
    if (val == 0x00) return 0x00;
 
108
    // extend byte
 
109
    for (long i = 0; i < pos; i++) {
 
110
      val >>= 1;
 
111
      val |= 0x80;
 
112
    }
 
113
    return val;
 
114
  }
 
115
 
 
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
 
119
    t_quad qval = x;
 
120
    // check for index 0
 
121
    if (index == 0) return (t_byte) (qval & 0x000000FFUL);
 
122
    // check for index 1
 
123
    if (index == 1) return (t_byte) ((qval >> 8) & 0x000000FFUL);
 
124
    // check for index 2
 
125
    if (index == 2) return (t_byte) ((qval >> 16) & 0x000000FFUL);
 
126
    // check for index 3
 
127
    if (index == 3) return (t_byte) ((qval >> 24) & 0x000000FFUL);
 
128
    // invalid index
 
129
    throw Exception ("mpi-error", "illegal quad byte index");
 
130
  }
 
131
 
 
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;
 
136
    // check for index 0
 
137
    switch (index) {
 
138
    case 0:
 
139
      break;
 
140
    case 1:
 
141
      result <<= 8;
 
142
      break;
 
143
    case 2:
 
144
      result <<= 16;
 
145
      break;
 
146
    case 3:
 
147
      result <<= 24;
 
148
      break;
 
149
    default:
 
150
      throw Exception ("mpi-error", "illegal byte quad index");
 
151
      break;
 
152
    }
 
153
    return result;
 
154
  }
 
155
 
 
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;
 
159
  }
 
160
 
 
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;
 
165
    // find the msb
 
166
    long lsb = 0;
 
167
    long msb = 32;
 
168
    while ((lsb + 1) != msb) {
 
169
      long mid = (lsb + msb) >> 1;
 
170
      if ((x & (MPI_QUAD_PMAX << mid)) != 0)
 
171
        lsb = mid;
 
172
      else
 
173
        msb = mid;
 
174
    }
 
175
    return msb;
 
176
  }
 
177
 
 
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;
 
182
    // find the lsb
 
183
    for (long i = 0; i < 32; i++) {
 
184
      if (((x >> i) & MPI_QUAD_PONE) == MPI_QUAD_PONE) return (i+1);
 
185
    }
 
186
    return 0;
 
187
  }
 
188
 
 
189
  // this function convert a character according to a base
 
190
  static inline long ctol (const char c, const long base) {
 
191
    switch (base) {
 
192
    case 2:
 
193
      if (c == '0') return 0;
 
194
      if (c == '1') return 1;
 
195
      break;
 
196
    case 10:
 
197
      if ((c >= '0') && (c <= '9')) return (long) (c - '0');
 
198
      break;
 
199
    case 16:
 
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;
 
203
      break;
 
204
    }
 
205
    throw Exception ("format-error", "cannot convert character in base");
 
206
  }
 
207
 
 
208
  // this function converts a string to a relatif object
 
209
  static Relatif strtor (const String& s) {
 
210
    // initialize base
 
211
    long base   = 10;
 
212
    // initialise result
 
213
    Relatif basval = 1;
 
214
    Relatif result = 0;  
 
215
    
 
216
    // check for size first
 
217
    long len = s.length ();
 
218
    if (len == 0) return result;
 
219
    // process one character
 
220
    if (len == 1) {
 
221
      result = ctol (s[0], 10);
 
222
      return result;
 
223
    }
 
224
 
 
225
    // here we have at least two characters - it can be the sign, the format
 
226
    // or a normal number
 
227
    bool sign  = false;
 
228
    long index = 0;
 
229
    // check for the sign
 
230
    if (s[0] == '-') {
 
231
      index++;
 
232
      sign = true;
 
233
      goto format;
 
234
    }
 
235
    if (s[0] == '+') {
 
236
      index++;
 
237
      sign = false;
 
238
      goto format;
 
239
    }
 
240
    
 
241
    // check for the format
 
242
  format:
 
243
    if (s[index] != '0') goto number;
 
244
    index++;
 
245
    if (index >= len) return result;
 
246
    if ((s[index] == 'x') || (s[index] == 'X')) {
 
247
      index++;
 
248
      if (index >= len)
 
249
        throw Exception ("format-error", "cannot convert to relatif", s);
 
250
      base = 16;
 
251
      goto number;
 
252
    }
 
253
    if ((s[index] == 'b') || (s[index] == 'B')) {
 
254
      index++;
 
255
      if (index >= len)
 
256
        throw Exception ("format-error", "cannot convert to relatif", s);
 
257
      base = 2;
 
258
      goto number;
 
259
    }
 
260
    
 
261
    // compute the number value
 
262
  number:
 
263
    // check for the last index
 
264
    long max = len - 1;
 
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;
 
270
    };
 
271
    return (sign) ? -result : result;
 
272
  }
 
273
 
 
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)
 
277
  struct s_mpi {
 
278
    // the mpi size
 
279
    long d_size;
 
280
    // the clamp flag
 
281
    bool d_cflg;
 
282
    // the mpi array
 
283
    t_quad* p_data;
 
284
 
 
285
    // the default mpi
 
286
    s_mpi (void) {
 
287
      d_size = 1;
 
288
      d_cflg = true;
 
289
      p_data = new t_quad (0);
 
290
    }
 
291
 
 
292
    // create a mpi by exponent and value
 
293
    s_mpi (const long size, const t_quad x) {
 
294
      if (x == nilq) {
 
295
        d_size = 1;
 
296
        p_data = new t_quad (nilq);
 
297
      } else {
 
298
        d_size = size;
 
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;
 
302
      }
 
303
      // mark the clamp flag
 
304
      d_cflg = true;
 
305
    }
 
306
 
 
307
    // create a mpi by data and size
 
308
    s_mpi (const t_byte* rbuf, const long size) {
 
309
      // preset the buffer arreay
 
310
      d_size = 0;
 
311
      p_data = nilp;
 
312
      d_cflg = false;
 
313
      // set as an unsigned buffer
 
314
      setubuf (rbuf, size);
 
315
    }
 
316
 
 
317
    // create a mpi by data and size
 
318
    s_mpi (t_quad* data, const long size) {
 
319
      d_size = size;
 
320
      d_cflg = false;
 
321
      p_data = data;
 
322
    }
 
323
 
 
324
    // create a mpi by value
 
325
    s_mpi (const t_octa x) {
 
326
      // find the size
 
327
      if (x > MAX_OCTA_UVAL) {
 
328
        d_size = 2;
 
329
        p_data = new t_quad[2];
 
330
        p_data[0] = x;
 
331
        p_data[1] = x >> 32;
 
332
      } else {
 
333
        d_size = 1;
 
334
        p_data = new t_quad[1];
 
335
        p_data[0] = x;
 
336
      }
 
337
      d_cflg = true;
 
338
    }
 
339
 
 
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];
 
346
    }
 
347
 
 
348
    // destroy this mpi
 
349
    ~s_mpi (void) {
 
350
      delete [] p_data;
 
351
    };
 
352
 
 
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;
 
357
      // cleanup and copy
 
358
      delete [] p_data;
 
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];
 
363
      return *this;
 
364
    }
 
365
 
 
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];
 
372
      // copy the array
 
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;
 
375
      // fix old value
 
376
      delete [] p_data;
 
377
      d_size = size;
 
378
      p_data = data;
 
379
      d_cflg = false;
 
380
    }
 
381
 
 
382
    // serialize the mpi data
 
383
    void wrstream (OutputStream& os) {
 
384
      Integer size (d_size);
 
385
      size.wrstream (os);
 
386
      // serialize the array
 
387
      for (long i = 0; i < d_size; i++) {
 
388
        t_byte bval[4];
 
389
        c_qhton (p_data[i], bval);
 
390
        os.write ((const char*) bval, 4);
 
391
      }
 
392
    }
 
393
 
 
394
    // get the mpi size quad size
 
395
    long vsize (void) const {
 
396
      // check for clamped
 
397
      if (d_cflg == true) return d_size;
 
398
      // initialize the size and check
 
399
      long size = d_size;
 
400
      for (long i = d_size - 1; i > 0; i--) {
 
401
        if (p_data[i] != nilq) break;
 
402
        size--;
 
403
      }
 
404
      return size;
 
405
    }
 
406
 
 
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]);
 
413
      // add the quad size
 
414
      result += (size-1) * 4;
 
415
      // here it is
 
416
      return result;
 
417
    }
 
418
 
 
419
    // clamp this mpi by fixing the size and return true if null
 
420
    bool clamp (void) {
 
421
      // fix the size if not already clamped
 
422
      if (d_cflg == false) {
 
423
        d_size = vsize ();
 
424
        d_cflg = true;
 
425
      }
 
426
      // check for null
 
427
      if ((d_size == 1) && (p_data[0] == nilq)) return true;
 
428
      return false;
 
429
    }
 
430
 
 
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;
 
436
      // check for index
 
437
      if (qidx >= d_size) {
 
438
        throw Exception ("mpi-error", "invalid quad index in byte access");
 
439
      }
 
440
      // get quad value
 
441
      t_quad qval = p_data[qidx];
 
442
      // extract byte value
 
443
      return getqb (qval, bidx);      
 
444
    }
 
445
 
 
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;
 
451
      // check for index
 
452
      if (qidx >= d_size) {
 
453
        throw Exception ("mpi-error", "invalid quad index in byte access");
 
454
      }
 
455
      // get quad value
 
456
      t_quad qval = makqb (x, bidx);
 
457
      // set the quad value
 
458
      p_data[qidx] |= qval;
 
459
    }
 
460
 
 
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
 
466
      if (size <= cbsz) {
 
467
        for (long i = 0, j = cbsz-1; i < size; i++, j--) rbuf[i] = getbyte (j);
 
468
        return size;
 
469
      }
 
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;
 
473
      return cbsz;
 
474
    }
 
475
 
 
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
 
481
      t_byte sbuf[cbsz];
 
482
      t_word cw = 0x0001U;
 
483
      for (long i = 0; i < cbsz; i++) {
 
484
        if (sgn == true) {
 
485
          t_word bo = ((t_word) ~getbyte (i)) & 0x00FFU;
 
486
          t_word ro = bo + cw;
 
487
          sbuf[i] = (t_byte) ro;
 
488
               cw = (ro >> 8) & 0x0001U;
 
489
        } else {
 
490
          sbuf[i] = getbyte (i);
 
491
        }
 
492
      }
 
493
      // sign extend and clamp if needed
 
494
      if (sgn == true) {
 
495
        // sign extend the last byte
 
496
        sbuf[cbsz-1] = sext (sbuf[cbsz-1]);
 
497
        // clamp the signed buffer
 
498
        long csiz = cbsz;
 
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;
 
502
          csiz--;
 
503
        }
 
504
        // adjust buffer size
 
505
        cbsz = csiz;
 
506
      }
 
507
      // fill with size range
 
508
      if (size <= cbsz) {
 
509
        for (long i = 0, j = cbsz-1; i < size; i++, j--) rbuf[i] = sbuf[j];
 
510
        return size;
 
511
      }
 
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;
 
515
      return cbsz;
 
516
    }
 
517
 
 
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
 
523
      if (size <= cbsz) {
 
524
        for (long i = 0, j = size-1; i < size; i++, j--) rbuf[i] = getbyte (j);
 
525
        return size;
 
526
      } 
 
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);
 
530
      return cbsz;
 
531
    }
 
532
 
 
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);
 
541
      }
 
542
      return result;
 
543
    }
 
544
 
 
545
    // convert this mpi to an octa
 
546
    t_octa toocta (void) const {
 
547
      // check for size
 
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);
 
552
      // here it is
 
553
      return data;
 
554
    }
 
555
 
 
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;
 
561
      }
 
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;
 
566
      }
 
567
      return true;
 
568
    }
 
569
 
 
570
    // return true if this mpi is odd
 
571
    bool isodd (void) const {
 
572
      return (p_data[0] & MPI_QUAD_PONE) == MPI_QUAD_PONE;
 
573
    }
 
574
    
 
575
    // return true if this mpi is odd
 
576
    bool iseven (void) const {
 
577
      return (p_data[0] & MPI_QUAD_PONE) == 0UL;
 
578
    }
 
579
 
 
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;
 
585
      // find the quad msb
 
586
      long mmsb = quadmsb (p_data[size-1]);
 
587
      // here is the msb
 
588
      return ((size - 1) << BIT_QUAD_SHIX) + mmsb;
 
589
    }
 
590
 
 
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;
 
596
      // find the quad lsb
 
597
      long qlsb = 0;
 
598
      for (long i = 0; i < size; i++) {
 
599
        if (p_data[i] != nilq) break;
 
600
        qlsb++;
 
601
      }
 
602
      long mlsb = quadlsb (p_data[qlsb]);
 
603
      // here is the lsb
 
604
      return (qlsb << BIT_QUAD_SHIX) + mlsb;
 
605
    }
 
606
 
 
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");
 
613
      }
 
614
      // get the quad and bit mark
 
615
      t_quad data = p_data[index];
 
616
      long   mark = bpos % 32;
 
617
      // read bit value
 
618
      t_quad qval = ((mark == 0) ? data : (data >> mark)) & MPI_QUAD_PONE;
 
619
      // compute result
 
620
      return (qval == MPI_QUAD_PONE);
 
621
    }
 
622
 
 
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");
 
629
      }
 
630
      // get the quad and bit mark
 
631
      t_quad data = p_data[index];
 
632
      long   mark = bpos % 32;
 
633
      // prepare the mask
 
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);
 
637
    }
 
638
 
 
639
    // set the mpi with an unsigned buffer
 
640
    void setubuf (const t_byte* ubuf, const long size) {
 
641
      // clear the old buffer
 
642
      delete [] p_data;
 
643
      // compute the number of quads
 
644
      d_size = size / 4;
 
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
 
653
      d_cflg = false;
 
654
    }
 
655
 
 
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
 
663
      if (sign == true) {
 
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;
 
672
        }
 
673
      }
 
674
      return sign;
 
675
    }
 
676
 
 
677
    // radix shift right by a certain amount
 
678
    void rsr (const long rsa) {
 
679
      // get the mpi size
 
680
      long size = vsize ();
 
681
      // loop and shift
 
682
      for (long i = 0; i < size; i++) {
 
683
        long  idx = i + rsa;
 
684
        p_data[i] = (idx < size) ? p_data[idx] : nilq;
 
685
      }
 
686
      // reset clamp flag
 
687
      d_cflg = false;
 
688
    }
 
689
  };
 
690
 
 
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);
 
701
    // fix upper bits
 
702
    long mbit = (((bits - 1) / 32) * 32) + 31;
 
703
    for (long i = bits; i <= mbit; i++) result->setbit (i, false);
 
704
    // clamp the result
 
705
    result->clamp ();
 
706
    // here is the result
 
707
    return result;
 
708
  }
 
709
 
 
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);
 
720
    // fix upper bits
 
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);
 
724
    // clamp the result
 
725
    result->clamp ();
 
726
    // here is the result
 
727
    return result;
 
728
  }
 
729
 
 
730
  // this function deserialize a stream into a mpi
 
731
  static s_mpi* mpi_rds (InputStream& is) {
 
732
    // deserialize the size
 
733
    Integer sval;
 
734
    sval.rdstream (is);
 
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++) {
 
739
      t_byte bval[4];
 
740
      for (long j = 0; j < 4; j++) bval[j] = is.read ();
 
741
      data[i] = c_qntoh (bval);
 
742
    }
 
743
    // build the mpi result
 
744
    return new s_mpi (data, size);
 
745
  }
 
746
 
 
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);
 
751
    // loop in the size
 
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;
 
756
    }
 
757
    // here the numbers are equal
 
758
    return true;
 
759
  }
 
760
 
 
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 ());
 
765
    // loop in the size
 
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;
 
770
    }
 
771
    // here the numbers are equal
 
772
    return true;
 
773
  }
 
774
  
 
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);
 
779
    // loop in the size
 
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;
 
785
    }
 
786
    // here the numbers are equal
 
787
    return false;
 
788
  }
 
789
 
 
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 ());
 
794
    // loop in the size
 
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;
 
800
    }
 
801
    // here the numbers are equal
 
802
    return false;
 
803
  }
 
804
 
 
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);
 
809
    // loop in the size
 
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;
 
815
    }
 
816
    // here the numbers are equal
 
817
    return true;
 
818
  }
 
819
 
 
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 ());
 
824
    // loop in the size
 
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;
 
830
    }
 
831
    // here the numbers are equal
 
832
    return true;
 
833
  }
 
834
 
 
835
  // shift left in place a mpi by a certain amount
 
836
  static void mpi_leq (s_mpi& x, const long asl) {
 
837
    // fix trivial case
 
838
    if (asl == 0) return;
 
839
    // compute the amount of quad and bit shift
 
840
    long qsl = asl >> BIT_QUAD_SHIX;
 
841
    long bsl = asl % 32;
 
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);
 
846
    // shift the data
 
847
    for (long i = max; i >= 0; i--) {
 
848
      // shift octa
 
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;
 
857
    }
 
858
    // clean remaining quad
 
859
    for (long i = 0; i < qsl; i++) x.p_data[i] = nilq;
 
860
    // reset clamp flag
 
861
    x.d_cflg = false;
 
862
  }
 
863
 
 
864
  // shift right in place a mpi by a certain amount
 
865
  static void mpi_req (s_mpi& x, const long asr) {
 
866
    // fix trivial case
 
867
    if (asr == 0) return;
 
868
    // compute the amount of quad and bit shift
 
869
    long qsr = asr >> BIT_QUAD_SHIX;
 
870
    long bsr = asr % 32;
 
871
    // shift the data
 
872
    for (long i = 0; i < x.d_size; i++) {
 
873
      long index = i + qsr;
 
874
      // shift octa
 
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);
 
879
      x.p_data[i] = uq;
 
880
      // process lower quad
 
881
      t_quad lq = (t_quad) ro;
 
882
      if (i > 0) x.p_data[i-1] |= lq;
 
883
    }
 
884
    // reset clamp flag
 
885
    x.d_cflg = false;
 
886
  }
 
887
 
 
888
  // shift left a mpi by a certain amount
 
889
  static s_mpi* mpi_shl (const s_mpi& x, const long asl) {
 
890
    // fix trivial case
 
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;
 
894
    long bsl = asl % 32;
 
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
 
899
    t_octa cq = nilq;
 
900
    // shift the data
 
901
    for (long i = 0; i < x.d_size; i++) {
 
902
      // compute shift
 
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;
 
907
      cq = ro >> 32;
 
908
    }
 
909
    // set the last quad
 
910
    data[size] = cq;
 
911
    // build result
 
912
    return new s_mpi (data, size+1);
 
913
  }
 
914
 
 
915
  // shift right a mpi by a certain amount
 
916
  static s_mpi* mpi_shr (const s_mpi& x, const long asr) {
 
917
    // fix trivial case
 
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;
 
921
    long bsl = asr % 32;
 
922
    t_quad* data = new t_quad[x.d_size]; rstdat (x.d_size, data);
 
923
    // initialize the borrow
 
924
    t_octa bq = nilq;
 
925
    // shift the data
 
926
    for (long i = x.d_size - 1; i >= 0; i--) {
 
927
      // compute shift
 
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;
 
932
      long j = i - qsl;
 
933
      if (j >= 0) data[j] = ro >> 32;
 
934
    }
 
935
    // build result
 
936
    return new s_mpi (data,x.d_size);
 
937
  }
 
938
 
 
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);
 
944
 
 
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];
 
951
    t_quad    cq = nilq;
 
952
    // loop and add
 
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);
 
959
    }
 
960
    // fix the carry
 
961
    data[size] = cq;
 
962
    // here is the result
 
963
    return new s_mpi (data, dsiz);
 
964
  }
 
965
 
 
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];
 
970
    t_quad    cq = nilq;
 
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);
 
978
    }
 
979
    // here is the result
 
980
    return new s_mpi (data, x.d_size);
 
981
  }
 
982
 
 
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];
 
989
    t_quad    cq = nilq;
 
990
    // loop and add
 
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);
 
997
    }
 
998
    // fix the carry
 
999
    data[size] = cq;
 
1000
    // here is the result
 
1001
    return new s_mpi (data,dsiz);
 
1002
  }
 
1003
 
 
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];
 
1010
    t_quad    cq = nilq;
 
1011
    // loop and add
 
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);
 
1018
    }
 
1019
    // fix the carry
 
1020
    data[size] = cq;
 
1021
    // here is the result
 
1022
    return new s_mpi (data,dsiz);
 
1023
  }
 
1024
 
 
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];
 
1029
    t_quad    cq = nilq;
 
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);
 
1037
    }
 
1038
    // here is the result
 
1039
    return new s_mpi (data, x.d_size);
 
1040
  }
 
1041
 
 
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
 
1045
    if (y.d_size > 2) {
 
1046
      throw Exception ("internal-error", "mpi argument size bigger than 2");
 
1047
    }
 
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
 
1054
    t_octa ro = x - yq;
 
1055
    data[0] = ro;
 
1056
    data[1] = ro >> 32;
 
1057
    // here is the result
 
1058
    return new s_mpi (data, 2);
 
1059
  }
 
1060
 
 
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];
 
1065
    t_quad    cq = nilq;
 
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);
 
1073
    }
 
1074
    // here is the result
 
1075
    return new s_mpi (data, x.d_size);
 
1076
  }
 
1077
 
 
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);
 
1083
    // reset carry
 
1084
    t_quad cq = nilq;
 
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
 
1091
      ro += xo * y + cq;
 
1092
      // adjust result
 
1093
      data[j] = (t_quad) ro;
 
1094
      // adjust carry
 
1095
      cq = (t_quad) (ro >> 32);
 
1096
    }
 
1097
    data[x.d_size] = cq;
 
1098
    // here is the result
 
1099
    return new s_mpi (data,size);
 
1100
  }
 
1101
 
 
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++) {
 
1109
      // reset carry
 
1110
      t_quad cq = nilq;
 
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
 
1118
        ro += xo * yo + cq;
 
1119
        // adjust result
 
1120
        data[i+j] = (t_quad) ro;
 
1121
        // adjust carry
 
1122
        cq = (t_quad) (ro >> 32);
 
1123
      }
 
1124
      data[i+x.d_size] = cq;
 
1125
    }
 
1126
    // here is the result
 
1127
    return new s_mpi (data, size);
 
1128
  }
 
1129
 
 
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++) {
 
1137
      // reset carry
 
1138
      t_quad cq = nilq;
 
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
 
1146
        ro += xo * yo + cq;
 
1147
        // adjust result
 
1148
        data[i+j] = (t_quad) ro;
 
1149
        // adjust carry
 
1150
        cq = (t_quad) (ro >> 32);
 
1151
      }
 
1152
      data[i+x.d_size] = cq;
 
1153
    }
 
1154
    // here is the result
 
1155
    return new s_mpi (data, size);
 
1156
  }
 
1157
 
 
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;
 
1167
    
 
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);
 
1171
    dx->clamp ();
 
1172
    dy->clamp ();
 
1173
 
 
1174
    // allocate the quotient
 
1175
    long delta = dx->d_size - dy->d_size;
 
1176
    if (delta < 0) {
 
1177
      delete dx;
 
1178
      delete dy;
 
1179
      throw Exception ("size-error", "invalid negative quotient size");
 
1180
    }
 
1181
    long qsize = delta + 1;    
 
1182
    t_quad* qdata = new t_quad[qsize]; rstdat (qsize, qdata);
 
1183
    
 
1184
    // step 2:
 
1185
    // py = y*b**n-t
 
1186
    s_mpi* py = mpi_shl (*dy, delta*32);
 
1187
    py->clamp ();
 
1188
    // while (dx >= py) {q[n-t] += 1; dx-= py}
 
1189
    while (mpi_geq (*dx, *py) == true) {
 
1190
      qdata[delta]++;
 
1191
      mpi_seq (*dx, *py);
 
1192
    }
 
1193
    dx->clamp ();
 
1194
    delete py;
 
1195
 
 
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;
 
1201
    // temporary tx
 
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);
 
1209
 
 
1210
    // step 3: main loop
 
1211
    for (long i = n; i >= dy->d_size; i--) {
 
1212
      // step 3.1:
 
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;
 
1216
      } else {
 
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;
 
1221
      }
 
1222
      // step 3.2:
 
1223
      // while(q[i-t-1]*ty) > (x[i]*b**2+x[i-1]*b+x[i-2])) (q[i-t-1]--)
 
1224
      qdata[i-t-1]++;
 
1225
      s_mpi* tq = nilp;
 
1226
      do {
 
1227
        // fix back quotient
 
1228
        qdata[i-t-1]--;
 
1229
        // q[i-t-1]*ty
 
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);
 
1237
      // step 3.3/3.4:
 
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) {
 
1244
        mpi_seq (*dx, *tq);
 
1245
      } else {
 
1246
        mpi_aeq (*dx, *tb);
 
1247
        mpi_seq (*dx, *tq);
 
1248
        qdata[i-t-1]--;
 
1249
      }
 
1250
      delete tb; tb = nilp;
 
1251
      delete tq; tq = nilp;
 
1252
    }
 
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);
 
1256
    // clean temporary
 
1257
    delete tx;
 
1258
    delete ty;
 
1259
    delete dx;
 
1260
    delete dy;
 
1261
    if (rflg == true) delete [] qdata;
 
1262
    // finally here it is
 
1263
    return result;
 
1264
  }
 
1265
 
 
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);
 
1272
    s_mpi  ts = x;
 
1273
    t_octa te = e;
 
1274
    // main loop
 
1275
    while (te != nilq) {
 
1276
      if ((te & MPI_OCTA_PONE) == MPI_OCTA_PONE) mpi_meq (*ta, ts);
 
1277
      te >>= 1;
 
1278
      if (te != nilq) mpi_meq (ts, ts);
 
1279
    }
 
1280
    return ta;
 
1281
  }
 
1282
 
 
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);
 
1289
    s_mpi  ts = x;
 
1290
    s_mpi  te = e;
 
1291
    // main loop
 
1292
    while (te.iszero () == false) {
 
1293
      if (te.isodd () == true) mpi_meq (*ta, ts);
 
1294
      mpi_req (te, 1);
 
1295
      if (te.iszero () == false) mpi_meq (ts, ts);
 
1296
    }
 
1297
    return ta;
 
1298
  }
 
1299
 
 
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);
 
1306
    s_mpi  ts = x;
 
1307
    t_octa te = e;
 
1308
    // main loop
 
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); 
 
1314
          ta->clamp ();
 
1315
        }
 
1316
      }
 
1317
      te >>= 1;
 
1318
      if (te != nilq) {
 
1319
        mpi_meq (ts, ts); ts.clamp ();
 
1320
        if (mpi_geq (ts, m) == true) {
 
1321
          mpi_deq (ts, m, true); 
 
1322
          ts.clamp ();
 
1323
        }
 
1324
      }
 
1325
    }
 
1326
    return ta;
 
1327
  }
 
1328
 
 
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);
 
1335
    s_mpi  ts = x;
 
1336
    s_mpi  te = e;
 
1337
    // main loop
 
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);
 
1343
          ta->clamp ();
 
1344
        }
 
1345
      }
 
1346
      mpi_req (te, 1);
 
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); 
 
1351
          ts.clamp ();
 
1352
        }
 
1353
      }
 
1354
    }
 
1355
    return ta;
 
1356
  }
 
1357
 
 
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);
 
1362
    // loop and add
 
1363
    t_quad cq = nilq;
 
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);
 
1370
    }
 
1371
    // fix the carry
 
1372
    if (cq != nilq) {
 
1373
      x.grow (x.d_size + 1);
 
1374
      x.p_data[x.d_size-1] = cq;
 
1375
    }
 
1376
    // reset clamp flag
 
1377
    x.d_cflg = false;
 
1378
  }
 
1379
 
 
1380
  // this function substracts in place two mpi assuming that x > y
 
1381
  static void mpi_seq (s_mpi& x, const s_mpi& y) {
 
1382
    // preset the carry
 
1383
    t_quad cq = nilq;
 
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);
 
1391
    }
 
1392
    // reset clamp flag
 
1393
    x.d_cflg = false;
 
1394
  }
 
1395
 
 
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);
 
1400
    // clean old data
 
1401
    delete [] x.p_data;
 
1402
    x.d_size = mpi->d_size;
 
1403
    x.p_data = mpi->p_data;
 
1404
    x.d_cflg = false;
 
1405
    // clean temporary mpi
 
1406
    mpi->p_data = nilp;
 
1407
    delete mpi;
 
1408
  }
 
1409
 
 
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);
 
1414
    // clean old data
 
1415
    delete [] x.p_data;
 
1416
    x.d_size = mpi->d_size;
 
1417
    x.p_data = mpi->p_data;
 
1418
    x.d_cflg = false;
 
1419
    // clean temporary mpi
 
1420
    mpi->p_data = nilp;
 
1421
    delete mpi;
 
1422
  }
 
1423
 
 
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];
 
1429
    // negate the data
 
1430
    for (long i = 0; i < size; i++) data[i] = ~x.p_data[i];
 
1431
    // build the result
 
1432
    return new s_mpi (data, size);
 
1433
  }
 
1434
 
 
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];
 
1440
    // and the data
 
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;
 
1444
      data[i] = xq & yq;
 
1445
    }
 
1446
    // build the result
 
1447
    return new s_mpi (data, size);
 
1448
  }
 
1449
 
 
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];
 
1455
    // and the data
 
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;
 
1459
      data[i] = xq | yq;
 
1460
    }
 
1461
    // build the result
 
1462
    return new s_mpi (data, size);
 
1463
  }
 
1464
 
 
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];
 
1470
    // and the data
 
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;
 
1474
      data[i] = xq ^ yq;
 
1475
    }
 
1476
    // build the result
 
1477
    return new s_mpi (data, size);
 
1478
  }
 
1479
 
 
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
 
1483
    s_mpi a = x;
 
1484
    s_mpi b = y;
 
1485
    s_mpi g = 1ULL;
 
1486
    // simplify by two and update even coefficient
 
1487
    while ((a.iseven () == true) && (b.iseven () == true)) {
 
1488
      mpi_req (a, 1);
 
1489
      mpi_req (b, 1);
 
1490
      mpi_leq (g, 1);
 
1491
    }
 
1492
    // clamp before looping
 
1493
    a.clamp ();
 
1494
    b.clamp ();
 
1495
    // main loop
 
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) {
 
1500
        s_mpi t = a; 
 
1501
        mpi_seq (t, b);
 
1502
        mpi_req (t, 1);
 
1503
        a = t;
 
1504
      } else {
 
1505
        s_mpi t = b; 
 
1506
        mpi_seq (t, a);
 
1507
        mpi_req (t, 1);
 
1508
        b = t;
 
1509
      }
 
1510
    }
 
1511
    // here it is
 
1512
    return mpi_mul (b, g);
 
1513
  }
 
1514
 
 
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) {
 
1519
    // get first digit
 
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)
 
1524
    x *=  2 - (b * x);
 
1525
    // x*a==1 (mod 2**16)
 
1526
    x *=  2 - (b * x);
 
1527
    // x*a==1 (mod 2**32)
 
1528
    x *=  2 - (b * x);
 
1529
    // rho = -1/m (mod b)
 
1530
    return (t_quad) (MPI_OCTA_HONE - x);
 
1531
  }
 
1532
 
 
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,
 
1537
                         const t_quad rho) {
 
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;
 
1548
      // z += xi.y
 
1549
      s_mpi* tx = mpi_mul (y, xi);
 
1550
      mpi_aeq (*z, *tx);
 
1551
      delete tx;
 
1552
      // z += ui.m
 
1553
      s_mpi* tu = mpi_mul (m, ui);
 
1554
      mpi_aeq (*z, *tu);
 
1555
      delete tu;
 
1556
      // divide one radix and clamp
 
1557
      z->rsr (1); z->clamp ();
 
1558
    }
 
1559
    if (mpi_geq (*z, m) == true) mpi_seq (*z, m);
 
1560
    return z;
 
1561
  }
 
1562
 
 
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 ();
 
1574
    delete y;
 
1575
    return z;
 
1576
  }
 
1577
 
 
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);
 
1583
  }
 
1584
 
 
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, 
 
1589
                         const t_quad rho) {
 
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--) {
 
1594
      // compute tr * tr
 
1595
      s_mpi* tz = mpi_mmm (*tr, *tr, m, rho);
 
1596
      *tr = *tz; delete tz;
 
1597
      tr->clamp ();
 
1598
      // check for bit set
 
1599
      if (e.getbit (i) == true) {
 
1600
        tz = mpi_mmm (*tr, x, m, rho);
 
1601
        *tr = *tz; delete tz;
 
1602
        tr->clamp ();
 
1603
      }
 
1604
    }
 
1605
    return tr;
 
1606
  }
 
1607
 
 
1608
  // this procedure computes a montgomery modular exponentiation of a mpi
 
1609
  // but unlike the other montgomery procedures, this one does the required 
 
1610
  // verifications
 
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");
 
1616
    }
 
1617
    // get the modulus rho factor
 
1618
    t_quad rho = mpi_rho (m);
 
1619
    // initialize and normalize x
 
1620
    s_mpi tx = 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
 
1629
    delete mx;
 
1630
    delete mz;
 
1631
    return z;
 
1632
  }
 
1633
 
 
1634
  // -------------------------------------------------------------------------
 
1635
  // - public section                                                        -
 
1636
  // -------------------------------------------------------------------------
 
1637
 
 
1638
  // compute the gcd of two relatifs
 
1639
 
 
1640
  Relatif Relatif::gcd (const Relatif& x, const Relatif& y) {
 
1641
    x.rdlock ();
 
1642
    y.rdlock ();
 
1643
    try {
 
1644
      // compute the gcd
 
1645
      s_mpi* mpi = mpi_gcd (*x.p_mpi, *y.p_mpi);
 
1646
      mpi->clamp ();
 
1647
      // build the result
 
1648
      Relatif result; delete result.p_mpi; result.p_mpi = nilp;
 
1649
      result.p_mpi = mpi;
 
1650
      // unlock and return;
 
1651
      x.unlock ();
 
1652
      y.unlock ();
 
1653
      return result;
 
1654
    } catch (...) {
 
1655
      x.unlock ();
 
1656
      y.unlock ();
 
1657
      throw;
 
1658
    }
 
1659
  }
 
1660
 
 
1661
  // compute the lcm of two relatifs
 
1662
 
 
1663
  Relatif Relatif::lcm (const Relatif& x, const Relatif& y) {
 
1664
    x.rdlock ();
 
1665
    y.rdlock ();
 
1666
    try {
 
1667
      // compute result
 
1668
      Relatif result = (x * y) / Relatif::gcd (x, y);
 
1669
      result.d_sgn = false;
 
1670
      result.p_mpi->clamp ();
 
1671
      // unlock and return;
 
1672
      x.unlock ();
 
1673
      y.unlock ();
 
1674
      return result;
 
1675
    } catch (...) {
 
1676
      x.unlock ();
 
1677
      y.unlock ();
 
1678
      throw;
 
1679
    }
 
1680
  }
 
1681
 
 
1682
  // compute the mmi of a relatif
 
1683
 
 
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
 
1688
    Relatif u = x;
 
1689
    Relatif v = m;
 
1690
    Relatif a = 1;
 
1691
    Relatif b = 0;
 
1692
    Relatif c = 0;
 
1693
    Relatif d = 1;
 
1694
    // main loop
 
1695
    while (u.iszero () == false) {
 
1696
      // process u division
 
1697
      while (u.iseven () == true) {
 
1698
        u >>= 1;
 
1699
        if ((a.iseven () == true) && (b.iseven () == true)) {
 
1700
          a >>= 1;
 
1701
          b >>= 1;
 
1702
        } else {
 
1703
          a = (a + m) >> 1;
 
1704
          b = (b - x) >> 1;
 
1705
        }
 
1706
      }
 
1707
      // process v division
 
1708
      while (v.iseven () == true) {
 
1709
        v >>= 1;
 
1710
        if ((c.iseven () == true) && (d.iseven () == true)) {
 
1711
          c >>= 1;
 
1712
          d >>= 1;
 
1713
        } else {
 
1714
          c = (c + m) >> 1;
 
1715
          d = (d - x) >> 1;
 
1716
        }
 
1717
      }
 
1718
      // adjust results
 
1719
      if (u >= v) {
 
1720
        u = u - v;
 
1721
        a = a - c;
 
1722
        b = b - d;
 
1723
      } else {
 
1724
        v = v - u;
 
1725
        c = c - a;
 
1726
        d = d - b;
 
1727
      }
 
1728
    }
 
1729
    if (u.iszero () == true) {
 
1730
      a = c;
 
1731
      b = d;
 
1732
    }
 
1733
    // check for gcd
 
1734
    if (v != 1) return 0;
 
1735
    // process negative
 
1736
    if (a < 0) return m + (a % m);
 
1737
    return a % m;
 
1738
  }
 
1739
 
 
1740
  // compute an optimized modular exponentiation
 
1741
 
 
1742
  Relatif Relatif::mme (const Relatif& x, const Relatif& e, const Relatif& m) {
 
1743
    // check for negative exponent
 
1744
    e.rdlock ();
 
1745
    if (e.d_sgn == true) {
 
1746
      e.unlock ();
 
1747
      throw Exception ("number-error", "invalid negative exponent in pow");
 
1748
    }
 
1749
    // check for negative modulo
 
1750
    m.rdlock ();
 
1751
    if (m.d_sgn == true) {
 
1752
      e.unlock ();
 
1753
      m.unlock ();
 
1754
      throw Exception ("number-error", "invalid negative modulo in pow");
 
1755
    }
 
1756
    // process trivial case
 
1757
    if (e == 1) {
 
1758
      e.unlock ();
 
1759
      m.unlock ();
 
1760
      return x % m;
 
1761
    }
 
1762
    // lock argument and prepare result
 
1763
    x.rdlock ();
 
1764
    Relatif result;
 
1765
    try {
 
1766
      // use the montgomery exponentiation if m is odd
 
1767
      if (m.isodd () == true) {
 
1768
        // compute result
 
1769
        delete result.p_mpi; result.p_mpi = nilp;
 
1770
        result.p_mpi = mpi_mme (*x.p_mpi, *e.p_mpi, *m.p_mpi);
 
1771
        // compute sign
 
1772
        result.d_sgn = (e.iseven () == true) ? false : x.d_sgn;
 
1773
        // clamp the result
 
1774
        if (result.p_mpi->clamp () == true) result.d_sgn = false;
 
1775
      } else {
 
1776
        result = x.pow (e, m);
 
1777
      }
 
1778
      x.unlock ();
 
1779
      e.unlock ();
 
1780
      m.unlock ();
 
1781
      return result;
 
1782
    } catch (...) {
 
1783
      x.unlock ();
 
1784
      e.unlock ();
 
1785
      m.unlock ();
 
1786
      throw;
 
1787
    }
 
1788
  }
 
1789
 
 
1790
  // generate a random n bits relatif number
 
1791
 
 
1792
  Relatif Relatif::random (const long bits) {
 
1793
    // check for valid size
 
1794
    if (bits < 0) {
 
1795
      throw Exception ("size-error", "invalid random number size");
 
1796
    }
 
1797
    // build mpi result
 
1798
    Relatif result; delete result.p_mpi; result.p_mpi = nilp;
 
1799
    result.p_mpi = mpi_rnd (bits);
 
1800
    // here is the number
 
1801
    return result;
 
1802
  }
 
1803
 
 
1804
  // generate a random n bits odd or even relatif number
 
1805
 
 
1806
  Relatif Relatif::random (const long bits, const bool oddf) {
 
1807
    // generate a random number
 
1808
    Relatif result = Relatif::random (bits);
 
1809
    // fix parity
 
1810
    if (result.iszero () == false) result.setbit (0, oddf);
 
1811
    // here is the number
 
1812
    return result;
 
1813
  }
 
1814
 
 
1815
  // generate a random number upto a maximum
 
1816
 
 
1817
  Relatif Relatif::random (const Relatif& mrn) {
 
1818
    // check for sign
 
1819
    mrn.rdlock ();
 
1820
    try {
 
1821
      if (mrn.d_sgn == true) {
 
1822
        throw Exception ("sign-error", "invalid maximum negative number");
 
1823
      }
 
1824
      // get the max number of bits
 
1825
      long bits = mrn.p_mpi->getmsb ();
 
1826
      // build mpi result
 
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 ();
 
1832
      }
 
1833
      mrn.unlock ();
 
1834
      // here is the number
 
1835
      return result;
 
1836
    } catch (...) {
 
1837
      mrn.unlock ();
 
1838
      throw;
 
1839
    }
 
1840
  }
 
1841
  
 
1842
  // change the sign of a relatif
 
1843
 
 
1844
  Relatif operator - (const Relatif& x) {
 
1845
    x.rdlock ();
 
1846
    try {
 
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);
 
1852
      // clamp the result
 
1853
      if (result.p_mpi->clamp () == true) result.d_sgn = false;
 
1854
      // unlock and return
 
1855
      x.unlock ();
 
1856
      return result;
 
1857
    } catch (...) {
 
1858
      x.unlock ();
 
1859
      throw;
 
1860
    }
 
1861
  }
 
1862
 
 
1863
  // add a relatif with an integer
 
1864
 
 
1865
  Relatif operator + (const Relatif& x, const t_long y) {
 
1866
    x.rdlock ();
 
1867
    try {
 
1868
      // create an empty result
 
1869
      Relatif result; delete result.p_mpi; result.p_mpi = nilp;
 
1870
      // prepare y data
 
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;
 
1879
      } else {
 
1880
        bool xflg = mpi_geq (*x.p_mpi, yval);
 
1881
        if (xflg == true) {
 
1882
          result.p_mpi = mpi_sub (*x.p_mpi, yval);
 
1883
          result.d_sgn = x.d_sgn;
 
1884
        } else {
 
1885
          result.p_mpi = mpi_sub (yval, *x.p_mpi);
 
1886
          result.d_sgn = ysgn;
 
1887
        }
 
1888
      }
 
1889
      // clamp the result
 
1890
      if (result.p_mpi->clamp () == true) result.d_sgn = false;
 
1891
      // unlock and return
 
1892
      x.unlock ();
 
1893
      return result;
 
1894
    } catch (...) {
 
1895
      x.unlock ();
 
1896
      throw;
 
1897
    }
 
1898
  }
 
1899
 
 
1900
  // add two relatifs
 
1901
 
 
1902
  Relatif operator + (const Relatif& x, const Relatif& y) {
 
1903
    x.rdlock ();
 
1904
    y.rdlock ();
 
1905
    try {
 
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;
 
1914
      } else {
 
1915
        bool xflg = mpi_geq (*x.p_mpi, *y.p_mpi);
 
1916
        if (xflg == true) {
 
1917
          result.p_mpi = mpi_sub (*x.p_mpi, *y.p_mpi);
 
1918
          result.d_sgn = x.d_sgn;
 
1919
        } else {
 
1920
          result.p_mpi = mpi_sub (*y.p_mpi, *x.p_mpi);
 
1921
          result.d_sgn = y.d_sgn;
 
1922
        }
 
1923
      }
 
1924
      // clamp the result
 
1925
      if (result.p_mpi->clamp () == true) result.d_sgn = false;
 
1926
      // unlock and return
 
1927
      y.unlock ();
 
1928
      x.unlock ();
 
1929
      return result;
 
1930
    } catch (...) {
 
1931
      y.unlock ();
 
1932
      x.unlock ();
 
1933
      throw;
 
1934
    }
 
1935
  }
 
1936
 
 
1937
  // substract a relatif with an integer
 
1938
 
 
1939
  Relatif operator - (const Relatif& x, const t_long y) {
 
1940
    x.rdlock ();
 
1941
    try {
 
1942
      // create an empty result
 
1943
      Relatif result; delete result.p_mpi; result.p_mpi = nilp;
 
1944
      // prepare y data
 
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
 
1950
      if (sflg == true) {
 
1951
        result.p_mpi = mpi_add (*x.p_mpi, yval);
 
1952
        result.d_sgn = x.d_sgn;
 
1953
      } else {
 
1954
        bool xflg = mpi_geq (*x.p_mpi, yval);
 
1955
        if (xflg == true) {
 
1956
          result.p_mpi = mpi_sub (*x.p_mpi, yval);
 
1957
          result.d_sgn = x.d_sgn;
 
1958
        } else {
 
1959
          result.p_mpi = mpi_sub (yval, *x.p_mpi);
 
1960
          result.d_sgn = !x.d_sgn;
 
1961
        }
 
1962
      }
 
1963
      // clamp the result
 
1964
      if (result.p_mpi->clamp () == true) result.d_sgn = false;
 
1965
      // unlock and return
 
1966
      x.unlock ();
 
1967
      return result;
 
1968
    } catch (...) {
 
1969
      x.unlock ();
 
1970
      throw;
 
1971
    }
 
1972
  }
 
1973
 
 
1974
  // substract two relatifs
 
1975
 
 
1976
  Relatif operator - (const Relatif& x, const Relatif& y) {
 
1977
    x.rdlock ();
 
1978
    y.rdlock ();
 
1979
    try {
 
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
 
1985
      if (sflg == true) {
 
1986
        result.p_mpi = mpi_add (*x.p_mpi, *y.p_mpi);
 
1987
        result.d_sgn = x.d_sgn;
 
1988
      } else {
 
1989
        bool xflg = mpi_geq (*x.p_mpi, *y.p_mpi);
 
1990
        if (xflg == true) {
 
1991
          result.p_mpi = mpi_sub (*x.p_mpi, *y.p_mpi);
 
1992
          result.d_sgn = x.d_sgn;
 
1993
        } else {
 
1994
          result.p_mpi = mpi_sub (*y.p_mpi, *x.p_mpi);
 
1995
          result.d_sgn = !x.d_sgn;
 
1996
        }
 
1997
      }
 
1998
      // clamp the result
 
1999
      if (result.p_mpi->clamp () == true) result.d_sgn = false;
 
2000
      // unlock and return
 
2001
      y.unlock ();
 
2002
      x.unlock ();
 
2003
      return result;
 
2004
    } catch (...) {
 
2005
      y.unlock ();
 
2006
      x.unlock ();
 
2007
      throw;
 
2008
    }
 
2009
  }
 
2010
 
 
2011
  // multiply a relatif with an integer
 
2012
 
 
2013
  Relatif operator * (const Relatif& x, const t_long y) {
 
2014
    x.rdlock ();
 
2015
    try {
 
2016
      // create an empty result
 
2017
      Relatif result; delete result.p_mpi; result.p_mpi = nilp;
 
2018
      // prepare y data
 
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);
 
2024
      // clamp the result
 
2025
      if (result.p_mpi->clamp () == true) result.d_sgn = false;
 
2026
      // unlock and return
 
2027
      x.unlock ();
 
2028
      return result;
 
2029
    } catch (...) {
 
2030
      x.unlock ();
 
2031
      throw;
 
2032
    }
 
2033
  }
 
2034
 
 
2035
  // multiply two relatifs
 
2036
 
 
2037
  Relatif operator * (const Relatif& x, const Relatif& y) {
 
2038
    x.rdlock ();
 
2039
    y.rdlock ();
 
2040
    try {
 
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);
 
2046
      // clamp the result
 
2047
      if (result.p_mpi->clamp () == true) result.d_sgn = false;
 
2048
      // unlock and return
 
2049
      y.unlock ();
 
2050
      x.unlock ();
 
2051
      return result;
 
2052
    } catch (...) {
 
2053
      y.unlock ();
 
2054
      x.unlock ();
 
2055
      throw;
 
2056
    }
 
2057
  }
 
2058
 
 
2059
  // divide a relatif with an integer
 
2060
 
 
2061
  Relatif operator / (const Relatif& x, const t_long y) {
 
2062
    x.rdlock ();
 
2063
    try {
 
2064
      // check y value
 
2065
      if (y == 0) {
 
2066
        throw Exception ("relatif-error", "division by zero");
 
2067
      }
 
2068
      // prepare y data
 
2069
      bool   ysgn = (y < 0);
 
2070
      t_octa yval = ysgn ? -y : y;
 
2071
      // create an empty result
 
2072
      Relatif result; 
 
2073
      // check for trivial case
 
2074
      if (mpi_geq (*x.p_mpi, yval) == false) {
 
2075
        x.unlock ();
 
2076
        return result;
 
2077
      }
 
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);
 
2083
      // clamp the result
 
2084
      if (result.p_mpi->clamp () == true) result.d_sgn = false;
 
2085
      // unlock and return
 
2086
      x.unlock ();
 
2087
      return result;
 
2088
    } catch (...) {
 
2089
      x.unlock ();
 
2090
      throw;
 
2091
    }
 
2092
  }
 
2093
  
 
2094
  // divide two relatifs
 
2095
 
 
2096
  Relatif operator / (const Relatif& x, const Relatif& y) {
 
2097
    x.rdlock ();
 
2098
    y.rdlock ();
 
2099
    try {
 
2100
      // check y value
 
2101
      if (y == 0) {
 
2102
        throw Exception ("relatif-error", "division by zero");
 
2103
      }
 
2104
      // create an empty result
 
2105
      Relatif result;
 
2106
      // check trivial case
 
2107
      if (mpi_geq (*x.p_mpi, *y.p_mpi) == false) {
 
2108
        y.unlock ();
 
2109
        x.unlock ();
 
2110
        return result;
 
2111
      }
 
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);
 
2117
      // clamp the result
 
2118
      if (result.p_mpi->clamp () == true) result.d_sgn = false;
 
2119
      // unlock and return
 
2120
      y.unlock ();
 
2121
      x.unlock ();
 
2122
      return result;
 
2123
    } catch (...) {
 
2124
      y.unlock ();
 
2125
      x.unlock ();
 
2126
      throw;
 
2127
    }
 
2128
  }
 
2129
 
 
2130
  // compute the reminder of a relatif with an integer
 
2131
 
 
2132
  Relatif operator % (const Relatif& x, const t_long y) {
 
2133
    x.rdlock ();
 
2134
    try {
 
2135
      // check y value
 
2136
      if (y == 0) {
 
2137
        throw Exception ("relatif-error", "division by zero");
 
2138
      }
 
2139
      // prepare y data
 
2140
      bool   ysgn = (y < 0);
 
2141
      t_octa yval = ysgn ? -y : y;
 
2142
      // create an empty result
 
2143
      Relatif result; 
 
2144
      // check trivial case
 
2145
      if (mpi_geq (*x.p_mpi, yval) == false) {
 
2146
        result = x;
 
2147
        x.unlock ();
 
2148
        return result;
 
2149
      }
 
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);
 
2155
      // clamp the result
 
2156
      if (result.p_mpi->clamp () == true) result.d_sgn = false;
 
2157
      // unlock and return
 
2158
      x.unlock ();
 
2159
      return result;
 
2160
    } catch (...) {
 
2161
      x.unlock ();
 
2162
      throw;
 
2163
    }
 
2164
  }
 
2165
 
 
2166
  // compute the reminder of two relatifs
 
2167
 
 
2168
  Relatif operator % (const Relatif& x, const Relatif& y) {
 
2169
    x.rdlock ();
 
2170
    y.rdlock ();
 
2171
    try {
 
2172
      // check y value
 
2173
      if (y == 0) {
 
2174
        throw Exception ("relatif-error", "division by zero");
 
2175
      }
 
2176
      // create an empty result
 
2177
      Relatif result;
 
2178
      // check trivial case
 
2179
      if (mpi_geq (*x.p_mpi, *y.p_mpi) == false) {
 
2180
        result = x;
 
2181
        y.unlock ();
 
2182
        x.unlock ();
 
2183
        return result;
 
2184
      }
 
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);
 
2190
      // clamp the result
 
2191
      if (result.p_mpi->clamp () == true) result.d_sgn = false;
 
2192
      // unlock and return
 
2193
      y.unlock ();
 
2194
      x.unlock ();
 
2195
      return result;
 
2196
    } catch (...) {
 
2197
      y.unlock ();
 
2198
      x.unlock ();
 
2199
      throw;
 
2200
    }
 
2201
  }
 
2202
 
 
2203
  // bitwise negate a relatif
 
2204
 
 
2205
  Relatif operator ~ (const Relatif& x) {
 
2206
    x.rdlock ();
 
2207
    try {
 
2208
      // create an empty result
 
2209
      Relatif result; delete result.p_mpi; result.p_mpi = nilp;
 
2210
      // bind the sign
 
2211
      result.d_sgn = x.d_sgn;
 
2212
      // bind the mpi
 
2213
      result.p_mpi = mpi_neg (*x.p_mpi);
 
2214
      // clamp the result
 
2215
      if (result.p_mpi->clamp () == true) result.d_sgn = false;
 
2216
      // unlock and return
 
2217
      x.unlock ();
 
2218
      return result;
 
2219
    } catch (...) {
 
2220
      x.unlock ();
 
2221
      throw;
 
2222
    }
 
2223
  }
 
2224
 
 
2225
  // bitwise and two relatifs
 
2226
 
 
2227
  Relatif operator & (const Relatif& x, const Relatif& y) {
 
2228
    x.rdlock ();
 
2229
    y.rdlock ();
 
2230
    try {
 
2231
      // create an empty result
 
2232
      Relatif result; delete result.p_mpi; result.p_mpi = nilp;
 
2233
      // bind the sign
 
2234
      result.d_sgn = x.d_sgn && y.d_sgn;
 
2235
      // bind the mpi
 
2236
      result.p_mpi = mpi_and (*x.p_mpi, *y.p_mpi);
 
2237
      // clamp the result
 
2238
      if (result.p_mpi->clamp () == true) result.d_sgn = false;
 
2239
      // unlock and return
 
2240
      y.unlock ();
 
2241
      x.unlock ();
 
2242
      return result;
 
2243
    } catch (...) {
 
2244
      y.unlock ();
 
2245
      x.unlock ();
 
2246
      throw;
 
2247
    }
 
2248
  }
 
2249
 
 
2250
  // bitwise or two relatifs
 
2251
 
 
2252
  Relatif operator | (const Relatif& x, const Relatif& y) {
 
2253
    x.rdlock ();
 
2254
    y.rdlock ();
 
2255
    try {
 
2256
      // create an empty result
 
2257
      Relatif result; delete result.p_mpi; result.p_mpi = nilp;
 
2258
      // bind the sign
 
2259
      result.d_sgn = x.d_sgn || y.d_sgn;
 
2260
      // bind the mpi
 
2261
      result.p_mpi = mpi_bor (*x.p_mpi, *y.p_mpi);
 
2262
      // clamp the result
 
2263
      if (result.p_mpi->clamp () == true) result.d_sgn = false;
 
2264
      // unlock and return
 
2265
      y.unlock ();
 
2266
      x.unlock ();
 
2267
      return result;
 
2268
    } catch (...) {
 
2269
      y.unlock ();
 
2270
      x.unlock ();
 
2271
      throw;
 
2272
    }
 
2273
  }
 
2274
 
 
2275
  // bitwise xor two relatifs
 
2276
 
 
2277
  Relatif operator ^ (const Relatif& x, const Relatif& y) {
 
2278
    x.rdlock ();
 
2279
    y.rdlock ();
 
2280
    try {
 
2281
      // create an empty result
 
2282
      Relatif result; delete result.p_mpi; result.p_mpi = nilp;
 
2283
      // bind the sign
 
2284
      result.d_sgn = x.d_sgn ^ y.d_sgn;
 
2285
      // bind the mpi
 
2286
      result.p_mpi = mpi_xor (*x.p_mpi, *y.p_mpi);
 
2287
      // clamp the result
 
2288
      if (result.p_mpi->clamp () == true) result.d_sgn = false;
 
2289
      // unlock and return
 
2290
      y.unlock ();
 
2291
      x.unlock ();
 
2292
      return result;
 
2293
    } catch (...) {
 
2294
      y.unlock ();
 
2295
      x.unlock ();
 
2296
      throw;
 
2297
    }
 
2298
  }
 
2299
 
 
2300
  // -------------------------------------------------------------------------
 
2301
  // - class section                                                         -
 
2302
  // -------------------------------------------------------------------------
 
2303
 
 
2304
  // create a default relatif
 
2305
 
 
2306
  Relatif::Relatif (void) {
 
2307
    d_sgn = false;
 
2308
    p_mpi = new s_mpi;
 
2309
  }
 
2310
 
 
2311
  // create a relatif by value
 
2312
 
 
2313
  Relatif::Relatif (const t_long x) {
 
2314
    // compute sign
 
2315
    d_sgn = x < 0;
 
2316
    // convert to unsigned
 
2317
    t_octa data = d_sgn ? -x : x;
 
2318
    // build mpi data
 
2319
    p_mpi = new s_mpi (data);
 
2320
  }
 
2321
 
 
2322
  // create a relatif from a string
 
2323
 
 
2324
  Relatif::Relatif (const String& s) {
 
2325
    d_sgn = 0;
 
2326
    p_mpi = nilp;
 
2327
    *this = strtor (s);
 
2328
  }
 
2329
 
 
2330
  // create a relatif from a byte array
 
2331
 
 
2332
  Relatif::Relatif (const t_byte* rbuf, const long size) {
 
2333
    if (size < 0) {
 
2334
      throw Exception ("size-error", "invalid relatif negative byte size");
 
2335
    }
 
2336
    if (size == 0) {
 
2337
      d_sgn = false;
 
2338
      p_mpi = new s_mpi;
 
2339
    } else {
 
2340
      d_sgn = false;
 
2341
      p_mpi = new s_mpi (rbuf, size); p_mpi->clamp ();
 
2342
    }
 
2343
  }
 
2344
 
 
2345
  // create a relatif from a byte array in complemented form
 
2346
 
 
2347
  Relatif::Relatif (const t_byte* rbuf, const long size, const bool cflg) {
 
2348
    if (size < 0) {
 
2349
      throw Exception ("size-error", "invalid relatif negative byte size");
 
2350
    }
 
2351
    if (size == 0) {
 
2352
      d_sgn = false;
 
2353
      p_mpi = new s_mpi;
 
2354
    } else {
 
2355
      if (cflg == false) {
 
2356
        d_sgn = false;
 
2357
        p_mpi = new s_mpi (rbuf, size); p_mpi->clamp ();
 
2358
      } else { 
 
2359
        p_mpi = new s_mpi;
 
2360
        d_sgn = p_mpi->setsbuf (rbuf, size); p_mpi->clamp ();
 
2361
      }
 
2362
    }
 
2363
  }
 
2364
 
 
2365
  // copy construct this relatif
 
2366
 
 
2367
  Relatif::Relatif (const Relatif& that) {
 
2368
    that.rdlock ();
 
2369
    try {
 
2370
      d_sgn = that.d_sgn;
 
2371
      p_mpi = new s_mpi (*that.p_mpi);
 
2372
      if (p_mpi->clamp () == true) d_sgn = false;
 
2373
      that.unlock ();
 
2374
    } catch (...) {
 
2375
      that.unlock ();
 
2376
      throw;
 
2377
    }
 
2378
  }
 
2379
 
 
2380
  // destroy this relatif
 
2381
 
 
2382
  Relatif::~Relatif (void) {
 
2383
    delete p_mpi;
 
2384
  }
 
2385
 
 
2386
  // return the class name
 
2387
 
 
2388
  String Relatif::repr (void) const {
 
2389
    return "Relatif";
 
2390
  }
 
2391
 
 
2392
  // return a clone of this object
 
2393
 
 
2394
  Object* Relatif::clone (void) const {
 
2395
    return new Relatif (*this);
 
2396
  }
 
2397
 
 
2398
  // return a literal representation of this relatif
 
2399
 
 
2400
  String Relatif::toliteral (void) const {
 
2401
    rdlock ();
 
2402
    String result = tostring () + 'R';
 
2403
    unlock ();
 
2404
    return result;
 
2405
  }
 
2406
 
 
2407
  // get a string representation on this relatif
 
2408
 
 
2409
  String Relatif::tostring (void) const {
 
2410
    rdlock ();
 
2411
    try {
 
2412
      Relatif bval = 10;
 
2413
      Relatif dval = d_sgn ? -(*this) : (*this);
 
2414
      Buffer buffer;
 
2415
      // loop until we reach 0
 
2416
      while (dval != 0) {
 
2417
        Relatif rval = dval % bval;
 
2418
        buffer.pushback ((char) ('0' + rval.tolong ()));
 
2419
        dval = dval / bval;
 
2420
      }
 
2421
      // readjust for sign and null value
 
2422
      if (buffer.length () == 0) {
 
2423
        unlock ();
 
2424
        return '0';
 
2425
      }
 
2426
      String result;
 
2427
      if (d_sgn == true) result = result + '-';
 
2428
      result = result + buffer.tostring ();
 
2429
      unlock ();
 
2430
      return result;
 
2431
    } catch (...) {
 
2432
      unlock ();
 
2433
      throw;
 
2434
    }
 
2435
  }
 
2436
 
 
2437
  // return the relatif serial code
 
2438
 
 
2439
  t_byte Relatif::serialid (void) const {
 
2440
    return SERIAL_RELT_ID;
 
2441
  }
 
2442
 
 
2443
  // serialize this relatif
 
2444
 
 
2445
  void Relatif::wrstream (OutputStream& os) const {
 
2446
    rdlock ();
 
2447
    try {
 
2448
      // serialize the sign
 
2449
      Boolean sign (d_sgn);
 
2450
      sign.wrstream (os);
 
2451
      // serialize the mpi
 
2452
      p_mpi->wrstream (os);
 
2453
      unlock ();
 
2454
    } catch (...) {
 
2455
      unlock ();
 
2456
      throw;
 
2457
    }
 
2458
  }
 
2459
 
 
2460
  // deserialize this relatif
 
2461
 
 
2462
  void Relatif::rdstream (InputStream& is) {
 
2463
    wrlock ();
 
2464
    try {
 
2465
      // clean the old value
 
2466
      delete p_mpi; p_mpi = nilp;
 
2467
      // deserialize the sign
 
2468
      Boolean sign;
 
2469
      sign.rdstream (is);
 
2470
      d_sgn = sign.tobool ();
 
2471
      // deserialize the mpi
 
2472
      p_mpi = mpi_rds (is);
 
2473
      unlock ();
 
2474
    } catch (...) {
 
2475
      unlock ();
 
2476
      throw;
 
2477
    }
 
2478
  }
 
2479
 
 
2480
  // assign a relatif to this one
 
2481
 
 
2482
  Relatif& Relatif::operator = (const Relatif& that) {
 
2483
    // check for same objects
 
2484
    if (this == &that) return *this;
 
2485
    // lock and check
 
2486
    wrlock ();
 
2487
    that.rdlock ();
 
2488
    try {
 
2489
      // clean old mpi
 
2490
      delete p_mpi;
 
2491
      // bin new mpi
 
2492
      d_sgn = that.d_sgn;
 
2493
      p_mpi = new s_mpi (*that.p_mpi);
 
2494
      if (p_mpi->clamp () == true) d_sgn = false;
 
2495
      that.unlock ();
 
2496
      unlock ();
 
2497
      return *this;
 
2498
    } catch (...) {
 
2499
      that.unlock ();
 
2500
      unlock ();
 
2501
      throw;
 
2502
    }
 
2503
  }
 
2504
 
 
2505
  // add a relatif to this one
 
2506
 
 
2507
  Relatif& Relatif::operator += (const Relatif& x) {
 
2508
    wrlock   ();
 
2509
    x.rdlock ();
 
2510
    try {
 
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;
 
2517
      } else {
 
2518
        bool xflg = mpi_geq (*p_mpi, *x.p_mpi);
 
2519
        if (xflg == true) {
 
2520
          s_mpi* mpi = mpi_sub (*p_mpi, *x.p_mpi);
 
2521
          delete p_mpi; p_mpi = mpi;
 
2522
        } else {
 
2523
          s_mpi* mpi = mpi_sub (*x.p_mpi, *p_mpi);
 
2524
          delete p_mpi; p_mpi = mpi;
 
2525
          d_sgn = x.d_sgn;
 
2526
        }
 
2527
      }
 
2528
      // clamp the result
 
2529
      if (p_mpi->clamp () == true) d_sgn = false;
 
2530
      // unlock and return
 
2531
      unlock   ();
 
2532
      x.unlock ();
 
2533
      return *this;
 
2534
    } catch (...) {
 
2535
      unlock   ();
 
2536
      x.unlock ();
 
2537
      throw;
 
2538
    }
 
2539
  }
 
2540
 
 
2541
  // substract a relatif to this one
 
2542
 
 
2543
  Relatif& Relatif::operator -= (const Relatif& x) {
 
2544
    wrlock   ();
 
2545
    x.rdlock ();
 
2546
    try {
 
2547
      // compute the type of operation to do
 
2548
      bool sflg = d_sgn ^ x.d_sgn;
 
2549
      // compute the result
 
2550
      if (sflg == true) {
 
2551
        s_mpi* mpi = mpi_add (*p_mpi, *x.p_mpi);
 
2552
        delete p_mpi; p_mpi = mpi;
 
2553
      } else {
 
2554
        bool xflg = mpi_geq (*p_mpi, *x.p_mpi);
 
2555
        if (xflg == true) {
 
2556
          s_mpi* mpi = mpi_sub (*p_mpi, *x.p_mpi);
 
2557
          delete p_mpi; p_mpi = mpi;
 
2558
        } else {
 
2559
          s_mpi* mpi = mpi_sub (*x.p_mpi, *p_mpi);
 
2560
          delete p_mpi; p_mpi = mpi;
 
2561
          d_sgn = !d_sgn;
 
2562
        }
 
2563
      }
 
2564
      // clamp the result
 
2565
      if (p_mpi->clamp () == true) d_sgn = false;
 
2566
      // unlock and return
 
2567
      unlock   ();
 
2568
      x.unlock ();
 
2569
      return *this;
 
2570
    } catch (...) {
 
2571
      unlock   ();
 
2572
      x.unlock ();
 
2573
      throw;
 
2574
    }
 
2575
  }
 
2576
 
 
2577
  // multiply a relatif with this one
 
2578
 
 
2579
  Relatif& Relatif::operator *= (const Relatif& x) {
 
2580
    wrlock   ();
 
2581
    x.rdlock ();
 
2582
    try {
 
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;
 
2587
      // clamp the result
 
2588
      if (p_mpi->clamp () == true) d_sgn = false;
 
2589
      // unlock and return
 
2590
      unlock ();
 
2591
      x.unlock ();
 
2592
      return *this;
 
2593
    } catch (...) {
 
2594
      unlock   ();
 
2595
      x.unlock ();
 
2596
      throw;
 
2597
    }
 
2598
  }
 
2599
 
 
2600
  // divide a relatif with this one
 
2601
 
 
2602
  Relatif& Relatif::operator /= (const Relatif& x) {
 
2603
    wrlock   ();
 
2604
    x.rdlock ();
 
2605
    try {
 
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;
 
2610
      // clamp the result
 
2611
      if (p_mpi->clamp () == true) d_sgn = false;
 
2612
      // unlock and return
 
2613
      unlock ();
 
2614
      x.unlock ();
 
2615
      return *this;
 
2616
    } catch (...) {
 
2617
      unlock   ();
 
2618
      x.unlock ();
 
2619
      throw;
 
2620
    }
 
2621
  }
 
2622
 
 
2623
  // prefix increment this relatif
 
2624
 
 
2625
  Relatif& Relatif::operator ++ (void) {
 
2626
    wrlock ();
 
2627
    try {
 
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;
 
2632
      } else {
 
2633
        if (mpi_gth (*p_mpi, 1) == true) {
 
2634
          s_mpi* mpi = mpi_dec (*p_mpi);
 
2635
          delete p_mpi; p_mpi = mpi;
 
2636
        } else {
 
2637
          delete p_mpi; p_mpi = new s_mpi;
 
2638
          d_sgn = false;
 
2639
        }
 
2640
      }
 
2641
      // clamp the result
 
2642
      if (p_mpi->clamp () == true) d_sgn = false;
 
2643
      // unlock and return
 
2644
      unlock ();
 
2645
      return *this;
 
2646
    } catch (...) {
 
2647
      unlock ();
 
2648
      throw;
 
2649
    }
 
2650
  }
 
2651
 
 
2652
  // prefix decrements this relatif
 
2653
 
 
2654
  Relatif& Relatif::operator -- (void) {
 
2655
    wrlock ();
 
2656
    try {
 
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;
 
2661
      } else {
 
2662
        if (mpi_gth (*p_mpi, 1) == true) {
 
2663
          s_mpi* mpi = mpi_dec (*p_mpi);
 
2664
          delete p_mpi; p_mpi = mpi;
 
2665
        } else {
 
2666
          delete p_mpi; p_mpi = new s_mpi;
 
2667
          d_sgn = false;
 
2668
        }
 
2669
      }
 
2670
      // clamp the result
 
2671
      if (p_mpi->clamp () == true) d_sgn = false;
 
2672
      // unlock and return
 
2673
      unlock ();
 
2674
      return *this;
 
2675
    } catch (...) {
 
2676
      unlock ();
 
2677
      throw;
 
2678
    }
 
2679
  }
 
2680
  
 
2681
  // postfix increments this relatif
 
2682
 
 
2683
  Relatif Relatif::operator ++ (int) {
 
2684
    wrlock ();
 
2685
    try {
 
2686
      // save the result
 
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;
 
2692
      } else {
 
2693
        if (mpi_gth (*p_mpi, 1) == true) {
 
2694
          s_mpi* mpi = mpi_dec (*p_mpi);
 
2695
          delete p_mpi; p_mpi = mpi;
 
2696
        } else {
 
2697
          delete p_mpi; p_mpi = new s_mpi;
 
2698
          d_sgn = false;
 
2699
        }
 
2700
      }
 
2701
      // clamp the result
 
2702
      if (p_mpi->clamp () == true) d_sgn = false;
 
2703
      // unlock and return
 
2704
      unlock ();
 
2705
      return result;
 
2706
    } catch (...) {
 
2707
      unlock ();
 
2708
      throw;
 
2709
    }
 
2710
  }
 
2711
 
 
2712
  // postfix decrements this relatif
 
2713
 
 
2714
  Relatif Relatif::operator -- (int) {
 
2715
    wrlock ();
 
2716
    try {
 
2717
      // save the result
 
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;
 
2723
      } else {
 
2724
        if (mpi_gth (*p_mpi, 1) == true) {
 
2725
          s_mpi* mpi = mpi_dec (*p_mpi);
 
2726
          delete p_mpi; p_mpi = mpi;
 
2727
        } else {
 
2728
          delete p_mpi; p_mpi = new s_mpi;
 
2729
          d_sgn = false;
 
2730
        }
 
2731
      }
 
2732
      // clamp the result
 
2733
      if (p_mpi->clamp () == true) d_sgn = false;
 
2734
      // unlock and return
 
2735
      unlock ();
 
2736
      return result;
 
2737
    } catch (...) {
 
2738
      unlock ();
 
2739
      throw;
 
2740
    }
 
2741
  }
 
2742
 
 
2743
  // shift left this relatif by a certain amount
 
2744
 
 
2745
  Relatif Relatif::operator << (const long asl) const {
 
2746
    // lock and compute
 
2747
    rdlock ();
 
2748
    try {
 
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;
 
2753
      if (asl >= 0) {
 
2754
        result.p_mpi = mpi_shl (*p_mpi, asl);
 
2755
      } else {
 
2756
        result.p_mpi = mpi_shr (*p_mpi, -asl);
 
2757
      }
 
2758
      // clamp the result
 
2759
      if (result.p_mpi->clamp () == true) result.d_sgn = false;
 
2760
      //unlock and return
 
2761
      unlock ();
 
2762
      return result;
 
2763
    } catch (...) {
 
2764
      unlock ();
 
2765
      throw;
 
2766
    }
 
2767
  }
 
2768
 
 
2769
  // shift right this relatif by a certain amount
 
2770
 
 
2771
  Relatif Relatif::operator >> (const long asr) const {
 
2772
    // lock and compute
 
2773
    rdlock ();
 
2774
    try {
 
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;
 
2779
      if (asr >= 0) {
 
2780
        result.p_mpi = mpi_shr (*p_mpi, asr);
 
2781
      } else {
 
2782
        result.p_mpi = mpi_shl (*p_mpi, -asr);
 
2783
      }
 
2784
      // clamp the result
 
2785
      if (result.p_mpi->clamp () == true) result.d_sgn = false;
 
2786
      //unlock and return
 
2787
      unlock ();
 
2788
      return result;
 
2789
    } catch (...) {
 
2790
      unlock ();
 
2791
      throw;
 
2792
    }
 
2793
  }
 
2794
 
 
2795
  // shift left this relatif by a certain amount
 
2796
 
 
2797
  Relatif& Relatif::operator <<= (const long asl) {
 
2798
    // lock and compute
 
2799
    wrlock ();
 
2800
    try {
 
2801
      if (asl >= 0) {
 
2802
        mpi_leq (*p_mpi, asl);
 
2803
      } else {
 
2804
        mpi_req (*p_mpi, -asl);
 
2805
      }
 
2806
      // clamp the result
 
2807
      if (p_mpi->clamp () == true) d_sgn = false;
 
2808
      //unlock and return
 
2809
      unlock ();
 
2810
      return *this;
 
2811
    } catch (...) {
 
2812
      unlock ();
 
2813
      throw;
 
2814
    }
 
2815
  }
 
2816
 
 
2817
  // shift right this relatif by a certain amount
 
2818
 
 
2819
  Relatif& Relatif::operator >>= (const long asr) {
 
2820
    // lock and compute
 
2821
    wrlock ();
 
2822
    try {
 
2823
      if (asr >= 0) {
 
2824
        mpi_req (*p_mpi, asr);
 
2825
      } else {
 
2826
        mpi_leq (*p_mpi, -asr);
 
2827
      }
 
2828
      // clamp the result
 
2829
      if (p_mpi->clamp () == true) d_sgn = false;
 
2830
      //unlock and return
 
2831
      unlock ();
 
2832
      return *this;
 
2833
    } catch (...) {
 
2834
      unlock ();
 
2835
      throw;
 
2836
    }
 
2837
  }
 
2838
  
 
2839
  // compare a relatif with an integer
 
2840
 
 
2841
  bool Relatif::operator == (const t_long x) const {
 
2842
    rdlock ();
 
2843
    try {
 
2844
      // prepare x data
 
2845
      bool   xsgn = (x < 0);
 
2846
      t_octa xval = xsgn ? -x : x;
 
2847
      // check for sign
 
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
 
2852
      unlock ();
 
2853
      return result;
 
2854
    } catch (...) {
 
2855
      unlock ();
 
2856
      throw;
 
2857
    }
 
2858
  }
 
2859
 
 
2860
  // compare two relatifs
 
2861
 
 
2862
  bool Relatif::operator == (const Relatif& x) const {
 
2863
    rdlock ();
 
2864
    x.rdlock ();
 
2865
    try {
 
2866
      // check for sign
 
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
 
2871
      x.unlock ();
 
2872
      unlock ();
 
2873
      return result;
 
2874
    } catch (...) {
 
2875
      x.unlock ();
 
2876
      unlock ();
 
2877
      throw;
 
2878
    }
 
2879
  }
 
2880
 
 
2881
  // compare two relatifs
 
2882
 
 
2883
  bool Relatif::operator != (const t_long x) const {
 
2884
    rdlock ();
 
2885
    try {
 
2886
      // prepare x data
 
2887
      bool   xsgn = (x < 0);
 
2888
      t_octa xval = xsgn ? -x : x;
 
2889
      // check for sign
 
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
 
2894
      unlock ();
 
2895
      return !result;
 
2896
    } catch (...) {
 
2897
      unlock ();
 
2898
      throw;
 
2899
    }
 
2900
  }
 
2901
 
 
2902
  // compare two relatifs
 
2903
 
 
2904
  bool Relatif::operator != (const Relatif& x) const {
 
2905
    rdlock ();
 
2906
    x.rdlock ();
 
2907
    try {
 
2908
      // check for sign
 
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
 
2913
      x.unlock ();
 
2914
      unlock ();
 
2915
      return !result;
 
2916
    } catch (...) {
 
2917
      x.unlock ();
 
2918
      unlock ();
 
2919
      throw;
 
2920
    }
 
2921
  }
 
2922
 
 
2923
  // compare a relatif with an integer
 
2924
 
 
2925
  bool Relatif::operator < (const t_long x) const {
 
2926
    rdlock ();
 
2927
    try {
 
2928
      // prepare x data
 
2929
      bool   xsgn = (x < 0);
 
2930
      t_octa xval = xsgn ? -x : x;
 
2931
      // check against sign first
 
2932
      if ((d_sgn == true)  && (xsgn == false)) {
 
2933
        unlock ();
 
2934
        return true;
 
2935
      }
 
2936
      if ((d_sgn == false) && (xsgn == true)){
 
2937
        unlock ();
 
2938
        return false;
 
2939
      }
 
2940
      // the number have the same sign
 
2941
      bool result = !mpi_geq (*p_mpi, xval);
 
2942
      unlock ();
 
2943
      return result;
 
2944
    } catch (...) {
 
2945
      unlock ();
 
2946
      throw;
 
2947
    }
 
2948
  }
 
2949
 
 
2950
  // compare two relatifs
 
2951
 
 
2952
  bool Relatif::operator < (const Relatif& x) const {
 
2953
    rdlock ();
 
2954
    x.rdlock ();
 
2955
    try {
 
2956
      // check against sign first
 
2957
      if ((d_sgn == true)  && (x.d_sgn == false)) {
 
2958
        x.unlock ();
 
2959
        unlock ();
 
2960
        return true;
 
2961
      }
 
2962
      if ((d_sgn == false) && (x.d_sgn == true)){
 
2963
        x.unlock ();
 
2964
        unlock ();
 
2965
        return false;
 
2966
      }
 
2967
      // the number have the same sign
 
2968
      bool result = !mpi_geq (*p_mpi, *x.p_mpi);
 
2969
      x.unlock ();
 
2970
      unlock ();
 
2971
      return result;
 
2972
    } catch (...) {
 
2973
      x.unlock ();
 
2974
      unlock ();
 
2975
      throw;
 
2976
    }
 
2977
  }
 
2978
 
 
2979
  // compare a relatif with an integer
 
2980
 
 
2981
  bool Relatif::operator <= (const t_long x) const {
 
2982
    rdlock ();
 
2983
    try {
 
2984
      // prepare x data
 
2985
      bool   xsgn = (x < 0);
 
2986
      t_octa xval = xsgn ? -x : x;
 
2987
      // check against sign first
 
2988
      if ((d_sgn == true)  && (xsgn == false)) {
 
2989
        unlock ();
 
2990
        return true;
 
2991
      }
 
2992
      if ((d_sgn == false) && (xsgn == true)){
 
2993
        unlock ();
 
2994
        return false;
 
2995
      }
 
2996
      // the number have the same sign
 
2997
      bool result = !mpi_gth (*p_mpi, xval);
 
2998
      unlock ();
 
2999
      return result;
 
3000
    } catch (...) {
 
3001
      unlock ();
 
3002
      throw;
 
3003
    }
 
3004
  }
 
3005
 
 
3006
  // compare two relatifs
 
3007
 
 
3008
  bool Relatif::operator <= (const Relatif& x) const {
 
3009
    rdlock ();
 
3010
    x.rdlock ();
 
3011
    try {
 
3012
      // check against sign first
 
3013
      if ((d_sgn == true)  && (x.d_sgn == false)) {
 
3014
        x.unlock ();
 
3015
        unlock ();
 
3016
        return true;
 
3017
      }
 
3018
      if ((d_sgn == false) && (x.d_sgn == true)){
 
3019
        x.unlock ();
 
3020
        unlock ();
 
3021
        return false;
 
3022
      }
 
3023
      // the number have the same sign
 
3024
      bool result = !mpi_gth (*p_mpi, *x.p_mpi);
 
3025
      x.unlock ();
 
3026
      unlock ();
 
3027
      return result;
 
3028
    } catch (...) {
 
3029
      x.unlock ();
 
3030
      unlock ();
 
3031
      throw;
 
3032
    }
 
3033
  }
 
3034
 
 
3035
  // compare a relatif with an integer
 
3036
 
 
3037
  bool Relatif::operator > (const t_long x) const {
 
3038
    rdlock ();
 
3039
    try {
 
3040
      // prepare x data
 
3041
      bool   xsgn = (x < 0);
 
3042
      t_octa xval = xsgn ? -x : x;
 
3043
      // check against sign first
 
3044
      if ((d_sgn == true)  && (xsgn == false)) {
 
3045
        unlock ();
 
3046
        return false;
 
3047
      }
 
3048
      if ((d_sgn == false) && (xsgn == true)){
 
3049
        unlock ();
 
3050
        return true;
 
3051
      }
 
3052
      // the number have the same sign
 
3053
      bool result = mpi_gth (*p_mpi, xval);
 
3054
      unlock ();
 
3055
      return result;
 
3056
    } catch (...) {
 
3057
      unlock ();
 
3058
      throw;
 
3059
    }
 
3060
  }
 
3061
 
 
3062
  // compare two relatifs
 
3063
 
 
3064
  bool Relatif::operator > (const Relatif& x) const {
 
3065
    rdlock ();
 
3066
    x.rdlock ();
 
3067
    try {
 
3068
      // check against sign first
 
3069
      if ((d_sgn == true)  && (x.d_sgn == false)) {
 
3070
        x.unlock ();
 
3071
        unlock ();
 
3072
        return false;
 
3073
      }
 
3074
      if ((d_sgn == false) && (x.d_sgn == true)){
 
3075
        x.unlock ();
 
3076
        unlock ();
 
3077
        return true;
 
3078
      }
 
3079
      // the number have the same sign
 
3080
      bool result = mpi_gth (*p_mpi, *x.p_mpi);
 
3081
      x.unlock ();
 
3082
      unlock ();
 
3083
      return result;
 
3084
    } catch (...) {
 
3085
      x.unlock ();
 
3086
      unlock ();
 
3087
      throw;
 
3088
    }
 
3089
  }
 
3090
 
 
3091
  // compare  a relatif with an integer
 
3092
 
 
3093
  bool Relatif::operator >= (const t_long x) const {
 
3094
    rdlock ();
 
3095
    try {
 
3096
      // prepare x data
 
3097
      bool   xsgn = (x < 0);
 
3098
      t_octa xval = xsgn ? -x : x;
 
3099
      // check against sign first
 
3100
      if ((d_sgn == true)  && (xsgn == false)) {
 
3101
        unlock ();
 
3102
        return false;
 
3103
      }
 
3104
      if ((d_sgn == false) && (xsgn == true)){
 
3105
        unlock ();
 
3106
        return true;
 
3107
      }
 
3108
      // the number have the same sign
 
3109
      bool result = mpi_geq (*p_mpi, xval);
 
3110
      unlock ();
 
3111
      return result;
 
3112
    } catch (...) {
 
3113
      unlock ();
 
3114
      throw;
 
3115
    }
 
3116
  }
 
3117
 
 
3118
  // compare two relatifs
 
3119
 
 
3120
  bool Relatif::operator >= (const Relatif& x) const {
 
3121
    rdlock ();
 
3122
    x.rdlock ();
 
3123
    try {
 
3124
      // check against sign first
 
3125
      if ((d_sgn == true)  && (x.d_sgn == false)) {
 
3126
        x.unlock ();
 
3127
        unlock ();
 
3128
        return false;
 
3129
      }
 
3130
      if ((d_sgn == false) && (x.d_sgn == true)){
 
3131
        x.unlock ();
 
3132
        unlock ();
 
3133
        return true;
 
3134
      }
 
3135
      // the number have the same sign
 
3136
      bool result = mpi_geq (*p_mpi, *x.p_mpi);
 
3137
      x.unlock ();
 
3138
      unlock ();
 
3139
      return result;
 
3140
    } catch (...) {
 
3141
      x.unlock ();
 
3142
      unlock ();
 
3143
      throw;
 
3144
    }
 
3145
  }
 
3146
 
 
3147
  // return true if this relatif is zero
 
3148
  
 
3149
  bool Relatif::iszero (void) const {
 
3150
    rdlock ();
 
3151
    try {
 
3152
      // compute result
 
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");
 
3157
      }
 
3158
      unlock ();
 
3159
      return result;
 
3160
    } catch (...) {
 
3161
      unlock ();
 
3162
      throw;
 
3163
    }
 
3164
  }
 
3165
 
 
3166
  // return true if this relatif is even
 
3167
  
 
3168
  bool Relatif::iseven (void) const {
 
3169
    rdlock ();
 
3170
    try {
 
3171
      bool result = p_mpi->iseven ();
 
3172
      unlock ();
 
3173
      return result;
 
3174
    } catch (...) {
 
3175
      unlock ();
 
3176
      throw;
 
3177
    }
 
3178
  }
 
3179
 
 
3180
  // return true if this relatif is odd
 
3181
  
 
3182
  bool Relatif::isodd (void) const {
 
3183
    rdlock ();
 
3184
    try {
 
3185
      bool result = p_mpi->isodd ();
 
3186
      unlock ();
 
3187
      return result;
 
3188
    } catch (...) {
 
3189
      unlock ();
 
3190
      throw;
 
3191
    }
 
3192
  }
 
3193
 
 
3194
  // return the absolute value of this relatif
 
3195
 
 
3196
  Relatif Relatif::abs (void) const {
 
3197
    rdlock ();
 
3198
    try {
 
3199
      // prepare the result
 
3200
      Relatif result = *this;
 
3201
      // fix the sign
 
3202
      result.d_sgn = false;
 
3203
      // unlock and return
 
3204
      unlock ();
 
3205
      return result;
 
3206
    } catch (...) {
 
3207
      unlock ();
 
3208
      throw;
 
3209
    }
 
3210
  }
 
3211
 
 
3212
  // compute the power of a relatif
 
3213
 
 
3214
  Relatif Relatif::pow (const t_long e) const {
 
3215
    // check for negative exponent
 
3216
    if (e < 0) {
 
3217
      throw Exception ("exponent-error", "invalid negative exponent in pow");
 
3218
    }
 
3219
    // process trivial case
 
3220
    rdlock ();
 
3221
    if (e == 0) {
 
3222
      unlock ();
 
3223
      return 1;
 
3224
    }
 
3225
    if (e == 1) {
 
3226
      Relatif result = *this;
 
3227
      unlock ();
 
3228
      return result;
 
3229
    }
 
3230
    // compute power
 
3231
    try {
 
3232
      // compute result
 
3233
      Relatif result; delete result.p_mpi; result.p_mpi = nilp;
 
3234
      result.p_mpi = mpi_pow (*p_mpi, e);
 
3235
      // compute sign
 
3236
      result.d_sgn = ((e & 1) == 0) ? false : d_sgn;
 
3237
      // clamp the result
 
3238
      if (result.p_mpi->clamp () == true) result.d_sgn = false;
 
3239
      unlock ();
 
3240
      return result;
 
3241
    } catch (...) {
 
3242
      unlock ();
 
3243
      throw;
 
3244
    }
 
3245
  }
 
3246
 
 
3247
 
 
3248
  // compute the power of a relatif
 
3249
 
 
3250
  Relatif Relatif::pow (const Relatif& e) const {
 
3251
    // check for negative exponent
 
3252
    e.rdlock ();
 
3253
    if (e.d_sgn == true) {
 
3254
      e.unlock ();
 
3255
      throw Exception ("exponent-error", "invalid negative exponent in pow");
 
3256
    }
 
3257
    // process trivial case
 
3258
    rdlock ();
 
3259
    if (e == 0) {
 
3260
      unlock ();
 
3261
      return 1;
 
3262
    }
 
3263
    if (e == 1) {
 
3264
      Relatif result = *this;
 
3265
      unlock ();
 
3266
      return result;
 
3267
    }
 
3268
    // compute the power                          
 
3269
    try {
 
3270
      // compute result
 
3271
      Relatif result; delete result.p_mpi; result.p_mpi = nilp;
 
3272
      result.p_mpi = mpi_pow (*p_mpi, *e.p_mpi);
 
3273
      // compute sign
 
3274
      result.d_sgn = (e.iseven () == true) ? false : d_sgn;
 
3275
      // clamp the result
 
3276
      if (result.p_mpi->clamp () == true) result.d_sgn = false;
 
3277
      unlock   ();
 
3278
      e.unlock ();
 
3279
      return result;
 
3280
    } catch (...) {
 
3281
      unlock   ();
 
3282
      e.unlock ();
 
3283
      throw;
 
3284
    }
 
3285
  }
 
3286
 
 
3287
  // compute the modular exponentiation of a relatif
 
3288
 
 
3289
  Relatif Relatif::pow (const t_long e, const Relatif& m) const {
 
3290
    // check for negative exponent
 
3291
    if (e < 0) {
 
3292
      throw Exception ("exponent-error", "invalid negative exponent in pow");
 
3293
    }
 
3294
    // check the modulus
 
3295
    m.rdlock ();
 
3296
    if (m.d_sgn == true) {
 
3297
      m.unlock ();
 
3298
      throw Exception ("modulus-error", "invalid negative modulus in pow");
 
3299
    }
 
3300
    // process trivial case
 
3301
    rdlock ();
 
3302
    if (e == 0) {
 
3303
      unlock   ();
 
3304
      m.unlock ();
 
3305
      return 1;
 
3306
    }
 
3307
    if (e == 1) {
 
3308
      Relatif result = *this % m;
 
3309
      unlock   ();
 
3310
      m.unlock ();
 
3311
      return result;
 
3312
    }
 
3313
    // compute the modular exponentiation
 
3314
    try {
 
3315
      // compute result
 
3316
      Relatif result; delete result.p_mpi; result.p_mpi = nilp;
 
3317
      result.p_mpi = mpi_pow (*p_mpi, e, *m.p_mpi);
 
3318
      // compute sign
 
3319
      result.d_sgn = ((e & 1) == 0) ? false : d_sgn;
 
3320
      // clamp the result
 
3321
      if (result.p_mpi->clamp () == true) result.d_sgn = false;
 
3322
      unlock ();
 
3323
      m.unlock ();
 
3324
      return result;
 
3325
    } catch (...) {
 
3326
      unlock ();
 
3327
      m.unlock ();
 
3328
      throw;
 
3329
    }
 
3330
  }
 
3331
 
 
3332
  // compute the modular exponentiation of a relatif
 
3333
 
 
3334
  Relatif Relatif::pow (const Relatif& e, const Relatif& m) const {
 
3335
    // check for negative exponent
 
3336
    e.rdlock ();
 
3337
    if (e.d_sgn == true) {
 
3338
      e.unlock ();
 
3339
      throw Exception ("exponent-error", "invalid negative exponent in pow");
 
3340
    }
 
3341
    // check the modulus
 
3342
    m.rdlock ();
 
3343
    if (m.d_sgn == true) {
 
3344
      e.unlock ();
 
3345
      m.unlock ();
 
3346
      throw Exception ("modulus-error", "invalid negative modulus in pow");
 
3347
    }
 
3348
    // process trivial case
 
3349
    rdlock ();
 
3350
    if (e == 0) {
 
3351
      unlock   ();
 
3352
      e.unlock ();
 
3353
      m.unlock ();
 
3354
      return 1;
 
3355
    }
 
3356
    if (e == 1) {
 
3357
      Relatif result = *this % m;
 
3358
      unlock   ();
 
3359
      e.unlock ();
 
3360
      m.unlock ();
 
3361
      return result;
 
3362
    }
 
3363
    // compute the modular exponentiation
 
3364
    try {
 
3365
      // compute result
 
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);
 
3368
      // compute sign
 
3369
      result.d_sgn = ((e & 1) == 0) ? false : d_sgn;
 
3370
      // clamp the result
 
3371
      if (result.p_mpi->clamp () == true) result.d_sgn = false;
 
3372
      unlock   ();
 
3373
      e.unlock ();
 
3374
      m.unlock ();
 
3375
      return result;
 
3376
    } catch (...) {
 
3377
      unlock   ();
 
3378
      e.unlock ();
 
3379
      m.unlock ();
 
3380
      throw;
 
3381
    }
 
3382
  }
 
3383
 
 
3384
  // return the lsb of this relatif
 
3385
 
 
3386
  long Relatif::getlsb (void) const {
 
3387
    rdlock ();
 
3388
    try {
 
3389
      long result = p_mpi->getlsb ();
 
3390
      unlock ();
 
3391
      return result;
 
3392
    } catch (...) {
 
3393
      unlock ();
 
3394
      throw;
 
3395
    }
 
3396
  }
 
3397
 
 
3398
  // return the msb of this relatif
 
3399
 
 
3400
  long Relatif::getmsb (void) const {
 
3401
    rdlock ();
 
3402
    try {
 
3403
      long result = p_mpi->getmsb ();
 
3404
      unlock ();
 
3405
      return result;
 
3406
    } catch (...) {
 
3407
      unlock ();
 
3408
      throw;
 
3409
    }
 
3410
  }
 
3411
 
 
3412
  // return the relatif bit value by position
 
3413
 
 
3414
  bool Relatif::getbit (const long bpos) const {
 
3415
    // check valid position and lock
 
3416
    if (bpos < 0) {
 
3417
      throw Exception ("position-error", "invalid negative bit position");
 
3418
    }
 
3419
    // lock and compute
 
3420
    rdlock ();
 
3421
    try {
 
3422
      bool result = p_mpi->getbit (bpos);
 
3423
      unlock ();
 
3424
      return result;
 
3425
    } catch (...) {
 
3426
      unlock ();
 
3427
      throw;
 
3428
    }
 
3429
  }
 
3430
 
 
3431
  // set the relatif bit value by position
 
3432
 
 
3433
  void Relatif::setbit (const long bpos, const bool bval) {
 
3434
    // check valid position and lock
 
3435
    if (bpos < 0) {
 
3436
      throw Exception ("position-error", "invalid negative bit position");
 
3437
    }
 
3438
    // lock and compute
 
3439
    wrlock ();
 
3440
    try {
 
3441
      p_mpi->setbit (bpos, bval);
 
3442
      unlock ();
 
3443
    } catch (...) {
 
3444
      unlock ();
 
3445
      throw;
 
3446
    }
 
3447
  }
 
3448
 
 
3449
  // get the relatif byte buffer size
 
3450
 
 
3451
  long Relatif::getbbs (void) const {
 
3452
    rdlock ();
 
3453
    try {
 
3454
      long result = p_mpi->bsize ();
 
3455
      unlock ();
 
3456
      return result;
 
3457
    } catch (...) {
 
3458
      unlock ();
 
3459
      throw;
 
3460
    }
 
3461
  }
 
3462
 
 
3463
  // fill an unsigned buffer representation by size
 
3464
 
 
3465
  long Relatif::toubuf (t_byte* rbuf, const long size) const {
 
3466
    rdlock ();
 
3467
    try {
 
3468
      // bind the mpi value
 
3469
      long result = p_mpi->toubuf (rbuf, size);
 
3470
      // unlock and return
 
3471
      unlock ();
 
3472
      return result;
 
3473
    } catch (...) {
 
3474
      unlock ();
 
3475
      throw;
 
3476
    }
 
3477
  }
 
3478
 
 
3479
  // fill a signed buffer representation by size
 
3480
 
 
3481
  long Relatif::tosbuf (t_byte* rbuf, const long size) const {
 
3482
    rdlock ();
 
3483
    try {
 
3484
      // bind the mpi value
 
3485
      long result = p_mpi->tosbuf (rbuf, size, d_sgn);
 
3486
      // unlock and return
 
3487
      unlock ();
 
3488
      return result;
 
3489
    } catch (...) {
 
3490
      unlock ();
 
3491
      throw;
 
3492
    }
 
3493
  }
 
3494
 
 
3495
  // fill a large buffer with an unsigned representation
 
3496
 
 
3497
  long Relatif::tobyte (t_byte* rbuf, const long size) const {
 
3498
    rdlock ();
 
3499
    try {
 
3500
      // bind the mpi value
 
3501
      long result = p_mpi->tobyte (rbuf, size);
 
3502
      // unlock and return
 
3503
      unlock ();
 
3504
      return result;
 
3505
    } catch (...) {
 
3506
      unlock ();
 
3507
      throw;
 
3508
    }
 
3509
  }
 
3510
 
 
3511
  // convert this relatif into a hexadecimal representation
 
3512
 
 
3513
  String Relatif::tohexa (void) const {
 
3514
    rdlock ();
 
3515
    try {
 
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
 
3521
      unlock ();
 
3522
      return result;
 
3523
    } catch (...) {
 
3524
      unlock ();
 
3525
      throw;
 
3526
    }
 
3527
  }
 
3528
 
 
3529
  // convert this relatif into a hexadecimal string
 
3530
 
 
3531
  String Relatif::tohstr (void) const {
 
3532
    rdlock ();
 
3533
    try {
 
3534
      // bind the mpi value
 
3535
      String result = p_mpi->tohexa ();
 
3536
      // unlock and return
 
3537
      unlock ();
 
3538
      return result;
 
3539
    } catch (...) {
 
3540
      unlock ();
 
3541
      throw;
 
3542
    }
 
3543
  }
 
3544
 
 
3545
  // convert this relatif to an integer
 
3546
 
 
3547
  t_long Relatif::tolong (void) const {
 
3548
    rdlock ();
 
3549
    try {
 
3550
      // get native value
 
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");
 
3555
      }
 
3556
      // adjust with the sign
 
3557
      t_long result = d_sgn ? - (t_long) data : (t_long) data;
 
3558
      unlock ();
 
3559
      return result;
 
3560
    } catch (...) {
 
3561
      unlock ();
 
3562
      throw;
 
3563
    }
 
3564
  }
 
3565
 
 
3566
  // -------------------------------------------------------------------------
 
3567
  // - object section                                                        -
 
3568
  // -------------------------------------------------------------------------
 
3569
 
 
3570
  // the quark zone
 
3571
  static const long QUARK_ZONE_LENGTH = 30;
 
3572
  static QuarkZone  zone (QUARK_ZONE_LENGTH);
 
3573
 
 
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");
 
3605
 
 
3606
  // create a new object in a generic way
 
3607
 
 
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;
 
3616
 
 
3617
    // try an integer object
 
3618
    Integer* ival = dynamic_cast <Integer*> (obj);
 
3619
    if (ival != nilp) return new Relatif (ival->tolong ());
 
3620
 
 
3621
    // try a relatif object
 
3622
    Relatif* xval = dynamic_cast <Relatif*> (obj);
 
3623
    if (xval != nilp) return new Relatif (*xval);
 
3624
 
 
3625
    // try a real object
 
3626
    Real* rval = dynamic_cast <Real*> (obj);
 
3627
    if (rval != nilp) return new Relatif (rval->tolong ());
 
3628
 
 
3629
    // try a character object
 
3630
    Character* cval = dynamic_cast <Character*> (obj);
 
3631
    if (cval != nilp) return new Relatif (cval->toquad ());
 
3632
 
 
3633
    // try a string object
 
3634
    String* sval = dynamic_cast <String*> (obj);
 
3635
    if (sval != nilp) return new Relatif (*sval);
 
3636
 
 
3637
    // illegal object
 
3638
    throw Exception ("type-error", "illegal object with relatif constructor",
 
3639
                     obj->repr ());
 
3640
  }
 
3641
 
 
3642
  // return true if the given quark is defined
 
3643
 
 
3644
  bool Relatif::isquark (const long quark, const bool hflg) const {
 
3645
    rdlock ();
 
3646
    if (zone.exists (quark) == true) {
 
3647
      unlock ();
 
3648
      return true;
 
3649
    }
 
3650
    bool result = hflg ? Number::isquark (quark, hflg) : false;
 
3651
    unlock ();
 
3652
    return result;
 
3653
  }
 
3654
 
 
3655
  // operate this object with another object
 
3656
 
 
3657
  Object* Relatif::oper (t_oper type, Object* object) {
 
3658
    Integer* iobj = dynamic_cast <Integer*> (object);
 
3659
    Relatif* robj = dynamic_cast <Relatif*> (object);
 
3660
    switch (type) {
 
3661
    case Object::ADD:
 
3662
      if (iobj != nilp) return new Relatif (*this + iobj->tolong ());
 
3663
      if (robj != nilp) return new Relatif (*this + *robj);
 
3664
      break;
 
3665
    case Object::SUB:
 
3666
      if (iobj != nilp) return new Relatif (*this - iobj->tolong ());
 
3667
      if (robj != nilp) return new Relatif (*this - *robj);
 
3668
      break;
 
3669
    case Object::MUL:
 
3670
      if (iobj != nilp) return new Relatif (*this * iobj->tolong ());
 
3671
      if (robj != nilp) return new Relatif (*this * *robj);
 
3672
      break;
 
3673
    case Object::DIV:
 
3674
      if (iobj != nilp) return new Relatif (*this / iobj->tolong ());
 
3675
      if (robj != nilp) return new Relatif (*this / *robj);
 
3676
      break;
 
3677
    case Object::UMN:
 
3678
      return new Relatif (-(*this));
 
3679
      break;
 
3680
    case Object::EQL:
 
3681
      if (iobj != nilp) return new Boolean (*this == iobj->tolong ());
 
3682
      if (robj != nilp) return new Boolean (*this == *robj);
 
3683
      break;
 
3684
    case Object::NEQ:
 
3685
      if (iobj != nilp) return new Boolean (*this != iobj->tolong ());
 
3686
      if (robj != nilp) return new Boolean (*this != *robj);
 
3687
      break;
 
3688
    case Object::GEQ:
 
3689
      if (iobj != nilp) return new Boolean (*this >= iobj->tolong ());
 
3690
      if (robj != nilp) return new Boolean (*this >= *robj);
 
3691
      break;
 
3692
    case Object::GTH:
 
3693
      if (iobj != nilp) return new Boolean (*this >  iobj->tolong ());
 
3694
      if (robj != nilp) return new Boolean (*this >  *robj);
 
3695
      break;
 
3696
    case Object::LEQ:
 
3697
      if (iobj != nilp) return new Boolean (*this <= iobj->tolong ());
 
3698
      if (robj != nilp) return new Boolean (*this <= *robj);
 
3699
      break;
 
3700
    case Object::LTH:
 
3701
      if (iobj != nilp) return new Boolean (*this <  iobj->tolong ());
 
3702
      if (robj != nilp) return new Boolean (*this <  *robj);
 
3703
      break;
 
3704
    }
 
3705
    throw Exception ("type-error", "invalid operand with relatif",
 
3706
                     Object::repr (object));
 
3707
  }
 
3708
  
 
3709
  // set an object to this relatif
 
3710
  
 
3711
  Object* Relatif::vdef (Runnable* robj, Nameset* nset, Object* object) {
 
3712
    Integer* iobj = dynamic_cast <Integer*> (object);
 
3713
    if (iobj != nilp) {
 
3714
      *this = iobj->tolong ();
 
3715
      return this;
 
3716
    }
 
3717
    Real* fobj = dynamic_cast <Real*> (object);
 
3718
    if (fobj != nilp) {
 
3719
      *this = fobj->tolong ();
 
3720
      return this;
 
3721
    }
 
3722
    Relatif* mobj = dynamic_cast <Relatif*> (object);
 
3723
    if (mobj != nilp) {
 
3724
      *this = *mobj;
 
3725
      return this;
 
3726
    }
 
3727
    throw Exception ("type-error", "invalid object with relatif vdef",
 
3728
                     Object::repr (object));
 
3729
  }
 
3730
 
 
3731
  // apply this object with a set of arguments and a quark
 
3732
 
 
3733
  Object* Relatif::apply (Runnable* robj, Nameset* nset, const long quark,
 
3734
                          Vector* argv) {
 
3735
    // get the number of arguments
 
3736
    long argc = (argv == nilp) ? 0 : argv->length ();
 
3737
 
 
3738
    // dispatch 0 argument
 
3739
    if (argc == 0) {
 
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) {
 
3746
        ++(*this);
 
3747
        robj->post (this);
 
3748
        return this;
 
3749
      }
 
3750
      if (quark == QUARK_OMM) {
 
3751
        --(*this);
 
3752
        robj->post (this);
 
3753
        return this;
 
3754
      }
 
3755
      if (quark == QUARK_NOT) {
 
3756
        return new Relatif (~(*this));
 
3757
      }
 
3758
    }
 
3759
 
 
3760
    // dispatch 1 argument
 
3761
    if (argc == 1) {
 
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));
 
3772
 
 
3773
      if (quark == QUARK_AEQ) {
 
3774
        t_long val = argv->getlong (0);
 
3775
        *this += val;
 
3776
        robj->post (this);
 
3777
        return this;
 
3778
      }
 
3779
      if (quark == QUARK_SEQ) {
 
3780
        t_long val = argv->getlong (0);
 
3781
        *this -= val;
 
3782
        robj->post (this);
 
3783
        return this;
 
3784
      }
 
3785
      if (quark == QUARK_MEQ) {
 
3786
        t_long val = argv->getlong (0);
 
3787
        *this *= val;
 
3788
        robj->post (this);
 
3789
        return this;
 
3790
      }
 
3791
      if (quark == QUARK_DEQ) {
 
3792
        t_long val = argv->getlong (0);
 
3793
        *this /= val;
 
3794
        robj->post (this);
 
3795
        return this;
 
3796
      }
 
3797
      if (quark == QUARK_MOD) {
 
3798
        Object* obj = argv->get (0);
 
3799
        // check for relatif
 
3800
        Relatif* mobj = dynamic_cast <Relatif*> (obj);
 
3801
        if (mobj != nilp) {
 
3802
          Object* result = new Relatif (*this % *mobj);
 
3803
          return result;
 
3804
        }
 
3805
        // check for integer
 
3806
        Integer* iobj = dynamic_cast <Integer*> (obj);
 
3807
        if (iobj != nilp) {
 
3808
          Object* result = new Relatif (*this % iobj->tolong ());
 
3809
          return result;
 
3810
        }
 
3811
        throw Exception ("type-error", "invalid object with mod operator",
 
3812
                         Object::repr (obj));
 
3813
      }
 
3814
      if (quark == QUARK_POW) {
 
3815
        Object* obj = argv->get (0);
 
3816
        // check for relatif
 
3817
        Relatif* mobj = dynamic_cast <Relatif*> (obj);
 
3818
        if (mobj != nilp) {
 
3819
          Object* result = new Relatif (pow (*mobj));
 
3820
          return result;
 
3821
        }
 
3822
        // check for integer
 
3823
        Integer* iobj = dynamic_cast <Integer*> (obj);
 
3824
        if (iobj != nilp) {
 
3825
          Object* result = new Relatif (pow (iobj->tolong ()));
 
3826
          return result;
 
3827
        }
 
3828
        throw Exception ("type-error", "invalid object with pow operator",
 
3829
                         Object::repr (obj));
 
3830
      }
 
3831
      if (quark == QUARK_MMI) {
 
3832
        Object* obj = argv->get (0);
 
3833
        // check for relatif
 
3834
        Relatif* mobj = dynamic_cast <Relatif*> (obj);
 
3835
        if (mobj != nilp) {
 
3836
          Object* result = new Relatif (Relatif::mmi (*this, *mobj));
 
3837
          return result;
 
3838
        }
 
3839
        // check for integer
 
3840
        Integer* iobj = dynamic_cast <Integer*> (obj);
 
3841
        if (iobj != nilp) {
 
3842
          t_long ival = iobj->tolong ();
 
3843
          Object* result = new Relatif (Relatif::mmi (*this, ival));
 
3844
          return result;
 
3845
        }
 
3846
        throw Exception ("type-error", "invalid object with mmi operator",
 
3847
                         Object::repr (obj));
 
3848
      }
 
3849
      if (quark == QUARK_SHL) {
 
3850
        t_long asl = argv->getlong (0);
 
3851
        Object* result = new Relatif (*this << asl);
 
3852
        return result;
 
3853
      }
 
3854
      if (quark == QUARK_SHR) {
 
3855
        t_long asr = argv->getlong (0);
 
3856
        Object* result = new Relatif (*this >> asr);
 
3857
        return result;
 
3858
      }
 
3859
      if (quark == QUARK_XOR) {
 
3860
        Object* obj = argv->get (0);
 
3861
        // check for relatif
 
3862
        Relatif* mobj = dynamic_cast <Relatif*> (obj);
 
3863
        if (mobj != nilp) {
 
3864
          Object* result = new Relatif (*this ^ *mobj);
 
3865
          return result;
 
3866
        }
 
3867
        // check for integer
 
3868
        Integer* iobj = dynamic_cast <Integer*> (obj);
 
3869
        if (iobj != nilp) {
 
3870
          Object* result = new Relatif (*this ^ iobj->tolong ());
 
3871
          return result;
 
3872
        }
 
3873
        throw Exception ("type-error", "invalid object with xor operator",
 
3874
                         Object::repr (obj));
 
3875
      }
 
3876
      if (quark == QUARK_AND) {
 
3877
        Object* obj = argv->get (0);
 
3878
        // check for relatif
 
3879
        Relatif* mobj = dynamic_cast <Relatif*> (obj);
 
3880
        if (mobj != nilp) {
 
3881
          Object* result = new Relatif (*this & *mobj);
 
3882
          return result;
 
3883
        }
 
3884
        // check for integer
 
3885
        Integer* iobj = dynamic_cast <Integer*> (obj);
 
3886
        if (iobj != nilp) {
 
3887
          Object* result = new Relatif (*this & iobj->tolong ());
 
3888
          return result;
 
3889
        }
 
3890
        throw Exception ("type-error", "invalid object with and operator",
 
3891
                         Object::repr (obj));
 
3892
      }
 
3893
      if (quark == QUARK_OR) {
 
3894
        Object* obj = argv->get (0);
 
3895
        // check for relatif
 
3896
        Relatif* mobj = dynamic_cast <Relatif*> (obj);
 
3897
        if (mobj != nilp) {
 
3898
          Object* result = new Relatif (*this | *mobj);
 
3899
          return result;
 
3900
        }
 
3901
        // check for integer
 
3902
        Integer* iobj = dynamic_cast <Integer*> (obj);
 
3903
        if (iobj != nilp) {
 
3904
          Object* result = new Relatif (*this | iobj->tolong ());
 
3905
          return result;
 
3906
        }
 
3907
        throw Exception ("type-error", "invalid object with or operator",
 
3908
                         Object::repr (obj));
 
3909
      }
 
3910
    }
 
3911
    // dispatch 2 arguments
 
3912
    if (argc == 2) {
 
3913
      if (quark == QUARK_POW) {
 
3914
        Object* e = argv->get (0);
 
3915
        Object* m = argv->get (1);
 
3916
        Relatif* mmo = dynamic_cast <Relatif*> (m);
 
3917
        if (mmo == nilp) {
 
3918
          throw Exception ("type-error", "invalid modulus with pow operator",
 
3919
                           Object::repr (m));
 
3920
        }
 
3921
        // check for relatif
 
3922
        Relatif* emo = dynamic_cast <Relatif*> (e);
 
3923
        if (emo != nilp) {
 
3924
          Object* result = new Relatif (pow (*emo, *mmo));
 
3925
          return result;
 
3926
        }
 
3927
        // check for integer
 
3928
        Integer* eio = dynamic_cast <Integer*> (e);
 
3929
        if (eio != nilp){
 
3930
          t_long ie = eio->tolong ();
 
3931
          Object* result = new Relatif (pow (ie, *mmo));
 
3932
          return result;
 
3933
        }
 
3934
        throw Exception ("type-error", "invalid exponent with pow operator",
 
3935
                         Object::repr (e));
 
3936
      }
 
3937
    }
 
3938
    // call the number method
 
3939
    return Number::apply (robj, nset, quark, argv);
 
3940
  }
 
3941
}