/*
* Copyright (c) 2016, Oracle and/or its affiliates.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to
* endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.oracle.truffle.llvm.nodes.intrinsics.c;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.NodeChildren;
import com.oracle.truffle.api.dsl.NodeField;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.llvm.nodes.intrinsics.llvm.LLVMIntrinsic;
import com.oracle.truffle.llvm.runtime.LLVMAddress;
import com.oracle.truffle.llvm.runtime.memory.LLVMMemory;
import com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode;
/**
* Implements the C functions from math.h.
*/
public abstract class LLVMCMathsIntrinsics {
@NodeChild(type = LLVMExpressionNode.class)
public abstract static class LLVMSqrt extends LLVMIntrinsic {
@Specialization
public double executeIntrinsic(double value) {
return Math.sqrt(value);
}
}
@NodeChild(type = LLVMExpressionNode.class)
public abstract static class LLVMLog extends LLVMIntrinsic {
@Specialization
public double executeIntrinsic(double value) {
return Math.log(value);
}
}
@NodeChild(type = LLVMExpressionNode.class)
public abstract static class LLVMLog2 extends LLVMIntrinsic {
private static final double LOG_2 = Math.log(2);
@Specialization
public double executeIntrinsic(double value) {
return Math.log(value) / LOG_2;
}
}
@NodeChild(type = LLVMExpressionNode.class)
public abstract static class LLVMLog10 extends LLVMIntrinsic {
@Specialization
public double executeIntrinsic(double value) {
return Math.log10(value);
}
}
@NodeChild(type = LLVMExpressionNode.class)
public abstract static class LLVMRint extends LLVMIntrinsic {
@Specialization
public double executeIntrinsic(double value) {
return Math.rint(value);
}
}
@NodeChild(type = LLVMExpressionNode.class)
public abstract static class LLVMCeil extends LLVMIntrinsic {
@Specialization
public double executeIntrinsic(double value) {
return Math.ceil(value);
}
}
@NodeChild(type = LLVMExpressionNode.class)
public abstract static class LLVMFloor extends LLVMIntrinsic {
@Specialization
public double executeIntrinsic(double value) {
return Math.floor(value);
}
}
@NodeChild(type = LLVMExpressionNode.class)
public abstract static class LLVMAbs extends LLVMIntrinsic {
@Specialization
public int executeIntrinsic(int value) {
return Math.abs(value);
}
}
@NodeField(name = "sourceSection", type = SourceSection.class)
@NodeChild(type = LLVMExpressionNode.class)
public abstract static class LLVMFAbs extends LLVMIntrinsic {
@Specialization
public double executeIntrinsic(double value) {
return Math.abs(value);
}
@Override
public abstract SourceSection getSourceSection();
}
@NodeChild(type = LLVMExpressionNode.class)
public abstract static class LLVMExp extends LLVMIntrinsic {
@Specialization
public double executeIntrinsic(double value) {
return Math.exp(value);
}
}
@NodeChild(type = LLVMExpressionNode.class)
public abstract static class LLVMExp2 extends LLVMIntrinsic {
@Specialization
public double executeIntrinsic(double value) {
return Math.pow(2, value);
}
}
@NodeChildren({@NodeChild(type = LLVMExpressionNode.class), @NodeChild(type = LLVMExpressionNode.class)})
public abstract static class LLVMLdexp extends LLVMIntrinsic {
@Specialization
public double executeIntrinsic(double value, int exp) {
return value * Math.pow(2, exp);
}
}
@NodeChildren({@NodeChild(type = LLVMExpressionNode.class), @NodeChild(type = LLVMExpressionNode.class)})
public abstract static class LLVMModf extends LLVMIntrinsic {
@Specialization
public double executeIntrinsic(double value, LLVMAddress integralAddr) {
double fractional = Math.IEEEremainder(value, 1);
double integral = value - fractional;
LLVMMemory.putDouble(integralAddr, integral);
return fractional;
}
}
@NodeChildren({@NodeChild(type = LLVMExpressionNode.class), @NodeChild(type = LLVMExpressionNode.class)})
public abstract static class LLVMFmod extends LLVMIntrinsic {
@Specialization
public double executeIntrinsic(double numer, double denom) {
if (CompilerDirectives.injectBranchProbability(CompilerDirectives.SLOWPATH_PROBABILITY, denom == 0)) {
return 0;
} else {
return Math.IEEEremainder(numer, denom);
}
}
}
@NodeField(name = "sourceSection", type = SourceSection.class)
@NodeChildren({@NodeChild(type = LLVMExpressionNode.class), @NodeChild(type = LLVMExpressionNode.class)})
public abstract static class LLVMPow extends LLVMIntrinsic {
@Specialization
public double executeIntrinsic(double a, double b) {
return Math.pow(a, b);
}
@Specialization
public double executeIntrinsic(double a, int b) {
return Math.pow(a, b);
}
@Specialization
public float executeDouble(float val, float pow) {
return (float) Math.pow(val, pow);
}
@Specialization
public float executeDouble(float val, int pow) {
return (float) Math.pow(val, pow);
}
@Override
public abstract SourceSection getSourceSection();
}
@NodeChild(type = LLVMExpressionNode.class)
public abstract static class LLVMLAbs extends LLVMIntrinsic {
@Specialization
public long executeIntrinsic(long value) {
return Math.abs(value);
}
}
@NodeChild(type = LLVMExpressionNode.class)
public abstract static class LLVMSin extends LLVMIntrinsic {
@Specialization
public double executeIntrinsic(double value) {
return Math.sin(value);
}
@Specialization
public float executeIntrinsic(float value) {
return (float) Math.sin(value);
}
}
@NodeChild(type = LLVMExpressionNode.class)
public abstract static class LLVMSinh extends LLVMIntrinsic {
@Specialization
public double executeIntrinsic(double value) {
return Math.sinh(value);
}
@Specialization
public float executeIntrinsic(float value) {
return (float) Math.sinh(value);
}
}
@NodeChild(type = LLVMExpressionNode.class)
public abstract static class LLVMASin extends LLVMIntrinsic {
@Specialization
public double executeIntrinsic(double value) {
return Math.asin(value);
}
@Specialization
public float executeIntrinsic(float value) {
return (float) Math.asin(value);
}
}
@NodeChild(type = LLVMExpressionNode.class)
public abstract static class LLVMCos extends LLVMIntrinsic {
@Specialization
public double executeIntrinsic(double value) {
return Math.cos(value);
}
@Specialization
public float executeIntrinsic(float value) {
return (float) Math.cos(value);
}
}
@NodeChild(type = LLVMExpressionNode.class)
public abstract static class LLVMCosh extends LLVMIntrinsic {
@Specialization
public double executeIntrinsic(double value) {
return Math.cosh(value);
}
@Specialization
public float executeIntrinsic(float value) {
return (float) Math.cosh(value);
}
}
@NodeChild(type = LLVMExpressionNode.class)
public abstract static class LLVMACos extends LLVMIntrinsic {
@Specialization
public double executeIntrinsic(double value) {
return Math.acos(value);
}
@Specialization
public float executeIntrinsic(float value) {
return (float) Math.acos(value);
}
}
@NodeChild(type = LLVMExpressionNode.class)
public abstract static class LLVMTan extends LLVMIntrinsic {
@Specialization
public double executeIntrinsic(double value) {
return Math.tan(value);
}
@Specialization
public float executeIntrinsic(float value) {
return (float) Math.tan(value);
}
}
@NodeChild(type = LLVMExpressionNode.class)
public abstract static class LLVMTanh extends LLVMIntrinsic {
@Specialization
public double executeIntrinsic(double value) {
return Math.tanh(value);
}
@Specialization
public float executeIntrinsic(float value) {
return (float) Math.tanh(value);
}
}
@NodeChild(type = LLVMExpressionNode.class)
public abstract static class LLVMATan extends LLVMIntrinsic {
@Specialization
public double executeIntrinsic(double value) {
return Math.atan(value);
}
@Specialization
public float executeIntrinsic(float value) {
return (float) Math.atan(value);
}
}
@NodeChildren({@NodeChild(type = LLVMExpressionNode.class), @NodeChild(type = LLVMExpressionNode.class)})
public abstract static class LLVMATan2 extends LLVMIntrinsic {
@Specialization
public double executeIntrinsic(double value1, double value2) {
return Math.atan2(value1, value2);
}
@Specialization
public float executeIntrinsic(float value1, float value2) {
return (float) Math.atan2(value1, value2);
}
}
}