source: trunk/lib/carryQ.hpp @ 1937

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