All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.speedment.runtime.compute.internal.expression.PowUtil Maven / Gradle / Ivy

Go to download

A Speedment bundle that shades all dependencies into one jar. This is useful when deploying an application on a server.

The newest version!
/*
 *
 * Copyright (c) 2006-2019, Speedment, Inc. All Rights Reserved.
 *
 * Licensed 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 com.speedment.runtime.compute.internal.expression;

import com.speedment.runtime.compute.ToByte;
import com.speedment.runtime.compute.ToDouble;
import com.speedment.runtime.compute.ToFloat;
import com.speedment.runtime.compute.ToInt;
import com.speedment.runtime.compute.ToLong;
import com.speedment.runtime.compute.ToShort;
import com.speedment.runtime.compute.expression.BinaryExpression;
import com.speedment.runtime.compute.expression.BinaryObjExpression;
import com.speedment.runtime.compute.expression.Expression;

import java.util.Objects;

import static java.util.Objects.requireNonNull;

/**
 * Utility class for creating expressions that takes the value of another
 * expression and raises it to a particular power.
 *
 * @author Emil Forslund
 * @since  3.1.0
 */
public final class PowUtil {

    ////////////////////////////////////////////////////////////////////////////
    //                                 ToByte                                 //
    ////////////////////////////////////////////////////////////////////////////

    /**
     * Returns an expression that gives the value of the specified expression,
     * raised to the specified power.
     *
     * @param expression  the expression to raise
     * @param power       the power to raise it to
     * @param          the type of the input
     * @return            the new expression
     */
    public static  ToDouble bytePowInt(ToByte expression, int power) {
        switch (power) {
            case 0: return ToDouble.constant(1);
            case 1: return expression.asDouble();
            case 2: return new IntPower>(expression, 2) {
                @Override
                public double applyAsDouble(T object) {
                    final double value = inner.applyAsByte(object);
                    return value * value;
                }
            };
            case 3: return new IntPower>(expression, 3) {
                @Override
                public double applyAsDouble(T object) {
                    final double value = inner.applyAsByte(object);
                    return value * value * value;
                }
            };
            case -1: return new IntPower>(expression, -1) {
                @Override
                public double applyAsDouble(T object) {
                    return 1d / inner.applyAsByte(object);
                }
            };
            default: return new IntPower>(expression, power) {
                @Override
                public double applyAsDouble(T object) {
                    return Math.pow(inner.applyAsByte(object), this.power);
                }
            };
        }
    }

    /**
     * Returns an expression that gives the value of the specified expression,
     * raised to the specified power.
     *
     * @param expression  the expression to raise
     * @param power       the power to raise it to
     * @param          the type of the input
     * @return            the new expression
     */
    public static  ToDouble bytePowDouble(ToByte expression, double power) {
        return new DoublePower>(expression, power) {
            @Override
            public double applyAsDouble(T object) {
                return Math.pow(inner.applyAsByte(object), this.power);
            }
        };
    }

    /**
     * Returns an expression that gives the value of the specified expression,
     * raised to the specified power.
     *
     * @param expression  the expression to raise
     * @param power       the power to raise it to
     * @param          the type of the input
     * @return            the new expression
     */
    public static  ToDouble bytePowInt(ToByte expression, ToInt power) {
        return new ToIntPower>(expression, power) {
            @Override
            public double applyAsDouble(T object) {
                final int p = power.applyAsInt(object);
                if (p == 0) return 1;
                final double value = inner.applyAsByte(object);
                switch (p) {
                    case 1: return value;
                    case 2: return value * value;
                    case 3: return value * value * value;
                    case 4: return value * value * value * value;
                    case 5: return value * value * value * value * value;
                    case -1: return 1d / value;
                    default: return Math.pow(value, p);
                }
            }
        };
    }

    /**
     * Returns an expression that gives the value of the specified expression,
     * raised to the specified power.
     *
     * @param expression  the expression to raise
     * @param power       the power to raise it to
     * @param          the type of the input
     * @return            the new expression
     */
    public static  ToDouble bytePowDouble(ToByte expression, ToDouble power) {
        return new ToDoublePower>(expression, power) {
            @Override
            public double applyAsDouble(T object) {
                return Math.pow(
                    inner.applyAsByte(object),
                    power.applyAsDouble(object)
                );
            }
        };
    }

