1 /* gnu_java_math_GMP.c -- Native MPI implemenetation over GNU MP
2    Copyright (C) 2006  Free Software Foundation, Inc.
3 
4 This file is a part of GNU Classpath.
5 
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or (at
9 your option) any later version.
10 
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
19 USA
20 
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25 
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version.  */
37 
38 #include <limits.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 
42 #ifdef HAVE_CONFIG_H
43 #include "config.h"
44 #endif /* HAVE_CONFIG_H */
45 
46 #include "gnu_java_math_GMP.h"
47 #include <jcl.h>
48 
49 #if defined(HAVE_GMP_H)
50 #include <gmp.h>
51 #endif /* defined(HAVE_GMP_H) */
52 
53 #if defined(WITH_GNU_MP)
54 #else
55 #warning GNU MP not available or wanted!
56 #warning Invocation of natXXX() methods will raise an exception
57 #endif
58 
59 /*
60  * This is the implementation of the native BigInteger$NativeMPI methods which
61  * use the GNU MP (GMP) library.
62  *
63  * In all the Java non-statically declared native methods, the second argument,
64  * an instance of jobject, refers to the current NativeMPI instance; i.e.
65  * "this" in Java parlance. The corresponding allocated data structure
66  * representing the GMP's counter-part is pointed-to by the pointer stored in a
67  * transient java field named "native_ptr". The first thing these methods do is
68  * (a) access that field with a JNI GetObjectField() call to obtain the
69  * reference to the gnu.classpath.Pointer subclass instance, then (b) obtain
70  * the native GMP pointer (an mpz_ptr), in order to perform their job; e.g.
71  *
72  *   JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr))
73  *
74  * For static methods the second argument, an instance of jclass, is almost
75  * always unused --except when initializing the library, which is the only time
76  * we get hold of the native pointer field.
77  *
78  * This code was written and tested with GNU MP version 4.1.2. More recent
79  * versions of that library offer more operations; e.g. in the implementation
80  * of the method Java_java_math_BigInteger_00024NativeMPI_natFlipBit, mpz_combit()
81  * should be used with GNU MP versions later than 4.2. As a consequence, this
82  * code should be reviewed, from time to time, to use newer features of the GNU
83  * MP library.
84  */
85 
86 static jfieldID native_ptr;
87 
88 #ifdef DEBUG
89 #define TRACE(msg) fprintf (stderr, "%s(%s:%d) -- %s\n", __FUNCTION__, __FILE__, __LINE__, msg)
90 #else
91 #define TRACE(msg)
92 #endif
93 
94 #define throw_config_exception(env) JCL_ThrowException (env, "java/lang/Error", "GNU MP was not specified/found by configure")
95 
96 /*
97  * Initialize the native library. Specifically this method:
98  *
99  * a. Pass NULLs to the mp_set_memory_functions implying that GMP should use
100  *    malloc, realloc and free for memory allocation, and if they fail GMP
101  *    will print a message to the standard error output and terminates the
102  *    program.
103  * b. Find out and store the reference to the NativeMPI class's 'native_ptr'
104  *    field. This is done so later in the method invocations we can access that
105  *    field and acquire the native value associated with that Pointer instance.
106  */
107 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natInitializeLibrary(JNIEnv * env,jclass nativeMPI)108 Java_gnu_java_math_GMP_natInitializeLibrary (JNIEnv *env,
109                                                                jclass nativeMPI)
110 {
111 #if defined(WITH_GNU_MP)
112   TRACE("Loading GMP-based BigInteger native library");
113   mp_set_memory_functions (NULL, NULL, NULL);
114   native_ptr = (*env)->GetFieldID (env, nativeMPI, "native_ptr",
115                                    "Lgnu/classpath/Pointer;");
116   TRACE("Loaded GMP-based BigInteger native library");
117 #else /* !defined(WITH_GNU_MP) */
118   (void) nativeMPI;
119   throw_config_exception(env);
120 #endif /* defined(WITH_GNU_MP) */
121 }
122 
123 /*
124  * Allocate and initialize the data structure for an instance of a NativeMPI.
125  *
126  * @param this  an instance of NativeMPI.
127  */
128 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natInitialize(JNIEnv * env,jobject this)129 Java_gnu_java_math_GMP_natInitialize(JNIEnv *env, jobject this)
130 {
131 #if defined(WITH_GNU_MP)
132   mpz_ptr _this;
133 
134   TRACE("begin");
135   _this = (mpz_ptr)JCL_malloc (env, sizeof (mpz_t));
136   /* initialize --GMP sets the value to zero. */
137   mpz_init (_this);
138   /* instantiate the Pointer instance for this NativeMPI. */
139   jobject native_ptr_fld = JCL_NewRawDataObject (env, _this);
140   /* ... and assign it to the native_ptr field. */
141   (*env)->SetObjectField (env, this, native_ptr, native_ptr_fld);
142   TRACE("end");
143 #else /* !defined(WITH_GNU_MP) */
144   (void) this;
145   throw_config_exception(env);
146 #endif /* defined(WITH_GNU_MP) */
147 }
148 
149 /*
150  * Clear and free the data structure for an instance of a NativeMPI.
151  *
152  * @param this  an instance of NativeMPI.
153  */
154 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natFinalize(JNIEnv * env,jobject this)155 Java_gnu_java_math_GMP_natFinalize(JNIEnv *env, jobject this)
156 {
157 #if defined(WITH_GNU_MP)
158   mpz_ptr _this;
159 
160   TRACE("begin");
161   _this = (mpz_ptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
162   if (_this != NULL)
163     {
164       mpz_clear (_this);
165       free (_this);
166       _this = NULL;
167     }
168   else
169     {
170       TRACE("WARNING: Already cleared + freed");
171     }
172   TRACE("end");
173 #else /* !defined(WITH_GNU_MP) */
174   (void) this;
175   throw_config_exception(env);
176 #endif /* defined(WITH_GNU_MP) */
177 }
178 
179 
180 /*
181  * @param this  an instance of NativeMPI. On exit, this will have a value of n.
182  * @param n  a Java long primitive value.
183  */
184 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natFromLong(JNIEnv * env,jobject this,jlong n)185 Java_gnu_java_math_GMP_natFromLong(JNIEnv *env, jobject this,
186                                                      jlong n)
187 {
188 #if defined(WITH_GNU_MP)
189   mpz_ptr _this;
190 
191   TRACE("begin");
192   _this = (mpz_ptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
193   /* the size of jlong (64-bit) is either the same as a long, or that of a long long.
194    * if it's the former, we use as is. */
195   if (sizeof (jlong) == sizeof (long))
196     {
197       mpz_set_si (_this, (signed long)n);
198     }
199   else
200     {
201       /* ...otherwise, we operate on the two halves of the long long, each half
202        * being 32-bit wide.  for simplicity, we work with positive
203        * values negating, if necessary, the final outcome.
204        */
205       const int isnegative = n < 0 ? 1 : 0;
206       if (isnegative)
207         {
208           n = -n;
209         }
210       mpz_set_ui (_this, (unsigned long)(((unsigned long long)n) >> 32));
211       mpz_mul_2exp (_this, _this, 32); /* shift left by 32 bits */
212       mpz_add_ui (_this, _this, (unsigned long)n);
213       if (isnegative)
214         {
215           mpz_neg (_this, _this);
216         }
217     }
218   TRACE("end");
219 #else /* !defined(WITH_GNU_MP) */
220   (void) n;
221   (void) r;
222   throw_config_exception(env);
223 #endif /* defined(WITH_GNU_MP) */
224 }
225 
226 /*
227  * @param this  an instance of NativeMPI. On exit, this will have the same
228  *           value as x.
229  * @param x  an instance of a NativeMPI's Pointer.
230  */
231 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natFromBI(JNIEnv * env,jobject this,jobject x)232 Java_gnu_java_math_GMP_natFromBI(JNIEnv *env, jobject this,
233                                                    jobject x)
234 {
235 #if defined(WITH_GNU_MP)
236   mpz_ptr _this;
237   mpz_srcptr _x;
238 
239   TRACE("begin");
240   _this = (mpz_ptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
241   _x = (mpz_srcptr)JCL_GetRawData (env, x);
242   mpz_set (_this, _x);
243   TRACE("end");
244 #else /* !defined(WITH_GNU_MP) */
245   (void) this;
246   (void) x;
247   throw_config_exception(env);
248 #endif /* defined(WITH_GNU_MP) */
249 }
250 
251 /*
252  * @param this  an instance of NativeMPI. On exit, this will have the value
253  *           represented by the v Java byte array (in 2's complement with most
254  *           significant byte at index position 0). The sign is implied by the
255  *           value of the most significant byte.
256  * @param v  a Java byte array containing the byte representation, in 2's
257  *           complement of the signed value to assign to this.
258  */
259 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natFromByteArray(JNIEnv * env,jobject this,jbyteArray v)260 Java_gnu_java_math_GMP_natFromByteArray(JNIEnv *env,
261                                                           jobject this,
262                                                           jbyteArray v)
263 {
264 #if defined(WITH_GNU_MP)
265   mpz_ptr _this;
266   jbyte *_v;
267   unsigned long b;
268   int vlength, isnegative, i;
269 
270   TRACE("begin");
271   _this = (mpz_ptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
272   _v = (*env)->GetByteArrayElements (env, v, NULL);
273   vlength = (*env)->GetArrayLength (env, v);
274   b = (unsigned long)(_v[0] & 0xFF);
275   isnegative = (b > 0x7F) ? 1 : 0;
276   mpz_set_ui (_this, 0);
277   for (i = 0; i < vlength; i++)
278     {
279       mpz_mul_2exp (_this, _this, 8); /* shift left 8 positions. */
280       b = (unsigned long)(_v[i] & 0xFF);
281       b = (isnegative) ? ~b : b;
282       mpz_add_ui (_this, _this, (unsigned long)(b & 0xFF));
283     }
284   (*env)->ReleaseByteArrayElements (env, v, _v, JNI_ABORT);
285   if (isnegative)
286     {
287       mpz_add_ui (_this, _this, 1);
288       mpz_neg (_this, _this);
289     }
290   TRACE("end");
291 #else /* !defined(WITH_GNU_MP) */
292   (void) this;
293   (void) v;
294   throw_config_exception(env);
295 #endif /* defined(WITH_GNU_MP) */
296 }
297 
298 /*
299  * @param this  an instance of NativeMPI. On exit, this will have the value
300  *           represented by the s Java string.
301  * @param s  a Java string containing, a possibly signed, value to assign to
302  *           this.
303  * @param rdx  the base in which the symbols, in s, are represented.
304  * @return  0 if the entire string is a valid number in base rdx. Otherwise it
305  *          returns -1.
306  *
307  * Implementation note:
308  * While the GMP library is more tolerant in what it accepts as parameter values
309  * for conversions from strings, the BigInteger code, which calls this method,
310  * ensures that the contract described in the RI's documentation is respected;
311  * e.g. no white spaces in the middle, limited valid radix values, etc...
312  */
313 JNIEXPORT jint JNICALL
Java_gnu_java_math_GMP_natFromString(JNIEnv * env,jobject this,jstring s,jint rdx)314 Java_gnu_java_math_GMP_natFromString(JNIEnv *env,
315                                                        jobject this, jstring s,
316                                                        jint rdx)
317 {
318 #if defined(WITH_GNU_MP)
319   mpz_ptr _this;
320   const char *_s;
321   int result;
322 
323   TRACE("begin");
324   _this = (mpz_ptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
325   _s = (*env)->GetStringUTFChars (env, s, NULL);
326   result = mpz_set_str (_this, _s, (int)rdx);
327   JCL_free_cstring (env, s, _s);
328   TRACE("end");
329   return (result);
330 #else /* !defined(WITH_GNU_MP) */
331   (void) this;
332   (void) s;
333   (void) rdx;
334   throw_config_exception(env);
335   return (-1);
336 #endif /* defined(WITH_GNU_MP) */
337 }
338 
339 /*
340  * @param this  an instance of NativeMPI. On exit, this will have the value
341  *           represented by the m Java byte array (most significant byte at
342  *           index position 0). It will be positive, or negative, depending on
343  *           the value of isnegative.
344  * @param m  a Java byte array containing the byte representation of the
345  *           absolute value (most significant byte being at index position 0)
346  *           to assign to this.
347  * @param isnegative  true if this should be negative and false if it should
348  *           be positive.
349  */
350 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natFromSignedMagnitude(JNIEnv * env,jobject this,jbyteArray m,jboolean isnegative)351 Java_gnu_java_math_GMP_natFromSignedMagnitude(JNIEnv *env,
352                                                                 jobject this,
353                                                                 jbyteArray m,
354                                                                 jboolean isnegative)
355 {
356 #if defined(WITH_GNU_MP)
357   mpz_ptr _this;
358   jbyte *_m;
359   int mlength, i;
360 
361   TRACE("begin");
362   _this = (mpz_ptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
363   _m = (*env)->GetByteArrayElements (env, m, NULL);
364   mlength = (*env)->GetArrayLength (env, m);
365   mpz_set_ui (_this, 0);
366   for (i = 0; i < mlength; i++)
367     {
368       mpz_mul_2exp (_this, _this, 8);
369       mpz_add_ui (_this, _this, (unsigned long)(_m[i] & 0xFF));
370     }
371   (*env)->ReleaseByteArrayElements (env, m, _m, JNI_ABORT);
372   if (isnegative == JNI_TRUE)
373     {
374       mpz_neg (_this, _this);
375     }
376   TRACE("end");
377 #else /* !defined(WITH_GNU_MP) */
378   (void) this;
379   (void) m;
380   (void) isnegative;
381   throw_config_exception(env);
382 #endif /* defined(WITH_GNU_MP) */
383 }
384 
385 /*
386  * @param this  an instance of NativeMPI.
387  * @param n  the base in which to represent this.
388  * @return  the Java string representing the value of this in base n.
389  */
390 JNIEXPORT jstring JNICALL
Java_gnu_java_math_GMP_natToString(JNIEnv * env,jobject this,jint n)391 Java_gnu_java_math_GMP_natToString(JNIEnv *env, jobject this,
392                                                      jint n)
393 {
394 #if defined(WITH_GNU_MP)
395   mpz_srcptr _this;
396   char *cstr;
397   jstring result;
398 
399   TRACE("begin");
400   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
401   cstr = mpz_get_str (NULL, (int)n, _this);
402   result  = (*env)->NewStringUTF (env, cstr);
403   free (cstr);
404   TRACE("end");
405   return (result);
406 #else /* !defined(WITH_GNU_MP) */
407   (void) this;
408   (void) n;
409   throw_config_exception(env);
410   return (NULL);
411 #endif /* defined(WITH_GNU_MP) */
412 }
413 
414 /*
415  * @param this  a non-ZERO instance of NativeMPI.
416  *
417  * output:
418  * @param r  a Java byte array which shall contain the byte representation of
419  *           this.
420  */
421 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natToByteArray(JNIEnv * env,jobject this,jbyteArray r)422 Java_gnu_java_math_GMP_natToByteArray(JNIEnv *env,
423                                                         jobject this,
424                                                         jbyteArray r)
425 {
426 #if defined(WITH_GNU_MP)
427   mpz_srcptr _this;
428   mpz_t _w;  /* a temporary work mpi */
429   jbyte *_r;
430   int rlength, sign, i;
431   unsigned long b;
432 
433   TRACE("begin");
434   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
435   _r = (*env)->GetByteArrayElements (env, r, NULL);
436   rlength = (*env)->GetArrayLength (env, r);
437   mpz_init (_w);
438   /* if this is negative set w to its 2's complement otherwise use as is. */
439   sign = mpz_sgn (_this);
440   if (sign == 1)
441     {
442       mpz_set (_w, _this);
443     }
444   else
445     {
446       mpz_neg (_w, _this);
447       mpz_sub_ui (_w, _w, 1);
448     }
449   /* _w SHOULD be >= 0.
450    * start filling the array starting from the least significant byte. */
451   for (i = rlength; --i >= 0; )
452     {
453       b = mpz_tdiv_q_ui (_w, _w, 256);
454       b = (sign == -1) ? ~b : b;
455       _r[i] = (unsigned long)(b & 0xFF);
456     }
457   (*env)->ReleaseByteArrayElements (env, r, _r, JNI_COMMIT);
458   /* if _w > 0 the byte array was short. */
459   if (mpz_cmp_ui (_w, 0) > 0)
460     {
461       TRACE("WARNING: byte array is too short");
462     }
463   mpz_clear (_w);
464   TRACE("end");
465 #else /* !defined(WITH_GNU_MP) */
466   (void) this;
467   (void) r;
468   throw_config_exception(env);
469 #endif /* defined(WITH_GNU_MP) */
470 }
471 
472 /*
473  * @param this  an instance of NativeMPI.
474  * @return  the "int" value (least significant 32 bits) of the absolute value
475  *          of this NativeMPI. The calling code MUST handle the sign. We do
476  *          this so we can use the same method when computing the "long" value
477  *          as well.
478  */
479 JNIEXPORT jint JNICALL
Java_gnu_java_math_GMP_natAbsIntValue(JNIEnv * env,jobject this)480 Java_gnu_java_math_GMP_natAbsIntValue(JNIEnv *env,
481                                                         jobject this)
482 {
483 #if defined(WITH_GNU_MP)
484   mpz_srcptr _this;
485 
486   TRACE("begin");
487   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
488   TRACE("end");
489   return ((jint)mpz_get_ui (_this));
490 #else /* !defined(WITH_GNU_MP) */
491   (void) s;
492   throw_config_exception(env);
493   return (-1);
494 #endif /* defined(WITH_GNU_MP) */
495 }
496 
497 /*
498  * @param this  an instance of NativeMPI.
499  * @return  the, eventually truncated, double value of this NativeMPI.
500  */
501 JNIEXPORT jdouble JNICALL
Java_gnu_java_math_GMP_natDoubleValue(JNIEnv * env,jobject this)502 Java_gnu_java_math_GMP_natDoubleValue(JNIEnv *env,
503                                                         jobject this)
504 {
505 #if defined(WITH_GNU_MP)
506   mpz_srcptr _this;
507 
508   TRACE("begin");
509   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
510   TRACE("end");
511   return ((jdouble)mpz_get_d (_this));
512 #else /* !defined(WITH_GNU_MP) */
513   (void) this;
514   throw_config_exception(env);
515   return (0.0);
516 #endif /* defined(WITH_GNU_MP) */
517 }
518 
519 /*
520  * @param this  a NativeMPI instance.
521  * @param x  an instance of NativeMPI's Pointer.
522  * @return  -1, 0, +1 if x is respectively less than, equal to, or greater
523  *          than y.
524  */
525 JNIEXPORT jint JNICALL
Java_gnu_java_math_GMP_natCompare(JNIEnv * env,jobject this,jobject x)526 Java_gnu_java_math_GMP_natCompare(JNIEnv *env, jobject this,
527                                                     jobject x)
528 {
529 #if defined(WITH_GNU_MP)
530   mpz_ptr _this, _x;
531   int res;
532 
533   TRACE("begin");
534   _this = (mpz_ptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
535   _x = (mpz_ptr)JCL_GetRawData (env, x);
536   res = mpz_cmp (_this, _x);
537   TRACE("end");
538   if (res == 0)
539     return ((jint)0);
540   else if (res < 0)
541     return ((jint)-1);
542   else
543     return ((jint)1);
544 #else /* !defined(WITH_GNU_MP) */
545   (void) x;
546   (void) y;
547   throw_config_exception(env);
548   return (0);
549 #endif /* defined(WITH_GNU_MP) */
550 }
551 
552 /*
553  * @param this  an instance of NativeMPI.
554  * @param x  an instance of NativeMPI's Pointer.
555  *
556  * output:
557  * @param r  a NativeMPI's Pointer such that r = this + x.
558  */
559 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natAdd(JNIEnv * env,jobject this,jobject x,jobject r)560 Java_gnu_java_math_GMP_natAdd(JNIEnv *env, jobject this,
561                                                 jobject x, jobject r)
562 {
563 #if defined(WITH_GNU_MP)
564   mpz_srcptr _this, _x;
565   mpz_ptr _r;
566 
567   TRACE("begin");
568   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
569   _x = (mpz_srcptr)JCL_GetRawData (env, x);
570   _r = (mpz_ptr)JCL_GetRawData (env, r);
571   mpz_add (_r, _this, _x);
572   TRACE("end");
573 #else /* !defined(WITH_GNU_MP) */
574   (void) this;
575   (void) x;
576   (void) r;
577   throw_config_exception(env);
578 #endif /* defined(WITH_GNU_MP) */
579 }
580 
581 /*
582  * @param this  an instance of NativeMPI.
583  * @param x  an instance of NativeMPI's Pointer.
584  *
585  * output:
586  * @param r  a NativeMPI's Pointer such that r = this - x.
587  */
588 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natSubtract(JNIEnv * env,jobject this,jobject x,jobject r)589 Java_gnu_java_math_GMP_natSubtract(JNIEnv *env, jobject this,
590                                                      jobject x, jobject r)
591 {
592 #if defined(WITH_GNU_MP)
593   mpz_srcptr _this, _x;
594   mpz_ptr _r;
595 
596   TRACE("begin");
597   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
598   _x = (mpz_srcptr)JCL_GetRawData (env, x);
599   _r = (mpz_ptr)JCL_GetRawData (env, r);
600   mpz_sub (_r, _this, _x);
601   TRACE("end");
602 #else /* !defined(WITH_GNU_MP) */
603   (void) this;
604   (void) x;
605   (void) r;
606   throw_config_exception(env);
607 #endif /* defined(WITH_GNU_MP) */
608 }
609 
610 /*
611  * @param this  an instance of NativeMPI.
612  * @param x  an instance of NativeMPI's Pointer.
613  *
614  * output:
615  * @param r  a NativeMPI's Pointer such that r = this * x.
616  */
617 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natMultiply(JNIEnv * env,jobject this,jobject x,jobject r)618 Java_gnu_java_math_GMP_natMultiply(JNIEnv *env, jobject this,
619                                                      jobject x, jobject r)
620 {
621 #if defined(WITH_GNU_MP)
622   mpz_srcptr _this, _x;
623   mpz_ptr _r;
624 
625   TRACE("begin");
626   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
627   _x = (mpz_srcptr)JCL_GetRawData (env, x);
628   _r = (mpz_ptr)JCL_GetRawData (env, r);
629   mpz_mul (_r, _this, _x);
630   TRACE("end");
631 #else /* !defined(WITH_GNU_MP) */
632   (void) this;
633   (void) x;
634   (void) r;
635   throw_config_exception(env);
636 #endif /* defined(WITH_GNU_MP) */
637 }
638 
639 /*
640  * @param this  an instance of NativeMPI.
641  * @param x  an instance of NativeMPI's Pointer.
642  *
643  * output:
644  * @param r  a NativeMPI's Pointer such that r = this div x.
645  */
646 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natQuotient(JNIEnv * env,jobject this,jobject x,jobject r)647 Java_gnu_java_math_GMP_natQuotient(JNIEnv *env, jobject this,
648                                                      jobject x, jobject r)
649 {
650 #if defined(WITH_GNU_MP)
651   mpz_srcptr _this, _x;
652   mpz_ptr _r;
653 
654   TRACE("begin");
655   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
656   _x = (mpz_srcptr)JCL_GetRawData (env, x);
657   _r = (mpz_ptr)JCL_GetRawData (env, r);
658   mpz_tdiv_q (_r, _this, _x);
659   TRACE("end");
660 #else /* !defined(WITH_GNU_MP) */
661   (void) this;
662   (void) x;
663   (void) r;
664   throw_config_exception(env);
665 #endif /* defined(WITH_GNU_MP) */
666 }
667 
668 /*
669  * @param this  an instance of NativeMPI.
670  * @param x  an instance of NativeMPI's Pointer.
671  *
672  * output:
673  * @param r  a NativeMPI's Pointer such that r = this mod x.
674  */
675 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natRemainder(JNIEnv * env,jobject this,jobject x,jobject r)676 Java_gnu_java_math_GMP_natRemainder(JNIEnv *env, jobject this,
677                                                       jobject x, jobject r)
678 {
679 #if defined(WITH_GNU_MP)
680   mpz_srcptr _this, _x;
681   mpz_ptr _r;
682 
683   TRACE("begin");
684   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
685   _x = (mpz_srcptr)JCL_GetRawData (env, x);
686   _r = (mpz_ptr)JCL_GetRawData (env, r);
687   mpz_tdiv_r (_r, _this, _x);
688   TRACE("end");
689 #else /* !defined(WITH_GNU_MP) */
690   (void) this;
691   (void) x;
692   (void) r;
693   throw_config_exception(env);
694 #endif /* defined(WITH_GNU_MP) */
695 }
696 
697 /*
698  * @param this  an instance of NativeMPI.
699  * @param x  an instance of NativeMPI's Pointer.
700  *
701  * output:
702  * @param q  a NativeMPI's Pointer such that q = this div x.
703  * @param r  a NativeMPI's Pointer such that r = this mod x.
704  */
705 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natQuotientAndRemainder(JNIEnv * env,jobject this,jobject x,jobject q,jobject r)706 Java_gnu_java_math_GMP_natQuotientAndRemainder(JNIEnv *env,
707                                                                  jobject this,
708                                                                  jobject x,
709                                                                  jobject q,
710                                                                  jobject r)
711 {
712 #if defined(WITH_GNU_MP)
713   mpz_srcptr _this, _x;
714   mpz_ptr _q, _r;
715 
716   TRACE("begin");
717   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
718   _x = (mpz_srcptr)JCL_GetRawData (env, x);
719   _q = (mpz_ptr)JCL_GetRawData (env, q);
720   _r = (mpz_ptr)JCL_GetRawData (env, r);
721   mpz_tdiv_qr (_q, _r, _this, _x);
722   TRACE("end");
723 #else /* !defined(WITH_GNU_MP) */
724   (void) this;
725   (void) x;
726   (void) q;
727   (void) r;
728   throw_config_exception(env);
729 #endif /* defined(WITH_GNU_MP) */
730 }
731 
732 /*
733  * @param this  an instance of NativeMPI.
734  * @param x  an instance of NativeMPI's Pointer.
735  *
736  * output:
737  * @param r  a NativeMPI's Pointer such that r = this mod x.
738  */
739 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natModulo(JNIEnv * env,jobject this,jobject x,jobject r)740 Java_gnu_java_math_GMP_natModulo(JNIEnv *env, jobject this,
741                                                    jobject x, jobject r)
742 {
743 #if defined(WITH_GNU_MP)
744   mpz_srcptr _this, _x;
745   mpz_ptr _r;
746 
747   TRACE("begin");
748   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
749   _x = (mpz_srcptr)JCL_GetRawData (env, x);
750   _r = (mpz_ptr)JCL_GetRawData (env, r);
751   mpz_mod (_r, _this, _x);
752   TRACE("end");
753 #else /* !defined(WITH_GNU_MP) */
754   (void) this;
755   (void) x;
756   (void) r;
757   throw_config_exception(env);
758 #endif /* defined(WITH_GNU_MP) */
759 }
760 
761 /*
762  * @param this  an instance of NativeMPI.
763  * @param n  a non-negative number to raise this to.
764  *
765  * output:
766  * @param r  a NativeMPI's Pointer such that r = this ** n.
767  */
768 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natPow(JNIEnv * env,jobject this,jint n,jobject r)769 Java_gnu_java_math_GMP_natPow(JNIEnv *env, jobject this,
770                                                 jint n, jobject r)
771 {
772 #if defined(WITH_GNU_MP)
773   mpz_srcptr _this;
774   mpz_ptr _r;
775 
776   TRACE("begin");
777   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
778   _r = (mpz_ptr)JCL_GetRawData (env, r);
779   mpz_pow_ui (_r, _this, (unsigned long)n);
780   TRACE("end");
781 #else /* !defined(WITH_GNU_MP) */
782   (void) this;
783   (void) n;
784   (void) r;
785   throw_config_exception(env);
786 #endif /* defined(WITH_GNU_MP) */
787 }
788 
789 /*
790  * @param this  an instance of NativeMPI.
791  * @param e  an instance of NativeMPI's Pointer.
792  * @param m  another instance of NativeMPI's Pointer.
793  *
794  * output:
795  * @param r  a NativeMPI's Pointer such that r = (this**e) mod m.
796  *
797  * @throws java.lang.ArithmeticException if e is negative and (1 / this) mod m
798  *         has no multiplicative inverse.
799  */
800 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natModPow(JNIEnv * env,jobject this,jobject e,jobject m,jobject r)801 Java_gnu_java_math_GMP_natModPow(JNIEnv *env, jobject this,
802                                                    jobject e, jobject m,
803                                                    jobject r)
804 {
805 #if defined(WITH_GNU_MP)
806   mpz_srcptr _this, _e, _m;
807   mpz_ptr _r;
808 
809   TRACE("begin");
810   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
811   _e = (mpz_srcptr)JCL_GetRawData (env, e);
812   _m = (mpz_srcptr)JCL_GetRawData (env, m);
813   _r = (mpz_ptr)JCL_GetRawData (env, r);
814   /* the documentation of mpz_powm(rop, b, e, m) states that it: "Set rop to
815    * (b raised to e) modulo m.  Negative e is supported if an inverse b^-1 mod m
816    * exists.... If an inverse doesn't exist then a divide by zero is raised."
817    * to work around this case we use the same code as in the pure java class;
818    * i.e.:
819    *     if (e.isNegative())
820    *       return this.modInverse(m).modPow(e.negate(), m); */
821   if (mpz_sgn (_e) == -1)
822     {
823       mpz_t _w;  /* a temporary work mpi */
824       const int res = mpz_invert (_r, _this, _m);
825       if (res == 0)
826         {
827           JCL_ThrowException (env, "java/lang/ArithmeticException",
828                               "No multiplicative inverse modulo the designated number exists");
829         }
830       mpz_init (_w);
831       mpz_neg (_w, _e);
832       mpz_powm (_r, _r, _w, _m);
833       mpz_clear (_w);
834     }
835   else
836     {
837       mpz_powm (_r, _this, _e, _m);
838     }
839 
840   while (mpz_sgn (_r) == -1)
841     {
842       mpz_add (_r, _r, _m);
843     }
844   TRACE("end");
845 #else /* !defined(WITH_GNU_MP) */
846   (void) this;
847   (void) e;
848   (void) m;
849   (void) r;
850   throw_config_exception(env);
851 #endif /* defined(WITH_GNU_MP) */
852 }
853 
854 /*
855  * @param this  an instance of NativeMPI.
856  * @param m  an instance of NativeMPI's Pointer.
857  *
858  * output:
859  * @param r  a NativeMPI's Pointer such that r = (1 / this) mod m.
860  * @throws java.lang.ArithmeticException if (1 / this) mod m has no
861  *         multiplicative inverse.
862  */
863 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natModInverse(JNIEnv * env,jobject this,jobject m,jobject r)864 Java_gnu_java_math_GMP_natModInverse(JNIEnv *env,
865                                                        jobject this,
866                                                        jobject m, jobject r)
867 {
868 #if defined(WITH_GNU_MP)
869   mpz_srcptr _this, _m;
870   mpz_ptr _r;
871   int res;
872 
873   TRACE("begin");
874   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
875   _m = (mpz_srcptr)JCL_GetRawData (env, m);
876   _r = (mpz_ptr)JCL_GetRawData (env, r);
877   res = mpz_invert (_r, _this, _m);
878   if (res == 0)
879     {
880       JCL_ThrowException (env, "java/lang/ArithmeticException",
881                           "No multiplicative inverse modulo the designated number exists");
882     }
883 
884   while (mpz_sgn (_r) == -1)
885     {
886       mpz_add (_r, _r, _m);
887     }
888   TRACE("end");
889 #else /* !defined(WITH_GNU_MP) */
890   (void) this;
891   (void) x;
892   (void) r;
893   throw_config_exception(env);
894 #endif /* defined(WITH_GNU_MP) */
895 }
896 
897 /*
898  * @param this  an instance of NativeMPI.
899  * @param x  an instance of NativeMPI's Pointer.
900  *
901  * output:
902  * @param r  a NativeMPI's Pointer such that r is the GCD of this and x.
903  */
904 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natGCD(JNIEnv * env,jobject this,jobject x,jobject r)905 Java_gnu_java_math_GMP_natGCD(JNIEnv *env, jobject this,
906                                                 jobject x, jobject r)
907 {
908 #if defined(WITH_GNU_MP)
909   mpz_srcptr _this, _x;
910   mpz_ptr _r;
911 
912   TRACE("begin");
913   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
914   _x = (mpz_srcptr)JCL_GetRawData (env, x);
915   _r = (mpz_ptr)JCL_GetRawData (env, r);
916   mpz_gcd (_r, _this, _x);
917   TRACE("end");
918 #else /* !defined(WITH_GNU_MP) */
919   (void) this;
920   (void) x;
921   (void) r;
922   throw_config_exception(env);
923 #endif /* defined(WITH_GNU_MP) */
924 }
925 
926 /*
927  * @param this  an instance of NativeMPI.
928  * @param n  number of Miller-Rabin tests to conduct.
929  * @return  2 if this is definitely prime. Returns 1 if this is probably prime
930  *          (without being certain). Finally, returns 0 if this is definitely
931  *          composite.
932  */
933 JNIEXPORT jint JNICALL
Java_gnu_java_math_GMP_natTestPrimality(JNIEnv * env,jobject this,jint n)934 Java_gnu_java_math_GMP_natTestPrimality(JNIEnv *env,
935                                                           jobject this, jint n)
936 {
937 #if defined(WITH_GNU_MP)
938   mpz_srcptr _this;
939 
940   TRACE("begin");
941   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
942   TRACE("end");
943   return ((jint)mpz_probab_prime_p (_this, (int)n));
944 #else /* !defined(WITH_GNU_MP) */
945   (void) this;
946   (void) n;
947   throw_config_exception(env);
948   return (0);
949 #endif /* defined(WITH_GNU_MP) */
950 }
951 
952 /*
953  * @param this  an instance of NativeMPI.
954  * @param n  the non-negative number of positions to shift right this by.
955  *
956  * output:
957  * @param r  a NativeMPI's Pointer such that r = this * 2**n.
958  */
959 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natShiftLeft(JNIEnv * env,jobject this,jint n,jobject r)960 Java_gnu_java_math_GMP_natShiftLeft(JNIEnv *env, jobject this,
961                                                       jint n, jobject r)
962 {
963 #if defined(WITH_GNU_MP)
964   mpz_srcptr _this;
965   mpz_ptr _r;
966 
967   TRACE("begin");
968   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
969   _r = (mpz_ptr)JCL_GetRawData (env, r);
970   mpz_mul_2exp (_r, _this, (unsigned long)n);
971   TRACE("end");
972 #else /* !defined(WITH_GNU_MP) */
973   (void) this;
974   (void) n;
975   (void) r;
976   throw_config_exception(env);
977 #endif /* defined(WITH_GNU_MP) */
978 }
979 
980 /*
981  * @param this  an instance of NativeMPI.
982  * @param n  the non-negative number of positions to shift left this by.
983  *
984  * output:
985  * @param r  a NativeMPI's Pointer such that r = floor(this / 2**n).
986  */
987 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natShiftRight(JNIEnv * env,jobject this,jint n,jobject r)988 Java_gnu_java_math_GMP_natShiftRight(JNIEnv *env,
989                                                        jobject this, jint n,
990                                                        jobject r)
991 {
992 #if defined(WITH_GNU_MP)
993   mpz_srcptr _this;
994   mpz_ptr _r;
995 
996   TRACE("begin");
997   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
998   _r = (mpz_ptr)JCL_GetRawData (env, r);
999   mpz_fdiv_q_2exp (_r, _this, (unsigned long)n);
1000   TRACE("end");
1001 #else /* !defined(WITH_GNU_MP) */
1002   (void) this;
1003   (void) n;
1004   (void) r;
1005   throw_config_exception(env);
1006 #endif /* defined(WITH_GNU_MP) */
1007 }
1008 
1009 /*
1010  * @param this  an instance of NativeMPI.
1011  * @return  the 0-based index of the lowest significant bit set (to 1) in this.
1012  */
1013 JNIEXPORT jint JNICALL
Java_gnu_java_math_GMP_natLowestSetBit(JNIEnv * env,jobject this)1014 Java_gnu_java_math_GMP_natLowestSetBit(JNIEnv *env,
1015                                                          jobject this)
1016 {
1017 #if defined(WITH_GNU_MP)
1018   mpz_srcptr _this;
1019 
1020   TRACE("begin");
1021   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
1022   TRACE("end");
1023   return ((jint)mpz_scan1 (_this, 0));
1024 #else /* !defined(WITH_GNU_MP) */
1025   (void) this;
1026   throw_config_exception(env);
1027   return (-1);
1028 #endif /* defined(WITH_GNU_MP) */
1029 }
1030 
1031 /*
1032  * @param this  an instance of NativeMPI.
1033  *
1034  * output:
1035  * @param r  a NativeMPI's Pointer such that r = abs(x).
1036  */
1037 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natAbs(JNIEnv * env,jobject this,jobject r)1038 Java_gnu_java_math_GMP_natAbs(JNIEnv *env, jobject this,
1039                                                 jobject r)
1040 {
1041 #if defined(WITH_GNU_MP)
1042   mpz_srcptr _this;
1043   mpz_ptr _r;
1044 
1045   TRACE("begin");
1046   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
1047   _r = (mpz_ptr)JCL_GetRawData (env, r);
1048   mpz_abs (_r, _this);
1049   TRACE("end");
1050 #else /* !defined(WITH_GNU_MP) */
1051   (void) this;
1052   (void) r;
1053   throw_config_exception(env);
1054 #endif /* defined(WITH_GNU_MP) */
1055 }
1056 
1057 /*
1058  * @param this  an instance of NativeMPI.
1059  *
1060  * output:
1061  * @param r  a NativeMPI's Pointer such that r = -x.
1062  */
1063 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natNegate(JNIEnv * env,jobject this,jobject r)1064 Java_gnu_java_math_GMP_natNegate(JNIEnv *env, jobject this,
1065                                                    jobject r)
1066 {
1067 #if defined(WITH_GNU_MP)
1068   mpz_srcptr _this;
1069   mpz_ptr _r;
1070 
1071   TRACE("begin");
1072   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
1073   _r = (mpz_ptr)JCL_GetRawData (env, r);
1074   mpz_neg (_r, _this);
1075   TRACE("end");
1076 #else /* !defined(WITH_GNU_MP) */
1077   (void) this;
1078   (void) r;
1079   throw_config_exception(env);
1080 #endif /* defined(WITH_GNU_MP) */
1081 }
1082 
1083 /*
1084  * @param this  an instance of NativeMPI.
1085  * @return  the number of bits needed to represent this.
1086  */
1087 JNIEXPORT jint JNICALL
Java_gnu_java_math_GMP_natBitLength(JNIEnv * env,jobject this)1088 Java_gnu_java_math_GMP_natBitLength(JNIEnv *env, jobject this)
1089 {
1090 #if defined(WITH_GNU_MP)
1091   mpz_srcptr _this;
1092 
1093   TRACE("begin");
1094   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
1095   TRACE("end");
1096   return ((jint)mpz_sizeinbase (_this, 2));
1097 #else /* !defined(WITH_GNU_MP) */
1098   (void) this;
1099   throw_config_exception(env);
1100   return (-1);
1101 #endif /* defined(WITH_GNU_MP) */
1102 }
1103 
1104 /*
1105  * @param this  an instance of NativeMPI. It MUST be >= ZERO.
1106  * @return  the number of bits set (to 1) in this.
1107  */
1108 JNIEXPORT jint JNICALL
Java_gnu_java_math_GMP_natSetBitCount(JNIEnv * env,jobject this)1109 Java_gnu_java_math_GMP_natSetBitCount(JNIEnv *env,
1110                                                         jobject this)
1111 {
1112 #if defined(WITH_GNU_MP)
1113   mpz_srcptr _this;
1114   mpz_ptr _bi;
1115   unsigned long res = 0;
1116 
1117   TRACE("begin");
1118   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
1119   switch (mpz_sgn (_this))
1120     {
1121       case -1:
1122         /* initialize --GMP sets the value to zero. */
1123         _bi = (mpz_ptr)JCL_malloc (env, sizeof (mpz_t));
1124         mpz_init (_bi);
1125         mpz_neg (_bi, _this);
1126         res = mpz_popcount (_bi);
1127         mpz_clear (_bi);
1128         free (_bi);
1129         break;
1130       case 0:
1131         res = 0;
1132         break;
1133       case 1:
1134         res = mpz_popcount (_this);
1135       default:
1136         JCL_ThrowException (env, "java/lang/Error",
1137                             "Unexpected sign value for a native MPI");
1138     }
1139   TRACE("end");
1140   return ((jint)res);
1141 #else /* !defined(WITH_GNU_MP) */
1142   (void) this;
1143   throw_config_exception(env);
1144   return (ULONG_MAX);
1145 #endif /* defined(WITH_GNU_MP) */
1146 }
1147 
1148 /*
1149  * @param this  an instance of NativeMPI.
1150  * @param x  an instance of NativeMPI's Pointer.
1151  *
1152  * output:
1153  * @param r  a NativeMPI's Pointer such that r = this ^ x.
1154  */
1155 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natXor(JNIEnv * env,jobject this,jobject x,jobject r)1156 Java_gnu_java_math_GMP_natXor(JNIEnv *env, jobject this,
1157                                                 jobject x, jobject r)
1158 {
1159 #if defined(WITH_GNU_MP)
1160   mpz_srcptr _this, _x;
1161   mpz_ptr _r;
1162 
1163   TRACE("begin");
1164   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
1165   _x = (mpz_srcptr)JCL_GetRawData (env, x);
1166   _r = (mpz_ptr)JCL_GetRawData (env, r);
1167   mpz_xor (_r, _this, _x);
1168   TRACE("end");
1169 #else /* !defined(WITH_GNU_MP) */
1170   (void) this;
1171   (void) x;
1172   (void) r;
1173   throw_config_exception(env);
1174 #endif /* defined(WITH_GNU_MP) */
1175 }
1176 
1177 /*
1178  * @param this  an instance of NativeMPI.
1179  * @param x  an instance of NativeMPI's Pointer.
1180  *
1181  * output:
1182  * @param r  a NativeMPI's Pointer such that r = this | x.
1183  */
1184 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natOr(JNIEnv * env,jobject this,jobject x,jobject r)1185 Java_gnu_java_math_GMP_natOr(JNIEnv *env, jobject this,
1186                                                jobject x, jobject r)
1187 {
1188 #if defined(WITH_GNU_MP)
1189   mpz_srcptr _this, _x;
1190   mpz_ptr _r;
1191 
1192   TRACE("begin");
1193   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
1194   _x = (mpz_srcptr)JCL_GetRawData (env, x);
1195   _r = (mpz_ptr)JCL_GetRawData (env, r);
1196   mpz_ior (_r, _this, _x);
1197   TRACE("end");
1198 #else /* !defined(WITH_GNU_MP) */
1199   (void) this;
1200   (void) x;
1201   (void) r;
1202   throw_config_exception(env);
1203 #endif /* defined(WITH_GNU_MP) */
1204 }
1205 
1206 /*
1207  * @param this  an instance of NativeMPI.
1208  * @param x  an instance of NativeMPI's Pointer.
1209  *
1210  * output:
1211  * @param r  a NativeMPI's Pointer such that r = this & x.
1212  */
1213 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natAnd(JNIEnv * env,jobject this,jobject x,jobject r)1214 Java_gnu_java_math_GMP_natAnd(JNIEnv *env, jobject this,
1215                                                 jobject x, jobject r)
1216 {
1217 #if defined(WITH_GNU_MP)
1218   mpz_srcptr _this, _x;
1219   mpz_ptr _r;
1220 
1221   TRACE("begin");
1222   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
1223   _x = (mpz_srcptr)JCL_GetRawData (env, x);
1224   _r = (mpz_ptr)JCL_GetRawData (env, r);
1225   mpz_and (_r, _this, _x);
1226   TRACE("end");
1227 #else /* !defined(WITH_GNU_MP) */
1228   (void) this;
1229   (void) x;
1230   (void) r;
1231   throw_config_exception(env);
1232 #endif /* defined(WITH_GNU_MP) */
1233 }
1234 
1235 /*
1236  * @param this  an instance of NativeMPI.
1237  * @param x  an instance of NativeMPI's Pointer.
1238  *
1239  * output:
1240  * @param r  a NativeMPI's Pointer such that r = this & ~x.
1241  */
1242 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natAndNot(JNIEnv * env,jobject this,jobject x,jobject r)1243 Java_gnu_java_math_GMP_natAndNot(JNIEnv *env, jobject this,
1244                                                    jobject x, jobject r)
1245 {
1246 #if defined(WITH_GNU_MP)
1247   mpz_srcptr _this, _x;
1248   mpz_ptr _r;
1249 
1250   TRACE("begin");
1251   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
1252   _x = (mpz_srcptr)JCL_GetRawData (env, x);
1253   _r = (mpz_ptr)JCL_GetRawData (env, r);
1254   mpz_com (_r, _x);
1255   mpz_and (_r, _this, _r);
1256   TRACE("end");
1257 #else /* !defined(WITH_GNU_MP) */
1258   (void) this;
1259   (void) x;
1260   (void) r;
1261   throw_config_exception(env);
1262 #endif /* defined(WITH_GNU_MP) */
1263 }
1264 
1265 /*
1266  * @param this  an instance of NativeMPI.
1267  * @param n  the 0-based index position of the bit to flip in this. n MUST be
1268  *           greater than, or equal to 0.
1269  *
1270  * output:
1271  * @param r  a copy of this NativeMPI's Pointer with its n-th bit flipped.
1272  */
1273 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natFlipBit(JNIEnv * env,jobject this,jint n,jobject r)1274 Java_gnu_java_math_GMP_natFlipBit(JNIEnv *env, jobject this,
1275                                                     jint n, jobject r)
1276 {
1277 #if defined(WITH_GNU_MP)
1278   mpz_srcptr _this;
1279   mpz_ptr _r;
1280 
1281   TRACE("begin");
1282   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
1283   _r = (mpz_ptr)JCL_GetRawData (env, r);
1284   mpz_set (_r, _this);
1285   /* GNU MP versions earlier than 4.2 do not define this method:
1286    *   mpz_combit (_r, (unsigned long)n); */
1287   if (mpz_tstbit (_r, (unsigned long)n) == 1)
1288     {
1289       mpz_clrbit (_r, (unsigned long)n);
1290     }
1291   else
1292     {
1293       mpz_setbit (_r, (unsigned long)n);
1294     }
1295   TRACE("end");
1296 #else /* !defined(WITH_GNU_MP) */
1297   (void) this;
1298   (void) n;
1299   (void) r;
1300   throw_config_exception(env);
1301 #endif /* defined(WITH_GNU_MP) */
1302 }
1303 
1304 /*
1305  * @param this  an instance of NativeMPI.
1306  * @param n  the 0-based index position of the bit to test in this. n MUST be
1307  *           greater than, or equal to 0.
1308  * @return  +1, or -1 depending on whether the n-th bit in this is set or not
1309  *          respectively.
1310  */
1311 JNIEXPORT jint JNICALL
Java_gnu_java_math_GMP_natTestBit(JNIEnv * env,jobject this,jint n)1312 Java_gnu_java_math_GMP_natTestBit(JNIEnv *env, jobject this,
1313                                                     jint n)
1314 {
1315 #if defined(WITH_GNU_MP)
1316   mpz_srcptr _this;
1317 
1318   TRACE("begin");
1319   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
1320   TRACE("end");
1321   return ((jint)mpz_tstbit (_this, (unsigned long)n));
1322 #else /* !defined(WITH_GNU_MP) */
1323   (void) this;
1324   (void) n;
1325   throw_config_exception(env);
1326   return (-1);
1327 #endif /* defined(WITH_GNU_MP) */
1328 }
1329 
1330 /*
1331  * @param this  an instance of NativeMPI.
1332  * @param n  the 0-based index position of the bit to set, or clear, in this.
1333  *           n MUST be greater than, or equal to 0.
1334  * @param setIt  if true, then the n-th bit in this will be set, otherwise it
1335  *           will be cleared.
1336  *
1337  * output:
1338  * @param r  a copy of this NativeMPI's Pointer with its n-th bit set or cleared
1339  *           as requested.
1340  */
1341 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natSetBit(JNIEnv * env,jobject this,jint n,jboolean setIt,jobject r)1342 Java_gnu_java_math_GMP_natSetBit(JNIEnv *env, jobject this,
1343                                                    jint n, jboolean setIt,
1344                                                    jobject r)
1345 {
1346 #if defined(WITH_GNU_MP)
1347   mpz_srcptr _this;
1348   mpz_ptr _r;
1349 
1350   TRACE("begin");
1351   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
1352   _r = (mpz_ptr)JCL_GetRawData (env, r);
1353   mpz_set (_r, _this);
1354   if (setIt == JNI_TRUE)
1355     {
1356       mpz_setbit (_r, (unsigned long)n);
1357     }
1358   else
1359     {
1360       mpz_clrbit (_r, (unsigned long)n);
1361     }
1362   TRACE("end");
1363 #else /* !defined(WITH_GNU_MP) */
1364   (void) this;
1365   (void) n;
1366   (void) setIt;
1367   (void) r;
1368   throw_config_exception(env);
1369 #endif /* defined(WITH_GNU_MP) */
1370 }
1371 
1372 /*
1373  * @param this  an instance of NativeMPI.
1374  *
1375  * output:
1376  * @param r  a NativeMPI's Pointer such that r = ~this.
1377  */
1378 JNIEXPORT void JNICALL
Java_gnu_java_math_GMP_natNot(JNIEnv * env,jobject this,jobject r)1379 Java_gnu_java_math_GMP_natNot(JNIEnv *env, jobject this,
1380                                                 jobject r)
1381 {
1382 #if defined(WITH_GNU_MP)
1383   mpz_srcptr _this;
1384   mpz_ptr _r;
1385 
1386   TRACE("begin");
1387   _this = (mpz_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, this, native_ptr));
1388   _r = (mpz_ptr)JCL_GetRawData (env, r);
1389   mpz_com (_r, _this);
1390   TRACE("end");
1391 #else /* !defined(WITH_GNU_MP) */
1392   (void) this;
1393   (void) r;
1394   throw_config_exception(env);
1395 #endif /* defined(WITH_GNU_MP) */
1396 }
1397