/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.sysml.runtime.compress.utils; import org.apache.sysml.runtime.matrix.data.LibMatrixMult; import org.apache.sysml.runtime.matrix.data.MatrixBlock; /** * This library contains all vector primitives that are used compressed * linear algebra. For primitives that exist in LibMatrixMult, these * calls are simply forwarded to ensure consistency in performance and * result correctness. */ public class LinearAlgebraUtils { //forwarded calls to LibMatrixMult public static double dotProduct(double[] a, double[] b, final int len) { return LibMatrixMult.dotProduct(a, b, 0, 0, len); } public static double dotProduct( double[] a, double[] b, int ai, int bi, final int len ) { return LibMatrixMult.dotProduct(a, b, ai, bi, len); } public static void vectMultiplyAdd( final double aval, double[] b, double[] c, int bi, int ci, final int len ) { LibMatrixMult.vectMultiplyAdd(aval, b, c, bi, ci, len); } public static void vectMultiplyAdd( final double aval, double[] b, double[] c, int[] bix, final int bi, final int ci, final int len ) { LibMatrixMult.vectMultiplyAdd(aval, b, c, bix, bi, ci, len); } public static void vectAdd( double[] a, double[] c, int ai, int ci, final int len ) { LibMatrixMult.vectAdd(a, c, ai, ci, len); } public static void vectAdd( final double aval, double[] c, char[] bix, final int bi, final int ci, final int len ) { final int bn = len%8; //rest, not aligned to 8-blocks for( int j = bi; j < bi+bn; j++ ) c[ ci + bix[j] ] += aval; //unrolled 8-block (for better instruction-level parallelism) for( int j = bi+bn; j < bi+len; j+=8 ) { c[ ci+bix[j+0] ] += aval; c[ ci+bix[j+1] ] += aval; c[ ci+bix[j+2] ] += aval; c[ ci+bix[j+3] ] += aval; c[ ci+bix[j+4] ] += aval; c[ ci+bix[j+5] ] += aval; c[ ci+bix[j+6] ] += aval; c[ ci+bix[j+7] ] += aval; } } public static void vectAdd( final double aval, double[] c, final int ci, final int len ) { final int bn = len%8; //rest, not aligned to 8-blocks for( int j = 0; j < bn; j++ ) c[ ci + j ] += aval; //unrolled 8-block (for better instruction-level parallelism) for( int j = bn; j < len; j+=8 ) { c[ ci+j+0 ] += aval; c[ ci+j+1 ] += aval; c[ ci+j+2 ] += aval; c[ ci+j+3 ] += aval; c[ ci+j+4 ] += aval; c[ ci+j+5 ] += aval; c[ ci+j+6 ] += aval; c[ ci+j+7 ] += aval; } } public static double vectSum( double[] a, char[] bix, final int ai, final int bi, final int len ) { double val = 0; final int bn = len%8; //rest, not aligned to 8-blocks for( int j = bi; j < bi+bn; j++ ) val += a[ ai + bix[j] ]; //unrolled 8-block (for better instruction-level parallelism) for( int j = bi+bn; j < bi+len; j+=8 ) { val += a[ ai+bix[j+0] ] + a[ ai+bix[j+1] ] + a[ ai+bix[j+2] ] + a[ ai+bix[j+3] ] + a[ ai+bix[j+4] ] + a[ ai+bix[j+5] ] + a[ ai+bix[j+6] ] + a[ ai+bix[j+7] ]; } return val; } public static double vectSum( double[] a, int ai, final int len ) { double val = 0; final int bn = len%8; //rest, not aligned to 8-blocks for( int j = ai; j < ai+bn; j++ ) val += a[ j ]; //unrolled 8-block (for better instruction-level parallelism) for( int j = ai+bn; j < ai+len; j+=8 ) { val += a[ j+0 ] + a[ j+1 ] + a[ j+2 ] + a[ j+3 ] + a[ j+4 ] + a[ j+5 ] + a[ j+6 ] + a[ j+7 ]; } return val; } public static long copyUpperToLowerTriangle( MatrixBlock ret ) { return LibMatrixMult.copyUpperToLowerTriangle(ret); } public static void copyNonZerosToUpperTriangle( MatrixBlock ret, MatrixBlock tmp, int ix ) { double[] a = tmp.getDenseBlock(); for(int i=0; i<tmp.getNumColumns(); i++) { if( a[i] != 0 ) { ret.setValueDenseUnsafe( (ix<i)?ix:i, (ix<i)?i:ix, a[i]); } } } /** * Obtain the index of the closest element in a to the value x. * * @param a array of ints * @param x value * @return the index of the closest element in a to the value x */ public static int getClosestK(int[] a, int x) { int low = 0; int high = a.length - 1; while (low < high) { int mid = (low + high) / 2; int d1 = Math.abs(a[mid] - x); int d2 = Math.abs(a[mid + 1] - x); if (d2 <= d1) { low = mid + 1; } else { high = mid; } } return high; } }