ope-rb 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,6 @@
1
+ require 'mkmf'
2
+
3
+ dir_config('openssl')
4
+ have_header("openssl/ssl.h")
5
+ have_library("ssl", "SSLv23_method")
6
+ create_makefile('ope/native')
@@ -0,0 +1,311 @@
1
+ #include <ruby.h>
2
+ #include <math.h>
3
+ #include <openssl/rand.h>
4
+
5
+ /*
6
+ * Helper methods from Mathlib : A C Library of Special Functions
7
+ * Copyright (C) 2005 The R Foundation, released under the GPL.
8
+ */
9
+ static double afc(int i)
10
+ {
11
+ static const double al[9] =
12
+ {
13
+ 0.0,
14
+ 0.0,/*ln(0!)=ln(1)*/
15
+ 0.0,/*ln(1!)=ln(1)*/
16
+ 0.69314718055994530941723212145817,/*ln(2) */
17
+ 1.79175946922805500081247735838070,/*ln(6) */
18
+ 3.17805383034794561964694160129705,/*ln(24)*/
19
+ 4.78749174278204599424770093452324,
20
+ 6.57925121201010099506017829290394,
21
+ 8.52516136106541430016553103634712
22
+ /*, 10.60460290274525022841722740072165*/
23
+ };
24
+ double di, value;
25
+
26
+ if (i < 0) {
27
+ printf(("rhyper.c: afc(i), i=%d < 0 -- SHOULD NOT HAPPEN!\n"),
28
+ i);
29
+ return -1;/* unreached (Wall) */
30
+ } else if (i <= 7) {
31
+ value = al[i + 1];
32
+ } else {
33
+ di = i;
34
+ value = (di + 0.5) * log(di) - di + 0.08333333333333 / di
35
+ - 0.00277777777777 / di / di / di + 0.9189385332;
36
+ }
37
+ return value;
38
+ }
39
+
40
+ static int imax2(int x, int y) {
41
+ return (x < y) ? y : x;
42
+ }
43
+
44
+ static int imin2(int x, int y) {
45
+ return (x < y) ? x : y;
46
+ }
47
+
48
+ static VALUE ope_rb;
49
+ static VALUE ope_rb_hgd;
50
+
51
+ static VALUE ope_rb_rhyper(VALUE self, VALUE rbNn1in, VALUE rbNn2in, VALUE rbKkin, VALUE rbSeed) {
52
+
53
+ double nn1in, nn2in, kkin;
54
+
55
+ static const double con = 57.56462733;
56
+ static const double deltal = 0.0078;
57
+ static const double deltau = 0.0034;
58
+ static const double scale = 1e25;
59
+
60
+ int nn1, nn2, kk;
61
+ int i, ix;
62
+ int reject, setup1, setup2;
63
+
64
+ double e, f, g, p, r, t, u, v, y;
65
+ double de, dg, dr, ds, dt, gl, gu, nk, nm, ub;
66
+ double xk, xm, xn, y1, ym, yn, yk, alv;
67
+
68
+ static int ks = -1;
69
+ static int n1s = -1, n2s = -1;
70
+
71
+ static int k, m;
72
+ static int minjx, maxjx, n1, n2;
73
+
74
+ static double a, d, s, w;
75
+ static double tn, xl, xr, kl, kr, lamdl, lamdr, p1, p2, p3;
76
+
77
+ unsigned char* seed;
78
+ int seedLen;
79
+
80
+ nn1in = NUM2DBL(rbNn1in);
81
+ nn2in = NUM2DBL(rbNn2in);
82
+ kkin = NUM2DBL(rbKkin);
83
+
84
+ StringValue(rbSeed);
85
+ seed = (unsigned char*) RSTRING_PTR(rbSeed);
86
+ seedLen = RSTRING_LEN(rbSeed);
87
+ RAND_seed(seed, seedLen);
88
+
89
+ if(!isfinite(nn1in) || !isfinite(nn2in) || !isfinite(kkin))
90
+ return -1;
91
+
92
+ nn1 = (int) nn1in;
93
+ nn2 = (int) nn2in;
94
+ kk = (int) kkin;
95
+
96
+ if (nn1 < 0 || nn2 < 0 || kk < 0 || kk > nn1 + nn2) {
97
+ //rb_raise(rb_eRuntimeError, 'Incorrect arguments to HGD');
98
+ return INT2NUM(-2);
99
+ }
100
+
101
+ reject = 1;
102
+ if (nn1 != n1s || nn2 != n2s) {
103
+ setup1 = 1; setup2 = 1;
104
+ } else if (kk != ks) {
105
+ setup1 = 0; setup2 = 1;
106
+ } else {
107
+ setup1 = 0; setup2 = 0;
108
+ }
109
+ if (setup1) {
110
+ n1s = nn1;
111
+ n2s = nn2;
112
+ tn = nn1 + nn2;
113
+ if (nn1 <= nn2) {
114
+ n1 = nn1;
115
+ n2 = nn2;
116
+ } else {
117
+ n1 = nn2;
118
+ n2 = nn1;
119
+ }
120
+ }
121
+ if (setup2) {
122
+ ks = kk;
123
+ if (kk + kk >= tn) {
124
+ k = (int)(tn - kk);
125
+ } else {
126
+ k = kk;
127
+ }
128
+ }
129
+ if (setup1 || setup2) {
130
+ m = (int) ((k + 1.0) * (n1 + 1.0) / (tn + 2.0));
131
+ minjx = imax2(0, k - n2);
132
+ maxjx = imin2(n1, k);
133
+ }
134
+
135
+ if (minjx == maxjx) {
136
+ ix = maxjx;
137
+
138
+ if (kk + kk >= tn) {
139
+ if (nn1 > nn2) {
140
+ ix = kk - nn2 + ix;
141
+ } else {
142
+ ix = nn1 - ix;
143
+ }
144
+ } else {
145
+ if (nn1 > nn2)
146
+ ix = kk - ix;
147
+ }
148
+
149
+ return DBL2NUM(ix);
150
+
151
+ } else if (m - minjx < 10) {
152
+ if (setup1 || setup2) {
153
+ if (k < n2) {
154
+ w = exp(con + afc(n2) + afc(n1 + n2 - k)
155
+ - afc(n2 - k) - afc(n1 + n2));
156
+ } else {
157
+ w = exp(con + afc(n1) + afc(k)
158
+ - afc(k - n2) - afc(n1 + n2));
159
+ }
160
+ }
161
+ L10:
162
+ p = w;
163
+ ix = minjx;
164
+ u = unif_rand(seed, seedLen) * scale;
165
+ L20:
166
+ if (u > p) {
167
+ u -= p;
168
+ p *= (n1 - ix) * (k - ix);
169
+ ix++;
170
+ p = p / ix / (n2 - k + ix);
171
+ if (ix > maxjx)
172
+ goto L10;
173
+ goto L20;
174
+ }
175
+ } else {
176
+
177
+ if (setup1 || setup2) {
178
+ s = sqrt((tn - k) * k * n1 * n2 / (tn - 1) / tn / tn);
179
+
180
+ d = (int) (1.5 * s) + .5;
181
+ xl = m - d + .5;
182
+ xr = m + d + .5;
183
+ a = afc(m) + afc(n1 - m) + afc(k - m) + afc(n2 - k + m);
184
+ kl = exp(a - afc((int) (xl)) - afc((int) (n1 - xl))
185
+ - afc((int) (k - xl))
186
+ - afc((int) (n2 - k + xl)));
187
+ kr = exp(a - afc((int) (xr - 1))
188
+ - afc((int) (n1 - xr + 1))
189
+ - afc((int) (k - xr + 1))
190
+ - afc((int) (n2 - k + xr - 1)));
191
+ lamdl = -log(xl * (n2 - k + xl) / (n1 - xl + 1) / (k - xl + 1));
192
+ lamdr = -log((n1 - xr + 1) * (k - xr + 1) / xr / (n2 - k + xr));
193
+ p1 = d + d;
194
+ p2 = p1 + kl / lamdl;
195
+ p3 = p2 + kr / lamdr;
196
+ }
197
+ L30:
198
+ u = unif_rand(seed, seedLen) * p3;
199
+ v = unif_rand(seed, seedLen);
200
+ if (u < p1) {
201
+ ix = (int) (xl + u);
202
+ } else if (u <= p2) {
203
+ ix = (int) (xl + log(v) / lamdl);
204
+ if (ix < minjx)
205
+ goto L30;
206
+ v = v * (u - p1) * lamdl;
207
+ } else {
208
+ ix = (int) (xr - log(v) / lamdr);
209
+ if (ix > maxjx)
210
+ goto L30;
211
+ v = v * (u - p2) * lamdr;
212
+ }
213
+
214
+ if (m < 100 || ix <= 50) {
215
+ f = 1.0;
216
+ if (m < ix) {
217
+ for (i = m + 1; i <= ix; i++)
218
+ f = f * (n1 - i + 1) * (k - i + 1) / (n2 - k + i) / i;
219
+ } else if (m > ix) {
220
+ for (i = ix + 1; i <= m; i++)
221
+ f = f * i * (n2 - k + i) / (n1 - i + 1) / (k - i + 1);
222
+ }
223
+ if (v <= f) {
224
+ reject = 0;
225
+ }
226
+ } else {
227
+ /* squeeze using upper and lower bounds */
228
+ y = ix;
229
+ y1 = y + 1.0;
230
+ ym = y - m;
231
+ yn = n1 - y + 1.0;
232
+ yk = k - y + 1.0;
233
+ nk = n2 - k + y1;
234
+ r = -ym / y1;
235
+ s = ym / yn;
236
+ t = ym / yk;
237
+ e = -ym / nk;
238
+ g = yn * yk / (y1 * nk) - 1.0;
239
+ dg = 1.0;
240
+ if (g < 0.0)
241
+ dg = 1.0 + g;
242
+ gu = g * (1.0 + g * (-0.5 + g / 3.0));
243
+ gl = gu - .25 * (g * g * g * g) / dg;
244
+ xm = m + 0.5;
245
+ xn = n1 - m + 0.5;
246
+ xk = k - m + 0.5;
247
+ nm = n2 - k + xm;
248
+ ub = y * gu - m * gl + deltau
249
+ + xm * r * (1. + r * (-0.5 + r / 3.0))
250
+ + xn * s * (1. + s * (-0.5 + s / 3.0))
251
+ + xk * t * (1. + t * (-0.5 + t / 3.0))
252
+ + nm * e * (1. + e * (-0.5 + e / 3.0));
253
+ alv = log(v);
254
+ if (alv > ub) {
255
+ reject = 1;
256
+ } else {
257
+ dr = xm * (r * r * r * r);
258
+ if (r < 0.0)
259
+ dr /= (1.0 + r);
260
+ ds = xn * (s * s * s * s);
261
+ if (s < 0.0)
262
+ ds /= (1.0 + s);
263
+ dt = xk * (t * t * t * t);
264
+ if (t < 0.0)
265
+ dt /= (1.0 + t);
266
+ de = nm * (e * e * e * e);
267
+ if (e < 0.0)
268
+ de /= (1.0 + e);
269
+ if (alv < ub - 0.25 * (dr + ds + dt + de)
270
+ + (y + m) * (gl - gu) - deltal) {
271
+ reject = 0;
272
+ }
273
+ else {
274
+ if (alv <= (a - afc(ix) - afc(n1 - ix)
275
+ - afc(k - ix) - afc(n2 - k + ix))) {
276
+ reject = 0;
277
+ } else {
278
+ reject = 1;
279
+ }
280
+ }
281
+ }
282
+ }
283
+ if (reject)
284
+ goto L30;
285
+ }
286
+
287
+ if (kk + kk >= tn) {
288
+ if (nn1 > nn2) {
289
+ ix = kk - nn2 + ix;
290
+ } else {
291
+ ix = nn1 - ix;
292
+ }
293
+ } else {
294
+ if (nn1 > nn2)
295
+ ix = kk - ix;
296
+ }
297
+
298
+ return DBL2NUM(ix);
299
+
300
+ }
301
+
302
+ void Init_native(void) {
303
+
304
+ ope_rb = rb_define_module("OPE");
305
+
306
+ ope_rb_hgd = rb_define_class_under(ope_rb, "HGD", rb_cObject);
307
+ rb_define_singleton_method(ope_rb_hgd, "rhyper_native", ope_rb_rhyper, 4);
308
+
309
+ return;
310
+
311
+ }
@@ -0,0 +1,155 @@
1
+ require 'ope-rb/native'
2
+ require 'ope-rb/version'
3
+ require 'ope-rb/prng'
4
+ require 'ope-rb/hgd'
5
+ require 'ope-rb/crypto'
6
+ require 'ope-rb/errors'
7
+
8
+ module OPE
9
+
10
+ class Cipher
11
+
12
+ OPE_KEY_SIZE = 128
13
+
14
+ include Crypto
15
+
16
+ def initialize(key, pt_len = 8, ct_len = 16)
17
+
18
+ check_key_size(key)
19
+
20
+ @key, @pt_len, @ct_len =
21
+ key, pt_len * 8, ct_len * 8
22
+
23
+ create_cipher
24
+
25
+ end
26
+
27
+ def check_key_size(key)
28
+
29
+ valid = key.bytesize * 8 == OPE_KEY_SIZE
30
+ raise Errors::KeySizeError unless valid
31
+
32
+ end
33
+
34
+ def sample_hgd(lo_d, hi_d, lo_r, hi_r, y, coins)
35
+
36
+ wb, bp = hi_d - lo_d + 1, y - lo_r
37
+ bb = hi_r - lo_r + 1 - wb
38
+
39
+ unless wb > 0 && bb >= 0 && y >= lo_r && y <= hi_r
40
+ raise Errors::HGDParameterError
41
+ end
42
+
43
+ prec = (hi_r - lo_r + 1).size * 8 + 10
44
+
45
+ lo_d + HGD.rhyper(bp, wb, bb, coins, prec)
46
+
47
+ end
48
+
49
+ def tape_gen(lo_d, hi_d, y, desired_no_bits)
50
+
51
+ if desired_no_bits % 8 != 0
52
+ raise Errors::NumBitsError
53
+ elsif (desired_bytes = desired_no_bits / 8) > 16
54
+ raise Errors::DesiredBytesError
55
+ end
56
+
57
+ digest = hash_concat(lo_d, hi_d, y)
58
+ seed = get_seed(digest, desired_bytes)
59
+
60
+ end
61
+
62
+ def encrypt(m)
63
+
64
+ lo_d, hi_d = 0, (1 << @pt_len) - 1
65
+ lo_r, hi_r = 0, (1 << @ct_len) - 1
66
+
67
+ encrypt_recurse(lo_d, hi_d, lo_r, hi_r, m)
68
+
69
+ end
70
+
71
+ def decrypt(m)
72
+
73
+ lo_d, hi_d = 0, (1 << @pt_len) - 1
74
+ lo_r, hi_r = 0, (1 << @ct_len) - 1
75
+
76
+ decrypt_recurse(lo_d, hi_d, lo_r, hi_r, m)
77
+
78
+ end
79
+
80
+ private
81
+
82
+ def get_seed(digest, desired_bytes)
83
+
84
+ # Encrypt the hash using the cipher
85
+ seed = cipher_encrypt(digest)
86
+
87
+ # Take only the desired no of bytes
88
+ seed = seed.byteslice(0, desired_bytes)
89
+
90
+ # Convert the seed to a Bignum
91
+ seed.unpack('H*')[0].hex
92
+
93
+ end
94
+
95
+ def encrypt_recurse(lo_d, hi_d, lo_r, hi_r, m)
96
+
97
+ m2, n = hi_d - lo_d + 1, hi_r - lo_r + 1
98
+ d, r = lo_d - 1, lo_r - 1; y = r + (n + 1) / 2
99
+
100
+ raise Errors::IncorrectMValueError unless m2 > 0
101
+
102
+ coins = nil
103
+
104
+ if m2 == 1
105
+
106
+ coins = tape_gen(lo_d, hi_d, m, @ct_len)
107
+ return lo_r + (coins % n)
108
+
109
+ end
110
+
111
+ coins = tape_gen(lo_d, hi_d, y, @pt_len)
112
+
113
+ x = sample_hgd(lo_d, hi_d, lo_r, hi_r, y, coins)
114
+
115
+ lo_d, hi_d = *((m <= x) ? [d + 1, x] : [x + 1, d + m2])
116
+ lo_r, hi_r = *((m <= x) ? [r + 1, y] : [y + 1, r + n])
117
+
118
+ encrypt_recurse(lo_d, hi_d, lo_r, hi_r, m)
119
+
120
+ end
121
+
122
+ def decrypt_recurse(lo_d, hi_d, lo_r, hi_r, c)
123
+
124
+ m2, n = hi_d - lo_d + 1, hi_r - lo_r + 1
125
+ d, r = lo_d - 1, lo_r - 1; y = r + (n + 1) / 2
126
+
127
+ raise Errors::IncorrectMValueError unless m2 > 0
128
+
129
+ if m2 == 1
130
+
131
+ m = lo_d.to_i
132
+
133
+ coins = tape_gen(lo_d, hi_d, m, @ct_len)
134
+ w = lo_r + coins % n
135
+
136
+ return m.to_i if w == c
137
+
138
+ raise Errors::BadDecryptError
139
+
140
+ end
141
+
142
+ coins = tape_gen(lo_d, hi_d, y, @pt_len)
143
+
144
+ x = sample_hgd(lo_d, hi_d, lo_r, hi_r, y, coins)
145
+
146
+ lo_d, hi_d = *((c <= y) ? [d + 1, x] : [x + 1, d + m2])
147
+ lo_r, hi_r = *((c <= y) ? [r + 1, y] : [y + 1, r + n])
148
+
149
+ decrypt_recurse(lo_d, hi_d, lo_r, hi_r, c)
150
+
151
+ end
152
+
153
+ end
154
+
155
+ end
@@ -0,0 +1,33 @@
1
+ module OPE
2
+
3
+ module Crypto
4
+
5
+ def hash_concat(*args)
6
+
7
+ lens = args.map { |arg| [1].pack("L") }
8
+ hash((lens + args).join(''))
9
+
10
+ end
11
+
12
+ def hash(data)
13
+
14
+ OpenSSL::Digest::SHA256.digest(data)
15
+
16
+ end
17
+
18
+ def create_cipher
19
+
20
+ @cipher = OpenSSL::Cipher::AES.new(128, :ECB)
21
+ @cipher.encrypt; @cipher.key = @key
22
+
23
+ end
24
+
25
+ def cipher_encrypt(data)
26
+
27
+ @cipher.update(data) + @cipher.final
28
+
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,55 @@
1
+ module OPE
2
+
3
+ module Errors
4
+
5
+ class KeySizeError < StandardError
6
+
7
+ def initialize
8
+ super('Incorrect key size')
9
+ end
10
+
11
+ end
12
+
13
+ class HGDParameterError < StandardError
14
+
15
+ def initialize
16
+ super('Corrupt HGD parameters')
17
+ end
18
+
19
+ end
20
+
21
+ class NumBitsError < StandardError
22
+
23
+ def initialize
24
+ super('Desired no bits not a multiple of 8')
25
+ end
26
+
27
+ end
28
+
29
+ class DesiredBytesError < StandardError
30
+
31
+ def initialize
32
+ super('Only 64-bit output is supported for now')
33
+ end
34
+
35
+ end
36
+
37
+ class IncorrectMValueError < StandardError
38
+
39
+ def initialize
40
+ super('M should not be less than or equal to 0')
41
+ end
42
+
43
+ end
44
+
45
+ class BadDecryptError < StandardError
46
+
47
+ def initialize
48
+ super('Decryption failed')
49
+ end
50
+
51
+ end
52
+
53
+ end
54
+
55
+ end
@@ -0,0 +1,267 @@
1
+ module OPE
2
+
3
+ class HGD
4
+
5
+ # Random variates from the hypergeometric distribution.
6
+ #
7
+ # Returns the number of white balls drawn when kk balls
8
+ # are drawn at random from an urn containing nn1 white
9
+ # and nn2 black balls.
10
+ def self.rhyper(kk, nn1, nn2, coins, precision)
11
+
12
+ ix = nil
13
+
14
+ prng = PRNG.new(coins)
15
+
16
+ con, deltal = 57.56462733, 0.0078
17
+ deltau, scale = 0.0034, 1.0e25
18
+
19
+ # Check validity of parameters.
20
+ if [nn1, nn2, kk].include?(Float::INFINITY) ||
21
+ (nn1 < 0 || nn2 < 0 || kk < 0 || kk > (nn1 + nn2))
22
+ raise 'Invalid parameters nn1, nn2 or kk'
23
+ end
24
+
25
+ reject = true
26
+
27
+ if nn1 >= nn2
28
+ n1, n2 = nn2.to_f, nn1.to_f
29
+ else
30
+ n1, n2 = nn1.to_f, nn2.to_f
31
+ end
32
+
33
+ tn = n1 + n2
34
+
35
+ if kk + kk >= tn
36
+ k = tn - kk
37
+ else
38
+ k = kk
39
+ end
40
+
41
+ m = (k+1.0) * (n1+1.0) / (tn+2.0)
42
+
43
+ minjx = (k - n2 < 0) ? 0 : k - n2
44
+ maxjx = (n1 < k) ? n1 : k
45
+
46
+ # Degenerate distribution
47
+ if minjx == maxjx
48
+
49
+ # no, need to untangle TSL
50
+ return maxjx.floor.to_f
51
+
52
+ # Inverse transformation
53
+ elsif m-minjx < 10
54
+
55
+ w = nil
56
+
57
+ if k < n2
58
+ w = Math.exp(con + afc(n2) + afc(n1+n2-k)-afc(n2-k)-afc(n1+n2))
59
+ else
60
+ w = Math.exp(con + afc(n1) + afc(k) + afc(k-n2) -afc(n1+n2))
61
+ end
62
+
63
+ catch :l10 do
64
+
65
+ p = w
66
+ ix = minjx
67
+ u = prng.draw * scale
68
+
69
+ catch :l20 do
70
+
71
+ if u > p
72
+ u = u - p
73
+ p = p * (n1-ix)*(k-ix)
74
+ ix = ix + 1
75
+ p = p / ix / (n2-k+ix)
76
+ throw :l10 if ix > maxjx
77
+ throw :l20
78
+ end
79
+
80
+ end
81
+
82
+ end
83
+
84
+ # Hypergeometrics-2 points-exponential tails
85
+ else
86
+
87
+ s = Math.sqrt( (tn-k) * k * n1 * n2 / (tn - 1.0) / tn / tn)
88
+
89
+ # Truncation centers cell boundaries at 0.5
90
+ d = (1.5 * s).floor.to_f + 0.5
91
+ xl = m - d + 0.5
92
+ xr = m + d + 0.5
93
+ a = afc(m) + afc(n1-m) +
94
+ afc(k-m) + afc(n2-k+m)
95
+
96
+ expon = a - afc(xl) -
97
+ afc(n1 - xl) - afc(k - xl) -
98
+ afc(n2 - k + xl)
99
+
100
+ kl = Math.exp(expon)
101
+
102
+ kr = Math.exp(a - afc(xr-1) -
103
+ afc(n1-xr+1) - afc(k-xr+1) -
104
+ afc(n2-k+xr-1))
105
+
106
+ lamdl = -Math.log(xl *
107
+ (n2 - k + xl) / (n1 - xl + 1) / (k - xl + 1))
108
+
109
+ lamdr = -Math.log(
110
+ (n1 - xr + 1) * (k -xr + 1) / xr / (n2 - k + xr))
111
+
112
+ p1 = 2 * d
113
+ p2 = p1 + kl / lamdl
114
+ p3 = p2 + kr / lamdr
115
+
116
+ count_30 = 0
117
+
118
+ catch :count do
119
+
120
+ count_30 += 1
121
+
122
+ u = prng.draw * p3
123
+ v = prng.draw
124
+
125
+ # Rectangular region
126
+ if u < p1
127
+ ix = xl + u
128
+ # Left tail region
129
+ elsif u <= p2
130
+ ix = xl + Math.log(v) / lamdl
131
+ throw :count if ix < minjx
132
+ v = v * (u - p1) * lamdl
133
+ # Right tail region
134
+ else
135
+ ix = xr - Math.log(v) / lamdr
136
+ throw :count if ix > maxjx
137
+ v = v * (u - p2) * lamdr
138
+ end
139
+
140
+ f = nil
141
+
142
+ if m < 100 || ix <= 50
143
+
144
+ f = 1
145
+
146
+ if m < ix
147
+
148
+ i = m + 1
149
+
150
+ while i < ix # <= ?
151
+
152
+ f = f * (n1 - i + 1.0) *
153
+ (k - i + 1.0) /
154
+ (n2 - k + i) / i
155
+ i += 1
156
+
157
+ end
158
+
159
+ elsif m > ix
160
+
161
+ i = ix + 1
162
+
163
+ while i < m # <= ?
164
+
165
+ f = f * i * (n2 - k + i) /
166
+ (n1 - i) / (k - i) # + 1 ?
167
+ i += 1
168
+
169
+ end
170
+
171
+ end
172
+
173
+ reject = false if v <= f
174
+
175
+ else
176
+
177
+ y = ix; y1 = y + 1.0; ym = y - m
178
+ yn = n1 - y + 1.0; yk = k - y + 1.0
179
+ nk = n2 - k + y1; r = -ym / y1
180
+ s2 = ym / yn; t = ym / yk; e = -ym / nk
181
+ g = yn * yk / (y1 * nk) - 1.0
182
+ dg = 1.0; dg = 1.0 + g if g < 0
183
+ gu = g * (1.0 + g * (-0.5 + g / 3.0))
184
+ gl = gu - 0.25 * (g * g * g * g) / dg
185
+ xm = m + 0.5; xn = n1 - m + 0.5
186
+ xk = k - m + 0.5; nm = n2 - k + xm
187
+
188
+ ub = y * gu - m * gl + deltau + xm *
189
+ r * (1 + r * (-0.5 + r / 3)) +
190
+ xn * s2 * (1.0 + s2 * (-0.5 + s2 / 3.0)) +
191
+ xk * t * (1.0 + t * (-0.5 + t / 3.0)) +
192
+ nm * e * (1.0 + e * (-0.5 + e / 3.0))
193
+
194
+ alv = Math.log(v)
195
+
196
+ if alv > ub
197
+ reject = true
198
+ else
199
+
200
+ dr = xm * (r * r * r * r)
201
+ dr /= (1.0 + r) if r < 0
202
+ ds = xn * (s2 * s2 * s2 * s2)
203
+ ds /= (1.0 + s2) if s2 < 0
204
+ dt = xk * (t * t * t * t)
205
+ dt /= (1.0 + t) if t < 0
206
+ de = nm * (e * e * e * e)
207
+ de /= (1.0 + e) if e < 0
208
+
209
+
210
+ cand = ub - 0.25 * (dr + ds + dt + de) +
211
+ (y + m) * (gl - gu) - deltal
212
+
213
+ if alv < cand
214
+ reject = false
215
+ else
216
+
217
+
218
+ cand = a - afc(ix) - afc(n1 - ix) -
219
+ afc(k - ix) - afc(n2 - k + ix)
220
+
221
+ reject = alv > cand
222
+
223
+ end
224
+
225
+ end
226
+
227
+ end
228
+
229
+ throw :count if reject
230
+
231
+ end
232
+
233
+ end
234
+
235
+ if kk + kk >= tn
236
+ if nn1 > nn2
237
+ ix = kk - nn2 + ix
238
+ else
239
+ ix = nn1 - ix
240
+ end
241
+ else
242
+ ix = kk - ix if nn1 > nn2
243
+ end
244
+
245
+ jx = ix
246
+
247
+ return jx.floor.to_f
248
+
249
+ end
250
+
251
+ # Calculates logarithm of i factorial: ln(i!)
252
+ # Uses Stirling's approximation to do so.
253
+ def self.afc(i)
254
+
255
+ raise 'i should not be < 0' if i < 0
256
+
257
+ frac_12, frac_360 = 1.0 / 12.0, 1.0 / 360.0
258
+ frac_pi = 0.5 * Math.log(2 * Math::PI)
259
+
260
+ (i + 0.5) * Math.log(i) - i + frac_12 /
261
+ i - frac_360 / i / i / i + frac_pi
262
+
263
+ end
264
+
265
+ end
266
+
267
+ end
@@ -0,0 +1,21 @@
1
+ module OPE
2
+
3
+ class PRNG
4
+
5
+ require 'bigdecimal'
6
+ require 'drbg-rb'
7
+
8
+ def initialize(coin)
9
+ coin = coin.to_s
10
+ coin += '0' while coin.bytesize < 24
11
+ @prng = DRBG::HMAC.new(coin, 128)
12
+ end
13
+
14
+ def draw
15
+ n = @prng.generate(4, 128).unpack('H*')[0]
16
+ n.byteslice(0, 8).hex.to_f / 2**32
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,5 @@
1
+ module OPE
2
+
3
+ VERSION = '0.0.1'
4
+
5
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ope-rb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Louis Mullie
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-05-01 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 2.12.0
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 2.12.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: ! ' '
47
+ email:
48
+ - louis.mullie@gmail.com
49
+ executables: []
50
+ extensions:
51
+ - ext/ope/extconf.rb
52
+ extra_rdoc_files: []
53
+ files:
54
+ - lib/ope-rb/crypto.rb
55
+ - lib/ope-rb/errors.rb
56
+ - lib/ope-rb/hgd.rb
57
+ - lib/ope-rb/prng.rb
58
+ - lib/ope-rb/version.rb
59
+ - lib/ope-rb.rb
60
+ - ext/ope/native.c
61
+ - ext/ope/extconf.rb
62
+ homepage: https://github.com/cryodex/ope-rb
63
+ licenses: []
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ! '>='
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ! '>='
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ requirements: []
81
+ rubyforge_project:
82
+ rubygems_version: 1.8.25
83
+ signing_key:
84
+ specification_version: 3
85
+ summary: A Ruby implementation of order-preserving encryption
86
+ test_files: []