001// --- BEGIN LICENSE BLOCK ---
002/*
003 * Copyright (c) 2009-2011, Mikio L. Braun
004 * All rights reserved.
005 *
006 * Redistribution and use in source and binary forms, with or without
007 * modification, are permitted provided that the following conditions are
008 * met:
009 *
010 *     * Redistributions of source code must retain the above copyright
011 *       notice, this list of conditions and the following disclaimer.
012 *
013 *     * Redistributions in binary form must reproduce the above
014 *       copyright notice, this list of conditions and the following
015 *       disclaimer in the documentation and/or other materials provided
016 *       with the distribution.
017 *
018 *     * Neither the name of the Technische Universität Berlin nor the
019 *       names of its contributors may be used to endorse or promote
020 *       products derived from this software without specific prior
021 *       written permission.
022 *
023 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
024 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
025 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
026 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
027 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
028 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
029 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
030 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
031 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
032 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
033 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
034 */
035// --- END LICENSE BLOCK ---
036package org.jblas.util;
037
038import org.jblas.ComplexDouble;
039import org.jblas.ComplexDoubleMatrix;
040import org.jblas.NativeBlas;
041import org.jblas.DoubleMatrix;
042
043/**
044 * Run a few sanity checks on the installation to see whether
045 * everything runs as expected.
046 *
047 * @author Mikio L. Braun
048 */
049public class SanityChecks {
050
051    public static int checksFailed;
052
053    public static void check(String message, boolean condition) {
054        System.out.print(message + "... ");
055        if (condition) {
056            System.out.println("ok");
057        } else {
058            System.out.println("failed");
059            checksFailed++;
060        }
061    }
062
063    /** Check whether vector addition works. This is pure Java code and should work. */
064    public static void checkVectorAddition() {
065        DoubleMatrix x = new DoubleMatrix(3, 1, 1.0, 2.0, 3.0);
066        DoubleMatrix y = new DoubleMatrix(3, 1, 4.0, 5.0, 6.0);
067        DoubleMatrix z = new DoubleMatrix(3, 1, 5.0, 7.0, 9.0);
068
069        check("checking vector addition", x.add(y).equals(z));
070    }
071
072    /** Check matrix multiplication. This is already ATLAS/BLAS code. */
073    public static void checkMatrixMultiplication() {
074
075        DoubleMatrix A = new DoubleMatrix(new double[][]{
076                    {1.0, 2.0, 3.0},
077                    {4.0, 5.0, 6.0},
078                    {7.0, 8.0, 9.0}
079                });
080        DoubleMatrix E = new DoubleMatrix(new double[][]{
081                    {0.0, 0.0, 1.0},
082                    {0.0, 1.0, 0.0},
083                    {1.0, 0.0, 0.0}
084                });
085        DoubleMatrix B = new DoubleMatrix(new double[][]{
086                    {3.0, 2.0, 1.0},
087                    {6.0, 5.0, 4.0},
088                    {9.0, 8.0, 7.0}
089                });
090
091        check("checking matrix multiplication", A.mmul(E).equals(B));
092    }
093
094    /**
095     * Check whether error handling works. If it works, you should see an
096     * ok, otherwise, you might see the actual error message and then
097     * the program exits.
098     */
099    public static void checkXerbla() {
100        double[] x = new double[9];
101        System.out.println("Check whether we're catching XERBLA errors. If you see something like \"** On entry to DGEMM  parameter number  4 had an illegal value\", it didn't work!");
102        try {
103            NativeBlas.dgemm('N', 'N', 3, -1, 3, 1.0, x, 0, 3, x, 0, 3, 0.0, x, 0, 3);
104        } catch (IllegalArgumentException e) {
105            check("checking XERBLA", e.getMessage().contains("XERBLA"));
106            return;
107        }
108        assert (false); // shouldn't happen
109    }
110
111    /**
112     * Compute eigenvalues. This is a routine not in ATLAS, but in the original
113     * LAPACK.
114     */
115    public static void checkEigenvalues() {
116        DoubleMatrix A = new DoubleMatrix(new double[][]{
117                    {3.0, 2.0, 0.0},
118                    {2.0, 3.0, 2.0},
119                    {0.0, 2.0, 3.0}
120                });
121
122        DoubleMatrix E = new DoubleMatrix(3, 1);
123
124        NativeBlas.dsyev('N', 'U', 3, A.data, 0, 3, E.data, 0);
125        check("checking existence of dsyev...", true);
126    }
127
128    public static void checkSVD() {
129        double[][] data = new double[][]{
130            {1.0, 2.0, 3.0},
131            {4.0, 5.0, 6.0},
132            {7.0, 8.0, 9.0},
133            {-1.0, -2.0, -3.0}
134        };
135
136        DoubleMatrix A = new DoubleMatrix(data);
137
138        DoubleMatrix[] USV = org.jblas.Singular.sparseSVD(A);
139        System.out.println(USV[0].toString());
140        System.out.println(USV[1].toString());
141        System.out.println(USV[2].toString());
142
143        System.out.println(org.jblas.Singular.SVDValues(A));
144
145        /*ComplexDoubleMatrix[] AZB = org.jblas.Singular.sparseSVD(new ComplexDoubleMatrix(data));
146        System.out.println(AZB[0].toString());
147        System.out.println(AZB[1].toString());
148        System.out.println(AZB[2].toString());*/
149        check("checking existence of dgesvd...", true);
150    }
151
152    public static void checkGeneralizedEigenvalues() {
153        DoubleMatrix A = new DoubleMatrix(3, 3, 2.0, 1.0, 0.0, 1.0, 2.0, 1.0, 0.0, 1.0, 2.0);
154        DoubleMatrix B = new DoubleMatrix(3, 3, 4.0, 2.0, 1.0, 2.0, 4.0, 2.0, 1.0, 2.0, 4.0);
155
156        DoubleMatrix[] LA = org.jblas.Eigen.symmetricGeneralizedEigenvectors(A, B);
157
158        check("checkign existence of gsyevd (generalized eigenvalues)...", true);
159    }
160
161    public static void checkComplexReturnValues() {
162        double[] data = new double[] {
163            1.0, 2.0, 3.0, 4.0, 5.0, 6.0
164        };
165
166        ComplexDoubleMatrix A = new ComplexDoubleMatrix(data);
167
168        ComplexDouble z = A.dotu(A);
169
170        System.out.print("Checking complex return values... ");
171        System.out.println("(z = " + z.toString() + ")");
172    }
173
174    public static void main(String[] args) {
175        Logger.getLogger().setLevel(Logger.CONFIG);
176        for (String arg : args) {
177            if (arg.equals("--debug")) {
178                Logger.getLogger().setLevel(Logger.DEBUG);
179            }
180        }
181        checkVectorAddition();
182        checkMatrixMultiplication();
183        checkEigenvalues();
184        checkSVD();
185        checkComplexReturnValues();
186        checkXerbla();
187        printSummary();
188    }
189
190    private static void printSummary() {
191        if (checksFailed == 0) {
192            System.out.println("Sanity checks passed.");
193        } else {
194            System.out.println("Sainty checks FAILED!");
195        }
196    }
197}