From: bdemsky Date: Wed, 12 Dec 2007 00:18:46 +0000 (+0000) Subject: add Random class X-Git-Tag: preEdgeChange~339 X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=37f7b5175feb57747887d525911d61b77737027e;p=IRC.git add Random class add various language features to make Random class compiler add currentTimeMillis method --- diff --git a/Robust/src/ClassLibrary/System.java b/Robust/src/ClassLibrary/System.java index d1352339..2595e546 100644 --- a/Robust/src/ClassLibrary/System.java +++ b/Robust/src/ClassLibrary/System.java @@ -4,6 +4,8 @@ public class System { printString(s); } + public static native long currentTimeMillis(); + public static native void printString(String s); public static void error() { diff --git a/Robust/src/ClassLibrary/gnu/Random.java b/Robust/src/ClassLibrary/gnu/Random.java new file mode 100644 index 00000000..083da05d --- /dev/null +++ b/Robust/src/ClassLibrary/gnu/Random.java @@ -0,0 +1,421 @@ +/* Random.java -- a pseudo-random number generator + Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +/** + * This class generates pseudorandom numbers. It uses the same + * algorithm as the original JDK-class, so that your programs behave + * exactly the same way, if started with the same seed. + * + * The algorithm is described in The Art of Computer Programming, + * Volume 2 by Donald Knuth in Section 3.2.1. It is a 48-bit seed, + * linear congruential formula. + * + * If two instances of this class are created with the same seed and + * the same calls to these classes are made, they behave exactly the + * same way. This should be even true for foreign implementations + * (like this), so every port must use the same algorithm as described + * here. + * + * If you want to implement your own pseudorandom algorithm, you + * should extend this class and overload the next() and + * setSeed(long) method. In that case the above + * paragraph doesn't apply to you. + * + * This class shouldn't be used for security sensitive purposes (like + * generating passwords or encryption keys. See SecureRandom + * in package java.security for this purpose. + * + * For simple random doubles between 0.0 and 1.0, you may consider using + * Math.random instead. + * + * @see java.security.SecureRandom + * @see Math#random() + * @author Jochen Hoenicke + * @author Eric Blake (ebb9@email.byu.edu) + * @status updated to 1.4 + */ +public class Random +{ + /** + * True if the next nextGaussian is available. This is used by + * nextGaussian, which generates two gaussian numbers by one call, + * and returns the second on the second call. + * + * @serial whether nextNextGaussian is available + * @see #nextGaussian() + * @see #nextNextGaussian + */ + private boolean haveNextNextGaussian; + + /** + * The next nextGaussian, when available. This is used by nextGaussian, + * which generates two gaussian numbers by one call, and returns the + * second on the second call. + * + * @serial the second gaussian of a pair + * @see #nextGaussian() + * @see #haveNextNextGaussian + */ + private double nextNextGaussian; + + /** + * The seed. This is the number set by setSeed and which is used + * in next. + * + * @serial the internal state of this generator + * @see #next(int) + */ + private long seed; + + + /** + * Creates a new pseudorandom number generator. The seed is initialized + * to the current time, as if by + * setSeed(System.currentTimeMillis());. + * + * @see System#currentTimeMillis() + */ + public Random() + { + setSeed(System.currentTimeMillis()); + } + + /** + * Creates a new pseudorandom number generator, starting with the + * specified seed, using setSeed(seed);. + * + * @param seed the initial seed + */ + public Random(long seed) + { + setSeed(seed); + } + + /** + * Sets the seed for this pseudorandom number generator. As described + * above, two instances of the same random class, starting with the + * same seed, should produce the same results, if the same methods + * are called. The implementation for java.util.Random is: + * +
public synchronized void setSeed(long seed)
+{
+  this.seed = (seed ^ 0x5DEECE66DL) & ((1L << 48) - 1);
+  haveNextNextGaussian = false;
+}
+ * + * @param seed the new seed + */ + public synchronized void setSeed(long seed) + { + this.seed = (seed ^ 0x5DEECE66DL) & ((1L << 48) - 1); + haveNextNextGaussian = false; + } + + /** + * Generates the next pseudorandom number. This returns + * an int value whose bits low order bits are + * independent chosen random bits (0 and 1 are equally likely). + * The implementation for java.util.Random is: + * +
protected synchronized int next(int bits)
+{
+  seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
+  return (int) (seed >>> (48 - bits));
+}
+ * + * @param bits the number of random bits to generate, in the range 1..32 + * @return the next pseudorandom value + * @since 1.1 + */ + protected synchronized int next(int bits) + { + seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1); + return (int) (seed >>> (48 - bits)); + } + + /** + * Fills an array of bytes with random numbers. All possible values + * are (approximately) equally likely. + * The JDK documentation gives no implementation, but it seems to be: + * +
public void nextBytes(byte[] bytes)
+{
+  for (int i = 0; i < bytes.length; i += 4)
+  {
+    int random = next(32);
+    for (int j = 0; i + j < bytes.length && j < 4; j++)
+    {
+      bytes[i+j] = (byte) (random & 0xff)
+      random >>= 8;
+    }
+  }
+}
+ * + * @param bytes the byte array that should be filled + * @throws NullPointerException if bytes is null + * @since 1.1 + */ + public void nextBytes(byte[] bytes) + { + int random; + // Do a little bit unrolling of the above algorithm. + int max = bytes.length & ~0x3; + for (int i = 0; i < max; i += 4) + { + random = next(32); + bytes[i] = (byte) random; + bytes[i + 1] = (byte) (random >> 8); + bytes[i + 2] = (byte) (random >> 16); + bytes[i + 3] = (byte) (random >> 24); + } + if (max < bytes.length) + { + random = next(32); + for (int j = max; j < bytes.length; j++) + { + bytes[j] = (byte) random; + random >>= 8; + } + } + } + + /** + * Generates the next pseudorandom number. This returns + * an int value whose 32 bits are independent chosen random bits + * (0 and 1 are equally likely). The implementation for + * java.util.Random is: + * +
public int nextInt()
+{
+  return next(32);
+}
+ * + * @return the next pseudorandom value + */ + public int nextInt() + { + return next(32); + } + + /** + * Generates the next pseudorandom number. This returns + * a value between 0(inclusive) and n(exclusive), and + * each value has the same likelihodd (1/n). + * (0 and 1 are equally likely). The implementation for + * java.util.Random is: + * +
+public int nextInt(int n)
+{
+  if (n <= 0)
+    throw new IllegalArgumentException("n must be positive");
+
+  if ((n & -n) == n)  // i.e., n is a power of 2
+    return (int)((n * (long) next(31)) >> 31);
+
+  int bits, val;
+  do
+  {
+    bits = next(31);
+    val = bits % n;
+  }
+  while(bits - val + (n-1) < 0);
+
+  return val;
+}
+ * + *

This algorithm would return every value with exactly the same + * probability, if the next()-method would be a perfect random number + * generator. + * + * The loop at the bottom only accepts a value, if the random + * number was between 0 and the highest number less then 1<<31, + * which is divisible by n. The probability for this is high for small + * n, and the worst case is 1/2 (for n=(1<<30)+1). + * + * The special treatment for n = power of 2, selects the high bits of + * the random number (the loop at the bottom would select the low order + * bits). This is done, because the low order bits of linear congruential + * number generators (like the one used in this class) are known to be + * ``less random'' than the high order bits. + * + * @param n the upper bound + * @throws IllegalArgumentException if the given upper bound is negative + * @return the next pseudorandom value + * @since 1.2 + */ + public int nextInt(int n) + { + if (n <= 0) + System.printString("ERROR: n must be positive\n"); + if ((n & -n) == n) // i.e., n is a power of 2 + return (int) ((n * (long) next(31)) >> 31); + int bits, val; + do + { + bits = next(31); + val = bits % n; + } + while (bits - val + (n - 1) < 0); + return val; + } + + /** + * Generates the next pseudorandom long number. All bits of this + * long are independently chosen and 0 and 1 have equal likelihood. + * The implementation for java.util.Random is: + * +

public long nextLong()
+{
+  return ((long) next(32) << 32) + next(32);
+}
+ * + * @return the next pseudorandom value + */ + public long nextLong() + { + return ((long) next(32) << 32) + next(32); + } + + /** + * Generates the next pseudorandom boolean. True and false have + * the same probability. The implementation is: + * +
public boolean nextBoolean()
+{
+  return next(1) != 0;
+}
+ * + * @return the next pseudorandom boolean + * @since 1.2 + */ + public boolean nextBoolean() + { + return next(1) != 0; + } + + /** + * Generates the next pseudorandom float uniformly distributed + * between 0.0f (inclusive) and 1.0f (exclusive). The + * implementation is as follows. + * +
public float nextFloat()
+{
+  return next(24) / ((float)(1 << 24));
+}
+ * + * @return the next pseudorandom float + */ + public float nextFloat() + { + return next(24) / (float) (1 << 24); + } + + /** + * Generates the next pseudorandom double uniformly distributed + * between 0.0 (inclusive) and 1.0 (exclusive). The + * implementation is as follows. + * +
public double nextDouble()
+{
+  return (((long) next(26) << 27) + next(27)) / (double)(1L << 53);
+}
+ * + * @return the next pseudorandom double + */ + public double nextDouble() + { + return (((long) next(26) << 27) + next(27)) / (double) (1L << 53); + } + + /** + * Generates the next pseudorandom, Gaussian (normally) distributed + * double value, with mean 0.0 and standard deviation 1.0. + * The algorithm is as follows. + * +
public synchronized double nextGaussian()
+{
+  if (haveNextNextGaussian)
+  {
+    haveNextNextGaussian = false;
+    return nextNextGaussian;
+  }
+  else
+  {
+    double v1, v2, s;
+    do
+    {
+      v1 = 2 * nextDouble() - 1; // between -1.0 and 1.0
+      v2 = 2 * nextDouble() - 1; // between -1.0 and 1.0
+      s = v1 * v1 + v2 * v2;
+    }
+    while (s >= 1);
+
+    double norm = Math.sqrt(-2 * Math.log(s) / s);
+    nextNextGaussian = v2 * norm;
+    haveNextNextGaussian = true;
+    return v1 * norm;
+  }
+}
+ * + *

This is described in section 3.4.1 of The Art of Computer + * Programming, Volume 2 by Donald Knuth. + * + * @return the next pseudorandom Gaussian distributed double + */ + public synchronized double nextGaussian() + { + if (haveNextNextGaussian) + { + haveNextNextGaussian = false; + return nextNextGaussian; + } + double v1, v2, s; + do + { + v1 = 2 * nextDouble() - 1; // Between -1.0 and 1.0. + v2 = 2 * nextDouble() - 1; // Between -1.0 and 1.0. + s = v1 * v1 + v2 * v2; + } + while (s >= 1); + double norm = Math.sqrt(-2 * Math.log(s) / s); + nextNextGaussian = v2 * norm; + haveNextNextGaussian = true; + return v1 * norm; + } +} diff --git a/Robust/src/IR/AssignOperation.java b/Robust/src/IR/AssignOperation.java index 3e750b9f..121c4d41 100644 --- a/Robust/src/IR/AssignOperation.java +++ b/Robust/src/IR/AssignOperation.java @@ -47,6 +47,8 @@ public class AssignOperation { return new Operation(Operation.LEFTSHIFT); case RSHIFTEQ: return new Operation(Operation.RIGHTSHIFT); + case URSHIFTEQ: + return new Operation(Operation.URIGHTSHIFT); case ANDEQ: return new Operation(Operation.BIT_AND); case XOREQ: @@ -76,6 +78,8 @@ public class AssignOperation { return MINUSEQ; else if (st.equals("lshifteq")) return LSHIFTEQ; + else if (st.equals("urshifteq")) + return URSHIFTEQ; else if (st.equals("rshifteq")) return RSHIFTEQ; else if (st.equals("andeq")) @@ -108,6 +112,8 @@ public class AssignOperation { return "<="; else if (operation==RSHIFTEQ) return ">="; + else if (operation==RSHIFTEQ) + return ">>="; else if (operation==ANDEQ) return "&="; else if (operation==XOREQ) diff --git a/Robust/src/IR/Flat/BuildCode.java b/Robust/src/IR/Flat/BuildCode.java index 9b3e2149..bde78891 100644 --- a/Robust/src/IR/Flat/BuildCode.java +++ b/Robust/src/IR/Flat/BuildCode.java @@ -2114,9 +2114,16 @@ public class BuildCode { } private void generateFlatOpNode(FlatMethod fm, LocalityBinding lb, FlatOpNode fon, PrintWriter output) { - if (fon.getRight()!=null) - output.println(generateTemp(fm, fon.getDest(),lb)+" = "+generateTemp(fm, fon.getLeft(),lb)+fon.getOp().toString()+generateTemp(fm,fon.getRight(),lb)+";"); - else if (fon.getOp().getOp()==Operation.ASSIGN) + if (fon.getRight()!=null) { + if (fon.getOp().getOp()==Operation.URIGHTSHIFT) { + if (fon.getLeft().getType().isLong()) + output.println(generateTemp(fm, fon.getDest(),lb)+" = ((unsigned long long)"+generateTemp(fm, fon.getLeft(),lb)+")>>"+generateTemp(fm,fon.getRight(),lb)+";"); + else + output.println(generateTemp(fm, fon.getDest(),lb)+" = ((unsigned int)"+generateTemp(fm, fon.getLeft(),lb)+")>>"+generateTemp(fm,fon.getRight(),lb)+";"); + + } else + output.println(generateTemp(fm, fon.getDest(),lb)+" = "+generateTemp(fm, fon.getLeft(),lb)+fon.getOp().toString()+generateTemp(fm,fon.getRight(),lb)+";"); + } else if (fon.getOp().getOp()==Operation.ASSIGN) output.println(generateTemp(fm, fon.getDest(),lb)+" = "+generateTemp(fm, fon.getLeft(),lb)+";"); else if (fon.getOp().getOp()==Operation.UNARYPLUS) output.println(generateTemp(fm, fon.getDest(),lb)+" = "+generateTemp(fm, fon.getLeft(),lb)+";"); @@ -2124,6 +2131,8 @@ public class BuildCode { output.println(generateTemp(fm, fon.getDest(),lb)+" = -"+generateTemp(fm, fon.getLeft(),lb)+";"); else if (fon.getOp().getOp()==Operation.LOGIC_NOT) output.println(generateTemp(fm, fon.getDest(),lb)+" = !"+generateTemp(fm, fon.getLeft(),lb)+";"); + else if (fon.getOp().getOp()==Operation.COMP) + output.println(generateTemp(fm, fon.getDest(),lb)+" = ~"+generateTemp(fm, fon.getLeft(),lb)+";"); else if (fon.getOp().getOp()==Operation.ISAVAILABLE) { output.println(generateTemp(fm, fon.getDest(),lb)+" = "+generateTemp(fm, fon.getLeft(),lb)+"->fses==NULL;"); } else @@ -2157,6 +2166,8 @@ public class BuildCode { } else if (fln.getType().isChar()) { String st=FlatLiteralNode.escapeString(fln.getValue().toString()); output.println(generateTemp(fm, fln.getDst(),lb)+"='"+st+"';"); + } else if (fln.getType().isLong()) { + output.println(generateTemp(fm, fln.getDst(),lb)+"="+fln.getValue()+"LL;"); } else output.println(generateTemp(fm, fln.getDst(),lb)+"="+fln.getValue()+";"); } diff --git a/Robust/src/IR/Operation.java b/Robust/src/IR/Operation.java index 1ea7a3e7..bc93b5f8 100644 --- a/Robust/src/IR/Operation.java +++ b/Robust/src/IR/Operation.java @@ -27,6 +27,8 @@ public class Operation { public static final int PREDEC=24; public static final int LOGIC_NOT=25; public static final int ISAVAILABLE=26; + public static final int URIGHTSHIFT=27; + public static final int COMP=28; /* Flat Operations */ public static final int ASSIGN=100; @@ -70,6 +72,8 @@ public class Operation { return LEFTSHIFT; else if (st.equals("rightshift")) return RIGHTSHIFT; + else if (st.equals("urightshift")) + return URIGHTSHIFT; else if (st.equals("sub")) return SUB; else if (st.equals("add")) @@ -94,6 +98,8 @@ public class Operation { return PREDEC; else if (st.equals("not")) return LOGIC_NOT; + else if (st.equals("comp")) + return COMP; else throw new Error(); } @@ -105,6 +111,8 @@ public class Operation { return "&&"; else if (operation==LOGIC_NOT) return "not"; + else if (operation==COMP) + return "~"; else if (operation==BIT_OR) return "|"; else if (operation==BIT_XOR) @@ -127,6 +135,8 @@ public class Operation { return "<<"; else if (operation==RIGHTSHIFT) return ">>"; + else if (operation==RIGHTSHIFT) + return ">>>"; else if (operation==SUB) return "-"; else if (operation==ADD) diff --git a/Robust/src/IR/Tree/BuildIR.java b/Robust/src/IR/Tree/BuildIR.java index f307880d..da609565 100644 --- a/Robust/src/IR/Tree/BuildIR.java +++ b/Robust/src/IR/Tree/BuildIR.java @@ -360,6 +360,7 @@ public class BuildIR { isNode(pn,"comp_lte")||isNode(pn,"comp_gt")|| isNode(pn,"comp_gte")||isNode(pn,"leftshift")|| isNode(pn,"rightshift")||isNode(pn,"sub")|| + isNode(pn,"urightshift")||isNode(pn,"sub")|| isNode(pn,"add")||isNode(pn,"mult")|| isNode(pn,"div")||isNode(pn,"mod")) { ParseNodeVector pnv=pn.getChildren(); @@ -369,7 +370,8 @@ public class BuildIR { return new OpNode(parseExpression(left),parseExpression(right),op); } else if (isNode(pn,"unaryplus")|| isNode(pn,"unaryminus")|| - isNode(pn,"not")) { + isNode(pn,"not")|| + isNode(pn,"comp")) { ParseNode left=pn.getFirstChild(); Operation op=new Operation(pn.getLabel()); return new OpNode(parseExpression(left),op); diff --git a/Robust/src/IR/Tree/SemanticCheck.java b/Robust/src/IR/Tree/SemanticCheck.java index 12538e16..816ee712 100644 --- a/Robust/src/IR/Tree/SemanticCheck.java +++ b/Robust/src/IR/Tree/SemanticCheck.java @@ -790,6 +790,21 @@ public class SemanticCheck { on.setType(new TypeDescriptor(TypeDescriptor.BOOLEAN)); break; + case Operation.COMP: + // 5.6.2 Binary Numeric Promotion + //TODO unboxing of reference objects + if (ltd.isDouble()) + throw new Error(); + else if (ltd.isFloat()) + throw new Error(); + else if (ltd.isLong()) + lefttype=new TypeDescriptor(TypeDescriptor.LONG); + else + lefttype=new TypeDescriptor(TypeDescriptor.INT); + on.setLeftType(lefttype); + on.setType(lefttype); + break; + case Operation.BIT_OR: case Operation.BIT_XOR: case Operation.BIT_AND: @@ -921,6 +936,7 @@ public class SemanticCheck { case Operation.LEFTSHIFT: case Operation.RIGHTSHIFT: + case Operation.URIGHTSHIFT: if (!rtd.isIntegerType()) throw new Error(); //5.6.1 Unary Numeric Promotion diff --git a/Robust/src/Parse/java14.cup b/Robust/src/Parse/java14.cup index 92665a47..9f0f5553 100644 --- a/Robust/src/Parse/java14.cup +++ b/Robust/src/Parse/java14.cup @@ -1611,7 +1611,8 @@ predecrement_expression ::= unary_expression_not_plus_minus ::= postfix_expression:exp {: RESULT=exp; :} -// | COMP unary_expression + | COMP unary_expression:exp + {: RESULT=(new ParseNode("comp")).addChild(exp).getRoot(); :} | NOT unary_expression:exp {: RESULT=(new ParseNode("not")).addChild(exp).getRoot(); :} | cast_expression:exp {: RESULT=exp; :} @@ -1687,7 +1688,12 @@ shift_expression ::= pn.addChild(exp2); RESULT=pn; :} -// | shift_expression URSHIFT additive_expression + | shift_expression:exp1 URSHIFT additive_expression:exp2 {: + ParseNode pn=new ParseNode("urightshift"); + pn.addChild(exp1); + pn.addChild(exp2); + RESULT=pn; + :} ; relational_expression ::= shift_expression:exp {: @@ -1819,7 +1825,7 @@ assignment_operator ::= | MINUSEQ {: RESULT=new ParseNode("minuseq"); :} | LSHIFTEQ {: RESULT=new ParseNode("lshifteq"); :} | RSHIFTEQ {: RESULT=new ParseNode("rshifteq"); :} -// | URSHIFTEQ {: RESULT=new ParseNode("urshifteq"); :} + | URSHIFTEQ {: RESULT=new ParseNode("urshifteq"); :} | ANDEQ {: RESULT=new ParseNode("andeq"); :} | XOREQ {: RESULT=new ParseNode("xoreq"); :} | OREQ {: RESULT=new ParseNode("oreq"); :} diff --git a/Robust/src/Runtime/runtime.c b/Robust/src/Runtime/runtime.c index 7f727511..197b9fb2 100644 --- a/Robust/src/Runtime/runtime.c +++ b/Robust/src/Runtime/runtime.c @@ -78,6 +78,15 @@ void CALL11(___System______exit____I,int ___status___, int ___status___) { exit(___status___); } +long CALL00(___System______currentTimeMillis____) { + struct timeval tv; long long retval; + gettimeofday(&tv, NULL); + retval = tv.tv_sec; /* seconds */ + retval*=1000; /* milliseconds */ + retval+= (tv.tv_usec/1000); /* adjust milliseconds & add them in */ + return retval; +} + void CALL01(___System______printString____L___String___,struct ___String___ * ___s___) { struct ArrayObject * chararray=VAR(___s___)->___value___; int i;