Fix errors from make distcheck
[gcalctool.git] / src / mp-binary.c
blobe9b10b702e87b70b6028b0acc58f232ff519fbdd
1 #include "mp.h"
2 #include "mp-internal.h"
3 #include "calctool.h" // FIXME: Used for MAX_DIGITS
5 static char digits[] = "0123456789ABCDEF";
7 static int hex_to_int(char digit)
9 if (digit >= '0' && digit <= '9')
10 return digit - '0';
11 if (digit >= 'A' && digit <= 'F')
12 return digit - 'A' + 10;
13 if (digit >= 'a' && digit <= 'f')
14 return digit - 'a' + 10;
15 return 0;
19 static void
20 mp_bitwise(const MPNumber *x, const MPNumber *y, int (*bitwise_operator)(int, int), MPNumber *z, int wordlen)
22 char text1[MAX_DIGITS], text2[MAX_DIGITS], text_out[MAX_DIGITS];
23 int offset1, offset2, offset_out;
25 mp_cast_to_string(x, 16, 0, 0, text1, MAX_DIGITS);
26 mp_cast_to_string(y, 16, 0, 0, text2, MAX_DIGITS);
27 offset1 = strlen(text1) - 1;
28 offset2 = strlen(text2) - 1;
29 offset_out = wordlen / 4 - 1;
30 if (offset_out <= 0) {
31 offset_out = offset1 > offset2 ? offset1 : offset2;
33 if (offset_out > 0 && (offset_out < offset1 || offset_out < offset2)) {
34 mperr("Overflow. Try a bigger word size");
35 return;
38 /* Perform bitwise operator on each character from right to left */
39 for (text_out[offset_out+1] = '\0'; offset_out >= 0; offset_out--) {
40 int v1 = 0, v2 = 0;
42 if (offset1 >= 0) {
43 v1 = hex_to_int(text1[offset1]);
44 offset1--;
46 if (offset2 >= 0) {
47 v2 = hex_to_int(text2[offset2]);
48 offset2--;
50 text_out[offset_out] = digits[bitwise_operator(v1, v2)];
53 mp_set_from_string(text_out, 16, z);
57 static int mp_bitwise_and(int v1, int v2) { return v1 & v2; }
58 static int mp_bitwise_or(int v1, int v2) { return v1 | v2; }
59 static int mp_bitwise_xor(int v1, int v2) { return v1 ^ v2; }
60 static int mp_bitwise_xnor(int v1, int v2) { return v1 ^ v2 ^ 0xF; }
61 static int mp_bitwise_not(int v1, int dummy) { return v1 ^ 0xF; }
64 int
65 mp_is_overflow (const MPNumber *x, int wordlen)
67 MPNumber tmp1, tmp2;
68 mp_set_from_integer(2, &tmp1);
69 mp_pwr_integer(&tmp1, wordlen, &tmp2);
70 return mp_is_greater_than (&tmp2, x);
74 void
75 mp_and(const MPNumber *x, const MPNumber *y, MPNumber *z)
77 mp_bitwise(x, y, mp_bitwise_and, z, 0);
81 void
82 mp_or(const MPNumber *x, const MPNumber *y, MPNumber *z)
84 mp_bitwise(x, y, mp_bitwise_or, z, 0);
88 void
89 mp_xor(const MPNumber *x, const MPNumber *y, MPNumber *z)
91 mp_bitwise(x, y, mp_bitwise_xor, z, 0);
95 void
96 mp_xnor(const MPNumber *x, const MPNumber *y, int wordlen, MPNumber *z)
98 mp_bitwise(x, y, mp_bitwise_xnor, z, wordlen);
102 void
103 mp_not(const MPNumber *x, int wordlen, MPNumber *z)
105 MPNumber temp;
106 mp_set_from_integer(0, &temp);
107 mp_bitwise(x, &temp, mp_bitwise_not, z, wordlen);
111 void
112 mp_mask(const MPNumber *x, int wordlen, MPNumber *z)
114 char text[MAX_DIGITS];
115 size_t len, offset;
117 /* Convert to a hexadecimal string and use last characters */
118 mp_cast_to_string(x, 16, 0, 0, text, MAX_DIGITS);
119 len = strlen(text);
120 offset = wordlen / 4;
121 offset = len > offset ? len - offset: 0;
122 mp_set_from_string(text + offset, 16, z);
126 void
127 mp_shift(const MPNumber *x, int count, MPNumber *z)
129 int i, multiplier = 1;
131 if (count >= 0) {
132 for (i = 0; i < count; i++)
133 multiplier *= 2;
134 mp_multiply_integer(x, multiplier, z);
136 else {
137 MPNumber temp;
138 for (i = 0; i < -count; i++)
139 multiplier *= 2;
140 mp_divide_integer(x, multiplier, &temp);
141 mp_integer_component(&temp, z);
146 void
147 mp_1s_complement(const MPNumber *x, int wordlen, MPNumber *z)
149 MPNumber t;
150 mp_set_from_integer(0, &t);
151 mp_bitwise(x, &t, mp_bitwise_xnor, z, wordlen);
155 void
156 mp_2s_complement(const MPNumber *x, int wordlen, MPNumber *z)
158 mp_1s_complement (x, wordlen, z);
159 mp_add_integer (z, 1, z);