1 16 17 package org.apache.commons.math.random; 18 19 import java.io.Serializable ; 20 import java.security.MessageDigest ; 21 import java.security.SecureRandom ; 22 import java.security.NoSuchAlgorithmException ; 23 import java.security.NoSuchProviderException ; 24 import java.util.Collection ; 25 26 81 public class RandomDataImpl implements RandomData, Serializable { 82 83 84 static final long serialVersionUID = -626730818244969716L; 85 86 87 private RandomGenerator rand = null; 88 89 90 private SecureRandom secRand = null; 91 92 95 public RandomDataImpl() { 96 } 97 98 105 public RandomDataImpl(RandomGenerator rand) { 106 super(); 107 this.rand = rand; 108 } 109 110 120 public String nextHexString(int len) { 121 if (len <= 0) { 122 throw new IllegalArgumentException ("length must be positive"); 123 } 124 125 RandomGenerator ran = getRan(); 127 128 StringBuffer outBuffer = new StringBuffer (); 130 131 byte[] randomBytes = new byte[(len / 2) + 1]; 133 ran.nextBytes(randomBytes); 134 135 for (int i = 0; i < randomBytes.length; i++) { 137 Integer c = new Integer (randomBytes[i]); 138 139 144 String hex = Integer.toHexString(c.intValue() + 128); 145 146 if (hex.length() == 1) { 148 hex = "0" + hex; 149 } 150 outBuffer.append(hex); 151 } 152 return outBuffer.toString().substring(0, len); 153 } 154 155 163 public int nextInt(int lower, int upper) { 164 if (lower >= upper) { 165 throw new IllegalArgumentException 166 ("upper bound must be > lower bound"); 167 } 168 RandomGenerator rand = getRan(); 169 return lower + (int) (rand.nextDouble() * (upper - lower + 1)); 170 } 171 172 180 public long nextLong(long lower, long upper) { 181 if (lower >= upper) { 182 throw new IllegalArgumentException 183 ("upper bound must be > lower bound"); 184 } 185 RandomGenerator rand = getRan(); 186 return lower + (long) (rand.nextDouble() * (upper - lower + 1)); 187 } 188 189 203 public String nextSecureHexString(int len) { 204 if (len <= 0) { 205 throw new IllegalArgumentException ("length must be positive"); 206 } 207 208 SecureRandom secRan = getSecRan(); 210 MessageDigest alg = null; 211 try { 212 alg = MessageDigest.getInstance("SHA-1"); 213 } catch (NoSuchAlgorithmException ex) { 214 return null; } 216 alg.reset(); 217 218 int numIter = (len / 40) + 1; 220 221 StringBuffer outBuffer = new StringBuffer (); 222 for (int iter = 1; iter < numIter + 1; iter++) { 223 byte[] randomBytes = new byte[40]; 224 secRan.nextBytes(randomBytes); 225 alg.update(randomBytes); 226 227 byte hash[] = alg.digest(); 229 230 for (int i = 0; i < hash.length; i++) { 232 Integer c = new Integer (hash[i]); 233 234 239 String hex = Integer.toHexString(c.intValue() + 128); 240 241 if (hex.length() == 1) { 243 hex = "0" + hex; 244 } 245 outBuffer.append(hex); 246 } 247 } 248 return outBuffer.toString().substring(0, len); 249 } 250 251 260 public int nextSecureInt(int lower, int upper) { 261 if (lower >= upper) { 262 throw new IllegalArgumentException 263 ("lower bound must be < upper bound"); 264 } 265 SecureRandom sec = getSecRan(); 266 return lower + (int) (sec.nextDouble() * (upper - lower + 1)); 267 } 268 269 278 public long nextSecureLong(long lower, long upper) { 279 if (lower >= upper) { 280 throw new IllegalArgumentException 281 ("lower bound must be < upper bound"); 282 } 283 SecureRandom sec = getSecRan(); 284 return lower + (long) (sec.nextDouble() * (upper - lower + 1)); 285 } 286 287 303 public long nextPoisson(double mean) { 304 if (mean <= 0) { 305 throw new IllegalArgumentException ("Poisson mean must be > 0"); 306 } 307 double p = Math.exp(-mean); 308 long n = 0; 309 double r = 1.0d; 310 double rnd = 1.0d; 311 RandomGenerator rand = getRan(); 312 while (n < 1000 * mean) { 313 rnd = rand.nextDouble(); 314 r = r * rnd; 315 if (r >= p) { 316 n++; 317 } else { 318 return n; 319 } 320 } 321 return n; 322 } 323 324 333 public double nextGaussian(double mu, double sigma) { 334 if (sigma <= 0) { 335 throw new IllegalArgumentException ("Gaussian std dev must be > 0"); 336 } 337 RandomGenerator rand = getRan(); 338 return sigma * rand.nextGaussian() + mu; 339 } 340 341 353 public double nextExponential(double mean) { 354 if (mean < 0.0) { 355 throw new IllegalArgumentException 356 ("Exponential mean must be >= 0"); 357 } 358 RandomGenerator rand = getRan(); 359 double unif = rand.nextDouble(); 360 while (unif == 0.0d) { 361 unif = rand.nextDouble(); 362 } 363 return -mean * Math.log(unif); 364 } 365 366 377 public double nextUniform(double lower, double upper) { 378 if (lower >= upper) { 379 throw new IllegalArgumentException 380 ("lower bound must be <= upper bound"); 381 } 382 RandomGenerator rand = getRan(); 383 384 double u = rand.nextDouble(); 386 while(u <= 0.0){ 387 u = rand.nextDouble(); 388 } 389 390 return lower + u * (upper - lower); 391 } 392 393 402 private RandomGenerator getRan() { 403 if (rand == null) { 404 rand = new JDKRandomGenerator(); 405 rand.setSeed(System.currentTimeMillis()); 406 } 407 return rand; 408 } 409 410 417 private SecureRandom getSecRan() { 418 if (secRand == null) { 419 secRand = new SecureRandom (); 420 secRand.setSeed(System.currentTimeMillis()); 421 } 422 return secRand; 423 } 424 425 432 public void reSeed(long seed) { 433 if (rand == null) { 434 rand = new JDKRandomGenerator(); 435 } 436 rand.setSeed(seed); 437 } 438 439 445 public void reSeedSecure() { 446 if (secRand == null) { 447 secRand = new SecureRandom (); 448 } 449 secRand.setSeed(System.currentTimeMillis()); 450 } 451 452 459 public void reSeedSecure(long seed) { 460 if (secRand == null) { 461 secRand = new SecureRandom (); 462 } 463 secRand.setSeed(seed); 464 } 465 466 470 public void reSeed() { 471 if (rand == null) { 472 rand = new JDKRandomGenerator(); 473 } 474 rand.setSeed(System.currentTimeMillis()); 475 } 476 477 494 public void setSecureAlgorithm(String algorithm, String provider) 495 throws NoSuchAlgorithmException , NoSuchProviderException { 496 secRand = SecureRandom.getInstance(algorithm, provider); 497 } 498 499 508 public int[] nextPermutation(int n, int k) { 509 if (k > n) { 510 throw new IllegalArgumentException 511 ("permutation k exceeds n"); 512 } 513 if (k == 0) { 514 throw new IllegalArgumentException 515 ("permutation k must be > 0"); 516 } 517 518 int[] index = getNatural(n); 519 shuffle(index, n - k); 520 int[] result = new int[k]; 521 for (int i = 0; i < k; i++) { 522 result[i] = index[n - i - 1]; 523 } 524 525 return result; 526 } 527 528 541 public Object [] nextSample(Collection c, int k) { 542 int len = c.size(); 543 if (k > len) { 544 throw new IllegalArgumentException 545 ("sample size exceeds collection size"); 546 } 547 if (k == 0) { 548 throw new IllegalArgumentException 549 ("sample size must be > 0"); 550 } 551 552 Object [] objects = c.toArray(); 553 int[] index = nextPermutation(len, k); 554 Object [] result = new Object [k]; 555 for (int i = 0; i < k; i++) { 556 result[i] = objects[index[i]]; 557 } 558 return result; 559 } 560 561 563 570 private void shuffle(int[] list, int end) { 571 int target = 0; 572 for (int i = list.length - 1 ; i >= end; i--) { 573 if (i == 0) { 574 target = 0; 575 } else { 576 target = nextInt(0, i); 577 } 578 int temp = list[target]; 579 list[target] = list[i]; 580 list[i] = temp; 581 } 582 } 583 584 590 private int[] getNatural(int n) { 591 int[] natural = new int[n]; 592 for (int i = 0; i < n; i++) { 593 natural[i] = i; 594 } 595 return natural; 596 } 597 } 598 | Popular Tags |