Alexandre Lision | 7fd5d3d | 2013-12-04 13:06:40 -0500 | [diff] [blame] | 1 | /* |
| 2 | * lbn.h - Low-level bignum header. |
| 3 | * Defines various word sizes and useful macros. |
| 4 | * TODO: Rewrite this to use <stdint.h> and/or <inttypes.h> |
| 5 | * |
| 6 | * Copyright (c) 1995 Colin Plumb. All rights reserved. |
| 7 | * For licensing and other legal details, see the file legal.c. |
| 8 | */ |
| 9 | #ifndef LBN_H |
| 10 | #define LBN_H |
| 11 | |
| 12 | #ifndef HAVE_CONFIG_H |
| 13 | #define HAVE_CONFIG_H 0 |
| 14 | #endif |
| 15 | #if HAVE_CONFIG_H |
| 16 | #include <bnconfig.h> |
| 17 | #endif |
| 18 | |
| 19 | /* |
| 20 | * Some compilers complain about #if FOO if FOO isn't defined, |
| 21 | * so do the ANSI-mandated thing explicitly... |
| 22 | */ |
| 23 | #ifndef NO_LIMITS_H |
| 24 | #define NO_LIMITS_H 0 |
| 25 | #endif |
| 26 | |
| 27 | #include <stdint.h> /* TODO: protect by configuration ifdef */ |
| 28 | |
| 29 | /* Make sure we have 8-bit bytes */ |
| 30 | #if !NO_LIMITS_H |
| 31 | #include <limits.h> |
| 32 | #if UCHAR_MAX != 0xff || CHAR_BIT != 8 |
| 33 | #error The bignum library requires 8-bit unsigned characters. |
| 34 | #endif |
| 35 | #endif /* !NO_LIMITS_H */ |
| 36 | |
| 37 | #ifdef BNINCLUDE /* If this is defined as, say, foo.h */ |
| 38 | #define STR(x) #x /* STR(BNINCLUDE) -> "BNINCLUDE" */ |
| 39 | #define XSTR(x) STR(x) /* XSTR(BNINCLUDE) -> STR(foo.h) -> "foo.h" */ |
| 40 | #include XSTR(BNINCLUDE) /* #include "foo.h" */ |
| 41 | #undef XSTR |
| 42 | #undef STR |
| 43 | #endif |
| 44 | |
| 45 | /* Do we want bnYield()? */ |
| 46 | #ifndef BNYIELD |
| 47 | #define BNYIELD 0 |
| 48 | #endif |
| 49 | |
| 50 | /* Figure out the endianness */ |
| 51 | /* Error if more than one is defined */ |
| 52 | #if defined(BN_BIG_ENDIAN) && defined(BN_LITTLE_ENDIAN) |
| 53 | #error Only one of BN_BIG_ENDIAN or BN_LITTLE_ENDIAN may be defined |
| 54 | #endif |
| 55 | |
| 56 | /* |
| 57 | * If no preference is stated, little-endian C code is slightly more |
| 58 | * efficient, so prefer that. (The endianness here does NOT have to |
| 59 | * match the machine's native byte sex; the library's C code will work |
| 60 | * either way. The flexibility is allowed for assembly routines |
| 61 | * that do care. |
| 62 | */ |
| 63 | #if !defined(BN_BIG_ENDIAN) && !defined(BN_LITTLE_ENDIAN) |
| 64 | #define BN_LITTLE_ENDIAN 1 |
| 65 | #endif /* !BN_BIG_ENDIAN && !BN_LITTLE_ENDIAN */ |
| 66 | |
| 67 | /* Macros to choose between big and little endian */ |
| 68 | #if defined(BN_BIG_ENDIAN) |
| 69 | #define BIG(b) b |
| 70 | #define LITTLE(l) /*nothing*/ |
| 71 | #define BIGLITTLE(b,l) b |
| 72 | #elif BN_LITTLE_ENDIAN |
| 73 | #define BIG(b) /*nothing*/ |
| 74 | #define LITTLE(l) l |
| 75 | #define BIGLITTLE(b,l) l |
| 76 | #else |
| 77 | #error One of BN_BIG_ENDIAN or BN_LITTLE_ENDIAN must be defined as 1 |
| 78 | #endif |
| 79 | |
| 80 | |
| 81 | /* |
| 82 | * Define a 16-bit unsigned type if available. |
| 83 | * Unsigned short is preferred over unsigned int to make the type chosen |
| 84 | * by this file more stable on platforms (such as many 68000 compilers) |
| 85 | * which support both 16- and 32-bit ints. |
| 86 | */ |
| 87 | #ifndef BNWORD16 |
| 88 | #if !defined USHRT_MAX || USHRT_MAX == 0xffff || UINT_MAX == 0xffff |
| 89 | #define BNWORD16 uint16_t |
| 90 | #endif |
| 91 | #endif /* BNWORD16 */ |
| 92 | |
| 93 | /* |
| 94 | * Define a 32-bit unsigned type if available. |
| 95 | * Unsigned long is preferred over unsigned int to make the type chosen |
| 96 | * by this file more stable on platforms (such as many 68000 compilers) |
| 97 | * which support both 16- and 32-bit ints. |
| 98 | */ |
| 99 | #ifndef BNWORD32 |
| 100 | #if !defined ULONG_MAX || ULONG_MAX == 0xfffffffful || UINT_MAX == 0xffffffff || USHRT_MAX == 0xffffffff |
| 101 | #define BNWORD32 uint32_t |
| 102 | #endif |
| 103 | #endif /* BNWORD32 */ |
| 104 | |
| 105 | /* |
| 106 | * Find a 64-bit unsigned type. |
| 107 | * The conditions here are more complicated to avoid using numbers that |
| 108 | * will choke lesser preprocessors (like 0xffffffffffffffff) unless |
| 109 | * we're reasonably certain that they'll be acceptable. |
| 110 | */ |
| 111 | #if !defined(BNWORD64) && ULONG_MAX > 0xffffffffUL |
| 112 | #if ULONG_MAX == 0xffffffffffffffff |
| 113 | #define BNWORD64 uint64_t |
| 114 | #endif |
| 115 | #endif |
| 116 | |
| 117 | /* |
| 118 | * I would test the value of unsigned long long, but some *preprocessors* |
| 119 | * don't constants that long even if the compiler can accept them, so it |
| 120 | * doesn't work reliably. So cross our fingers and hope that it's a 64-bit |
| 121 | * type. |
| 122 | * |
| 123 | * GCC uses ULONG_LONG_MAX. Solaris uses ULLONG_MAX. IRIX uses ULONGLONG_MAX. |
| 124 | * Are there any other names for this? |
| 125 | */ |
| 126 | #if !defined(BNWORD64) && \ |
| 127 | (defined(ULONG_LONG_MAX) || defined (ULLONG_MAX) || defined(ULONGLONG_MAX)) |
| 128 | #define BNWORD64 uint64_t |
| 129 | #endif |
| 130 | |
| 131 | /* We don't even try to find a 128-bit type at the moment */ |
| 132 | |
| 133 | #endif /* !LBN_H */ |