/* model.c
 * Greg Cook, 9/Apr/2015
 */

/* CRC RevEng, an arbitrary-precision CRC calculator and algorithm finder
 * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015  Gregory Cook
 *
 * This file is part of CRC RevEng.
 *
 * CRC RevEng is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * CRC RevEng is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with CRC RevEng.  If not, see <http://www.gnu.org/licenses/>.
 */

/* 2014-01-14: added CRC-8/DVB-S2
 * 2014-01-11: corrected CRC-40/GSM, added alias CRC-8/AES
 * 2013-10-14: added CRC-13/BBC and six cdma2000 algorithms
 * 2013-06-11: ensure BMP_BIT is an integer constant to compile presets
 * 2013-01-20: big polynomials autogenerated, corrected CRC-82/DARC
 * 2012-07-19: added CRC-8/EBU
 * 2012-07-16: added CRC-15/MPT1327
 * 2012-05-25: removed CRC-1/PARITY-EVEN, CRC-1/PARITY-ODD
 * 2012-04-12: added model CRC-31/PHILIPS
 * 2012-03-03: single-line Williams model string conversion
 * 2012-02-20: corrected model CRC-6/DARC
 * 2011-09-03: added mrev(), mnovel()
 * 2011-08-28: added model CRC-64/XZ
 * 2011-04-30: added models CRC-16/TMS37157 and CRC-A, and alias CRC-B
 * 2011-02-10: made preset models ANSI C compliant
 * 2011-01-17: fixed ANSI C warnings (except preset models)
 * 2011-01-01: added mbynum(), mcount()
 * 2010-12-26: renamed CRC RevEng
 * 2010-12-18: minor change to mtostr() output format
 * 2010-12-15: added mcmp(), mmatch()
 * 2010-12-14: finished mbynam(), mnames(), mtostr()
 * 2010-12-13: restarted with PCONST macros
 * 2010-12-12: was having so much fun I didn't think to try compiling. :(
 * 2010-12-12: started models.c
 */

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "reveng.h"

/* Private declarations */

struct mpreset {
	const unsigned long width;	/* width of CRC algorithm */
	const bmp_t *const bspoly;	/* polynomial with highest-order term removed. length determines CRC width */
	const bmp_t *const binit;	/* initial register value. length == poly.length */
	const int flags;		/* P_REFIN and P_REFOUT indicate reflected input/output */
	const bmp_t *const bxorout;	/* final register XOR mask. length == poly.length */
	const bmp_t *const bcheck;	/* optional check value, the CRC of the UTF-8 string "123456789" */
	const char *const name;		/* optional canonical name of the model */
};

struct malias {
	const char *name;
	const struct mpreset *model;
	const int isprimry;
};

#ifdef PRESETS
#  if BMP_BIT < 32
#    error config.h: BMP_BIT must be an integer constant macro to compile presets
#  else /* BMP_BIT */

/* Big polynomial constants. */

/* Directives for relink.pl */
/* CONSTANT b40  = (40, 0x0004820009) */
/* CONSTANT b40a = (40, 0xffffffffff) */
/* CONSTANT b40b = (40, 0xd4164fc646) */
/* CONSTANT b64  = (64, 0x42f0e1eba9ea3693) */
/* CONSTANT b64a = (64, 0x6c40df5f0b497347) */
/* CONSTANT b64b = (64, 0xffffffffffffffff) */
/* CONSTANT b64c = (64, 0x62ec59e3f1a4f00a) */
/* CONSTANT b64d = (64, 0x995dc9bbdf1939fa) */
/* CONSTANT b82  = (82, 0x0308c0111011401440411) */
/* CONSTANT b82a = (82, 0x09ea83f625023801fd612) */

/* The next section was generated by relink.pl from the directives above. */

/* DO NOT EDIT the section below, INCLUDING the next comment. */
/* BEGIN AUTO-GENERATED CONSTANTS */
#    if BMP_BIT >= 40
static const bmp_t b40[] = {
	BMP_C(0x0004820009) << (BMP_BIT - 40),
};
static const bmp_t b40a[] = {
	BMP_C(0xffffffffff) << (BMP_BIT - 40),
};
static const bmp_t b40b[] = {
	BMP_C(0xd4164fc646) << (BMP_BIT - 40),
};
#    else /* BMP_BIT */
static const bmp_t b40[] = {
	BMP_C(0x00048200) << (BMP_BIT - 32) | BMP_C(0x04) >> (39 - BMP_BIT),
	BMP_C(0x09) << (BMP_BIT * 2 - 40),
};
static const bmp_t b40a[] = {
	BMP_C(0xffffffff) << (BMP_BIT - 32) | BMP_C(0x7f) >> (39 - BMP_BIT),
	BMP_C(0xff) << (BMP_BIT * 2 - 40),
};
static const bmp_t b40b[] = {
	BMP_C(0xd4164fc6) << (BMP_BIT - 32) | BMP_C(0x23) >> (39 - BMP_BIT),
	BMP_C(0x46) << (BMP_BIT * 2 - 40),
};
#    endif /* BMP_BIT */

#    if BMP_BIT >= 64
static const bmp_t b64[] = {
	BMP_C(0x42f0e1eba9ea3693) << (BMP_BIT - 64),
};
static const bmp_t b64a[] = {
	BMP_C(0x6c40df5f0b497347) << (BMP_BIT - 64),
};
static const bmp_t b64b[] = {
	BMP_C(0xffffffffffffffff) << (BMP_BIT - 64),
};
static const bmp_t b64c[] = {
	BMP_C(0x62ec59e3f1a4f00a) << (BMP_BIT - 64),
};
static const bmp_t b64d[] = {
	BMP_C(0x995dc9bbdf1939fa) << (BMP_BIT - 64),
};
#    else /* BMP_BIT */
static const bmp_t b64[] = {
	BMP_C(0x42f0e1eb) << (BMP_BIT - 32) | BMP_C(0x54f51b49) >> (63 - BMP_BIT),
	BMP_C(0xa9ea3693) << (BMP_BIT * 2 - 64),
};
static const bmp_t b64a[] = {
	BMP_C(0x6c40df5f) << (BMP_BIT - 32) | BMP_C(0x05a4b9a3) >> (63 - BMP_BIT),
	BMP_C(0x0b497347) << (BMP_BIT * 2 - 64),
};
static const bmp_t b64b[] = {
	BMP_C(0xffffffff) << (BMP_BIT - 32) | BMP_C(0x7fffffff) >> (63 - BMP_BIT),
	BMP_C(0xffffffff) << (BMP_BIT * 2 - 64),
};
static const bmp_t b64c[] = {
	BMP_C(0x62ec59e3) << (BMP_BIT - 32) | BMP_C(0x78d27805) >> (63 - BMP_BIT),
	BMP_C(0xf1a4f00a) << (BMP_BIT * 2 - 64),
};
static const bmp_t b64d[] = {
	BMP_C(0x995dc9bb) << (BMP_BIT - 32) | BMP_C(0x6f8c9cfd) >> (63 - BMP_BIT),
	BMP_C(0xdf1939fa) << (BMP_BIT * 2 - 64),
};
#    endif /* BMP_BIT */

