2 * Copyright (C) 1987-2008 Sun Microsystems, Inc. All Rights Reserved.
3 * Copyright (C) 2008-2011 Robert Ancell
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
15 #include "mp-private.h"
16 #include "mp-serializer.h"
18 // FIXME: Make dynamic
19 #define MAX_DIGITS 1000
21 static char digits
[] = "0123456789ABCDEF";
23 static int hex_to_int(char digit
)
25 if (digit
>= '0' && digit
<= '9')
27 if (digit
>= 'A' && digit
<= 'F')
28 return digit
- 'A' + 10;
29 if (digit
>= 'a' && digit
<= 'f')
30 return digit
- 'a' + 10;
36 to_hex_string(const MPNumber
*x
)
38 MpSerializer
*serializer
;
41 serializer
= mp_serializer_new(MP_DISPLAY_FORMAT_FIXED
, 16, 0);
42 result
= mp_serializer_to_string(serializer
, x
);
43 g_object_unref(serializer
);
50 mp_bitwise(const MPNumber
*x
, const MPNumber
*y
, int (*bitwise_operator
)(int, int), MPNumber
*z
, int wordlen
)
52 char *text1
, *text2
, text_out
[MAX_DIGITS
], text_out2
[MAX_DIGITS
];
53 int offset1
, offset2
, offset_out
;
55 text1
= to_hex_string(x
);
56 text2
= to_hex_string(y
);
57 offset1
= strlen(text1
) - 1;
58 offset2
= strlen(text2
) - 1;
59 offset_out
= wordlen
/ 4 - 1;
60 if (offset_out
<= 0) {
61 offset_out
= offset1
> offset2
? offset1
: offset2
;
63 if (offset_out
> 0 && (offset_out
< offset1
|| offset_out
< offset2
)) {
66 mp_set_from_integer(0, z
);
67 mperr("Overflow. Try a bigger word size");
71 /* Perform bitwise operator on each character from right to left */
72 for (text_out
[offset_out
+1] = '\0'; offset_out
>= 0; offset_out
--) {
76 v1
= hex_to_int(text1
[offset1
]);
80 v2
= hex_to_int(text2
[offset2
]);
83 text_out
[offset_out
] = digits
[bitwise_operator(v1
, v2
)];
86 snprintf(text_out2
, MAX_DIGITS
, "%s", text_out
);
87 mp_set_from_string(text_out2
, 16, z
);
93 static int mp_bitwise_and(int v1
, int v2
) { return v1
& v2
; }
94 static int mp_bitwise_or(int v1
, int v2
) { return v1
| v2
; }
95 static int mp_bitwise_xor(int v1
, int v2
) { return v1
^ v2
; }
96 static int mp_bitwise_not(int v1
, int dummy
) { return v1
^ 0xF; }
100 mp_is_overflow (const MPNumber
*x
, int wordlen
)
103 mp_set_from_integer(2, &tmp1
);
104 mp_xpowy_integer(&tmp1
, wordlen
, &tmp2
);
105 return mp_is_greater_than (&tmp2
, x
);
110 mp_and(const MPNumber
*x
, const MPNumber
*y
, MPNumber
*z
)
112 if (!mp_is_positive_integer(x
) || !mp_is_positive_integer(y
))
114 /* Translators: Error displayed when boolean AND attempted on non-integer values */
115 mperr(_("Boolean AND is only defined for positive integers"));
118 mp_bitwise(x
, y
, mp_bitwise_and
, z
, 0);
123 mp_or(const MPNumber
*x
, const MPNumber
*y
, MPNumber
*z
)
125 if (!mp_is_positive_integer(x
) || !mp_is_positive_integer(y
))
127 /* Translators: Error displayed when boolean OR attempted on non-integer values */
128 mperr(_("Boolean OR is only defined for positive integers"));
131 mp_bitwise(x
, y
, mp_bitwise_or
, z
, 0);
136 mp_xor(const MPNumber
*x
, const MPNumber
*y
, MPNumber
*z
)
138 if (!mp_is_positive_integer(x
) || !mp_is_positive_integer(y
))
140 /* Translators: Error displayed when boolean XOR attempted on non-integer values */
141 mperr(_("Boolean XOR is only defined for positive integers"));
144 mp_bitwise(x
, y
, mp_bitwise_xor
, z
, 0);
149 mp_not(const MPNumber
*x
, int wordlen
, MPNumber
*z
)
153 if (!mp_is_positive_integer(x
))
155 /* Translators: Error displayed when boolean XOR attempted on non-integer values */
156 mperr(_("Boolean NOT is only defined for positive integers"));
159 mp_set_from_integer(0, &temp
);
160 mp_bitwise(x
, &temp
, mp_bitwise_not
, z
, wordlen
);
165 mp_mask(const MPNumber
*x
, int wordlen
, MPNumber
*z
)
170 /* Convert to a hexadecimal string and use last characters */
171 text
= to_hex_string(x
);
173 offset
= wordlen
/ 4;
174 offset
= len
> offset
? len
- offset
: 0;
175 mp_set_from_string(text
+ offset
, 16, z
);
181 mp_shift(const MPNumber
*x
, int count
, MPNumber
*z
)
183 int i
, multiplier
= 1;
185 if (!mp_is_integer(x
)) {
186 /* Translators: Error displayed when bit shift attempted on non-integer values */
187 mperr(_("Shift is only possible on integer values"));
192 for (i
= 0; i
< count
; i
++)
194 mp_multiply_integer(x
, multiplier
, z
);
198 for (i
= 0; i
< -count
; i
++)
200 mp_divide_integer(x
, multiplier
, &temp
);
207 mp_ones_complement(const MPNumber
*x
, int wordlen
, MPNumber
*z
)
210 mp_set_from_integer(0, &t
);
211 mp_bitwise(x
, &t
, mp_bitwise_xor
, z
, wordlen
);
212 mp_not(z
, wordlen
, z
);
217 mp_twos_complement(const MPNumber
*x
, int wordlen
, MPNumber
*z
)
219 mp_ones_complement (x
, wordlen
, z
);
220 mp_add_integer (z
, 1, z
);