File: bitdo2.h

package info (click to toggle)
galib 2.4.7-3.1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 2,224 kB
  • ctags: 3,153
  • sloc: cpp: 23,666; ansic: 520; makefile: 247; sh: 93
file content (184 lines) | stat: -rw-r--r-- 4,791 bytes parent folder | download | duplicates (12)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#ifndef ONES
#define ONES  ((_BS_word)(~0L))
#endif

#ifndef DOIT_SOLID
#ifdef DOIT
#define DOIT_SOLID(dst, src) DOIT(dst, src, (_BS_word)(~0))
#else
#define DOIT_SOLID(dst, src) (dst) = (COMBINE(dst, src))
#endif
#endif

#ifndef DOIT
#define DOIT(dst, src, mask) \
  (dst) = ((COMBINE(dst, src)) & (mask)) | ((dst) & ~(mask))
#endif

  _BS_word word0, mask;
  int shift0, shift1;

  if (length == 0)
    goto done;

  shift0 = srcbit - dstbit;

  /* First handle the case that only one destination word is touched. */
  if (length + dstbit <= _BS_BITS_PER_WORD)
    {
      _BS_word mask
	= (ONES _BS_LEFT (_BS_BITS_PER_WORD - length)) _BS_RIGHT dstbit;
      _BS_word word0 = *psrc++;
      if (shift0 <= 0)  /* dstbit >= srcbit */
        {
	  word0 = word0 _BS_RIGHT (-shift0);
	}
      else
	{
	  word0 = word0 _BS_LEFT shift0;
	  if (length + srcbit > _BS_BITS_PER_WORD)
	    word0 = word0 | (*psrc _BS_RIGHT (_BS_BITS_PER_WORD - shift0));
	}
      DOIT(*pdst, word0, mask);
      goto done;
    }

  /* Next optimize the case that the source and destination are aligned. */
  if (shift0 == 0)
    {
      _BS_word mask;
      if (psrc > pdst)
        {
	  if (srcbit)
	    {
	      mask = ONES _BS_RIGHT srcbit;
	      DOIT(*pdst, *psrc, mask);
	      pdst++; psrc++;
	      length -= _BS_BITS_PER_WORD - srcbit;
	    }
	  for (; length >= _BS_BITS_PER_WORD; length -= _BS_BITS_PER_WORD)
	    {
	      DOIT_SOLID(*pdst, *psrc);
	      pdst++;  psrc++;
	    }
	  if (length)
	    {
	      mask = ONES _BS_LEFT (_BS_BITS_PER_WORD - length);
	      DOIT(*pdst, *psrc, mask);
	    }
        }
      else if (psrc < pdst)
        {
	  _BS_size_t span = srcbit + length;
	  pdst += span / (_BS_size_t)_BS_BITS_PER_WORD;
	  psrc += span / (_BS_size_t)_BS_BITS_PER_WORD;
	  span %= (_BS_size_t)_BS_BITS_PER_WORD;
	  if (span)
	    {
	      mask = ONES _BS_LEFT (_BS_BITS_PER_WORD - span);
	      DOIT(*pdst, *psrc, mask);
	      length -= span;
	    }
	  pdst--;  psrc--;
	  for (; length >= _BS_BITS_PER_WORD; length -= _BS_BITS_PER_WORD)
	    {
	      DOIT_SOLID(*pdst, *psrc);
	      pdst--;  psrc--;
	    }
	  if (srcbit)
	    {
	      mask = ONES _BS_RIGHT srcbit;
	      DOIT(*pdst, *psrc, mask);
	    }
	}
      /* else if (psrc == pdst) --nothing to do--; */
      goto done;
    }

  /* Now we assume shift!=0, and more than on destination word is changed. */
  if (psrc >= pdst) /* Do the updates in forward direction. */
    {
      _BS_word word0 = *psrc++;
      _BS_word mask = ONES _BS_RIGHT dstbit;
      if (shift0 > 0)
        {
	  _BS_word word1 = *psrc++;
	  shift1 = _BS_BITS_PER_WORD - shift0;
	  DOIT(*pdst, (word0 _BS_LEFT shift0) | (word1 _BS_RIGHT shift1), mask);
	  word0 = word1;
        }
      else /* dstbit > srcbit */
        {
	  shift1 = -shift0;
	  shift0 += _BS_BITS_PER_WORD;
	  DOIT(*pdst, word0 _BS_RIGHT shift1, mask);
      }
      pdst++;
      length -= _BS_BITS_PER_WORD - dstbit;

      for ( ; length >= _BS_BITS_PER_WORD; length -= _BS_BITS_PER_WORD)
        {
	  register _BS_word word1 = *psrc++;
	  DOIT_SOLID(*pdst,
		     (word0 _BS_LEFT shift0) | (word1 _BS_RIGHT shift1));
	  pdst++;
	  word0 = word1;
        }
      if (length > 0)
        {
	  _BS_size_t mask = ONES _BS_LEFT (_BS_BITS_PER_WORD - length);
	  word0 = word0 _BS_LEFT shift0;
	  if (length > shift1)
	    word0 = word0 | (*psrc _BS_RIGHT shift1) ;
	  DOIT (*pdst, word0, mask);
        }
    }
  else /* Do the updates in backward direction. */
    {
      _BS_word word0;

      /* Make (psrc, srcbit) and (pdst, dstbit) point to *last* bit. */
      psrc += (srcbit + length  - 1) / _BS_BITS_PER_WORD;
      srcbit = (srcbit + length - 1) % _BS_BITS_PER_WORD;
      pdst += (dstbit + length - 1) / _BS_BITS_PER_WORD;
      dstbit = (dstbit + length - 1) % _BS_BITS_PER_WORD;

      shift0 = srcbit - dstbit;

      word0 = *psrc--;
      mask = ONES _BS_LEFT (_BS_BITS_PER_WORD - 1 - dstbit);
      if (shift0 < 0)
        {
	  _BS_word word1 = *psrc--;
	  shift1 = -shift0;
	  shift0 += _BS_BITS_PER_WORD;
	  DOIT (*pdst, (word0 _BS_RIGHT shift1) | (word1 _BS_LEFT shift0),
		mask);
	  word0 = word1;
        }
      else
        {
	  shift1 = _BS_BITS_PER_WORD - shift0;
	  DOIT(*pdst, word0 _BS_LEFT shift0, mask);
      }
      pdst--;
      length -= dstbit + 1;

      for ( ; length >= _BS_BITS_PER_WORD; length -= _BS_BITS_PER_WORD)
        {
	  register _BS_word word1 = *psrc--;
	  DOIT_SOLID(*pdst,
		     (word0 _BS_RIGHT shift1) | (word1 _BS_LEFT shift0));
	  pdst--;
	  word0 = word1;
        }
      if (length > 0)
        {
	  _BS_size_t mask = ONES _BS_RIGHT (_BS_BITS_PER_WORD - length);
	  word0 = word0 _BS_RIGHT shift1;
	  if (length > shift0)
	    word0 = word0 | (*psrc _BS_LEFT shift0) ;
	  DOIT (*pdst, word0, mask);
        }
    }
 done: ;