]>
git.zerfleddert.de Git - proxmark3-svn/blob - client/reveng/poly.c
2 * Greg Cook, 26/Jul/2016
5 /* CRC RevEng: arbitrary-precision CRC calculator and algorithm finder
6 * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 Gregory Cook
8 * This file is part of CRC RevEng.
10 * CRC RevEng is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
15 * CRC RevEng is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with CRC RevEng. If not, see <https://www.gnu.org/licenses/>.
24 /* 2016-06-27: pcmp() shortcut returns 0 when pointers identical
25 * 2015-07-29: discard leading $, &, 0x from argument to strtop()
26 * 2015-04-03: added direct mode to strtop()
27 * 2014-01-11: added LOFS(), RNDUP()
28 * 2013-09-16: SIZE(), IDX(), OFS() macros bitshift if BMP_POF2
29 * 2013-02-07: conditional non-2^n fix, pmpar() return mask constant type
30 * 2013-01-17: fixed pfirst(), plast() for non-2^n BMP_BIT
31 * 2012-07-16: added pident()
32 * 2012-05-23: added pmpar()
33 * 2012-03-03: internal lookup tables stored better
34 * 2012-03-02: fixed full-width masking in filtop()
35 * 2011-09-06: added prevch()
36 * 2011-08-27: fixed zero test in piter()
37 * 2011-01-17: fixed ANSI C warnings, uses bmp_t type
38 * 2011-01-15: palloc() and praloc() gracefully handle lengths slightly
40 * 2011-01-15: strtop() error on invalid argument. pkchop() special case
41 * when argument all zeroes
42 * 2011-01-14: added pkchop()
43 * 2011-01-04: fixed bogus final length calculation in wide pcrc()
44 * 2011-01-02: faster, more robust prcp()
45 * 2011-01-01: commented functions, full const declarations, all-LUT rev()
46 * 2010-12-26: renamed CRC RevEng
47 * 2010-12-18: removed pmods(), finished pcrc(), added piter()
48 * 2010-12-17: roughed out pcrc(). difficult, etiam aberat musa heri :(
49 * 2010-12-15: added psnorm(), psncmp(); optimised pnorm(); fix to praloc()
50 * 2010-12-14: strtop() resets count between passes
51 * 2010-12-12: added pright()
52 * 2010-12-11: filtop won't read more than length bits
53 * 2010-12-10: finished filtop. 26 public functions
54 * 2010-12-05: finished strtop, pxsubs; unit tests
55 * 2010-12-02: project started
58 /* Note: WELL-FORMED poly_t objects have a valid bitmap pointer pointing
59 * to a malloc()-ed array of at least as many bits as stated in its
60 * length field. Any poly_t with a length of 0 is also a WELL-FORMED
61 * poly_t (whatever value the bitmap pointer has.)
62 * All poly_t objects passed to and from functions must be WELL-FORMED
63 * unless otherwise stated.
65 * CLEAN (or CANONICAL) poly_t objects are WELL-FORMED objects in which
66 * all spare bits in the bitmap word containing the last bit are zero.
67 * (Any excess allocated words will not be accessed.)
69 * SEMI-NORMALISED poly_t objects are CLEAN objects in which the last
70 * bit, at position (length - 1), is one.
72 * NORMALISED poly_t objects are SEMI-NORMALISED objects in which the
75 * pfree() should be called on every poly_t object (including
76 * those returned by functions) after its last use.
77 * As always, free() should be called on every malloc()-ed string after
86 static bmp_t
getwrd(const poly_t poly
, unsigned long iter
);
87 static bmp_t
rev(bmp_t accu
, int bits
);
88 static void prhex(char **spp
, bmp_t bits
, int flags
, int bperhx
);
90 static const poly_t pzero
= PZERO
;
92 /* word number (0..m-1) of var'th bit (0..n-1) */
94 # define IDX(var) ((var) >> BMP_POF2)
96 # define IDX(var) ((var) / BMP_BIT)
99 /* size of polynomial with var bits */
101 # define SIZE(var) ((BMP_BIT - 1UL + (var)) >> BMP_POF2)
103 # define SIZE(var) ((BMP_BIT - 1UL + (var)) / BMP_BIT)
106 /* polynomial length rounded up to BMP_BIT */
108 # define RNDUP(var) (~(BMP_BIT - 1UL) & (BMP_BIT - 1UL + (var)))
110 # define RNDUP(var) ((BMP_BIT - (var) % BMP_BIT) % BMP_BIT + (var))
113 /* bit offset (0..BMP_BIT-1, 0 = LSB) of var'th bit (0..n-1) */
115 # define OFS(var) ((int) ((BMP_BIT - 1UL) & ~(var)))
117 # define OFS(var) ((int) (BMP_BIT - 1UL - (var) % BMP_BIT))
120 /* bit offset (0..BMP_BIT-1, 0 = MSB) of var'th bit (0..n-1) */
122 # define LOFS(var) ((int) ((BMP_BIT - 1UL) & (var)))
124 # define LOFS(var) ((int) ((var) % BMP_BIT))
128 filtop(FILE *input
, unsigned long length
, int flags
, int bperhx
) {
129 /* reads binary data from input into a poly_t until EOF or until
130 * length bits are read. Characters are read until
131 * ceil(bperhx / CHAR_BIT) bits are collected; if P_LTLBYT is
132 * set in flags then the first character contains the LSB,
133 * otherwise the last one does. The least significant bperhx
134 * bits are taken, reflected (if P_REFIN) and appended to the
135 * result, then more characters are read. The maximum number of
137 * floor(length / bperhx) * ceil(bperhx / * CHAR_BIT).
138 * The returned poly_t is CLEAN.
141 bmp_t accu
= BMP_C(0);
142 bmp_t mask
= bperhx
== BMP_BIT
? ~BMP_C(0) : (BMP_C(1) << bperhx
) - BMP_C(1);
143 unsigned long iter
= 0UL, idx
;
144 int cmask
= (1 << CHAR_BIT
) - 1, c
;
147 if(bperhx
== 0) return(poly
);
149 length
-= length
% bperhx
;
150 palloc(&poly
, length
); /* >= 0 */
152 while(iter
< length
&& (c
= fgetc(input
)) != EOF
) {
154 accu
|= (bmp_t
) (c
& cmask
) << count
;
156 accu
= (accu
<< CHAR_BIT
) | (bmp_t
) (c
& cmask
);
158 if(count
>= bperhx
) {
159 /* the low bperhx bits of accu contain bits of the poly.*/
163 accu
= rev(accu
, bperhx
);
166 /* iter >= bperhx > 0 */
167 idx
= IDX(iter
- 1UL);
168 ofs
= OFS(iter
- 1UL);
169 poly
.bitmap
[idx
] |= accu
<< ofs
;
170 if(ofs
+ bperhx
> BMP_BIT
) {
171 poly
.bitmap
[idx
-1] |= accu
>> (BMP_BIT
- ofs
);
173 accu
= BMP_C(0); /* only needed for P_LTLBYT */
181 strtop(const char *string
, int flags
, int bperhx
) {
182 /* Converts a hex or character string to a poly_t.
183 * Each character is converted to a hex nibble yielding 4 bits
184 * unless P_DIRECT, when each character yields CHAR_BIT bits.
185 * Nibbles and characters are accumulated left-to-right
186 * unless P_DIRECT && P_LTLBYT, when they are accumulated
187 * right-to-left without reflection.
188 * As soon as at least bperhx bits are accumulated, the
189 * rightmost bperhx bits are reflected (if P_REFIN)
190 * and appended to the poly. When !P_DIRECT:
191 * bperhx=8 reads hex nibbles in pairs
192 * bperhx=7 reads hex nibbles in pairs and discards
194 * bperhx=4 reads hex nibbles singly
195 * bperhx=3 reads octal
196 * bperhx=1 reads longhand binary
197 * in theory if !P_REFIN, bperhx can be any multiple of 4
199 * The returned poly_t is CLEAN.
202 /* make two passes, one to determine the poly size
203 * one to populate the bitmap
205 unsigned long length
= 1UL, idx
;
207 bmp_t mask
= bperhx
== BMP_BIT
? ~BMP_C(0) : (BMP_C(1) << bperhx
) - BMP_C(1);
208 int pass
, count
, ofs
;
209 int cmask
= (1 << CHAR_BIT
) - 1 , c
;
213 if(bperhx
> BMP_BIT
|| bperhx
<= 0 || string
== NULL
|| *string
== '\0')
216 if(~flags
& P_DIRECT
) {
217 if(*string
== '$' || *string
== '&')
219 else if(*string
== '0'
220 && (string
[1] == 'x' || string
[1] == 'X'))
223 length
= (*string
!= '\0');
225 for(pass
=0; pass
<2 && length
> 0UL; ++pass
) {
231 if(flags
& P_DIRECT
) {
233 accu
|= (bmp_t
) (c
& cmask
) << count
;
235 accu
= (accu
<< CHAR_BIT
) | (bmp_t
) (c
& cmask
);
238 if(c
== ' ' || c
== '\t' || c
== '\r' || c
== '\n') continue;
252 accu
|= (bmp_t
) c
- '0';
279 uerror("invalid character in hexadecimal argument");
283 if(count
>= bperhx
) {
284 /* the low bperhx bits of accu contain bits of the poly.
285 * in pass 0, increment length by bperhx.
286 * in pass 1, put the low bits of accu into the bitmap. */
291 accu
= rev(accu
, bperhx
);
294 /* length >= bperhx > 0 */
295 idx
= IDX(length
- 1);
296 ofs
= OFS(length
- 1);
297 poly
.bitmap
[idx
] |= accu
<< ofs
;
298 if(ofs
+ bperhx
> BMP_BIT
)
299 poly
.bitmap
[idx
-1] |= accu
>> (BMP_BIT
- ofs
);
300 accu
= BMP_C(0); /* only needed for P_LTLBYT */
304 if(pass
== 0) palloc(&poly
, length
);
310 ptostr(const poly_t poly
, int flags
, int bperhx
) {
311 /* Returns a malloc()-ed string containing a hexadecimal
312 * representation of poly. See phxsubs().
314 return(pxsubs(poly
, flags
, bperhx
, 0UL, poly
.length
));
318 pxsubs(const poly_t poly
, int flags
, int bperhx
, unsigned long start
, unsigned long end
) {
319 /* Returns a malloc()-ed string containing a hexadecimal
320 * representation of a portion of poly, from bit offset start to
321 * (end - 1) inclusive. The output is grouped into words of
322 * bperhx bits each. If P_RTJUST then the first word is padded
323 * with zeroes at the MSB end to make a whole number of words,
324 * otherwise the last word is padded at the LSB end. After
325 * justification the bperhx bits of each word are reversed (if
326 * P_REFOUT) and printed as a hex sequence, with words
327 * optionally separated by spaces (P_SPACE).
328 * If end exceeds the length of poly then zero bits are appended
329 * to make up the difference, in which case poly must be CLEAN.
332 unsigned long size
, iter
;
334 bmp_t mask
= bperhx
== BMP_BIT
? ~BMP_C(0) : (BMP_C(1) << bperhx
) - BMP_C(1);
337 if(bperhx
<= 0 || bperhx
> BMP_BIT
) return(NULL
);
339 if(start
> poly
.length
) start
= poly
.length
;
340 if(end
> poly
.length
) end
= poly
.length
;
341 if(end
< start
) end
= start
;
343 cperhx
= (bperhx
+ 3) >> 2;
344 if(flags
& P_SPACE
) ++cperhx
;
346 size
= (end
- start
+ bperhx
- 1UL) / bperhx
;
348 if(!size
|| ~flags
& P_SPACE
) ++size
; /* for trailing null */
350 if(!(sptr
= string
= (char *) malloc(size
)))
351 uerror("cannot allocate memory for string");
354 part
= (int) size
% bperhx
;
355 if(part
&& flags
& P_RTJUST
) {
357 accu
= getwrd(poly
, iter
- 1UL) & ((BMP_C(1) << part
) - BMP_C(1));
359 /* best to reverse over bperhx rather than part, I think
360 * e.g. converting a 7-bit poly to 8-bit little-endian hex
362 accu
= rev(accu
, bperhx
);
363 prhex(&sptr
, accu
, flags
, bperhx
);
364 if(flags
& P_SPACE
&& size
> iter
) *sptr
++ = ' ';
369 while((iter
+=bperhx
) <= end
) {
370 accu
= getwrd(poly
, iter
- 1UL) & mask
;
372 accu
= rev(accu
, bperhx
);
373 prhex(&sptr
, accu
, flags
, bperhx
);
374 if(flags
& P_SPACE
&& size
> iter
) *sptr
++ = ' ';
377 if(part
&& ~flags
& P_RTJUST
) {
378 accu
= getwrd(poly
, end
- 1UL);
380 accu
= rev(accu
, part
);
382 accu
= accu
<< (bperhx
- part
) & mask
;
383 prhex(&sptr
, accu
, flags
, bperhx
);
390 pclone(const poly_t poly
) {
391 /* Returns a freestanding copy of poly. Does not clean poly or
394 poly_t clone
= PZERO
;
401 pcpy(poly_t
*dest
, const poly_t src
) {
402 /* Assigns (copies) src into dest. Does not clean src or dest.
404 unsigned long iter
, idx
;
406 praloc(dest
, src
.length
);
407 for(iter
=0UL, idx
=0UL; iter
< src
.length
; iter
+= BMP_BIT
, ++idx
)
408 dest
->bitmap
[idx
] = src
.bitmap
[idx
];
412 pcanon(poly_t
*poly
) {
413 /* Converts poly into a CLEAN object by freeing unused bitmap words
414 * and clearing any bits in the last word beyond the last bit.
415 * The length field has absolute priority over the contents of the bitmap.
416 * Canonicalisation differs from normalisation in that leading and trailing
417 * zero terms are significant and preserved.
418 * poly may or may not be WELL-FORMED.
420 praloc(poly
, poly
->length
);
424 pnorm(poly_t
*poly
) {
425 /* Converts poly into a NORMALISED object by removing leading
426 * and trailing zeroes, so that the polynomial starts and ends
427 * with significant terms.
428 * poly may or may not be WELL-FORMED.
432 /* call pcanon() here so pfirst() and plast() return the correct
436 first
= pfirst(*poly
);
438 pshift(poly
, *poly
, 0UL, first
, plast(*poly
), 0UL);
440 praloc(poly
, plast(*poly
));
444 psnorm(poly_t
*poly
) {
445 /* Converts poly into a SEMI-NORMALISED object by removing
446 * trailing zeroes, so that the polynomial ends with a
448 * poly may or may not be WELL-FORMED.
451 /* call pcanon() here so plast() returns the correct result */
453 praloc(poly
, plast(*poly
));
457 pchop(poly_t
*poly
) {
458 /* Normalise poly, then chop off the highest significant term
459 * (produces a SEMI-NORMALISED object). poly becomes a suitable
460 * divisor for pcrc().
461 * poly may or may not be WELL-FORMED.
464 /* call pcanon() here so pfirst() and plast() return correct
468 pshift(poly
, *poly
, 0UL, pfirst(*poly
) + 1UL, plast(*poly
), 0UL);
472 pkchop(poly_t
*poly
) {
473 /* Convert poly from Koopman notation to chopped form (produces
474 * a SEMI-NORMALISED object). poly becomes a suitable divisor
476 * poly may or may not be WELL-FORMED.
480 /* call pcanon() here so pfirst() returns the correct result */
482 first
= pfirst(*poly
);
483 if(first
>= poly
->length
) {
487 pshift(poly
, *poly
, 0UL, first
+ 1UL, poly
->length
, 1UL);
492 plen(const poly_t poly
) {
493 /* Return length of polynomial.
494 * poly may or may not be WELL-FORMED.
500 pcmp(const poly_t
*a
, const poly_t
*b
) {
501 /* Compares poly_t objects for identical sizes and contents.
502 * a and b must be CLEAN.
503 * Defines a total order relation for sorting, etc. although
504 * mathematically, polynomials of equal degree are no greater or
505 * less than one another.
510 if(!a
|| !b
) return(!b
- !a
);
511 if(a
->length
< b
->length
) return(-1);
512 if(a
->length
> b
->length
) return(1);
517 for(iter
=0UL; iter
< a
->length
; iter
+= BMP_BIT
) {
520 if(*aptr
++ > *bptr
++)
527 psncmp(const poly_t
*a
, const poly_t
*b
) {
528 /* Compares polys for identical effect, i.e. as though the
529 * shorter poly were padded with zeroes to the length of the
531 * a and b must still be CLEAN, therefore psncmp() is *not*
532 * identical to pcmp() on semi-normalised polys as psnorm()
533 * clears the slack space.
535 unsigned long length
, iter
, idx
;
537 if(!a
|| !b
) return(!b
- !a
);
538 length
= (a
->length
> b
->length
) ? a
->length
: b
->length
;
539 for(iter
= 0UL, idx
= 0UL; iter
< length
; iter
+= BMP_BIT
, ++idx
) {
540 aword
= (iter
< a
->length
) ? a
->bitmap
[idx
] : BMP_C(0);
541 bword
= (iter
< b
->length
) ? b
->bitmap
[idx
] : BMP_C(0);
552 ptst(const poly_t poly
) {
553 /* Tests whether a polynomial equals zero. Returns 0 if equal,
554 * a nonzero value otherwise.
555 * poly must be CLEAN.
559 if(!poly
.bitmap
) return(0);
560 for(iter
= 0UL, bptr
= poly
.bitmap
; iter
< poly
.length
; iter
+= BMP_BIT
)
561 if(*bptr
++) return(1);
566 pfirst(const poly_t poly
) {
567 /* Returns the index of the first nonzero term in poly. If none
568 * is found, returns the length of poly.
569 * poly must be CLEAN.
571 unsigned long idx
= 0UL, size
= SIZE(poly
.length
);
572 bmp_t accu
= BMP_C(0); /* initialiser for Acorn C */
573 unsigned int probe
= BMP_SUB
, ofs
= 0;
575 while(idx
< size
&& !(accu
= poly
.bitmap
[idx
])) ++idx
;
576 if(idx
>= size
) return(poly
.length
);
579 while((ofs
| probe
) >= (unsigned int) BMP_BIT
) probe
>>= 1;
581 if(accu
>> (ofs
| probe
)) ofs
|= probe
;
585 return(BMP_BIT
- 1UL - ofs
+ idx
* BMP_BIT
);
589 plast(const poly_t poly
) {
590 /* Returns 1 plus the index of the last nonzero term in poly.
591 * If none is found, returns zero.
592 * poly must be CLEAN.
594 unsigned long idx
, size
= SIZE(poly
.length
);
596 unsigned int probe
= BMP_SUB
, ofs
= 0;
598 if(!poly
.length
) return(0UL);
600 while(idx
&& !(accu
= poly
.bitmap
[idx
])) --idx
;
601 if(!idx
&& !(accu
= poly
.bitmap
[idx
])) return(0UL);
602 /* now accu == poly.bitmap[idx] and contains last significant term */
605 while((ofs
| probe
) >= (unsigned int) BMP_BIT
) probe
>>= 1;
607 if(accu
<< (ofs
| probe
)) ofs
|= probe
;
611 return(idx
* BMP_BIT
+ ofs
+ 1UL);
615 psubs(const poly_t src
, unsigned long head
, unsigned long start
, unsigned long end
, unsigned long tail
) {
617 pshift(&dest
, src
, head
, start
, end
, tail
);
622 pright(poly_t
*poly
, unsigned long length
) {
623 /* Trims or extends poly to length at the left edge, prepending
624 * zeroes if necessary. Analogous to praloc() except the
625 * rightmost terms of poly are preserved.
626 * On entry, poly may or may not be WELL-FORMED.
627 * On exit, poly is CLEAN.
630 if(length
> poly
->length
)
631 pshift(poly
, *poly
, length
- poly
->length
, 0UL, poly
->length
, 0UL);
632 else if(length
< poly
->length
)
633 pshift(poly
, *poly
, 0UL, poly
->length
- length
, poly
->length
, 0UL);
635 praloc(poly
, poly
->length
);
639 pshift(poly_t
*dest
, const poly_t src
, unsigned long head
, unsigned long start
, unsigned long end
, unsigned long tail
) {
640 /* copies bits start to end-1 of src to dest, plus the number of leading and trailing zeroes given by head and tail.
641 * end may exceed the length of src in which case more zeroes are appended.
642 * dest may point to src, in which case the poly is edited in place.
643 * On exit, dest is CLEAN.
646 unsigned long length
, fulllength
, size
, fullsize
, iter
, idx
, datidx
;
647 /* condition inputs; end, head and tail may be any value */
648 if(end
< start
) end
= start
;
650 length
= end
- start
+ head
;
651 fulllength
= length
+ tail
;
652 if(fulllength
> src
.length
)
653 praloc(dest
, fulllength
);
655 praloc(dest
, src
.length
);
657 /* number of words in new poly */
659 fullsize
= SIZE(fulllength
);
660 /* array index of first word ending up with source material */
663 if(head
> start
&& end
> start
) {
664 /* shifting right, size > 0 */
665 /* index of the source bit ending up in the LSB of the last word
666 * size * BMP_BIT >= length > head > 0 */
667 iter
= size
* BMP_BIT
- head
- 1UL;
668 for(idx
= size
- 1UL; idx
> datidx
; iter
-= BMP_BIT
, --idx
)
669 dest
->bitmap
[idx
] = getwrd(src
, iter
);
670 dest
->bitmap
[idx
] = getwrd(src
, iter
);
671 /* iter == size * BMP_BIT - head - 1 - BMP_BIT * (size - 1 - datidx)
672 * == BMP_BIT * (size - size + 1 + datidx) - head - 1
673 * == BMP_BIT * (1 + head / BMP_BIT) - head - 1
674 * == BMP_BIT + head - head % BMP_BIT - head - 1
675 * == BMP_BIT - head % BMP_BIT - 1
678 } else if(head
<= start
) {
679 /* shifting left or copying */
680 /* index of the source bit ending up in the LSB of bitmap[idx] */
681 iter
= start
- head
+ BMP_BIT
- 1UL;
682 for(idx
= datidx
; idx
< size
; iter
+= BMP_BIT
, ++idx
)
683 dest
->bitmap
[idx
] = getwrd(src
, iter
);
687 for(idx
= 0UL; idx
< datidx
; ++idx
)
688 dest
->bitmap
[idx
] = BMP_C(0);
690 dest
->bitmap
[datidx
] &= ~BMP_C(0) >> LOFS(head
);
694 dest
->bitmap
[size
- 1UL] &= ~(~BMP_C(0) >> LOFS(length
));
695 for(idx
= size
; idx
< fullsize
; ++idx
)
696 dest
->bitmap
[idx
] = BMP_C(0);
698 /* call praloc to shrink poly if required */
699 if(dest
->length
> fulllength
)
700 praloc(dest
, fulllength
);
704 ppaste(poly_t
*dest
, const poly_t src
, unsigned long skip
, unsigned long seek
, unsigned long end
, unsigned long fulllength
) {
705 /* pastes terms of src, starting from skip, to positions seek to end-1 of dest
706 * then sets length of dest to fulllength (>= end)
707 * to paste n terms of src, give end = seek + n
708 * to truncate dest at end of paste, set fulllength = end
709 * to avoid truncating, set fulllength = plen(*dest)
710 * dest may point to src, in which case the poly is edited in place.
711 * src must be CLEAN in the case that the end is overrun.
712 * On exit, dest is CLEAN.
715 unsigned long seekidx
, endidx
, iter
;
717 if(end
< seek
) end
= seek
;
718 if(fulllength
< end
) fulllength
= end
;
720 /* expand dest if necessary. don't shrink as dest may be src */
721 if(fulllength
> dest
->length
)
722 praloc(dest
, fulllength
);
726 /* index of the source bit ending up in the LSB of the first modified word */
727 iter
= skip
+ seekofs
;
728 if(seekidx
== endidx
) {
729 /* paste affects one word (traps end = seek case) */
730 mask
= ((BMP_C(1) << seekofs
) - (BMP_C(1) << OFS(end
))) << 1;
731 dest
->bitmap
[seekidx
] = (dest
->bitmap
[seekidx
] & ~mask
) | (getwrd(src
, iter
) & mask
);
732 } else if(seek
> skip
) {
734 /* index of the source bit ending up in the LSB of the last modified word */
735 iter
+= (endidx
- seekidx
) * BMP_BIT
;
736 mask
= ~BMP_C(0) >> LOFS(end
);
737 dest
->bitmap
[endidx
] = (dest
->bitmap
[endidx
] & mask
) | (getwrd(src
, iter
) & ~mask
);
738 for(iter
-= BMP_BIT
, --endidx
; endidx
> seekidx
; iter
-= BMP_BIT
, --endidx
)
739 dest
->bitmap
[endidx
] = getwrd(src
, iter
);
740 mask
= ~BMP_C(0) >> LOFS(seek
);
741 dest
->bitmap
[endidx
] = (dest
->bitmap
[endidx
] & ~mask
) | (getwrd(src
, iter
) & mask
);
742 /* iter == skip + seekofs + (endidx - seekidx) * BMP_BIT - BMP_BIT * (endidx - seekidx)
743 * == skip + seekofs + BMP_BIT * (endidx - seekidx - endidx + seekidx)
748 /* shifting left or copying */
749 mask
= ~BMP_C(0) >> LOFS(seek
);
750 dest
->bitmap
[seekidx
] = (dest
->bitmap
[seekidx
] & ~mask
) | (getwrd(src
, iter
) & mask
);
751 for(iter
+= BMP_BIT
, ++seekidx
; seekidx
< endidx
; iter
+= BMP_BIT
, ++seekidx
)
752 dest
->bitmap
[seekidx
] = getwrd(src
, iter
);
753 mask
= ~BMP_C(0) >> LOFS(end
);
754 dest
->bitmap
[seekidx
] = (dest
->bitmap
[seekidx
] & mask
) | (getwrd(src
, iter
) & ~mask
);
756 /* shrink poly if required */
757 if(dest
->length
> fulllength
)
758 praloc(dest
, fulllength
);
762 pdiff(poly_t
*dest
, const poly_t src
, unsigned long ofs
) {
763 /* Subtract src from dest (modulo 2) at offset ofs.
764 * In modulo 2 arithmetic, subtraction is equivalent to addition
765 * We include an alias for those who wish to retain the distinction
766 * src and dest must be CLEAN.
768 psum(dest
, src
, ofs
);
772 psum(poly_t
*dest
, const poly_t src
, unsigned long ofs
) {
773 /* Adds src to dest (modulo 2) at offset ofs.
774 * When ofs == dest->length, catenates src on to dest.
775 * src and dest must be CLEAN.
777 unsigned long fulllength
, idx
, iter
, end
;
779 fulllength
= ofs
+ src
.length
;
780 if(fulllength
> dest
->length
)
781 praloc(dest
, fulllength
);
782 /* array index of first word in dest to be modified */
784 /* index of bit in src to be added to LSB of dest->bitmap[idx] */
786 /* stop value for iter */
787 end
= BMP_BIT
- 1UL + src
.length
;
788 for(; iter
< end
; iter
+= BMP_BIT
, ++idx
)
789 dest
->bitmap
[idx
] ^= getwrd(src
, iter
);
794 /* Reverse or reciprocate a polynomial.
795 * On exit, poly is CLEAN.
797 unsigned long leftidx
= 0UL, rightidx
= SIZE(poly
->length
);
798 unsigned long ofs
= LOFS(BMP_BIT
- LOFS(poly
->length
));
799 unsigned long fulllength
= poly
->length
+ ofs
;
803 /* removable optimisation */
804 if(poly
->length
< (unsigned long) BMP_BIT
) {
805 *poly
->bitmap
= rev(*poly
->bitmap
>> ofs
, (int) poly
->length
) << ofs
;
809 /* claim remaining bits of last word (as we use public function pshift()) */
810 poly
->length
= fulllength
;
812 /* reverse and swap words in the array, leaving it right-justified */
813 while(leftidx
< rightidx
) {
815 accu
= rev(poly
->bitmap
[--rightidx
], BMP_BIT
);
816 poly
->bitmap
[rightidx
] = rev(poly
->bitmap
[leftidx
], BMP_BIT
);
817 poly
->bitmap
[leftidx
++] = accu
;
819 /* shift polynomial to left edge if required */
821 pshift(poly
, *poly
, 0UL, ofs
, fulllength
, 0UL);
825 prevch(poly_t
*poly
, int bperhx
) {
826 /* Reverse each group of bperhx bits in a polynomial.
827 * Does not clean poly.
829 unsigned long iter
= 0, idx
, ofs
;
832 if(bperhx
< 2 || bperhx
> BMP_BIT
)
834 if(poly
->length
% bperhx
)
835 praloc(poly
, bperhx
- (poly
->length
% bperhx
) + poly
->length
);
836 mask
= ~BMP_C(0) >> (BMP_BIT
- bperhx
);
837 for(iter
= (unsigned long) (bperhx
- 1); iter
< poly
->length
; iter
+= bperhx
) {
838 accu
= getwrd(*poly
, iter
) & mask
;
839 accu
^= rev(accu
, bperhx
);
842 poly
->bitmap
[idx
] ^= accu
<< ofs
;
843 if(ofs
+ bperhx
> (unsigned int) BMP_BIT
)
844 /* (BMP_BIT - 1UL - (iter) % BMP_BIT) + bperhx > BMP_BIT
845 * (-1UL - (iter) % BMP_BIT) + bperhx > 0
846 * (- (iter % BMP_BIT)) + bperhx > 1
847 * - (iter % BMP_BIT) > 1 - bperhx
848 * iter % BMP_BIT < bperhx - 1, iter >= bperhx - 1
852 poly
->bitmap
[idx
-1] ^= accu
>> (BMP_BIT
- ofs
);
858 /* Reciprocate a chopped polynomial. Use prev() on whole
860 * On exit, poly is SEMI-NORMALISED.
864 praloc(poly
, RNDUP(poly
->length
));
866 first
= pfirst(*poly
);
867 if(first
>= poly
->length
) {
871 pshift(poly
, *poly
, 0UL, first
+ 1UL, poly
->length
, 1UL);
877 /* Invert a polynomial, i.e. add 1 (modulo 2) to the coefficient of each term
878 * on exit, poly is CLEAN.
880 unsigned long idx
, size
= SIZE(poly
->length
);
882 for(idx
= 0UL; idx
<size
; ++idx
)
883 poly
->bitmap
[idx
] = ~poly
->bitmap
[idx
];
884 if(LOFS(poly
->length
))
885 poly
->bitmap
[size
- 1UL] &= ~(~BMP_C(0) >> LOFS(poly
->length
));
889 pmod(const poly_t dividend
, const poly_t divisor
) {
890 /* Divide dividend by normalised divisor and return the remainder
891 * This function generates a temporary 'chopped' divisor for pcrc()
892 * If calling repeatedly with a constant divisor, produce a chopped copy
893 * with pchop() and call pcrc() directly for higher efficiency.
894 * dividend and divisor must be CLEAN.
897 /* perhaps generate an error if divisor is zero */
898 poly_t subdivisor
= psubs(divisor
, 0UL, pfirst(divisor
) + 1UL, plast(divisor
), 0UL);
899 poly_t result
= pcrc(dividend
, subdivisor
, pzero
, pzero
, 0);
905 pcrc(const poly_t message
, const poly_t divisor
, const poly_t init
, const poly_t xorout
, int flags
) {
906 /* Divide message by divisor and return the remainder.
907 * init is added to divisor, highest terms aligned, before
909 * xorout is added to the remainder, highest terms aligned.
910 * If P_MULXN is set in flags, message is multiplied by x^n
911 * (i.e. trailing zeroes equal to the CRC width are appended)
912 * before adding init and division. Set P_MULXN for most CRC
914 * All inputs must be CLEAN.
915 * If all inputs are CLEAN, the returned poly_t will be CLEAN.
917 unsigned long max
= 0UL, iter
, ofs
, resiter
;
918 bmp_t probe
, rem
, dvsr
, *rptr
, *sptr
;
919 const bmp_t
*bptr
, *eptr
;
920 poly_t result
= PZERO
;
923 max
= message
.length
;
924 else if(message
.length
> divisor
.length
)
925 max
= message
.length
- divisor
.length
;
927 eptr
=message
.bitmap
+SIZE(message
.length
);
928 probe
=~(~BMP_C(0) >> 1);
929 if(divisor
.length
<= (unsigned long) BMP_BIT
930 && init
.length
<= (unsigned long) BMP_BIT
) {
931 rem
= init
.length
? *init
.bitmap
: BMP_C(0);
932 dvsr
= divisor
.length
? *divisor
.bitmap
: BMP_C(0);
933 for(iter
= 0UL, ofs
= 0UL; iter
< max
; ++iter
, --ofs
) {
939 rem
= (rem
<< 1) ^ dvsr
;
944 /* max < message.length */
945 rem
^= *bptr
>> OFS(BMP_BIT
- 1UL + max
);
946 if(init
.length
> max
&& init
.length
- max
> divisor
.length
) {
947 palloc(&result
, init
.length
- max
);
948 *result
.bitmap
= rem
;
949 } else if(divisor
.length
) {
950 palloc(&result
, divisor
.length
);
951 *result
.bitmap
= rem
;
954 /* allocate maximum size plus one word for shifted divisors and one word containing zero.
955 * This also ensures that result[1] exists
957 palloc(&result
, (init
.length
> divisor
.length
? init
.length
: divisor
.length
) + (unsigned long) (BMP_BIT
<< 1));
958 /*if there is content in init, there will be an extra word in result to clear it */
959 psum(&result
, init
, 0UL);
961 *result
.bitmap
^= *bptr
++;
962 for(iter
= 0UL, ofs
= 0UL; iter
< max
; ++iter
, probe
>>= 1) {
964 probe
= ~(~BMP_C(0) >> 1);
966 sptr
= rptr
= result
.bitmap
;
968 /* iter < max <= message.length, so bptr is valid
969 * shift result one word to the left, splicing in a message word
970 * and clearing the last active word
972 *rptr
++ = *sptr
++ ^ *bptr
++;
973 for(resiter
= (unsigned long) (BMP_BIT
<< 1); resiter
< result
.length
; resiter
+= BMP_BIT
)
977 if(*result
.bitmap
& probe
)
978 psum(&result
, divisor
, ofs
);
980 rptr
= result
.bitmap
;
984 /* 0 <= ofs <= BMP_BIT, location of the first bit of the result */
985 pshift(&result
, result
, 0UL, ofs
, (init
.length
> max
+ divisor
.length
? init
.length
- max
- divisor
.length
: 0UL) + divisor
.length
+ ofs
, 0UL);
987 psum(&result
, xorout
, 0UL);
992 piter(poly_t
*poly
) {
993 /* Replace poly with the 'next' polynomial of equal length.
994 * Returns zero if the next polynomial is all zeroes, a nonzero
996 * Does not clean poly.
999 if(!poly
->length
) return(0);
1001 bptr
= poly
->bitmap
+ IDX(poly
->length
- 1UL);
1002 *bptr
+= BMP_C(1) << OFS(poly
->length
- 1UL);
1003 while(bptr
!= poly
->bitmap
&& !*bptr
)
1005 return(*bptr
!= BMP_C(0));
1009 palloc(poly_t
*poly
, unsigned long length
) {
1010 /* Replaces poly with a CLEAN object of the specified length,
1011 * consisting of all zeroes.
1012 * It is safe to call with length = 0, in which case the object
1014 * poly may or may not be WELL-FORMED.
1015 * On exit, poly is CLEAN.
1017 unsigned long size
= SIZE(length
);
1021 poly
->bitmap
= NULL
;
1024 size
= IDX(length
) + 1UL;
1025 poly
->bitmap
= (bmp_t
*) calloc(size
, sizeof(bmp_t
));
1027 poly
->length
= length
;
1029 uerror("cannot allocate memory for poly");
1033 pfree(poly_t
*poly
) {
1034 /* Frees poly's bitmap storage and sets poly equal to the empty
1035 * polynomial (PZERO).
1036 * poly may or may not be WELL-FORMED.
1037 * On exit, poly is CLEAN.
1040 /* palloc(poly, 0UL); */
1044 poly
->bitmap
= NULL
;
1048 praloc(poly_t
*poly
, unsigned long length
) {
1049 /* Trims or extends poly to length at the right edge, appending
1050 * zeroes if necessary.
1051 * On entry, poly may or may not be WELL-FORMED.
1052 * On exit, poly is CLEAN.
1054 unsigned long oldsize
, size
= SIZE(length
);
1059 poly
->bitmap
= NULL
;
1063 size
= IDX(length
) + 1UL;
1066 oldsize
= SIZE(poly
->length
);
1068 /* reallocate if array pointer is null or array resized */
1069 poly
->bitmap
= (bmp_t
*) realloc((void *)poly
->bitmap
, size
* sizeof(bmp_t
));
1071 if(poly
->length
< length
) {
1072 /* poly->length >= 0, length > 0, size > 0.
1073 * poly expanded. clear old last word and all new words
1075 if(LOFS(poly
->length
))
1076 poly
->bitmap
[oldsize
- 1UL] &= ~(~BMP_C(0) >> LOFS(poly
->length
));
1077 while(oldsize
< size
)
1078 poly
->bitmap
[oldsize
++] = BMP_C(0);
1079 } else if(LOFS(length
))
1080 /* poly->length >= length > 0.
1081 * poly shrunk. clear new last word
1083 poly
->bitmap
[size
- 1UL] &= ~(~BMP_C(0) >> LOFS(length
));
1084 poly
->length
= length
;
1086 uerror("cannot reallocate memory for poly");
1090 pmpar(const poly_t poly
, const poly_t mask
) {
1091 /* Return even parity of poly masked with mask.
1092 * Poly and mask must be CLEAN.
1094 bmp_t res
= BMP_C(0);
1096 const bmp_t
*pptr
= poly
.bitmap
, *mptr
= mask
.bitmap
;
1097 const bmp_t
*const pend
= poly
.bitmap
+ SIZE(poly
.length
);
1098 const bmp_t
*const mend
= mask
.bitmap
+ SIZE(mask
.length
);
1100 while(pptr
< pend
&& mptr
< mend
)
1101 res
^= *pptr
++ & *mptr
++;
1106 return((int) (res
& BMP_C(1)));
1110 pident(const poly_t a
, const poly_t b
) {
1111 /* Return nonzero if a and b have the same length
1112 * and point to the same bitmap.
1113 * a and b need not be CLEAN.
1115 return(a
.length
== b
.length
&& a
.bitmap
== b
.bitmap
);
1118 /* Private functions */
1121 getwrd(const poly_t poly
, unsigned long iter
) {
1122 /* Fetch unaligned word from poly where LSB of result is
1123 * bit iter of the bitmap (counting from zero). If iter exceeds
1124 * the length of poly then zeroes are appended as necessary.
1125 * Factored from ptostr().
1126 * poly must be CLEAN.
1128 bmp_t accu
= BMP_C(0);
1129 unsigned long idx
, size
;
1134 size
= SIZE(poly
.length
);
1137 accu
|= poly
.bitmap
[idx
] >> ofs
;
1138 if(idx
&& idx
<= size
&& ofs
> 0)
1139 accu
|= poly
.bitmap
[idx
- 1UL] << (BMP_BIT
- ofs
);
1144 rev(bmp_t accu
, int bits
) {
1145 /* Returns the bitmap word argument with the given number of
1146 * least significant bits reversed and the rest cleared.
1148 static const unsigned char revtab
[256] = {
1149 0x00,0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0,
1150 0x10,0x90,0x50,0xd0,0x30,0xb0,0x70,0xf0,
1151 0x08,0x88,0x48,0xc8,0x28,0xa8,0x68,0xe8,
1152 0x18,0x98,0x58,0xd8,0x38,0xb8,0x78,0xf8,
1153 0x04,0x84,0x44,0xc4,0x24,0xa4,0x64,0xe4,
1154 0x14,0x94,0x54,0xd4,0x34,0xb4,0x74,0xf4,
1155 0x0c,0x8c,0x4c,0xcc,0x2c,0xac,0x6c,0xec,
1156 0x1c,0x9c,0x5c,0xdc,0x3c,0xbc,0x7c,0xfc,
1157 0x02,0x82,0x42,0xc2,0x22,0xa2,0x62,0xe2,
1158 0x12,0x92,0x52,0xd2,0x32,0xb2,0x72,0xf2,
1159 0x0a,0x8a,0x4a,0xca,0x2a,0xaa,0x6a,0xea,
1160 0x1a,0x9a,0x5a,0xda,0x3a,0xba,0x7a,0xfa,
1161 0x06,0x86,0x46,0xc6,0x26,0xa6,0x66,0xe6,
1162 0x16,0x96,0x56,0xd6,0x36,0xb6,0x76,0xf6,
1163 0x0e,0x8e,0x4e,0xce,0x2e,0xae,0x6e,0xee,
1164 0x1e,0x9e,0x5e,0xde,0x3e,0xbe,0x7e,0xfe,
1165 0x01,0x81,0x41,0xc1,0x21,0xa1,0x61,0xe1,
1166 0x11,0x91,0x51,0xd1,0x31,0xb1,0x71,0xf1,
1167 0x09,0x89,0x49,0xc9,0x29,0xa9,0x69,0xe9,
1168 0x19,0x99,0x59,0xd9,0x39,0xb9,0x79,0xf9,
1169 0x05,0x85,0x45,0xc5,0x25,0xa5,0x65,0xe5,
1170 0x15,0x95,0x55,0xd5,0x35,0xb5,0x75,0xf5,
1171 0x0d,0x8d,0x4d,0xcd,0x2d,0xad,0x6d,0xed,
1172 0x1d,0x9d,0x5d,0xdd,0x3d,0xbd,0x7d,0xfd,
1173 0x03,0x83,0x43,0xc3,0x23,0xa3,0x63,0xe3,
1174 0x13,0x93,0x53,0xd3,0x33,0xb3,0x73,0xf3,
1175 0x0b,0x8b,0x4b,0xcb,0x2b,0xab,0x6b,0xeb,
1176 0x1b,0x9b,0x5b,0xdb,0x3b,0xbb,0x7b,0xfb,
1177 0x07,0x87,0x47,0xc7,0x27,0xa7,0x67,0xe7,
1178 0x17,0x97,0x57,0xd7,0x37,0xb7,0x77,0xf7,
1179 0x0f,0x8f,0x4f,0xcf,0x2f,0xaf,0x6f,0xef,
1180 0x1f,0x9f,0x5f,0xdf,0x3f,0xbf,0x7f,0xff
1182 bmp_t result
= BMP_C(0);
1185 result
= result
<< 8 | revtab
[accu
& 0xff];
1188 result
= result
<< bits
| (bmp_t
) (revtab
[accu
& 0xff] >> (8 - bits
));
1193 prhex(char **spp
, bmp_t bits
, int flags
, int bperhx
) {
1194 /* Appends a hexadecimal string representing the bperhx least
1195 * significant bits of bits to an external string.
1196 * spp points to a character pointer that in turn points to the
1197 * end of a hex string being built. prhex() advances this
1198 * second pointer by the number of characters written.
1199 * The unused MSBs of bits MUST be cleared.
1200 * Set P_UPPER in flags to write A-F in uppercase.
1202 static const char hex
[] = "0123456789abcdef0123456789ABCDEF";
1203 const int upper
= (flags
& P_UPPER
? 0x10 : 0);
1205 bperhx
-= ((bperhx
+ 3) & 3) + 1;
1206 *(*spp
)++ = hex
[(bits
>> bperhx
& BMP_C(0xf)) | upper
];