import java.util.Random; import static edu.rice.hj.Module1.doWork; /** * Contains a bunch of utility functions for summing up arrays * @author Shams Imam (shams@rice.edu) */ public class ArraySumUtil { static final int default_n = 64; static final String err = "Incorrect argument for array size (should be > 0), assuming n = " + default_n; /** * Creates a new array of random integers of size n * @param n - the size of the array * @return - an array of random integers. */ protected static int[] initialize(final int n) { // Initialization final int[] X = new int[n]; final Random myRand = new Random(n); for (int i = 0; i < n; i++) { X[i] = myRand.nextInt(n * 100); } return X; } /** * Reads the input paramter to the program. If there * is no input parameter or the input is illegal, * uses a default n * @param argv - the string array of input parameters * @return the number of random ints to use */ protected static int readLengthArgument(final String[] argv) { int n; if (argv.length != 0) { try { n = Integer.parseInt(argv[0]); if (n <= 0) { // Bad value of n System.out.println(err); n = default_n; } } catch (Throwable e) { System.out.println(err); n = default_n; } } else { // argv.length == 0 n = default_n; } return n; } /** * Divide x by y, and round up to next largest int * @param x - dividend * @param y - divisor * @return quotient rounded to the up to an integer */ protected static int ceilDiv(int x, int y) { return (x + y - 1) / y; } /** * Gaurenteed correct answer summation of an array to check the effectiveness * of other solutions * @param x - an integer array to sum up * @return - the sum of all the elements in the input array */ protected static int expectedResult(final int[] x) { int result = 0; for (int i = 0; i < x.length; i++) { result += x[i]; } return result; } /** * Sums up elements in an array, incrementing the work counter by an amount * specified by the startegy defined elsewhere and stored in the system * @param x - array whose values are getting summed * @param leftIndex - an index in the array * @param rightIndex - an index in the array * @return - the sum of the values at the two indeces */ protected static int doOperation(final int[] x, final int leftIndex, final int rightIndex) { doWork(extractWorkStrategy().computeWork(x[leftIndex], x[rightIndex])); return x[leftIndex] + x[rightIndex]; } /** * Returns the kind of strategy defind by the system * @return a WorkStrategy object */ private static WorkStrategy extractWorkStrategy() { final String strategyStr = System.getProperty("arraysum.work.strategy"); if ("bit".equalsIgnoreCase(strategyStr)) { return WorkStrategy.BIT_COUNT; } if ("string".equalsIgnoreCase(strategyStr)) { return WorkStrategy.STRING_LENGTH; } if ("simple".equalsIgnoreCase(strategyStr)) { return WorkStrategy.SIMPLE; } return WorkStrategy.SIMPLE; } /** * Factory inteferface allowing for the creation of diffeerent kinds * of work startegies with different ways of computing work */ private static interface WorkStrategy { WorkStrategy SIMPLE = new SimpleWorkStrategy(); WorkStrategy STRING_LENGTH = new StringLengthWorkStrategy(); WorkStrategy BIT_COUNT = new BitCountWorkStrategy(); /** * Calculates how much work was done to add the values * given the two values * @param left - first value * @param right - second value * @return the amount of work done to add them */ int computeWork(int left, int right); /** * Work strategy where every addition is one unit of work */ static class SimpleWorkStrategy implements WorkStrategy { public int computeWork(int left, int right) { // count each + operator as 1 unit of work in the abstract performance metrics return 1; } } /** * Work strategy where every addition takes the sum of terms' * decimal length */ static class StringLengthWorkStrategy implements WorkStrategy { public int computeWork(int left, int right) { return String.valueOf(left).length() + String.valueOf(right).length(); } } /** * Work strategy where every addition takes the sum of the terms' * bit length */ static class BitCountWorkStrategy implements WorkStrategy { public int computeWork(int left, int right) { // count work as sum of the bits in input operands return countBits(left) + countBits(right); } /** * Return the number of bits in x for use in abstract performance metrics. * If x is negative, return the number of bits in -x. * @param x integer * @return the number of bits of x */ private int countBits(int x) { // Convert x to a positive value if (x == Integer.MIN_VALUE) { x = Integer.MAX_VALUE; } else if (x < 0) { x = -x; } return 32 - Integer.numberOfLeadingZeros(x); } } } }