~ubuntu-branches/ubuntu/precise/weka/precise

« back to all changes in this revision

Viewing changes to weka/core/Utils.java

  • Committer: Bazaar Package Importer
  • Author(s): Soeren Sonnenburg
  • Date: 2008-02-24 09:18:45 UTC
  • Revision ID: james.westby@ubuntu.com-20080224091845-1l8zy6fm6xipbzsr
Tags: upstream-3.5.7+tut1
ImportĀ upstreamĀ versionĀ 3.5.7+tut1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *    This program is free software; you can redistribute it and/or modify
 
3
 *    it under the terms of the GNU General Public License as published by
 
4
 *    the Free Software Foundation; either version 2 of the License, or
 
5
 *    (at your option) any later version.
 
6
 *
 
7
 *    This program is distributed in the hope that it will be useful,
 
8
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
 *    GNU General Public License for more details.
 
11
 *
 
12
 *    You should have received a copy of the GNU General Public License
 
13
 *    along with this program; if not, write to the Free Software
 
14
 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
15
 */
 
16
 
 
17
/*
 
18
 *    Utils.java
 
19
 *    Copyright (C) 1999-2004 University of Waikato, Hamilton, New Zealand
 
20
 *
 
21
 */
 
22
 
 
23
package weka.core;
 
24
 
 
25
import java.lang.Math;
 
26
import java.lang.reflect.Array;
 
27
import java.util.Properties;
 
28
import java.io.File;
 
29
import java.io.FileInputStream;
 
30
import java.util.Random;
 
31
 
 
32
/**
 
33
 * Class implementing some simple utility methods.
 
34
 *
 
35
 * @author Eibe Frank 
 
36
 * @author Yong Wang 
 
37
 * @author Len Trigg 
 
38
 * @author Julien Prados
 
39
 * @version $Revision: 1.57 $
 
40
 */
 
