001    // --- BEGIN LICENSE BLOCK ---
002    /*
003     * Copyright (c) 2009, 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 ---
036    package org.jblas.util;
037    
038    import org.jblas.ComplexDouble;
039    import org.jblas.ComplexDoubleMatrix;
040    import org.jblas.NativeBlas;
041    import 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     */
049    public 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 checkComplexReturnValues() {
153            double[] data = new double[] {
154                1.0, 2.0, 3.0, 4.0, 5.0, 6.0
155            };
156    
157            ComplexDoubleMatrix A = new ComplexDoubleMatrix(data);
158    
159            ComplexDouble z = A.dotu(A);
160    
161            System.out.print("Checking complex return values... ");
162            System.out.println("(z = " + z.toString() + ")");
163        }
164    
165        public static void main(String[] args) {
166            Logger.getLogger().setLevel(Logger.CONFIG);
167            for (String arg : args) {
168                if (arg.equals("--debug")) {
169                    Logger.getLogger().setLevel(Logger.DEBUG);
170                }
171            }
172            checkVectorAddition();
173            checkMatrixMultiplication();
174            checkEigenvalues();
175            checkSVD();
176            checkComplexReturnValues();
177            checkXerbla();
178            printSummary();
179        }
180    
181        private static void printSummary() {
182            if (checksFailed == 0) {
183                System.out.println("Sanity checks passed.");
184            } else {
185                System.out.println("Sainty checks FAILED!");
186            }
187        }
188    }