renamed 'hf mfdes readdata, writedata' to 'read/write'
[RRG-proxmark3.git] / client / deps / reveng / poly.c
blob44f5709f4c548e0571e8bcfefbfe4780c187ff5e
1 /* poly.c
2 * Greg Cook, 23/Feb/2019
3 */
5 /* CRC RevEng: arbitrary-precision CRC calculator and algorithm finder
6 * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018,
7 * 2019 Gregory Cook
9 * This file is part of CRC RevEng.
11 * CRC RevEng is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
16 * CRC RevEng is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with CRC RevEng. If not, see <https://www.gnu.org/licenses/>.
25 /* 2017-11-28: added braces, redundant statement skipped in prev()
26 * 2016-06-27: pcmp() shortcut returns 0 when pointers identical
27 * 2015-07-29: discard leading $, &, 0x from argument to strtop()
28 * 2015-04-03: added direct mode to strtop()
29 * 2014-01-11: added LOFS(), RNDUP()
30 * 2013-09-16: SIZE(), IDX(), OFS() macros bitshift if BMP_POF2
31 * 2013-02-07: conditional non-2^n fix, pmpar() return mask constant type
32 * 2013-01-17: fixed pfirst(), plast() for non-2^n BMP_BIT
33 * 2012-07-16: added pident()
34 * 2012-05-23: added pmpar()
35 * 2012-03-03: internal lookup tables stored better
36 * 2012-03-02: fixed full-width masking in filtop()
37 * 2011-09-06: added prevch()
38 * 2011-08-27: fixed zero test in piter()
39 * 2011-01-17: fixed ANSI C warnings, uses bmp_t type
40 * 2011-01-15: palloc() and praloc() gracefully handle lengths slightly
41 * less than ULONG_MAX
42 * 2011-01-15: strtop() error on invalid argument. pkchop() special case
43 * when argument all zeroes
44 * 2011-01-14: added pkchop()
45 * 2011-01-04: fixed bogus final length calculation in wide pcrc()
46 * 2011-01-02: faster, more robust prcp()
47 * 2011-01-01: commented functions, full const declarations, all-LUT rev()
48 * 2010-12-26: renamed CRC RevEng
49 * 2010-12-18: removed pmods(), finished pcrc(), added piter()
50 * 2010-12-17: roughed out pcrc(). difficult, etiam aberat musa heri :(
51 * 2010-12-15: added psnorm(), psncmp(); optimised pnorm(); fix to praloc()
52 * 2010-12-14: strtop() resets count between passes
53 * 2010-12-12: added pright()
54 * 2010-12-11: filtop won't read more than length bits
55 * 2010-12-10: finished filtop. 26 public functions
56 * 2010-12-05: finished strtop, pxsubs; unit tests
57 * 2010-12-02: project started
60 /* Note: WELL-FORMED poly_t objects have a valid bitmap pointer pointing
61 * to a malloc()-ed array of at least as many bits as stated in its
62 * length field. Any poly_t with a length of 0 is also a WELL-FORMED
63 * poly_t (whatever value the bitmap pointer has.)
64 * All poly_t objects passed to and from functions must be WELL-FORMED
65 * unless otherwise stated.
67 * CLEAN (or CANONICAL) poly_t objects are WELL-FORMED objects in which
68 * all spare bits in the bitmap word containing the last bit are zero.
69 * (Any excess allocated words will not be accessed.)
71 * SEMI-NORMALISED poly_t objects are CLEAN objects in which the last
72 * bit, at position (length - 1), is one.
74 * NORMALISED poly_t objects are SEMI-NORMALISED objects in which the
75 * first bit is one.
77 * pfree() should be called on every poly_t object (including
78 * those returned by functions) after its last use.
79 * As always, free() should be called on every malloc()-ed string after
80 * its last use.
83 #include <limits.h>
84 #include <stdio.h>
85 #include <stdlib.h>
86 #include "reveng.h"
88 static bmp_t getwrd(const poly_t poly, unsigned long iter);
89 static bmp_t rev(bmp_t accu, int bits);
90 static void prhex(char **spp, bmp_t bits, int flags, int bperhx);
92 static const poly_t pzero = PZERO;
94 /* word number (0..m-1) of var'th bit (0..n-1) */
95 #if BMP_POF2 >= 5
96 # define IDX(var) ((var) >> BMP_POF2)
97 #else
98 # define IDX(var) ((var) / BMP_BIT)
99 #endif
101 /* size of polynomial with var bits */
102 #if BMP_POF2 >= 5
103 # define SIZE(var) ((BMP_BIT - 1UL + (var)) >> BMP_POF2)
104 #else
105 # define SIZE(var) ((BMP_BIT - 1UL + (var)) / BMP_BIT)
106 #endif
108 /* polynomial length rounded up to BMP_BIT */
109 #ifdef BMP_POF2
110 # define RNDUP(var) (~(BMP_BIT - 1UL) & (BMP_BIT - 1UL + (var)))
111 #else
112 # define RNDUP(var) ((BMP_BIT - (var) % BMP_BIT) % BMP_BIT + (var))
113 #endif
115 /* bit offset (0..BMP_BIT-1, 0 = LSB) of var'th bit (0..n-1) */
116 #ifdef BMP_POF2
117 # define OFS(var) ((int) ((BMP_BIT - 1UL) & ~(var)))
118 #else
119 # define OFS(var) ((int) (BMP_BIT - 1UL - (var) % BMP_BIT))
120 #endif
122 /* bit offset (0..BMP_BIT-1, 0 = MSB) of var'th bit (0..n-1) */
123 #ifdef BMP_POF2
124 # define LOFS(var) ((int) ((BMP_BIT - 1UL) & (var)))
125 #else
126 # define LOFS(var) ((int) ((var) % BMP_BIT))
127 #endif
129 poly_t
130 filtop(FILE *input, unsigned long length, int flags, int bperhx) {
131 /* reads binary data from input into a poly_t until EOF or until
132 * length bits are read. Characters are read until
133 * ceil(bperhx / CHAR_BIT) bits are collected; if P_LTLBYT is
134 * set in flags then the first character contains the LSB,
135 * otherwise the last one does. The least significant bperhx
136 * bits are taken, reflected (if P_REFIN) and appended to the
137 * result, then more characters are read. The maximum number of
138 * characters read is
139 * floor(length / bperhx) * ceil(bperhx / * CHAR_BIT).
140 * The returned poly_t is CLEAN.
143 bmp_t accu = BMP_C(0);
144 bmp_t mask = bperhx == BMP_BIT ? ~BMP_C(0) : (BMP_C(1) << bperhx) - BMP_C(1);
145 unsigned long iter = 0UL, idx;
146 int cmask = (1 << CHAR_BIT) - 1, c;
147 int count = 0, ofs;
148 poly_t poly = PZERO;
149 if (bperhx == 0) return (poly);
151 length -= length % bperhx;
152 palloc(&poly, length); /* >= 0 */
154 while (iter < length && (c = fgetc(input)) != EOF) {
155 if (flags & P_LTLBYT)
156 accu |= (bmp_t)(c & cmask) << count;
157 else
158 accu = (accu << CHAR_BIT) | (bmp_t)(c & cmask);
159 count += CHAR_BIT;
160 if (count >= bperhx) {
161 /* the low bperhx bits of accu contain bits of the poly.*/
162 iter += bperhx;
163 count = 0;
164 if (flags & P_REFIN)
165 accu = rev(accu, bperhx);
166 accu &= mask;
168 /* iter >= bperhx > 0 */
169 idx = IDX(iter - 1UL);
170 ofs = OFS(iter - 1UL);
171 poly.bitmap[idx] |= accu << ofs;
172 if (ofs + bperhx > BMP_BIT) {
173 poly.bitmap[idx - 1] |= accu >> (BMP_BIT - ofs);
175 accu = BMP_C(0); /* only needed for P_LTLBYT */
178 praloc(&poly, iter);
179 return (poly);
182 poly_t
183 strtop(const char *string, int flags, int bperhx) {
184 /* Converts a hex or character string to a poly_t.
185 * Each character is converted to a hex nibble yielding 4 bits
186 * unless P_DIRECT, when each character yields CHAR_BIT bits.
187 * Nibbles and characters are accumulated left-to-right
188 * unless P_DIRECT && P_LTLBYT, when they are accumulated
189 * right-to-left without reflection.
190 * As soon as at least bperhx bits are accumulated, the
191 * rightmost bperhx bits are reflected (if P_REFIN)
192 * and appended to the poly. When !P_DIRECT:
193 * bperhx=8 reads hex nibbles in pairs
194 * bperhx=7 reads hex nibbles in pairs and discards
195 * b3 of first nibble
196 * bperhx=4 reads hex nibbles singly
197 * bperhx=3 reads octal
198 * bperhx=1 reads longhand binary
199 * in theory if !P_REFIN, bperhx can be any multiple of 4
200 * with equal effect
201 * The returned poly_t is CLEAN.
204 /* make two passes, one to determine the poly size
205 * one to populate the bitmap
207 unsigned long length = 1UL, idx;
208 bmp_t accu;
209 bmp_t mask = bperhx == BMP_BIT ? ~BMP_C(0) : (BMP_C(1) << bperhx) - BMP_C(1);
210 int pass, count, ofs;
211 int cmask = (1 << CHAR_BIT) - 1, c;
212 const char *s;
214 poly_t poly = PZERO;
215 if (bperhx > BMP_BIT || bperhx <= 0 || string == NULL || *string == '\0')
216 return (poly);
218 if (~flags & P_DIRECT) {
219 if (*string == '$' || *string == '&')
220 ++string;
221 else if (*string == '0'
222 && (string[1] == 'x' || string[1] == 'X'))
223 string += 2;
225 length = (*string != '\0');
227 for (pass = 0; pass < 2 && length > 0UL; ++pass) {
228 s = string;
229 length = 0UL;
230 count = 0;
231 accu = BMP_C(0);
232 while ((c = *s++)) {
233 if (flags & P_DIRECT) {
234 if (flags & P_LTLBYT)
235 accu |= (bmp_t)(c & cmask) << count;
236 else
237 accu = (accu << CHAR_BIT) | (bmp_t)(c & cmask);
238 count += CHAR_BIT;
239 } else {
240 if (c == ' ' || c == '\t' || c == '\r' || c == '\n') continue;
241 accu <<= 4;
242 count += 4;
243 switch (c) {
244 case '0':
245 case '1':
246 case '2':
247 case '3':
248 case '4':
249 case '5':
250 case '6':
251 case '7':
252 case '8':
253 case '9':
254 accu |= (bmp_t) c - '0';
255 break;
256 case 'A':
257 case 'a':
258 accu |= BMP_C(0xa);
259 break;
260 case 'B':
261 case 'b':
262 accu |= BMP_C(0xb);
263 break;
264 case 'C':
265 case 'c':
266 accu |= BMP_C(0xc);
267 break;
268 case 'D':
269 case 'd':
270 accu |= BMP_C(0xd);
271 break;
272 case 'E':
273 case 'e':
274 accu |= BMP_C(0xe);
275 break;
276 case 'F':
277 case 'f':
278 accu |= BMP_C(0xf);
279 break;
280 default:
281 uerror("invalid character in hexadecimal argument");
285 if (count >= bperhx) {
286 /* the low bperhx bits of accu contain bits of the poly.
287 * in pass 0, increment length by bperhx.
288 * in pass 1, put the low bits of accu into the bitmap. */
289 length += bperhx;
290 count = 0;
291 if (pass == 1) {
292 if (flags & P_REFIN)
293 accu = rev(accu, bperhx);
294 accu &= mask;
296 /* length >= bperhx > 0 */
297 idx = IDX(length - 1);
298 ofs = OFS(length - 1);
299 poly.bitmap[idx] |= accu << ofs;
300 if (ofs + bperhx > BMP_BIT)
301 poly.bitmap[idx - 1] |= accu >> (BMP_BIT - ofs);
302 accu = BMP_C(0); /* only needed for P_LTLBYT */
306 if (pass == 0) palloc(&poly, length);
308 return (poly);
311 char *
312 ptostr(const poly_t poly, int flags, int bperhx) {
313 /* Returns a malloc()-ed string containing a hexadecimal
314 * representation of poly. See phxsubs().
316 return (pxsubs(poly, flags, bperhx, 0UL, poly.length));
319 char *
320 pxsubs(const poly_t poly, int flags, int bperhx, unsigned long start, unsigned long end) {
321 /* Returns a malloc()-ed string containing a hexadecimal
322 * representation of a portion of poly, from bit offset start to
323 * (end - 1) inclusive. The output is grouped into words of
324 * bperhx bits each. If P_RTJUST then the first word is padded
325 * with zeroes at the MSB end to make a whole number of words,
326 * otherwise the last word is padded at the LSB end. After
327 * justification the bperhx bits of each word are reversed (if
328 * P_REFOUT) and printed as a hex sequence, with words
329 * optionally separated by spaces (P_SPACE).
330 * If end exceeds the length of poly then zero bits are appended
331 * to make up the difference, in which case poly must be CLEAN.
333 char *string, *sptr;
334 unsigned long size, iter;
335 bmp_t accu;
336 bmp_t mask = bperhx == BMP_BIT ? ~BMP_C(0) : (BMP_C(1) << bperhx) - BMP_C(1);
337 int cperhx, part;
339 if (bperhx <= 0 || bperhx > BMP_BIT) return (NULL);
341 if (start > poly.length) start = poly.length;
342 if (end > poly.length) end = poly.length;
343 if (end < start) end = start;
345 cperhx = (bperhx + 3) >> 2;
346 if (flags & P_SPACE) ++cperhx;
348 size = (end - start + bperhx - 1UL) / bperhx;
349 size *= cperhx;
350 if (!size || ~flags & P_SPACE) ++size; /* for trailing null */
352 if (!(sptr = string = (char *) calloc(size, sizeof(char))))
353 uerror("cannot allocate memory for string");
355 size = end - start;
356 part = (int) size % bperhx;
357 if (part && flags & P_RTJUST) {
358 iter = start + part;
359 accu = getwrd(poly, iter - 1UL) & ((BMP_C(1) << part) - BMP_C(1));
360 if (flags & P_REFOUT)
361 /* best to reverse over bperhx rather than part, I think
362 * e.g. converting a 7-bit poly to 8-bit little-endian hex
364 accu = rev(accu, bperhx);
365 prhex(&sptr, accu, flags, bperhx);
366 if (flags & P_SPACE && size > iter) *sptr++ = ' ';
367 } else {
368 iter = start;
371 while ((iter += bperhx) <= end) {
372 accu = getwrd(poly, iter - 1UL) & mask;
373 if (flags & P_REFOUT)
374 accu = rev(accu, bperhx);
375 prhex(&sptr, accu, flags, bperhx);
376 if (flags & P_SPACE && size > iter) *sptr++ = ' ';
379 if (part && ~flags & P_RTJUST) {
380 accu = getwrd(poly, end - 1UL);
381 if (flags & P_REFOUT)
382 accu = rev(accu, part);
383 else
384 accu = accu << (bperhx - part) & mask;
385 prhex(&sptr, accu, flags, bperhx);
387 *sptr = '\0';
388 return (string);
391 poly_t
392 pclone(const poly_t poly) {
393 /* Returns a freestanding copy of poly. Does not clean poly or
394 * the result.
396 poly_t clone = PZERO;
398 pcpy(&clone, poly);
399 return (clone);
402 void
403 pcpy(poly_t *dest, const poly_t src) {
404 /* Assigns (copies) src into dest. Does not clean src or dest.
406 unsigned long iter, idx;
408 praloc(dest, src.length);
409 for (iter = 0UL, idx = 0UL; iter < src.length; iter += BMP_BIT, ++idx)
410 dest->bitmap[idx] = src.bitmap[idx];
413 void
414 pcanon(poly_t *poly) {
415 /* Converts poly into a CLEAN object by freeing unused bitmap words
416 * and clearing any bits in the last word beyond the last bit.
417 * The length field has absolute priority over the contents of the bitmap.
418 * Canonicalisation differs from normalisation in that leading and trailing
419 * zero terms are significant and preserved.
420 * poly may or may not be WELL-FORMED.
422 praloc(poly, poly->length);
425 void
426 pnorm(poly_t *poly) {
427 /* Converts poly into a NORMALISED object by removing leading
428 * and trailing zeroes, so that the polynomial starts and ends
429 * with significant terms.
430 * poly may or may not be WELL-FORMED.
432 unsigned long first;
434 /* call pcanon() here so pfirst() and plast() return the correct
435 * results
437 pcanon(poly);
438 first = pfirst(*poly);
439 if (first)
440 pshift(poly, *poly, 0UL, first, plast(*poly), 0UL);
441 else
442 praloc(poly, plast(*poly));
445 void
446 psnorm(poly_t *poly) {
447 /* Converts poly into a SEMI-NORMALISED object by removing
448 * trailing zeroes, so that the polynomial ends with a
449 * significant term.
450 * poly may or may not be WELL-FORMED.
453 /* call pcanon() here so plast() returns the correct result */
454 pcanon(poly);
455 praloc(poly, plast(*poly));
458 void
459 pchop(poly_t *poly) {
460 /* Normalise poly, then chop off the highest significant term
461 * (produces a SEMI-NORMALISED object). poly becomes a suitable
462 * divisor for pcrc().
463 * poly may or may not be WELL-FORMED.
466 /* call pcanon() here so pfirst() and plast() return correct
467 * results
469 pcanon(poly);
470 pshift(poly, *poly, 0UL, pfirst(*poly) + 1UL, plast(*poly), 0UL);
473 void
474 pkchop(poly_t *poly) {
475 /* Convert poly from Koopman notation to chopped form (produces
476 * a SEMI-NORMALISED object). poly becomes a suitable divisor
477 * for pcrc().
478 * poly may or may not be WELL-FORMED.
480 unsigned long first;
482 /* call pcanon() here so pfirst() returns the correct result */
483 pcanon(poly);
484 first = pfirst(*poly);
485 if (first >= poly->length) {
486 pfree(poly);
487 return;
489 pshift(poly, *poly, 0UL, first + 1UL, poly->length, 1UL);
490 piter(poly);
493 unsigned long
494 plen(const poly_t poly) {
495 /* Return length of polynomial.
496 * poly may or may not be WELL-FORMED.
498 return (poly.length);
502 pcmp(const poly_t *a, const poly_t *b) {
503 /* Compares poly_t objects for identical sizes and contents.
504 * a and b must be CLEAN.
505 * Defines a total order relation for sorting, etc. although
506 * mathematically, polynomials of equal degree are no greater or
507 * less than one another.
509 unsigned long iter;
510 bmp_t *aptr, *bptr;
512 if (!a || !b) return (!b - !a);
513 if (a->length < b->length) return (-1);
514 if (a->length > b->length) return (1);
515 aptr = a->bitmap;
516 bptr = b->bitmap;
517 if (aptr == bptr)
518 return (0);
519 for (iter = 0UL; iter < a->length; iter += BMP_BIT) {
520 if (*aptr < *bptr)
521 return (-1);
522 if (*aptr++ > *bptr++)
523 return (1);
525 return (0);
529 psncmp(const poly_t *a, const poly_t *b) {
530 /* Compares polys for identical effect, i.e. as though the
531 * shorter poly were padded with zeroes to the length of the
532 * longer.
533 * a and b must still be CLEAN, therefore psncmp() is *not*
534 * identical to pcmp() on semi-normalised polys as psnorm()
535 * clears the slack space.
537 unsigned long length, iter, idx;
538 bmp_t aword, bword;
539 if (!a || !b) return (!b - !a);
540 length = (a->length > b->length) ? a->length : b->length;
541 for (iter = 0UL, idx = 0UL; iter < length; iter += BMP_BIT, ++idx) {
542 aword = (iter < a->length) ? a->bitmap[idx] : BMP_C(0);
543 bword = (iter < b->length) ? b->bitmap[idx] : BMP_C(0);
544 if (aword < bword)
545 return (-1);
546 if (aword > bword)
547 return (1);
549 return (0);
554 ptst(const poly_t poly) {
555 /* Tests whether a polynomial equals zero. Returns 0 if equal,
556 * a nonzero value otherwise.
557 * poly must be CLEAN.
559 unsigned long iter;
560 bmp_t *bptr;
561 if (!poly.bitmap) return (0);
562 for (iter = 0UL, bptr = poly.bitmap; iter < poly.length; iter += BMP_BIT)
563 if (*bptr++) return (1);
564 return (0);
567 unsigned long
568 pfirst(const poly_t poly) {
569 /* Returns the index of the first nonzero term in poly. If none
570 * is found, returns the length of poly.
571 * poly must be CLEAN.
573 unsigned long idx = 0UL, size = SIZE(poly.length);
574 bmp_t accu = BMP_C(0); /* initialiser for Acorn C */
575 unsigned int probe = BMP_SUB, ofs = 0;
577 while (idx < size && !(accu = poly.bitmap[idx])) ++idx;
578 if (idx >= size) return (poly.length);
579 while (probe) {
580 #ifndef BMP_POF2
581 while ((ofs | probe) >= (unsigned int) BMP_BIT) probe >>= 1;
582 #endif
583 if (accu >> (ofs | probe)) ofs |= probe;
584 probe >>= 1;
587 return (BMP_BIT - 1UL - ofs + idx * BMP_BIT);
590 unsigned long
591 plast(const poly_t poly) {
592 /* Returns 1 plus the index of the last nonzero term in poly.
593 * If none is found, returns zero.
594 * poly must be CLEAN.
596 unsigned long idx, size = SIZE(poly.length);
597 bmp_t accu;
598 unsigned int probe = BMP_SUB, ofs = 0;
599 if (!poly.length) return (0UL);
600 idx = size - 1UL;
601 while (idx && !(accu = poly.bitmap[idx])) --idx;
603 if (!idx && !(accu = poly.bitmap[idx])) return (0UL);
605 /* now accu == poly.bitmap[idx] and contains last significant term */
606 while (probe) {
607 #ifndef BMP_POF2
608 while ((ofs | probe) >= (unsigned int) BMP_BIT) probe >>= 1;
609 #endif
610 if (accu << (ofs | probe)) ofs |= probe;
611 probe >>= 1;
613 return (idx * BMP_BIT + ofs + 1UL);
616 poly_t
617 psubs(const poly_t src, unsigned long head, unsigned long start, unsigned long end, unsigned long tail) {
618 poly_t dest = PZERO;
619 pshift(&dest, src, head, start, end, tail);
620 return (dest);
623 void
624 pright(poly_t *poly, unsigned long length) {
625 /* Trims or extends poly to length at the left edge, prepending
626 * zeroes if necessary. Analogous to praloc() except the
627 * rightmost terms of poly are preserved.
628 * On entry, poly may or may not be WELL-FORMED.
629 * On exit, poly is CLEAN.
632 if (length > poly->length)
633 pshift(poly, *poly, length - poly->length, 0UL, poly->length, 0UL);
634 else if (length < poly->length)
635 pshift(poly, *poly, 0UL, poly->length - length, poly->length, 0UL);
636 else
637 praloc(poly, poly->length);
640 void
641 pshift(poly_t *dest, const poly_t src, unsigned long head, unsigned long start, unsigned long end, unsigned long tail) {
642 /* copies bits start to end-1 of src to dest, plus the number of leading and trailing zeroes given by head and tail.
643 * end may exceed the length of src in which case more zeroes are appended.
644 * dest may point to src, in which case the poly is edited in place.
645 * src must be CLEAN.
646 * On exit, dest is CLEAN.
649 unsigned long length, fulllength, size, fullsize, iter, idx, datidx;
650 /* condition inputs; end, head and tail may be any value */
651 if (end < start) end = start;
653 length = end - start + head;
654 fulllength = length + tail;
655 if (fulllength > src.length)
656 praloc(dest, fulllength);
657 else
658 praloc(dest, src.length);
660 /* number of words in new poly */
661 size = SIZE(length);
662 fullsize = SIZE(fulllength);
663 /* array index of first word ending up with source material */
664 datidx = IDX(head);
666 if (head > start && end > start) {
667 /* shifting right, size > 0 */
668 /* index of the source bit ending up in the LSB of the last word
669 * size * BMP_BIT >= length > head > 0 */
670 iter = size * BMP_BIT - head - 1UL;
671 for (idx = size - 1UL; idx > datidx; iter -= BMP_BIT, --idx)
672 dest->bitmap[idx] = getwrd(src, iter);
673 dest->bitmap[idx] = getwrd(src, iter);
674 /* iter == size * BMP_BIT - head - 1 - BMP_BIT * (size - 1 - datidx)
675 * == BMP_BIT * (size - size + 1 + datidx) - head - 1
676 * == BMP_BIT * (1 + head / BMP_BIT) - head - 1
677 * == BMP_BIT + head - head % BMP_BIT - head - 1
678 * == BMP_BIT - head % BMP_BIT - 1
679 * >= 0
681 } else if (head <= start) {
682 /* shifting left or copying */
683 /* index of the source bit ending up in the LSB of bitmap[idx] */
684 iter = start - head + BMP_BIT - 1UL;
685 for (idx = datidx; idx < size; iter += BMP_BIT, ++idx)
686 dest->bitmap[idx] = getwrd(src, iter);
689 /* clear head */
690 for (idx = 0UL; idx < datidx; ++idx)
691 dest->bitmap[idx] = BMP_C(0);
692 if (size)
693 dest->bitmap[datidx] &= ~BMP_C(0) >> LOFS(head);
695 /* clear tail */
696 if (LOFS(length))
697 dest->bitmap[size - 1UL] &= ~(~BMP_C(0) >> LOFS(length));
698 for (idx = size; idx < fullsize; ++idx)
699 dest->bitmap[idx] = BMP_C(0);
701 /* call praloc to shrink poly if required */
702 if (dest->length > fulllength)
703 praloc(dest, fulllength);
706 void
707 ppaste(poly_t *dest, const poly_t src, unsigned long skip, unsigned long seek, unsigned long end, unsigned long fulllength) {
708 /* pastes terms of src, starting from skip, to positions seek to end-1 of dest
709 * then sets length of dest to fulllength (>= end)
710 * to paste n terms of src, give end = seek + n
711 * to truncate dest at end of paste, set fulllength = end
712 * to avoid truncating, set fulllength = plen(*dest)
713 * dest may point to src, in which case the poly is edited in place.
714 * src must be CLEAN in the case that the end is overrun.
715 * On exit, dest is CLEAN.
717 bmp_t mask;
718 unsigned long seekidx, endidx, iter;
719 int seekofs;
720 if (end < seek) end = seek;
721 if (fulllength < end) fulllength = end;
723 /* expand dest if necessary. don't shrink as dest may be src */
724 if (fulllength > dest->length)
725 praloc(dest, fulllength);
726 seekidx = IDX(seek);
727 endidx = IDX(end);
728 seekofs = OFS(seek);
729 /* index of the source bit ending up in the LSB of the first modified word */
730 iter = skip + seekofs;
731 if (seekidx == endidx) {
732 /* paste affects one word (traps end = seek case) */
733 mask = ((BMP_C(1) << seekofs) - (BMP_C(1) << OFS(end))) << 1;
734 dest->bitmap[seekidx] = (dest->bitmap[seekidx] & ~mask) | (getwrd(src, iter) & mask);
735 } else if (seek > skip) {
736 /* shifting right */
737 /* index of the source bit ending up in the LSB of the last modified word */
738 iter += (endidx - seekidx) * BMP_BIT;
739 mask = ~BMP_C(0) >> LOFS(end);
740 dest->bitmap[endidx] = (dest->bitmap[endidx] & mask) | (getwrd(src, iter) & ~mask);
741 for (iter -= BMP_BIT, --endidx; endidx > seekidx; iter -= BMP_BIT, --endidx)
742 dest->bitmap[endidx] = getwrd(src, iter);
743 mask = ~BMP_C(0) >> LOFS(seek);
744 dest->bitmap[endidx] = (dest->bitmap[endidx] & ~mask) | (getwrd(src, iter) & mask);
745 /* iter == skip + seekofs + (endidx - seekidx) * BMP_BIT - BMP_BIT * (endidx - seekidx)
746 * == skip + seekofs + BMP_BIT * (endidx - seekidx - endidx + seekidx)
747 * == skip + seekofs
748 * >= 0
750 } else {
751 /* shifting left or copying */
752 mask = ~BMP_C(0) >> LOFS(seek);
753 dest->bitmap[seekidx] = (dest->bitmap[seekidx] & ~mask) | (getwrd(src, iter) & mask);
754 for (iter += BMP_BIT, ++seekidx; seekidx < endidx; iter += BMP_BIT, ++seekidx)
755 dest->bitmap[seekidx] = getwrd(src, iter);
756 mask = ~BMP_C(0) >> LOFS(end);
757 dest->bitmap[seekidx] = (dest->bitmap[seekidx] & mask) | (getwrd(src, iter) & ~mask);
759 /* shrink poly if required */
760 if (dest->length > fulllength)
761 praloc(dest, fulllength);
764 void
765 pdiff(poly_t *dest, const poly_t src, unsigned long ofs) {
766 /* Subtract src from dest (modulo 2) at offset ofs.
767 * In modulo 2 arithmetic, subtraction is equivalent to addition
768 * We include an alias for those who wish to retain the distinction
769 * src and dest must be CLEAN.
771 psum(dest, src, ofs);
774 void
775 psum(poly_t *dest, const poly_t src, unsigned long ofs) {
776 /* Adds src to dest (modulo 2) at offset ofs.
777 * When ofs == dest->length, catenates src on to dest.
778 * src and dest must be CLEAN.
780 unsigned long fulllength, idx, iter, end;
782 fulllength = ofs + src.length;
783 if (fulllength > dest->length)
784 praloc(dest, fulllength);
785 /* array index of first word in dest to be modified */
786 idx = IDX(ofs);
787 /* index of bit in src to be added to LSB of dest->bitmap[idx] */
788 iter = OFS(ofs);
789 /* stop value for iter */
790 end = BMP_BIT - 1UL + src.length;
791 for (; iter < end; iter += BMP_BIT, ++idx)
792 dest->bitmap[idx] ^= getwrd(src, iter);
795 void
796 prev(poly_t *poly) {
797 /* Reverse or reciprocate a polynomial.
798 * On exit, poly is CLEAN.
800 unsigned long leftidx = 0UL, rightidx = SIZE(poly->length);
801 unsigned long ofs = LOFS(BMP_BIT - LOFS(poly->length));
802 unsigned long fulllength = poly->length + ofs;
803 bmp_t accu;
805 if (ofs) {
806 /* removable optimisation */
807 if (poly->length < (unsigned long) BMP_BIT) {
808 *poly->bitmap = rev(*poly->bitmap >> ofs, (int) poly->length) << ofs;
809 return;
812 /* claim remaining bits of last word (as we use public function pshift()) */
813 poly->length = fulllength;
816 /* reverse and swap words in the array, leaving it right-justified */
817 while (leftidx < rightidx) {
818 /* rightidx > 0 */
819 accu = rev(poly->bitmap[--rightidx], BMP_BIT);
820 poly->bitmap[rightidx] = rev(poly->bitmap[leftidx], BMP_BIT);
821 poly->bitmap[leftidx++] = accu;
823 /* shift polynomial to left edge if required */
824 if (ofs)
825 pshift(poly, *poly, 0UL, ofs, fulllength, 0UL);
828 void
829 prevch(poly_t *poly, int bperhx) {
830 /* Reverse each group of bperhx bits in a polynomial.
831 * Does not clean poly.
833 unsigned long iter = 0, idx, ofs;
834 bmp_t mask, accu;
836 if (bperhx < 2 || bperhx > BMP_BIT)
837 return;
838 if (poly->length % bperhx)
839 praloc(poly, bperhx - (poly->length % bperhx) + poly->length);
840 mask = ~BMP_C(0) >> (BMP_BIT - bperhx);
841 for (iter = (unsigned long)(bperhx - 1); iter < poly->length; iter += bperhx) {
842 accu = getwrd(*poly, iter) & mask;
843 accu ^= rev(accu, bperhx);
844 idx = IDX(iter);
845 ofs = OFS(iter);
846 poly->bitmap[idx] ^= accu << ofs;
847 if (ofs + bperhx > (unsigned int) BMP_BIT)
848 /* (BMP_BIT - 1UL - (iter) % BMP_BIT) + bperhx > BMP_BIT
849 * (-1UL - (iter) % BMP_BIT) + bperhx > 0
850 * (- (iter % BMP_BIT)) + bperhx > 1
851 * - (iter % BMP_BIT) > 1 - bperhx
852 * iter % BMP_BIT < bperhx - 1, iter >= bperhx - 1
853 * iter >= BMP_BIT
854 * idx >= 1
856 poly->bitmap[idx - 1] ^= accu >> (BMP_BIT - ofs);
860 void
861 prcp(poly_t *poly) {
862 /* Reciprocate a chopped polynomial. Use prev() on whole
863 * polynomials.
864 * On exit, poly is SEMI-NORMALISED.
866 unsigned long first;
868 praloc(poly, RNDUP(poly->length));
869 prev(poly);
870 first = pfirst(*poly);
871 if (first >= poly->length) {
872 pfree(poly);
873 return;
875 pshift(poly, *poly, 0UL, first + 1UL, poly->length, 1UL);
876 piter(poly);
879 void
880 pinv(poly_t *poly) {
881 /* Invert a polynomial, i.e. add 1 (modulo 2) to the coefficient of each term
882 * on exit, poly is CLEAN.
884 unsigned long idx, size = SIZE(poly->length);
886 for (idx = 0UL; idx < size; ++idx)
887 poly->bitmap[idx] = ~poly->bitmap[idx];
888 if (LOFS(poly->length))
889 poly->bitmap[size - 1UL] &= ~(~BMP_C(0) >> LOFS(poly->length));
892 poly_t
893 pmod(const poly_t dividend, const poly_t divisor) {
894 /* Divide dividend by normalised divisor and return the remainder
895 * This function generates a temporary 'chopped' divisor for pcrc()
896 * If calling repeatedly with a constant divisor, produce a chopped copy
897 * with pchop() and call pcrc() directly for higher efficiency.
898 * dividend and divisor must be CLEAN.
901 /* perhaps generate an error if divisor is zero */
902 poly_t subdivisor = psubs(divisor, 0UL, pfirst(divisor) + 1UL, plast(divisor), 0UL);
903 poly_t result = pcrc(dividend, subdivisor, pzero, pzero, 0);
904 pfree(&subdivisor);
905 return (result);
908 poly_t
909 pcrc(const poly_t message, const poly_t divisor, const poly_t init, const poly_t xorout, int flags) {
910 /* Divide message by divisor and return the remainder.
911 * init is added to divisor, highest terms aligned, before
912 * division.
913 * xorout is added to the remainder, highest terms aligned.
914 * If P_MULXN is set in flags, message is multiplied by x^n
915 * (i.e. trailing zeroes equal to the CRC width are appended)
916 * before adding init and division. Set P_MULXN for most CRC
917 * calculations.
918 * All inputs must be CLEAN.
919 * If all inputs are CLEAN, the returned poly_t will be CLEAN.
921 unsigned long max = 0UL, iter, ofs, resiter;
922 bmp_t probe, rem, dvsr, *rptr, *sptr;
923 const bmp_t *bptr, *eptr;
924 poly_t result = PZERO;
926 if (flags & P_MULXN)
927 max = message.length;
928 else if (message.length > divisor.length)
929 max = message.length - divisor.length;
930 bptr = message.bitmap;
931 eptr = message.bitmap + SIZE(message.length);
932 probe = ~(~BMP_C(0) >> 1);
933 if (divisor.length <= (unsigned long) BMP_BIT
934 && init.length <= (unsigned long) BMP_BIT) {
935 rem = init.length ? *init.bitmap : BMP_C(0);
936 dvsr = divisor.length ? *divisor.bitmap : BMP_C(0);
937 for (iter = 0UL, ofs = 0UL; iter < max; ++iter, --ofs) {
938 if (!ofs) {
939 ofs = BMP_BIT;
940 rem ^= *bptr++;
942 if (rem & probe)
943 rem = (rem << 1) ^ dvsr;
944 else
945 rem <<= 1;
947 if (bptr < eptr)
948 /* max < message.length */
949 rem ^= *bptr >> OFS(BMP_BIT - 1UL + max);
950 if (init.length > max && init.length - max > divisor.length) {
951 palloc(&result, init.length - max);
952 *result.bitmap = rem;
953 } else if (divisor.length) {
954 palloc(&result, divisor.length);
955 *result.bitmap = rem;
957 } else {
958 /* allocate maximum size plus one word for shifted divisors and one word containing zero.
959 * This also ensures that result[1] exists
961 palloc(&result, (init.length > divisor.length ? init.length : divisor.length) + (unsigned long)(BMP_BIT << 1));
962 /*if there is content in init, there will be an extra word in result to clear it */
963 psum(&result, init, 0UL);
964 if (max)
965 *result.bitmap ^= *bptr++;
966 for (iter = 0UL, ofs = 0UL; iter < max; ++iter, probe >>= 1) {
967 if (!probe) {
968 probe = ~(~BMP_C(0) >> 1);
969 ofs = 0UL;
970 sptr = rptr = result.bitmap;
971 ++sptr;
972 /* iter < max <= message.length, so bptr is valid
973 * shift result one word to the left, splicing in a message word
974 * and clearing the last active word
976 *rptr++ = *sptr++ ^ *bptr++;
977 for (resiter = (unsigned long)(BMP_BIT << 1); resiter < result.length; resiter += BMP_BIT)
978 * rptr++ = *sptr++;
980 ++ofs;
981 if (*result.bitmap & probe)
982 psum(&result, divisor, ofs);
984 rptr = result.bitmap;
985 ++rptr;
986 while (bptr < eptr)
987 *rptr++ ^= *bptr++;
988 /* 0 <= ofs <= BMP_BIT, location of the first bit of the result */
989 pshift(&result, result, 0UL, ofs, (init.length > max + divisor.length ? init.length - max - divisor.length : 0UL) + divisor.length + ofs, 0UL);
992 if (result.bitmap != NULL)
993 psum(&result, xorout, 0UL);
995 return (result);
999 piter(poly_t *poly) {
1000 /* Replace poly with the 'next' polynomial of equal length.
1001 * Returns zero if the next polynomial is all zeroes, a nonzero
1002 * value otherwise.
1003 * Does not clean poly.
1005 bmp_t *bptr;
1006 if (!poly->length) return (0);
1008 bptr = poly->bitmap + IDX(poly->length - 1UL);
1009 *bptr += BMP_C(1) << OFS(poly->length - 1UL);
1010 while (bptr != poly->bitmap && !*bptr)
1011 ++(*--bptr);
1012 return (*bptr != BMP_C(0));
1015 void
1016 palloc(poly_t *poly, unsigned long length) {
1017 /* Replaces poly with a CLEAN object of the specified length,
1018 * consisting of all zeroes.
1019 * It is safe to call with length = 0, in which case the object
1020 * is freed.
1021 * poly may or may not be WELL-FORMED.
1022 * On exit, poly is CLEAN.
1024 unsigned long size = SIZE(length);
1026 poly->length = 0UL;
1027 free(poly->bitmap);
1028 poly->bitmap = NULL;
1029 if (!length) return;
1030 if (!size)
1031 size = IDX(length) + 1UL;
1032 poly->bitmap = (bmp_t *) calloc(size, sizeof(bmp_t));
1033 if (poly->bitmap) {
1034 poly->length = length;
1035 } else
1036 uerror("cannot allocate memory for poly");
1039 void
1040 pfree(poly_t *poly) {
1041 /* Frees poly's bitmap storage and sets poly equal to the empty
1042 * polynomial (PZERO).
1043 * poly may or may not be WELL-FORMED.
1044 * On exit, poly is CLEAN.
1047 /* palloc(poly, 0UL); */
1049 poly->length = 0UL;
1050 free(poly->bitmap);
1051 poly->bitmap = NULL;
1054 void
1055 praloc(poly_t *poly, unsigned long length) {
1056 /* Trims or extends poly to length at the right edge, appending
1057 * zeroes if necessary.
1058 * On entry, poly may or may not be WELL-FORMED.
1059 * On exit, poly is CLEAN.
1061 unsigned long oldsize, size = SIZE(length);
1062 if (!poly) return;
1063 if (!length) {
1064 poly->length = 0UL;
1065 free(poly->bitmap);
1066 poly->bitmap = NULL;
1067 return;
1069 if (!size)
1070 size = IDX(length) + 1UL;
1071 if (!poly->bitmap)
1072 poly->length = 0UL;
1073 oldsize = SIZE(poly->length);
1074 if (oldsize != size)
1075 /* reallocate if array pointer is null or array resized */
1076 poly->bitmap = (bmp_t *) realloc((void *)poly->bitmap, size * sizeof(bmp_t));
1078 if (poly->bitmap) {
1080 if (poly->length < length) {
1081 /* poly->length >= 0, length > 0, size > 0.
1082 * poly expanded. clear old last word and all new words
1084 if (LOFS(poly->length))
1085 poly->bitmap[oldsize - 1UL] &= ~(~BMP_C(0) >> LOFS(poly->length));
1087 while (oldsize < size)
1088 poly->bitmap[oldsize++] = BMP_C(0);
1090 } else if (LOFS(length)) {
1091 /* poly->length >= length > 0.
1092 * poly shrunk. clear new last word
1094 poly->bitmap[size - 1UL] &= ~(~BMP_C(0) >> LOFS(length));
1097 poly->length = length;
1098 } else
1099 uerror("cannot reallocate memory for poly");
1103 pmpar(const poly_t poly, const poly_t mask) {
1104 /* Return even parity of poly masked with mask.
1105 * Poly and mask must be CLEAN.
1107 bmp_t res = BMP_C(0);
1108 int i = BMP_SUB;
1109 const bmp_t *pptr = poly.bitmap, *mptr = mask.bitmap;
1110 const bmp_t *const pend = poly.bitmap + SIZE(poly.length);
1111 const bmp_t *const mend = mask.bitmap + SIZE(mask.length);
1113 while (pptr < pend && mptr < mend)
1114 res ^= *pptr++ & *mptr++;
1116 res ^= res >> i;
1117 while (i >>= 1);
1119 return ((int)(res & BMP_C(1)));
1123 pident(const poly_t a, const poly_t b) {
1124 /* Return nonzero if a and b have the same length
1125 * and point to the same bitmap.
1126 * a and b need not be CLEAN.
1128 return (a.length == b.length && a.bitmap == b.bitmap);
1131 /* Private functions */
1133 static bmp_t
1134 getwrd(const poly_t poly, unsigned long iter) {
1135 /* Fetch unaligned word from poly where LSB of result is
1136 * bit iter of the bitmap (counting from zero). If iter exceeds
1137 * the length of poly then zeroes are appended as necessary.
1138 * Factored from ptostr().
1139 * poly must be CLEAN.
1141 bmp_t accu = BMP_C(0);
1142 unsigned long idx, size;
1143 int ofs;
1145 idx = IDX(iter);
1146 ofs = OFS(iter);
1147 size = SIZE(poly.length);
1149 if (idx < size)
1150 accu |= poly.bitmap[idx] >> ofs;
1151 if (idx && idx <= size && ofs > 0)
1152 accu |= poly.bitmap[idx - 1UL] << (BMP_BIT - ofs);
1153 return (accu);
1156 static bmp_t
1157 rev(bmp_t accu, int bits) {
1158 /* Returns the bitmap word argument with the given number of
1159 * least significant bits reversed and the rest cleared.
1161 static const unsigned char revtab[256] = {
1162 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
1163 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
1164 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
1165 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
1166 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
1167 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
1168 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
1169 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
1170 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
1171 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
1172 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
1173 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
1174 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
1175 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
1176 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
1177 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
1178 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
1179 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
1180 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
1181 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
1182 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
1183 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
1184 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
1185 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
1186 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
1187 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
1188 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
1189 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
1190 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
1191 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
1192 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
1193 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
1195 bmp_t result = BMP_C(0);
1196 while (bits > 8) {
1197 bits -= 8;
1198 result = result << 8 | revtab[accu & 0xff];
1199 accu >>= 8;
1201 result = result << bits | (bmp_t)(revtab[accu & 0xff] >> (8 - bits));
1202 return (result);
1205 static void
1206 prhex(char **spp, bmp_t bits, int flags, int bperhx) {
1207 /* Appends a hexadecimal string representing the bperhx least
1208 * significant bits of bits to an external string.
1209 * spp points to a character pointer that in turn points to the
1210 * end of a hex string being built. prhex() advances this
1211 * second pointer by the number of characters written.
1212 * The unused MSBs of bits MUST be cleared.
1213 * Set P_UPPER in flags to write A-F in uppercase.
1215 static const char hex[] = "0123456789abcdef0123456789ABCDEF";
1216 const int upper = ((flags & P_UPPER) ? 0x10 : 0);
1217 while (bperhx > 0) {
1218 bperhx -= ((bperhx + 3) & 3) + 1;
1219 *(*spp)++ = hex[(bits >> bperhx & BMP_C(0xf)) | upper];