source: trunk/lib/carryQ.hpp @ 2005

Last change on this file since 2005 was 2005, checked in by cameron, 7 years ago

Fix odd comment for carryQ.hpp

File size: 9.7 KB
Line 
1#ifndef CARRYQ_HPP_
2#define CARRYQ_HPP_
3
4/*=============================================================================
5  carryQ.hpp - Pablo compiler support for carry introduction.
6  Ken Herdy, Robert D. Cameron
7  April 2012
8=============================================================================*/
9
10#include <stdint.h>
11#include <iostream>
12using namespace std;
13
14#include "bitblock.hpp"
15#include "stdio.h"
16
17///////////////////////////////////////////////////////////////////////////////
18//
19// Carry method variants.
20//
21// BitBlock_op_ci_co()  - standard block non while loop statement and in final block if ignore the carry out
22// BitBlock_op_co()     - standard block while loop and in final block while loop if ignore carry out
23// BitBlock_op_ci()             - final block non while loop statement
24// BitBlock_op()                - final while loop statement
25//
26// BitBlock_op_ci(), BitBlock_op() methods not implemented to reduce the total number of
27// methods and Pablo compiler complexity.
28//
29///////////////////////////////////////////////////////////////////////////////
30
31#define interpose32(x,y,pos) interpose32_<pos>(x,y)     
32template<uint32_t n>
33IDISA_ALWAYS_INLINE BitBlock interpose32_(BitBlock s, BitBlock s32) {
34        return simd_or(simd<32>::slli<n>(s), simd<32>::srli<32-n>(s32));
35}
36
37// Abstract Base Class
38class ICarryQueue {
39
40        IDISA_ALWAYS_INLINE BitBlock BitBlock_advance_ci_co(BitBlock strm, uint16_t carryno);
41        IDISA_ALWAYS_INLINE BitBlock BitBlock_advance_co(BitBlock strm, uint16_t carryno);
42        IDISA_ALWAYS_INLINE BitBlock BitBlock_add_ci_co(BitBlock strm1, BitBlock strm2, const uint16_t carryno);
43        IDISA_ALWAYS_INLINE BitBlock BitBlock_add_co(BitBlock strm1, BitBlock strm2, uint16_t carryno);
44        IDISA_ALWAYS_INLINE BitBlock BitBlock_sub_ci_co(BitBlock strm1, BitBlock strm2, uint16_t carryno);
45        IDISA_ALWAYS_INLINE BitBlock BitBlock_sub_co(BitBlock strm1, BitBlock strm2, uint16_t carryno);
46        IDISA_ALWAYS_INLINE BitBlock BitBlock_scantofirst(BitBlock charclass, uint16_t carryno);
47        IDISA_ALWAYS_INLINE BitBlock BitBlock_scanthru_ci_co(BitBlock markers0, BitBlock charclass, uint16_t carryno);
48        IDISA_ALWAYS_INLINE BitBlock BitBlock_scanthru_co(BitBlock markers0, BitBlock charclass, uint16_t carryno);
49        IDISA_ALWAYS_INLINE BitBlock BitBlock_advance32_ci_co(BitBlock strm, uint32_t & pending);
50        IDISA_ALWAYS_INLINE BitBlock BitBlock_advance32_co(BitBlock strm, uint32_t & pending);
51
52        IDISA_ALWAYS_INLINE BitBlock BitBlock_advance_ci_co(BitBlock strm, BitBlock carryin, uint16_t carryno);
53        IDISA_ALWAYS_INLINE BitBlock BitBlock_add_ci_co(BitBlock strm1, BitBlock strm2, BitBlock carryin, const uint16_t carryno);
54        IDISA_ALWAYS_INLINE BitBlock BitBlock_sub_ci_co(BitBlock strm1, BitBlock strm2, BitBlock carryin, uint16_t carryno);
55
56        IDISA_ALWAYS_INLINE BitBlock BitBlock_scantofirst(BitBlock charclass, BitBlock carryin, uint16_t carryno);
57        IDISA_ALWAYS_INLINE BitBlock BitBlock_scanthru_ci_co(BitBlock markers0, BitBlock charclass, BitBlock carryin, uint16_t carryno);
58        IDISA_ALWAYS_INLINE BitBlock BitBlock_advance32_ci_co(BitBlock strm, uint32_t pending_in, uint32_t & pending_out);
59
60        IDISA_ALWAYS_INLINE bool CarryTest(uint16_t carryno, uint16_t carry_count);
61        IDISA_ALWAYS_INLINE void CarryDequeueEnqueue(uint16_t carryno, uint16_t carry_count);
62        IDISA_ALWAYS_INLINE void CarryQ_Adjust(uint16_t carry_count);
63        IDISA_ALWAYS_INLINE void CarryCombine(ICarryQueue carryqueue, uint16_t carryno, uint16_t carry_count);
64
65        IDISA_ALWAYS_INLINE BitBlock get_carry_in(uint16_t carryno) const ;
66protected:
67        ICarryQueue(){};
68        ~ICarryQueue(){};
69        // helpers
70        IDISA_ALWAYS_INLINE BitBlock carry_flip(BitBlock carry) const ;
71        IDISA_ALWAYS_INLINE bool test_carry(BitBlock carry) const ;
72        IDISA_ALWAYS_INLINE BitBlock carry_or(BitBlock carry1, BitBlock carry2) const ;
73};
74
75#include <string.h>
76
77// Array of BitBlock implementation.
78template <uint16_t CarryCount>
79class CarryArray: public ICarryQueue{
80
81public:
82
83    #define Carry0 simd<BLOCK_SIZE>::constant<0>()
84    #define Carry1 simd<BLOCK_SIZE>::constant<1>()
85 
86        CarryArray()
87        {
88            memset (cq, 0, sizeof(BitBlock) * CarryCount);// size_t num )
89        }
90        ~CarryArray() {}
91
92        IDISA_ALWAYS_INLINE BitBlock BitBlock_advance_ci_co(BitBlock strm, uint16_t carryno)
93        {
94                BitBlock rslt;
95                advance_with_carry(strm, cq[carryno], rslt);
96                return rslt;
97        }
98
99        IDISA_ALWAYS_INLINE BitBlock BitBlock_advance_co(BitBlock strm, uint16_t carryno)
100        {
101                BitBlock rslt;
102                cq[carryno] = Carry0;
103                advance_with_carry(strm, cq[carryno], rslt);
104                return rslt;
105        }
106
107        IDISA_ALWAYS_INLINE BitBlock BitBlock_add_ci_co(BitBlock strm1, BitBlock strm2, const uint16_t carryno)
108        {
109                BitBlock sum;
110                adc(strm1, strm2, cq[carryno], sum);
111                return sum;
112        }
113
114        IDISA_ALWAYS_INLINE BitBlock BitBlock_add_co(BitBlock strm1, BitBlock strm2, uint16_t carryno)
115        {
116                BitBlock sum;
117                cq[carryno] = Carry0;
118                adc(strm1, strm2, cq[carryno], sum);
119                return sum;
120        }
121
122        IDISA_ALWAYS_INLINE BitBlock BitBlock_sub_ci_co(BitBlock strm1, BitBlock strm2, uint16_t carryno)
123        {
124                BitBlock diff;
125                sbb(strm1, strm2, cq[carryno], diff);
126                return diff;
127        }
128
129        IDISA_ALWAYS_INLINE BitBlock BitBlock_sub_co(BitBlock strm1, BitBlock strm2, uint16_t carryno)
130        {
131                BitBlock diff;
132                cq[carryno] = Carry0;
133                sbb(strm1, strm2, cq[carryno], diff);
134                return diff;
135        }
136
137        IDISA_ALWAYS_INLINE BitBlock BitBlock_scantofirst(BitBlock charclass, uint16_t carryno)
138        {
139                BitBlock marker;
140                BitBlock c = carry_flip(cq[carryno]);
141                adc(simd<BLOCK_SIZE>::constant<0>(), simd_not(charclass), c, marker);
142                cq[carryno] = carry_flip(c);
143                return simd_and(marker, charclass);
144        }
145
146        IDISA_ALWAYS_INLINE BitBlock BitBlock_scanthru_ci_co(BitBlock markers0, BitBlock charclass, uint16_t carryno)
147        {
148                BitBlock markers1;
149                adc(markers0, charclass, cq[carryno], markers1);
150                return simd_andc(markers1, charclass);
151        }
152
153        IDISA_ALWAYS_INLINE BitBlock BitBlock_scanthru_co(BitBlock markers0, BitBlock charclass, uint16_t carryno)
154        {
155                BitBlock markers1;
156                cq[carryno] = Carry0;
157                adc(markers0, charclass, cq[carryno], markers1);
158                return simd_andc(markers1, charclass);
159        }
160
161        IDISA_ALWAYS_INLINE BitBlock BitBlock_advance32_ci_co(BitBlock strm, uint32_t & pending)
162        {
163                uint32_t temp = pending;
164                pending = (uint32_t) mvmd<32>::extract< (sizeof(BitBlock)/sizeof(pending))-1 >(strm);
165                return simd_or(simd<BLOCK_SIZE>::slli<32>(strm), mvmd<BLOCK_SIZE>::fill((uint64_t)temp));
166        }
167
168        /*
169        static inline BitBlock BitBlock_advance32_ci_co(BitBlock strm, uint32_t & pending){
170                uint32_t temp = pending;
171                pending = sisd_to_int(sisd_srli(strm,96));
172                return simd_or(sisd_slli(strm, 32), sisd_from_int(temp));
173        }
174        */
175
176        IDISA_ALWAYS_INLINE BitBlock BitBlock_advance32_co(BitBlock strm, uint32_t & pending)
177        {
178                pending = (uint32_t) mvmd<32>::extract<(sizeof(BitBlock)/sizeof(pending))-1>(strm);
179                return mvmd<32>::slli<1>(strm);
180        }
181
182        /*
183        static inline BitBlock BitBlock_advance32_co(BitBlock strm, uint32_t & pending) {
184                pending = sisd_to_int(sisd_srli(strm,96));
185                return sisd_slli(strm, 32);
186        }
187        */
188
189        IDISA_ALWAYS_INLINE BitBlock BitBlock_advance_ci_co(BitBlock strm, BitBlock carryin, uint16_t carryno)
190        {
191                BitBlock rslt;
192                advance_with_carry(strm, carryin, cq[carryno], rslt);
193                return rslt;
194        }
195
196        IDISA_ALWAYS_INLINE BitBlock BitBlock_add_ci_co(BitBlock strm1, BitBlock strm2, BitBlock carryin, const uint16_t carryno)
197        {
198                BitBlock sum;
199                adc(strm1, strm2, carryin, cq[carryno], sum);
200                return sum;
201        }
202
203        IDISA_ALWAYS_INLINE BitBlock BitBlock_sub_ci_co(BitBlock strm1, BitBlock strm2, BitBlock carryin, uint16_t carryno)
204        {
205                BitBlock diff;
206                sbb(strm1, strm2, carryin, cq[carryno], diff);
207                return diff;
208        }
209
210        IDISA_ALWAYS_INLINE BitBlock BitBlock_scantofirst(BitBlock charclass, BitBlock carryin, uint16_t carryno)
211        {
212                BitBlock marker;
213                BitBlock c = carry_flip(carryin);
214                adc(simd<BLOCK_SIZE>::constant<0>(), simd_not(charclass), c, marker);
215                cq[carryno] = carry_flip(c);
216                return simd_and(marker, charclass);
217        }
218
219        IDISA_ALWAYS_INLINE BitBlock BitBlock_scanthru_ci_co(BitBlock markers0, BitBlock charclass, BitBlock carryin, uint16_t carryno)
220        {
221                BitBlock markers1;
222                adc(markers0, charclass, carryin, cq[carryno], markers1);
223                return simd_andc(markers1, charclass);
224        }
225
226        IDISA_ALWAYS_INLINE BitBlock BitBlock_advance32_ci_co(BitBlock strm, uint32_t pending_in, uint32_t & pending_out)
227        {
228                pending_out = (uint32_t) mvmd<32>::extract< (sizeof(BitBlock)/sizeof(pending_out))-1 >(strm);
229                return simd_or(simd<BLOCK_SIZE>::slli<32>(strm), mvmd<BLOCK_SIZE>::fill((uint64_t)pending_in));
230        }
231
232        IDISA_ALWAYS_INLINE bool CarryTest(uint16_t carryno, uint16_t carry_count)
233        {
234                  BitBlock c1 = cq[carryno];
235                  int ubound = carryno + carry_count;
236                  for (int i = carryno + 1; i < ubound ; i++) {
237                        c1 = carry_or(c1, cq[i]);
238                  }
239                  return test_carry(c1);
240        }
241
242        IDISA_ALWAYS_INLINE void CarryDequeueEnqueue(uint16_t carryno, uint16_t carry_count)
243        {
244                return;
245        }
246
247        IDISA_ALWAYS_INLINE void CarryQ_Adjust(uint16_t carry_count)
248        {
249                return;
250        }
251
252        IDISA_ALWAYS_INLINE void CarryCombine(ICarryQueue * carryqueue, uint16_t carryno, uint16_t carry_count)
253        {
254                  BitBlock * local_cq = ((CarryArray *)carryqueue)->cq;
255                  for (int i = 0; i < carry_count; i++) {
256                    cq[carryno+i] = carry_or(cq[carryno+i], local_cq[i]);
257                  }
258        }
259
260        IDISA_ALWAYS_INLINE BitBlock get_carry_in(uint16_t carryno) const 
261        {
262                return carry2bitblock(cq[carryno]);
263        }
264
265private:
266        BitBlock cq[CarryCount];
267
268        // helpers
269        IDISA_ALWAYS_INLINE BitBlock carry_flip(BitBlock carry) const
270        {
271                return simd_xor(carry, Carry1);
272        }
273
274        IDISA_ALWAYS_INLINE bool test_carry(BitBlock carry) const
275        {
276                return bitblock::any(carry);
277        }
278
279        IDISA_ALWAYS_INLINE BitBlock carry_or(BitBlock carry1, BitBlock carry2) const
280        {
281                return simd_or(carry1, carry2);
282        }
283       
284#undef Carry0
285#undef Carry1
286
287};
288
289// Single bit per carry implementation.
290template <class BitBlock, uint16_t CarryCount>
291class CarryRegister: public ICarryQueue {
292
293public:
294        CarryRegister() {}
295        ~CarryRegister() {}
296
297private:
298        BitBlock cq;
299};
300
301#endif // CARRYQ_HPP_
Note: See TracBrowser for help on using the repository browser.