View Javadoc
1   package eu.simuline.testhelpers;
2   
3   import java.util.List;
4   import java.util.ArrayList;
5   
6   /**
7    * To create double values for tests 
8    *
9    *
10   * Created: Tue Mar 20 01:05:54 2012
11   *
12   * @author <a href="mailto:ernst@">Ernst Reissner</a>
13   * @version 1.0
14   */
15  public abstract class DTestHelper {
16  
17      /**
18       * Returns a random number with absolute value in <code>[0,1]</code>. 
19       *
20       * @param signed 
21       *    whether the number returned may be negative. 
22       * @return 
23       *    a random number 
24       *    <ul>
25       *    <li> in <code>[-1,1]</code> if <code> signed</code>. 
26       *    <li> in <code>[ 0,1]</code> if <code>!signed</code>. 
27       *    </ul>
28       */
29      static double random(boolean signed) {
30  	return signed ? 2*(Math.random()-0.5) : Math.random();
31      }
32  
33      public static double createArgD(boolean isSigned) {
34  	double cand;
35  	cand = Math.random();
36  	cand *= Math.pow(2.0,100*Math.random()-50);
37  	cand *= isSigned ? Math.signum(Math.random() - 0.5) : 1;
38  	return cand;
39      }
40  
41      /**
42       * Returns a random number which is signed 
43       * if demanded by <code>isSigned</code> 
44       * and which ranges from the given exponents. 
45       */
46      public static double createArgD(boolean isSigned, int exp0, int exp1) {
47  	double cand;
48  	cand = Math.random();
49  	cand *= Math.pow(2.0,(exp1-exp0)*Math.random()+exp0);
50  	cand *= isSigned ? Math.signum(Math.random() - 0.5) : 1;
51  	return cand;
52      }
53  
54      /**
55       * Returns a list of <code>numArgs</code> arguments as double values. 
56       * The sum of all numbers are restricted as specified by the parameters. 
57       *
58       * @param numArgs
59       *    the length of the argument list to be returned. 
60       * @param signed 
61       *    whether the arguments may be negative. 
62       * @param inRange 
63       *    whether the sum of the entries in the result List 
64       *    is in <code>[0,1)</code> or, 
65       *    if <code>signed</code> in <code>(-1,1)</code>. 
66       * @return
67       *    a list of <code>numArgs</code> arguments as double values. 
68       *    The sum of all numbers is in <code>[0,1)</code> 
69       *    and for <code>!signed</code> even in <code>[0.5,1)</code>. 
70       *    The entries are in <code>[0,1)</code> for <code>!signed</code> 
71       *    and in <code>(-1,1)</code> for <code>signed</code>. 
72       */
73      public static List<Double> createMultArgsSumD(int numArgs,
74  						  boolean signed,
75  						  boolean inRange) {
76  
77  	// create a list of random numbers in Double-format. 
78  	List<Double> resultD = new ArrayList<Double>(numArgs);
79  
80  	if (numArgs == 0) {
81  	    return resultD;
82  	}
83  
84  	double sum = 0;
85  	double max = 0;
86  	double cand;
87  	for (int i = 0; i < numArgs; i++) {
88  	    cand = random(signed);
89  	    // cand in [-1,1] or in [ 0,1] depending on signed
90  	    max = Math.max(max,Math.abs(cand));
91  	    resultD.add(cand);
92  	    sum += cand;
93  	} // for i 
94  	// Here, sum contains the sum of the entries of resultD 
95  	// whereas max contains the maximum of the absolute values. 
96  
97  	if (inRange) {
98  	    int sgn = (int)Math.signum(sum);
99  
100 	    // make sure that the sum of all arguments does not reach 1. 
101 	    max = Math.max(max,Math.abs(sum));
102 	    // TBC: why is this necessary? 
103 	    double shift = Math.pow(2,
104 				    //Math.ceil(MathExt.ld(max)));
105 				    Math.ceil(Math.log(max)/Math.log(2)));
106 	    // Note that shift is in fact an integer. 
107 	    // leaving out Math.ceil, we obtain 
108 	    // shift <= Math.pow(2,MathExt.ld(max))=max 
109 
110 	    assert -1 < sum/shift && sum/shift < 1;
111 	    assert -1 < max/shift && max/shift < 1;
112 
113 	    for (int i = 0; i < numArgs; i++) {
114 		// "/shift" that all entries and the sum are in (-1,1)
115 		// "*sgn"   that the sum is even in [0,1) 
116 		resultD.set(i,(double)resultD.get(i)/shift*sgn);
117 	    }
118 	} // inRange 
119 	
120 	return resultD;
121     }
122 
123 
124     public static List<Double> createMultArgsSumD(boolean signed,
125 						  boolean inRange) {
126 	int numArgs = 1+(int)Math.round(10*Math.random());
127 	return createMultArgsSumD(numArgs, signed, inRange);
128     }
129 
130     public static List<Double> createMultArgsD(int numArgs,
131 					       boolean allowsSigned,
132 					       boolean inRange, 
133 					       boolean allowsNaN) {
134 	// create a list of random numbers in Double-format. 
135 	List<Double> resultD = new ArrayList<Double>(numArgs);
136 	double num;
137 	for (int i = 0; i < numArgs; i++) {
138 	    if (allowsNaN && Math.random() > 0.95) {
139 		num = Double.NaN;
140 	    } else {
141 		num = Math.random();
142 		num *= inRange ? 1 : Math.pow(2.0,100*Math.random()-50);
143 		num *= allowsSigned ? Math.signum(Math.random() - 0.5) : 1;
144 	    }
145 
146 
147 	    resultD.add(num);
148 	}
149 
150 	return resultD;
151     }
152 
153     public static List<Double> createMultArgsD(boolean signed,
154 					       boolean inRange, 
155 					       boolean allowsNaN) {
156 	int numArgs = 1+(int)Math.round(10*Math.random());
157 	return createMultArgsD(numArgs, signed, inRange, allowsNaN);
158     }
159 
160 }