41
public final class Utils {
 
42
 
 
43
  /** The natural logarithm of 2. */
 
44
  public static double log2 = Math.log(2);
 
45
 
 
46
  /** The small deviation allowed in double comparisons */
 
47
  public static double SMALL = 1e-6;
 
48
 
 
49
  
 
50
  /**
 
51
   * Reads properties that inherit from three locations. Properties
 
52
   * are first defined in the system resource location (i.e. in the
 
53
   * CLASSPATH).  These default properties must exist. Properties
 
54
   * defined in the users home directory (optional) override default
 
55
   * settings. Properties defined in the current directory (optional)
 
56
   * override all these settings.
 
57
   *
 
58
   * @param resourceName the location of the resource that should be
 
59
   * loaded.  e.g.: "weka/core/Utils.props". (The use of hardcoded
 
60
   * forward slashes here is OK - see
 
61
   * jdk1.1/docs/guide/misc/resources.html) This routine will also
 
62
   * look for the file (in this case) "Utils.props" in the users home
 
63
   * directory and the current directory.
 
64
   * @return the Properties
 
65
   * @exception Exception if no default properties are defined, or if
 
66
   * an error occurs reading the properties files.  
 
67
   */
 
68
  public static Properties readProperties(String resourceName)
 
69
    throws Exception {
 
70
 
 
71
    Properties defaultProps = new Properties();
 
72
    try {
 
73
      // Apparently hardcoded slashes are OK here
 
74
      // jdk1.1/docs/guide/misc/resources.html
 
75
      defaultProps.load(ClassLoader.getSystemResourceAsStream(resourceName));
 
76
    } catch (Exception ex) {
 
77
/*      throw new Exception("Problem reading default properties: "
 
78
        + ex.getMessage()); */
 
79
      System.err.println("Warning, unable to load properties file from "
 
80
                         +"system resource (Utils.java)");
 
81
    }
 
82
 
 
83
    // Hardcoded slash is OK here
 
84
    // eg: see jdk1.1/docs/guide/misc/resources.html
 
85
    int slInd = resourceName.lastIndexOf('/');
 
86
    if (slInd != -1) {
 
87
      resourceName = resourceName.substring(slInd + 1);
 
88
    }
 
89
 
 
90
    // Allow a properties file in the home directory to override
 
91
    Properties userProps = new Properties(defaultProps);    
 
92
    File propFile = new File(System.getProperties().getProperty("user.home")
 
93
                             + File.separatorChar
 
94
                             + resourceName);
 
95
    if (propFile.exists()) {
 
96
      try {
 
97
        userProps.load(new FileInputStream(propFile));
 
98
      } catch (Exception ex) {
 
99
        throw new Exception("Problem reading user properties: " + propFile);
 
100
      }
 
101
    }
 
102
 
 
103
    // Allow a properties file in the current directory to override
 
104
    Properties localProps = new Properties(userProps);
 
105
    propFile = new File(resourceName);
 
106
    if (propFile.exists()) {
 
107
      try {
 
108
        localProps.load(new FileInputStream(propFile));
 
109
      } catch (Exception ex) {
 
110
        throw new Exception("Problem reading local properties: " + propFile);
 
111
      }
 
112
    }
 
113
    
 
114
    return localProps;
 
115
  }
 
116
 
 
117
  /**
 
118
   * Returns the correlation coefficient of two double vectors.
 
119
   *
 
120
   * @param y1 double vector 1
 
121
   * @param y2 double vector 2
 
122
   * @param n the length of two double vectors
 
123
   * @return the correlation coefficient
 
124
   */
 
125
  public static final double correlation(double y1[],double y2[],int n) {
 
126
 
 
127
    int i;
 
128
    double av1 = 0.0, av2 = 0.0, y11 = 0.0, y22 = 0.0, y12 = 0.0, c;
 
129
    
 
130
    if (n <= 1) {
 
131
      return 1.0;
 
132
    }
 
133
    for (i = 0; i < n; i++) {
 
134
      av1 += y1[i];
 
135
      av2 += y2[i];
 
136
    }
 
137
    av1 /= (double) n;
 
138
    av2 /= (double) n;
 
139
    for (i = 0; i < n; i++) {
 
140
      y11 += (y1[i] - av1) * (y1[i] - av1);
 
141
      y22 += (y2[i] - av2) * (y2[i] - av2);
 
142
      y12 += (y1[i] - av1) * (y2[i] - av2);
 
143
    }
 
144
    if (y11 * y22 == 0.0) {
 
145
      c=1.0;
 
146
    } else {
 
147
      c = y12 / Math.sqrt(Math.abs(y11 * y22));
 
148
    }
 
149
    
 
150
    return c;
 
151
  }
 
152
 
 
153
  /**
 
154
   * Removes all occurrences of a string from another string.
 
155
   *
 
156
   * @param inString the string to remove substrings from.
 
157
   * @param substring the substring to remove.
 
158
   * @return the input string with occurrences of substring removed.
 
159
   */
 
160
  public static String removeSubstring(String inString, String substring) {
 
161
 
 
162
    StringBuffer result = new StringBuffer();
 
163
    int oldLoc = 0, loc = 0;
 
164
    while ((loc = inString.indexOf(substring, oldLoc))!= -1) {
 
165
      result.append(inString.substring(oldLoc, loc));
 
166
      oldLoc = loc + substring.length();
 
167
    }
 
168
    result.append(inString.substring(oldLoc));
 
169
    return result.toString();
 
170
  }
 
171
 
 
172
  /**
 
173
   * Replaces with a new string, all occurrences of a string from 
 
174
   * another string.
 
175
   *
 
176
   * @param inString the string to replace substrings in.
 
177
   * @param subString the substring to replace.
 
178
   * @param replaceString the replacement substring
 
179
   * @return the input string with occurrences of substring replaced.
 
180
   */
 
181
  public static String replaceSubstring(String inString, String subString,
 
182
                                        String replaceString) {
 
183
 
 
184
    StringBuffer result = new StringBuffer();
 
185
    int oldLoc = 0, loc = 0;
 
186
    while ((loc = inString.indexOf(subString, oldLoc))!= -1) {
 
187
      result.append(inString.substring(oldLoc, loc));
 
188
      result.append(replaceString);
 
189
      oldLoc = loc + subString.length();
 
190
    }
 
191
    result.append(inString.substring(oldLoc));
 
192
    return result.toString();
 
193
  }
 
194
 
 
195
 
 
196
  /**
 
197
   * Pads a string to a specified length, inserting spaces on the left
 
198
   * as required. If the string is too long, characters are removed (from
 
199
   * the right).
 
200
   *
 
201
   * @param inString the input string
 
202
   * @param length the desired length of the output string
 
203
   * @return the output string
 
204
   */
 
205
  public static String padLeft(String inString, int length) {
 
206
 
 
207
    return fixStringLength(inString, length, false);
 
208
  }
 
209
  
 
210
  /**
 
211
   * Pads a string to a specified length, inserting spaces on the right
 
212
   * as required. If the string is too long, characters are removed (from
 
213
   * the right).
 
214
   *
 
215
   * @param inString the input string
 
216
   * @param length the desired length of the output string
 
217
   * @return the output string
 
218
   */
 
219
  public static String padRight(String inString, int length) {
 
220
 
 
221
    return fixStringLength(inString, length, true);
 
222
  }
 
223
  
 
224
  /**
 
225
   * Pads a string to a specified length, inserting spaces as
 
226
   * required. If the string is too long, characters are removed (from
 
227
   * the right).
 
228
   *
 
229
   * @param inString the input string
 
230
   * @param length the desired length of the output string
 
231
   * @param right true if inserted spaces should be added to the right
 
232
   * @return the output string
 
233
   */
 
234
  private static /*@pure@*/ String fixStringLength(String inString, int length,
 
235
                                        boolean right) {
 
236
 
 
237
    if (inString.length() < length) {
 
238
      while (inString.length() < length) {
 
239
        inString = (right ? inString.concat(" ") : " ".concat(inString));
 
240
      }
 
241
    } else if (inString.length() > length) {
 
242
      inString = inString.substring(0, length);
 
243
    }
 
244
    return inString;
 
245
  }
 
246
 
 
247
  /**
 
248
   * Rounds a double and converts it into String.
 
249
   *
 
250
   * @param value the double value
 
251
   * @param afterDecimalPoint the (maximum) number of digits permitted
 
252
   * after the decimal point
 
253
   * @return the double as a formatted string
 
254
   */
 
255
  public static /*@pure@*/ String doubleToString(double value, int afterDecimalPoint) {
 
256
    
 
257
    StringBuffer stringBuffer;
 
258
    double temp;
 
259
    int dotPosition;
 
260
    long precisionValue;
 
261
    
 
262
    temp = value * Math.pow(10.0, afterDecimalPoint);
 
263
    if (Math.abs(temp) < Long.MAX_VALUE) {
 
264
      precisionValue =  (temp > 0) ? (long)(temp + 0.5) 
 
265
                                   : -(long)(Math.abs(temp) + 0.5);
 
266
      if (precisionValue == 0) {
 
267
        stringBuffer = new StringBuffer(String.valueOf(0));
 
268
      } else {
 
269
        stringBuffer = new StringBuffer(String.valueOf(precisionValue));
 
270
      }
 
271
      if (afterDecimalPoint == 0) {
 
272
        return stringBuffer.toString();
 
273
      }
 
274
      dotPosition = stringBuffer.length() - afterDecimalPoint;
 
275
      while (((precisionValue < 0) && (dotPosition < 1)) ||
 
276
             (dotPosition < 0)) {
 
277
        if (precisionValue < 0) {
 
278
          stringBuffer.insert(1, '0');
 
279
        } else {
 
280
          stringBuffer.insert(0, '0');
 
281
        }
 
282
        dotPosition++;
 
283
      }
 
284
      stringBuffer.insert(dotPosition, '.');
 
285
      if ((precisionValue < 0) && (stringBuffer.charAt(1) == '.')) {
 
286
        stringBuffer.insert(1, '0');
 
287
      } else if (stringBuffer.charAt(0) == '.') {
 
288
        stringBuffer.insert(0, '0');
 
289
      }
 
290
      int currentPos = stringBuffer.length() - 1;
 
291
      while ((currentPos > dotPosition) &&
 
292
             (stringBuffer.charAt(currentPos) == '0')) {
 
293
        stringBuffer.setCharAt(currentPos--, ' ');
 
294
      }
 
295
      if (stringBuffer.charAt(currentPos) == '.') {
 
296
        stringBuffer.setCharAt(currentPos, ' ');
 
297
      }
 
298
      
 
299
      return stringBuffer.toString().trim();
 
300
    }
 
301
    return new String("" + value);
 
302
  }
 
303
 
 
304
  /**
 
305
   * Rounds a double and converts it into a formatted decimal-justified String.
 
306
   * Trailing 0's are replaced with spaces.
 
307
   *
 
308
   * @param value the double value
 
309
   * @param width the width of the string
 
310
   * @param afterDecimalPoint the number of digits after the decimal point
 
311
   * @return the double as a formatted string
 
312
   */
 
313
  public static /*@pure@*/ String doubleToString(double value, int width,
 
314
                                      int afterDecimalPoint) {
 
315
    
 
316
    String tempString = doubleToString(value, afterDecimalPoint);
 
317
    char[] result;
 
318
    int dotPosition;
 
319
 
 
320
    if ((afterDecimalPoint >= width) 
 
321
        || (tempString.indexOf('E') != -1)) { // Protects sci notation
 
322
      return tempString;
 
323
    }
 
324
 
 
325
    // Initialize result
 
326
    result = new char[width];
 
327
    for (int i = 0; i < result.length; i++) {
 
328
      result[i] = ' ';
 
329
    }
 
330
 
 
331
    if (afterDecimalPoint > 0) {
 
332
      // Get position of decimal point and insert decimal point
 
333
      dotPosition = tempString.indexOf('.');
 
334
      if (dotPosition == -1) {
 
335
        dotPosition = tempString.length();
 
336
      } else {
 
337
        result[width - afterDecimalPoint - 1] = '.';
 
338
      }
 
339
    } else {
 
340
      dotPosition = tempString.length();
 
341
    }
 
342
    
 
343
 
 
344
    int offset = width - afterDecimalPoint - dotPosition;
 
345
    if (afterDecimalPoint > 0) {
 
346
      offset--;
 
347
    }
 
348
 
 
349
    // Not enough room to decimal align within the supplied width
 
350
    if (offset < 0) {
 
351
      return tempString;
 
352
    }
 
353
 
 
354
    // Copy characters before decimal point
 
355
    for (int i = 0; i < dotPosition; i++) {
 
356
      result[offset + i] = tempString.charAt(i);
 
357
    }
 
358
 
 
359
    // Copy characters after decimal point
 
360
    for (int i = dotPosition + 1; i < tempString.length(); i++) {
 
361
      result[offset + i] = tempString.charAt(i);
 
362
    }
 
363
 
 
364
    return new String(result);
 
365
  }
 
366
 
 
367
  /**
 
368
   * Returns the basic class of an array class (handles multi-dimensional
 
369
   * arrays).
 
370
   * @param c        the array to inspect
 
371
   * @return         the class of the innermost elements
 
372
   */
 
373
  public static Class getArrayClass(Class c) {
 
374
     if (c.getComponentType().isArray())
 
375
        return getArrayClass(c.getComponentType());
 
376
     else
 
377
        return c.getComponentType();
 
378
  }
 
379
 
 
380
  /**
 
381
   * Returns the dimensions of the given array. Even though the
 
382
   * parameter is of type "Object" one can hand over primitve arrays, e.g.
 
383
   * int[3] or double[2][4].
 
384
   *
 
385
   * @param array       the array to determine the dimensions for
 
386
   * @return            the dimensions of the array
 
387
   */
 
388
  public static int getArrayDimensions(Class array) {
 
389
    if (array.getComponentType().isArray())
 
390
      return 1 + getArrayDimensions(array.getComponentType());
 
391
    else
 
392
      return 1;
 
393
  }
 
394
 
 
395
  /**
 
396
   * Returns the dimensions of the given array. Even though the
 
397
   * parameter is of type "Object" one can hand over primitve arrays, e.g.
 
398
   * int[3] or double[2][4].
 
399
   *
 
400
   * @param array       the array to determine the dimensions for
 
401
   * @return            the dimensions of the array
 
402
   */
 
403
  public static int getArrayDimensions(Object array) {
 
404
    return getArrayDimensions(array.getClass());
 
405
  }
 
406
 
 
407
  /**
 
408
   * Returns the given Array in a string representation. Even though the
 
409
   * parameter is of type "Object" one can hand over primitve arrays, e.g.
 
410
   * int[3] or double[2][4].
 
411
   * 
 
412
   * @param array       the array to return in a string representation
 
413
   * @return            the array as string
 
414
   */
 
415
  public static String arrayToString(Object array) {
 
416
    String        result;
 
417
    int           dimensions;
 
418
    int           i;       
 
419
 
 
420
    result     = "";
 
421
    dimensions = getArrayDimensions(array);
 
422
    
 
423
    if (dimensions == 0) {
 
424
      result = "null";
 
425
    }
 
426
    else if (dimensions == 1) {
 
427
      for (i = 0; i < Array.getLength(array); i++) {
 
428
        if (i > 0)
 
429
          result += ",";
 
430
        if (Array.get(array, i) == null)
 
431
          result += "null";
 
432
        else
 
433
          result += Array.get(array, i).toString();
 
434
      }
 
435
    }
 
436
    else {
 
437
      for (i = 0; i < Array.getLength(array); i++) {
 
438
        if (i > 0)
 
439
          result += ",";
 
440
        result += "[" + arrayToString(Array.get(array, i)) + "]";
 
441
      }
 
442
    }
 
443
    
 
444
    return result;
 
445
  }
 
446
 
 
447
  /**
 
448
   * Tests if a is equal to b.
 
449
   *
 
450
   * @param a a double
 
451
   * @param b a double
 
452
   */
 
453
  public static /*@pure@*/ boolean eq(double a, double b){
 
454
    
 
455
    return (a - b < SMALL) && (b - a < SMALL); 
 
456
  }
 
457
 
 
458
  /**
 
459
   * Checks if the given array contains any non-empty options.
 
460
   *
 
461
   * @param options an array of strings
 
462
   * @exception Exception if there are any non-empty options
 
463
   */
 
464
  public static void checkForRemainingOptions(String[] options) 
 
465
    throws Exception {
 
466
    
 
467
    int illegalOptionsFound = 0;
 
468
    StringBuffer text = new StringBuffer();
 
469
 
 
470
    if (options == null) {
 
471
      return;
 
472
    }
 
473
    for (int i = 0; i < options.length; i++) {
 
474
      if (options[i].length() > 0) {
 
475
        illegalOptionsFound++;
 
476
        text.append(options[i] + ' ');
 
477
      }
 
478
    }
 
479
    if (illegalOptionsFound > 0) {
 
480
      throw new Exception("Illegal options: " + text);
 
481
    }
 
482
  }
 
483
  
 
484
  /**
 
485
   * Checks if the given array contains the flag "-Char". Stops
 
486
   * searching at the first marker "--". If the flag is found,
 
487
   * it is replaced with the empty string.
 
488
   *
 
489
   * @param flag the character indicating the flag.
 
490
   * @param options the array of strings containing all the options.
 
491
   * @return true if the flag was found
 
492
   * @exception Exception if an illegal option was found
 
493
   */
 
494
  public static boolean getFlag(char flag, String[] options) 
 
495
    throws Exception {
 
496
    
 
497
    return getFlag("" + flag, options);
 
498
  }
 
499
  
 
500
  /**
 
501
   * Checks if the given array contains the flag "-String". Stops
 
502
   * searching at the first marker "--". If the flag is found,
 
503
   * it is replaced with the empty string.
 
504
   *
 
505
   * @param flag the String indicating the flag.
 
506
   * @param options the array of strings containing all the options.
 
507
   * @return true if the flag was found
 
508
   * @exception Exception if an illegal option was found
 
509
   */
 
510
  public static boolean getFlag(String flag, String[] options) 
 
511
    throws Exception {
 
512
    
 
513
    int pos = getOptionPos(flag, options);
 
514
 
 
515
    if (pos > -1)
 
516
      options[pos] = "";
 
517
    
 
518
    return (pos > -1);
 
519
  }
 
520
 
 
521
  /**
 
522
   * Gets an option indicated by a flag "-Char" from the given array
 
523
   * of strings. Stops searching at the first marker "--". Replaces 
 
524
   * flag and option with empty strings.
 
525
   *
 
526
   * @param flag the character indicating the option.
 
527
   * @param options the array of strings containing all the options.
 
528
   * @return the indicated option or an empty string
 
529
   * @exception Exception if the option indicated by the flag can't be found
 
530
   */
 
531
  public static /*@non_null@*/ String getOption(char flag, String[] options) 
 
532
    throws Exception {
 
533
    
 
534
    return getOption("" + flag, options);
 
535
  }
 
536
 
 
537
  /**
 
538
   * Gets an option indicated by a flag "-String" from the given array
 
539
   * of strings. Stops searching at the first marker "--". Replaces 
 
540
   * flag and option with empty strings.
 
541
   *
 
542
   * @param flag the String indicating the option.
 
543
   * @param options the array of strings containing all the options.
 
544
   * @return the indicated option or an empty string
 
545
   * @exception Exception if the option indicated by the flag can't be found
 
546
   */
 
547
  public static /*@non_null@*/ String getOption(String flag, String[] options) 
 
548
    throws Exception {
 
549
 
 
550
    String newString;
 
551
    int i = getOptionPos(flag, options);
 
552
 
 
553
    if (i > -1) {
 
554
      if (options[i].equals("-" + flag)) {
 
555
        if (i + 1 == options.length) {
 
556
          throw new Exception("No value given for -" + flag + " option.");
 
557
        }
 
558
        options[i] = "";
 
559
        newString = new String(options[i + 1]);
 
560
        options[i + 1] = "";
 
561
        return newString;
 
562
      }
 
563
      if (options[i].charAt(1) == '-') {
 
564
        return "";
 
565
      }
 
566
    }
 
567
    
 
568
    return "";
 
569
  }
 
570
 
 
571
  /**
 
572
   * Gets the index of an option or flag indicated by a flag "-Char" from 
 
573
   * the given array of strings. Stops searching at the first marker "--".
 
574
   *
 
575
   * @param flag        the character indicating the option.
 
576
   * @param options     the array of strings containing all the options.
 
577
   * @return            the position if found, or -1 otherwise
 
578
   */
 
579
  public static int getOptionPos(char flag, String[] options) {
 
580
     return getOptionPos("" + flag, options);
 
581
  }
 
582
 
 
583
  /**
 
584
   * Gets the index of an option or flag indicated by a flag "-String" from 
 
585
   * the given array of strings. Stops searching at the first marker "--".
 
586
   *
 
587
   * @param flag        the String indicating the option.
 
588
   * @param options     the array of strings containing all the options.
 
589
   * @return            the position if found, or -1 otherwise
 
590
   */
 
591
  public static int getOptionPos(String flag, String[] options) {
 
592
    if (options == null)
 
593
      return -1;
 
594
    
 
595
    for (int i = 0; i < options.length; i++) {
 
596
      if ((options[i].length() > 0) && (options[i].charAt(0) == '-')) {
 
597
        // Check if it is a negative number
 
598
        try {
 
599
          Double.valueOf(options[i]);
 
600
        } 
 
601
        catch (NumberFormatException e) {
 
602
          // found?
 
603
          if (options[i].equals("-" + flag))
 
604
            return i;
 
605
          // did we reach "--"?
 
606
          if (options[i].charAt(1) == '-')
 
607
            return -1;
 
608
        }
 
609
      }
 
610
    }
 
611
    
 
612
    return -1;
 
613
  }
 
614
 
 
615
  /**
 
616
   * Quotes a string if it contains special characters.
 
617
   * 
 
618
   * The following rules are applied:
 
619
   *
 
620
   * A character is backquoted version of it is one 
 
621
   * of <tt>" ' % \ \n \r \t</tt>.
 
622
   *
 
623
   * A string is enclosed within single quotes if a character has been
 
624
   * backquoted using the previous rule above or contains 
 
625
   * <tt>{ }</tt> or is exactly equal to the strings 
 
626
   * <tt>, ? space or ""</tt> (empty string).
 
627
   *
 
628
   * A quoted question mark distinguishes it from the missing value which
 
629
   * is represented as an unquoted question mark in arff files.
 
630
   *
 
631
   * @param string      the string to be quoted
 
632
   * @return            the string (possibly quoted)
 
633
   * @see               #unquote(String)
 
634
   */
 
635
  public static /*@pure@*/ String quote(String string) {
 
636
      boolean quote = false;
 
637
 
 
638
      // backquote the following characters 
 
639
      if ((string.indexOf('\n') != -1) || (string.indexOf('\r') != -1) || 
 
640
          (string.indexOf('\'') != -1) || (string.indexOf('"') != -1) || 
 
641
          (string.indexOf('\\') != -1) || 
 
642
          (string.indexOf('\t') != -1) || (string.indexOf('%') != -1)) {
 
643
          string = backQuoteChars(string);
 
644
          quote = true;
 
645
      }
 
646
 
 
647
      // Enclose the string in 's if the string contains a recently added
 
648
      // backquote or contains one of the following characters.
 
649
      if((quote == true) || 
 
650
         (string.indexOf('{') != -1) || (string.indexOf('}') != -1) ||
 
651
         (string.indexOf(',') != -1) || (string.equals("?")) ||
 
652
         (string.indexOf(' ') != -1) || (string.equals(""))) {
 
653
          string = ("'".concat(string)).concat("'");
 
654
      }
 
655
 
 
656
      return string;
 
657
  }
 
658
 
 
659
  /**
 
660
   * unquotes are previously quoted string (but only if necessary), i.e., it
 
661
   * removes the single quotes around it. Inverse to quote(String).
 
662
   * 
 
663
   * @param string      the string to process
 
664
   * @return            the unquoted string
 
665
   * @see               #quote(String)
 
666
   */
 
667
  public static String unquote(String string) {
 
668
    if (string.startsWith("'") && string.endsWith("'")) {
 
669
      string = string.substring(1, string.length() - 1);
 
670
      
 
671
      if ((string.indexOf("\\n") != -1) || (string.indexOf("\\r") != -1) || 
 
672
          (string.indexOf("\\'") != -1) || (string.indexOf("\\\"") != -1) || 
 
673
          (string.indexOf("\\\\") != -1) || 
 
674
          (string.indexOf("\\t") != -1) || (string.indexOf("\\%") != -1)) {
 
675
        string = unbackQuoteChars(string);
 
676
      }
 
677
    }
 
678
 
 
679
    return string;
 
680
  }
 
681
 
 
682
  /**
 
683
   * Converts carriage returns and new lines in a string into \r and \n.
 
684
   * Backquotes the following characters: ` " \ \t and %
 
685
   * 
 
686
   * @param string      the string
 
687
   * @return            the converted string
 
688
   * @see               #unbackQuoteChars(String)
 
689
   */
 
690
  public static /*@pure@*/ String backQuoteChars(String string) {
 
691
 
 
692
    int index;
 
693
    StringBuffer newStringBuffer;
 
694
 
 
695
    // replace each of the following characters with the backquoted version
 
696
    char   charsFind[] =    {'\\',   '\'',  '\t',  '\n',  '\r',  '"',    '%'};
 
697
    String charsReplace[] = {"\\\\", "\\'", "\\t", "\\n", "\\r", "\\\"", "\\%"};
 
698
    for (int i = 0; i < charsFind.length; i++) {
 
699
      if (string.indexOf(charsFind[i]) != -1 ) {
 
700
        newStringBuffer = new StringBuffer();
 
701
        while ((index = string.indexOf(charsFind[i])) != -1) {
 
702
          if (index > 0) {
 
703
            newStringBuffer.append(string.substring(0, index));
 
704
          }
 
705
          newStringBuffer.append(charsReplace[i]);
 
706
          if ((index + 1) < string.length()) {
 
707
            string = string.substring(index + 1);
 
708
          } else {
 
709
            string = "";
 
710
          }
 
711
        }
 
712
        newStringBuffer.append(string);
 
713
        string = newStringBuffer.toString();
 
714
      }
 
715
    }
 
716
 
 
717
    return string;
 
718
  }
 
719
 
 
720
  /**
 
721
   * Converts carriage returns and new lines in a string into \r and \n.
 
722
   *
 
723
   * @param string the string
 
724
   * @return the converted string
 
725
   */
 
726
  public static String convertNewLines(String string) {
 
727
    int index;
 
728
 
 
729
    // Replace with \n
 
730
    StringBuffer newStringBuffer = new StringBuffer();
 
731
    while ((index = string.indexOf('\n')) != -1) {
 
732
      if (index > 0) {
 
733
        newStringBuffer.append(string.substring(0, index));
 
734
      }
 
735
      newStringBuffer.append('\\');
 
736
      newStringBuffer.append('n');
 
737
      if ((index + 1) < string.length()) {
 
738
        string = string.substring(index + 1);
 
739
      } else {
 
740
        string = "";
 
741
      }
 
742
    }
 
743
    newStringBuffer.append(string);
 
744
    string = newStringBuffer.toString();
 
745
 
 
746
    // Replace with \r
 
747
    newStringBuffer = new StringBuffer();
 
748
    while ((index = string.indexOf('\r')) != -1) {
 
749
      if (index > 0) {
 
750
        newStringBuffer.append(string.substring(0, index));
 
751
      }
 
752
      newStringBuffer.append('\\');
 
753
      newStringBuffer.append('r');
 
754
      if ((index + 1) < string.length()){
 
755
        string = string.substring(index + 1);
 
756
      } else {
 
757
        string = "";
 
758
      }
 
759
    }
 
760
    newStringBuffer.append(string);
 
761
    return newStringBuffer.toString();
 
762
  }
 
763
 
 
764
  /**
 
765
   * Reverts \r and \n in a string into carriage returns and new lines.
 
766
   * 
 
767
   * @param string the string
 
768
   * @return the converted string
 
769
   */
 
770
  public static String revertNewLines(String string) {
 
771
    int index;
 
772
 
 
773
    // Replace with \n
 
774
    StringBuffer newStringBuffer = new StringBuffer();
 
775
    while ((index = string.indexOf("\\n")) != -1) {
 
776
      if (index > 0) {
 
777
        newStringBuffer.append(string.substring(0, index));
 
778
      }
 
779
      newStringBuffer.append('\n');
 
780
      if ((index + 2) < string.length()) {
 
781
        string = string.substring(index + 2);
 
782
      } else {
 
783
        string = "";
 
784
      }
 
785
    }
 
786
    newStringBuffer.append(string);
 
787
    string = newStringBuffer.toString();
 
788
 
 
789
    // Replace with \r
 
790
    newStringBuffer = new StringBuffer();
 
791
    while ((index = string.indexOf("\\r")) != -1) {
 
792
      if (index > 0) {
 
793
        newStringBuffer.append(string.substring(0, index));
 
794
      }
 
795
      newStringBuffer.append('\r');
 
796
      if ((index + 2) < string.length()){
 
797
        string = string.substring(index + 2);
 
798
      } else {
 
799
        string = "";
 
800
      }
 
801
    }
 
802
    newStringBuffer.append(string);
 
803
    
 
804
    return newStringBuffer.toString();
 
805
  }
 
806
 
 
807
  /**
 
808
   * Returns the secondary set of options (if any) contained in
 
809
   * the supplied options array. The secondary set is defined to
 
810
   * be any options after the first "--". These options are removed from
 
811
   * the original options array.
 
812
   *
 
813
   * @param options the input array of options
 
814
   * @return the array of secondary options
 
815
   */
 
816
  public static String[] partitionOptions(String[] options) {
 
817
 
 
818
    for (int i = 0; i < options.length; i++) {
 
819
      if (options[i].equals("--")) {
 
820
        options[i++] = "";
 
821
        String[] result = new String [options.length - i];
 
822
        for (int j = i; j < options.length; j++) {
 
823
          result[j - i] = options[j];
 
824
          options[j] = "";
 
825
        }
 
826
        return result;
 
827
      }
 
828
    }
 
829
    return new String [0];
 
830
  }
 
831
    
 
832
  /**
 
833
   * The inverse operation of backQuoteChars().
 
834
   * Converts back-quoted carriage returns and new lines in a string 
 
835
   * to the corresponding character ('\r' and '\n').
 
836
   * Also "un"-back-quotes the following characters: ` " \ \t and %
 
837
   *
 
838
   * @param string      the string
 
839
   * @return            the converted string
 
840
   * @see               #backQuoteChars(String)
 
841
   */
 
842
  public static String unbackQuoteChars(String string) {
 
843
 
 
844
    int index;
 
845
    StringBuffer newStringBuffer;
 
846
    
 
847
    // replace each of the following characters with the backquoted version
 
848
    String charsFind[]    = {"\\\\", "\\'", "\\t", "\\n", "\\r", "\\\"", "\\%"};
 
849
    char   charsReplace[] = {'\\',   '\'',  '\t',  '\n',  '\r',  '"',    '%'};
 
850
    int pos[] = new int[charsFind.length];
 
851
    int curPos;
 
852
    
 
853
    String str = new String(string);
 
854
    newStringBuffer = new StringBuffer();
 
855
    while (str.length() > 0) {
 
856
      // get positions and closest character to replace
 
857
      curPos = str.length();
 
858
      index  = -1;
 
859
      for (int i = 0; i < pos.length; i++) {
 
860
        pos[i] = str.indexOf(charsFind[i]);
 
861
        if ( (pos[i] > -1) && (pos[i] < curPos) ) {
 
862
          index  = i;
 
863
          curPos = pos[i];
 
864
        }
 
865
      }
 
866
      
 
867
      // replace character if found, otherwise finished
 
868
      if (index == -1) {
 
869
        newStringBuffer.append(str);
 
870
        str = "";
 
871
      }
 
872
      else {
 
873
        newStringBuffer.append(str.substring(0, pos[index]));
 
874
        newStringBuffer.append(charsReplace[index]);
 
875
        str = str.substring(pos[index] + charsFind[index].length());
 
876
      }
 
877
    }
 
878
 
 
879
    return newStringBuffer.toString();
 
880
  }    
 
881
  
 
882
  /**
 
883
   * Split up a string containing options into an array of strings,
 
884
   * one for each option.
 
885
   *
 
886
   * @param             quotedOptionString the string containing the options
 
887
   * @return            the array of options
 
888
   * @throws Exception  in case of an unterminated string, unknown character or
 
889
   *                    a parse error
 
890
   */
 
891
  public static String[] splitOptions(String quotedOptionString) throws Exception{
 
892
 
 
893
    FastVector optionsVec = new FastVector();
 
894
    String str = new String(quotedOptionString);
 
895
    int i;
 
896
    
 
897
    while (true){
 
898
 
 
899
      //trimLeft 
 
900
      i = 0;
 
901
      while ((i < str.length()) && (Character.isWhitespace(str.charAt(i)))) i++;
 
902
      str = str.substring(i);
 
903
      
 
904
      //stop when str is empty
 
905
      if (str.length() == 0) break;
 
906
      
 
907
      //if str start with a double quote
 
908
      if (str.charAt(0) == '"'){
 
909
        
 
910
        //find the first not anti-slached double quote
 
911
        i = 1;
 
912
        while(i < str.length()){
 
913
          if (str.charAt(i) == str.charAt(0)) break;
 
914
          if (str.charAt(i) == '\\'){
 
915
            i += 1;
 
916
            if (i >= str.length()) 
 
917
              throw new Exception("String should not finish with \\");
 
918
          }
 
919
          i += 1;
 
920
        }
 
921
        if (i >= str.length()) throw new Exception("Quote parse error.");
 
922
        
 
923
        //add the founded string to the option vector (without quotes)
 
924
        String optStr = str.substring(1,i);
 
925
        optStr = unbackQuoteChars(optStr);
 
926
        optionsVec.addElement(optStr);
 
927
        str = str.substring(i+1);
 
928
      } else {
 
929
        //find first whiteSpace
 
930
        i=0;
 
931
        while((i < str.length()) && (!Character.isWhitespace(str.charAt(i)))) i++;
 
932
        
 
933
        //add the founded string to the option vector
 
934
        String optStr = str.substring(0,i);
 
935
        optionsVec.addElement(optStr);
 
936
        str = str.substring(i);
 
937
      }
 
938
    }
 
939
    
 
940
    //convert optionsVec to an array of String
 
941
    String[] options = new String[optionsVec.size()];
 
942
    for (i = 0; i < optionsVec.size(); i++) {
 
943
      options[i] = (String)optionsVec.elementAt(i);
 
944
    }
 
945
    return options;
 
946
  }    
 
947
 
 
948
  /**
 
949
   * Joins all the options in an option array into a single string,
 
950
   * as might be used on the command line.
 
951
   *
 
952
   * @param optionArray the array of options
 
953
   * @return the string containing all options.
 
954
   */
 
955
  public static String joinOptions(String[] optionArray) {
 
956
 
 
957
    String optionString = "";
 
958
    for (int i = 0; i < optionArray.length; i++) {
 
959
      if (optionArray[i].equals("")) {
 
960
        continue;
 
961
      }
 
962
      boolean escape = false;
 
963
      for (int n = 0; n < optionArray[i].length(); n++) {
 
964
        if (Character.isWhitespace(optionArray[i].charAt(n))) {
 
965
          escape = true;
 
966
          break;
 
967
        }
 
968
      }
 
969
      if (escape) {
 
970
        optionString += '"' + backQuoteChars(optionArray[i]) + '"';
 
971
      } else {
 
972
        optionString += optionArray[i];
 
973
      }
 
974
      optionString += " ";
 
975
    }
 
976
    return optionString.trim();
 
977
  }
 
978
  
 
979
  /**
 
980
   * Creates a new instance of an object given it's class name and
 
981
   * (optional) arguments to pass to it's setOptions method. If the
 
982
   * object implements OptionHandler and the options parameter is
 
983
   * non-null, the object will have it's options set. Example use:<p>
 
984
   *
 
985
   * <code> <pre>
 
986
   * String classifierName = Utils.getOption('W', options);
 
987
   * Classifier c = (Classifier)Utils.forName(Classifier.class,
 
988
   *                                          classifierName,
 
989
   *                                          options);
 
990
   * setClassifier(c);
 
991
   * </pre></code>
 
992
   *
 
993
   * @param classType the class that the instantiated object should
 
994
   * be assignable to -- an exception is thrown if this is not the case
 
995
   * @param className the fully qualified class name of the object
 
996
   * @param options an array of options suitable for passing to setOptions. May
 
997
   * be null. Any options accepted by the object will be removed from the
 
998
   * array.
 
999
   * @return the newly created object, ready for use.
 
1000
   * @exception Exception if the class name is invalid, or if the
 
1001
   * class is not assignable to the desired class type, or the options
 
1002
   * supplied are not acceptable to the object
 
1003
   */
 
1004
  public static Object forName(Class classType,
 
1005
                               String className,
 
1006
                               String[] options) throws Exception {
 
1007
 
 
1008
    Class c = null;
 
1009
    try {
 
1010
      c = Class.forName(className);
 
1011
    } catch (Exception ex) {
 
1012
      throw new Exception("Can't find class called: " + className);
 
1013
    }
 
1014
    if (!classType.isAssignableFrom(c)) {
 
1015
      throw new Exception(classType.getName() + " is not assignable from "
 
1016
                          + className);
 
1017
    }
 
1018
    Object o = c.newInstance();
 
1019
    if ((o instanceof OptionHandler)
 
1020
        && (options != null)) {
 
1021
      ((OptionHandler)o).setOptions(options);
 
1022
      Utils.checkForRemainingOptions(options);
 
1023
    }
 
1024
    return o;
 
1025
  }
 
1026
 
 
1027
  /**
 
1028
   * Computes entropy for an array of integers.
 
1029
   *
 
1030
   * @param counts array of counts
 
1031
   * @return - a log2 a - b log2 b - c log2 c + (a+b+c) log2 (a+b+c)
 
1032
   * when given array [a b c]
 
1033
   */
 
1034
  public static /*@pure@*/ double info(int counts[]) {
 
1035
    
 
1036
    int total = 0;
 
1037
    double x = 0;
 
1038
    for (int j = 0; j < counts.length; j++) {
 
1039
      x -= xlogx(counts[j]);
 
1040
      total += counts[j];
 
1041
    }
 
1042
    return x + xlogx(total);
 
1043
  }
 
1044
 
 
1045
  /**
 
1046
   * Tests if a is smaller or equal to b.
 
1047
   *
 
1048
   * @param a a double
 
1049
   * @param b a double
 
1050
   */
 
1051
  public static /*@pure@*/ boolean smOrEq(double a,double b) {
 
1052
    
 
1053
    return (a-b < SMALL);
 
1054
  }
 
1055
 
 
1056
  /**
 
1057
   * Tests if a is greater or equal to b.
 
1058
   *
 
1059
   * @param a a double
 
1060
   * @param b a double
 
1061
   */
 
1062
  public static /*@pure@*/ boolean grOrEq(double a,double b) {
 
1063
    
 
1064
    return (b-a < SMALL);
 
1065
  }
 
1066
  
 
1067
  /**
 
1068
   * Tests if a is smaller than b.
 
1069
   *
 
1070
   * @param a a double
 
1071
   * @param b a double
 
1072
   */
 
1073
  public static /*@pure@*/ boolean sm(double a,double b) {
 
1074
    
 
1075
    return (b-a > SMALL);
 
1076
  }
 
1077
 
 
1078
  /**
 
1079
   * Tests if a is greater than b.
 
1080
   *
 
1081
   * @param a a double
 
1082
   * @param b a double 
 
1083
   */
 
1084
  public static /*@pure@*/ boolean gr(double a,double b) {
 
1085
    
 
1086
    return (a-b > SMALL);
 
1087
  }
 
1088
 
 
1089
  /**
 
1090
   * Returns the kth-smallest value in the array.
 
1091
   *
 
1092
   * @param array the array of integers
 
1093
   * @param k the value of k
 
1094
   * @return the kth-smallest value
 
1095
   */
 
1096
  public static double kthSmallestValue(int[] array, int k) {
 
1097
 
 
1098
    int[] index = new int[array.length];
 
1099
    
 
1100
    for (int i = 0; i < index.length; i++) {
 
1101
      index[i] = i;
 
1102
    }
 
1103
 
 
1104
    return array[index[select(array, index, 0, array.length - 1, k)]];
 
1105
  }
 
1106
 
 
1107
  /**
 
1108
   * Returns the kth-smallest value in the array
 
1109
   *
 
1110
   * @param array the array of double
 
1111
   * @param k the value of k
 
1112
   * @return the kth-smallest value
 
1113
   */
 
1114
  public static double kthSmallestValue(double[] array, int k) {
 
1115
 
 
1116
    int[] index = new int[array.length];
 
1117
    
 
1118
    for (int i = 0; i < index.length; i++) {
 
1119
      index[i] = i;
 
1120
    }
 
1121
 
 
1122
    return array[index[select(array, index, 0, array.length - 1, k)]];
 
1123
  }
 
1124
 
 
1125
  /**
 
1126
   * Returns the logarithm of a for base 2.
 
1127
   *
 
1128
   * @param a   a double
 
1129
   * @return    the logarithm for base 2
 
1130
   */
 
1131
  public static /*@pure@*/ double log2(double a) {
 
1132
    
 
1133
    return Math.log(a) / log2;
 
1134
  }
 
1135
 
 
1136
  /**
 
1137
   * Returns index of maximum element in a given
 
1138
   * array of doubles. First maximum is returned.
 
1139
   *
 
1140
   * @param doubles the array of doubles
 
1141
   * @return the index of the maximum element
 
1142
   */
 
1143
  public static /*@pure@*/ int maxIndex(double[] doubles) {
 
1144
 
 
1145
    double maximum = 0;
 
1146
    int maxIndex = 0;
 
1147
 
 
1148
    for (int i = 0; i < doubles.length; i++) {
 
1149
      if ((i == 0) || (doubles[i] > maximum)) {
 
1150
        maxIndex = i;
 
1151
        maximum = doubles[i];
 
1152
      }
 
1153
    }
 
1154
 
 
1155
    return maxIndex;
 
1156
  }
 
1157
 
 
1158
  /**
 
1159
   * Returns index of maximum element in a given
 
1160
   * array of integers. First maximum is returned.
 
1161
   *
 
1162
   * @param ints the array of integers
 
1163
   * @return the index of the maximum element
 
1164
   */
 
1165
  public static /*@pure@*/ int maxIndex(int[] ints) {
 
1166
 
 
1167
    int maximum = 0;
 
1168
    int maxIndex = 0;
 
1169
 
 
1170
    for (int i = 0; i < ints.length; i++) {
 
1171
      if ((i == 0) || (ints[i] > maximum)) {
 
1172
        maxIndex = i;
 
1173
        maximum = ints[i];
 
1174
      }
 
1175
    }
 
1176
 
 
1177
    return maxIndex;
 
1178
  }
 
1179
 
 
1180
  /**
 
1181
   * Computes the mean for an array of doubles.
 
1182
   *
 
1183
   * @param vector the array
 
1184
   * @return the mean
 
1185
   */
 
1186
  public static /*@pure@*/ double mean(double[] vector) {
 
1187
  
 
1188
    double sum = 0;
 
1189
 
 
1190
    if (vector.length == 0) {
 
1191
      return 0;
 
1192
    }
 
1193
    for (int i = 0; i < vector.length; i++) {
 
1194
      sum += vector[i];
 
1195
    }
 
1196
    return sum / (double) vector.length;
 
1197
  }
 
1198
 
 
1199
  /**
 
1200
   * Returns index of minimum element in a given
 
1201
   * array of integers. First minimum is returned.
 
1202
   *
 
1203
   * @param ints the array of integers
 
1204
   * @return the index of the minimum element
 
1205
   */
 
1206
  public static /*@pure@*/ int minIndex(int[] ints) {
 
1207
 
 
1208
    int minimum = 0;
 
1209
    int minIndex = 0;
 
1210
 
 
1211
    for (int i = 0; i < ints.length; i++) {
 
1212
      if ((i == 0) || (ints[i] < minimum)) {
 
1213
        minIndex = i;
 
1214
        minimum = ints[i];
 
1215
      }
 
1216
    }
 
1217
 
 
1218
    return minIndex;
 
1219
  }
 
1220
 
 
1221
  /**
 
1222
   * Returns index of minimum element in a given
 
1223
   * array of doubles. First minimum is returned.
 
1224
   *
 
1225
   * @param doubles the array of doubles
 
1226
   * @return the index of the minimum element
 
1227
   */
 
1228
  public static /*@pure@*/ int minIndex(double[] doubles) {
 
1229
 
 
1230
    double minimum = 0;
 
1231
    int minIndex = 0;
 
1232
 
 
1233
    for (int i = 0; i < doubles.length; i++) {
 
1234
      if ((i == 0) || (doubles[i] < minimum)) {
 
1235
        minIndex = i;
 
1236
        minimum = doubles[i];
 
1237
      }
 
1238
    }
 
1239
 
 
1240
    return minIndex;
 
1241
  }
 
1242
 
 
1243
  /**
 
1244
   * Normalizes the doubles in the array by their sum.
 
1245
   *
 
1246
   * @param doubles the array of double
 
1247
   * @exception IllegalArgumentException if sum is Zero or NaN
 
1248
   */
 
1249
  public static void normalize(double[] doubles) {
 
1250
 
 
1251
    double sum = 0;
 
1252
    for (int i = 0; i < doubles.length; i++) {
 
1253
      sum += doubles[i];
 
1254
    }
 
1255
    normalize(doubles, sum);
 
1256
  }
 
1257
 
 
1258
  /**
 
1259
   * Normalizes the doubles in the array using the given value.
 
1260
   *
 
1261
   * @param doubles the array of double
 
1262
   * @param sum the value by which the doubles are to be normalized
 
1263
   * @exception IllegalArgumentException if sum is zero or NaN
 
1264
   */
 
1265
  public static void normalize(double[] doubles, double sum) {
 
1266
 
 
1267
    if (Double.isNaN(sum)) {
 
1268
      throw new IllegalArgumentException("Can't normalize array. Sum is NaN.");
 
1269
    }
 
1270
    if (sum == 0) {
 
1271
      // Maybe this should just be a return.
 
1272
      throw new IllegalArgumentException("Can't normalize array. Sum is zero.");
 
1273
    }
 
1274
    for (int i = 0; i < doubles.length; i++) {
 
1275
      doubles[i] /= sum;
 
1276
    }
 
1277
  }
 
1278
 
 
1279
  /**
 
1280
   * Converts an array containing the natural logarithms of
 
1281
   * probabilities stored in a vector back into probabilities.
 
1282
   * The probabilities are assumed to sum to one.
 
1283
   *
 
1284
   * @param a an array holding the natural logarithms of the probabilities
 
1285
   * @return the converted array 
 
1286
   */
 
1287
  public static double[] logs2probs(double[] a) {
 
1288
 
 
1289
    double max = a[maxIndex(a)];
 
1290
    double sum = 0.0;
 
1291
 
 
1292
    double[] result = new double[a.length];
 
1293
    for(int i = 0; i < a.length; i++) {
 
1294
      result[i] = Math.exp(a[i] - max);
 
1295
      sum += result[i];
 
1296
    }
 
1297
 
 
1298
    normalize(result, sum);
 
1299
 
 
1300
    return result;
 
1301
  } 
 
1302
 
 
1303
  /**
 
1304
   * Returns the log-odds for a given probabilitiy.
 
1305
   *
 
1306
   * @param prob the probabilitiy
 
1307
   *
 
1308
   * @return the log-odds after the probability has been mapped to
 
1309
   * [Utils.SMALL, 1-Utils.SMALL]
 
1310
   */
 
1311
  public static /*@pure@*/ double probToLogOdds(double prob) {
 
1312
 
 
1313
    if (gr(prob, 1) || (sm(prob, 0))) {
 
1314
      throw new IllegalArgumentException("probToLogOdds: probability must " +
 
1315
                                     "be in [0,1] "+prob);
 
1316
    }
 
1317
    double p = SMALL + (1.0 - 2 * SMALL) * prob;
 
1318
    return Math.log(p / (1 - p));
 
1319
  }
 
1320
 
 
1321
  /**
 
1322
   * Rounds a double to the next nearest integer value. The JDK version
 
1323
   * of it doesn't work properly.
 
1324
   *
 
1325
   * @param value the double value
 
1326
   * @return the resulting integer value
 
1327
   */
 
1328
  public static /*@pure@*/ int round(double value) {
 
1329
 
 
1330
    int roundedValue = value > 0
 
1331
      ? (int)(value + 0.5)
 
1332
      : -(int)(Math.abs(value) + 0.5);
 
1333
    
 
1334
    return roundedValue;
 
1335
  }
 
1336
 
 
1337
  /**
 
1338
   * Rounds a double to the next nearest integer value in a probabilistic
 
1339
   * fashion (e.g. 0.8 has a 20% chance of being rounded down to 0 and a
 
1340
   * 80% chance of being rounded up to 1). In the limit, the average of
 
1341
   * the rounded numbers generated by this procedure should converge to
 
1342
   * the original double.
 
1343
   *
 
1344
   * @param value the double value
 
1345
   * @param rand the random number generator
 
1346
   * @return the resulting integer value
 
1347
   */
 
1348
  public static int probRound(double value, Random rand) {
 
1349
 
 
1350
    if (value >= 0) {
 
1351
      double lower = Math.floor(value);
 
1352
      double prob = value - lower;
 
1353
      if (rand.nextDouble() < prob) {
 
1354
        return (int)lower + 1;
 
1355
      } else {
 
1356
        return (int)lower;
 
1357
      }
 
1358
    } else {
 
1359
      double lower = Math.floor(Math.abs(value));
 
1360
      double prob = Math.abs(value) - lower;
 
1361
      if (rand.nextDouble() < prob) {
 
1362
        return -((int)lower + 1);
 
1363
      } else {
 
1364
        return -(int)lower;
 
1365
      }
 
1366
    }
 
1367
  }
 
1368
 
 
1369
  /**
 
1370
   * Rounds a double to the given number of decimal places.
 
1371
   *
 
1372
   * @param value the double value
 
1373
   * @param afterDecimalPoint the number of digits after the decimal point
 
1374
   * @return the double rounded to the given precision
 
1375
   */
 
1376
  public static /*@pure@*/ double roundDouble(double value,int afterDecimalPoint) {
 
1377
 
 
1378
    double mask = Math.pow(10.0, (double)afterDecimalPoint);
 
1379
 
 
1380
    return (double)(Math.round(value * mask)) / mask;
 
1381
  }
 
1382
 
 
1383
  /**
 
1384
   * Sorts a given array of integers in ascending order and returns an 
 
1385
   * array of integers with the positions of the elements of the original 
 
1386
   * array in the sorted array. The sort is stable. (Equal elements remain
 
1387
   * in their original order.)
 
1388
   *
 
1389
   * @param array this array is not changed by the method!
 
1390
   * @return an array of integers with the positions in the sorted
 
1391
   * array.
 
1392
   */
 
1393
  public static /*@pure@*/ int[] sort(int[] array) {
 
1394
 
 
1395
    int[] index = new int[array.length];
 
1396
    int[] newIndex = new int[array.length];
 
1397
    int[] helpIndex;
 
1398
    int numEqual;
 
1399
    
 
1400
    for (int i = 0; i < index.length; i++) {
 
1401
      index[i] = i;
 
1402
    }
 
1403
    quickSort(array, index, 0, array.length - 1);
 
1404
 
 
1405
    // Make sort stable
 
1406
    int i = 0;
 
1407
    while (i < index.length) {
 
1408
      numEqual = 1;
 
1409
      for (int j = i + 1; ((j < index.length)
 
1410
                           && (array[index[i]] == array[index[j]]));
 
1411
           j++) {
 
1412
        numEqual++;
 
1413
      }
 
1414
      if (numEqual > 1) {
 
1415
        helpIndex = new int[numEqual];
 
1416
        for (int j = 0; j < numEqual; j++) {
 
1417
          helpIndex[j] = i + j;
 
1418
        }
 
1419
        quickSort(index, helpIndex, 0, numEqual - 1);
 
1420
        for (int j = 0; j < numEqual; j++) {
 
1421
          newIndex[i + j] = index[helpIndex[j]];
 
1422
        }
 
1423
        i += numEqual;
 
1424
      } else {
 
1425
        newIndex[i] = index[i];
 
1426
        i++;
 
1427
      }
 
1428
    }
 
1429
    return newIndex;
 
1430
  }
 
1431
 
 
1432
  /**
 
1433
   * Sorts a given array of doubles in ascending order and returns an
 
1434
   * array of integers with the positions of the elements of the
 
1435
   * original array in the sorted array. NOTE THESE CHANGES: the sort
 
1436
   * is no longer stable and it doesn't use safe floating-point
 
1437
   * comparisons anymore. Occurrences of Double.NaN are treated as 
 
1438
   * Double.MAX_VALUE
 
1439
   *
 
1440
   * @param array this array is not changed by the method!
 
1441
   * @return an array of integers with the positions in the sorted
 
1442
   * array.  
 
1443
   */
 
1444
  public static /*@pure@*/ int[] sort(/*@non_null@*/ double[] array) {
 
1445
 
 
1446
    int[] index = new int[array.length];
 
1447
    array = (double[])array.clone();
 
1448
    for (int i = 0; i < index.length; i++) {
 
1449
      index[i] = i;
 
1450
      if (Double.isNaN(array[i])) {
 
1451
        array[i] = Double.MAX_VALUE;
 
1452
      }
 
1453
    }
 
1454
    quickSort(array, index, 0, array.length - 1);
 
1455
    return index;
 
1456
  }
 
1457
 
 
1458
  /**
 
1459
   * Sorts a given array of doubles in ascending order and returns an 
 
1460
   * array of integers with the positions of the elements of the original 
 
1461
   * array in the sorted array. The sort is stable (Equal elements remain
 
1462
   * in their original order.) Occurrences of Double.NaN are treated as 
 
1463
   * Double.MAX_VALUE
 
1464
   *
 
1465
   * @param array this array is not changed by the method!
 
1466
   * @return an array of integers with the positions in the sorted
 
1467
   * array.
 
1468
   */
 
1469
  public static /*@pure@*/ int[] stableSort(double[] array){
 
1470
 
 
1471
    int[] index = new int[array.length];
 
1472
    int[] newIndex = new int[array.length];
 
1473
    int[] helpIndex;
 
1474
    int numEqual;
 
1475
    
 
1476
    array = (double[])array.clone();
 
1477
    for (int i = 0; i < index.length; i++) {
 
1478
      index[i] = i;
 
1479
      if (Double.isNaN(array[i])) {
 
1480
        array[i] = Double.MAX_VALUE;
 
1481
      }
 
1482
    }
 
1483
    quickSort(array,index,0,array.length-1);
 
1484
 
 
1485
    // Make sort stable
 
1486
 
 
1487
    int i = 0;
 
1488
    while (i < index.length) {
 
1489
      numEqual = 1;
 
1490
      for (int j = i+1; ((j < index.length) && Utils.eq(array[index[i]],
 
1491
                                                        array[index[j]])); j++)
 
1492
        numEqual++;
 
1493
      if (numEqual > 1) {
 
1494
        helpIndex = new int[numEqual];
 
1495
        for (int j = 0; j < numEqual; j++)
 
1496
          helpIndex[j] = i+j;
 
1497
        quickSort(index, helpIndex, 0, numEqual-1);
 
1498
        for (int j = 0; j < numEqual; j++) 
 
1499
          newIndex[i+j] = index[helpIndex[j]];
 
1500
        i += numEqual;
 
1501
      } else {
 
1502
        newIndex[i] = index[i];
 
1503
        i++;
 
1504
      }
 
1505
    }
 
1506
 
 
1507
    return newIndex;
 
1508
  }
 
1509
 
 
1510
  /**
 
1511
   * Computes the variance for an array of doubles.
 
1512
   *
 
1513
   * @param vector the array
 
1514
   * @return the variance
 
1515
   */
 
1516
  public static /*@pure@*/ double variance(double[] vector) {
 
1517
  
 
1518
    double sum = 0, sumSquared = 0;
 
1519
 
 
1520
    if (vector.length <= 1) {
 
1521
      return 0;
 
1522
    }
 
1523
    for (int i = 0; i < vector.length; i++) {
 
1524
      sum += vector[i];
 
1525
      sumSquared += (vector[i] * vector[i]);
 
1526
    }
 
1527
    double result = (sumSquared - (sum * sum / (double) vector.length)) / 
 
1528
      (double) (vector.length - 1);
 
1529
 
 
1530
    // We don't like negative variance
 
1531
    if (result < 0) {
 
1532
      return 0;
 
1533
    } else {
 
1534
      return result;
 
1535
    }
 
1536
  }
 
1537
 
 
1538
  /**
 
1539
   * Computes the sum of the elements of an array of doubles.
 
1540
   *
 
1541
   * @param doubles the array of double
 
1542
   * @return the sum of the elements
 
1543
   */
 
1544
  public static /*@pure@*/ double sum(double[] doubles) {
 
1545
 
 
1546
    double sum = 0;
 
1547
 
 
1548
    for (int i = 0; i < doubles.length; i++) {
 
1549
      sum += doubles[i];
 
1550
    }
 
1551
    return sum;
 
1552
  }
 
1553
 
 
1554
  /**
 
1555
   * Computes the sum of the elements of an array of integers.
 
1556
   *
 
1557
   * @param ints the array of integers
 
1558
   * @return the sum of the elements
 
1559
   */
 
1560
  public static /*@pure@*/ int sum(int[] ints) {
 
1561
 
 
1562
    int sum = 0;
 
1563
 
 
1564
    for (int i = 0; i < ints.length; i++) {
 
1565
      sum += ints[i];
 
1566
    }
 
1567
    return sum;
 
1568
  }
 
1569
 
 
1570
  /**
 
1571
   * Returns c*log2(c) for a given integer value c.
 
1572
   *
 
1573
   * @param c an integer value
 
1574
   * @return c*log2(c) (but is careful to return 0 if c is 0)
 
1575
   */
 
1576
  public static /*@pure@*/ double xlogx(int c) {
 
1577
    
 
1578
    if (c == 0) {
 
1579
      return 0.0;
 
1580
    }
 
1581
    return c * Utils.log2((double) c);
 
1582
  }
 
1583
 
 
1584
  /**
 
1585
   * Partitions the instances around a pivot. Used by quicksort and
 
1586
   * kthSmallestValue.
 
1587
   *
 
1588
   * @param array the array of doubles to be sorted
 
1589
   * @param index the index into the array of doubles
 
1590
   * @param l the first index of the subset 
 
1591
   * @param r the last index of the subset 
 
1592
   *
 
1593
   * @return the index of the middle element
 
1594
   */
 
1595
  private static int partition(double[] array, int[] index, int l, int r) {
 
1596
    
 
1597
    double pivot = array[index[(l + r) / 2]];
 
1598
    int help;
 
1599
 
 
1600
    while (l < r) {
 
1601
      while ((array[index[l]] < pivot) && (l < r)) {
 
1602
        l++;
 
1603
      }
 
1604
      while ((array[index[r]] > pivot) && (l < r)) {
 
1605
        r--;
 
1606
      }
 
1607
      if (l < r) {
 
1608
        help = index[l];
 
1609
        index[l] = index[r];
 
1610
        index[r] = help;
 
1611
        l++;
 
1612
        r--;
 
1613
      }
 
1614
    }
 
1615
    if ((l == r) && (array[index[r]] > pivot)) {
 
1616
      r--;
 
1617
    } 
 
1618
 
 
1619
    return r;
 
1620
  }
 
1621
 
 
1622
  /**
 
1623
   * Partitions the instances around a pivot. Used by quicksort and
 
1624
   * kthSmallestValue.
 
1625
   *
 
1626
   * @param array the array of integers to be sorted
 
1627
   * @param index the index into the array of integers
 
1628
   * @param l the first index of the subset 
 
1629
   * @param r the last index of the subset 
 
1630
   *
 
1631
   * @return the index of the middle element
 
1632
   */
 
1633
  private static int partition(int[] array, int[] index, int l, int r) {
 
1634
    
 
1635
    double pivot = array[index[(l + r) / 2]];
 
1636
    int help;
 
1637
 
 
1638
    while (l < r) {
 
1639
      while ((array[index[l]] < pivot) && (l < r)) {
 
1640
        l++;
 
1641
      }
 
1642
      while ((array[index[r]] > pivot) && (l < r)) {
 
1643
        r--;
 
1644
      }
 
1645
      if (l < r) {
 
1646
        help = index[l];
 
1647
        index[l] = index[r];
 
1648
        index[r] = help;
 
1649
        l++;
 
1650
        r--;
 
1651
      }
 
1652
    }
 
1653
    if ((l == r) && (array[index[r]] > pivot)) {
 
1654
      r--;
 
1655
    } 
 
1656
 
 
1657
    return r;
 
1658
  }
 
1659
  
 
1660
  /**
 
1661
   * Implements quicksort according to Manber's "Introduction to
 
1662
   * Algorithms".
 
1663
   *
 
1664
   * @param array the array of doubles to be sorted
 
1665
   * @param index the index into the array of doubles
 
1666
   * @param left the first index of the subset to be sorted
 
1667
   * @param right the last index of the subset to be sorted
 
1668
   */
 
1669
  //@ requires 0 <= first && first <= right && right < array.length;
 
1670
  //@ requires (\forall int i; 0 <= i && i < index.length; 0 <= index[i] && index[i] < array.length);
 
1671
  //@ requires array != index;
 
1672
  //  assignable index;
 
1673
  private static void quickSort(/*@non_null@*/ double[] array, /*@non_null@*/ int[] index, 
 
1674
                                int left, int right) {
 
1675
 
 
1676
    if (left < right) {
 
1677
      int middle = partition(array, index, left, right);
 
1678
      quickSort(array, index, left, middle);
 
1679
      quickSort(array, index, middle + 1, right);
 
1680
    }
 
1681
  }
 
1682
  
 
1683
  /**
 
1684
   * Implements quicksort according to Manber's "Introduction to
 
1685
   * Algorithms".
 
1686
   *
 
1687
   * @param array the array of integers to be sorted
 
1688
   * @param index the index into the array of integers
 
1689
   * @param left the first index of the subset to be sorted
 
1690
   * @param right the last index of the subset to be sorted
 
1691
   */
 
1692
  //@ requires 0 <= first && first <= right && right < array.length;
 
1693
  //@ requires (\forall int i; 0 <= i && i < index.length; 0 <= index[i] && index[i] < array.length);
 
1694
  //@ requires array != index;
 
1695
  //  assignable index;
 
1696
  private static void quickSort(/*@non_null@*/ int[] array, /*@non_null@*/  int[] index, 
 
1697
                                int left, int right) {
 
1698
 
 
1699
    if (left < right) {
 
1700
      int middle = partition(array, index, left, right);
 
1701
      quickSort(array, index, left, middle);
 
1702
      quickSort(array, index, middle + 1, right);
 
1703
    }
 
1704
  }
 
1705
  
 
1706
  /**
 
1707
   * Implements computation of the kth-smallest element according
 
1708
   * to Manber's "Introduction to Algorithms".
 
1709
   *
 
1710
   * @param array the array of double
 
1711
   * @param index the index into the array of doubles
 
1712
   * @param left the first index of the subset 
 
1713
   * @param right the last index of the subset 
 
1714
   * @param k the value of k
 
1715
   *
 
1716
   * @return the index of the kth-smallest element
 
1717
   */
 
1718
  //@ requires 0 <= first && first <= right && right < array.length;
 
1719
  private static int select(/*@non_null@*/ double[] array, /*@non_null@*/ int[] index, 
 
1720
                            int left, int right, int k) {
 
1721
    
 
1722
    if (left == right) {
 
1723
      return left;
 
1724
    } else {
 
1725
      int middle = partition(array, index, left, right);
 
1726
      if ((middle - left + 1) >= k) {
 
1727
        return select(array, index, left, middle, k);
 
1728
      } else {
 
1729
        return select(array, index, middle + 1, right, k - (middle - left + 1));
 
1730
      }
 
1731
    }
 
1732
  }
 
1733
  
 
1734
  /**
 
1735
   * Implements computation of the kth-smallest element according
 
1736
   * to Manber's "Introduction to Algorithms".
 
1737
   *
 
1738
   * @param array the array of integers
 
1739
   * @param index the index into the array of integers
 
1740
   * @param left the first index of the subset 
 
1741
   * @param right the last index of the subset 
 
1742
   * @param k the value of k
 
1743
   *
 
1744
   * @return the index of the kth-smallest element
 
1745
   */
 
1746
  //@ requires 0 <= first && first <= right && right < array.length;
 
1747
  private static int select(/*@non_null@*/ int[] array, /*@non_null@*/ int[] index, 
 
1748
                            int left, int right, int k) {
 
1749
    
 
1750
    if (left == right) {
 
1751
      return left;
 
1752
    } else {
 
1753
      int middle = partition(array, index, left, right);
 
1754
      if ((middle - left + 1) >= k) {
 
1755
        return select(array, index, left, middle, k);
 
1756
      } else {
 
1757
        return select(array, index, middle + 1, right, k - (middle - left + 1));
 
1758
      }
 
1759
    }
 
1760
  }
 
1761
 
 
1762
  /**
 
1763
   * Main method for testing this class.
 
1764
   *
 
1765
   * @param ops some dummy options
 
1766
   */
 
1767
  public static void main(String[] ops) {
 
1768
 
 
1769
    double[] doublesWithNaN = {4.5, 6.7, Double.NaN, 3.4, 4.8, 1.2, 3.4};
 
1770
    double[] doubles = {4.5, 6.7, 6.7, 3.4, 4.8, 1.2, 3.4, 6.7, 6.7, 3.4};
 
1771
    int[] ints = {12, 6, 2, 18, 16, 6, 7, 5, 18, 18, 17};
 
1772
 
 
1773
    try {
 
1774
 
 
1775
      // Option handling
 
1776
      System.out.println("First option split up:");
 
1777
      if (ops.length > 0) {
 
1778
        String[] firstOptionSplitUp = Utils.splitOptions(ops[0]);
 
1779
        for (int i = 0; i < firstOptionSplitUp.length; i ++) {
 
1780
          System.out.println(firstOptionSplitUp[i]);
 
1781
        }
 
1782
      }                                        
 
1783
      System.out.println("Partitioned options: ");
 
1784
      String[] partitionedOptions = Utils.partitionOptions(ops);
 
1785
      for (int i  = 0; i < partitionedOptions.length; i++) {
 
1786
        System.out.println(partitionedOptions[i]);
 
1787
      }
 
1788
      System.out.println("Get position of flag -f: " + Utils.getOptionPos('f', ops));
 
1789
      System.out.println("Get flag -f: " + Utils.getFlag('f', ops));
 
1790
      System.out.println("Get position of option -o: " + Utils.getOptionPos('o', ops));
 
1791
      System.out.println("Get option -o: " + Utils.getOption('o', ops));
 
1792
      System.out.println("Checking for remaining options... ");
 
1793
      Utils.checkForRemainingOptions(ops);
 
1794
      
 
1795
      // Statistics
 
1796
      System.out.println("Original array with NaN (doubles): ");
 
1797
      for (int i = 0; i < doublesWithNaN.length; i++) {
 
1798
        System.out.print(doublesWithNaN[i] + " ");
 
1799
      }
 
1800
      System.out.println();
 
1801
      System.out.println("Original array (doubles): ");
 
1802
      for (int i = 0; i < doubles.length; i++) {
 
1803
        System.out.print(doubles[i] + " ");
 
1804
      }
 
1805
      System.out.println();
 
1806
      System.out.println("Original array (ints): ");
 
1807
      for (int i = 0; i < ints.length; i++) {
 
1808
        System.out.print(ints[i] + " ");
 
1809
      }
 
1810
      System.out.println();
 
1811
      System.out.println("Correlation: " + Utils.correlation(doubles, doubles, 
 
1812
                                                             doubles.length));
 
1813
      System.out.println("Mean: " + Utils.mean(doubles));
 
1814
      System.out.println("Variance: " + Utils.variance(doubles));
 
1815
      System.out.println("Sum (doubles): " + Utils.sum(doubles));
 
1816
      System.out.println("Sum (ints): " + Utils.sum(ints));
 
1817
      System.out.println("Max index (doubles): " + Utils.maxIndex(doubles));
 
1818
      System.out.println("Max index (ints): " + Utils.maxIndex(ints));
 
1819
      System.out.println("Min index (doubles): " + Utils.minIndex(doubles));
 
1820
      System.out.println("Min index (ints): " + Utils.minIndex(ints));
 
1821
      System.out.println("Median (doubles): " + 
 
1822
                         Utils.kthSmallestValue(doubles, doubles.length / 2));
 
1823
      System.out.println("Median (ints): " + 
 
1824
                         Utils.kthSmallestValue(ints, ints.length / 2));
 
1825
 
 
1826
      // Sorting and normalizing
 
1827
      System.out.println("Sorted array with NaN (doubles): ");
 
1828
      int[] sorted = Utils.sort(doublesWithNaN);
 
1829
      for (int i = 0; i < doublesWithNaN.length; i++) {
 
1830
        System.out.print(doublesWithNaN[sorted[i]] + " ");
 
1831
      }
 
1832
      System.out.println();
 
1833
      System.out.println("Sorted array (doubles): ");
 
1834
      sorted = Utils.sort(doubles);
 
1835
      for (int i = 0; i < doubles.length; i++) {
 
1836
        System.out.print(doubles[sorted[i]] + " ");
 
1837
      }
 
1838
      System.out.println();
 
1839
      System.out.println("Sorted array (ints): ");
 
1840
      sorted = Utils.sort(ints);
 
1841
      for (int i = 0; i < ints.length; i++) {
 
1842
        System.out.print(ints[sorted[i]] + " ");
 
1843
      }
 
1844
      System.out.println();
 
1845
      System.out.println("Indices from stable sort (doubles): ");
 
1846
      sorted = Utils.stableSort(doubles);
 
1847
      for (int i = 0; i < doubles.length; i++) {
 
1848
        System.out.print(sorted[i] + " ");
 
1849
      }
 
1850
      System.out.println();
 
1851
      System.out.println("Indices from sort (ints): ");
 
1852
      sorted = Utils.sort(ints);
 
1853
      for (int i = 0; i < ints.length; i++) {
 
1854
        System.out.print(sorted[i] + " ");
 
1855
      }
 
1856
      System.out.println();
 
1857
      System.out.println("Normalized array (doubles): ");
 
1858
      Utils.normalize(doubles);
 
1859
      for (int i = 0; i < doubles.length; i++) {
 
1860
        System.out.print(doubles[i] + " ");
 
1861
      }
 
1862
      System.out.println();
 
1863
      System.out.println("Normalized again (doubles): ");
 
1864
      Utils.normalize(doubles, Utils.sum(doubles));
 
1865
      for (int i = 0; i < doubles.length; i++) {
 
1866
        System.out.print(doubles[i] + " ");
 
1867
      }
 
1868
      System.out.println();
 
1869
      
 
1870
      // Pretty-printing
 
1871
      System.out.println("-4.58: " + Utils.doubleToString(-4.57826535, 2));
 
1872
      System.out.println("-6.78: " + Utils.doubleToString(-6.78214234, 6,2));
 
1873
      
 
1874
      // Comparisons
 
1875
      System.out.println("5.70001 == 5.7 ? " + Utils.eq(5.70001, 5.7));
 
1876
      System.out.println("5.70001 > 5.7 ? " + Utils.gr(5.70001, 5.7));
 
1877
      System.out.println("5.70001 >= 5.7 ? " + Utils.grOrEq(5.70001, 5.7));
 
1878
      System.out.println("5.7 < 5.70001 ? " + Utils.sm(5.7, 5.70001));
 
1879
      System.out.println("5.7 <= 5.70001 ? " + Utils.smOrEq(5.7, 5.70001));
 
1880
      
 
1881
      // Math
 
1882
      System.out.println("Info (ints): " + Utils.info(ints));
 
1883
      System.out.println("log2(4.6): " + Utils.log2(4.6));
 
1884
      System.out.println("5 * log(5): " + Utils.xlogx(5));
 
1885
      System.out.println("5.5 rounded: " + Utils.round(5.5));
 
1886
      System.out.println("5.55555 rounded to 2 decimal places: " + 
 
1887
                         Utils.roundDouble(5.55555, 2));
 
1888
      
 
1889
      // Arrays
 
1890
      System.out.println("Array-Dimensions of 'new int[][]': " + Utils.getArrayDimensions(new int[][]{}));
 
1891
      System.out.println("Array-Dimensions of 'new int[][]{{1,2,3},{4,5,6}}': " + Utils.getArrayDimensions(new int[][]{{1,2,3},{4,5,6}}));
 
1892
      String[][][] s = new String[3][4][];
 
1893
      System.out.println("Array-Dimensions of 'new String[3][4][]': " + Utils.getArrayDimensions(s));
 
1894
    } catch (Exception e) {
 
1895
      e.printStackTrace();
 
1896
    }
 
1897
  }
 
1898
}
 
1899