source: core/c/jbigi/jbigi/src/jbigi.c @ 08d24b0

Last change on this file since 08d24b0 was 08d24b0, checked in by zzz <zzz@…>, 9 years ago

remove nativeDoubleValue(), update jbigi README

  • Property mode set to 100644
File size: 4.8 KB
Line 
1#include <stdio.h>
2#include <gmp.h>
3#include "jbigi.h"
4
5/******** prototypes */
6
7void convert_j2mp(JNIEnv* env, jbyteArray jvalue, mpz_t* mvalue);
8void convert_mp2j(JNIEnv* env, mpz_t mvalue, jbyteArray* jvalue);
9
10
11/*****************************************
12 *****Native method implementations*******
13 *****************************************/
14
15/******** nativeModPow() */
16/*
17 * Class:     net_i2p_util_NativeBigInteger
18 * Method:    nativeModPow
19 * Signature: ([B[B[B)[B
20 *
21 * From the javadoc:
22 *
23 * calculate (base ^ exponent) % modulus.
24 * @param curVal big endian twos complement representation of the base (but it must be positive)
25 * @param exponent big endian twos complement representation of the exponent
26 * @param modulus big endian twos complement representation of the modulus
27 * @return big endian twos complement representation of (base ^ exponent) % modulus
28 */
29
30JNIEXPORT jbyteArray JNICALL Java_net_i2p_util_NativeBigInteger_nativeModPow
31        (JNIEnv* env, jclass cls, jbyteArray jbase, jbyteArray jexp, jbyteArray jmod) {
32        /* 1) Convert base, exponent, modulus into the format libgmp understands
33         * 2) Call libgmp's modPow.
34         * 3) Convert libgmp's result into a big endian twos complement number.
35         */
36
37        mpz_t mbase;
38        mpz_t mexp;
39        mpz_t mmod;
40        jbyteArray jresult;
41
42        convert_j2mp(env, jbase, &mbase);
43        convert_j2mp(env, jexp,  &mexp);
44        convert_j2mp(env, jmod,  &mmod);
45 
46                /* Perform the actual powmod. We use mmod for the result because it is
47         * always at least as big as the result.
48         */
49        mpz_powm(mmod, mbase, mexp, mmod);
50
51                convert_mp2j(env, mmod, &jresult);
52
53        mpz_clear(mbase);
54        mpz_clear(mexp);
55        mpz_clear(mmod);
56
57        return jresult;
58}
59
60/******************************
61 *****Conversion methods*******
62 ******************************/
63
64/*Luckily we can use GMP's mpz_import() and mpz_export() functions to convert from/to
65 *BigInteger.toByteArray() representation.
66 */
67
68/******** convert_j2mp() */
69/*
70 * Initializes the GMP value with enough preallocated size, and converts the
71 * Java value into the GMP value. The value that mvalue points to should be
72 * uninitialized
73 */
74
75void convert_j2mp(JNIEnv* env, jbyteArray jvalue, mpz_t* mvalue)
76{
77        jsize size;
78        jbyte* jbuffer;
79                //int sign;
80
81        size = (*env)->GetArrayLength(env, jvalue);
82        jbuffer = (*env)->GetByteArrayElements(env, jvalue, NULL);
83
84        mpz_init2(*mvalue, sizeof(jbyte) * 8 * size); //preallocate the size
85
86        /* void mpz_import(
87         *   mpz_t rop, size_t count, int order, int size, int endian,
88         *   size_t nails, const void *op);
89         *
90         * order = 1
91         *   order can be 1 for most significant word first or -1 for least
92         *   significant first.
93         * endian = 1
94         *   Within each word endian can be 1 for most significant byte first,
95         *   -1 for least significant first.
96         * nails = 0
97         *   The most significant nails bits of each word are skipped, this can
98         *   be 0 to use the full words.
99         */
100        mpz_import(*mvalue, size, 1, sizeof(jbyte), 1, 0, (void*)jbuffer);
101                /*Uncomment this to support negative integer values,
102                not tested though..
103                sign = jbuffer[0] < 0?-1:1;
104                if(sign == -1)
105                        mpz_neg(*mvalue,*mvalue);
106                */
107        (*env)->ReleaseByteArrayElements(env, jvalue, jbuffer, JNI_ABORT);
108}
109
110/******** convert_mp2j() */
111/*
112 * Converts the GMP value into the Java value; Doesn't do anything else.
113 * Pads the resulting jbyte array with 0, so the twos complement value is always
114 * positive.
115 */
116
117void convert_mp2j(JNIEnv* env, mpz_t mvalue, jbyteArray* jvalue)
118{
119        // size_t not jsize to work with 64bit CPUs (do we need to update this
120        // elsewhere, and/or adjust memory alloc sizes?)
121        size_t size; 
122        jbyte* buffer;
123        jboolean copy;
124                //int i;
125
126        copy = JNI_FALSE;
127
128        /* sizeinbase() + 7 => Ceil division */
129        size = (mpz_sizeinbase(mvalue, 2) + 7) / 8 + sizeof(jbyte);
130        *jvalue = (*env)->NewByteArray(env, size);
131
132        buffer = (*env)->GetByteArrayElements(env, *jvalue, &copy);
133        buffer[0] = 0x00;
134                //Uncomment the comments below to support negative integer values,
135                //not very well-tested though..
136                //if(mpz_sgn(mvalue) >=0){
137                mpz_export((void*)&buffer[1], &size, 1, sizeof(jbyte), 1, 0, mvalue);
138                //}else{
139                //      mpz_add_ui(mvalue,mvalue,1);
140                //      mpz_export((void*)&buffer[1], &size, 1, sizeof(jbyte), 1, 0, mvalue);
141                //      for(i =0;i<=size;i++){ //This could be done more effectively
142                //              buffer[i]=~buffer[i];
143                //      }
144                //}
145
146                /* mode has (supposedly) no effect if elems is not a copy of the
147         * elements in array
148         */
149        (*env)->ReleaseByteArrayElements(env, *jvalue, buffer, 0);
150        //mode has (supposedly) no effect if elems is not a copy of the elements in array
151}
152
153/******** eof */
Note: See TracBrowser for help on using the repository browser.