source: icXML/icXML-devel/src/icxmlc/PopCounter.hpp @ 2720

Last change on this file since 2720 was 2720, checked in by cameron, 6 years ago

Initial check-in of icXML 0.8 source files

File size: 3.3 KB
Line 
1/*  Parallel Bitwise Tracking of Line Number/Column Number
2 *
3 *  Copyright © 2012 International Characters.
4 *  This software is licensed to the public under the Open Software License 3.0.
5 *  icXML is a trademark of International Characters.
6 */
7
8/*
9 * @author Nigel Medforth, nigelm -at- interational-characters.com
10 * @version $Id: PopCounter.hpp 207 2012-12-02 20:38:22Z robc $
11 *
12 */
13
14
15#if !defined(XERCESC_INCLUDE_GUARD_POPCOUNTER_HPP)
16#define XERCESC_INCLUDE_GUARD_POPCOUNTER_HPP
17
18#include <simd-lib/bitblock.hpp>
19#include <icxmlc/XMLConfig.hpp>
20
21XERCES_CPP_NAMESPACE_BEGIN
22
23// note: we could use template metaprogramming to force the loops to
24// unroll properly.
25
26template<unsigned int COUNTERS>
27class PopCounter
28{
29        public:
30
31                PopCounter();
32
33                PopCounter(const uint64_t popCount);
34
35                PopCounter(const PopCounter<COUNTERS>&);
36
37                PopCounter<COUNTERS>& operator=(const PopCounter<COUNTERS>& counter);
38
39                void set(const uint64_t popCount);
40
41                void tally(const BitBlock value);
42
43                uint64_t count();
44
45        private:
46
47                static void half_add
48                (
49                        const BitBlock sum_in
50                        , const BitBlock carry_in
51                        , BitBlock & sum_out
52                        , BitBlock & carry_out
53                );
54
55                uint64_t   _pop_count;
56                BitBlock   _pop_counters[COUNTERS];
57};
58
59#define POP_COUNTER(ret) \
60        template<unsigned int COUNTERS> \
61        IDISA_ALWAYS_INLINE \
62        ret PopCounter<COUNTERS>
63
64#define POP_ZERO_COUNTER(ret) \
65        template<> \
66        IDISA_ALWAYS_INLINE \
67        ret PopCounter<0>
68
69POP_COUNTER()::
70PopCounter()
71: _pop_count(0)
72{
73        for (unsigned int i = 0; i < COUNTERS; i++)
74        {
75                _pop_counters[i] = simd<1>::constant<0>();
76        }
77}
78
79POP_COUNTER()::
80PopCounter(const uint64_t popCount)
81: _pop_count(popCount)
82{
83        for (unsigned int i = 0; i < COUNTERS; i++)
84        {
85                _pop_counters[i] = simd<1>::constant<0>();
86        }
87}
88
89POP_COUNTER()::
90PopCounter(const PopCounter<COUNTERS>& counter)
91: _pop_count(counter._pop_count)
92{
93        for (unsigned int i = 0; i < COUNTERS; i++)
94        {
95                _pop_counters[i] = counter._pop_counters[i];
96        }
97}
98
99POP_COUNTER(PopCounter<COUNTERS>&)::
100operator=(const PopCounter<COUNTERS>& counter)
101{
102        _pop_count = counter._pop_count;
103        for (unsigned int i = 0; i < COUNTERS; i++)
104        {
105                _pop_counters[i] = counter._pop_counters[i];
106        }
107        return *this;
108}
109
110POP_COUNTER(void)::
111set(const uint64_t popCount)
112{
113        _pop_count = popCount;
114        for (unsigned int i = 0; i < COUNTERS; i++)
115        {
116                _pop_counters[i] = simd<1>::constant<0>();
117        }
118}
119
120POP_COUNTER(void)::
121half_add(const BitBlock sum_in, const BitBlock carry_in, BitBlock & sum_out, BitBlock & carry_out)
122{
123        sum_out = simd_xor(sum_in, carry_in);
124        carry_out = simd_and(sum_in, carry_in);
125}
126
127POP_COUNTER(void)::
128tally(const BitBlock value)
129{
130        if (COUNTERS == 0)
131        {
132                // this comparison ought to be removed at compile time
133                _pop_count += bitblock::popcount(value);
134        }
135        else if (bitblock::any(value))
136        {
137                BitBlock carry = value;
138                for (unsigned int i = 0; i < COUNTERS; i++)
139                {
140                        half_add(_pop_counters[i], carry, _pop_counters[i], carry);
141                }
142                if (unlikely(bitblock::any(carry)))
143                {
144                        count();
145                        _pop_count += (bitblock::popcount(carry) << COUNTERS);
146                }
147        }
148}
149
150POP_COUNTER(uint64_t)::
151count()
152{
153        for (unsigned int i = 0; i < COUNTERS; i++)
154        {
155                _pop_count += (bitblock::popcount(_pop_counters[i]) << i);
156        }
157        for (unsigned int i = 0; i < COUNTERS; i++)
158        {
159                bitblock::store_aligned(simd<1>::constant<0>(), &_pop_counters[i]);
160        }
161        return _pop_count;
162}
163
164#undef POP_COUNTER
165#undef POP_ZERO_COUNTER
166
167XERCES_CPP_NAMESPACE_END
168
169#endif
Note: See TracBrowser for help on using the repository browser.