source: trunk/lib/carryQ.hpp @ 1662

Last change on this file since 1662 was 1662, checked in by ksherdy, 8 years ago

Update interpose, advance32

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 simd_slli_32(r, shft) _mm_slli_epi32(r, shft)
29#define simd_srli_32(r, shft) _mm_srli_epi32(r, shft)
30
31static IDISA_ALWAYS_INLINE BitBlock interpose32(BitBlock s, BitBlock s32, const uint32_t n);
32IDISA_ALWAYS_INLINE BitBlock interpose32(BitBlock s, BitBlock s32, const uint32_t n) {
33        return simd_or(simd<32>::slli<n>(s), simd<32>::srli<32-n>(s32));
34}
35
36// Abstract Base Class
37class ICarryQueue {
38
39        IDISA_ALWAYS_INLINE BitBlock BitBlock_advance_ci_co(BitBlock strm, uint16_t carryno);
40        IDISA_ALWAYS_INLINE BitBlock BitBlock_advance_co(BitBlock strm, uint16_t carryno);
41        IDISA_ALWAYS_INLINE BitBlock BitBlock_add_ci_co(BitBlock strm1, BitBlock strm2, const uint16_t carryno);
42        IDISA_ALWAYS_INLINE BitBlock BitBlock_add_co(BitBlock strm1, BitBlock strm2, uint16_t carryno);
43        IDISA_ALWAYS_INLINE BitBlock BitBlock_sub_ci_co(BitBlock strm1, BitBlock strm2, uint16_t carryno);
44        IDISA_ALWAYS_INLINE BitBlock BitBlock_sub_co(BitBlock strm1, BitBlock strm2, uint16_t carryno);
45        IDISA_ALWAYS_INLINE BitBlock BitBlock_scantofirst(BitBlock charclass, uint16_t carryno);
46        IDISA_ALWAYS_INLINE BitBlock BitBlock_scanthru_ci_co(BitBlock markers0, BitBlock charclass, uint16_t carryno);
47        IDISA_ALWAYS_INLINE BitBlock BitBlock_scanthru_co(BitBlock markers0, BitBlock charclass, uint16_t carryno);
48        IDISA_ALWAYS_INLINE BitBlock BitBlock_advance32_ci_co(BitBlock strm, uint32_t & pending32);
49        IDISA_ALWAYS_INLINE BitBlock BitBlock_advance32_co(BitBlock strm, uint32_t & pending32);
50        IDISA_ALWAYS_INLINE bool CarryTest(uint16_t carryno, uint16_t carry_count);
51        IDISA_ALWAYS_INLINE void CarryDequeueEnqueue(uint16_t carryno, uint16_t carry_count);
52        IDISA_ALWAYS_INLINE void CarryQ_Adjust(uint16_t carry_count);
53        IDISA_ALWAYS_INLINE void CarryCombine(ICarryQueue carryqueue, uint16_t carryno, uint16_t carry_count);
54
55protected:
56        ICarryQueue(){};
57        ~ICarryQueue(){};
58        // helpers
59        IDISA_ALWAYS_INLINE BitBlock carry_flip(BitBlock carry) const ;
60        IDISA_ALWAYS_INLINE bool test_carry(BitBlock carry) const ;
61        IDISA_ALWAYS_INLINE BitBlock carry_or(BitBlock carry1, BitBlock carry2) const ;
62};
63
64#include <string.h>
65
66// Array of BitBlock implementation.
67template <uint16_t CarryCount>
68class CarryArray: public ICarryQueue {
69
70public:
71        CarryArray()
72        {
73                Carry0 = simd<BLOCK_SIZE>::constant<0>();
74                Carry1 = simd<BLOCK_SIZE>::constant<1>();
75
76                memset (cq, 0, sizeof(BitBlock) * CarryCount);// size_t num )
77        }
78        ~CarryArray() {}
79
80        IDISA_ALWAYS_INLINE BitBlock BitBlock_advance_ci_co(BitBlock strm, uint16_t carryno)
81        {
82                BitBlock rslt;
83                advance_with_carry(strm, cq[carryno], rslt);
84                return rslt;
85        }
86
87        IDISA_ALWAYS_INLINE BitBlock BitBlock_advance_co(BitBlock strm, uint16_t carryno)
88        {
89                BitBlock rslt;
90                cq[carryno] = Carry0;
91                advance_with_carry(strm, cq[carryno], rslt);
92                return rslt;
93        }
94
95        IDISA_ALWAYS_INLINE BitBlock BitBlock_add_ci_co(BitBlock strm1, BitBlock strm2, const uint16_t carryno)
96        {
97                BitBlock sum;
98                adc(strm1, strm2, cq[carryno], sum);
99                return sum;
100        }
101
102        IDISA_ALWAYS_INLINE BitBlock BitBlock_add_co(BitBlock strm1, BitBlock strm2, uint16_t carryno)
103        {
104                BitBlock sum;
105                cq[carryno] = Carry0;
106                adc(strm1, strm2, cq[carryno], sum);
107                return sum;
108        }
109
110        IDISA_ALWAYS_INLINE BitBlock BitBlock_sub_ci_co(BitBlock strm1, BitBlock strm2, uint16_t carryno)
111        {
112                BitBlock diff;
113                sbb(strm1, strm2, cq[carryno], diff);
114                return diff;
115        }
116
117        IDISA_ALWAYS_INLINE BitBlock BitBlock_sub_co(BitBlock strm1, BitBlock strm2, uint16_t carryno)
118        {
119                BitBlock diff;
120                cq[carryno] = Carry0;
121                sbb(strm1, strm2, cq[carryno], diff);
122                return diff;
123        }
124
125        IDISA_ALWAYS_INLINE BitBlock BitBlock_scantofirst(BitBlock charclass, uint16_t carryno)
126        {
127                BitBlock marker;
128                BitBlock c = carry_flip(cq[carryno]);
129            adc(simd<128>::constant<0>(), simd_not(charclass), c, marker);
130            cq[carryno] = carry_flip(c);
131            return simd_and(marker, charclass);
132        }
133
134        IDISA_ALWAYS_INLINE BitBlock BitBlock_scanthru_ci_co(BitBlock markers0, BitBlock charclass, uint16_t carryno)
135        {
136                BitBlock markers1;
137                adc(markers0, charclass, cq[carryno], markers1);
138                return simd_andc(markers1, charclass);
139        }
140
141        IDISA_ALWAYS_INLINE BitBlock BitBlock_scanthru_co(BitBlock markers0, BitBlock charclass, uint16_t carryno)
142        {
143                BitBlock markers1;
144                cq[carryno] = Carry0;
145                adc(markers0, charclass, cq[carryno], markers1);
146                return simd_andc(markers1, charclass);
147        }
148
149        IDISA_ALWAYS_INLINE BitBlock BitBlock_advance32_ci_co(BitBlock strm, uint32_t & pending32)
150        {
151                uint32_t temp = pending32;
152                pending32 = (uint32_t) mvmd<32>::extract<3>(strm);
153                return mvmd<32>::dslli<1>(strm, mvmd128<BLOCK_SIZE>::fill((uint32_t)temp));
154        }
155
156/*
157        static inline BitBlock BitBlock_advance32_ci_co(BitBlock strm, uint32_t & pending32){
158                uint32_t temp = pending32;
159                pending32 = sisd_to_int(sisd_srli(strm,96));
160                return simd_or(sisd_slli(strm, 32), sisd_from_int(temp));
161        }
162 */
163
164        IDISA_ALWAYS_INLINE BitBlock BitBlock_advance32_co(BitBlock strm, uint32_t & pending32)
165        {
166                pending32 = (uint32_t) mvmd<32>::extract<3>(strm);
167                return mvmd<32>::slli<1>(strm);
168        }
169
170/*
171        static inline BitBlock BitBlock_advance32_co(BitBlock strm, uint32_t & pending32) {
172                pending32 = sisd_to_int(sisd_srli(strm,96));
173                return sisd_slli(strm, 32);
174        }
175
176 */
177
178        IDISA_ALWAYS_INLINE bool CarryTest(uint16_t carryno, uint16_t carry_count)
179        {
180                  BitBlock c1 = cq[carryno];
181                  int ubound = carryno + carry_count;
182                  for (int i = carryno + 1; i < ubound ; i++) {
183                        c1 = carry_or(c1, cq[i]);
184                  }
185                  return test_carry(c1);
186        }
187
188        IDISA_ALWAYS_INLINE void CarryDequeueEnqueue(uint16_t carryno, uint16_t carry_count)
189        {
190                return;
191        }
192
193        IDISA_ALWAYS_INLINE void CarryQ_Adjust(uint16_t carry_count)
194        {
195                return;
196        }
197
198        IDISA_ALWAYS_INLINE void CarryCombine(const BitBlock local_cq[], uint16_t carryno, uint16_t carry_count)
199        {
200                  for (int i = 0; i < carry_count; i++) {
201                    cq[carryno+i] = carry_or(cq[carryno+i], local_cq[i]);
202                  }
203        }
204
205        /* read-only */
206        IDISA_ALWAYS_INLINE const BitBlock * array() const
207        {
208                return cq;
209        }
210
211private:
212        BitBlock cq[CarryCount];
213        BitBlock Carry0;
214        BitBlock Carry1;
215
216        // helpers
217        IDISA_ALWAYS_INLINE BitBlock carry_flip(BitBlock carry) const
218        {
219                return simd_xor(carry, Carry1);
220        }
221
222        IDISA_ALWAYS_INLINE bool test_carry(BitBlock carry) const
223        {
224                return bitblock_has_bit(carry);
225        }
226
227        IDISA_ALWAYS_INLINE BitBlock carry_or(BitBlock carry1, BitBlock carry2) const
228        {
229                return simd_or(carry1, carry2);
230        }
231
232};
233
234// Single bit per carry implementation.
235template <class BitBlock, uint16_t CarryCount>
236class CarryRegister: public ICarryQueue {
237
238public:
239        CarryRegister() {}
240        ~CarryRegister() {}
241
242private:
243        BitBlock cq;
244};
245
246#endif /* CARRYQ_HPP_ */
Note: See TracBrowser for help on using the repository browser.