    ////////////////////////////////////////////////////////////////////////////
    //                                 ToShort                                //
    ////////////////////////////////////////////////////////////////////////////

    /**
     * Returns an expression that gives the value of the specified expression,
     * raised to the specified power.
     *
     * @param expression  the expression to raise
     * @param power       the power to raise it to
     * @param          the type of the input
     * @return            the new expression
     */
    public static  ToDouble shortPowInt(ToShort expression, int power) {
        switch (power) {
            case 0: return ToDouble.constant(1);
            case 1: return expression.asDouble();
            case 2: return new IntPower>(expression, 2) {
                @Override
                public double applyAsDouble(T object) {
                    final double value = inner.applyAsShort(object);
                    return value * value;
                }
            };
            case 3: return new IntPower>(expression, 3) {
                @Override
                public double applyAsDouble(T object) {
                    final double value = inner.applyAsShort(object);
                    return value * value * value;
                }
            };
            case -1: return new IntPower>(expression, -1) {
                @Override
                public double applyAsDouble(T object) {
                    return 1d / inner.applyAsShort(object);
                }
            };
            default: return new IntPower>(expression, power) {
                @Override
                public double applyAsDouble(T object) {
                    return Math.pow(inner.applyAsShort(object), this.power);
                }
            };
        }
    }

    /**
     * Returns an expression that gives the value of the specified expression,
     * raised to the specified power.
     *
     * @param expression  the expression to raise
     * @param power       the power to raise it to
     * @param          the type of the input
     * @return            the new expression
     */
    public static  ToDouble shortPowDouble(ToShort expression, double power) {
        return new DoublePower>(expression, power) {
            @Override
            public double applyAsDouble(T object) {
                return Math.pow(inner.applyAsShort(object), this.power);
            }
        };
    }

    /**
     * Returns an expression that gives the value of the specified expression,
     * raised to the specified power.
     *
     * @param expression  the expression to raise
     * @param power       the power to raise it to
     * @param          the type of the input
     * @return            the new expression
     */
    public static  ToDouble shortPowInt(ToShort expression, ToInt power) {
        return new ToIntPower>(expression, power) {
            @Override
            public double applyAsDouble(T object) {
                final int p = power.applyAsInt(object);
                if (p == 0) return 1;
                final double value = inner.applyAsShort(object);
                switch (p) {
                    case 1: return value;
                    case 2: return value * value;
                    case 3: return value * value * value;
                    case 4: return value * value * value * value;
                    case 5: return value * value * value * value * value;
                    case -1: return 1d / value;
                    default: return Math.pow(value, p);
                }
            }
        };
    }

    /**
     * Returns an expression that gives the value of the specified expression,
     * raised to the specified power.
     *
     * @param expression  the expression to raise
     * @param power       the power to raise it to
     * @param          the type of the input
     * @return            the new expression
     */
    public static  ToDouble shortPowDouble(ToShort expression, ToDouble power) {
        return new ToDoublePower>(expression, power) {
            @Override
            public double applyAsDouble(T object) {
                return Math.pow(
                    inner.applyAsShort(object),
                    power.applyAsDouble(object)
                );
            }
        };
    }

    ////////////////////////////////////////////////////////////////////////////
    //                                 ToInt                                  //
    ////////////////////////////////////////////////////////////////////////////

    /**
     * Returns an expression that gives the value of the specified expression,
     * raised to the specified power.
     *
     * @param expression  the expression to raise
     * @param power       the power to raise it to
     * @param          the type of the input
     * @return            the new expression
     */
    public static  ToDouble intPowInt(ToInt expression, int power) {
        switch (power) {
            case 0: return ToDouble.constant(1);
            case 1: return expression.asDouble();
            case 2: return new IntPower>(expression, 2) {
                @Override
                public double applyAsDouble(T object) {
                    final double value = inner.applyAsInt(object);
                    return value * value;
                }
            };
            case 3: return new IntPower>(expression, 3) {
                @Override
                public double applyAsDouble(T object) {
                    final double value = inner.applyAsInt(object);
                    return value * value * value;
                }
            };
            case -1: return new IntPower>(expression, -1) {
                @Override
                public double applyAsDouble(T object) {
                    return 1d / inner.applyAsInt(object);
                }
            };
            default: return new IntPower>(expression, power) {
                @Override
                public double applyAsDouble(T object) {
                    return Math.pow(inner.applyAsInt(object), this.power);
                }
            };
        }
    }

