Project Euler Solutions
bcd.h
Go to the documentation of this file.
1 
7 #include <stdbool.h>
8 #include <stdint.h>
9 #include <string.h>
10 #include "macros.h"
11 
12 #include <stdlib.h>
13 #include <math.h>
14 
15 #ifdef DOXYGEN
16 namespace c::include::bcd {
17 #endif
18 
20 
32 typedef uint8_t packed_BCD_pair;
33 
37 typedef enum {
42 } comp_t;
43 
47 typedef enum {
64 } BCD_error;
65 
69 typedef struct BCD_int {
70  packed_BCD_pair *data;
71  size_t bcd_digits;
72  size_t decimal_digits;
73  union {
74  uint8_t nan;
75  PACK(struct {
76  BCD_error error : 4;
77  BCD_error orig_error : 4;
78  });
79  };
80  bool negative : 1;
81  bool zero : 1;
82  bool even : 1;
83  bool constant : 1;
84 } BCD_int;
85  // // end of types
88 
98 const BCD_int BCD_two = {
99  .data = (packed_BCD_pair[]) {2},
100  .bcd_digits = 1,
101  .decimal_digits = 1,
102  .even = true,
103  .constant = true
104 }; // note that non-specified values are initialized to NULL or 0
105 
107 const BCD_int BCD_one = {
108  .data = (packed_BCD_pair[]) {1},
109  .bcd_digits = 1,
110  .decimal_digits = 1,
111  .constant = true
112 }; // note that non-specified values are initialized to NULL or 0
113 
115 const BCD_int BCD_zero = {
116  .zero = true,
117  .even = true,
118  .constant = true
119 }; // note that non-specified values are initialized to NULL or 0
120 
122 const BCD_int BCD_nan = {
123  .error = ORIG_NAN,
124  .orig_error = ORIG_NAN,
125  .constant = true,
126 }; // note that non-specified values are initialized to NULL or 0
127  // // end of constants
130 
149 void free_BCD_int(BCD_int *const x);
150  // // end of destructor
153 
171 BCD_int new_BCD_int1(const intmax_t a);
172 
183 BCD_int new_BCD_int2(uintmax_t a, const bool negative);
184 
195 
208 BCD_int BCD_from_bytes(const unsigned char *const str, const size_t chars, const bool negative, const bool little_endian);
209 
221 BCD_int BCD_from_ascii(const char *const str, const size_t digits, const bool negative);
222 
234 BCD_int bcd_error(const BCD_error error, const BCD_error orig_error);
235  // // end of constructor
238 
262 comp_t cmp_bcd(const BCD_int x, const BCD_int y);
263 
278 BCD_int sign_bcd(BCD_int x, const bool no_copy, const bool negative);
279 
294 BCD_int abs_bcd(const BCD_int x, const bool no_copy);
295 
310 BCD_int neg_bcd(const BCD_int x, const bool no_copy);
311 
326 BCD_int opp_bcd(const BCD_int x, const bool no_copy);
327 
345 BCD_int add_bcd(const BCD_int x, const BCD_int y);
346 
360 BCD_int inc_bcd(const BCD_int x);
361 
379 BCD_int sub_bcd(const BCD_int x, const BCD_int y);
380 
394 BCD_int dec_bcd(const BCD_int x);
395 
411 BCD_int mul_bcd(const BCD_int x, const BCD_int y);
412 
428 BCD_int div_bcd(const BCD_int x, const BCD_int y);
429 
448 BCD_int mod_bcd(const BCD_int x, const BCD_int y);
449 
470 BCD_int divmod_bcd(const BCD_int x, BCD_int y, BCD_int *mod);
471 
488 BCD_int pow_bcd(const BCD_int x, const BCD_int y);
489 
505 BCD_int factorial_bcd(const BCD_int x);
506  // // end of operators
509 
529 void isign_bcd(BCD_int *const x, const bool negative);
530 
542 void iabs_bcd(BCD_int *const x);
543 
555 void ineg_bcd(BCD_int *const x);
556 
568 void iopp_bcd(BCD_int *const x);
569 
582 void iadd_bcd(BCD_int *const x, const BCD_int y);
583 
595 void iinc_bcd(BCD_int *const x);
596 
609 void isub_bcd(BCD_int *const x, const BCD_int y);
610 
622 void idec_bcd(BCD_int *const x);
623 
636 void imul_bcd(BCD_int *const x, const BCD_int y);
637 
652 void idiv_bcd(BCD_int *const x, const BCD_int y);
653 
668 void imod_bcd(BCD_int *const x, const BCD_int y);
669 
684 void idivmod_bcd(BCD_int *const x, BCD_int *const y);
685 
700 void ipow_bcd(BCD_int *const x, const BCD_int y);
701 
715 void ifactorial_bcd(BCD_int *const x);
716  // // end of in_place_operators
719 
737 uintmax_t abs_bcd_cuint(const BCD_int x);
738 
748 intmax_t val_bcd_cint(const BCD_int x);
749 
762 comp_t cmp_bcd_cint(const BCD_int x, const intmax_t y);
763 
776 comp_t cmp_bcd_cuint(const BCD_int x, const uintmax_t y);
777 
789 BCD_int mul_bcd_cint(const BCD_int x, const intmax_t y);
790 
802 BCD_int mul_bcd_cuint(const BCD_int x, uintmax_t y);
803 
817 BCD_int mul_bcd_pow_10(const BCD_int x, const size_t tens);
818 
834 BCD_int shift_bcd_left(const BCD_int a, const size_t tens);
835 
853 BCD_int div_bcd_pow_10(const BCD_int x, const size_t tens);
854 
874 BCD_int shift_bcd_right(const BCD_int a, const size_t tens);
875 
887 BCD_int pow_cint_cuint(const intmax_t x, uintmax_t y);
888 
900 BCD_int pow_cuint_cuint(const uintmax_t x, uintmax_t y);
901  // // end of bcd_c_operators
904 
925 void imul_bcd_cint(BCD_int *const x, const intmax_t y);
926 
939 void imul_bcd_cuint(BCD_int *const x, const uintmax_t y);
940 
953 void imul_bcd_pow_10(BCD_int *const x, const size_t tens);
954 
967 void ishift_bcd_left(BCD_int *const a, const size_t tens);
968 
983 void idiv_bcd_pow_10(BCD_int *const x, const size_t tens);
984 
999 void ishift_bcd_right(BCD_int *const a, const size_t tens);
1000  // // end of in_place_bcd_c_operators
1003 
1020 uint16_t mul_dig_pair(const packed_BCD_pair ab, const packed_BCD_pair cd);
1021 
1029 void print_bcd(const BCD_int x);
1030 
1038 void print_bcd_ln(const BCD_int x);
1039  // // end of bcd_utility
1042 
1043 inline void free_BCD_int(BCD_int *const x) {
1044  if (x->error != IS_FREED && !x->constant) {
1045  free(x->data);
1046  *x = (BCD_int) {.error = IS_FREED, .orig_error = IS_FREED};
1047  }
1048 }
1049 
1050 BCD_int new_BCD_int1(const intmax_t a) {
1051  if (a < 0)
1052  return new_BCD_int2((uintmax_t) (-a), true);
1053  return new_BCD_int2((uintmax_t) a, false);
1054 }
1055 
1056 BCD_int new_BCD_int2(uintmax_t a, const bool negative) {
1057  BCD_int c = {
1058  .negative = negative,
1059  .even = !(a % 2),
1060  .zero = !a,
1061  .decimal_digits = (size_t) ceil(log10((double) (a + 1))),
1062  };
1063  c.bcd_digits = (c.decimal_digits + 1) / 2;
1064  c.data = (packed_BCD_pair *) malloc(sizeof(packed_BCD_pair) * c.bcd_digits);
1065  if (unlikely(c.data == NULL))
1066  return bcd_error(NO_MEM, NO_MEM);
1067  for (size_t i = 0; i < c.bcd_digits; i++) {
1068  c.data[i] = (((a % 100) / 10) << 4) | (a % 10);
1069  a /= 100;
1070  }
1071  return c;
1072 }
1073 
1075  if (likely(a.data != NULL)) {
1076  const packed_BCD_pair *const data = a.data;
1077  a.data = (packed_BCD_pair *) malloc(sizeof(packed_BCD_pair) * a.bcd_digits);
1078  if (unlikely(a.data == NULL))
1079  return bcd_error(NO_MEM, NO_MEM);
1080  memcpy(a.data, data, a.bcd_digits);
1081  }
1082  a.constant = false;
1083  return a;
1084 }
1085 
1086 BCD_int BCD_from_bytes(const unsigned char *const str, const size_t chars, const bool negative, const bool little_endian) {
1087  // converts a BCD-formatted bytestring to a little-endian BCD int
1088  if (!chars || str == NULL)
1089  return BCD_zero;
1090  size_t i;
1091  BCD_int c = (BCD_int) {
1092  .negative = negative,
1093  .data = (packed_BCD_pair *) malloc(sizeof(packed_BCD_pair) * chars),
1094  };
1095  if (unlikely(c.data == NULL))
1096  return bcd_error(NO_MEM, NO_MEM);
1097  if (little_endian) {
1098  memcpy(c.data, str, chars);
1099  }
1100  else {
1101  size_t j;
1102  for (i = 0, j = chars - 1; i < chars; i++, j--) {
1103  c.data[i] = str[j];
1104  }
1105  }
1106  for (i = chars - 1; i != -1; i--) {
1107  if (c.data[i]) {
1108  c.bcd_digits = i + 1;
1109  if (c.data[i] & 0xF0)
1110  c.decimal_digits = i * 2 + 1;
1111  else
1112  c.decimal_digits = i * 2;
1113  break;
1114  }
1115  }
1116  if (unlikely(i == -1)) {
1117  free_BCD_int(&c);
1118  return BCD_zero;
1119  }
1120  c.even = !(c.data[0] % 2);
1121  return c;
1122 }
1123 
1124 BCD_int BCD_from_ascii(const char *const str, const size_t digits, const bool negative) {
1125  // packs an ASCII digit string into big-endian bytes, then runs through BCD_from_bytes()
1126  const size_t length = (digits + 1) / 2;
1127  size_t i, j;
1128  unsigned char * const bytes = (unsigned char *) malloc(sizeof(unsigned char) * length);
1129  if (unlikely(bytes == NULL))
1130  return bcd_error(NO_MEM, NO_MEM);
1131  if ((j = i = digits % 2))
1132  bytes[0] = str[0] - '0';
1133  for (; i < length; i++, j += 2) {
1134  bytes[i] = ((str[j] - '0') << 4) | ((str[j + 1] - '0') & 0xF);
1135  }
1136  BCD_int ret = BCD_from_bytes(bytes, length, negative, false);
1137  free(bytes);
1138  return ret;
1139 }
1140 
1141 inline BCD_int bcd_error(const BCD_error error, const BCD_error orig_error) {
1142  return (BCD_int) { // note that uninitialized data is 0 or NULL
1143  .error = error,
1144  .orig_error = orig_error
1145  };
1146 }
1147 
1148 comp_t cmp_bcd(const BCD_int x, const BCD_int y) {
1149  // returns:
1150  // NO_COMP if (x.nan || y.nan)
1151  // GREATER_THAN if x > y
1152  // LESS_THAN if x < y
1153  // EQUAL_TO else
1154  if (unlikely(x.nan || y.nan))
1155  return NO_COMP;
1156  if (x.negative != y.negative)
1157  return (x.negative) ? LESS_THAN : GREATER_THAN;
1158  if (x.decimal_digits != y.decimal_digits) {
1159  if (x.decimal_digits > y.decimal_digits)
1160  return (x.negative) ? LESS_THAN : GREATER_THAN;
1161  return (x.negative) ? GREATER_THAN : LESS_THAN;
1162  }
1163  for (size_t i = x.bcd_digits - 1; i != -1; i--) {
1164  if (x.data[i] != y.data[i]) {
1165  if (x.negative)
1166  return (x.data[i] > y.data[i]) ? LESS_THAN : GREATER_THAN;
1167  return (x.data[i] > y.data[i]) ? GREATER_THAN : LESS_THAN;
1168  }
1169  }
1170  return EQUAL_TO;
1171 }
1172 
1173 inline bool bool_bcd(const BCD_int x) {
1174  return x.zero;
1175 }
1176 
1177 inline bool not_bcd(const BCD_int x) {
1178  return !x.zero;
1179 }
1180 
1181 inline BCD_int sign_bcd(BCD_int x, const bool no_copy, const bool negative) {
1182  if (likely(!x.nan))
1183  x.negative = negative;
1184  return (no_copy) ? x : copy_BCD_int(x);
1185 }
1186 
1187 inline BCD_int abs_bcd(const BCD_int x, const bool no_copy) {
1188  return sign_bcd(x, no_copy, false);
1189 }
1190 
1191 inline BCD_int neg_bcd(const BCD_int x, const bool no_copy) {
1192  return sign_bcd(x, no_copy, true);
1193 }
1194 
1195 inline BCD_int opp_bcd(const BCD_int x, const bool no_copy) {
1196  return sign_bcd(x, no_copy, !x.negative);
1197 }
1198 
1199 BCD_int add_bcd(const BCD_int x, const BCD_int y) {
1200  if (unlikely(x.nan || y.nan))
1201  return bcd_error(ADD_NAN, (x.nan) ? x.orig_error : y.orig_error);
1202  if (unlikely(x.zero))
1203  return copy_BCD_int(y);
1204  if (unlikely(y.zero))
1205  return copy_BCD_int(x);
1206  if (x.negative != y.negative)
1207  return sub_bcd(x, opp_bcd(y, true));
1208  // if signs don't match, absolute value would go down.
1209  // that means we need to flip y's sign and move through sub_bcd()
1210  if (cmp_bcd(abs_bcd(x, true), abs_bcd(y, true)) == LESS_THAN) // remember this compares absolute values
1211  return add_bcd(y, x);
1212  // this lets us have x be constant
1213  BCD_int z = (BCD_int) {
1214  .negative = x.negative, // we know this is also y.negative
1215  .data = (packed_BCD_pair *) malloc(sizeof(packed_BCD_pair) * (x.bcd_digits + 1)), // in case of final overflow
1216  };
1217  if (unlikely(z.data == NULL))
1218  return bcd_error(NO_MEM, NO_MEM);
1219  size_t i;
1220  uint8_t overflow = false; // note that it's only ever set to 0 or 1, but assembly complains if bool is specified
1221  packed_BCD_pair a, b, c;
1222  for (i = 0; i < y.bcd_digits; i++) {
1223  a = x.data[i];
1224  b = y.data[i];
1225  if (!(overflow || a)) {
1226  c = b;
1227  overflow = false;
1228  }
1229  else if (!(overflow || b)) {
1230  c = a;
1231  overflow = false;
1232  }
1233  else {
1234  b += overflow; // incorporate overflow from last pair
1235  #if (!defined(NO_ASSEMBLY) && X86_COMPILER) // if on these architectures, there's assembly tricks to adjust BCD in-silicon
1236  #if CL_COMPILER
1237  // CL compiler has a different syntax for inline assembly, does a lot less lifting
1238  // note that the syntax here is: op [dest [, src]]
1239  // brackets indicate a C symbol is referenced rather than a register
1240  __asm {
1241  mov al, [a]; // move C symbol a to register al
1242  add al, [b]; // add C symbol b to register al
1243  daa; // have the CPU make sure register al contains valid, packed BCD digits
1244  setc [overflow]; // set C symbol overflow to contain the carry bit, set by daa
1245  mov [c], al; // move register al to C symbol c
1246  }
1247  #else
1248  // this is the standard GCC/LLVM syntax for it
1249  // note that the syntax here is: op [[src, ] dest]
1250  // %\d indicates a C symbol is referenced, see the lookups at the end of code for which
1251  __asm__(
1252  "add %3, %%al;" // add the register containing b to al
1253  "daa;" // have the CPU make sure register al contains valid, packed BCD digits
1254  "setc %1;" // set the register containing overflow to hold the carry bit, set by daa
1255  // this next section tells the compiler what to do after execution
1256  : "=a" (c), // store the contents of register al in symbol c
1257  "=rgm" (overflow) // and a general register or memory location gets assigned to symbol overflow (referenced as %1)
1258  // then below tells the compiler what our inputs are
1259  : "a" (a), // symbol a should get dumped to register al
1260  "rgm" (b) // and symbol b in a general register or memory location (referenced as %3)
1261  );
1262  #endif
1263  #else // otherwise fall back to doing it in C
1264  c = a + b; // set c to be the result of (a + b) % 0x100
1265  if ((overflow = (a > 0x99 - b))) // if c would overflow the decimal range
1266  c += 0x60; // and add 0x60 to make a decimal digit
1267  if (((a & 0xF) + (b & 0xF)) > 9) // if the lower nibble be bigger than 9
1268  c += 0x06; // add 6 to make a decimal digit
1269  #endif
1270  }
1271  z.data[i] = c;
1272  }
1273  for (; i < x.bcd_digits; i++) { // while there's overflow and digits, continue adding
1274  a = x.data[i] + overflow;
1275  if ((a & 0x0F) == 0x0A) // since all that's left is overflow, we don't need to check ranges
1276  a += 0x06;
1277  if ((overflow = ((a & 0xF0) == 0xA0)))
1278  a += 0x60;
1279  z.data[i] = a;
1280  }
1281  if (i < x.bcd_digits) // if there's no more overflow, but still digits left, copy directly
1282  memcpy(z.data + i, x.data + i, x.bcd_digits - i);
1283  z.bcd_digits = x.bcd_digits + overflow;
1284  if ((z.data[x.bcd_digits] = overflow))
1285  z.decimal_digits = x.bcd_digits * 2 + 1;
1286  else if (z.data[x.bcd_digits - 1] & 0xF0)
1287  z.decimal_digits = x.bcd_digits * 2;
1288  else
1289  z.decimal_digits = x.bcd_digits * 2 - 1;
1290  z.even = !(z.data[0] % 2);
1291  return z;
1292 }
1293 
1294 inline BCD_int inc_bcd(const BCD_int x) {
1295  return add_bcd(x, BCD_one);
1296 }
1297 
1298 BCD_int sub_bcd(const BCD_int x, const BCD_int y) {
1299  if (x.negative != y.negative)
1300  return add_bcd(x, opp_bcd(y, true));
1301  // if signs don't match, absolute value would go up.
1302  // that means we need to flip y's sign and move through add_bcd()
1303  if (unlikely(x.nan || y.nan))
1304  return bcd_error(SUB_NAN, (x.nan) ? x.orig_error : y.orig_error);
1305  const comp_t cmp = cmp_bcd(x, y);
1306  if (unlikely(cmp == EQUAL_TO))
1307  return BCD_zero;
1308  if (unlikely(x.zero))
1309  return opp_bcd(y, false);
1310  if (unlikely(y.zero))
1311  return copy_BCD_int(x);
1312  if ((x.negative && cmp == GREATER_THAN) || (!x.negative && cmp == LESS_THAN))
1313  return opp_bcd(sub_bcd(y, x), true);
1314  // it's easier to do this than it is to properly handle 10s complement math
1315  BCD_int z = (BCD_int) {
1316  .data = (packed_BCD_pair *) malloc(sizeof(packed_BCD_pair) * x.bcd_digits),
1317  .negative = x.negative, // remember this is the same as y.negative, and that |y| is less than |x|
1318  };
1319  if (unlikely(z.data == NULL))
1320  return bcd_error(NO_MEM, NO_MEM);
1321  bool carry = false;
1322  size_t i;
1323  packed_BCD_pair a, b, c;
1324  for (i = 0; i < y.bcd_digits; i++) {
1325  a = x.data[i];
1326  b = y.data[i];
1327  b += carry; // incorporate carry from last pair
1328  #if (!defined(NO_ASSEMBLY) && X86_COMPILER) // if on these architectures, there's assembly tricks to adjust BCD in-silicon
1329  #if CL_COMPILER
1330  // CL compiler has a different syntax for inline assembly, does a lot less lifting
1331  // note that the syntax here is: op [dest [, src]]
1332  // brackets indicate a C symbol is referenced rather than a register
1333  __asm {
1334  mov al, [a]; // move C symbol a to register al
1335  sub al, [b]; // subtract C symbol b from register al
1336  das; // have the CPU make sure register al contains valid, packed BCD digits
1337  setc [carry]; // set C symbol carry to contain the carry bit, set by daa
1338  mov [c], al; // move register al to C symbol c
1339  }
1340  #else
1341  // this is the standard GCC/LLVM syntax for it
1342  // note that the syntax here is: op [[src, ] dest]
1343  // %\d indicates a C symbol is referenced, see the lookups at the end of code for which
1344  __asm__(
1345  "sub %3, %%al;" // subtract the register containing b from al
1346  "das;" // have the CPU make sure register al contains valid, packed BCD digits
1347  "setc %1;" // set the register containing carry to hold the carry bit, set by daa
1348  // this next section tells the compiler what to do after execution
1349  : "=a" (c), // store the contents of register al in symbol c
1350  "=rgm" (carry) // and a general register or memory location gets assigned to symbol carry (referenced as %1)
1351  // then below tells the compiler what our inputs are
1352  : "a" (a), // symbol a should get dumped to register al
1353  "rgm" (b) // and symbol b in a general register or memory location (referenced as %3)
1354  );
1355  #endif
1356  #else // otherwise fall back to doing it in C. the code below should replicate the DAS x86 instruction
1357  const uint8_t old_c = c = a - b;
1358  const bool AF = ((int8_t) (a & 0x0F) - (b & 0x0F)) < 0; // this is to replicate the x86 AF flag
1359  const bool old_carry = ((int16_t) a - b) < 0;
1360  carry = false;
1361  if (AF || ((c & 0x0F) > 0x09)) { // if the lower nibble borrowed, or it's greater than 9
1362  carry = old_carry || (((int16_t) c - 0x06) < 0);
1363  c -= 0x06;
1364  }
1365  if (old_carry || (old_c > 0x99)) { // if the initial subtraction carried, or the original value overflowed
1366  carry = true;
1367  c -= 0x60;
1368  }
1369  #endif
1370  z.data[i] = c;
1371  }
1372  for (; carry && i < x.bcd_digits; i++) { // while there's carry and digits, continue adding
1373  a = x.data[i] - carry;
1374  if ((a & 0x0F) == 0x0F) // since all that's left is carry, we don't need to check ranges
1375  a -= 0x06;
1376  if ((carry = ((a & 0xF0) == 0xF0)))
1377  a -= 0x60;
1378  z.data[i] = a;
1379  }
1380  if (i < x.bcd_digits) // if there's no more carry, but still digits left, copy directly
1381  memcpy(z.data + i, x.data + i, x.bcd_digits - i);
1382  i = x.bcd_digits;
1383  while (--i != -1) {
1384  if (z.data[i]) {
1385  z.bcd_digits = i + 1;
1386  if (z.data[i] & 0xF0)
1387  z.decimal_digits = 2 * z.bcd_digits;
1388  else
1389  z.decimal_digits = 2 * z.bcd_digits - 1;
1390  z.even = !(z.data[0] % 2);
1391  return z;
1392  }
1393  }
1394  free_BCD_int(&z); // should not get here, but just in case
1395  return BCD_zero;
1396 }
1397 
1398 
1399 inline BCD_int dec_bcd(const BCD_int x) {
1400  return sub_bcd(x, BCD_one);
1401 }
1402 
1403 BCD_int mul_bcd(const BCD_int x, const BCD_int y) {
1404  // multiplies two BCD ints by breaking them down into their component bytes and adding the results
1405  // this takes O(log_100(x) * log_100(y) * log_100(xy)) time
1406  if (unlikely(x.nan || y.nan))
1407  return bcd_error(MUL_NAN, (x.nan) ? x.orig_error : y.orig_error);
1408  if (unlikely(x.zero || y.zero))
1409  return BCD_zero;
1410  if (unlikely(x.decimal_digits == 1 && x.data[0] == 1))
1411  return sign_bcd(y, false, !(x.negative == y.negative));
1412  if (unlikely(y.decimal_digits == 1 && y.data[0] == 1))
1413  return sign_bcd(x, false, !(x.negative == y.negative));
1415  return new_BCD_int2(abs_bcd_cuint(x) * abs_bcd_cuint(y), !(x.negative == y.negative));
1416  // if they're small enough to multiply directly, do so
1417  BCD_int answer = BCD_nan, tmp;
1418  const size_t digits = min(x.decimal_digits, y.decimal_digits);
1419  if (digits < 256) {
1420  // grid method
1421  // this relies on the same principle as FOIL. basically:
1422  // AB * CD = 100AC + 10(BC + AD) + BD, done for each byte
1423  size_t i, j, pow_10, ipow_10 = 0;
1424  uint16_t staging;
1425  answer = BCD_zero;
1426  for (i = 0; i < x.bcd_digits; i++, ipow_10 += 2) {
1427  for (j = 0, pow_10 = ipow_10; j < y.bcd_digits; j++, pow_10 += 2) {
1428  if ((staging = mul_dig_pair(x.data[i], y.data[j])) == 0)
1429  continue;
1430  tmp = new_BCD_int2(staging, false);
1431  if (likely(pow_10))
1432  imul_bcd_pow_10(&tmp, pow_10);
1433  iadd_bcd(&answer, tmp);
1434  free_BCD_int(&tmp);
1435  }
1436  }
1437  }
1438  else {
1439  // recursive karatsuba
1440  const size_t cutoff = digits / 2;
1441  tmp = shift_bcd_left(BCD_one, cutoff);
1442  // first divide each number roughly in half
1443  BCD_int x_lower = mod_bcd(abs_bcd(x, true), tmp),
1444  x_higher = shift_bcd_right(abs_bcd(x, true), cutoff),
1445  y_lower = mod_bcd(abs_bcd(y, true), tmp),
1446  y_higher = shift_bcd_right(abs_bcd(y, true), cutoff);
1447  free_BCD_int(&tmp);
1448  // then set up the z variables
1449  BCD_int z0 = mul_bcd(x_lower, y_lower),
1450  z1 = add_bcd(x_lower, x_higher), // not final value
1451  z2 = mul_bcd(x_higher, y_higher);
1452  tmp = add_bcd(y_lower, y_higher);
1453  imul_bcd(&z1, tmp);
1454  isub_bcd(&z1, z0);
1455  isub_bcd(&z1, z2);
1456  free_BCD_int(&tmp);
1457  free_BCD_int(&x_lower);
1458  free_BCD_int(&x_higher);
1459  free_BCD_int(&y_lower);
1460  free_BCD_int(&y_higher);
1461  ishift_bcd_left(&z2, 2 * cutoff);
1462  ishift_bcd_left(&z1, cutoff);
1463  answer = add_bcd(z0, z1);
1464  iadd_bcd(&answer, z2);
1465  free_BCD_int(&z0);
1466  free_BCD_int(&z1);
1467  free_BCD_int(&z2);
1468  }
1469  return sign_bcd(answer, true, !(x.negative == y.negative));
1470 }
1471 
1472 inline BCD_int div_bcd(const BCD_int x, const BCD_int y) {
1473  return divmod_bcd(x, y, NULL);
1474 }
1475 
1476 inline BCD_int mod_bcd(const BCD_int x, const BCD_int y) {
1477  if (y.decimal_digits == 1 && y.data[0] == 1) {
1478  return BCD_zero;
1479  }
1480  BCD_int mod, div = divmod_bcd(x, y, &mod);
1481  free_BCD_int(&div);
1482  return mod;
1483 }
1484 
1486  BCD_int div = BCD_zero;
1487  if (unlikely(x.nan || y.nan || y.zero)) {
1488  BCD_error error, orig_error;
1489  orig_error = error = (y.zero) ? DIV_ZERO : DIV_NAN;
1490  if (x.nan)
1491  orig_error = x.orig_error;
1492  else if (y.nan)
1493  orig_error = y.orig_error;
1494  div = bcd_error(error, orig_error);
1495  if (mod != NULL)
1496  *mod = div;
1497  return div;
1498  }
1499  if (unlikely(x.zero)) {
1500  if (mod != NULL)
1501  *mod = BCD_zero;
1502  return div;
1503  }
1504  if (y.decimal_digits == 1 && y.data[0] == 1) {
1505  if (mod != NULL)
1506  *mod = BCD_zero;
1507  return sign_bcd(copy_BCD_int(x), true, x.negative != y.negative);
1508  }
1509  const bool x_negative = x.negative, y_negative = y.negative;
1510  const BCD_int divisor = abs_bcd(y, true);
1511  BCD_int tmp = abs_bcd(x, false);
1512  while ((tmp.decimal_digits - 1) > divisor.decimal_digits) { // first go through it by multiples of 10
1513  const size_t pow_10 = tmp.decimal_digits - divisor.decimal_digits - 1;
1514  BCD_int tmp2 = mul_bcd_pow_10(divisor, pow_10);
1515  isub_bcd(&tmp, tmp2);
1516  free_BCD_int(&tmp2);
1517  tmp2 = mul_bcd_pow_10(BCD_one, pow_10);
1518  iadd_bcd(&div, tmp2);
1519  free_BCD_int(&tmp2);
1520  }
1521  while (cmp_bcd(tmp, divisor) != LESS_THAN) { // x and y can't be NaN, so this is safe
1522  isub_bcd(&tmp, divisor);
1523  iinc_bcd(&div);
1524  }
1525  if ((div.negative = (x_negative != y_negative))) {
1526  if (!tmp.zero) {
1527  idec_bcd(&div);
1528  if (mod != NULL)
1529  *mod = sign_bcd(sub_bcd(divisor, tmp), true, y_negative);
1530  }
1531  else if (mod != NULL)
1532  *mod = BCD_zero;
1533  free_BCD_int(&tmp);
1534  }
1535  else if (mod != NULL) {
1536  *mod = sign_bcd(tmp, true, y_negative);
1537  }
1538  else {
1539  free_BCD_int(&tmp);
1540  }
1541  return div;
1542 }
1543 
1544 BCD_int pow_bcd(const BCD_int x, const BCD_int y) {
1545  if (unlikely(x.nan || y.nan || y.negative)) {
1546  BCD_error error, orig_error;
1547  if (y.negative) {
1548  orig_error = error = POW_NEG;
1549  }
1550  else {
1551  error = POW_NAN;
1552  orig_error = (x.nan) ? x.orig_error : y.orig_error;
1553  }
1554  return bcd_error(error, orig_error);
1555  }
1556  if (unlikely(x.zero))
1557  return BCD_zero;
1558  if (unlikely((x.decimal_digits == 1 && x.data[0] == 1) || y.zero)) // x == 1 || y == 0
1559  return BCD_one;
1560  if (unlikely(y.decimal_digits == 1 && y.data[0] == 1)) // y == 1
1561  return copy_BCD_int(x);
1562  if (y.decimal_digits == 1 && y.data[0] == 2) // y == 2
1563  return mul_bcd(x, x);
1564  // after all shortcuts are exhausted, solve by successive squaring
1565  // ex: x^13 = x * ((x * x^2)^2)^2
1566  BCD_int answer = BCD_one, tmp_x = copy_BCD_int(x), tmp_y = copy_BCD_int(y);
1567  while (!tmp_y.zero) {
1568  if (!tmp_y.even) {
1569  imul_bcd(&answer, tmp_x);
1570  }
1571  imul_bcd(&tmp_x, tmp_x);
1572  idiv_bcd(&tmp_y, BCD_two);
1573  }
1574  free_BCD_int(&tmp_x);
1575  free_BCD_int(&tmp_y);
1576  return answer;
1577 }
1578 
1580  if (unlikely(x.nan))
1581  return bcd_error(FACT_NAN, x.orig_error);
1582  if (unlikely(x.negative))
1583  return bcd_error(FACT_NEG, FACT_NEG);
1584  if (unlikely(x.zero || (x.decimal_digits == 1 && x.data[0] == 1)))
1585  return BCD_one;
1586  BCD_int i = dec_bcd(x), ret = copy_BCD_int(x);
1587  while (!i.zero) {
1588  imul_bcd(&ret, i);
1589  idec_bcd(&i);
1590  }
1591  free_BCD_int(&i);
1592  return ret;
1593 }
1594 
1595 inline void isign_bcd(BCD_int *const x, const bool negative) {
1596  if (!x->nan && x->constant)
1597  *x = copy_BCD_int(*x);
1598  if (likely(!x->nan)) // this needs a second check because copy can return NaN
1599  x->negative = negative;
1600 }
1601 
1602 inline void iabs_bcd(BCD_int *const x) {
1603  isign_bcd(x, false);
1604 }
1605 
1606 inline void ineg_bcd(BCD_int *const x) {
1607  isign_bcd(x, true);
1608 }
1609 
1610 inline void iopp_bcd(BCD_int *const x) {
1611  isign_bcd(x, !x->negative);
1612 }
1613 
1614 inline void iadd_bcd(BCD_int *const x, const BCD_int y) {
1615  BCD_int ret = add_bcd(*x, y);
1616  free_BCD_int(x);
1617  *x = ret;
1618 }
1619 
1620 inline void iinc_bcd(BCD_int *const x) {
1621  BCD_int ret = inc_bcd(*x);
1622  free_BCD_int(x);
1623  *x = ret;
1624 }
1625 
1626 inline void isub_bcd(BCD_int *const x, const BCD_int y) {
1627  BCD_int ret = sub_bcd(*x, y);
1628  free_BCD_int(x);
1629  *x = ret;
1630 }
1631 
1632 inline void idec_bcd(BCD_int *const x) {
1633  BCD_int ret = dec_bcd(*x);
1634  free_BCD_int(x);
1635  *x = ret;
1636 }
1637 
1638 inline void imul_bcd(BCD_int *const x, const BCD_int y) {
1639  BCD_int ret = mul_bcd(*x, y);
1640  free_BCD_int(x);
1641  *x = ret;
1642 }
1643 
1644 inline void idiv_bcd(BCD_int *const x, const BCD_int y) {
1645  BCD_int ret = div_bcd(*x, y);
1646  free_BCD_int(x);
1647  *x = ret;
1648 }
1649 
1650 inline void imod_bcd(BCD_int *const x, const BCD_int y) {
1651  BCD_int ret = mod_bcd(*x, y);
1652  free_BCD_int(x);
1653  *x = ret;
1654 }
1655 
1656 inline void idivmod_bcd(BCD_int *const x, BCD_int *const y) {
1657  BCD_int mod, div = divmod_bcd(*x, *y, &mod);
1658  free_BCD_int(x);
1659  free_BCD_int(y);
1660  *x = div;
1661  *y = mod;
1662 }
1663 
1664 inline void ipow_bcd(BCD_int *const x, const BCD_int y) {
1665  BCD_int ret = pow_bcd(*x, y);
1666  free_BCD_int(x);
1667  *x = ret;
1668 }
1669 
1670 void ifactorial_bcd(BCD_int *const x) {
1671  BCD_int ret = factorial_bcd(*x);
1672  free_BCD_int(x);
1673  *x = ret;
1674 }
1675 
1676 uintmax_t abs_bcd_cuint(const BCD_int x) {
1677  if (unlikely(x.nan || (x.decimal_digits > POW_OF_MAX_POW_10_64 + 2)))
1678  return -1; // overflow certain, or invalid number
1679  uintmax_t answer = 0, pow_10 = 1;
1680  for (size_t i = 0; i < x.bcd_digits; i++, pow_10 *= 100) {
1681  answer += pow_10 * ((x.data[i] & 0x0F) + 10 * (x.data[i] >> 4));
1682  }
1683  if ((x.data[0] & 0xF) != (answer % 10))
1684  return -1; // overflowed
1685  return answer;
1686 }
1687 
1688 intmax_t val_bcd_cint(const BCD_int x) {
1689  if (unlikely(x.nan || (x.decimal_digits > POW_OF_MAX_POW_10_64 + 1)))
1690  return INTMAX_MIN; // overflow certain, or invalid number
1691  uintmax_t answer = abs_bcd_cuint(x);
1692  if (answer > (uintmax_t) INTMAX_MAX)
1693  return INTMAX_MIN; // overflowed
1694  return ((x.negative) ? -((intmax_t) answer) : (intmax_t) answer);
1695 }
1696 
1697 inline comp_t cmp_bcd_cint(const BCD_int x, const intmax_t y) {
1698  if (y < 0) {
1699  comp_t inverse_answer = cmp_bcd_cuint(opp_bcd(x, true), (uintmax_t) (-y));
1700  if (inverse_answer == GREATER_THAN)
1701  return LESS_THAN;
1702  if (inverse_answer == LESS_THAN)
1703  return GREATER_THAN;
1704  return inverse_answer;
1705  }
1706  return cmp_bcd_cuint(x, (uintmax_t) y);
1707 }
1708 
1709 comp_t cmp_bcd_cuint(const BCD_int x, const uintmax_t y) {
1710  if (unlikely(x.nan))
1711  return NO_COMP;
1712  if (unlikely(x.zero))
1713  return (y) ? GREATER_THAN : EQUAL_TO;
1714  if (x.negative)
1715  return LESS_THAN;
1717  return GREATER_THAN;
1718  uintmax_t x_prime = abs_bcd_cuint(x);
1719  if (unlikely(x_prime == -1))
1720  return NO_COMP;
1721  if (x_prime > y)
1722  return GREATER_THAN;
1723  if (x_prime < y)
1724  return LESS_THAN;
1725  return EQUAL_TO;
1726 }
1727 
1728 inline BCD_int mul_bcd_cint(const BCD_int x, const intmax_t y) {
1729  if (y < 0)
1730  return opp_bcd(mul_bcd_cuint(x, (uintmax_t) (-y)), true);
1731  return mul_bcd_cuint(x, (uintmax_t) y);
1732 }
1733 
1734 BCD_int mul_bcd_cuint(const BCD_int x, uintmax_t y) {
1735  // this takes roughly O(log(y) * log(x)) time, and is nearly linear if y is a multiple of 10
1736  // it works by breaking the multiplication down into groups of addition
1737  // full formula for performance is something like:
1738  // y = 10^a * b
1739  // f(i) = sum(n = 1 thru 19, (i % 10^(n + 1)) / 10^n) + i / 10^20
1740  // bool(i) = 1 if i else 0
1741  // time = O(bool(a) * log_100(x) + f(b) * log_100(xy))
1742  if (unlikely(x.nan))
1743  return bcd_error(MUL_NAN, x.orig_error);
1744  if (unlikely(!y || x.zero))
1745  return BCD_zero;
1746  uint8_t tens = 0; // will up size when there's an 848-bit system
1747  BCD_int ret = BCD_zero, mul_by_power_10;
1748  while (y % 10 == 0) {
1749  y /= 10; // first remove factors of ten
1750  ++tens;
1751  }
1752  if (tens)
1753  ret = mul_bcd_pow_10(x, tens);
1754  // then for decreasing powers of ten, batch additions
1755  tens = POW_OF_MAX_POW_10_64;
1756  for (uintmax_t p = MAX_POW_10_64; p > 1; p /= 10, --tens) {
1757  while (y >= p) {
1758  mul_by_power_10 = mul_bcd_pow_10(x, tens);
1759  iadd_bcd(&ret, mul_by_power_10);
1760  free_BCD_int(&mul_by_power_10);
1761  y -= p;
1762  }
1763  }
1764  while (y--) {
1765  iadd_bcd(&ret, x); // then do simple addition
1766  }
1767  return ret;
1768 }
1769 
1770 BCD_int mul_bcd_pow_10(const BCD_int x, const size_t tens) {
1771  // this takes O(log_100(x)) time. Note that it's significantly faster if tens is even
1772  // returns x * 10^tens
1773  if (unlikely(x.nan))
1774  return bcd_error(SHIFT_NAN, x.orig_error);
1775  if (unlikely(x.zero))
1776  return BCD_zero;
1777  if (unlikely(!tens))
1778  return copy_BCD_int(x);
1779  BCD_int ret = {
1780  .even = x.even || !!tens,
1781  .negative = x.negative,
1782  .decimal_digits = (size_t) x.decimal_digits + tens,
1783  };
1784  ret.bcd_digits = (ret.decimal_digits + 1) / 2;
1785  ret.data = (packed_BCD_pair *) calloc(ret.bcd_digits, sizeof(packed_BCD_pair));
1786  if (unlikely(ret.data == NULL))
1787  return bcd_error(NO_MEM, NO_MEM);
1788  if (tens % 2 == 0) {
1789  // +--+--+ +--+--+--+
1790  // |23|01| -> ...|23|01|
1791  // +--+--+ +--+--+--+
1792  const size_t digit_diff = ret.bcd_digits - x.bcd_digits;
1793  memcpy(ret.data + digit_diff, x.data, x.bcd_digits);
1794  }
1795  else {
1796  // +--+--+ +--+--+--+
1797  // |23|01| -> ...|30|12|
1798  // +--+--+ +--+--+--+
1799  // +--+--+ +--+--+--+--+
1800  // |34|12| -> ...|40|23|01|
1801  // +--+--+ +--+--+--+--+
1802  const size_t digit_diff = ret.bcd_digits - x.bcd_digits - ret.decimal_digits % 2;
1803  // note that digit_diff needs to be adjusted on this branch, so it can't be common
1804  ret.data[digit_diff] = x.data[0] << 4;
1805  for (size_t i = 1; i < x.bcd_digits; i++) {
1806  ret.data[i + digit_diff] = x.data[i] << 4;
1807  ret.data[i + digit_diff] |= x.data[i - 1] >> 4;
1808  }
1809  if (ret.decimal_digits % 2)
1810  ret.data[x.bcd_digits + digit_diff] |= x.data[x.bcd_digits - 1] >> 4;
1811  }
1812  return ret;
1813 }
1814 
1815 inline BCD_int shift_bcd_left(const BCD_int x, const size_t tens) {
1816  return mul_bcd_pow_10(x, tens);
1817 }
1818 
1819 BCD_int div_bcd_pow_10(const BCD_int a, const size_t tens) {
1820  if (unlikely(a.nan))
1821  return bcd_error(SHIFT_NAN, a.orig_error);
1822  if (unlikely(!tens))
1823  return copy_BCD_int(a);
1824  if (tens >= a.decimal_digits)
1825  return BCD_zero;
1826  BCD_int ret = (BCD_int) {
1827  .decimal_digits = a.decimal_digits - tens,
1828  .negative = a.negative
1829  };
1830  ret.bcd_digits = (ret.decimal_digits + 1) / 2;
1831  ret.data = (packed_BCD_pair *) malloc(sizeof(packed_BCD_pair) * ret.bcd_digits);
1832  if (unlikely(ret.data == NULL))
1833  return bcd_error(NO_MEM, NO_MEM);
1834  if (tens % 2 == 0) {
1835  // +--+--+--+ +--+--+
1836  // ...|23|01| -> |23|01|
1837  // +--+--+--+ +--+--+
1838  const size_t digit_diff = a.bcd_digits - ret.bcd_digits;
1839  memcpy(ret.data, a.data + digit_diff, ret.bcd_digits);
1840  }
1841  else {
1842  // +--+--+--+--+ +--+--+
1843  // ...|45|23|01| -> |34|12|
1844  // +--+--+--+--+ +--+--+
1845  // +--+--+--+--+ +--+--+--+
1846  // ...|56|34|12| -> |45|23|01|
1847  // +--+--+--+--+ +--+--+--+
1848  const size_t digit_diff = a.bcd_digits - ret.bcd_digits - (a.decimal_digits % 2);
1849  ret.data[0] = a.data[digit_diff] >> 4;
1850  for (size_t i = 1; i < ret.bcd_digits; i++) {
1851  ret.data[i - 1] |= a.data[i + digit_diff] << 4;
1852  ret.data[i] = a.data[i + digit_diff] >> 4;
1853  }
1854  if (a.decimal_digits % 2)
1855  ret.data[ret.bcd_digits - 1] |= a.data[ret.bcd_digits + digit_diff] << 4;
1856  }
1857  ret.even = !(ret.data[0] % 2);
1858  return ret;
1859 }
1860 
1861 inline BCD_int shift_bcd_right(const BCD_int a, const size_t tens) {
1862  return div_bcd_pow_10(a, tens);
1863 }
1864 
1865 inline BCD_int pow_cuint_cuint(const uintmax_t x, uintmax_t y) {
1866  // this takes roughly O(x * y * log_100(xy)) time
1867  BCD_int answer = BCD_one;
1868  while (y--) {
1869  imul_bcd_cuint(&answer, x);
1870  }
1871  return answer;
1872 }
1873 
1874 inline BCD_int pow_cint_cuint(const intmax_t x, uintmax_t y) {
1875  // this takes roughly O(x * y * log_100(xy)) time
1876  BCD_int answer = BCD_one;
1877  while (y--) {
1878  imul_bcd_cint(&answer, x);
1879  }
1880  return answer;
1881 }
1882 
1883 inline void imul_bcd_cuint(BCD_int *const x, const uintmax_t y) {
1884  BCD_int ret = mul_bcd_cuint(*x, y);
1885  free_BCD_int(x);
1886  *x = ret;
1887 }
1888 
1889 inline void imul_bcd_cint(BCD_int *const x, const intmax_t y) {
1890  BCD_int ret = mul_bcd_cint(*x, y);
1891  free_BCD_int(x);
1892  *x = ret;
1893 }
1894 
1895 inline void imul_bcd_pow_10(BCD_int *const x, const size_t tens) {
1896  BCD_int ret = mul_bcd_pow_10(*x, tens);
1897  free_BCD_int(x);
1898  *x = ret;
1899 }
1900 
1901 inline void ishift_bcd_left(BCD_int *const x, const size_t tens) {
1902  imul_bcd_pow_10(x, tens);
1903 }
1904 
1905 inline void idiv_bcd_pow_10(BCD_int *const a, const size_t tens) {
1906  BCD_int ret = div_bcd_pow_10(*a, tens);
1907  free_BCD_int(a);
1908  *a = ret;
1909 }
1910 
1911 inline void ishift_bcd_right(BCD_int *const a, const size_t tens) {
1912  idiv_bcd_pow_10(a, tens);
1913 }
1914 
1915 inline uint16_t mul_dig_pair(const packed_BCD_pair ab, const packed_BCD_pair cd) {
1916  // multiplies two digits pairs and returns an unsigned C short. valid range is 0 thru 9801
1917  // first unpack the digits
1918  const uint8_t a = ab >> 4,
1919  b = ab & 0xF,
1920  c = cd >> 4,
1921  d = cd & 0xF;
1922  // then solve by FOIL
1923  return 100 * a * c + 10 * (a * d + b * c) + b * d;
1924 }
1925 
1926 void print_bcd(const BCD_int x) {
1927  if (unlikely(x.nan)) {
1928  printf("NaN");
1929  return;
1930  }
1931  if (unlikely(x.zero)) {
1932  printf("0");
1933  return;
1934  }
1935  if (x.negative)
1936  printf("-");
1937  size_t i = x.bcd_digits - 1;
1938  printf("%x", x.data[i--]);
1939  for (; i != -1; i--) {
1940  printf("%02x", x.data[i]);
1941  }
1942 }
1943 
1944 inline void print_bcd_ln(const BCD_int x) {
1945  print_bcd(x);
1946  printf("\n");
1947 }
1948 
1949 #ifdef DOXYGEN
1950 };
1951 #endif
BCD_int mul_bcd(const BCD_int x, const BCD_int y)
Definition: bcd.h:1403
void ipow_bcd(BCD_int *const x, const BCD_int y)
Definition: bcd.h:1664
void imod_bcd(BCD_int *const x, const BCD_int y)
Definition: bcd.h:1650
void imul_bcd_cuint(BCD_int *const x, const uintmax_t y)
Definition: bcd.h:1883
uint16_t mul_dig_pair(const packed_BCD_pair ab, const packed_BCD_pair cd)
Multiply a pair of BCD bytes.
Definition: bcd.h:1915
you tried to divide NaN
Definition: bcd.h:54
you tried to do a yet-unimplemented feature
Definition: bcd.h:62
bool zero
indicates the integer is 0
Definition: bcd.h:81
void idiv_bcd(BCD_int *const x, const BCD_int y)
Definition: bcd.h:1644
const BCD_int BCD_two
The BCD_two constant is used to represent the commonly used value two.
Definition: bcd.h:98
void imul_bcd_cint(BCD_int *const x, const intmax_t y)
Definition: bcd.h:1889
void iabs_bcd(BCD_int *const x)
Definition: bcd.h:1602
size_t decimal_digits
the number of decimal digits in this integer
Definition: bcd.h:72
comp_t cmp_bcd(const BCD_int x, const BCD_int y)
Definition: bcd.h:1148
void idivmod_bcd(BCD_int *const x, BCD_int *const y)
Definition: bcd.h:1656
BCD_int shift_bcd_right(const BCD_int a, const size_t tens)
Definition: bcd.h:1861
BCD_int sign_bcd(BCD_int x, const bool no_copy, const bool negative)
Definition: bcd.h:1181
bool constant
indicates that the integer is a constant and will not be touched by free_bcd_int() ...
Definition: bcd.h:83
void free_BCD_int(BCD_int *const x)
Definition: bcd.h:1043
#define likely(x)
Indicates to the compiler (if supported) that this branch is likely to occur and it should arrange co...
Definition: math.h:143
const BCD_int BCD_one
The BCD_one constant is used to represent the commonly used value one.
Definition: bcd.h:107
bool bool_bcd(const BCD_int x)
Definition: bcd.h:1173
BCD_error
An enum that we use to track errors in BCD integers.
Definition: bcd.h:47
def digits
Definition: p0052.py:20
packed_BCD_pair * data
the raw data of the integer, DO NOT modify directly
Definition: bcd.h:70
there wasn&#39;t an error
Definition: bcd.h:48
BCD_int mul_bcd_cint(const BCD_int x, const intmax_t y)
Definition: bcd.h:1728
BCD_int abs_bcd(const BCD_int x, const bool no_copy)
Definition: bcd.h:1187
you tried to divide by zero
Definition: bcd.h:60
comp_t
An enum that we return for BCD comparisons.
Definition: bcd.h:37
BCD_int inc_bcd(const BCD_int x)
Definition: bcd.h:1294
bool negative
indicates the integer is negative
Definition: bcd.h:80
void ishift_bcd_left(BCD_int *const x, const size_t tens)
Definition: bcd.h:1901
void print_bcd(const BCD_int x)
Definition: bcd.h:1926
void print_bcd_ln(const BCD_int x)
Definition: bcd.h:1944
x > y
Definition: bcd.h:39
comp_t cmp_bcd_cuint(const BCD_int x, const uintmax_t y)
Definition: bcd.h:1709
BCD_int shift_bcd_left(const BCD_int x, const size_t tens)
Definition: bcd.h:1815
x == y
Definition: bcd.h:38
you tried to get the factorial of NaN
Definition: bcd.h:56
BCD_int pow_bcd(const BCD_int x, const BCD_int y)
Definition: bcd.h:1544
you tried to multiply NaN
Definition: bcd.h:53
void ineg_bcd(BCD_int *const x)
Definition: bcd.h:1606
you tried to use NaN as an exponent or base
Definition: bcd.h:55
void idiv_bcd_pow_10(BCD_int *const a, const size_t tens)
Definition: bcd.h:1905
BCD_int mod_bcd(const BCD_int x, const BCD_int y)
Definition: bcd.h:1476
BCD_int opp_bcd(const BCD_int x, const bool no_copy)
Definition: bcd.h:1195
comp_t cmp_bcd_cint(const BCD_int x, const intmax_t y)
Definition: bcd.h:1697
BCD_int mul_bcd_pow_10(const BCD_int x, const size_t tens)
Definition: bcd.h:1770
#define MAX_POW_10_64
This macro denotes the largest power of 10 that can be stored in a 64-bit unsigned integer...
Definition: math.h:212
BCD_int BCD_from_ascii(const char *const str, const size_t digits, const bool negative)
Definition: bcd.h:1124
BCD_int new_BCD_int1(const intmax_t a)
Definition: bcd.h:1050
you tried to shift NaN
Definition: bcd.h:57
BCD_int new_BCD_int2(uintmax_t a, const bool negative)
Definition: bcd.h:1056
BCD_int copy_BCD_int(BCD_int a)
Definition: bcd.h:1074
you tried to subtract NaN
Definition: bcd.h:52
void iinc_bcd(BCD_int *const x)
Definition: bcd.h:1620
Definition: __init__.py:1
uintmax_t abs_bcd_cuint(const BCD_int x)
Definition: bcd.h:1676
void imul_bcd(BCD_int *const x, const BCD_int y)
Definition: bcd.h:1638
BCD_int pow_cuint_cuint(const uintmax_t x, uintmax_t y)
Definition: bcd.h:1865
#define POW_OF_MAX_POW_10_64
This macro defines the power of MAX_POW_10_64.
Definition: math.h:217
size_t bcd_digits
the byte count of data
Definition: bcd.h:71
bool not_bcd(const BCD_int x)
Definition: bcd.h:1177
BCD_int neg_bcd(const BCD_int x, const bool no_copy)
Definition: bcd.h:1191
void imul_bcd_pow_10(BCD_int *const x, const size_t tens)
Definition: bcd.h:1895
BCD_int div_bcd_pow_10(const BCD_int a, const size_t tens)
Definition: bcd.h:1819
BCD_int dec_bcd(const BCD_int x)
Definition: bcd.h:1399
void idec_bcd(BCD_int *const x)
Definition: bcd.h:1632
void ishift_bcd_right(BCD_int *const a, const size_t tens)
Definition: bcd.h:1911
you are out of memory to make new ints
Definition: bcd.h:61
EXTERN_PRINTF
Definition: bcd.h:19
#define min(a, b)
Given two comparable variables, return the lesser.
Definition: macros.h:122
BCD_int factorial_bcd(const BCD_int x)
Definition: bcd.h:1579
this is the original NaN
Definition: bcd.h:49
you tried to get a negative factorial
Definition: bcd.h:59
you tried to use a negative exponent
Definition: bcd.h:58
x < y
Definition: bcd.h:40
void isign_bcd(BCD_int *const x, const bool negative)
Definition: bcd.h:1595
BCD_int add_bcd(const BCD_int x, const BCD_int y)
Definition: bcd.h:1199
A little-endian, arbitrary-precision, binary-coded-decimal number.
Definition: bcd.h:69
Definition: bcd.h:16
void isub_bcd(BCD_int *const x, const BCD_int y)
Definition: bcd.h:1626
x.nan || y.nan
Definition: bcd.h:41
uint8_t packed_BCD_pair
An alias for uint8_t that shows it is intended to store packed BCD data.
Definition: bcd.h:32
you tried to add NaN
Definition: bcd.h:51
#define PACK(decl)
Indicates to the compiler that the structure defined within should be packed bitwise.
Definition: math.h:160
#define unlikely(x)
Indicates to the compiler (if supported) that this branch is unlikely to occur and it should arrange ...
Definition: math.h:152
BCD_int BCD_from_bytes(const unsigned char *const str, const size_t chars, const bool negative, const bool little_endian)
Definition: bcd.h:1086
BCD_int div_bcd(const BCD_int x, const BCD_int y)
Definition: bcd.h:1472
const BCD_int BCD_nan
The BCD_nan constant is used to represent the commonly used value NaN.
Definition: bcd.h:122
BCD_int bcd_error(const BCD_error error, const BCD_error orig_error)
Definition: bcd.h:1141
void iopp_bcd(BCD_int *const x)
Definition: bcd.h:1610
BCD_int sub_bcd(const BCD_int x, const BCD_int y)
Definition: bcd.h:1298
BCD_int pow_cint_cuint(const intmax_t x, uintmax_t y)
Definition: bcd.h:1874
void ifactorial_bcd(BCD_int *const x)
Definition: bcd.h:1670
this BCD_int has been freed
Definition: bcd.h:50
reserved
Definition: bcd.h:63
uint8_t nan
indicates that the integer is NaN
Definition: bcd.h:74
intmax_t val_bcd_cint(const BCD_int x)
Definition: bcd.h:1688
bool even
indicates the integer is even
Definition: bcd.h:82
BCD_int mul_bcd_cuint(const BCD_int x, uintmax_t y)
Definition: bcd.h:1734
const BCD_int BCD_zero
The BCD_zero constant is used to represent the commonly used value zero.
Definition: bcd.h:115
BCD_int divmod_bcd(const BCD_int x, BCD_int y, BCD_int *mod)
Definition: bcd.h:1485
void iadd_bcd(BCD_int *const x, const BCD_int y)
Definition: bcd.h:1614