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