#    if BMP_BIT >= 82
static const bmp_t b82[] = {
	BMP_C(0x0308c0111011401440411) << (BMP_BIT - 82),
};
static const bmp_t b82a[] = {
	BMP_C(0x09ea83f625023801fd612) << (BMP_BIT - 82),
};
#    elif BMP_BIT >= 41
static const bmp_t b82[] = {
	BMP_C(0x01846008880) << (BMP_BIT - 41) | BMP_C(0x08a00a20208) >> (81 - BMP_BIT),
	BMP_C(0x11401440411) << (BMP_BIT * 2 - 82),
};
static const bmp_t b82a[] = {
	BMP_C(0x04f541fb128) << (BMP_BIT - 41) | BMP_C(0x011c00feb09) >> (81 - BMP_BIT),
	BMP_C(0x023801fd612) << (BMP_BIT * 2 - 82),
};
#    else /* BMP_BIT */
static const bmp_t b82[] = {
	BMP_C(0x0c230044) << (BMP_BIT - 32) | BMP_C(0x040) >> (40 - BMP_BIT),
	BMP_C(0x40450051) << (BMP_BIT * 2 - 64) | BMP_C(0x00104) >> (80 - BMP_BIT * 2),
	BMP_C(0x00411) << (BMP_BIT * 3 - 82),
};
static const bmp_t b82a[] = {
	BMP_C(0x27aa0fd8) << (BMP_BIT - 32) | BMP_C(0x094) >> (40 - BMP_BIT),
	BMP_C(0x9408e007) << (BMP_BIT * 2 - 64) | BMP_C(0x0f584) >> (80 - BMP_BIT * 2),
	BMP_C(0x3d612) << (BMP_BIT * 3 - 82),
};
#    endif /* BMP_BIT */

/* END AUTO-GENERATED CONSTANTS */
/* DO NOT EDIT the section above, INCLUDING the previous comment. */

