]> www.ginac.de Git - cln.git/blob - src/integer/bitwise/cl_I_ldbxtest.cc
9ee07672832e2f707c034d550335eb2f22cf39c6
[cln.git] / src / integer / bitwise / cl_I_ldbxtest.cc
1 // ldb_extract_test().
2
3 // General includes.
4 #include "cl_sysdep.h"
5
6 // Specification.
7 #include "cl_I_byte.h"
8
9
10 // Implementation.
11
12 #include "cln/integer.h"
13 #include "cl_I.h"
14 #include "cl_DS.h"
15
16 namespace cln {
17
18 cl_boolean ldb_extract_test (const cl_I& x, uintL p, uintL q)
19     { var const uintD* MSDptr;
20       var uintC len;
21       var const uintD* LSDptr;
22       I_to_NDS_nocopy(x, MSDptr=,len=,LSDptr=,cl_true, { return cl_false; } ); // NDS zu x bilden
23       // MSDptr erhöhen und len erniedrigen, so daß len = ceiling(q/intDsize) wird:
24       { var uintL qD = ceiling(q,intDsize); // ceiling(q/intDsize)
25         // wegen q<=l ist qD = ceiling(q/intDsize) <= ceiling((l+1)/intDsize) = len, also
26         // paßt qD ebenso wie len in ein uintC.
27         MSDptr = MSDptr mspop ((uintL)len - qD); // MSDptr um len-qD Digits erhöhen
28         len = qD; // len um len-qD erniedrigen
29       }
30       // LSDptr und len um floor(p/intDsize) erniedrigen:
31       { var uintL pD = p/intDsize; // floor(p/intDsize)
32         LSDptr = LSDptr lspop pD;
33         len -= pD;
34       }
35       // Jetzt enthält MSDptr/len/LSDptr genau die maßgeblichen Digits.
36       if (len==0) return cl_false; // len=0 -> keine Bits abzutesten
37       q = ((q-1)%intDsize); // q := intDsize - (intDsize*ceiling(q/intDsize) - q) - 1
38       p = p%intDsize; // p := p - intDsize*floor(p/intDsize)
39       // Jetzt ist 0 <= q < intDsize, 0 <= p < intDsize.
40       // Vom ersten Digit müssen die vorderen intDsize-1-q Bits unberücksichtigt bleiben.
41       // Ein AND 2^(q+1)-1 erreicht dies.
42       // Vom letzten Digit müssen die hinteren p Bits unberücksichtigt bleiben.
43       // Ein AND -2^p erreicht dies.
44       if (--len==0)
45         // 1 Digit maßgeblich, wird von beiden Seiten angeschnitten:
46         // Ein AND 2^(q+1)-2^p erreicht dies.
47         if (!(((uintD)(bitm(q+1)-bit(p)) & mspref(MSDptr,0)) == 0))
48           return cl_true;
49           else
50           return cl_false;
51       // mindestens 2 Digits. Teste erst die Randdigits, dann die inneren:
52       if (!(((msprefnext(MSDptr) & (uintD)(bitm(q+1)-1)) == 0) &&
53             ((lsprefnext(LSDptr) & (uintD)(minus_bit(p))) == 0)
54          ) )
55         return cl_true;
56       len--; // die beiden Randdigits sind jetzt abgezogen.
57       if (DS_test_loop(MSDptr,len,LSDptr)) { return cl_true; } else { return cl_false; }
58     }
59
60 }  // namespace cln