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