]> www.ginac.de Git - cln.git/blob - src/integer/bitwise/cl_I_mkfx.cc
df069b2ab1e3a5b7186a56f0fdc49a7233cd7b18
[cln.git] / src / integer / bitwise / cl_I_mkfx.cc
1 // mkf_extract().
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 const cl_I mkf_extract (const cl_I& x, uintC p, uintC q)
19 {
20       CL_ALLOCA_STACK;
21       var const uintD* MSDptr;
22       var uintC len;
23       var const uintD* LSDptr;
24       I_to_NDS_nocopy(x, MSDptr=,len=,LSDptr=,true, { return 0; } ); // NDS zu x bilden
25       // MSDptr erhöhen und len erniedrigen, so daß len = ceiling(q/intDsize) wird:
26       { var uintC qD = ceiling(q,intDsize); // ceiling(q/intDsize)
27         // wegen q<=l ist qD = ceiling(q/intDsize) <= ceiling((l+1)/intDsize) = len, also
28         // paßt qD ebenso wie len in ein uintC.
29         MSDptr = MSDptr mspop (len - qD); // MSDptr um len-qD Digits erhöhen
30         len = qD; // len um len-qD erniedrigen
31       }
32       // Platz (len Digits) für die neue UDS bereitstellen:
33       var uintD* newMSDptr;
34       num_stack_alloc_1(len, newMSDptr = ,); // Platz belegen
35       {var uintC pD = p/intDsize; // floor(p/intDsize), paßt in ein uintC
36        // Kopiere len-pD Digits aus der DS zu x heraus:
37        var uintD* midptr = copy_loop_msp(MSDptr,newMSDptr,len-pD);
38        // Lösche p-intDsize*floor(p/intDsize) Bits im Digit unterhalb von midptr:
39        {var uintC p_D = p%intDsize;
40         if (!(p_D==0)) { lspref(midptr,0) &= minus_bit(p_D); }
41        }
42        // Lösche pD Digits darüber:
43        clear_loop_msp(midptr,pD);
44       }
45       // Lösche intDsize*ceiling(q/intDsize)-q Bits im ersten Digit:
46       {var uintL q_D = q%intDsize;
47 #ifdef HAVE_FAST_LONGLONG
48        if (!(q_D==0))
49          mspref(newMSDptr,0) &= (uintD)((1LL<<q_D)-1); // erase intDsize-q_D bits
50 #else
51        if (!(q_D==0))
52          mspref(newMSDptr,0) &= (uintD)((1L<<q_D)-1); // erase intDsize-q_D bits
53 #endif
54       }
55       // Jetzt enthält die UDS newMSDptr/len/.. die extrahierten Bits.
56       return UDS_to_I(newMSDptr,len);
57 }
58
59 }  // namespace cln