/*
* 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.udf.lib;
import org.apache.sysml.udf.FunctionParameter;
import org.apache.sysml.udf.Matrix;
import org.apache.sysml.udf.PackageFunction;
import org.apache.sysml.udf.Scalar;
import org.apache.sysml.udf.Matrix.ValueType;
import org.apache.sysml.udf.Scalar.ScalarValueType;
/**
* Wrapper class for binning a sorted input vector
*
*/
public class BinningWrapper extends PackageFunction
{
private static final long serialVersionUID = 1L;
private static final String OUTPUT_FILE = "TMP";
//return matrix
private Matrix _bins; //return matrix col_bins
private Scalar _defBins; //return num defined bins
@Override
public int getNumFunctionOutputs()
{
return 2;
}
@Override
public FunctionParameter getFunctionOutput(int pos)
{
switch(pos) {
case 0: return _bins;
case 1: return _defBins;
}
throw new RuntimeException("Invalid function output being requested");
}
@Override
public void execute()
{
try
{
//get input parameters (input matrix assumed to be sorted)
Matrix inM = (Matrix) getFunctionInput(0);
double [][] col = inM.getMatrixAsDoubleArray();
int binsize = Integer.parseInt(((Scalar)getFunctionInput(1)).getValue());
int numbins = Integer.parseInt(((Scalar)getFunctionInput(2)).getValue());
int nrowX = (int) inM.getNumRows();
//execute binning (extend bins for duplicates)
double[] col_bins = new double[numbins+1];
int pos_col = 0;
int bin_id = 0;
col_bins[0] = col[0][0];
while(pos_col < nrowX-1 && bin_id < numbins) { //for all bins
pos_col = (pos_col + binsize >= nrowX) ? nrowX-1 : pos_col + binsize;
double end_val = col[pos_col][0];
col_bins[bin_id+1] = end_val;
//pull all duplicates in current bin
boolean cont = true;
while( cont && pos_col < nrowX-1 ){
if( end_val == col[pos_col+1][0] )
pos_col++;
else
cont = false;
}
bin_id++;
}
//prepare results
int num_bins_defined = bin_id;
for( int i=0; i<num_bins_defined; i++ )
col_bins[i] = (col_bins[i] + col_bins[i+1])/2;
//create and copy output matrix
String dir = createOutputFilePathAndName( OUTPUT_FILE );
_bins = new Matrix( dir, col_bins.length, 1, ValueType.Double );
_bins.setMatrixDoubleArray(col_bins);
_defBins = new Scalar(ScalarValueType.Integer, String.valueOf(num_bins_defined));
}
catch (Exception e)
{
throw new RuntimeException("Error executing external order function", e);
}
}
}