source: icXML/icXML-devel/src/icxmlc/XMLLineColTracker.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: 6.0 KB
Line 
1/*
2 *  Copyright © 2012 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 *  icXML is a trademark of International Characters.
5 */
6
7/*
8 * @author Nigel Medforth, nigelm -at- interational-characters.com
9 * @version $Id: XMLLineColTracker.hpp 207 2012-12-02 20:38:22Z robc $
10 *
11 */
12
13/*  Parallel Bitwise Tracking of Line Number/Column Number */
14
15#if !defined(XERCESC_INCLUDE_GUARD_XMLLINECOLTRACKER_HPP)
16#define XERCESC_INCLUDE_GUARD_XMLLINECOLTRACKER_HPP
17
18#include <icxmlc/clog2.h>
19#include <simd-lib/bitblock.hpp>
20#include <icxmlc/PopCounter.hpp>
21#include <icxmlc/BitTracker.hpp>
22#include <icxmlc/XMLConfig.hpp>
23
24XERCES_CPP_NAMESPACE_BEGIN
25
26class XMLLineColTracker
27{
28  public:
29
30                XMLLineColTracker();
31
32                XMLLineColTracker(const XMLLineColTracker&);
33
34                void set(const XMLFileLoc line, const XMLFileLoc column);
35
36                void next(const BitBlock newLine, const BitBlock skipMask);
37
38                XMLLineColTracker& operator=(const XMLLineColTracker& tracker);
39
40                void advance();
41
42                void get
43                (
44                        const unsigned int     position
45                        , XMLFileLoc         & line
46                        , XMLFileLoc         & column
47                );
48
49                void get
50                (
51                        XMLFileLoc           & line
52                        , XMLFileLoc         & column
53                );
54
55  private:
56
57                XMLFileLoc calculateSkipCount(const unsigned int position);
58
59
60                // TODO: if this is just a temporary storage line/col tracker,
61                // have popcounter set to 0 to eliminate the tally bit blocks?
62                BitBlock                      _currentLine;
63                PopCounter<3>                 _line;
64                BitTracker                    _column;
65                BitBlock                      _currentSkipMask;
66                PopCounter<1>                 _skip;
67                BitBlock                      _initialPartialSkipMask;
68};
69
70/// --------------------------------------------------------------------------- ///
71
72IDISA_ALWAYS_INLINE
73XMLLineColTracker::XMLLineColTracker()
74        : _currentLine(simd<1>::constant<0>())
75        , _line()
76        , _column()
77        , _currentSkipMask(simd<1>::constant<0>())
78        , _skip()
79        , _initialPartialSkipMask(simd<1>::constant<0>())
80{
81
82}
83
84/// --------------------------------------------------------------------------- ///
85
86IDISA_ALWAYS_INLINE
87XMLLineColTracker::XMLLineColTracker(const XMLLineColTracker & tracker)
88        : _currentLine(tracker._currentLine)
89        , _line(tracker._line)
90        , _column(tracker._column)
91        , _currentSkipMask(tracker._currentSkipMask)
92        , _skip(tracker._skip)
93        , _initialPartialSkipMask(tracker._initialPartialSkipMask)
94{
95
96}
97
98/// --------------------------------------------------------------------------- ///
99
100IDISA_ALWAYS_INLINE
101XMLLineColTracker& XMLLineColTracker::operator=(const XMLLineColTracker& tracker)
102{
103        _currentLine = tracker._currentLine;
104        _line = tracker._line;
105        _column = tracker._column;
106        _currentSkipMask = tracker._currentSkipMask;
107        _skip = tracker._skip;
108        _initialPartialSkipMask = tracker._initialPartialSkipMask;
109        return *this;
110}
111
112/// --------------------------------------------------------------------------- ///
113
114IDISA_ALWAYS_INLINE
115void XMLLineColTracker::set(const XMLFileLoc line, const XMLFileLoc column)
116{
117        _currentLine = simd<1>::constant<0>();
118        _line.set(line - 1);
119        _column.set(column - 1);
120        _currentSkipMask = simd<1>::constant<0>();
121        _skip.set(0);
122        _initialPartialSkipMask = simd<1>::constant<0>();
123}
124
125/// --------------------------------------------------------------------------- ///
126
127IDISA_ALWAYS_INLINE
128void XMLLineColTracker::next(const BitBlock newLine, const BitBlock skipMask)
129{
130        _currentLine = newLine;
131        _currentSkipMask = skipMask;
132}
133
134/// --------------------------------------------------------------------------- ///
135
136IDISA_ALWAYS_INLINE
137void XMLLineColTracker::advance()
138{
139        if (_column.append(_currentLine))
140        {
141                // at least one new line exists in this block
142                _line.tally(_currentLine);
143                _initialPartialSkipMask = _currentSkipMask;
144                _skip.set(0);
145        }
146        else
147        {
148                // no new lines exist in this block
149                _skip.tally(_currentSkipMask);
150        }
151        _currentLine = simd<1>::constant<0>();
152        _currentSkipMask = simd<1>::constant<0>();
153}
154
155/// --------------------------------------------------------------------------- ///
156
157IDISA_ALWAYS_INLINE
158void XMLLineColTracker::get
159(
160        XMLFileLoc           & line
161        , XMLFileLoc         & column
162)
163{
164        // count up how many column positions we skip up to and including this block
165        const unsigned int dist = _column.distance();
166        _skip.tally
167        (
168                simd_andc(_initialPartialSkipMask, mask_reverse_zeroes(dist & (BLOCK_SIZE - 1)))
169        );
170        _initialPartialSkipMask = simd<1>::constant<0>();
171        // get the final line/column positions
172        column = dist - _skip.count() + 1;
173        line = _line.count() + 1;
174}
175
176/// --------------------------------------------------------------------------- ///
177
178IDISA_ALWAYS_INLINE
179void XMLLineColTracker::get
180(
181        const unsigned int     position
182        , XMLFileLoc         & line
183        , XMLFileLoc         & column
184)
185{
186        const BitBlock partialBlockMask = mask_forward_zeroes(position);
187        const BitBlock partialCurrentLine = simd_andc(_currentLine, partialBlockMask);
188        const BitBlock partialSkipMask = simd_andc(_currentSkipMask, partialBlockMask);
189
190        // data dependant but predictable condition
191        if (bitblock::any(partialCurrentLine))
192        {
193                const unsigned int dist =
194                        count_reverse_zeroes(partialCurrentLine);
195                const uint64_t skipCount =
196                        bitblock::popcount(simd_andc(partialSkipMask, mask_reverse_zeroes(dist)));
197                // get the final line/column positions
198                line = _line.count() + bitblock::popcount(partialCurrentLine) + 1;
199                column = position + dist - BLOCK_SIZE + 1 - skipCount;
200        }
201        else // the last new line was in one of the previous blocks. find it.
202        {
203                const unsigned int dist = _column.distance();
204                // count up how many column positions we skip up to this block
205                _skip.tally
206                (
207                        simd_andc(_initialPartialSkipMask, mask_reverse_zeroes(dist & (BLOCK_SIZE - 1)))
208                );
209                _initialPartialSkipMask = simd<1>::constant<0>();
210                // count how many column positions we skip within this block
211                const uint64_t skipCount =
212                        _skip.count() +
213                        bitblock::popcount(partialSkipMask);
214                // set the final line/column positions
215                line = _line.count() + 1;
216                column = dist + position - skipCount + 1;
217        }
218}
219
220/// --------------------------------------------------------------------------- ///
221
222
223
224
225XERCES_CPP_NAMESPACE_END
226
227#endif
Note: See TracBrowser for help on using the repository browser.