/* Array of the polynomial bitmaps used in the model table. */
static const bmp_t b32[] = {
	BMP_C(0x00000000) << (BMP_BIT - 32),	/*   0 --  5,      00 */
	BMP_C(0x000000af) << (BMP_BIT - 32),	/*   1 -- 32,000000af */
	BMP_C(0x00010000) << (BMP_BIT - 32),	/*   2 -- 16,    0001 */
	BMP_C(0x00020000) << (BMP_BIT - 32),	/*   3 -- 15,    0001 */
	BMP_C(0x007e0000) << (BMP_BIT - 32),	/*   4 -- 16,    007e */
	BMP_C(0x007f0000) << (BMP_BIT - 32),	/*   5 -- 16,    007f */
	BMP_C(0x03400000) << (BMP_BIT - 32),	/*   6 -- 11,     01a */
	BMP_C(0x0376e6e7) << (BMP_BIT - 32),	/*   7 -- 32,0376e6e7 */
	BMP_C(0x04c11db7) << (BMP_BIT - 32),	/*   8 -- 32,04c11db7 */
	BMP_C(0x05890000) << (BMP_BIT - 32),	/*   9 -- 16,    0589 */
	BMP_C(0x07000000) << (BMP_BIT - 32),	/*  10 --  8,      07 */
	BMP_C(0x09823b6e) << (BMP_BIT - 32),	/*  11 -- 31,04c11db7 */
	BMP_C(0x0b3c0000) << (BMP_BIT - 32),	/*  12 -- 15,    059e */
	BMP_C(0x0c000000) << (BMP_BIT - 32),	/*  13 --  6,      03 */
	BMP_C(0x0fb30000) << (BMP_BIT - 32),	/*  14 -- 16,    0fb3 */
	BMP_C(0x10210000) << (BMP_BIT - 32),	/*  15 -- 16,    1021 */
	BMP_C(0x12000000) << (BMP_BIT - 32),	/*  16 --  7,      09 */
	BMP_C(0x15000000) << (BMP_BIT - 32),	/*  17 --  8,      15 */
	BMP_C(0x18000000) << (BMP_BIT - 32),	/*  18 --  6,      06 */
	BMP_C(0x19d3c8d8) << (BMP_BIT - 32),	/*  19 -- 31,0ce9e46c */
	BMP_C(0x1c000000) << (BMP_BIT - 32),	/*  20 --  6,      07 */
	BMP_C(0x1d000000) << (BMP_BIT - 32),	/*  21 --  8,      1d */
	BMP_C(0x1d0f0000) << (BMP_BIT - 32),	/*  22 -- 16,    1d0f */
	BMP_C(0x1edc6f41) << (BMP_BIT - 32),	/*  23 -- 32,1edc6f41 */
	BMP_C(0x1f23b800) << (BMP_BIT - 32),	/*  24 -- 24,  1f23b8 */
	BMP_C(0x20140000) << (BMP_BIT - 32),	/*  25 -- 14,    0805 */
	BMP_C(0x20b40000) << (BMP_BIT - 32),	/*  26 -- 14,    082d */
	BMP_C(0x21890000) << (BMP_BIT - 32),	/*  27 -- 16,    2189 */
	BMP_C(0x21cf0200) << (BMP_BIT - 32),	/*  28 -- 24,  21cf02 */
	BMP_C(0x25000000) << (BMP_BIT - 32),	/*  29 --  8,      25 */
	BMP_C(0x26b10000) << (BMP_BIT - 32),	/*  30 -- 16,    26b1 */
	BMP_C(0x27d00000) << (BMP_BIT - 32),	/*  31 -- 13,    04fa */
	BMP_C(0x28000000) << (BMP_BIT - 32),	/*  32 --  5,      05 */
	BMP_C(0x29b10000) << (BMP_BIT - 32),	/*  33 -- 16,    29b1 */
	BMP_C(0x30000000) << (BMP_BIT - 32),	/*  34 --  4,       3 */
	BMP_C(0x3010bf7f) << (BMP_BIT - 32),	/*  35 -- 32,3010bf7f */
	BMP_C(0x31000000) << (BMP_BIT - 32),	/*  36 --  8,      31 */
	BMP_C(0x31c30000) << (BMP_BIT - 32),	/*  37 -- 16,    31c3 */
	BMP_C(0x34000000) << (BMP_BIT - 32),	/*  38 --  6,      0d */
	BMP_C(0x340bc6d9) << (BMP_BIT - 32),	/*  39 -- 32,340bc6d9 */
	BMP_C(0x38000000) << (BMP_BIT - 32),	/*  40 --  5,      07 */
	BMP_C(0x39000000) << (BMP_BIT - 32),	/*  41 --  8,      39 */
	BMP_C(0x3d650000) << (BMP_BIT - 32),	/*  42 -- 16,    3d65 */
	BMP_C(0x44c20000) << (BMP_BIT - 32),	/*  43 -- 16,    44c2 */
	BMP_C(0x48000000) << (BMP_BIT - 32),	/*  44 --  5,      09 */
	BMP_C(0x4acc0000) << (BMP_BIT - 32),	/*  45 -- 15,    2566 */
	BMP_C(0x4b370000) << (BMP_BIT - 32),	/*  46 -- 16,    4b37 */
	BMP_C(0x4c060000) << (BMP_BIT - 32),	/*  47 -- 16,    4c06 */
	BMP_C(0x55000000) << (BMP_BIT - 32),	/*  48 --  8,      55 */
	BMP_C(0x5d6dcb00) << (BMP_BIT - 32),	/*  49 -- 24,  5d6dcb */
	BMP_C(0x60000000) << (BMP_BIT - 32),	/*  50 --  3,       3 */
	BMP_C(0x63d00000) << (BMP_BIT - 32),	/*  51 -- 16,    63d0 */
	BMP_C(0x64000000) << (BMP_BIT - 32),	/*  52 --  6,      19 */
	BMP_C(0x66400000) << (BMP_BIT - 32),	/*  53 -- 10,     199 */
	BMP_C(0x6f910000) << (BMP_BIT - 32),	/*  54 -- 16,    6f91 */
	BMP_C(0x70000000) << (BMP_BIT - 32),	/*  55 --  4,       7 */
	BMP_C(0x70a00000) << (BMP_BIT - 32),	/*  56 -- 11,     385 */
	BMP_C(0x765e7680) << (BMP_BIT - 32),	/*  57 -- 32,765e7680 */
	BMP_C(0x7979bd00) << (BMP_BIT - 32),	/*  58 -- 24,  7979bd */
	BMP_C(0x7e000000) << (BMP_BIT - 32),	/*  59 --  8,      7e */
	BMP_C(0x80050000) << (BMP_BIT - 32),	/*  60 -- 16,    8005 */
	BMP_C(0x800d0000) << (BMP_BIT - 32),	/*  61 -- 16,    800d */
	BMP_C(0x80f00000) << (BMP_BIT - 32),	/*  62 -- 12,     80f */
	BMP_C(0x814141ab) << (BMP_BIT - 32),	/*  63 -- 32,814141ab */
	BMP_C(0x864cfb00) << (BMP_BIT - 32),	/*  64 -- 24,  864cfb */
	BMP_C(0x87315576) << (BMP_BIT - 32),	/*  65 -- 32,87315576 */
	BMP_C(0x89ec0000) << (BMP_BIT - 32),	/*  66 -- 16,    89ec */
	BMP_C(0x8b320000) << (BMP_BIT - 32),	/*  67 -- 15,    4599 */
	BMP_C(0x8bb70000) << (BMP_BIT - 32),	/*  68 -- 16,    8bb7 */
	BMP_C(0x8cc00000) << (BMP_BIT - 32),	/*  69 -- 10,     233 */
	BMP_C(0x906e0000) << (BMP_BIT - 32),	/*  70 -- 16,    906e */
	BMP_C(0x97000000) << (BMP_BIT - 32),	/*  71 --  8,      97 */
	BMP_C(0x98000000) << (BMP_BIT - 32),	/*  72 --  6,      26 */
	BMP_C(0x9b000000) << (BMP_BIT - 32),	/*  73 --  8,      9b */
	BMP_C(0x9c000000) << (BMP_BIT - 32),	/*  74 --  6,      27 */
	BMP_C(0x9e000000) << (BMP_BIT - 32),	/*  75 --  7,      4f */
	BMP_C(0x9ecf0000) << (BMP_BIT - 32),	/*  76 -- 16,    9ecf */
	BMP_C(0xa0970000) << (BMP_BIT - 32),	/*  77 -- 16,    a097 */
	BMP_C(0xa1000000) << (BMP_BIT - 32),	/*  78 --  8,      a1 */
	BMP_C(0xa6000000) << (BMP_BIT - 32),	/*  79 --  7,      53 */
	BMP_C(0xa8000000) << (BMP_BIT - 32),	/*  80 --  5,      15 */
	BMP_C(0xa833982b) << (BMP_BIT - 32),	/*  81 -- 32,a833982b */
	BMP_C(0xabcdef00) << (BMP_BIT - 32),	/*  82 -- 24,  abcdef */
	BMP_C(0xb2aa0000) << (BMP_BIT - 32),	/*  83 -- 16,    b2aa */
	BMP_C(0xb4600000) << (BMP_BIT - 32),	/*  84 -- 11,     5a3 */
	BMP_C(0xb4c80000) << (BMP_BIT - 32),	/*  85 -- 16,    b4c8 */
	BMP_C(0xb704ce00) << (BMP_BIT - 32),	/*  86 -- 24,  b704ce */
	BMP_C(0xbb3d0000) << (BMP_BIT - 32),	/*  87 -- 16,    bb3d */
	BMP_C(0xbc000000) << (BMP_BIT - 32),	/*  88 --  8,      bc */
	BMP_C(0xbd0be338) << (BMP_BIT - 32),	/*  89 -- 32,bd0be338 */
	BMP_C(0xbf050000) << (BMP_BIT - 32),	/*  90 -- 16,    bf05 */
	BMP_C(0xc0000000) << (BMP_BIT - 32),	/*  91 --  3,       6 */
	BMP_C(0xc2b70000) << (BMP_BIT - 32),	/*  92 -- 16,    c2b7 */
	BMP_C(0xc6c60000) << (BMP_BIT - 32),	/*  93 -- 16,    c6c6 */
	BMP_C(0xc8000000) << (BMP_BIT - 32),	/*  94 --  5,      19 */
	BMP_C(0xc8670000) << (BMP_BIT - 32),	/*  95 -- 16,    c867 */
	BMP_C(0xcbf43926) << (BMP_BIT - 32),	/*  96 -- 32,cbf43926 */
	BMP_C(0xd0000000) << (BMP_BIT - 32),	/*  97 --  8,      d0 */
	BMP_C(0xd02a0000) << (BMP_BIT - 32),	/*  98 -- 15,    6815 */
	BMP_C(0xd0db0000) << (BMP_BIT - 32),	/*  99 -- 16,    d0db */
	BMP_C(0xd4d00000) << (BMP_BIT - 32),	/* 100 -- 12,     d4d */
	BMP_C(0xd5000000) << (BMP_BIT - 32),	/* 101 --  8,      d5 */
	BMP_C(0xd64e0000) << (BMP_BIT - 32),	/* 102 -- 16,    d64e */
	BMP_C(0xda000000) << (BMP_BIT - 32),	/* 103 --  8,      da */
	BMP_C(0xdaf00000) << (BMP_BIT - 32),	/* 104 -- 12,     daf */
	BMP_C(0xe0000000) << (BMP_BIT - 32),	/* 105 --  3,       7 */
	BMP_C(0xe3069283) << (BMP_BIT - 32),	/* 106 -- 32,e3069283 */
	BMP_C(0xe5cc0000) << (BMP_BIT - 32),	/* 107 -- 16,    e5cc */
	BMP_C(0xe7a80000) << (BMP_BIT - 32),	/* 108 -- 13,    1cf5 */
	BMP_C(0xea000000) << (BMP_BIT - 32),	/* 109 --  7,      75 */
	BMP_C(0xea820000) << (BMP_BIT - 32),	/* 110 -- 16,    ea82 */
	BMP_C(0xec000000) << (BMP_BIT - 32),	/* 111 --  6,      3b */
	BMP_C(0xf1300000) << (BMP_BIT - 32),	/* 112 -- 12,     f13 */
	BMP_C(0xf4000000) << (BMP_BIT - 32),	/* 113 --  8,      f4 */
	BMP_C(0xf5b00000) << (BMP_BIT - 32),	/* 114 -- 12,     f5b */
	BMP_C(0xf6400000) << (BMP_BIT - 32),	/* 115 -- 10,     3d9 */
	BMP_C(0xf8000000) << (BMP_BIT - 32),	/* 116 --  5,      1f */
	BMP_C(0xfc000000) << (BMP_BIT - 32),	/* 117 --  6,      3f */
	BMP_C(0xfc891918) << (BMP_BIT - 32),	/* 118 -- 32,fc891918 */
	BMP_C(0xfd000000) << (BMP_BIT - 32),	/* 119 --  8,      fd */
	BMP_C(0xfe000000) << (BMP_BIT - 32),	/* 120 --  7,      7f */
	BMP_C(0xfedcba00) << (BMP_BIT - 32),	/* 121 -- 24,  fedcba */
	BMP_C(0xfee80000) << (BMP_BIT - 32),	/* 122 -- 16,    fee8 */
	BMP_C(0xff000000) << (BMP_BIT - 32),	/* 123 --  8,      ff */
	BMP_C(0xffc00000) << (BMP_BIT - 32),	/* 124 -- 10,     3ff */
	BMP_C(0xfff00000) << (BMP_BIT - 32),	/* 125 -- 12,     fff */
	BMP_C(0xffff0000) << (BMP_BIT - 32),	/* 126 -- 16,    ffff */
	BMP_C(0xfffffffe) << (BMP_BIT - 32),	/* 127 -- 31,7fffffff */
	BMP_C(0xffffffff) << (BMP_BIT - 32),	/* 128 -- 32,ffffffff */
};

