001: /*
002: * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences.
003: * Copyright (C) 2006 - JScience (http://jscience.org/)
004: * All rights reserved.
005: *
006: * Permission to use, copy, modify, and distribute this software is
007: * freely granted, provided that this notice is preserved.
008: */
009: package org.jscience;
010:
011: import java.math.BigInteger;
012: import java.util.Date;
013: import java.util.Random;
014:
015: import javax.measure.quantity.*;
016: import javax.measure.unit.*;
017:
018: import org.jscience.economics.money.Currency;
019: import org.jscience.economics.money.Money;
020: import org.jscience.geography.coordinates.Altitude;
021: import org.jscience.geography.coordinates.CompoundCoordinates;
022: import org.jscience.geography.coordinates.LatLong;
023: import org.jscience.geography.coordinates.Time;
024: import org.jscience.geography.coordinates.UTM;
025: import org.jscience.geography.coordinates.XYZ;
026: import org.jscience.geography.coordinates.crs.CoordinatesConverter;
027: import org.jscience.mathematics.function.Polynomial;
028: import org.jscience.mathematics.function.Variable;
029: import org.jscience.mathematics.number.Complex;
030: import org.jscience.mathematics.number.Float64;
031: import org.jscience.mathematics.number.LargeInteger;
032: import org.jscience.mathematics.number.ModuloInteger;
033: import org.jscience.mathematics.number.Rational;
034: import org.jscience.mathematics.number.Real;
035: import org.jscience.mathematics.vector.ComplexMatrix;
036: import org.jscience.mathematics.vector.DenseMatrix;
037: import org.jscience.mathematics.vector.DenseVector;
038: import org.jscience.mathematics.vector.Float64Matrix;
039: import org.jscience.mathematics.vector.Matrix;
040: import org.jscience.mathematics.vector.Vector;
041: import org.jscience.physics.amount.Amount;
042: import org.jscience.physics.amount.AmountFormat;
043: import org.jscience.physics.model.RelativisticModel;
044:
045: import javolution.lang.Configurable;
046: import javolution.lang.MathLib;
047: import javolution.text.TextBuilder;
048: import javolution.context.ConcurrentContext;
049: import javolution.context.LocalContext;
050: import javolution.context.StackContext;
051: import static javax.measure.unit.NonSI.*;
052: import static javax.measure.unit.SI.*;
053: import static org.jscience.economics.money.Currency.*;
054:
055: /**
056: * <p> This class represents the <b>J</b>Science library; it contains the
057: * {@link #main} method for versionning, self-tests, and performance
058: * analysis.</p>
059: *
060: * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
061: * @version 3.0, February 13, 2006
062: */
063: public final class JScience {
064:
065: /**
066: * Holds the version information.
067: */
068: public final static String VERSION = "@VERSION@";
069:
070: public static Configurable<Character> MODULO = new Configurable<Character>(
071: 'w');
072:
073: /**
074: * Default constructor.
075: */
076: private JScience() {// Forbids derivation.
077: }
078:
079: /**
080: * The library {@link #main} method. The archive <codejscience.jar</code>
081: * is auto-executable.
082: * <ul>
083: * <li><code>java [-cp javolution.jar] -jar jscience.jar version</code>
084: * to output version information.</li>
085: * <li><code>java [-cp javolution.jar] -jar jscience.jar test</code> to
086: * perform self-tests.</li>
087: * <li><code>java [-cp javolution.jar] -jar jscience.jar perf</code> for
088: * performance analysis.</li>
089: * </ul>
090: *
091: * @param args the option arguments.
092: * @throws Exception if a problem occurs.
093: */
094: public static void main(String[] args) throws Exception {
095: System.out.println("Version " + VERSION
096: + " (http://jscience.org)");
097: System.out.println("");
098: if (args.length > 0) {
099: if (args[0].equals("version")) {
100: System.out.println("Version " + VERSION);
101: return;
102: } else if (args[0].equals("test")) {
103: testing();
104: return;
105: } else if (args[0].equals("perf")) {
106: benchmark();
107: return;
108: }
109: }
110: System.out
111: .println("Usage: java [-cp javolution.jar] -jar jscience.jar [arg]");
112: System.out.println("where arg is one of:");
113: System.out.println(" version (to show version information)");
114: System.out.println(" test (to perform self-tests)");
115: System.out.println(" perf (to run benchmark)");
116: }
117:
118: /**
119: * Performs simple tests.
120: *
121: * @throws Exception if a problem occurs.
122: */
123: private static void testing() throws Exception {
124: System.out
125: .println("Load Configurable Parameters from System.getProperties()...");
126: Configurable.read(System.getProperties());
127: System.out.println("");
128:
129: System.out.println("Testing...");
130: {
131: System.out.println("");
132: System.out.println("Exact Measurements");
133: Amount<Mass> m0 = Amount.valueOf(100, POUND);
134: Amount<Mass> m1 = m0.times(33).divide(2);
135: Amount<ElectricCurrent> m2 = Amount.valueOf("234 mA").to(
136: MICRO(AMPERE));
137: System.out.println("m0 = " + m0);
138: System.out.println("m1 = " + m1);
139: System.out.println("m2 = " + m2);
140:
141: System.out.println("");
142: System.out.println("Inexact Measurements");
143: Amount<Mass> m3 = Amount.valueOf(100.0, POUND);
144: Amount<Mass> m4 = m0.divide(3);
145: Amount<ElectricCurrent> m5 = Amount.valueOf("234 mA").to(
146: AMPERE);
147: Amount<Temperature> t0 = Amount.valueOf(-7.3, 0.5, CELSIUS);
148: System.out.println("m3 = " + m3);
149: System.out.println("m4 = " + m4);
150: System.out.println("m5 = " + m5);
151: System.out.println("t0 = " + t0);
152:
153: System.out.println("");
154: System.out.println("Interval measurements");
155: Amount<Volume> m6 = Amount.valueOf(20, 0.1, LITRE);
156: Amount<Frequency> m7 = Amount.rangeOf(10, 11, KILO(HERTZ));
157: System.out.println("m6 = " + m6);
158: System.out.println("m7 = " + m7);
159:
160: System.out.println("");
161: System.out
162: .println("Amount.equals (identical) / Amount.approximates "
163: + "(takes into account errors such as numeric errors)");
164: Amount<Frequency> m8 = Amount.valueOf(9000, HERTZ);
165: Amount<Frequency> m10 = m8.divide(3).times(3); // Still exact.
166: Amount<Frequency> m11 = m8.divide(7).times(7); // No more exact.
167: System.out.println("m8 = " + m8);
168: System.out.println("m10 = " + m10);
169: System.out.println("m11 = " + m11);
170: System.out.println("(m10 == m8) = " + m10.equals(m8));
171: System.out
172: .println("(m10 ≅ m8) = " + m10.approximates(m8));
173: System.out.println("(m11 == m8) = " + m11.equals(m8));
174: System.out
175: .println("(m11 ≅ m8) = " + m11.approximates(m8));
176:
177: System.out.println("");
178: System.out
179: .println("AmountFormat - Plus/Minus Error (3 digits error)");
180: AmountFormat.setInstance(AmountFormat
181: .getPlusMinusErrorInstance(3));
182: System.out.println("m3 = " + m3);
183: System.out.println("m4 = " + m4);
184: System.out.println("m5 = " + m5);
185:
186: System.out.println("");
187: System.out
188: .println("AmountFormat - Bracket Error (2 digits error)");
189: AmountFormat.setInstance(AmountFormat
190: .getBracketErrorInstance(2));
191: System.out.println("m3 = " + m3);
192: System.out.println("m4 = " + m4);
193: System.out.println("m5 = " + m5);
194:
195: System.out.println("");
196: System.out.println("AmountFormat - Exact Digits Only");
197: AmountFormat.setInstance(AmountFormat
198: .getExactDigitsInstance());
199: System.out.println("m3 = " + m3);
200: System.out.println("m4 = " + m4);
201: System.out.println("m5 = " + m5);
202:
203: System.out.println("");
204: System.out.println("Numeric Errors");
205: {
206: Amount<Length> x = Amount.valueOf(1.0, METRE);
207: Amount<Velocity> v = Amount.valueOf(0.01,
208: METRES_PER_SECOND);
209: Amount<Duration> t = Amount.valueOf(1.0, MICRO(SECOND));
210: long ns = System.nanoTime();
211: for (int i = 0; i < 10000000; i++) {
212: x = x.plus(v.times(t));
213: }
214: ns = System.nanoTime() - ns;
215: AmountFormat.setInstance(AmountFormat
216: .getExactDigitsInstance());
217: System.out.println(x
218: + " ("
219: + Amount.valueOf(ns, 0.5, NANO(SECOND)).to(
220: MILLI(SECOND)) + ")");
221: }
222: {
223: double x = 1.0; // m
224: double v = 0.01; // m/s
225: double t = 1E-6; // s
226: for (int i = 0; i < 10000000; i++) {
227: x += v * t; // Note: Most likely the compiler get v * t out of the loop.
228: }
229: System.out.println(x);
230: }
231: AmountFormat.setInstance(AmountFormat
232: .getPlusMinusErrorInstance(2));
233: }
234: {
235: System.out.println("");
236: System.out.println("Physical Models");
237: // Selects a relativistic model for dimension checking (typically at start-up).
238: RelativisticModel.select();
239:
240: // Length and Duration can be added.
241: Amount<Length> x = Amount.valueOf(100, NonSI.INCH);
242: x = x.plus(Amount.valueOf("2.3 µs")).to(METRE);
243: System.out.println(x);
244:
245: // Energy is compatible with mass (E=mc2)
246: Amount<Mass> m = Amount.valueOf("12 GeV").to(KILOGRAM);
247: System.out.println(m);
248: }
249:
250: {
251: System.out.println("");
252: System.out.println("Money/Currencies");
253: ///////////////////////////////////////////////////////////////////////
254: // Calculates the cost of a car trip in Europe for an American tourist.
255: ///////////////////////////////////////////////////////////////////////
256:
257: // Use currency symbols instead of ISO-4217 codes.
258: UnitFormat.getInstance().label(USD, "$"); // Use "$" symbol instead of currency code ("USD")
259: UnitFormat.getInstance().label(EUR, "€"); // Use "€" symbol instead of currency code ("EUR")
260:
261: // Sets exchange rates.
262: Currency.setReferenceCurrency(USD);
263: EUR.setExchangeRate(1.17); // 1.0 € = 1.17 $
264:
265: // Calculates trip cost.
266: Amount<?> carMileage = Amount.valueOf(20, MILE
267: .divide(GALLON_LIQUID_US)); // 20 mi/gal.
268: Amount<?> gazPrice = Amount.valueOf(1.2, EUR.divide(LITRE)); // 1.2 €/L
269: Amount<Length> tripDistance = Amount.valueOf(400,
270: KILO(SI.METRE)); // 400 km
271: Amount<Money> tripCost = tripDistance.divide(carMileage)
272: .times(gazPrice).to(USD);
273: // Displays cost.
274: System.out.println("Trip cost = " + tripCost + " ("
275: + tripCost.to(EUR) + ")");
276: }
277: {
278: System.out.println("");
279: System.out.println("Matrices/Vectors");
280:
281: Amount<ElectricResistance> R1 = Amount.valueOf(100, 1, OHM); // 1% precision.
282: Amount<ElectricResistance> R2 = Amount.valueOf(300, 3, OHM); // 1% precision.
283: Amount<ElectricPotential> U0 = Amount.valueOf(28, 0.01,
284: VOLT); // ±0.01 V fluctuation.
285:
286: // Equations: U0 = U1 + U2 |1 1 0 | |U1| |U0|
287: // U1 = R1 * I => |-1 0 R1| * |U2| = |0 |
288: // U2 = R2 * I |0 -1 R2| |I | |0 |
289: //
290: // A * X = B
291: //
292: DenseMatrix<Amount<?>> A = DenseMatrix
293: .valueOf(new Amount<?>[][] {
294: { Amount.ONE, Amount.ONE,
295: Amount.valueOf(0, OHM) },
296: { Amount.ONE.opposite(), Amount.ZERO, R1 },
297: { Amount.ZERO, Amount.ONE.opposite(), R2 } });
298: DenseVector<Amount<?>> B = DenseVector
299: .valueOf(new Amount<?>[] { U0,
300: Amount.valueOf(0, VOLT),
301: Amount.valueOf(0, VOLT) });
302: Vector<Amount<?>> X = A.solve(B);
303: System.out.println(X);
304: System.out.println(X.get(2).to(MILLI(AMPERE)));
305: }
306: {
307: System.out.println("");
308: System.out.println("Polynomials");
309:
310: // Defines two local variables (x, y).
311: Variable<Complex> varX = new Variable.Local<Complex>("x");
312: Variable<Complex> varY = new Variable.Local<Complex>("y");
313:
314: // f(x) = 1 + 2x + ix²
315: Polynomial<Complex> x = Polynomial.valueOf(Complex.ONE,
316: varX);
317: Polynomial<Complex> fx = x.pow(2).times(Complex.I).plus(
318: x.times(Complex.valueOf(2, 0)).plus(Complex.ONE));
319: System.out.println(fx);
320: System.out.println(fx.pow(2));
321: System.out.println(fx.differentiate(varX));
322: System.out.println(fx.integrate(varY));
323: System.out.println(fx.compose(fx));
324:
325: // Calculates expression.
326: varX.set(Complex.valueOf(2, 3));
327: System.out.println(fx.evaluate());
328: }
329:
330: {
331: System.out.println("");
332: System.out.println("Coordinates Conversions");
333:
334: // Simple Lat/Long to UTM conversion.
335: CoordinatesConverter<LatLong, UTM> latLongToUTM = LatLong.CRS
336: .getConverterTo(UTM.CRS);
337: LatLong latLong = LatLong.valueOf(34.34, 23.56,
338: DEGREE_ANGLE);
339: UTM utm = latLongToUTM.convert(latLong);
340: System.out.println(utm);
341:
342: // Lat/Long to XYZ conversion (assume height of zero).
343: CoordinatesConverter<LatLong, XYZ> latLongToXYZ = LatLong.CRS
344: .getConverterTo(XYZ.CRS);
345: XYZ xyz = latLongToXYZ.convert(latLong);
346: System.out.println(xyz);
347:
348: // Compound coordinates - Lat/Long/Alt to XYZ conversion.
349: Altitude alt = Altitude.valueOf(2000, FOOT);
350: CompoundCoordinates<LatLong, Altitude> latLongAlt = CompoundCoordinates
351: .valueOf(latLong, alt);
352: xyz = latLongAlt.getCoordinateReferenceSystem()
353: .getConverterTo(XYZ.CRS).convert(latLongAlt);
354: System.out.println(xyz);
355:
356: // Even more compounding...
357: Time time = Time.valueOf(new Date());
358: CompoundCoordinates<CompoundCoordinates<LatLong, Altitude>, Time> latLongAltTime = CompoundCoordinates
359: .valueOf(latLongAlt, time);
360: System.out.println(latLongAltTime);
361: }
362:
363: {
364: System.out.println("");
365: System.out.println("Numbers");
366:
367: Real two = Real.valueOf(2); // 2.0000..00
368: Real three = Real.valueOf(3);
369: Real.setExactPrecision(100); // Assumes 100 exact digits for exact numbers.
370:
371: System.out.println("2/3 = " + two.divide(three));
372: Real sqrt2 = two.sqrt();
373: System.out.println("sqrt(2) = " + sqrt2);
374: System.out.println("Precision = " + sqrt2.getPrecision()
375: + " digits.");
376:
377: LargeInteger dividend = LargeInteger
378: .valueOf("3133861182986538201");
379: LargeInteger divisor = LargeInteger
380: .valueOf("25147325102501733369");
381: Rational rational = Rational.valueOf(dividend, divisor);
382: System.out.println("rational = " + rational);
383:
384: ModuloInteger m = ModuloInteger.valueOf("233424242346");
385: LocalContext.enter(); // Avoids impacting others threads.
386: try {
387: ModuloInteger.setModulus(LargeInteger
388: .valueOf("31225208137"));
389: ModuloInteger inv = m.inverse();
390: System.out.println("inverse modulo = " + inv);
391:
392: ModuloInteger one = inv.times(m);
393: System.out.println("verification: one = " + one);
394:
395: } finally {
396: LocalContext.exit();
397: }
398:
399: }
400: }
401:
402: /**
403: * Measures performance.
404: */
405: private static void benchmark() throws Exception {
406: System.out
407: .println("Load Configurable Parameters from System.getProperties()...");
408: Configurable.read(System.getProperties());
409: System.out.println("");
410:
411: System.out.println("Benchmark...");
412:
413: Object[] results = new Object[10000];
414:
415: System.out.println("");
416: System.out.println("Numerics Operations");
417:
418: System.out.print("Float64 add: ");
419: startTime();
420: for (int i = 0; i < 10000; i++) {
421: StackContext.enter();
422: Float64 x = Float64.ONE;
423: for (int j = 0; j < results.length; j++) {
424: results[j] = x.plus(x);
425: }
426: StackContext.exit();
427: }
428: endTime(10000 * results.length);
429:
430: System.out.print("Float64 multiply: ");
431: startTime();
432: for (int i = 0; i < 10000; i++) {
433: StackContext.enter();
434: Float64 x = Float64.valueOf(1.0);
435: for (int j = 0; j < results.length; j++) {
436: results[j] = x.times(x);
437: }
438: StackContext.exit();
439: }
440: endTime(10000 * results.length);
441:
442: System.out.print("Complex add: ");
443: startTime();
444: for (int i = 0; i < 10000; i++) {
445: StackContext.enter();
446: Complex x = Complex.valueOf(1.0, 2.0);
447: for (int j = 0; j < results.length; j++) {
448: results[j] = x.plus(x);
449: }
450: StackContext.exit();
451: }
452: endTime(10000 * results.length);
453:
454: System.out.print("Complex multiply: ");
455: startTime();
456: for (int i = 0; i < 10000; i++) {
457: StackContext.enter();
458: Complex x = Complex.valueOf(1.0, 2.0);
459: for (int j = 0; j < results.length; j++) {
460: results[j] = x.times(x);
461: }
462: StackContext.exit();
463: }
464: endTime(10000 * results.length);
465:
466: System.out.print("Amount<Mass> add: ");
467: startTime();
468: for (int i = 0; i < 10000; i++) {
469: StackContext.enter();
470: Amount<Mass> x = Amount.valueOf(1.0, SI.KILOGRAM);
471: for (int j = 0; j < results.length; j++) {
472: results[j] = x.plus(x);
473: }
474: StackContext.exit();
475: }
476: endTime(10000 * results.length);
477:
478: System.out.print("Amount<Mass> multiply: ");
479: startTime();
480: for (int i = 0; i < 10000; i++) {
481: StackContext.enter();
482: Amount<Mass> x = Amount.valueOf(1.0, SI.KILOGRAM);
483: for (int j = 0; j < results.length; j++) {
484: results[j] = x.times(x);
485: }
486: StackContext.exit();
487: }
488: endTime(10000 * results.length);
489:
490: System.out.println();
491: System.out
492: .println("LargeInteger (StackContext) versus BigInteger");
493: BigInteger big = BigInteger.probablePrime(1024, new Random());
494: byte[] bytes = big.toByteArray();
495: LargeInteger large = LargeInteger.valueOf(bytes, 0,
496: bytes.length);
497:
498: System.out.print("LargeInteger (1024 bits) addition: ");
499: startTime();
500: for (int i = 0; i < 1000; i++) {
501: StackContext.enter();
502: for (int j = 0; j < results.length; j++) {
503: results[j] = large.plus(large);
504: }
505: StackContext.exit();
506: }
507: endTime(1000 * results.length);
508:
509: System.out.print("LargeInteger (1024 bits) multiplication: ");
510: startTime();
511: for (int i = 0; i < 100; i++) {
512: StackContext.enter();
513: for (int j = 0; j < results.length; j++) {
514: results[j] = large.times(large);
515: }
516: StackContext.exit();
517: }
518: endTime(100 * results.length);
519:
520: System.out.print("BigInteger (1024 bits) addition: ");
521: startTime();
522: for (int i = 0; i < 1000; i++) {
523: for (int j = 0; j < results.length; j++) {
524: results[j] = big.add(big);
525: }
526: }
527: endTime(1000 * results.length);
528:
529: System.out.print("BigInteger (1024 bits) multiplication: ");
530: startTime();
531: for (int i = 0; i < 100; i++) {
532: for (int j = 0; j < results.length; j++) {
533: results[j] = big.multiply(big);
534: }
535: }
536: endTime(100 * results.length);
537:
538: System.out.println();
539: System.out
540: .println("Matrix<Float64> and Matrix<Complex> versus "
541: + "non-parameterized matrix (double)");
542: final int size = 500;
543: double[][] values = new double[size][size];
544: for (int i = 0; i < size; i++) {
545: for (int j = 0; j < size; j++) {
546: values[i][j] = MathLib.random();
547: }
548: }
549:
550: System.out.println("Javolution Concurrency Disabled");
551: LocalContext.enter(); // Local setting.
552: try {
553: ConcurrentContext.setConcurrency(0);
554: multiplyMatrices(values);
555: } finally {
556: LocalContext.exit();
557: }
558:
559: System.out.println("Javolution Concurrency: "
560: + ConcurrentContext.getConcurrency());
561: multiplyMatrices(values);
562:
563: System.out.println();
564: System.out
565: .println("More performance analysis in future versions...");
566: }
567:
568: private static void multiplyMatrices(double[][] values) {
569:
570: int size = values.length;
571:
572: System.out.print("Non-parameterized matrix (double based)"
573: + " 500x500 multiplication: ");
574: for (int i = 0; i < size; i++) {
575: for (int j = 0; j < size; j++) {
576: values[i][j] = MathLib.random();
577: }
578: }
579: MatrixDouble PM = new MatrixDouble(values);
580: for (int i = 0; i < 5; i++)
581: PM.times(PM); // Warming up.
582: startTime();
583: MatrixDouble R1 = PM.times(PM);
584: endTime(1);
585:
586: System.out.print("Matrix<Float64> 500x500 multiplication: ");
587: Matrix<Float64> FM = Float64Matrix.valueOf(values);
588: for (int i = 0; i < 5; i++)
589: FM.times(FM); // Warming up.
590: startTime();
591: Matrix<Float64> R2 = FM.times(FM);
592: endTime(1);
593:
594: // Checks results.
595: if (!R2.equals(Float64Matrix.valueOf(R1.o)))
596: throw new Error("Error in matrix multiplication");
597:
598: System.out.print("Matrix<Complex> 500x500 multiplication: ");
599: Complex[][] complexes = new Complex[size][size];
600: for (int i = 0; i < size; i++) {
601: for (int j = 0; j < size; j++) {
602: complexes[i][j] = Complex.valueOf(MathLib.random(),
603: MathLib.random());
604: }
605: }
606: Matrix<Complex> CM = ComplexMatrix.valueOf(complexes);
607: for (int i = 0; i < 5; i++)
608: CM.times(CM); // Warming up.
609: startTime();
610: CM.times(CM);
611: endTime(1);
612:
613: System.out.print("Matrix<Amount> 500x500 multiplication: ");
614: Amount<?>[][] measures = new Amount<?>[size][size];
615: for (int i = 0; i < size; i++) {
616: for (int j = 0; j < size; j++) {
617: measures[i][j] = Amount.valueOf(MathLib.random(
618: Long.MIN_VALUE, Long.MAX_VALUE), Unit.ONE);
619: }
620: }
621: DenseMatrix<Amount<?>> MM = DenseMatrix.valueOf(measures);
622: startTime();
623: MM.times(MM);
624: endTime(1);
625:
626: }
627:
628: private static final class MatrixDouble {
629: double[][] o;
630:
631: int m; // Nbr of rows.
632:
633: int n; // Nbr of columns.
634:
635: MatrixDouble(double[][] elements) {
636: o = elements;
637: m = elements.length;
638: n = elements[0].length;
639: }
640:
641: MatrixDouble times(MatrixDouble that) {
642: if (that.m != this .n)
643: throw new Error("Wrong dimensions");
644: MatrixDouble M = new MatrixDouble(
645: new double[this .m][that.n]);
646: double[] thatColj = new double[n];
647: for (int j = 0; j < that.n; j++) {
648: for (int k = 0; k < n; k++) {
649: thatColj[k] = that.o[k][j];
650: }
651: for (int i = 0; i < m; i++) {
652: double[] this Rowi = o[i];
653: double s = 0;
654: for (int k = 0; k < n; k++) {
655: s += this Rowi[k] * thatColj[k];
656: }
657: M.o[i][j] = s;
658: }
659: }
660: return M;
661: }
662: }
663:
664: private static void startTime() {
665: _time = System.nanoTime();
666: }
667:
668: /**
669: * Ends measuring time and display the execution time per iteration.
670: *
671: * @param iterations
672: * the number iterations performed since {@link #startTime}.
673: */
674: public static void endTime(int iterations) {
675: long nanoSeconds = System.nanoTime() - _time;
676: long picoDuration = nanoSeconds * 1000 / iterations;
677: long divisor;
678: String unit;
679: if (picoDuration > 1000 * 1000 * 1000 * 1000L) { // 1 s
680: unit = " s";
681: divisor = 1000 * 1000 * 1000 * 1000L;
682: } else if (picoDuration > 1000 * 1000 * 1000L) {
683: unit = " ms";
684: divisor = 1000 * 1000 * 1000L;
685: } else if (picoDuration > 1000 * 1000L) {
686: unit = " us";
687: divisor = 1000 * 1000L;
688: } else {
689: unit = " ns";
690: divisor = 1000L;
691: }
692: TextBuilder tb = TextBuilder.newInstance();
693: tb.append(picoDuration / divisor);
694: int fracDigits = 4 - tb.length(); // 4 digits precision.
695: tb.append(".");
696: for (int i = 0, j = 10; i < fracDigits; i++, j *= 10) {
697: tb.append((picoDuration * j / divisor) % 10);
698: }
699: System.out.println(tb.append(unit));
700: }
701:
702: private static long _time;
703:
704: }
|