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-internal.h"
25 // FIXME: Make dynamic
26 #define MAX_DIGITS 1000
28 static char digits
[] = "0123456789ABCDEF";
30 static int hex_to_int(char digit
)
32 if (digit
>= '0' && digit
<= '9')
34 if (digit
>= 'A' && digit
<= 'F')
35 return digit
- 'A' + 10;
36 if (digit
>= 'a' && digit
<= 'f')
37 return digit
- 'a' + 10;
43 mp_bitwise(const MPNumber
*x
, const MPNumber
*y
, int (*bitwise_operator
)(int, int), MPNumber
*z
, int wordlen
)
45 char text1
[MAX_DIGITS
], text2
[MAX_DIGITS
], text_out
[MAX_DIGITS
], text_out2
[MAX_DIGITS
];
46 int offset1
, offset2
, offset_out
;
48 mp_cast_to_string(x
, 16, 0, 0, text1
, MAX_DIGITS
);
49 mp_cast_to_string(y
, 16, 0, 0, text2
, MAX_DIGITS
);
50 offset1
= strlen(text1
) - 1 - strlen("₁₆");
51 offset2
= strlen(text2
) - 1 - strlen("₁₆");
52 offset_out
= wordlen
/ 4 - 1;
53 if (offset_out
<= 0) {
54 offset_out
= offset1
> offset2
? offset1
: offset2
;
56 if (offset_out
> 0 && (offset_out
< offset1
|| offset_out
< offset2
)) {
57 mperr("Overflow. Try a bigger word size");
61 /* Perform bitwise operator on each character from right to left */
62 for (text_out
[offset_out
+1] = '\0'; offset_out
>= 0; offset_out
--) {
66 v1
= hex_to_int(text1
[offset1
]);
70 v2
= hex_to_int(text2
[offset2
]);
73 text_out
[offset_out
] = digits
[bitwise_operator(v1
, v2
)];
76 snprintf(text_out2
, MAX_DIGITS
, "%s₁₆", text_out
);
77 mp_set_from_string(text_out2
, z
);
81 static int mp_bitwise_and(int v1
, int v2
) { return v1
& v2
; }
82 static int mp_bitwise_or(int v1
, int v2
) { return v1
| v2
; }
83 static int mp_bitwise_xor(int v1
, int v2
) { return v1
^ v2
; }
84 static int mp_bitwise_not(int v1
, int dummy
) { return v1
^ 0xF; }
88 mp_is_overflow (const MPNumber
*x
, int wordlen
)
91 mp_set_from_integer(2, &tmp1
);
92 mp_xpowy_integer(&tmp1
, wordlen
, &tmp2
);
93 return mp_is_greater_than (&tmp2
, x
);
98 mp_and(const MPNumber
*x
, const MPNumber
*y
, MPNumber
*z
)
100 if (!mp_is_positive_integer(x
) || !mp_is_positive_integer(y
))
102 /* Translators: Error displayed when boolean AND attempted on non-integer values */
103 mperr(_("Boolean AND is only defined for positive integers"));
106 mp_bitwise(x
, y
, mp_bitwise_and
, z
, 0);
111 mp_or(const MPNumber
*x
, const MPNumber
*y
, MPNumber
*z
)
113 if (!mp_is_positive_integer(x
) || !mp_is_positive_integer(y
))
115 /* Translators: Error displayed when boolean OR attempted on non-integer values */
116 mperr(_("Boolean OR is only defined for positive integers"));
119 mp_bitwise(x
, y
, mp_bitwise_or
, z
, 0);
124 mp_xor(const MPNumber
*x
, const MPNumber
*y
, MPNumber
*z
)
126 if (!mp_is_positive_integer(x
) || !mp_is_positive_integer(y
))
128 /* Translators: Error displayed when boolean XOR attempted on non-integer values */
129 mperr(_("Boolean XOR is only defined for positive integers"));
132 mp_bitwise(x
, y
, mp_bitwise_xor
, z
, 0);
137 mp_not(const MPNumber
*x
, int wordlen
, MPNumber
*z
)
141 if (!mp_is_positive_integer(x
))
143 /* Translators: Error displayed when boolean XOR attempted on non-integer values */
144 mperr(_("Boolean NOT is only defined for positive integers"));
147 mp_set_from_integer(0, &temp
);
148 mp_bitwise(x
, &temp
, mp_bitwise_not
, z
, wordlen
);
153 mp_mask(const MPNumber
*x
, int wordlen
, MPNumber
*z
)
155 char text
[MAX_DIGITS
];
158 /* Convert to a hexadecimal string and use last characters */
159 mp_cast_to_string(x
, 16, 0, 0, text
, MAX_DIGITS
);
160 len
= strlen(text
) - strlen("₁₆");
161 offset
= wordlen
/ 4;
162 offset
= len
> offset
? len
- offset
: 0;
163 mp_set_from_string(text
+ offset
, z
);
168 mp_shift(const MPNumber
*x
, int count
, MPNumber
*z
)
170 int i
, multiplier
= 1;
172 if (!mp_is_integer(x
)) {
173 /* Translators: Error displayed when bit shift attempted on non-integer values */
174 mperr(_("Shift is only possible on integer values"));
179 for (i
= 0; i
< count
; i
++)
181 mp_multiply_integer(x
, multiplier
, z
);
185 for (i
= 0; i
< -count
; i
++)
187 mp_divide_integer(x
, multiplier
, &temp
);
188 mp_integer_component(&temp
, z
);
194 mp_ones_complement(const MPNumber
*x
, int wordlen
, MPNumber
*z
)
197 mp_set_from_integer(0, &t
);
198 mp_bitwise(x
, &t
, mp_bitwise_xor
, z
, wordlen
);
199 mp_not(z
, wordlen
, z
);
204 mp_twos_complement(const MPNumber
*x
, int wordlen
, MPNumber
*z
)
206 mp_ones_complement (x
, wordlen
, z
);
207 mp_add_integer (z
, 1, z
);