# HG changeset patch # User Doug Simon # Date 1415360192 -3600 # Node ID bf586af6fa0c7fd572aac80828bee54d456bb947 # Parent ab47ef2f220731a62aa1b9c545928288f231017a# Parent 9734f97bddfe7d9308c3ea4025a7ca1972dbc93a Merge. diff -r ab47ef2f2207 -r bf586af6fa0c graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Fri Nov 07 12:35:58 2014 +0100 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Fri Nov 07 12:36:32 2014 +0100 @@ -1006,7 +1006,16 @@ @Override public Value emitMathAbs(Value input) { Variable result = newVariable(LIRKind.derive(input)); - append(new BinaryRegConst(DAND, result, asAllocatable(input), JavaConstant.forDouble(Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL)))); + switch (input.getKind()) { + case Float: + append(new BinaryRegConst(FAND, result, asAllocatable(input), JavaConstant.forFloat(Float.intBitsToFloat(0x7FFFFFFF)))); + break; + case Double: + append(new BinaryRegConst(DAND, result, asAllocatable(input), JavaConstant.forDouble(Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL)))); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } return result; } diff -r ab47ef2f2207 -r bf586af6fa0c graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ArithmeticOpTable.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ArithmeticOpTable.java Fri Nov 07 12:35:58 2014 +0100 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ArithmeticOpTable.java Fri Nov 07 12:36:32 2014 +0100 @@ -41,8 +41,10 @@ import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp.Narrow; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp.SignExtend; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp.ZeroExtend; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp.Abs; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp.Neg; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp.Not; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp.Sqrt; /** * Information about arithmetic operations. @@ -62,6 +64,9 @@ private final BinaryOp or; private final BinaryOp xor; + private final UnaryOp abs; + private final UnaryOp sqrt; + private final IntegerConvertOp zeroExtend; private final IntegerConvertOp signExtend; private final IntegerConvertOp narrow; @@ -76,11 +81,12 @@ } } - public static final ArithmeticOpTable EMPTY = new ArithmeticOpTable(null, null, null, null, null, null, null, null, null, null, null, null, null); + public static final ArithmeticOpTable EMPTY = new ArithmeticOpTable(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null); public ArithmeticOpTable(UnaryOp neg, BinaryOp add, BinaryOp sub, BinaryOp mul, BinaryOp
div, BinaryOp rem, UnaryOp not, BinaryOp and, BinaryOp or, - BinaryOp xor, IntegerConvertOp zeroExtend, IntegerConvertOp signExtend, IntegerConvertOp narrow, FloatConvertOp... floatConvert) { - this(neg, add, sub, mul, div, rem, not, and, or, xor, zeroExtend, signExtend, narrow, Stream.of(floatConvert)); + BinaryOp xor, UnaryOp abs, UnaryOp sqrt, IntegerConvertOp zeroExtend, IntegerConvertOp signExtend, IntegerConvertOp narrow, + FloatConvertOp... floatConvert) { + this(neg, add, sub, mul, div, rem, not, and, or, xor, abs, sqrt, zeroExtend, signExtend, narrow, Stream.of(floatConvert)); } public interface ArithmeticOpWrapper { @@ -116,17 +122,21 @@ BinaryOp or = wrapIfNonNull(wrapper::wrapBinaryOp, inner.getOr()); BinaryOp xor = wrapIfNonNull(wrapper::wrapBinaryOp, inner.getXor()); + UnaryOp abs = wrapIfNonNull(wrapper::wrapUnaryOp, inner.getAbs()); + UnaryOp sqrt = wrapIfNonNull(wrapper::wrapUnaryOp, inner.getSqrt()); + IntegerConvertOp zeroExtend = wrapIfNonNull(wrapper::wrapIntegerConvertOp, inner.getZeroExtend()); IntegerConvertOp signExtend = wrapIfNonNull(wrapper::wrapIntegerConvertOp, inner.getSignExtend()); IntegerConvertOp narrow = wrapIfNonNull(wrapper::wrapIntegerConvertOp, inner.getNarrow()); Stream floatConvert = Stream.of(inner.floatConvert).filter(Objects::nonNull).map(wrapper::wrapFloatConvertOp); - return new ArithmeticOpTable(neg, add, sub, mul, div, rem, not, and, or, xor, zeroExtend, signExtend, narrow, floatConvert); + return new ArithmeticOpTable(neg, add, sub, mul, div, rem, not, and, or, xor, abs, sqrt, zeroExtend, signExtend, narrow, floatConvert); } private ArithmeticOpTable(UnaryOp neg, BinaryOp add, BinaryOp sub, BinaryOp mul, BinaryOp
div, BinaryOp rem, UnaryOp not, BinaryOp and, BinaryOp or, - BinaryOp xor, IntegerConvertOp zeroExtend, IntegerConvertOp signExtend, IntegerConvertOp narrow, Stream floatConvert) { + BinaryOp xor, UnaryOp abs, UnaryOp sqrt, IntegerConvertOp zeroExtend, IntegerConvertOp signExtend, IntegerConvertOp narrow, + Stream floatConvert) { this.neg = neg; this.add = add; this.sub = sub; @@ -137,6 +147,8 @@ this.and = and; this.or = or; this.xor = xor; + this.abs = abs; + this.sqrt = sqrt; this.zeroExtend = zeroExtend; this.signExtend = signExtend; this.narrow = narrow; @@ -215,6 +227,20 @@ } /** + * Describes the absolute value operation. + */ + public UnaryOp getAbs() { + return abs; + } + + /** + * Describes the square root operation. + */ + public UnaryOp getSqrt() { + return sqrt; + } + + /** * Describes the zero extend conversion. */ public IntegerConvertOp getZeroExtend() { @@ -248,7 +274,8 @@ @Override public String toString() { - return getClass().getSimpleName() + "[" + toString(neg, add, sub, mul, div, rem, not, and, or, xor, zeroExtend, signExtend, narrow) + ",floatConvert[" + toString(floatConvert) + "]]"; + return getClass().getSimpleName() + "[" + toString(neg, add, sub, mul, div, rem, not, and, or, xor, abs, sqrt, zeroExtend, signExtend, narrow) + ",floatConvert[" + toString(floatConvert) + + "]]"; } public abstract static class Op { @@ -300,6 +327,20 @@ } } + public abstract static class Abs extends UnaryOp { + + protected Abs() { + super("ABS"); + } + } + + public abstract static class Sqrt extends UnaryOp { + + protected Sqrt() { + super("SQRT"); + } + } + protected UnaryOp(String operation) { super(operation); } diff -r ab47ef2f2207 -r bf586af6fa0c graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java Fri Nov 07 12:35:58 2014 +0100 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java Fri Nov 07 12:36:32 2014 +0100 @@ -452,7 +452,191 @@ } }, - null, null, null, null, + new UnaryOp.Not() { + + @Override + public Constant foldConstant(Constant c) { + PrimitiveConstant value = (PrimitiveConstant) c; + switch (value.getKind()) { + case Float: + int f = Float.floatToRawIntBits(value.asFloat()); + return JavaConstant.forFloat(Float.intBitsToFloat(~f)); + case Double: + long d = Double.doubleToRawLongBits(value.asDouble()); + return JavaConstant.forDouble(Double.longBitsToDouble(~d)); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + @Override + public Stamp foldStamp(Stamp s) { + return s.unrestricted(); + } + }, + + new BinaryOp.And(true, true) { + + @Override + public Constant foldConstant(Constant const1, Constant const2) { + PrimitiveConstant a = (PrimitiveConstant) const1; + PrimitiveConstant b = (PrimitiveConstant) const2; + assert a.getKind() == b.getKind(); + switch (a.getKind()) { + case Float: + int fa = Float.floatToRawIntBits(a.asFloat()); + int fb = Float.floatToRawIntBits(b.asFloat()); + return JavaConstant.forFloat(Float.intBitsToFloat(fa & fb)); + case Double: + long da = Double.doubleToRawLongBits(a.asDouble()); + long db = Double.doubleToRawLongBits(b.asDouble()); + return JavaConstant.forDouble(Double.longBitsToDouble(da & db)); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + @Override + public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { + return stamp1.unrestricted(); + } + + @Override + public boolean isNeutral(Constant n) { + PrimitiveConstant value = (PrimitiveConstant) n; + switch (value.getKind()) { + case Float: + return Float.floatToRawIntBits(value.asFloat()) == 0xFFFFFFFF; + case Double: + return Double.doubleToRawLongBits(value.asDouble()) == 0xFFFFFFFFFFFFFFFFL; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + }, + + new BinaryOp.Or(true, true) { + + @Override + public Constant foldConstant(Constant const1, Constant const2) { + PrimitiveConstant a = (PrimitiveConstant) const1; + PrimitiveConstant b = (PrimitiveConstant) const2; + assert a.getKind() == b.getKind(); + switch (a.getKind()) { + case Float: + int fa = Float.floatToRawIntBits(a.asFloat()); + int fb = Float.floatToRawIntBits(b.asFloat()); + return JavaConstant.forFloat(Float.intBitsToFloat(fa | fb)); + case Double: + long da = Double.doubleToRawLongBits(a.asDouble()); + long db = Double.doubleToRawLongBits(b.asDouble()); + return JavaConstant.forDouble(Double.longBitsToDouble(da | db)); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + @Override + public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { + return stamp1.unrestricted(); + } + + @Override + public boolean isNeutral(Constant n) { + PrimitiveConstant value = (PrimitiveConstant) n; + switch (value.getKind()) { + case Float: + return Float.floatToRawIntBits(value.asFloat()) == 0; + case Double: + return Double.doubleToRawLongBits(value.asDouble()) == 0L; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + }, + + new BinaryOp.Xor(true, true) { + + @Override + public Constant foldConstant(Constant const1, Constant const2) { + PrimitiveConstant a = (PrimitiveConstant) const1; + PrimitiveConstant b = (PrimitiveConstant) const2; + assert a.getKind() == b.getKind(); + switch (a.getKind()) { + case Float: + int fa = Float.floatToRawIntBits(a.asFloat()); + int fb = Float.floatToRawIntBits(b.asFloat()); + return JavaConstant.forFloat(Float.intBitsToFloat(fa ^ fb)); + case Double: + long da = Double.doubleToRawLongBits(a.asDouble()); + long db = Double.doubleToRawLongBits(b.asDouble()); + return JavaConstant.forDouble(Double.longBitsToDouble(da ^ db)); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + @Override + public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { + return stamp1.unrestricted(); + } + + @Override + public boolean isNeutral(Constant n) { + PrimitiveConstant value = (PrimitiveConstant) n; + switch (value.getKind()) { + case Float: + return Float.floatToRawIntBits(value.asFloat()) == 0; + case Double: + return Double.doubleToRawLongBits(value.asDouble()) == 0L; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + }, + + new UnaryOp.Abs() { + + @Override + public Constant foldConstant(Constant c) { + PrimitiveConstant value = (PrimitiveConstant) c; + switch (value.getKind()) { + case Float: + return JavaConstant.forFloat(Math.abs(value.asFloat())); + case Double: + return JavaConstant.forDouble(Math.abs(value.asDouble())); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + @Override + public Stamp foldStamp(Stamp s) { + FloatStamp stamp = (FloatStamp) s; + return new FloatStamp(stamp.getBits(), 0, Math.max(-stamp.lowerBound(), stamp.upperBound()), stamp.isNonNaN()); + } + }, + + new UnaryOp.Sqrt() { + + @Override + public Constant foldConstant(Constant c) { + PrimitiveConstant value = (PrimitiveConstant) c; + switch (value.getKind()) { + case Float: + return JavaConstant.forFloat((float) Math.sqrt(value.asFloat())); + case Double: + return JavaConstant.forDouble(Math.sqrt(value.asDouble())); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + @Override + public Stamp foldStamp(Stamp s) { + return s.unrestricted(); + } + }, null, null, null, diff -r ab47ef2f2207 -r bf586af6fa0c graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java Fri Nov 07 12:35:58 2014 +0100 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java Fri Nov 07 12:36:32 2014 +0100 @@ -678,6 +678,29 @@ } }, + new UnaryOp.Abs() { + + @Override + public Constant foldConstant(Constant value) { + PrimitiveConstant c = (PrimitiveConstant) value; + return PrimitiveConstant.forIntegerKind(c.getKind(), Math.abs(c.asLong())); + } + + @Override + public Stamp foldStamp(Stamp input) { + IntegerStamp stamp = (IntegerStamp) input; + int bits = stamp.getBits(); + if (stamp.lowerBound() == CodeUtil.minValue(bits)) { + return input.unrestricted(); + } else { + long limit = Math.max(-stamp.lowerBound(), stamp.upperBound()); + return StampFactory.forInteger(bits, 0, limit); + } + } + }, + + null, + new IntegerConvertOp.ZeroExtend() { @Override diff -r ab47ef2f2207 -r bf586af6fa0c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AbsNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AbsNode.java Fri Nov 07 12:36:32 2014 +0100 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes.calc; + +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp.Abs; +import com.oracle.graal.graph.spi.*; +import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; + +/** + * Absolute value. + */ +@NodeInfo +public class AbsNode extends UnaryArithmeticNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode { + + public static AbsNode create(ValueNode x) { + return new AbsNode(x); + } + + protected AbsNode(ValueNode x) { + super(ArithmeticOpTable::getAbs, x); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + ValueNode ret = super.canonical(tool, forValue); + if (ret != this) { + return ret; + } + if (forValue instanceof AbsNode) { + return forValue; + } + return this; + } + + @Override + public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { + builder.setResult(this, gen.emitMathAbs(builder.operand(getValue()))); + } + + @NodeIntrinsic + public static float abs(float n) { + return Math.abs(n); + } + + @NodeIntrinsic + public static double abs(double n) { + return Math.abs(n); + } +} diff -r ab47ef2f2207 -r bf586af6fa0c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SqrtNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SqrtNode.java Fri Nov 07 12:36:32 2014 +0100 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes.calc; + +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp.Sqrt; +import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; + +/** + * Square root. + */ +@NodeInfo +public class SqrtNode extends UnaryArithmeticNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode { + + public static SqrtNode create(ValueNode x) { + return new SqrtNode(x); + } + + protected SqrtNode(ValueNode x) { + super(ArithmeticOpTable::getSqrt, x); + } + + @Override + public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { + builder.setResult(this, gen.emitMathSqrt(builder.operand(getValue()))); + } + + @NodeIntrinsic + public static double sqrt(double n) { + return Math.sqrt(n); + } +} diff -r ab47ef2f2207 -r bf586af6fa0c graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java Fri Nov 07 12:35:58 2014 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java Fri Nov 07 12:36:32 2014 +0100 @@ -39,7 +39,7 @@ @Test public void testMathSubstitutions() { - assertInGraph(assertNotInGraph(test("mathAbs"), IfNode.class), MathIntrinsicNode.class); // Java + assertInGraph(assertNotInGraph(test("mathAbs"), IfNode.class), AbsNode.class); // Java test("math"); double value = 34567.891D; diff -r ab47ef2f2207 -r bf586af6fa0c graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/MathSubstitutionsX86.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/MathSubstitutionsX86.java Fri Nov 07 12:35:58 2014 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/MathSubstitutionsX86.java Fri Nov 07 12:36:32 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ import com.oracle.graal.api.replacements.*; import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; +import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.replacements.nodes.MathIntrinsicNode.Operation; @@ -39,13 +40,18 @@ private static final double PI_4 = Math.PI / 4; @MethodSubstitution + public static float abs(float x) { + return AbsNode.abs(x); + } + + @MethodSubstitution public static double abs(double x) { - return MathIntrinsicNode.compute(x, Operation.ABS); + return AbsNode.abs(x); } @MethodSubstitution public static double sqrt(double x) { - return MathIntrinsicNode.compute(x, Operation.SQRT); + return SqrtNode.sqrt(x); } @MethodSubstitution(guard = UnsafeSubstitutions.GetAndSetGuard.class) diff -r ab47ef2f2207 -r bf586af6fa0c graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java Fri Nov 07 12:35:58 2014 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java Fri Nov 07 12:36:32 2014 +0100 @@ -38,8 +38,6 @@ protected final Operation operation; public enum Operation { - ABS, - SQRT, LOG, LOG10, SIN, @@ -66,12 +64,6 @@ Value input = builder.operand(getValue()); Value result; switch (operation()) { - case ABS: - result = gen.emitMathAbs(input); - break; - case SQRT: - result = gen.emitMathSqrt(input); - break; case LOG: result = gen.emitMathLog(input, false); break; @@ -109,10 +101,6 @@ private static double doCompute(double value, Operation op) { switch (op) { - case ABS: - return Math.abs(value); - case SQRT: - return Math.sqrt(value); case LOG: return Math.log(value); case LOG10: