Package r.builtins

Source Code of r.builtins.MathBase

package r.builtins;

import r.data.*;
import r.data.internal.*;
import r.data.internal.ProfilingView.ViewProfile;
import r.errors.*;
import r.nodes.ast.*;
import r.nodes.exec.*;
import r.runtime.*;

// TODO: complex numbers
// TODO: nan produced warnings and checks (note - only some of the operations implemented by subclasses can produce an NaN)
abstract class MathBase extends CallFactory {

    MathBase(String name) {
        super(name, new String[]{"x"}, null);
    }

    abstract double op(ASTNode ast, double value);
    abstract void op(ASTNode ast, double[] x, double[] res);

    final RDouble calcEager(final ASTNode ast, final RDouble value) {
        double[] content = value.getContent();
        if (value.isTemporary()) {
            op(ast, content, content);
            return value;
        }
        int size = value.size();
        double[] res = new double[size];
        op(ast, content, res);
        return RDouble.RDoubleFactory.getFor(res, value.dimensions(), value.names(), value.attributes());
    }

    private RDouble createView(final ASTNode ast, final RDouble value, final int size) {
        return TracingView.ViewTrace.trace(new View.RDoubleProxy<RDouble>(value) {
            @Override public int size() {
                return size;
            }

            @Override public double getDouble(int i) {
                return op(ast, value.getDouble(i));
            }
            @Override
            public void materializeInto(double[] resContent) {
                if (orig instanceof DoubleImpl) {
                    op(ast, orig.getContent(), resContent);
                } else if (orig instanceof RDoubleView) {
                    ((RDoubleView) orig).materializeInto(resContent);
                    op(ast, resContent, resContent);
                } else  {
                    super.materializeInto(resContent);
                }
            }
            @Override
            public void materializeIntoOnTheFly(double[] resContent) {
                if (orig instanceof DoubleImpl) {
                    op(ast, orig.getContent(), resContent);
                } else  {
                    super.materializeIntoOnTheFly(resContent);
                }
            }
            @Override
            public void accept(ValueVisitor v) {
                v.visit(this);
            }
        });
    }

    @Override
    public RNode create(ASTNode call, RSymbol[] names, RNode[] exprs) {
        check(call, names, exprs);
        return new MathBuiltin(call, names, exprs);
    }

    public class MathBuiltin extends Builtin.Builtin1 {

        public MathBuiltin(ASTNode ast, RSymbol[] names, RNode[] exprs) {
            super(ast, names, exprs);
        }

        @Override
        public RAny doBuiltIn(Frame frame, RAny value) {
            if (value instanceof RDouble || value instanceof RInt || value instanceof RLogical) {
                return calcInitial(value.asDouble());
            }
            throw RError.getNonNumericMath(ast);
        }

        private ViewProfile profile;

        RDouble calcInitial(final RDouble value) {
            final int size = value.size();
            if (size == 1) {
                return RDouble.RDoubleFactory.getScalar(op(ast, value.getDouble(0)), value.dimensions(), value.names(), value.attributesRef());
            } else if (size > 0) {
                if (profile == null) {
                    profile = new ViewProfile();
                    return ProfilingView.ViewProfile.profile(createView(ast, value, size), profile);
                } else {
                    if (profile.shouldBeLazy()) {
                        return replaceAndExecuteLazy(value);
                    } else {
                        return replaceAndExecuteEager(value);
                    }
                }
            }
            return RDouble.EMPTY;
        }

        RDouble replaceAndExecuteLazy(final RDouble currentValue) {
            RNode newNode = new Builtin.Builtin1(ast, argNames, argExprs) {
                @Override
                public RAny doBuiltIn(Frame frame, RAny value) {
                    if (value instanceof RDouble || value instanceof RInt || value instanceof RLogical) {
                        RDouble doubleValue = value.asDouble();
                        return createView(ast, doubleValue, doubleValue.size());
                    }
                    throw RError.getNonNumericMath(ast);
                }
            };
            replace(newNode);
            return createView(ast, currentValue, currentValue.size());
        }

        RDouble replaceAndExecuteEager(final RDouble currentValue) {
            RNode newNode = new Builtin.Builtin1(ast, argNames, argExprs) {
                @Override
                public RAny doBuiltIn(Frame frame, RAny value) {
                    if (value instanceof RDouble || value instanceof RInt || value instanceof RLogical) {
                        return calcEager(ast, value.asDouble());
                    }
                    throw RError.getNonNumericMath(ast);
                }
            };
            replace(newNode);
            return calcEager(ast, currentValue);
        }

    }
}
TOP

Related Classes of r.builtins.MathBase

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.