/* Table of preset CRC models.
 * Sorted by left-justified polynomial for bsearch().
 */
static const struct mpreset models[] = {
	{32UL, b32+  1, 0,       P_BE,   0,       b32+ 89, "XFER"              },	/*  0 */
	{40UL, b40,     0,       P_BE,   b40a,    b40b,    "CRC-40/GSM"        },	/*  1 */
	{32UL, b32+  8, 0,       P_BE,   b32+128, b32+ 57, "CRC-32/POSIX"      },	/*  2 */
	{32UL, b32+  8, b32+128, P_BE,   0,       b32+  7, "CRC-32/MPEG-2"     },	/*  3 */
	{32UL, b32+  8, b32+128, P_BE,   b32+128, b32+118, "CRC-32/BZIP2"      },	/*  4 */
	{32UL, b32+  8, b32+128, P_LE,   0,       b32+ 39, "JAMCRC"            },	/*  5 */
	{32UL, b32+  8, b32+128, P_LE,   b32+128, b32+ 96, "CRC-32"            },	/*  6 */
	{16UL, b32+  9, 0,       P_BE,   0,       b32+  5, "CRC-16/DECT-X"     },	/*  7 */
	{16UL, b32+  9, 0,       P_BE,   b32+  2, b32+  4, "CRC-16/DECT-R"     },	/*  8 */
	{ 8UL, b32+ 10, 0,       P_BE,   0,       b32+113, "CRC-8"             },	/*  9 */
	{ 8UL, b32+ 10, 0,       P_BE,   b32+ 48, b32+ 78, "CRC-8/ITU"         },	/* 10 */
	{ 8UL, b32+ 10, b32+123, P_LE,   0,       b32+ 97, "CRC-8/ROHC"        },	/* 11 */
	{31UL, b32+ 11, b32+127, P_BE,   b32+127, b32+ 19, "CRC-31/PHILIPS"    },	/* 12 */
	{ 6UL, b32+ 13, 0,       P_LE,   0,       b32+ 18, "CRC-6/ITU"         },	/* 13 */
	{82UL, b82,     0,       P_LE,   0,       b82a,    "CRC-82/DARC"       },	/* 14 */
	{16UL, b32+ 15, 0,       P_BE,   0,       b32+ 37, "XMODEM"            },	/* 15 */
	{16UL, b32+ 15, 0,       P_LE,   0,       b32+ 27, "KERMIT"            },	/* 16 */
	{16UL, b32+ 15, b32+ 22, P_BE,   0,       b32+107, "CRC-16/AUG-CCITT"  },	/* 17 */
	{16UL, b32+ 15, b32+ 66, P_LE,   0,       b32+ 30, "CRC-16/TMS37157"   },	/* 18 */
	{16UL, b32+ 15, b32+ 83, P_LE,   0,       b32+ 51, "CRC-16/RIELLO"     },	/* 19 */
	{16UL, b32+ 15, b32+ 93, P_LE,   0,       b32+ 90, "CRC-A"             },	/* 20 */
	{16UL, b32+ 15, b32+126, P_BE,   0,       b32+ 33, "CRC-16/CCITT-FALSE"},	/* 21 */
	{16UL, b32+ 15, b32+126, P_BE,   b32+126, b32+102, "CRC-16/GENIBUS"    },	/* 22 */
	{16UL, b32+ 15, b32+126, P_LE,   0,       b32+ 54, "CRC-16/MCRF4XX"    },	/* 23 */
	{16UL, b32+ 15, b32+126, P_LE,   b32+126, b32+ 70, "X-25"              },	/* 24 */
	{ 7UL, b32+ 16, 0,       P_BE,   0,       b32+109, "CRC-7"             },	/* 25 */
	{ 6UL, b32+ 20, b32+117, P_BE,   0,       b32+111, "CRC-6/CDMA2000-B"  },	/* 26 */
	{ 8UL, b32+ 21, b32+119, P_BE,   0,       b32+ 59, "CRC-8/I-CODE"      },	/* 27 */
	{ 8UL, b32+ 21, b32+123, P_LE,   0,       b32+ 71, "CRC-8/EBU"         },	/* 28 */
	{32UL, b32+ 23, b32+128, P_LE,   b32+128, b32+106, "CRC-32C"           },	/* 29 */
	{14UL, b32+ 25, 0,       P_LE,   0,       b32+ 26, "CRC-14/DARC"       },	/* 30 */
	{ 5UL, b32+ 32, b32+116, P_LE,   b32+116, b32+ 94, "CRC-5/USB"         },	/* 31 */
	{ 4UL, b32+ 34, 0,       P_LE,   0,       b32+ 55, "CRC-4/ITU"         },	/* 32 */
	{ 8UL, b32+ 36, 0,       P_LE,   0,       b32+ 78, "CRC-8/MAXIM"       },	/* 33 */
	{ 8UL, b32+ 41, 0,       P_LE,   0,       b32+ 17, "CRC-8/DARC"        },	/* 34 */
	{16UL, b32+ 42, 0,       P_BE,   b32+126, b32+ 92, "CRC-16/EN-13757"   },	/* 35 */
	{16UL, b32+ 42, 0,       P_LE,   b32+126, b32+110, "CRC-16/DNP"        },	/* 36 */
	{64UL, b64,     0,       P_BE,   0,       b64a,    "CRC-64"            },	/* 37 */
	{64UL, b64,     b64b,    P_BE,   b64b,    b64c,    "CRC-64/WE"         },	/* 38 */
	{64UL, b64,     b64b,    P_LE,   b64b,    b64d,    "CRC-64/XZ"         },	/* 39 */
	{ 5UL, b32+ 44, b32+ 44, P_BE,   0,       b32+  0, "CRC-5/EPC"         },	/* 40 */
	{24UL, b32+ 49, b32+ 82, P_BE,   0,       b32+ 24, "CRC-24/FLEXRAY-B"  },	/* 41 */
	{24UL, b32+ 49, b32+121, P_BE,   0,       b32+ 58, "CRC-24/FLEXRAY-A"  },	/* 42 */
	{ 3UL, b32+ 50, b32+105, P_LE,   0,       b32+ 91, "CRC-3/ROHC"        },	/* 43 */
	{ 6UL, b32+ 52, 0,       P_LE,   0,       b32+ 72, "CRC-6/DARC"        },	/* 44 */
	{11UL, b32+ 56, b32+  6, P_BE,   0,       b32+ 84, "CRC-11"            },	/* 45 */
	{16UL, b32+ 60, 0,       P_BE,   0,       b32+122, "CRC-16/BUYPASS"    },	/* 46 */
	{16UL, b32+ 60, 0,       P_LE,   0,       b32+ 87, "ARC"               },	/* 47 */
	{16UL, b32+ 60, 0,       P_LE,   b32+126, b32+ 43, "CRC-16/MAXIM"      },	/* 48 */
	{16UL, b32+ 60, b32+ 61, P_BE,   0,       b32+ 76, "CRC-16/DDS-110"    },	/* 49 */
	{16UL, b32+ 60, b32+126, P_LE,   0,       b32+ 46, "MODBUS"            },	/* 50 */
	{16UL, b32+ 60, b32+126, P_LE,   b32+126, b32+ 85, "CRC-16/USB"        },	/* 51 */
	{12UL, b32+ 62, 0,       P_BE,   0,       b32+114, "CRC-12/DECT"       },	/* 52 */
	{12UL, b32+ 62, 0,       P_BELE, 0,       b32+104, "CRC-12/3GPP"       },	/* 53 */
	{32UL, b32+ 63, 0,       P_BE,   0,       b32+ 35, "CRC-32Q"           },	/* 54 */
	{24UL, b32+ 64, b32+ 86, P_BE,   0,       b32+ 28, "CRC-24"            },	/* 55 */
	{15UL, b32+ 67, 0,       P_BE,   0,       b32+ 12, "CRC-15"            },	/* 56 */
	{16UL, b32+ 68, 0,       P_BE,   0,       b32+ 99, "CRC-16/T10-DIF"    },	/* 57 */
	{10UL, b32+ 69, 0,       P_BE,   0,       b32+ 53, "CRC-10"            },	/* 58 */
	{ 8UL, b32+ 73, 0,       P_LE,   0,       b32+ 29, "CRC-8/WCDMA"       },	/* 59 */
	{ 8UL, b32+ 73, b32+123, P_BE,   0,       b32+103, "CRC-8/CDMA2000"    },	/* 60 */
	{ 6UL, b32+ 74, b32+117, P_BE,   0,       b32+ 38, "CRC-6/CDMA2000-A"  },	/* 61 */
	{ 7UL, b32+ 75, b32+120, P_LE,   0,       b32+ 79, "CRC-7/ROHC"        },	/* 62 */
	{16UL, b32+ 77, 0,       P_BE,   0,       b32+ 14, "CRC-16/TELEDISK"   },	/* 63 */
	{ 5UL, b32+ 80, 0,       P_LE,   0,       b32+ 40, "CRC-5/ITU"         },	/* 64 */
	{32UL, b32+ 81, b32+128, P_LE,   b32+128, b32+ 65, "CRC-32D"           },	/* 65 */
	{16UL, b32+ 95, b32+126, P_BE,   0,       b32+ 47, "CRC-16/CDMA2000"   },	/* 66 */
	{15UL, b32+ 98, 0,       P_BE,   b32+  3, b32+ 45, "CRC-15/MPT1327"    },	/* 67 */
	{ 8UL, b32+101, 0,       P_BE,   0,       b32+ 88, "CRC-8/DVB-S2"      },	/* 68 */
	{13UL, b32+108, 0,       P_BE,   0,       b32+ 31, "CRC-13/BBC"        },	/* 69 */
	{12UL, b32+112, b32+125, P_BE,   0,       b32+100, "CRC-12/CDMA2000"   },	/* 70 */
	{10UL, b32+115, b32+124, P_BE,   0,       b32+ 69, "CRC-10/CDMA2000"   },	/* 71 */
};
#    define NPRESETS 72