    /**
     * Returns an expression that gives the value of the specified expression,
     * raised to the specified power.
     *
     * @param expression  the expression to raise
     * @param power       the power to raise it to
     * @param          the type of the input
     * @return            the new expression
     */
    public static  ToDouble intPowDouble(ToInt expression, double power) {
        return new DoublePower>(expression, power) {
            @Override
            public double applyAsDouble(T object) {
                return Math.pow(inner.applyAsInt(object), this.power);
            }
        };
    }

    /**
     * Returns an expression that gives the value of the specified expression,
     * raised to the specified power.
     *
     * @param expression  the expression to raise
     * @param power       the power to raise it to
     * @param          the type of the input
     * @return            the new expression
     */
    public static  ToDouble intPowInt(ToInt expression, ToInt power) {
        return new ToIntPower>(expression, power) {
            @Override
            public double applyAsDouble(T object) {
                final int p = power.applyAsInt(object);
                if (p == 0) return 1;
                final double value = inner.applyAsInt(object);
                switch (p) {
                    case 1: return value;
                    case 2: return value * value;
                    case 3: return value * value * value;
                    case 4: return value * value * value * value;
                    case 5: return value * value * value * value * value;
                    case -1: return 1d / value;
                    default: return Math.pow(value, p);
                }
            }
        };
    }

    /**
     * Returns an expression that gives the value of the specified expression,
     * raised to the specified power.
     *
     * @param expression  the expression to raise
     * @param power       the power to raise it to
     * @param          the type of the input
     * @return            the new expression
     */
    public static  ToDouble intPowDouble(ToInt expression, ToDouble power) {
        return new ToDoublePower>(expression, power) {
            @Override
            public double applyAsDouble(T object) {
                return Math.pow(
                    inner.applyAsInt(object),
                    power.applyAsDouble(object)
                );
            }
        };
    }

    ////////////////////////////////////////////////////////////////////////////
    //                                 ToLong                                 //
    ////////////////////////////////////////////////////////////////////////////

    /**
     * Returns an expression that gives the value of the specified expression,
     * raised to the specified power.
     *
     * @param expression  the expression to raise
     * @param power       the power to raise it to
     * @param          the type of the input
     * @return            the new expression
     */
    public static  ToDouble longPowInt(ToLong expression, int power) {
        switch (power) {
            case 0: return ToDouble.constant(1);
            case 1: return expression.asDouble();
            case 2: return new IntPower>(expression, 2) {
                @Override
                public double applyAsDouble(T object) {
                    final double value = inner.applyAsLong(object);
                    return value * value;
                }
            };
            case 3: return new IntPower>(expression, 3) {
                @Override
                public double applyAsDouble(T object) {
                    final double value = inner.applyAsLong(object);
                    return value * value * value;
                }
            };
            case -1: return new IntPower>(expression, -1) {
                @Override
                public double applyAsDouble(T object) {
                    return 1d / inner.applyAsLong(object);
                }
            };
            default: return new IntPower>(expression, power) {
                @Override
                public double applyAsDouble(T object) {
                    return Math.pow(inner.applyAsLong(object), this.power);
                }
            };
        }
    }

    /**
     * Returns an expression that gives the value of the specified expression,
     * raised to the specified power.
     *
     * @param expression  the expression to raise
     * @param power       the power to raise it to
     * @param          the type of the input
     * @return            the new expression
     */
    public static  ToDouble longPowDouble(ToLong expression, double power) {
        return new DoublePower>(expression, power) {
            @Override
            public double applyAsDouble(T object) {
                return Math.pow(inner.applyAsLong(object), this.power);
            }
        };
    }

