4 * Copyright (C) 2008 Vincent Geddes
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 #include "st-large-integer.h"
26 #include "st-universe.h"
30 #define VALUE(oop) (&(ST_LARGE_INTEGER(oop)->value))
33 /* useful macros to avoid duplication of error-handling code */
41 result = mp_init (&value); \
42 if (result != MP_OKAY) \
47 if (result != MP_OKAY) \
49 return st_large_integer_new (&value); \
57 #define BINARY_OP(op, a, b) \
59 result = op (VALUE (a), VALUE (b), &value); \
62 #define BINARY_DIV_OP(op, a, b) \
64 result = op (VALUE (a), VALUE (b), &value, NULL); \
67 #define UNARY_OP(op, a) \
69 result = op (VALUE (a), &value); \
73 st_large_integer_add (st_oop a
, st_oop b
, bool *error
)
75 BINARY_OP (mp_add
, a
, b
);
79 st_large_integer_sub (st_oop a
, st_oop b
, bool *error
)
81 BINARY_OP (mp_sub
, a
, b
);
85 st_large_integer_mul (st_oop a
, st_oop b
, bool *error
)
87 BINARY_OP (mp_mul
, a
, b
);
91 st_large_integer_div (st_oop a
, st_oop b
, bool *error
)
93 BINARY_DIV_OP (mp_div
, a
, b
);
97 st_large_integer_mod (st_oop a
, st_oop b
, bool *error
)
99 BINARY_OP (mp_mod
, a
, b
);
103 st_large_integer_sqr (st_oop a
, bool *error
)
105 UNARY_OP (mp_sqr
, a
);
109 st_large_integer_neg (st_oop a
, bool *error
)
111 UNARY_OP (mp_neg
, a
);
115 st_large_integer_abs (st_oop a
, bool *error
)
117 UNARY_OP (mp_abs
, a
);
121 st_large_integer_gcd (st_oop a
, st_oop b
, bool *error
)
123 BINARY_OP (mp_gcd
, a
, b
);
127 st_large_integer_lcm (st_oop a
, st_oop b
, bool *error
)
129 BINARY_OP (mp_lcm
, a
, b
);
133 st_large_integer_bitor (st_oop a
, st_oop b
, bool *error
)
135 BINARY_OP (mp_or
, a
, b
);
139 st_large_integer_bitand (st_oop a
, st_oop b
, bool *error
)
141 BINARY_OP (mp_and
, a
, b
);
145 st_large_integer_bitxor (st_oop a
, st_oop b
, bool *error
)
147 BINARY_OP (mp_xor
, a
, b
);
151 st_large_integer_bitshift (st_oop a
, int shift
, bool *error
)
157 result
= mp_init (&value
);
158 if (result
!= MP_OKAY
)
162 result
= mp_mul_2d (VALUE (a
), shift
, &value
);
164 result
= mp_div_2d (VALUE (a
), shift
, &value
, NULL
);
166 if (result
!= MP_OKAY
)
169 return st_large_integer_new (&value
);
179 st_large_integer_eq (st_oop a
, st_oop b
, bool * error
)
182 return mp_cmp (VALUE (a
), VALUE (b
)) == MP_EQ
;
186 st_large_integer_lt (st_oop a
, st_oop b
, bool * error
)
189 return mp_cmp (VALUE (a
), VALUE (b
)) == MP_LT
;
193 st_large_integer_gt (st_oop a
, st_oop b
, bool * error
)
196 return mp_cmp (VALUE (a
), VALUE (b
)) == MP_GT
;
200 st_large_integer_le (st_oop a
, st_oop b
, bool * error
)
203 int relation
= mp_cmp (VALUE (a
), VALUE (b
));
204 return (relation
== MP_LT
) || (relation
== MP_EQ
);
208 st_large_integer_ge (st_oop a
, st_oop b
, bool * error
)
211 int relation
= mp_cmp (VALUE (a
), VALUE (b
));
212 return (relation
== MP_GT
) || (relation
== MP_EQ
);
216 st_large_integer_is_positive (st_oop a
, bool * error
)
219 return SIGN (VALUE (a
)) != MP_NEG
;
223 st_large_integer_is_prime (st_oop a
, bool * error
)
229 int ntrials
= mp_prime_rabin_miller_trials (mp_count_bits (VALUE (a
)));
231 result
= mp_prime_is_prime (VALUE (a
), ntrials
, &isprime
);
232 if (result
!= MP_OKAY
) {
237 return isprime
== MP_YES
;
241 st_large_integer_new_from_string (const char *string
, guint radix
)
246 g_assert (string
!= NULL
);
248 result
= mp_init (&value
);
249 if (result
!= MP_OKAY
)
252 result
= mp_read_radix (&value
, string
, radix
);
253 if (result
!= MP_OKAY
)
256 return st_large_integer_new (&value
);
260 g_warning (mp_error_to_string (result
));
265 st_large_integer_new_from_smi (st_smi integer
)
269 bool negative
= integer
< 0;
270 st_smi integer_abs
= abs(integer
);
272 result
= mp_init_set_int (&value
, integer_abs
);
273 if (result
!= MP_OKAY
)
277 mp_neg (&value
, &value
);
279 return st_large_integer_new (&value
);
283 g_warning (mp_error_to_string (result
));
288 st_large_integer_to_string (st_oop integer
, guint radix
)
293 result
= mp_radix_size (VALUE (integer
), radix
, &size
);
294 if (result
!= MP_OKAY
)
297 char *str
= g_malloc (size
);
299 mp_toradix (VALUE (integer
), str
, radix
);
300 if (result
!= MP_OKAY
)
306 g_warning (mp_error_to_string (result
));
311 allocate_with_value (st_oop klass
, mp_int
* value
)
313 st_oop object
= st_allocate_object (sizeof (STLargeInteger
) / sizeof (st_oop
));
315 st_heap_object_initialize_header (object
, klass
);
318 *VALUE (object
) = *value
;
320 mp_init (VALUE (object
));
326 st_large_integer_new (mp_int
* value
)
328 return allocate_with_value (st_large_integer_class
, value
);
333 allocate (st_oop klass
)
335 return allocate_with_value (klass
, NULL
);
340 large_integer_copy (st_oop object
)
345 result
= mp_init_copy (&value
, VALUE (object
));
346 if (result
!= MP_OKAY
)
347 g_assert_not_reached ();
349 return st_large_integer_new (&value
);
353 st_large_integer_descriptor (void)
355 static const STDescriptor __descriptor
=
356 { .allocate
= allocate
,
357 .allocate_arrayed
= NULL
,
358 .copy
= large_integer_copy
,
361 return & __descriptor
;