1 /*
   2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /**
  25  * @test
  26  * @summary Calculates Fibonacci numbers "recursively" via threads and compares
  27  *     the result with the classical calculation.
  28  *     This test is skipped on 32-bit Windows: limited virtual space on Win-32
  29  *     make this test inherently unstable on Windows with 32-bit VM data model.
  30  * @requires !(os.family == "windows" & sun.arch.data.model == "32")
  31  * @modules java.base/jdk.internal.misc
  32  * @library /test/lib
  33  * @run main/othervm Fibonacci 15
  34  */
  35 
  36 import jdk.test.lib.Asserts;
  37 
  38 public class Fibonacci extends Thread {
  39     private int index;
  40     private int value;
  41     private Fibonacci left;
  42     private Fibonacci right;
  43 
  44     public Fibonacci(int i) {
  45         index = i;
  46     }
  47 
  48     private int getValue() {
  49         return value;
  50     }
  51 
  52     @Override
  53     public void run() {
  54         if (index == 0 || index == 1) {
  55             // base cases, 0 Fibonacci number = 0, 1 Fibonacci number = 1
  56             value = index;
  57         } else {
  58             // inductive cases
  59             left = new Fibonacci(index - 2);
  60             right = new Fibonacci(index - 1);
  61             left.start();
  62             right.start();
  63             try {
  64                 left.join();
  65                 right.join();
  66             } catch (InterruptedException e) {
  67                 throw new Error("InterruptedException for index " + index, e);
  68             }
  69             // compute and terminate
  70             value = left.getValue() + right.getValue();
  71         }
  72     }
  73 
  74     public static int traditionalFibonacci(int n) {
  75         int n1 = 0, n2 = 1, nn = 0;
  76 
  77         if (n == 0 || n == 1) {
  78            nn = n;
  79         }
  80 
  81         for (int i = 1; i < n; ++i) {
  82             nn = n2 + n1;
  83             n1 = n2;
  84             n2 = nn;
  85         }
  86         return nn;
  87     }
  88 
  89     public static void main(String[] args) throws Error,AssertionError {
  90         int expected;
  91         int number;
  92         Fibonacci recursiveFibonacci;
  93 
  94         if (args.length != 1) {
  95             throw new Error("Error: args.length must be 1");
  96         }
  97 
  98         number = Integer.parseInt(args[0]);
  99         recursiveFibonacci = new Fibonacci(number);
 100 
 101         recursiveFibonacci.start();
 102         try {
 103             recursiveFibonacci.join();
 104         } catch (InterruptedException e) {
 105             throw new Error("InterruptedException in main thread", e);
 106         }
 107 
 108         expected = traditionalFibonacci(number);
 109 
 110         System.out.println("Fibonacci[" + number + "] = " + expected);
 111 
 112         Asserts.assertEQ(recursiveFibonacci.getValue(), expected,
 113                           "Unexpected calculated value: " + recursiveFibonacci.getValue() + " expected " + expected );
 114     }
 115 }