    /**
     * Returns an expression that gives the value of the specified expression,
     * raised to the specified power.
     *
     * @param expression  the expression to raise
     * @param power       the power to raise it to
     * @param          the type of the input
     * @return            the new expression
     */
    public static  ToDouble longPowInt(ToLong expression, ToInt power) {
        return new ToIntPower>(expression, power) {
            @Override
            public double applyAsDouble(T object) {
                final int p = power.applyAsInt(object);
                if (p == 0) return 1;
                final double value = inner.applyAsLong(object);
                switch (p) {
                    case 1: return value;
                    case 2: return value * value;
                    case 3: return value * value * value;
                    case 4: return value * value * value * value;
                    case 5: return value * value * value * value * value;
                    case -1: return 1d / value;
                    default: return Math.pow(value, p);
                }
            }
        };
    }

    /**
     * Returns an expression that gives the value of the specified expression,
     * raised to the specified power.
     *
     * @param expression  the expression to raise
     * @param power       the power to raise it to
     * @param          the type of the input
     * @return            the new expression
     */
    public static  ToDouble longPowDouble(ToLong expression, ToDouble power) {
        return new ToDoublePower>(expression, power) {
            @Override
            public double applyAsDouble(T object) {
                return Math.pow(
                    inner.applyAsLong(object),
                    power.applyAsDouble(object)
                );
            }
        };
    }

    ////////////////////////////////////////////////////////////////////////////
    //                                 ToFloat                                //
    ////////////////////////////////////////////////////////////////////////////

    /**
     * Returns an expression that gives the value of the specified expression,
     * raised to the specified power.
     *
     * @param expression  the expression to raise
     * @param power       the power to raise it to
     * @param          the type of the input
     * @return            the new expression
     */
    public static  ToDouble floatPowInt(ToFloat expression, int power) {
        switch (power) {
            case 0: return ToDouble.constant(1);
            case 1: return expression.asDouble();
            case 2: return new IntPower>(expression, 2) {
                @Override
                public double applyAsDouble(T object) {
                    final float value = inner.applyAsFloat(object);
                    return value * value;
                }
            };
            case 3: return new IntPower>(expression, 3) {
                @Override
                public double applyAsDouble(T object) {
                    final float value = inner.applyAsFloat(object);
                    return value * value * value;
                }
            };
            case -1: return new IntPower>(expression, -1) {
                @Override
                public double applyAsDouble(T object) {
                    return 1 / inner.applyAsFloat(object);
                }
            };
            default: return new IntPower>(expression, power) {
                @Override
                public double applyAsDouble(T object) {
                    return Math.pow(inner.applyAsFloat(object), this.power);
                }
            };
        }
    }

    /**
     * Returns an expression that gives the value of the specified expression,
     * raised to the specified power.
     *
     * @param expression  the expression to raise
     * @param power       the power to raise it to
     * @param          the type of the input
     * @return            the new expression
     */
    public static  ToDouble floatPowDouble(ToFloat expression, double power) {
        return new DoublePower>(expression, power) {
            @Override
            public double applyAsDouble(T object) {
                return Math.pow(inner.applyAsFloat(object), this.power);
            }
        };
    }

    /**
     * Returns an expression that gives the value of the specified expression,
     * raised to the specified power.
     *
     * @param expression  the expression to raise
     * @param power       the power to raise it to
     * @param          the type of the input
     * @return            the new expression
     */
    public static  ToDouble floatPowInt(ToFloat expression, ToInt power) {
        return new ToIntPower>(expression, power) {
            @Override
            public double applyAsDouble(T object) {
                final int p = power.applyAsInt(object);
                if (p == 0) return 1;
                final float value = inner.applyAsFloat(object);
                switch (p) {
                    case 1: return value;
                    case 2: return value * value;
                    case 3: return value * value * value;
                    case 4: return value * value * value * value;
                    case 5: return value * value * value * value * value;
                    case -1: return 1 / value;
                    default: return Math.pow(value, p);
                }
            }
        };
    }

