1 // -*- c++ -*-
2 #include <stdio.h>
3 template<unsigned int N>
4 class Integral {
5 
6   unsigned char bytes[N];
7 
8  public:
Integral()9   Integral() {
10     for (unsigned int i=0; i<N; i++)
11       bytes[i] = 0;
12   }
Integral(const Integral & I)13   Integral(const Integral &I) {
14     for (unsigned int i=0; i<N; i++)
15       bytes[i] = I.bytes[i];
16   }
Integral(long long value)17   Integral(long long value) {
18     resize_signed_int((unsigned char*)&value, sizeof(value), bytes, N);
19   }
20 
21   operator long long() const {
22     long long value;
23     resize_signed_int(bytes, N, (unsigned char*)&value, sizeof(value));
24     return value;
25   }
26 
27   Integral& operator=(const Integral &I) {
28     for (unsigned int i=0; i<N; i++)
29       bytes[i] = I.bytes[i];
30     return *this;
31   }
32   bool operator<(const Integral &I) const
33   { return cmp(I) < 0; }
34   bool operator>(const Integral &I) const
35   { return cmp(I) > 0; }
36   bool operator<=(const Integral &I) const
37   { return cmp(I) <= 0; }
38   bool operator>=(const Integral &I) const
39   { return cmp(I) >= 0; }
40   bool operator==(const Integral &I) const
41   { return cmp(I) == 0; }
42   bool operator!=(const Integral &I) const
43   { return cmp(I) != 0; }
44 
45   bool operator==(const long long value) const {
46     size_t len = sizeof(long long) > N ? sizeof(long long) : N;
47     unsigned char* extended = new unsigned char[len];
48     unsigned char* other;
49     if (sizeof(long long) < N) {
50         resize_signed_int((unsigned char*)&value, sizeof(value), extended, len);
51         other = bytes;
52     } else {
53         resize_signed_int(bytes, N, extended, len);
54     }
55     bool res = memcmp(extended, other, len);
56     delete extended;
57     return res;
58   }
59   bool operator!=(const long long val) const
60   { return !(*this == val); }
61 
62  private:
is_le()63   static bool is_le() {
64     int one = 1;
65     int b = (int)*(unsigned char *)&one;
66     return b ? true : false;
67   }
lsb()68   static unsigned int lsb() {
69     return is_le() ? 0 : N-1;
70   }
msb()71   static unsigned int msb() {
72     return is_le() ? N-1 : 0;
73   }
cmp(const Integral & J)74   int cmp(const Integral& J) const {
75     const Integral& I = *this;
76     unsigned char sI = I.bytes[msb()] & 0x80;
77     unsigned char sJ = J.bytes[msb()] & 0x80;
78     if (sI > sJ) return -1;
79     if (sI < sJ) return +1;
80     unsigned char bI = I.bytes[msb()] & 0x7F;
81     unsigned char bJ = J.bytes[msb()] & 0x7F;
82     int cmpabs = 0;
83     if (bI < bJ)
84       cmpabs = -1;
85     else if (bI > bJ)
86       cmpabs = +1;
87     else {
88       int incr = is_le() ? -1 : 1;
89       unsigned int i = msb() + incr;
90       while (i != lsb()) {
91 	if (I.bytes[i] < J.bytes[i])
92 	  { cmpabs = -1;  break; }
93 	if (I.bytes[i] > J.bytes[i])
94 	  { cmpabs = +1;  break; }
95 	i += incr;
96       }
97     }
98     if (sI) return -cmpabs;
99     else    return +cmpabs;
100   }
101 
resize_signed_int(const unsigned char * src,size_t src_len,unsigned char * dst,size_t dst_len)102   static void resize_signed_int(const unsigned char* src, size_t src_len, unsigned char* dst, size_t dst_len) {
103     unsigned char msb;
104     size_t dst_offset = 0;
105     size_t src_offset = 0;
106     if (is_le()) {
107         dst_offset = 0;
108         src_offset = 0;
109         msb = ((unsigned char*) src)[src_len - 1];
110         if (src_len > dst_len) {
111             src_len = dst_len;
112         }
113     } else {
114         if (dst_len > src_len) {
115             dst_offset = dst_len - src_len;
116         } else {
117             src_offset = src_len - dst_len;
118             src_len = dst_len;
119         }
120         msb = ((unsigned char*) src)[0];
121     }
122     if (msb & 0x80) {
123         memset(dst, 0xFF, dst_len);
124     } else {
125         memset(dst, 0, dst_len);
126     }
127     memcpy(dst + dst_offset, src + src_offset, src_len);
128   }
129 };
130 
131 typedef Integral<3> Int24;
132 typedef Integral<7> Int56;
133 typedef Integral<11> Int88;
134 typedef Integral<64> Int512;
135