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  * @library /testlibrary
  32  * @run main Fibonacci 15
  33  */
  34 
  35 import com.oracle.java.testlibrary.Asserts;
  36 
  37 public class Fibonacci extends Thread {
  38     private int index;
  39     private int value;
  40     private Fibonacci left;
  41     private Fibonacci right;
  42 
  43     public Fibonacci(int i) {
  44         index = i;
  45     }
  46 
  47     private int getValue() {
  48         return value;
  49     }
  50 
  51     @Override
  52     public void run() {
  53         if (index == 0 || index == 1) {
  54             // base cases, 0 Fibonacci number = 0, 1 Fibonacci number = 1
  55             value = index;
  56         } else {
  57             // inductive cases
  58             left = new Fibonacci(index - 2);
  59             right = new Fibonacci(index - 1);
  60             left.start();
  61             right.start();
  62             try {
  63                 left.join();
  64                 right.join();
  65             } catch (InterruptedException e) {
  66                 throw new Error("InterruptedException for index " + index, e);
  67             }
  68             // compute and terminate
  69             value = left.getValue() + right.getValue();
  70         }
  71     }
  72 
  73     public static int traditionalFibonacci(int n) {
  74         int n1 = 0, n2 = 1, nn = 0;
  75 
  76         if (n == 0 || n == 1) {
  77            nn = n;
  78         }
  79 
  80         for (int i = 1; i < n; ++i) {
  81             nn = n2 + n1;
  82             n1 = n2;
  83             n2 = nn;
  84         }
  85         return nn;
  86     }
  87 
  88     public static void main(String[] args) throws Error,AssertionError {
  89         int expected;
  90         int number;
  91         Fibonacci recursiveFibonacci;
  92 
  93         if (args.length != 1) {
  94             throw new Error("Error: args.length must be 1");
  95         }
  96 
  97         number = Integer.parseInt(args[0]);
  98         recursiveFibonacci = new Fibonacci(number);
  99 
 100         recursiveFibonacci.start();
 101         try {
 102             recursiveFibonacci.join();
 103         } catch (InterruptedException e) {
 104             throw new Error("InterruptedException in main thread", e);
 105         }
 106 
 107         expected = traditionalFibonacci(number);
 108 
 109         System.out.println("Fibonacci[" + number + "] = " + expected);
 110 
 111         Asserts.assertEQ(recursiveFibonacci.getValue(), expected,
 112                           "Unexpected calculated value: " + recursiveFibonacci.getValue() + " expected " + expected );
 113     }
 114 }