    /**
     * Returns an expression that gives the value of the specified expression,
     * raised to the specified power.
     *
     * @param expression  the expression to raise
     * @param power       the power to raise it to
     * @param          the type of the input
     * @return            the new expression
     */
    public static  ToDouble floatPowDouble(ToFloat expression, ToDouble power) {
        return new ToDoublePower>(expression, power) {
            @Override
            public double applyAsDouble(T object) {
                return Math.pow(
                    inner.applyAsFloat(object),
                    power.applyAsDouble(object)
                );
            }
        };
    }

    ////////////////////////////////////////////////////////////////////////////
    //                                 ToDouble                                //
    ////////////////////////////////////////////////////////////////////////////

    /**
     * Returns an expression that gives the value of the specified expression,
     * raised to the specified power.
     *
     * @param expression  the expression to raise
     * @param power       the power to raise it to
     * @param          the type of the input
     * @return            the new expression
     */
    public static  ToDouble doublePowInt(ToDouble expression, int power) {
        switch (power) {
            case 0: return ToDouble.constant(1);
            case 1: return expression.asDouble();
            case 2: return new IntPower>(expression, 2) {
                @Override
                public double applyAsDouble(T object) {
                    final double value = inner.applyAsDouble(object);
                    return value * value;
                }
            };
            case 3: return new IntPower>(expression, 3) {
                @Override
                public double applyAsDouble(T object) {
                    final double value = inner.applyAsDouble(object);
                    return value * value * value;
                }
            };
            case -1: return new IntPower>(expression, -1) {
                @Override
                public double applyAsDouble(T object) {
                    return 1 / inner.applyAsDouble(object);
                }
            };
            default: return new IntPower>(expression, power) {
                @Override
                public double applyAsDouble(T object) {
                    return Math.pow(inner.applyAsDouble(object), this.power);
                }
            };
        }
    }

    /**
     * Returns an expression that gives the value of the specified expression,
     * raised to the specified power.
     *
     * @param expression  the expression to raise
     * @param power       the power to raise it to
     * @param          the type of the input
     * @return            the new expression
     */
    public static  ToDouble doublePowDouble(ToDouble expression, double power) {
        return new DoublePower>(expression, power) {
            @Override
            public double applyAsDouble(T object) {
                return Math.pow(inner.applyAsDouble(object), this.power);
            }
        };
    }

    /**
     * Returns an expression that gives the value of the specified expression,
     * raised to the specified power.
     *
     * @param expression  the expression to raise
     * @param power       the power to raise it to
     * @param          the type of the input
     * @return            the new expression
     */
    public static  ToDouble doublePowInt(ToDouble expression, ToInt power) {
        return new ToIntPower>(expression, power) {
            @Override
            public double applyAsDouble(T object) {
                final int p = power.applyAsInt(object);
                if (p == 0) return 1;
                final double value = inner.applyAsDouble(object);
                switch (p) {
                    case 1: return value;
                    case 2: return value * value;
                    case 3: return value * value * value;
                    case 4: return value * value * value * value;
                    case 5: return value * value * value * value * value;
                    case -1: return 1 / value;
                    default: return Math.pow(value, p);
                }
            }
        };
    }

    /**
     * Returns an expression that gives the value of the specified expression,
     * raised to the specified power.
     *
     * @param expression  the expression to raise
     * @param power       the power to raise it to
     * @param          the type of the input
     * @return            the new expression
     */
    public static  ToDouble doublePowDouble(ToDouble expression, ToDouble power) {
        return new ToDoublePower>(expression, power) {
            @Override
            public double applyAsDouble(T object) {
                return Math.pow(
                    inner.applyAsDouble(object),
                    power.applyAsDouble(object)
                );
            }
        };
    }

    ////////////////////////////////////////////////////////////////////////////
    //                          Internal Base Classes                         //
    ////////////////////////////////////////////////////////////////////////////

