1 /*
2 * Copyright (C) 1987-2008 Sun Microsystems, Inc. All Rights Reserved.
3 * Copyright (C) 2008-2011 Robert Ancell
4 *
5 * This program is free software: you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License as published by the Free Software
7 * Foundation, either version 2 of the License, or (at your option) any later
8 * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
9 * license.
10 */
11
12 #include <stdio.h>
13
14 #include "mp.h"
15 #include "mp-serializer.h"
16
17 // FIXME: Make dynamic
18 #define MAX_DIGITS 1000
19
20 static char digits[] = "0123456789ABCDEF";
21
hex_to_int(char digit)22 static int hex_to_int(char digit)
23 {
24 if (digit >= '0' && digit <= '9')
25 return digit - '0';
26 if (digit >= 'A' && digit <= 'F')
27 return digit - 'A' + 10;
28 if (digit >= 'a' && digit <= 'f')
29 return digit - 'a' + 10;
30 return 0;
31 }
32
33
34 static gchar *
to_hex_string(const MPNumber * x)35 to_hex_string(const MPNumber *x)
36 {
37 MpSerializer *serializer;
38 gchar *result;
39
40 serializer = mp_serializer_new(MP_DISPLAY_FORMAT_FIXED, 16, 0);
41 result = mp_serializer_to_string(serializer, x);
42 g_object_unref(serializer);
43
44 return result;
45 }
46
47
48 static void
mp_bitwise(const MPNumber * x,const MPNumber * y,int (* bitwise_operator)(int,int),MPNumber * z,int wordlen)49 mp_bitwise(const MPNumber *x, const MPNumber *y, int (*bitwise_operator)(int, int), MPNumber *z, int wordlen)
50 {
51 char *text1, *text2, text_out[MAX_DIGITS], text_out2[MAX_DIGITS];
52 int offset1, offset2, offset_out;
53
54 text1 = to_hex_string(x);
55 text2 = to_hex_string(y);
56 offset1 = strlen(text1) - 1;
57 offset2 = strlen(text2) - 1;
58 offset_out = wordlen / 4 - 1;
59 if (offset_out <= 0) {
60 offset_out = offset1 > offset2 ? offset1 : offset2;
61 }
62 if (offset_out > 0 && (offset_out < offset1 || offset_out < offset2)) {
63 g_free(text1);
64 g_free(text2);
65 mp_set_from_integer(0, z);
66 mperr("Overflow. Try a bigger word size");
67 return;
68 }
69
70 /* Perform bitwise operator on each character from right to left */
71 for (text_out[offset_out+1] = '\0'; offset_out >= 0; offset_out--) {
72 int v1 = 0, v2 = 0;
73
74 if (offset1 >= 0) {
75 v1 = hex_to_int(text1[offset1]);
76 offset1--;
77 }
78 if (offset2 >= 0) {
79 v2 = hex_to_int(text2[offset2]);
80 offset2--;
81 }
82 text_out[offset_out] = digits[bitwise_operator(v1, v2)];
83 }
84
85 snprintf(text_out2, MAX_DIGITS, "%s", text_out);
86 mp_set_from_string(text_out2, 16, z);
87 g_free(text1);
88 g_free(text2);
89 }
90
91
mp_bitwise_and(int v1,int v2)92 static int mp_bitwise_and(int v1, int v2) { return v1 & v2; }
mp_bitwise_or(int v1,int v2)93 static int mp_bitwise_or(int v1, int v2) { return v1 | v2; }
mp_bitwise_xor(int v1,int v2)94 static int mp_bitwise_xor(int v1, int v2) { return v1 ^ v2; }
mp_bitwise_not(int v1,int dummy)95 static int mp_bitwise_not(int v1, int dummy) { return v1 ^ 0xF; }
96
97
98 bool
mp_is_overflow(const MPNumber * x,int wordlen)99 mp_is_overflow (const MPNumber *x, int wordlen)
100 {
101 bool is_overflow;
102 MPNumber tmp1 = mp_new();
103 MPNumber tmp2 = mp_new();
104 mp_set_from_integer(2, &tmp1);
105 mp_xpowy_integer(&tmp1, wordlen, &tmp2);
106 is_overflow = mp_is_greater_than (&tmp2, x);
107 mp_clear(&tmp1);
108 mp_clear(&tmp2);
109 return is_overflow;
110 }
111
112
113 void
mp_and(const MPNumber * x,const MPNumber * y,MPNumber * z)114 mp_and(const MPNumber *x, const MPNumber *y, MPNumber *z)
115 {
116 if (!mp_is_positive_integer(x) || !mp_is_positive_integer(y))
117 {
118 /* Translators: Error displayed when boolean AND attempted on non-integer values */
119 mperr(_("Boolean AND is only defined for positive integers"));
120 }
121
122 mp_bitwise(x, y, mp_bitwise_and, z, 0);
123 }
124
125
126 void
mp_or(const MPNumber * x,const MPNumber * y,MPNumber * z)127 mp_or(const MPNumber *x, const MPNumber *y, MPNumber *z)
128 {
129 if (!mp_is_positive_integer(x) || !mp_is_positive_integer(y))
130 {
131 /* Translators: Error displayed when boolean OR attempted on non-integer values */
132 mperr(_("Boolean OR is only defined for positive integers"));
133 }
134
135 mp_bitwise(x, y, mp_bitwise_or, z, 0);
136 }
137
138
139 void
mp_xor(const MPNumber * x,const MPNumber * y,MPNumber * z)140 mp_xor(const MPNumber *x, const MPNumber *y, MPNumber *z)
141 {
142 if (!mp_is_positive_integer(x) || !mp_is_positive_integer(y))
143 {
144 /* Translators: Error displayed when boolean XOR attempted on non-integer values */
145 mperr(_("Boolean XOR is only defined for positive integers"));
146 }
147
148 mp_bitwise(x, y, mp_bitwise_xor, z, 0);
149 }
150
151
152 void
mp_not(const MPNumber * x,int wordlen,MPNumber * z)153 mp_not(const MPNumber *x, int wordlen, MPNumber *z)
154 {
155 MPNumber temp = mp_new();
156
157 mp_set_from_integer(0, &temp);
158
159 if (!mp_is_positive_integer(x))
160 {
161 /* Translators: Error displayed when boolean NOT attempted on non-integer values */
162 mperr(_("Boolean NOT is only defined for positive integers"));
163 }
164
165 mp_bitwise(x, &temp, mp_bitwise_not, z, wordlen);
166 mp_clear(&temp);
167 }
168
169
170 void
mp_shift(const MPNumber * x,int count,MPNumber * z)171 mp_shift(const MPNumber *x, int count, MPNumber *z)
172 {
173 if (!mp_is_integer(x)) {
174 /* Translators: Error displayed when bit shift attempted on non-integer values */
175 mperr(_("Shift is only possible on integer values"));
176 return;
177 }
178
179 MPNumber multiplier = mp_new();
180 mp_set_from_integer(1, &multiplier);
181 if (count >= 0) {
182 for (int i = 0; i < count; i++)
183 mp_multiply_integer(&multiplier, 2, &multiplier);
184 mp_multiply(x, &multiplier, z);
185 }
186 else {
187 for (int i = 0; i < -count; i++)
188 mp_multiply_integer(&multiplier, 2, &multiplier);
189 mp_divide(x, &multiplier, z);
190 mp_floor(z, z);
191 }
192 mp_clear(&multiplier);
193 }
194
195
196 void
mp_ones_complement(const MPNumber * x,int wordlen,MPNumber * z)197 mp_ones_complement(const MPNumber *x, int wordlen, MPNumber *z)
198 {
199 MPNumber t = mp_new();
200 mp_set_from_integer(0, &t);
201 mp_bitwise(x, &t, mp_bitwise_xor, z, wordlen);
202 mp_not(z, wordlen, z);
203 mp_clear(&t);
204 }
205
206
207 void
mp_twos_complement(const MPNumber * x,int wordlen,MPNumber * z)208 mp_twos_complement(const MPNumber *x, int wordlen, MPNumber *z)
209 {
210 mp_ones_complement (x, wordlen, z);
211 mp_add_integer (z, 1, z);
212 }
213