1 /* Copyright (c) 1987-2008 Sun Microsystems, Inc. All Rights Reserved.
2 * Copyright (c) 2008-2009 Robert Ancell
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2, or (at your option)
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23 #include "mp-private.h"
24 #include "mp-serializer.h"
26 // FIXME: Make dynamic
27 #define MAX_DIGITS 1000
29 static char digits
[] = "0123456789ABCDEF";
31 static int hex_to_int(char digit
)
33 if (digit
>= '0' && digit
<= '9')
35 if (digit
>= 'A' && digit
<= 'F')
36 return digit
- 'A' + 10;
37 if (digit
>= 'a' && digit
<= 'f')
38 return digit
- 'a' + 10;
44 to_hex_string(const MPNumber
*x
)
46 MpSerializer
*serializer
;
49 serializer
= mp_serializer_new(MP_DISPLAY_FORMAT_FIXED
, 16, 0);
50 result
= mp_serializer_to_string(serializer
, x
);
51 g_object_unref(serializer
);
58 mp_bitwise(const MPNumber
*x
, const MPNumber
*y
, int (*bitwise_operator
)(int, int), MPNumber
*z
, int wordlen
)
60 char *text1
, *text2
, text_out
[MAX_DIGITS
], text_out2
[MAX_DIGITS
];
61 int offset1
, offset2
, offset_out
;
63 text1
= to_hex_string(x
);
64 text2
= to_hex_string(y
);
65 offset1
= strlen(text1
) - 1;
66 offset2
= strlen(text2
) - 1;
67 offset_out
= wordlen
/ 4 - 1;
68 if (offset_out
<= 0) {
69 offset_out
= offset1
> offset2
? offset1
: offset2
;
71 if (offset_out
> 0 && (offset_out
< offset1
|| offset_out
< offset2
)) {
72 mperr("Overflow. Try a bigger word size");
78 /* Perform bitwise operator on each character from right to left */
79 for (text_out
[offset_out
+1] = '\0'; offset_out
>= 0; offset_out
--) {
83 v1
= hex_to_int(text1
[offset1
]);
87 v2
= hex_to_int(text2
[offset2
]);
90 text_out
[offset_out
] = digits
[bitwise_operator(v1
, v2
)];
93 snprintf(text_out2
, MAX_DIGITS
, "%s", text_out
);
94 mp_set_from_string(text_out2
, 16, z
);
100 static int mp_bitwise_and(int v1
, int v2
) { return v1
& v2
; }
101 static int mp_bitwise_or(int v1
, int v2
) { return v1
| v2
; }
102 static int mp_bitwise_xor(int v1
, int v2
) { return v1
^ v2
; }
103 static int mp_bitwise_not(int v1
, int dummy
) { return v1
^ 0xF; }
107 mp_is_overflow (const MPNumber
*x
, int wordlen
)
110 mp_set_from_integer(2, &tmp1
);
111 mp_xpowy_integer(&tmp1
, wordlen
, &tmp2
);
112 return mp_is_greater_than (&tmp2
, x
);
117 mp_and(const MPNumber
*x
, const MPNumber
*y
, MPNumber
*z
)
119 if (!mp_is_positive_integer(x
) || !mp_is_positive_integer(y
))
121 /* Translators: Error displayed when boolean AND attempted on non-integer values */
122 mperr(_("Boolean AND is only defined for positive integers"));
125 mp_bitwise(x
, y
, mp_bitwise_and
, z
, 0);
130 mp_or(const MPNumber
*x
, const MPNumber
*y
, MPNumber
*z
)
132 if (!mp_is_positive_integer(x
) || !mp_is_positive_integer(y
))
134 /* Translators: Error displayed when boolean OR attempted on non-integer values */
135 mperr(_("Boolean OR is only defined for positive integers"));
138 mp_bitwise(x
, y
, mp_bitwise_or
, z
, 0);
143 mp_xor(const MPNumber
*x
, const MPNumber
*y
, MPNumber
*z
)
145 if (!mp_is_positive_integer(x
) || !mp_is_positive_integer(y
))
147 /* Translators: Error displayed when boolean XOR attempted on non-integer values */
148 mperr(_("Boolean XOR is only defined for positive integers"));
151 mp_bitwise(x
, y
, mp_bitwise_xor
, z
, 0);
156 mp_not(const MPNumber
*x
, int wordlen
, MPNumber
*z
)
160 if (!mp_is_positive_integer(x
))
162 /* Translators: Error displayed when boolean XOR attempted on non-integer values */
163 mperr(_("Boolean NOT is only defined for positive integers"));
166 mp_set_from_integer(0, &temp
);
167 mp_bitwise(x
, &temp
, mp_bitwise_not
, z
, wordlen
);
172 mp_mask(const MPNumber
*x
, int wordlen
, MPNumber
*z
)
177 /* Convert to a hexadecimal string and use last characters */
178 text
= to_hex_string(x
);
180 offset
= wordlen
/ 4;
181 offset
= len
> offset
? len
- offset
: 0;
182 mp_set_from_string(text
+ offset
, 16, z
);
188 mp_shift(const MPNumber
*x
, int count
, MPNumber
*z
)
190 int i
, multiplier
= 1;
192 if (!mp_is_integer(x
)) {
193 /* Translators: Error displayed when bit shift attempted on non-integer values */
194 mperr(_("Shift is only possible on integer values"));
199 for (i
= 0; i
< count
; i
++)
201 mp_multiply_integer(x
, multiplier
, z
);
205 for (i
= 0; i
< -count
; i
++)
207 mp_divide_integer(x
, multiplier
, &temp
);
214 mp_ones_complement(const MPNumber
*x
, int wordlen
, MPNumber
*z
)
217 mp_set_from_integer(0, &t
);
218 mp_bitwise(x
, &t
, mp_bitwise_xor
, z
, wordlen
);
219 mp_not(z
, wordlen
, z
);
224 mp_twos_complement(const MPNumber
*x
, int wordlen
, MPNumber
*z
)
226 mp_ones_complement (x
, wordlen
, z
);
227 mp_add_integer (z
, 1, z
);