    /**
     * Abstract base implementation of a power expression.
     *
     * @param       the input type
     * @param   the inner expression type
     */
    private abstract static class IntPower>
    implements BinaryObjExpression, ToDouble {

        final INNER inner;
        final int power;

        IntPower(INNER inner, int power) {
            this.inner = requireNonNull(inner);
            this.power = power;
        }

        @Override
        public final INNER first() {
            return inner;
        }

        @Override
        public final Integer second() {
            return power;
        }

        @Override
        public final Operator operator() {
            return Operator.POW;
        }

        @Override
        public final boolean equals(Object o) {
            if (o == null) return false;
            else if (this == o) return true;
            else if (!(o instanceof BinaryObjExpression)) return false;
            final BinaryObjExpression that = (BinaryObjExpression) o;
            return Objects.equals(inner, that.first()) &&
                Objects.equals(power, that.second()) &&
                Objects.equals(operator(), that.operator());
        }

        @Override
        public final int hashCode() {
            return Objects.hash(inner, power, operator());
        }
    }

    /**
     * Abstract base implementation of a power expression.
     *
     * @param       the input type
     * @param   the inner expression type
     */
    private abstract static class DoublePower>
        implements BinaryObjExpression, ToDouble {

        final INNER inner;
        final double power;

        DoublePower(INNER inner, double power) {
            this.inner = requireNonNull(inner);
            this.power = power;
        }

        @Override
        public final INNER first() {
            return inner;
        }

        @Override
        public final Double second() {
            return power;
        }

        @Override
        public final Operator operator() {
            return Operator.POW;
        }

        @Override
        public final boolean equals(Object o) {
            if (o == null) return false;
            else if (this == o) return true;
            else if (!(o instanceof BinaryObjExpression)) return false;
            final BinaryObjExpression that = (BinaryObjExpression) o;
            return Objects.equals(inner, that.first()) &&
                Objects.equals(power, that.second()) &&
                Objects.equals(operator(), that.operator());
        }

        @Override
        public final int hashCode() {
            return Objects.hash(inner, power, operator());
        }
    }

    /**
     * Abstract base implementation of a power expression.
     *
     * @param       the input type
     * @param   the inner expression type
     */
    private abstract static class ToIntPower>
    implements BinaryExpression>, ToDouble {

        final INNER inner;
        final ToInt power;

        ToIntPower(INNER inner, ToInt power) {
            this.inner = requireNonNull(inner);
            this.power = requireNonNull(power);
        }

        @Override
        public final INNER first() {
            return inner;
        }

        @Override
        public final ToInt second() {
            return power;
        }

        @Override
        public final Operator operator() {
            return Operator.POW;
        }

        @Override
        public final boolean equals(Object o) {
            if (o == null) return false;
            else if (this == o) return true;
            else if (!(o instanceof BinaryExpression)) return false;
            final BinaryExpression that = (BinaryExpression) o;
            return Objects.equals(inner, that.first()) &&
                Objects.equals(power, that.second()) &&
                Objects.equals(operator(), that.operator());
        }

        @Override
        public final int hashCode() {
            return Objects.hash(inner, power, operator());
        }
    }

    /**
     * Abstract base implementation of a power expression.
     *
     * @param       the input type
     * @param   the inner expression type
     */
    private abstract static class ToDoublePower>
    implements BinaryExpression>, ToDouble {

        final INNER inner;
        final ToDouble power;

        ToDoublePower(INNER inner, ToDouble power) {
            this.inner = requireNonNull(inner);
            this.power = requireNonNull(power);
        }

        @Override
        public final INNER first() {
            return inner;
        }

        @Override
        public final ToDouble second() {
            return power;
        }

        @Override
        public final Operator operator() {
            return Operator.POW;
        }

        @Override
        public final boolean equals(Object o) {
            if (o == null) return false;
            else if (this == o) return true;
            else if (!(o instanceof BinaryExpression)) return false;
            final BinaryExpression that = (BinaryExpression) o;
            return Objects.equals(inner, that.first()) &&
                Objects.equals(power, that.second()) &&
                Objects.equals(operator(), that.operator());
        }

        @Override
        public final int hashCode() {
            return Objects.hash(inner, power, operator());
        }
    }

    /**
     * Utility classes should not be instantiated.
     */
    private PowUtil() {}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy