|
| 1 | +// SPDX-FileCopyrightText: 2025 fosslinux <[email protected]> |
| 2 | +// SPDX-License-Identifier: GPL-3.0-or-later |
| 3 | + |
| 4 | +#include <stdio.h> |
| 5 | +#include <stdint.h> |
| 6 | +#include <stdbool.h> |
| 7 | + |
| 8 | +/* |
| 9 | + * Creates decDPD.h. |
| 10 | + * Based upon the algorithm given on; |
| 11 | + * https://web.archive.org/web/20080308073422/http://www2.hursley.ibm.com/decimal/DPDecimal.html |
| 12 | + * originally written in the (obsolete) language Rexx. |
| 13 | + * |
| 14 | + * Is not bit-for-bit identical to the original decDPD.h, as we don't bother |
| 15 | + * to follow the same formatting. |
| 16 | + * |
| 17 | + * The original Rexx code follows; |
| 18 | + */ |
| 19 | + |
| 20 | +// /* dpdGenerate.rex -- display Densely Packed Decimal table */ |
| 21 | +// /* mfc 2000.10.03; Rexx version with new equations 2007.02.01 */ |
| 22 | +// |
| 23 | +// do i=0 to 999 |
| 24 | +// bcd=right(i, 3, 0) -- make three-digit hexadecimal string |
| 25 | +// bit10=bcd2dpd(x2b(bcd)) -- compress |
| 26 | +// bit12=dpd2bcd(bit10) -- expand |
| 27 | +// say bcd bit10 bit12 -- display |
| 28 | +// end i |
| 29 | +// exit |
| 30 | +// |
| 31 | +// /* bcd2dpd -- Compress BCD to Densely Packed Decimal |
| 32 | +// argument is a string of 12 characters, each 0 or 1, being 3 digits |
| 33 | +// of 4 bits, each being a valid BCD digit (0000-1001) |
| 34 | +// (for example, 923 is 100100100011) |
| 35 | +// result is a string of 10 characters, each 0 or 1 |
| 36 | +// (for the example, this would be 1001010011) |
| 37 | +// */ |
| 38 | +// bcd2dpd: procedure |
| 39 | +// -- assign each bit to a variable, named as in the description |
| 40 | +// parse arg a +1 b +1 c +1 d +1 e +1 f +1 g +1 h +1 i +1 j +1 k +1 m +1 |
| 41 | +// |
| 42 | +// -- derive the result bits, using boolean expressions only |
| 43 | +// -- [the operators are: '&'=AND, '|'=OR, '\'=NOT.] |
| 44 | +// p=b | (a & j) | (a & f & i) |
| 45 | +// q=c | (a & k) | (a & g & i) |
| 46 | +// r=d |
| 47 | +// s=(f & (\a | \i)) | (\a & e & j) | (e & i) |
| 48 | +// t=g | (\a & e &k;) | (a & i) |
| 49 | +// u=h |
| 50 | +// v=a | e | i |
| 51 | +// w=a | (e & i) | (\e & j) |
| 52 | +// x=e | (a & i) | (\a & k) |
| 53 | +// y=m |
| 54 | +// -- concatenate the bits and return |
| 55 | +// return p||q||r||s||t||u||v||w||x||y |
| 56 | +// |
| 57 | +// /* dpd2bcd -- Expand Densely Packed Decimal to BCD |
| 58 | +// argument is a string of 10 characters, each 0 or 1; all 1024 |
| 59 | +// possibilities are accepted (non-canonicals -> 999) |
| 60 | +// (for example, 1001010011) |
| 61 | +// result is a string of 12 characters, each 0 or 1 |
| 62 | +// (for the example, 100100100011 -- 923) |
| 63 | +// */ |
| 64 | +// dpd2bcd: procedure |
| 65 | +// -- assign each bit to a variable, named as in the description |
| 66 | +// parse arg p +1 q +1 r +1 s +1 t +1 u +1 v +1 w +1 x +1 y +1 |
| 67 | +// |
| 68 | +// -- derive the result bits, using boolean expressions only |
| 69 | +// a= (v & w) & (\s | t | \x) |
| 70 | +// b=p & (\v | \w | (s & \t & x)) |
| 71 | +// c=q & (\v | \w | (s & \t & x)) |
| 72 | +// d=r |
| 73 | +// e=v & ((\w & x) | (\t & x) | (s & x)) |
| 74 | +// f=(s & (\v | \x)) | (p & \s & t & v & w & x) |
| 75 | +// g=(t & (\v | \x)) | (q & \s & t & w) |
| 76 | +// h=u |
| 77 | +// i=v & ((\w & \x) | (w & x & (s | t))) |
| 78 | +// j=(\v & w) | (s & v & \w & x) | (p & w & (\x | (\s & \t))) |
| 79 | +// k=(\v & x) | (t & \w & x) | (q & v & w & (\x | (\s & \t))) |
| 80 | +// m=y |
| 81 | +// -- concatenate the bits and return |
| 82 | +// return a||b||c||d||e||f||g||h||i||j||k||m |
| 83 | + |
| 84 | +void int2boolarr(uint32_t num, bool *arr, int bits) { |
| 85 | + int j = 0; |
| 86 | + for (int i = bits - 1; i >= 0; i--) { |
| 87 | + arr[j++] = (num >> i) & 0x1; |
| 88 | + } |
| 89 | +} |
| 90 | + |
| 91 | +uint32_t boolarr2int(bool *dpd, int bits) { |
| 92 | + uint32_t num = 0; |
| 93 | + int j = 0; |
| 94 | + for (int i = bits - 1; i >= 0; i--) { |
| 95 | + num |= dpd[j++] << i; |
| 96 | + } |
| 97 | + return num; |
| 98 | +} |
| 99 | + |
| 100 | +uint32_t bcd2dpd(uint16_t ibcd) { |
| 101 | + bool bcd[12]; |
| 102 | + int2boolarr(ibcd, bcd, 12); |
| 103 | + |
| 104 | + bool dpd[10]; |
| 105 | + dpd[0] = bcd[1] | (bcd[0] & bcd[9]) | (bcd[0] & bcd[5] & bcd[8]); |
| 106 | + dpd[1] = bcd[2] | (bcd[0] & bcd[10]) | (bcd[0] & bcd[6] & bcd[8]); |
| 107 | + dpd[2] = bcd[3]; |
| 108 | + dpd[3] = (bcd[5] & (~bcd[0] | ~bcd[8])) | (~bcd[0] & bcd[4] & bcd[9]) | (bcd[4] & bcd[8]); |
| 109 | + dpd[4] = bcd[6] | (~bcd[0] & bcd[4] & bcd[10]) | (bcd[0] & bcd[8]); |
| 110 | + dpd[5] = bcd[7]; |
| 111 | + dpd[6] = bcd[0] | bcd[4] | bcd[8]; |
| 112 | + dpd[7] = bcd[0] | (bcd[4] & bcd[8]) | (~bcd[4] & bcd[9]); |
| 113 | + dpd[8] = bcd[4] | (bcd[0] & bcd[8]) | (~bcd[0] & bcd[10]); |
| 114 | + dpd[9] = bcd[11]; |
| 115 | + |
| 116 | + return boolarr2int(dpd, 10); |
| 117 | +} |
| 118 | + |
| 119 | +uint32_t dpd2bcd(uint32_t idpd) { |
| 120 | + bool dpd[10]; |
| 121 | + int2boolarr(idpd, dpd, 10); |
| 122 | + |
| 123 | + bool bcd[12]; |
| 124 | + bcd[0] = (dpd[6] & dpd[7]) & (~dpd[3] | dpd[4] | ~dpd[8]); |
| 125 | + bcd[1] = dpd[0] & (~dpd[6] | ~dpd[7] | (dpd[3] & ~dpd[4] & dpd[8])); |
| 126 | + bcd[2] = dpd[1] & (~dpd[6] | ~dpd[7] | (dpd[3] & ~dpd[4] & dpd[8])); |
| 127 | + bcd[3] = dpd[2]; |
| 128 | + bcd[4] = dpd[6] & ((~dpd[7] & dpd[8]) | (~dpd[4] & dpd[8]) | (dpd[3] & dpd[8])); |
| 129 | + bcd[5] = (dpd[3] & (~dpd[6] | ~dpd[8])) | (dpd[0] & ~dpd[3] & dpd[4] & dpd[6] & dpd[7] & dpd[8]); |
| 130 | + bcd[6] = (dpd[4] & (~dpd[6] | ~dpd[8])) | (dpd[1] & ~dpd[3] & dpd[4] & dpd[7]); |
| 131 | + bcd[7] = dpd[5]; |
| 132 | + bcd[8] = dpd[6] & ((~dpd[7] & ~dpd[8]) | (dpd[7] & dpd[8] & (dpd[3] | dpd[4]))); |
| 133 | + bcd[9] = (~dpd[6] & dpd[7]) | (dpd[3] & dpd[6] & ~dpd[7] & dpd[8]) | (dpd[0] & dpd[7] & (~dpd[8] | (~dpd[3] & ~dpd[4]))); |
| 134 | + bcd[10] = (~dpd[6] & dpd[8]) | (dpd[4] & ~dpd[7] & dpd[8]) | (dpd[1] & dpd[6] & dpd[7] & (~dpd[8] | (~dpd[3] & ~dpd[4]))); |
| 135 | + bcd[11] = dpd[9]; |
| 136 | + |
| 137 | + return boolarr2int(bcd, 12); |
| 138 | +} |
| 139 | + |
| 140 | +uint8_t get_cntrl_char(uint8_t num) { |
| 141 | + if (num == 0) { |
| 142 | + return 0; |
| 143 | + } else if (num < 10) { |
| 144 | + return 1; |
| 145 | + } else if (num < 100) { |
| 146 | + return 2; |
| 147 | + } else { |
| 148 | + return 3; |
| 149 | + } |
| 150 | +} |
| 151 | + |
| 152 | +void bin2char(uint8_t num, uint32_t str[4]) { |
| 153 | + str[0] = get_cntrl_char(num); |
| 154 | + str[1] = num / 100 + '0'; |
| 155 | + str[2] = (num % 100) / 10 + '0'; |
| 156 | + str[3] = num % 10 + '0'; |
| 157 | +} |
| 158 | + |
| 159 | +void bin2bcd8(uint8_t num, char digit[4], uint32_t arr[4]) { |
| 160 | + for (int i = 0; i < 3; i++) { |
| 161 | + arr[i] = digit[i] - '0'; |
| 162 | + } |
| 163 | + arr[3] = get_cntrl_char(num); |
| 164 | +} |
| 165 | + |
| 166 | +#define TABLES_COUNT 9 |
| 167 | + |
| 168 | +int main(void) { |
| 169 | + uint32_t BCD2DPD[2458] = {0}; |
| 170 | + uint32_t BIN2DPD[1000] = {0}; |
| 171 | + uint32_t BIN2BCD8[4000]; |
| 172 | + uint32_t BIN2CHAR[4001]; |
| 173 | + uint32_t DPD2BCD[1024] = {0}; |
| 174 | + uint32_t DPD2BIN[1024] = {0}; |
| 175 | + uint32_t DPD2BINK[1024] = {0}; |
| 176 | + uint32_t DPD2BINM[1024] = {0}; |
| 177 | + uint32_t DPD2BCD8[4096]; |
| 178 | + |
| 179 | + for (int i = 0; i < 1000; i++) { |
| 180 | + char digit[4]; |
| 181 | + snprintf(digit, 4, "%03d", i); |
| 182 | + uint32_t bcd = 0; |
| 183 | + for (int j = 0; j < 3; j++) { |
| 184 | + bcd |= (digit[j] - '0') << (4 * (2 - j)); |
| 185 | + } |
| 186 | + |
| 187 | + uint32_t dpd = bcd2dpd(bcd); |
| 188 | + BCD2DPD[bcd] = dpd; |
| 189 | + DPD2BCD[dpd] = bcd; |
| 190 | + BIN2DPD[i] = dpd; |
| 191 | + DPD2BIN[dpd] = i; |
| 192 | + DPD2BINK[dpd] = i * 1000; |
| 193 | + DPD2BINM[dpd] = i * 1E+6; |
| 194 | + |
| 195 | + bin2char(i, BIN2CHAR + (4 * i)); |
| 196 | + bin2bcd8(i, digit, BIN2BCD8 + (4 * i)); |
| 197 | + bin2bcd8(i, digit, DPD2BCD8 + (4 * dpd)); |
| 198 | + } |
| 199 | + BIN2CHAR[4000] = '\0'; |
| 200 | + |
| 201 | + char *names[] = { |
| 202 | + "BCD2DPD", "BIN2DPD", "BIN2CHAR", "BIN2BCD8", "DPD2BCD", "DPD2BIN", |
| 203 | + "DPD2BINK", "DPD2BINM", "DPD2BCD8", |
| 204 | + }; |
| 205 | + char *types[] = { |
| 206 | + "uint16_t", "uint16_t", "uint8_t", "uint8_t", "uint16_t", "uint16_t", |
| 207 | + "uint32_t", "uint32_t", "uint8_t", |
| 208 | + }; |
| 209 | + uint32_t *data[] = { |
| 210 | + BCD2DPD, BIN2DPD, BIN2CHAR, BIN2BCD8, DPD2BCD, DPD2BIN, |
| 211 | + DPD2BINK, DPD2BINM, DPD2BCD8, |
| 212 | + }; |
| 213 | + int lengths[] = {2458, 1000, 4001, 4000, 1024, 1024, 1024, 1024, 4096}; |
| 214 | + |
| 215 | + for (int i = 0; i < TABLES_COUNT; i++) { |
| 216 | + printf("#if defined(DEC_%s) && DEC_%s==1 && !defined(DEC%s)\n", names[i], names[i], names[i]); |
| 217 | + printf("#define DEC%s\n", names[i]); |
| 218 | + printf("const %s %s[%d] = {\n", types[i], names[i], lengths[i]); |
| 219 | + for (int j = 0; j < lengths[i] / 16; j++) { |
| 220 | + for (int k = j * 16; k < (j + 1) * 16 && k < lengths[i]; k++) { |
| 221 | + printf("%s%d,", k == j * 16 ? "" : " ", data[i][k]); |
| 222 | + } |
| 223 | + printf("\n"); |
| 224 | + } |
| 225 | + printf("};\n"); |
| 226 | + printf("#endif\n\n"); |
| 227 | + } |
| 228 | +} |
0 commit comments