/* List of names with pointers to models, pre-sorted for use with bsearch() */
static const struct malias aliases[] = {
	{"ARC",			models+47, 1},	/*   0 */
	{"B-CRC-32",		models+ 4, 0},	/*   1 */
	{"CKSUM",		models+ 2, 0},	/*   2 */
	{"CRC-10",		models+58, 1},	/*   3 */
	{"CRC-10/CDMA2000",	models+71, 1},	/*   4 */
	{"CRC-11",		models+45, 1},	/*   5 */
	{"CRC-12/3GPP",		models+53, 1},	/*   6 */
	{"CRC-12/CDMA2000",	models+70, 1},	/*   7 */
	{"CRC-12/DECT",		models+52, 1},	/*   8 */
	{"CRC-13/BBC",		models+69, 1},	/*   9 */
	{"CRC-14/DARC",		models+30, 1},	/*  10 */
	{"CRC-15",		models+56, 1},	/*  11 */
	{"CRC-15/MPT1327",	models+67, 1},	/*  12 */
	{"CRC-16",		models+47, 0},	/*  13 */
	{"CRC-16/ACORN",	models+15, 0},	/*  14 */
	{"CRC-16/ARC",		models+47, 0},	/*  15 */
	{"CRC-16/AUG-CCITT",	models+17, 1},	/*  16 */
	{"CRC-16/BUYPASS",	models+46, 1},	/*  17 */
	{"CRC-16/CCITT",	models+16, 0},	/*  18 */
	{"CRC-16/CCITT-FALSE",	models+21, 1},	/*  19 */
	{"CRC-16/CCITT-TRUE",	models+16, 0},	/*  20 */
	{"CRC-16/CDMA2000",	models+66, 1},	/*  21 */
	{"CRC-16/DARC",		models+22, 0},	/*  22 */
	{"CRC-16/DDS-110",	models+49, 1},	/*  23 */
	{"CRC-16/DECT-R",	models+ 8, 1},	/*  24 */
	{"CRC-16/DECT-X",	models+ 7, 1},	/*  25 */
	{"CRC-16/DNP",		models+36, 1},	/*  26 */
	{"CRC-16/EN-13757",	models+35, 1},	/*  27 */
	{"CRC-16/EPC",		models+22, 0},	/*  28 */
	{"CRC-16/GENIBUS",	models+22, 1},	/*  29 */
	{"CRC-16/I-CODE",	models+22, 0},	/*  30 */
	{"CRC-16/IBM-SDLC",	models+24, 0},	/*  31 */
	{"CRC-16/ISO-HDLC",	models+24, 0},	/*  32 */
	{"CRC-16/LHA",		models+47, 0},	/*  33 */
	{"CRC-16/MAXIM",	models+48, 1},	/*  34 */
	{"CRC-16/MCRF4XX",	models+23, 1},	/*  35 */
	{"CRC-16/RIELLO",	models+19, 1},	/*  36 */
	{"CRC-16/SPI-FUJITSU",	models+17, 0},	/*  37 */
	{"CRC-16/T10-DIF",	models+57, 1},	/*  38 */
	{"CRC-16/TELEDISK",	models+63, 1},	/*  39 */
	{"CRC-16/TMS37157",	models+18, 1},	/*  40 */
	{"CRC-16/USB",		models+51, 1},	/*  41 */
	{"CRC-16/VERIFONE",	models+46, 0},	/*  42 */
	{"CRC-24",		models+55, 1},	/*  43 */
	{"CRC-24/FLEXRAY-A",	models+42, 1},	/*  44 */
	{"CRC-24/FLEXRAY-B",	models+41, 1},	/*  45 */
	{"CRC-24/OPENPGP",	models+55, 0},	/*  46 */
	{"CRC-3/ROHC",		models+43, 1},	/*  47 */
	{"CRC-31/PHILIPS",	models+12, 1},	/*  48 */
	{"CRC-32",		models+ 6, 1},	/*  49 */
	{"CRC-32/AAL5",		models+ 4, 0},	/*  50 */
	{"CRC-32/ADCCP",	models+ 6, 0},	/*  51 */
	{"CRC-32/BZIP2",	models+ 4, 1},	/*  52 */
	{"CRC-32/CASTAGNOLI",	models+29, 0},	/*  53 */
	{"CRC-32/DECT-B",	models+ 4, 0},	/*  54 */
	{"CRC-32/ISCSI",	models+29, 0},	/*  55 */
	{"CRC-32/MPEG-2",	models+ 3, 1},	/*  56 */
	{"CRC-32/POSIX",	models+ 2, 1},	/*  57 */
	{"CRC-32C",		models+29, 1},	/*  58 */
	{"CRC-32D",		models+65, 1},	/*  59 */
	{"CRC-32Q",		models+54, 1},	/*  60 */
	{"CRC-4/ITU",		models+32, 1},	/*  61 */
	{"CRC-40/GSM",		models+ 1, 1},	/*  62 */
	{"CRC-5/EPC",		models+40, 1},	/*  63 */
	{"CRC-5/ITU",		models+64, 1},	/*  64 */
	{"CRC-5/USB",		models+31, 1},	/*  65 */
	{"CRC-6/CDMA2000-A",	models+61, 1},	/*  66 */
	{"CRC-6/CDMA2000-B",	models+26, 1},	/*  67 */
	{"CRC-6/DARC",		models+44, 1},	/*  68 */
	{"CRC-6/ITU",		models+13, 1},	/*  69 */
	{"CRC-64",		models+37, 1},	/*  70 */
	{"CRC-64/WE",		models+38, 1},	/*  71 */
	{"CRC-64/XZ",		models+39, 1},	/*  72 */
	{"CRC-7",		models+25, 1},	/*  73 */
	{"CRC-7/ROHC",		models+62, 1},	/*  74 */
	{"CRC-8",		models+ 9, 1},	/*  75 */
	{"CRC-8/AES",		models+28, 0},	/*  76 */
	{"CRC-8/CDMA2000",	models+60, 1},	/*  77 */
	{"CRC-8/DARC",		models+34, 1},	/*  78 */
	{"CRC-8/DVB-S2",	models+68, 1},	/*  79 */
	{"CRC-8/EBU",		models+28, 1},	/*  80 */
	{"CRC-8/I-CODE",	models+27, 1},	/*  81 */
	{"CRC-8/ITU",		models+10, 1},	/*  82 */
	{"CRC-8/MAXIM",		models+33, 1},	/*  83 */
	{"CRC-8/ROHC",		models+11, 1},	/*  84 */
	{"CRC-8/WCDMA",		models+59, 1},	/*  85 */
	{"CRC-82/DARC",		models+14, 1},	/*  86 */
	{"CRC-A",		models+20, 1},	/*  87 */
	{"CRC-B",		models+24, 0},	/*  88 */
	{"CRC-CCITT",		models+16, 0},	/*  89 */
	{"CRC-IBM",		models+47, 0},	/*  90 */
	{"DOW-CRC",		models+33, 0},	/*  91 */
	{"JAMCRC",		models+ 5, 1},	/*  92 */
	{"KERMIT",		models+16, 1},	/*  93 */
	{"MODBUS",		models+50, 1},	/*  94 */
	{"PKZIP",		models+ 6, 0},	/*  95 */
	{"R-CRC-16",		models+ 8, 0},	/*  96 */
	{"X-25",		models+24, 1},	/*  97 */
	{"X-CRC-12",		models+52, 0},	/*  98 */
	{"X-CRC-16",		models+ 7, 0},	/*  99 */
	{"XFER",		models+ 0, 1},	/* 100 */
	{"XMODEM",		models+15, 1},	/* 101 */
	{"ZMODEM",		models+15, 0},	/* 102 */
	{NULL,			NULL,      0},	/* terminating entry */
};
#    define NALIASES 103

