source: trunk/lib/carryQ.hpp @ 1660

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

Preliminary check in of CarryQ advance32, interpose functionality.

File size: 7.2 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_slli_32(s, n), simd_srli_32(s32, 32-n));
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< sizeof(BitBlock)*8 >::constant<0>();
74                Carry1 = simd< sizeof(BitBlock)*8 >::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<0>((simd< sizeof(BitBlock)*8 >::srli<96>(strm)));
153                return simd_or(simd< sizeof(BitBlock)*8 >::slli<32>(strm), mvmd128< sizeof(BitBlock)*8 >::fill((uint32_t)temp) );
154
155        }
156
157
158
159/*
160        static inline BitBlock BitBlock_advance32_ci_co(BitBlock strm, uint32_t & pending32){
161                uint32_t temp = pending32;
162                pending32 = sisd_to_int(sisd_srli(strm,96));
163                return simd_or(sisd_slli(strm, 32), sisd_from_int(temp));
164        }
165 */
166
167        IDISA_ALWAYS_INLINE BitBlock BitBlock_advance32_co(BitBlock strm, uint32_t & pending32)
168        {
169                pending32 = (uint32_t) mvmd<32>::extract<0>((simd< sizeof(BitBlock)*8 >::srli<96>(strm)));
170                return simd< sizeof(BitBlock)*8 >::slli<32>(strm);
171        }
172
173/*
174        static inline BitBlock BitBlock_advance32_co(BitBlock strm, uint32_t & pending32) {
175                pending32 = sisd_to_int(sisd_srli(strm,96));
176                return sisd_slli(strm, 32);
177        }
178
179 */
180
181        IDISA_ALWAYS_INLINE bool CarryTest(uint16_t carryno, uint16_t carry_count)
182        {
183                  BitBlock c1 = cq[carryno];
184                  int ubound = carryno + carry_count;
185                  for (int i = carryno + 1; i < ubound ; i++) {
186                        c1 = carry_or(c1, cq[i]);
187                  }
188                  return test_carry(c1);
189        }
190
191        IDISA_ALWAYS_INLINE void CarryDequeueEnqueue(uint16_t carryno, uint16_t carry_count)
192        {
193                return;
194        }
195
196        IDISA_ALWAYS_INLINE void CarryQ_Adjust(uint16_t carry_count)
197        {
198                return;
199        }
200
201        IDISA_ALWAYS_INLINE void CarryCombine(const BitBlock local_cq[], uint16_t carryno, uint16_t carry_count)
202        {
203                  for (int i = 0; i < carry_count; i++) {
204                    cq[carryno+i] = carry_or(cq[carryno+i], local_cq[i]);
205                  }
206        }
207
208        /* read-only */
209        IDISA_ALWAYS_INLINE const BitBlock * array() const
210        {
211                return cq;
212        }
213
214private:
215        BitBlock cq[CarryCount];
216        BitBlock Carry0;
217        BitBlock Carry1;
218
219        // helpers
220        IDISA_ALWAYS_INLINE BitBlock carry_flip(BitBlock carry) const
221        {
222                return simd_xor(carry, Carry1);
223        }
224
225        IDISA_ALWAYS_INLINE bool test_carry(BitBlock carry) const
226        {
227                return bitblock_has_bit(carry);
228        }
229
230        IDISA_ALWAYS_INLINE BitBlock carry_or(BitBlock carry1, BitBlock carry2) const
231        {
232                return simd_or(carry1, carry2);
233        }
234
235};
236
237// Single bit per carry implementation.
238template <class BitBlock, uint16_t CarryCount>
239class CarryRegister: public ICarryQueue {
240
241public:
242        CarryRegister() {}
243        ~CarryRegister() {}
244
245private:
246        BitBlock cq;
247};
248
249#endif /* CARRYQ_HPP_ */
Note: See TracBrowser for help on using the repository browser.