blob: 4093b25bf0b2de33894f023abd89c51cd75b9f86 [file] [log] [blame]
/*
* 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.sysds.runtime.compress.utils;
import org.apache.sysds.runtime.data.DenseBlock;
import org.apache.sysds.runtime.matrix.data.LibMatrixMult;
import org.apache.sysds.runtime.matrix.data.MatrixBlock;
/**
* This library contains all vector primitives that are used in 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.getDenseBlockValues();
DenseBlock c = ret.getDenseBlock();
for(int i = 0; i < tmp.getNumColumns(); i++)
if(a[i] != 0)
c.set((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;
}
}