#  endif /* BMP_BIT */
#else /* PRESETS */

static const struct mpreset models[] = {
	{ 0UL, 0,       0,       P_BE,   0,       0,       NULL                },	/* terminating entry */
};
#  define NPRESETS 0

static const struct malias aliases[] = {
	{NULL,			NULL,      0},	/* terminating entry */
};
#  define NALIASES 0

#endif /* PRESETS */

static const poly_t pzero = PZERO;

static int acmp(const struct malias *, const struct malias *);
static void munpack(model_t *, const struct mpreset *);

/* copy a parameter of a preset into a model */
#define MUNPACK(parm) \
	praloc(&dest->parm, (src->b##parm ? src->width : 0UL)); \
	for(iter=0UL, idx=0UL; iter < dest->parm.length; iter += BMP_BIT, ++idx)\
		dest->parm.bitmap[idx] = src->b##parm[idx];

/* Definitions */

void
mcpy(model_t *dest, const model_t *src) {
	/* Copies the parameters of src to dest.
	 * dest must be an initialised model.
	 */
	if(!dest || !src) return;
	pcpy(&dest->spoly, src->spoly);
	pcpy(&dest->init, src->init);
	pcpy(&dest->xorout, src->xorout);
	pcpy(&dest->check, src->check);
	dest->flags = src->flags;
	/* link to the name as it is static */
	dest->name = src->name;
}

void
mfree(model_t *model) {
	/* Frees the parameters of model. */
	if(!model) return;
	pfree(&model->spoly);
	pfree(&model->init);
	pfree(&model->xorout);
	pfree(&model->check);
	/* not name as it is static */
	/* not model either, it might point to an array! */
}

int
mcmp(const model_t *a, const model_t *b) {
	/* Compares a and b for identical effect, i.e. disregarding
	 * trailing zeroes in parameter polys.
	 * Intended for bsearch() to find a matching model in models[].
	 */
	int result;
	if(!a || !b) return(!b - !a);
	if((result = psncmp(&a->spoly, &b->spoly))) return(result);
	if((result = psncmp(&a->init, &b->init))) return(result);
	if((a->flags & P_REFIN) && (~b->flags & P_REFIN)) return(1);
	if((~a->flags & P_REFIN) && (b->flags & P_REFIN)) return(-1);
	if((a->flags & P_REFOUT) && (~b->flags & P_REFOUT)) return(1);
	if((~a->flags & P_REFOUT) && (b->flags & P_REFOUT)) return(-1);
	return(psncmp(&a->xorout, &b->xorout));
}

int
mbynam(model_t *dest, const char *key) {
	/* Sets parameters in dest according to the model named by key.
	 */
	struct malias akey = {NULL, NULL, 0}, *aptr;
	char *ukey, *uptr;

	if(!aliases->name)
		return(-1);
	if(!(ukey = malloc((size_t) 1 + strlen(key))))
		uerror("cannot allocate memory for comparison string");
	akey.name = uptr = ukey;
	do
		*uptr++ = toupper(*key);
	while(*key++);

	aptr = bsearch(&akey, aliases, NALIASES, sizeof(struct malias), (int (*)(const void *, const void *)) &acmp);
	free(ukey);

	if(aptr == NULL)
		return(0);
	munpack(dest, aptr->model);
	return(1);
}

void
mbynum(model_t *dest, int num) {
	/* Sets parameters in dest according to the model indexed by num. */
	if(num > NPRESETS)
		num = NPRESETS;
	munpack(dest, models+num);
}

int
mcount(void) {
	/* Returns the number of preset models. */
	return(NPRESETS);
}

char *
mnames(void) {
	/* Returns a malloc()-ed string of the names of all preset
	 * models, separated by newlines and terminated by NULL.
	 * Aliases are not listed.
	 */
	size_t size = 0;
	char *string, *sptr;
	const struct malias *aptr = aliases;

	while(aptr->name) {
		if(aptr->isprimry)
			size += strlen(aptr->name) + 1;
		++aptr;
	}
	if(!size) return(NULL);
	if((string = malloc(size))) {
		aptr = aliases;
		sptr = string;
		while(aptr->name) {
			if(aptr->isprimry) {
				strcpy(sptr, aptr->name);
				sptr += strlen(aptr->name);
				*sptr++ = '\n';
			}
			++aptr;
		}
		*--sptr = '\0';
	} else
		uerror("cannot allocate memory for list of models");

	return(string);
}

char *
mtostr(const model_t *model) {
	/* Returns a malloc()-ed string containing a Williams model
	 * record representing the input model.
	 * mcanon() should be called on the argument before printing.
	 */
	size_t size;
	char *polystr, *initstr, *xorotstr, *checkstr, strbuf[512], *string = NULL;

	if(!model) return(NULL);
	polystr = ptostr(model->spoly, P_RTJUST, 4);
	initstr = ptostr(model->init, P_RTJUST, 4);
	xorotstr = ptostr(model->xorout, P_RTJUST, 4);
	checkstr = ptostr(model->check, P_RTJUST, 4);

	sprintf(strbuf, "%lu", plen(model->spoly));
	size =
		70
		+ (model->name && *model->name ? 2 + strlen(model->name) : 6)
		+ strlen(strbuf)
		+ (polystr && *polystr ? strlen(polystr) : 6)
		+ (initstr && *initstr ? strlen(initstr) : 6)
		+ (model->flags & P_REFIN ? 4 : 5)
		+ (model->flags & P_REFOUT ? 4 : 5)
		+ (xorotstr && *xorotstr ? strlen(xorotstr) : 6)
		+ (checkstr && *checkstr ? strlen(checkstr) : 6);
	if((string = malloc(size))) {
		sprintf(strbuf, "\"%s\"", model->name);
		sprintf(string,
				"width=%lu  "
				"poly=0x%s  "
				"init=0x%s  "
				"refin=%s  "
				"refout=%s  "
				"xorout=0x%s  "
				"check=0x%s  "
				"name=%s",
				plen(model->spoly),
				polystr && *polystr ? polystr : "(none)",
				initstr && *initstr ? initstr :  "(none)",
				(model->flags & P_REFIN) ? "true" : "false",
				(model->flags & P_REFOUT) ? "true" : "false",
				xorotstr && *xorotstr ? xorotstr : "(none)",
				checkstr && *checkstr ? checkstr : "(none)",
				(model->name && *model->name) ? strbuf : "(none)");
	}
	free(polystr);
	free(initstr);
	free(xorotstr);
	free(checkstr);
	if(!string)
		uerror("cannot allocate memory for model description");
	return(string);
}

void
mmatch(model_t *model, int flags) {
	/* searches models[] for a model matching the argument, and links a name if found
	 * if flags & M_OVERWR, copies the found model onto the argument. */
	model_t *mptr;
	if(!model) return;

	mptr = bsearch(model, models, NPRESETS, sizeof(model_t), (int (*)(const void *, const void *)) &mcmp);
	if(mptr) {
		model->name = mptr->name;
		if(flags & M_OVERWR)
			mcpy(model, mptr);
	}
}

void
mcanon(model_t *model) {
	/* canonicalise a model */
	unsigned long dlen;

	if(!model) return;

	/* extending on the right here. This preserves the functionality
	 * of a presumed working model.
	 */
	psnorm(&model->spoly);
	dlen = plen(model->spoly);
	praloc(&model->init, dlen);
	praloc(&model->xorout, dlen);

	if(!plen(model->check))
		mcheck(model);
}

void
mcheck(model_t *model) {
	/* calculate a check for the model */
	poly_t checkstr, check;

	/* generate the check string with the correct bit order */
	checkstr = strtop("313233343536373839", model->flags, 8);
	check = pcrc(checkstr, model->spoly, model->init, pzero, model->flags);
	if(model->flags & P_REFOUT)
		prev(&check);
	psum(&check, model->xorout, 0UL);
	model->check = check;
	pfree(&checkstr);
}

void
mrev(model_t *model) {
	/* reverse the model to calculate reversed CRCs */
	/* Here we invert RefIn and RefOut so that the user need only
	 * reverse the order of characters in the arguments, not the
	 * characters themselves.  If RefOut=True, the mirror image of
	 * Init seen through RefOut becomes XorOut, and as RefOut
	 * becomes false, the XorOut value moved to Init stays upright.
	 * If RefOut=False, Init transfers to XorOut without reflection
	 * but the new Init must be reflected to present the same image,
	 * as RefOut becomes true.
	 */
	poly_t temp;

	prcp(&model->spoly);
	if(model->flags & P_REFOUT)
		prev(&model->init);
	else
		prev(&model->xorout);

	/* exchange init and xorout */
	temp = model->init;
	model->init = model->xorout;
	model->xorout = temp;

	/* invert refin and refout */
	model->flags ^= P_REFIN | P_REFOUT;

	mnovel(model);
}

void
mnovel(model_t *model) {
	/* remove name and check string from modified model */
	model->name = NULL;
	pfree(&model->check);
}

static int
acmp(const struct malias *a, const struct malias *b) {
	/* compares two aliases, for use in bsearch */
	if(!a || !b) return(!b - !a);
	if(!a->name || !b->name) return(!b->name - !a->name);
	return(strcmp(a->name, b->name));
}

static void
munpack(model_t *dest, const struct mpreset *src) {
	/* Copies the parameters of src to dest.
	 * dest must be an initialised model.
	 */
	unsigned long iter, idx;
	if(!dest || !src) return;
	MUNPACK(spoly);
	MUNPACK(init);
	MUNPACK(xorout);
	MUNPACK(check);
	dest->flags = src->flags;
	/* link to the name as it is static */
	dest->name = src->name;
}
