blob: 9542280814c7c8520f77d2b60fc8ba28a1a99f29 [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.pinot.core.operator.transform.function;
import com.google.common.base.Preconditions;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;
import org.apache.pinot.core.operator.blocks.ProjectionBlock;
import org.apache.pinot.core.operator.transform.TransformResultMetadata;
import org.apache.pinot.segment.spi.datasource.DataSource;
import org.apache.pinot.spi.data.FieldSpec.DataType;
/**
* A group of commonly used math transformation which has only one single parameter,
* including abs, ceil, exp, floor, ln, sqrt.
* Note:
* abs(x) -> output data type is either double or BigDecimal.
* ceil(x) -> output data type is either double or BigDecimal.
* exp(x) -> output data type is always double.
* floor(x) -> output data type is either double or BigDecimal.
* ln(x) -> output data type is always double.
* sqrt(x) -> output data type is always double.
*/
public abstract class SingleParamMathTransformFunction extends BaseTransformFunction {
private TransformFunction _transformFunction;
@Override
public void init(List<TransformFunction> arguments, Map<String, DataSource> dataSourceMap) {
Preconditions.checkArgument(arguments.size() == 1, "Exactly 1 argument is required for transform function: %s",
getName());
TransformFunction transformFunction = arguments.get(0);
Preconditions.checkArgument(!(transformFunction instanceof LiteralTransformFunction),
"Argument cannot be literal for transform function: %s", getName());
Preconditions.checkArgument(transformFunction.getResultMetadata().isSingleValue(),
"Argument must be single-valued for transform function: %s", getName());
_transformFunction = transformFunction;
}
@Override
public TransformResultMetadata getResultMetadata() {
if (_transformFunction.getResultMetadata().getDataType() == DataType.BIG_DECIMAL) {
return BIG_DECIMAL_SV_NO_DICTIONARY_METADATA;
}
return DOUBLE_SV_NO_DICTIONARY_METADATA;
}
@Override
public double[] transformToDoubleValuesSV(ProjectionBlock projectionBlock) {
int length = projectionBlock.getNumDocs();
if (_doubleValuesSV == null || _doubleValuesSV.length < length) {
_doubleValuesSV = new double[length];
}
double[] values = _transformFunction.transformToDoubleValuesSV(projectionBlock);
applyMathOperator(values, projectionBlock.getNumDocs());
return _doubleValuesSV;
}
@Override
public BigDecimal[] transformToBigDecimalValuesSV(ProjectionBlock projectionBlock) {
int length = projectionBlock.getNumDocs();
if (_bigDecimalValuesSV == null || _bigDecimalValuesSV.length < length) {
_bigDecimalValuesSV = new BigDecimal[length];
}
BigDecimal[] values = _transformFunction.transformToBigDecimalValuesSV(projectionBlock);
applyMathOperator(values, projectionBlock.getNumDocs());
return _bigDecimalValuesSV;
}
abstract protected void applyMathOperator(double[] values, int length);
protected void applyMathOperator(BigDecimal[] values, int length) {
throw new UnsupportedOperationException("Math operator does not support BIG_DECIMAL data type");
}
public static class AbsTransformFunction extends SingleParamMathTransformFunction {
public static final String FUNCTION_NAME = "abs";
@Override
public String getName() {
return FUNCTION_NAME;
}
@Override
protected void applyMathOperator(double[] values, int length) {
for (int i = 0; i < length; i++) {
_doubleValuesSV[i] = Math.abs(values[i]);
}
}
@Override
protected void applyMathOperator(BigDecimal[] values, int length) {
for (int i = 0; i < length; i++) {
_bigDecimalValuesSV[i] = values[i].abs();
}
}
}
public static class CeilTransformFunction extends SingleParamMathTransformFunction {
public static final String FUNCTION_NAME = "ceil";
@Override
public String getName() {
return FUNCTION_NAME;
}
@Override
protected void applyMathOperator(double[] values, int length) {
for (int i = 0; i < length; i++) {
_doubleValuesSV[i] = Math.ceil(values[i]);
}
}
@Override
protected void applyMathOperator(BigDecimal[] values, int length) {
for (int i = 0; i < length; i++) {
_bigDecimalValuesSV[i] = values[i].setScale(0, RoundingMode.CEILING);
}
}
}
public static class ExpTransformFunction extends SingleParamMathTransformFunction {
public static final String FUNCTION_NAME = "exp";
@Override
public String getName() {
return FUNCTION_NAME;
}
@Override
protected void applyMathOperator(double[] values, int length) {
for (int i = 0; i < length; i++) {
_doubleValuesSV[i] = Math.exp(values[i]);
}
}
}
public static class FloorTransformFunction extends SingleParamMathTransformFunction {
public static final String FUNCTION_NAME = "floor";
@Override
public String getName() {
return FUNCTION_NAME;
}
@Override
protected void applyMathOperator(double[] values, int length) {
for (int i = 0; i < length; i++) {
_doubleValuesSV[i] = Math.floor(values[i]);
}
}
@Override
protected void applyMathOperator(BigDecimal[] values, int length) {
for (int i = 0; i < length; i++) {
_bigDecimalValuesSV[i] = values[i].setScale(0, RoundingMode.FLOOR);
}
}
}
public static class LnTransformFunction extends SingleParamMathTransformFunction {
public static final String FUNCTION_NAME = "ln";
@Override
public String getName() {
return FUNCTION_NAME;
}
@Override
protected void applyMathOperator(double[] values, int length) {
for (int i = 0; i < length; i++) {
_doubleValuesSV[i] = Math.log(values[i]);
}
}
}
public static class Log2TransformFunction extends SingleParamMathTransformFunction {
public static final String FUNCTION_NAME = "log2";
public static final double LOG_BASE = Math.log(2.0);
@Override
public String getName() {
return FUNCTION_NAME;
}
@Override
protected void applyMathOperator(double[] values, int length) {
for (int i = 0; i < length; i++) {
_doubleValuesSV[i] = Math.log(values[i]) / LOG_BASE;
}
}
}
public static class Log10TransformFunction extends SingleParamMathTransformFunction {
public static final String FUNCTION_NAME = "log10";
@Override
public String getName() {
return FUNCTION_NAME;
}
@Override
protected void applyMathOperator(double[] values, int length) {
for (int i = 0; i < length; i++) {
_doubleValuesSV[i] = Math.log10(values[i]);
}
}
}
public static class SqrtTransformFunction extends SingleParamMathTransformFunction {
public static final String FUNCTION_NAME = "sqrt";
@Override
public String getName() {
return FUNCTION_NAME;
}
@Override
protected void applyMathOperator(double[] values, int length) {
for (int i = 0; i < length; i++) {
_doubleValuesSV[i] = Math.sqrt(values[i]);
}
}
}
public static class SignTransformFunction extends SingleParamMathTransformFunction {
public static final String FUNCTION_NAME = "sign";
@Override
public String getName() {
return FUNCTION_NAME;
}
@Override
protected void applyMathOperator(double[] values, int length) {
for (int i = 0; i < length; i++) {
_doubleValuesSV[i] = Math.signum(values[i]);
}
}
}
}