diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java index f8d34c719561803502b83654cad520a4bd6ca95c..4c03ebeafe358d7a88cc8456ae5ee198783faad7 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java @@ -36,6 +36,8 @@ import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage.ContextReference; import com.oracle.truffle.api.dsl.UnsupportedSpecializationException; import com.oracle.truffle.api.frame.Frame; +import com.oracle.truffle.api.frame.FrameSlot; +import com.oracle.truffle.api.frame.FrameSlotKind; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.TruffleObject; @@ -76,6 +78,7 @@ import com.oracle.truffle.r.runtime.RParserFactory; import com.oracle.truffle.r.runtime.RProfile; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RSource; +import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.ReturnException; import com.oracle.truffle.r.runtime.RootWithBody; import com.oracle.truffle.r.runtime.SubstituteVirtualFrame; @@ -98,12 +101,15 @@ import com.oracle.truffle.r.runtime.data.RSymbol; import com.oracle.truffle.r.runtime.data.RTypedValue; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.env.frame.ActiveBinding; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.interop.R2Foreign; import com.oracle.truffle.r.runtime.interop.R2ForeignNodeGen; import com.oracle.truffle.r.runtime.nodes.RCodeBuilder; import com.oracle.truffle.r.runtime.nodes.RNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; +import com.oracle.truffle.r.runtime.rng.RRNG; /** * The engine for the FastR implementation. Handles parsing and evaluation. There is one instance of @@ -152,6 +158,7 @@ final class REngine implements Engine, Engine.Timings { if (context.getKind() == RContext.ContextKind.SHARE_NOTHING) { initializeNonShared(); } + initializeRNG(); } private void initializeNonShared() { @@ -201,6 +208,15 @@ final class REngine implements Engine, Engine.Timings { } } + private void initializeRNG() { + assert REnvironment.globalEnv() != null; + RFunction fun = context.lookupBuiltin(".fastr.set.seed"); + ActiveBinding dotRandomSeed = new ActiveBinding(RType.Any, fun); + Frame frame = REnvironment.globalEnv().getFrame(); + FrameSlot slot = FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), RRNG.RANDOM_SEED, FrameSlotKind.Object); + FrameSlotChangeMonitor.setActiveBinding(frame, slot, dotRandomSeed, false, null); + } + @Override public void checkAndRunStartupShutdownFunction(String name, String... args) { Object func = REnvironment.globalEnv().findFunction(name); diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_C.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_C.java index 17325b33650a5e6e338a27d9e0fc71eda1a57871..8b8e778a0eb4ae4ca2fdf599791cf15688f5d483 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_C.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_C.java @@ -41,12 +41,10 @@ public class JNI_C implements CRFFI { @Override @TruffleBoundary public void execute(NativeCallInfo nativeCallInfo, Object[] args, boolean hasStrings) { - synchronized (JNI_C.class) { - if (traceEnabled()) { - traceDownCall(nativeCallInfo.name, args); - } - c(nativeCallInfo.address.asAddress(), args, hasStrings); + if (traceEnabled()) { + traceDownCall(nativeCallInfo.name, args); } + c(nativeCallInfo.address.asAddress(), args, hasStrings); } } diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_Call.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_Call.java index ee3d5222ab9ef5942554bf0221b1231271614bd5..70ad5c69a4f2269113074d15c04c06c57c013e18 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_Call.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_Call.java @@ -52,53 +52,51 @@ public class JNI_Call implements CallRFFI { @Override @TruffleBoundary public Object execute(NativeCallInfo nativeCallInfo, Object[] args) { - synchronized (JNI_Call.class) { - long address = nativeCallInfo.address.asAddress(); - Object result = null; - if (traceEnabled()) { - traceDownCall(nativeCallInfo.name, args); + long address = nativeCallInfo.address.asAddress(); + Object result = null; + if (traceEnabled()) { + traceDownCall(nativeCallInfo.name, args); + } + try { + switch (args.length) { + case 0: + result = call0(address); + break; + case 1: + result = call1(address, args[0]); + break; + case 2: + result = call2(address, args[0], args[1]); + break; + case 3: + result = call3(address, args[0], args[1], args[2]); + break; + case 4: + result = call4(address, args[0], args[1], args[2], args[3]); + break; + case 5: + result = call5(address, args[0], args[1], args[2], args[3], args[4]); + break; + case 6: + result = call6(address, args[0], args[1], args[2], args[3], args[4], args[5]); + break; + case 7: + result = call7(address, args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + break; + case 8: + result = call8(address, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); + break; + case 9: + result = call9(address, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]); + break; + default: + result = call(address, args); + break; } - try { - switch (args.length) { - case 0: - result = call0(address); - break; - case 1: - result = call1(address, args[0]); - break; - case 2: - result = call2(address, args[0], args[1]); - break; - case 3: - result = call3(address, args[0], args[1], args[2]); - break; - case 4: - result = call4(address, args[0], args[1], args[2], args[3]); - break; - case 5: - result = call5(address, args[0], args[1], args[2], args[3], args[4]); - break; - case 6: - result = call6(address, args[0], args[1], args[2], args[3], args[4], args[5]); - break; - case 7: - result = call7(address, args[0], args[1], args[2], args[3], args[4], args[5], args[6]); - break; - case 8: - result = call8(address, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); - break; - case 9: - result = call9(address, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]); - break; - default: - result = call(address, args); - break; - } - return result; - } finally { - if (traceEnabled()) { - traceDownCallReturn(nativeCallInfo.name, result); - } + return result; + } finally { + if (traceEnabled()) { + traceDownCallReturn(nativeCallInfo.name, result); } } } diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_C.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_C.java index e869188edb5536668845518bb77468b88a57c634..c6a44575fbe04e3278328db0b434fb5601f18f72 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_C.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_C.java @@ -44,82 +44,70 @@ public class TruffleNFI_C implements CRFFI { @Specialization(guards = "args.length == 0") protected void invokeCall0(NativeCallInfo nativeCallInfo, @SuppressWarnings("unused") Object[] args, @SuppressWarnings("unused") boolean hasStrings, @Cached("createExecute(args.length)") Node executeNode) { - synchronized (TruffleNFI_Call.class) { - try { - TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, - nativeCallInfo.address.asTruffleObject(), "bind", "(): void"); - ForeignAccess.sendExecute(executeNode, callFunction); - } catch (InteropException ex) { - throw RInternalError.shouldNotReachHere(ex); - } + try { + TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, + nativeCallInfo.address.asTruffleObject(), "bind", "(): void"); + ForeignAccess.sendExecute(executeNode, callFunction); + } catch (InteropException ex) { + throw RInternalError.shouldNotReachHere(ex); } } @Specialization(guards = "args.length == 1") protected void invokeCall1(NativeCallInfo nativeCallInfo, Object[] args, @SuppressWarnings("unused") boolean hasStrings, @Cached("createExecute(args.length)") Node executeNode) { - synchronized (TruffleNFI_Call.class) { - try { - Object[] nargs = new Object[args.length]; - TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, - nativeCallInfo.address.asTruffleObject(), "bind", getSignature(args, nargs)); - ForeignAccess.sendExecute(executeNode, callFunction, nargs[0]); - } catch (InteropException ex) { - throw RInternalError.shouldNotReachHere(ex); - } + try { + Object[] nargs = new Object[args.length]; + TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, + nativeCallInfo.address.asTruffleObject(), "bind", getSignature(args, nargs)); + ForeignAccess.sendExecute(executeNode, callFunction, nargs[0]); + } catch (InteropException ex) { + throw RInternalError.shouldNotReachHere(ex); } } @Specialization(guards = "args.length == 2") protected void invokeCall2(NativeCallInfo nativeCallInfo, Object[] args, @SuppressWarnings("unused") boolean hasStrings, @Cached("createExecute(args.length)") Node executeNode) { - synchronized (TruffleNFI_Call.class) { - try { - Object[] nargs = new Object[args.length]; - TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, - nativeCallInfo.address.asTruffleObject(), "bind", getSignature(args, nargs)); - ForeignAccess.sendExecute(executeNode, callFunction, nargs[0], nargs[1]); - } catch (InteropException ex) { - throw RInternalError.shouldNotReachHere(ex); - } + try { + Object[] nargs = new Object[args.length]; + TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, + nativeCallInfo.address.asTruffleObject(), "bind", getSignature(args, nargs)); + ForeignAccess.sendExecute(executeNode, callFunction, nargs[0], nargs[1]); + } catch (InteropException ex) { + throw RInternalError.shouldNotReachHere(ex); } } @Specialization(guards = "args.length == 3") protected void invokeCall3(NativeCallInfo nativeCallInfo, Object[] args, @SuppressWarnings("unused") boolean hasStrings, @Cached("createExecute(args.length)") Node executeNode) { - synchronized (TruffleNFI_Call.class) { - try { - Object[] nargs = new Object[args.length]; - TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, - nativeCallInfo.address.asTruffleObject(), "bind", getSignature(args, nargs)); - ForeignAccess.sendExecute(executeNode, callFunction, nargs[0], nargs[1], nargs[2]); - } catch (InteropException ex) { - throw RInternalError.shouldNotReachHere(ex); - } + try { + Object[] nargs = new Object[args.length]; + TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, + nativeCallInfo.address.asTruffleObject(), "bind", getSignature(args, nargs)); + ForeignAccess.sendExecute(executeNode, callFunction, nargs[0], nargs[1], nargs[2]); + } catch (InteropException ex) { + throw RInternalError.shouldNotReachHere(ex); } } @Specialization(guards = "args.length == 4") protected void invokeCall4(NativeCallInfo nativeCallInfo, Object[] args, @SuppressWarnings("unused") boolean hasStrings, @Cached("createExecute(args.length)") Node executeNode) { - synchronized (TruffleNFI_Call.class) { - try { - Object[] nargs = new Object[args.length]; - TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, - nativeCallInfo.address.asTruffleObject(), "bind", getSignature(args, nargs)); - ForeignAccess.sendExecute(executeNode, callFunction, nargs[0], nargs[1], nargs[2], nargs[3]); - } catch (InteropException ex) { - throw RInternalError.shouldNotReachHere(ex); - } + try { + Object[] nargs = new Object[args.length]; + TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, + nativeCallInfo.address.asTruffleObject(), "bind", getSignature(args, nargs)); + ForeignAccess.sendExecute(executeNode, callFunction, nargs[0], nargs[1], nargs[2], nargs[3]); + } catch (InteropException ex) { + throw RInternalError.shouldNotReachHere(ex); } } @Fallback protected void invokeCallN(@SuppressWarnings("unused") NativeCallInfo nativeCallInfo, @SuppressWarnings("unused") Object[] args, @SuppressWarnings("unused") boolean hasStrings) { - synchronized (TruffleNFI_Call.class) { - throw RInternalError.unimplemented(".C (too many args)"); - } + throw RInternalError.unimplemented(".C (too many args)"); } public static Node createExecute(int n) { diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Call.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Call.java index 4c1547d092df23ed89a23f5a5ca64df3d0070e19..2e474e0ac64cc2758b89e88eb6158a6553e539e5 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Call.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Call.java @@ -236,178 +236,160 @@ public class TruffleNFI_Call implements CallRFFI { @Specialization(guards = "args.length == 0") protected Object invokeCall0(NativeCallInfo nativeCallInfo, Object[] args, @Cached("createExecute(args.length)") Node executeNode) { - synchronized (TruffleNFI_Call.class) { - Object result = null; - boolean isNullSetting = prepareCall(nativeCallInfo.name, args); - try { - TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, - nativeCallInfo.address.asTruffleObject(), "bind", "(): object"); - result = ForeignAccess.sendExecute(executeNode, callFunction); - return result; - } catch (InteropException ex) { - throw RInternalError.shouldNotReachHere(ex); - } finally { - prepareReturn(nativeCallInfo.name, result, isNullSetting); - } + Object result = null; + boolean isNullSetting = prepareCall(nativeCallInfo.name, args); + try { + TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, + nativeCallInfo.address.asTruffleObject(), "bind", "(): object"); + result = ForeignAccess.sendExecute(executeNode, callFunction); + return result; + } catch (InteropException ex) { + throw RInternalError.shouldNotReachHere(ex); + } finally { + prepareReturn(nativeCallInfo.name, result, isNullSetting); } } @Specialization(guards = "args.length == 1") protected Object invokeCall1(NativeCallInfo nativeCallInfo, Object[] args, @Cached("createExecute(args.length)") Node executeNode) { - synchronized (TruffleNFI_Call.class) { - Object result = null; - boolean isNullSetting = prepareCall(nativeCallInfo.name, args); - try { - TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, - nativeCallInfo.address.asTruffleObject(), "bind", "(object): object"); - result = ForeignAccess.sendExecute(executeNode, callFunction, args[0]); - return result; - } catch (InteropException ex) { - throw RInternalError.shouldNotReachHere(ex); - } finally { - prepareReturn(nativeCallInfo.name, result, isNullSetting); - } + Object result = null; + boolean isNullSetting = prepareCall(nativeCallInfo.name, args); + try { + TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, + nativeCallInfo.address.asTruffleObject(), "bind", "(object): object"); + result = ForeignAccess.sendExecute(executeNode, callFunction, args[0]); + return result; + } catch (InteropException ex) { + throw RInternalError.shouldNotReachHere(ex); + } finally { + prepareReturn(nativeCallInfo.name, result, isNullSetting); } } @Specialization(guards = "args.length == 2") protected Object invokeCall2(NativeCallInfo nativeCallInfo, Object[] args, @Cached("createExecute(args.length)") Node executeNode) { - synchronized (TruffleNFI_Call.class) { - Object result = null; - boolean isNullSetting = prepareCall(nativeCallInfo.name, args); - try { - TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, - nativeCallInfo.address.asTruffleObject(), "bind", "(object, object): object"); - result = ForeignAccess.sendExecute(executeNode, callFunction, args[0], args[1]); - return result; - } catch (InteropException ex) { - throw RInternalError.shouldNotReachHere(ex); - } finally { - prepareReturn(nativeCallInfo.name, result, isNullSetting); - } + Object result = null; + boolean isNullSetting = prepareCall(nativeCallInfo.name, args); + try { + TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, + nativeCallInfo.address.asTruffleObject(), "bind", "(object, object): object"); + result = ForeignAccess.sendExecute(executeNode, callFunction, args[0], args[1]); + return result; + } catch (InteropException ex) { + throw RInternalError.shouldNotReachHere(ex); + } finally { + prepareReturn(nativeCallInfo.name, result, isNullSetting); } } @Specialization(guards = "args.length == 3") protected Object invokeCall3(NativeCallInfo nativeCallInfo, Object[] args, @Cached("createExecute(args.length)") Node executeNode) { - synchronized (TruffleNFI_Call.class) { - Object result = null; - boolean isNullSetting = prepareCall(nativeCallInfo.name, args); - try { - TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, - nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object): object"); - result = ForeignAccess.sendExecute(executeNode, callFunction, args[0], args[1], args[2]); - return result; - } catch (InteropException ex) { - throw RInternalError.shouldNotReachHere(ex); - } finally { - prepareReturn(nativeCallInfo.name, result, isNullSetting); - } + Object result = null; + boolean isNullSetting = prepareCall(nativeCallInfo.name, args); + try { + TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, + nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object): object"); + result = ForeignAccess.sendExecute(executeNode, callFunction, args[0], args[1], args[2]); + return result; + } catch (InteropException ex) { + throw RInternalError.shouldNotReachHere(ex); + } finally { + prepareReturn(nativeCallInfo.name, result, isNullSetting); } } @Specialization(guards = "args.length == 4") protected Object invokeCall4(NativeCallInfo nativeCallInfo, Object[] args, @Cached("createExecute(args.length)") Node executeNode) { - synchronized (TruffleNFI_Call.class) { - Object result = null; - boolean isNullSetting = prepareCall(nativeCallInfo.name, args); - try { - TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, - nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object): object"); - result = ForeignAccess.sendExecute(executeNode, callFunction, args[0], args[1], args[2], - args[3]); - return result; - } catch (InteropException ex) { - throw RInternalError.shouldNotReachHere(ex); - } finally { - prepareReturn(nativeCallInfo.name, result, isNullSetting); - } + Object result = null; + boolean isNullSetting = prepareCall(nativeCallInfo.name, args); + try { + TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, + nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object): object"); + result = ForeignAccess.sendExecute(executeNode, callFunction, args[0], args[1], args[2], + args[3]); + return result; + } catch (InteropException ex) { + throw RInternalError.shouldNotReachHere(ex); + } finally { + prepareReturn(nativeCallInfo.name, result, isNullSetting); } } @Specialization(guards = "args.length == 5") protected Object invokeCall5(NativeCallInfo nativeCallInfo, Object[] args, @Cached("createExecute(args.length)") Node executeNode) { - synchronized (TruffleNFI_Call.class) { - Object result = null; - boolean isNullSetting = prepareCall(nativeCallInfo.name, args); - try { - TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, - nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object): object"); - result = ForeignAccess.sendExecute(executeNode, callFunction, args[0], args[1], - args[2], args[3], args[4]); - return result; - } catch (InteropException ex) { - throw RInternalError.shouldNotReachHere(ex); - } finally { - prepareReturn(nativeCallInfo.name, result, isNullSetting); - } + Object result = null; + boolean isNullSetting = prepareCall(nativeCallInfo.name, args); + try { + TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, + nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object): object"); + result = ForeignAccess.sendExecute(executeNode, callFunction, args[0], args[1], + args[2], args[3], args[4]); + return result; + } catch (InteropException ex) { + throw RInternalError.shouldNotReachHere(ex); + } finally { + prepareReturn(nativeCallInfo.name, result, isNullSetting); } } @Specialization(guards = "args.length == 6") protected Object invokeCall6(NativeCallInfo nativeCallInfo, Object[] args, @Cached("createExecute(args.length)") Node executeNode) { - synchronized (TruffleNFI_Call.class) { - Object result = null; - boolean isNullSetting = prepareCall(nativeCallInfo.name, args); - try { - TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, - nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object, object): object"); - result = ForeignAccess.sendExecute(executeNode, callFunction, args[0], args[1], - args[2], args[3], args[4], args[5]); - return result; - } catch (InteropException ex) { - throw RInternalError.shouldNotReachHere(ex); - } finally { - prepareReturn(nativeCallInfo.name, result, isNullSetting); - } + Object result = null; + boolean isNullSetting = prepareCall(nativeCallInfo.name, args); + try { + TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, + nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object, object): object"); + result = ForeignAccess.sendExecute(executeNode, callFunction, args[0], args[1], + args[2], args[3], args[4], args[5]); + return result; + } catch (InteropException ex) { + throw RInternalError.shouldNotReachHere(ex); + } finally { + prepareReturn(nativeCallInfo.name, result, isNullSetting); } } @Specialization(guards = "args.length == 7") protected Object invokeCall7(NativeCallInfo nativeCallInfo, Object[] args, @Cached("createExecute(args.length)") Node executeNode) { - synchronized (TruffleNFI_Call.class) { - Object result = null; - boolean isNullSetting = prepareCall(nativeCallInfo.name, args); - try { - TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, - nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object, object, object): object"); - result = ForeignAccess.sendExecute(executeNode, callFunction, args[0], args[1], - args[2], args[3], args[4], args[5], - args[6]); - return result; - } catch (InteropException ex) { - throw RInternalError.shouldNotReachHere(ex); - } finally { - prepareReturn(nativeCallInfo.name, result, isNullSetting); - } + Object result = null; + boolean isNullSetting = prepareCall(nativeCallInfo.name, args); + try { + TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, + nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object, object, object): object"); + result = ForeignAccess.sendExecute(executeNode, callFunction, args[0], args[1], + args[2], args[3], args[4], args[5], + args[6]); + return result; + } catch (InteropException ex) { + throw RInternalError.shouldNotReachHere(ex); + } finally { + prepareReturn(nativeCallInfo.name, result, isNullSetting); } } @Specialization(guards = "args.length == 8") protected Object invokeCall8(NativeCallInfo nativeCallInfo, Object[] args, @Cached("createExecute(args.length)") Node executeNode) { - synchronized (TruffleNFI_Call.class) { - Object result = null; - boolean isNullSetting = prepareCall(nativeCallInfo.name, args); - try { - TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, - nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object, object, object, object): object"); - result = ForeignAccess.sendExecute(executeNode, callFunction, args[0], args[1], - args[2], args[3], args[4], args[5], - args[6], args[7]); - return result; - } catch (InteropException ex) { - throw RInternalError.shouldNotReachHere(ex); - } finally { - prepareReturn(nativeCallInfo.name, result, isNullSetting); - } + Object result = null; + boolean isNullSetting = prepareCall(nativeCallInfo.name, args); + try { + TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, + nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object, object, object, object): object"); + result = ForeignAccess.sendExecute(executeNode, callFunction, args[0], args[1], + args[2], args[3], args[4], args[5], + args[6], args[7]); + return result; + } catch (InteropException ex) { + throw RInternalError.shouldNotReachHere(ex); + } finally { + prepareReturn(nativeCallInfo.name, result, isNullSetting); } } @@ -425,26 +407,24 @@ public class TruffleNFI_Call implements CallRFFI { @Override public void execute(NativeCallInfo nativeCallInfo, Object[] args) { - synchronized (TruffleNFI_Call.class) { - boolean isNullSetting = prepareCall(nativeCallInfo.name, args); - try { - switch (args.length) { - case 0: - TruffleObject callVoid0Function = (TruffleObject) ForeignAccess.sendInvoke(bindNode, - nativeCallInfo.address.asTruffleObject(), "bind", CallVoid0Sig); - ForeignAccess.sendExecute(execute0Node, callVoid0Function); - break; - case 1: - TruffleObject callVoid1Function = (TruffleObject) ForeignAccess.sendInvoke(bindNode, - nativeCallInfo.address.asTruffleObject(), "bind", CallVoid1Sig); - ForeignAccess.sendExecute(execute1Node, callVoid1Function, args[0]); - break; - } - } catch (InteropException ex) { - throw RInternalError.shouldNotReachHere(ex); - } finally { - prepareReturn(nativeCallInfo.name, null, isNullSetting); + boolean isNullSetting = prepareCall(nativeCallInfo.name, args); + try { + switch (args.length) { + case 0: + TruffleObject callVoid0Function = (TruffleObject) ForeignAccess.sendInvoke(bindNode, + nativeCallInfo.address.asTruffleObject(), "bind", CallVoid0Sig); + ForeignAccess.sendExecute(execute0Node, callVoid0Function); + break; + case 1: + TruffleObject callVoid1Function = (TruffleObject) ForeignAccess.sendInvoke(bindNode, + nativeCallInfo.address.asTruffleObject(), "bind", CallVoid1Sig); + ForeignAccess.sendExecute(execute1Node, callVoid1Function, args[0]); + break; } + } catch (InteropException ex) { + throw RInternalError.shouldNotReachHere(ex); + } finally { + prepareReturn(nativeCallInfo.name, null, isNullSetting); } } } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java index 75d9d6ee5c0736b70933c19c375dcf9ca5eb5f1a..beb97cd30e1db39d6818bdc9726038447d2d9bd8 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java @@ -39,7 +39,6 @@ import com.oracle.truffle.r.nodes.builtin.RInternalCodeBuiltinNode; import com.oracle.truffle.r.runtime.RInternalCode; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RNull; @@ -193,6 +192,6 @@ public final class FastRGridExternalLookup { } private static RExternalBuiltinNode getExternalFastRGridBuiltinNode(String name) { - return new RInternalCodeBuiltinNode(RContext.getInstance(), "grid", RInternalCode.loadSourceRelativeTo(LInitGrid.class, "fastrGrid.R"), name); + return new RInternalCodeBuiltinNode("grid", RInternalCode.loadSourceRelativeTo(LInitGrid.class, "fastrGrid.R"), name); } } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java index 7e9d9c2c63e33d6457db83931b5fd92591c2e6bf..283a18303f840f13a145e68646bccbb85737f8c6 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java @@ -12,745 +12,901 @@ package com.oracle.truffle.r.library.stats; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.eq; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; -import java.util.Arrays; - +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; -import com.oracle.truffle.api.profiles.LoopConditionProfile; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode; +import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNamesAttributeNode; +import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimNamesAttributeNode; +import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctionsFactory.SetDimNamesAttributeNodeGen; import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.nodes.unary.IsFactorNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RDoubleVector; -import com.oracle.truffle.r.runtime.data.RIntVector; +import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; -import com.oracle.truffle.r.runtime.ops.na.NACheck; +import com.oracle.truffle.r.runtime.nmath.RMath; /* * Logic derived from GNU-R, library/stats/src/cov.c */ public abstract class Covcor extends RExternalBuiltinNode.Arg4 { + // Checkstyle: stop method name check - private final boolean isCor; - - public Covcor(boolean isCor) { - this.isCor = isCor; + private static RuntimeException error(String message) { + CompilerDirectives.transferToInterpreter(); + throw RError.error(RError.SHOW_CALLER, Message.GENERIC, message); } - static { - Casts casts = new Casts(Covcor.class); - casts.arg(0).mustNotBeMissing().mustBe(nullValue().not(), Message.IS_NULL, "x").asDoubleVector(); - casts.arg(1).mustNotBeMissing().asDoubleVector(); - casts.arg(2).asIntegerVector().findFirst().mustBe(eq(4), Message.NYI, "covcor: other method than 4 not implemented."); - casts.arg(3).asLogicalVector().findFirst().map(toBoolean()); + private static double ANS(double[] ans, int ncx, int i, int j) { + return ans[i + j * ncx]; } - @Specialization - public Object call(RAbstractDoubleVector x, @SuppressWarnings("unused") RNull y, int method, boolean iskendall) { - return corcov(x.materialize(), null, method, iskendall, this); + private static void ANS(double[] ans, int ncx, int i, int j, double value) { + ans[i + j * ncx] = value; } - @Specialization - public Object call(RAbstractDoubleVector x, RAbstractDoubleVector y, int method, boolean iskendall) { - return corcov(x.materialize(), y.materialize(), method, iskendall, this); + private static double CLAMP(double X) { + return (X >= 1 ? 1 : (X <= -1 ? -1 : X)); } - private final NACheck check = NACheck.create(); - - private final ConditionProfile noNAXProfile = ConditionProfile.createBinaryProfile(); - private final ConditionProfile noNAYProfile = ConditionProfile.createBinaryProfile(); - private final ConditionProfile xCompleteProfile = ConditionProfile.createBinaryProfile(); - private final ConditionProfile yCompleteProfile = ConditionProfile.createBinaryProfile(); - private final ConditionProfile bothZeroProfile = ConditionProfile.createBinaryProfile(); - private final BranchProfile tooManyMissing = BranchProfile.create(); - private final BranchProfile naInRes = BranchProfile.create(); - private final BranchProfile error = BranchProfile.create(); - private final BranchProfile warning = BranchProfile.create(); - - @Child private GetDimAttributeNode getDimsNode = GetDimAttributeNode.create(); - - private final LoopConditionProfile loopLength = LoopConditionProfile.createCountingProfile(); - - public RDoubleVector corcov(RDoubleVector x, RDoubleVector y, @SuppressWarnings("unused") int method, boolean iskendall, RBaseNode invokingNode) throws RError { - - boolean ansmat = getDimsNode.isMatrix(x); - int n; - int ncx; - if (ansmat) { - n = nrows(x); - ncx = ncols(x); - } else { - n = x.getLength(); - ncx = 1; - } + private static boolean ISNAN(double v) { + return Double.isNaN(v); + } - int ncy; - if (y == null) { - ncy = ncx; - } else if (getDimsNode.isMatrix(y)) { - if (nrows(y) != n) { - error.enter(); - throw error("incompatible dimensions"); + /* + * Note that "if (kendall)" and "if (cor)" are used inside a double for() loop; which makes the + * code better readable -- and is hopefully dealt with by a smartly optimizing compiler + */ + + /** + * Compute Cov(xx[], yy[]) or Cor(.,.) with n = length(xx) + */ + private static void COV_PAIRWISE_BODY(double[] ans, int n, int ncx, int i, int j, double[] x, double[] y, int xx, int yy, boolean[] sd_0, boolean cor, boolean kendall) { + double xmean = 0, ymean = 0; + int nobs = 0; + if (!kendall) { + for (int k = 0; k < n; k++) { + if (!(ISNAN(x[xx + k]) || ISNAN(y[yy + k]))) { + nobs++; + xmean += x[xx + k]; + ymean += y[yy + k]; + } } - ncy = ncols(y); - ansmat = true; - } else { - if (y.getLength() != n) { - error.enter(); - throw error("incompatible dimensions"); + } else /* kendall */ + for (int k = 0; k < n; k++) { + if (!(ISNAN(x[xx + k]) || ISNAN(y[yy + k]))) { + nobs++; + } } - ncy = 1; - } - // TODO adopt full use semantics + if (nobs >= 2) { + int n1 = -1; + double xsd = 0, ysd = 0, sum = 0; + if (!kendall) { + xmean /= nobs; + ymean /= nobs; + n1 = nobs - 1; + } + for (int k = 0; k < n; k++) { + if (!(ISNAN(x[xx + k]) || ISNAN(y[yy + k]))) { + if (!kendall) { + double xm = x[xx + k] - xmean; + double ym = y[yy + k] - ymean; + + sum += xm * ym; + if (cor) { + xsd += xm * xm; + ysd += ym * ym; + } + } - /* "default: complete" (easier for -Wall) */ - boolean naFail = false; - boolean everything = false; - boolean emptyErr = true; + else { /* Kendall's tau */ + for (n1 = 0; n1 < k; n1++) { + if (!(ISNAN(x[xx + n1]) || ISNAN(y[yy + n1]))) { + double xm = RMath.sign(x[xx + k] - x[xx + n1]); + double ym = RMath.sign(y[yy + k] - y[yy + n1]); - // case 4: /* "everything": NAs are propagated */ - everything = true; - emptyErr = false; + sum += xm * ym; + if (cor) { + xsd += xm * xm; + ysd += ym * ym; + } + } + } + } + } + } + if (cor) { + if (xsd == 0 || ysd == 0) { + sd_0[0] = true; + sum = RRuntime.DOUBLE_NA; + } else { + if (!kendall) { + xsd /= n1; + ysd /= n1; + sum /= n1; + } + sum /= (Math.sqrt(xsd) * Math.sqrt(ysd)); + sum = CLAMP(sum); + } + } else if (!kendall) { + sum /= n1; + } - if (emptyErr && x.getLength() == 0) { - error.enter(); - throw error("'x' is empty"); + ANS(ans, ncx, i, j, sum); + } else { + ANS(ans, ncx, i, j, RRuntime.DOUBLE_NA); } + } - double[] answerData = new double[ncx * ncy]; + private static void cov_pairwise1(int n, int ncx, double[] x, double[] ans, boolean[] sd_0, boolean cor, boolean kendall) { + for (int i = 0; i < ncx; i++) { + int xx = i * n; + for (int j = 0; j <= i; j++) { + int yy = j * n; - double[] xm = new double[ncx]; - boolean sd0; - if (y == null) { - if (everything) { - sd0 = covNA1(n, ncx, x, xm, answerData, isCor, iskendall); - } else { - RIntVector ind = RDataFactory.createIntVector(n); - complete1(n, ncx, x, ind, naFail); - sd0 = covComplete1(n, ncx, x, xm, ind, answerData, isCor, iskendall); - } - } else { - double[] ym = new double[ncy]; - if (everything) { - sd0 = covNA2(n, ncx, ncy, x, y, xm, ym, answerData, isCor, iskendall); - } else { - RIntVector ind = RDataFactory.createIntVector(n); - complete2(n, ncx, ncy, x, y, ind, naFail); - sd0 = covComplete2(n, ncx, ncy, x, y, xm, ym, ind, answerData, isCor, iskendall); + COV_PAIRWISE_BODY(ans, n, ncx, i, j, x, x, xx, yy, sd_0, cor, kendall); + + ANS(ans, ncx, j, i, ANS(ans, ncx, i, j)); } } + } - if (sd0) { /* only in cor() */ - warning.enter(); - RError.warning(invokingNode, RError.Message.SD_ZERO); - } + private static void cov_pairwise2(int n, int ncx, int ncy, double[] x, double[] y, double[] ans, boolean[] sd_0, boolean cor, boolean kendall) { + for (int i = 0; i < ncx; i++) { + int xx = i * n; + for (int j = 0; j < ncy; j++) { + int yy = j * n; - boolean seenNA = false; - for (int i = 0; i < answerData.length; i++) { - if (RRuntime.isNA(answerData[i])) { - naInRes.enter(); - seenNA = true; - break; + COV_PAIRWISE_BODY(ans, n, ncx, i, j, x, y, xx, yy, sd_0, cor, kendall); } } - - RDoubleVector ans = null; - if (getDimsNode.isMatrix(x)) { - ans = RDataFactory.createDoubleVector(answerData, !seenNA, new int[]{ncx, ncy}); - } else { - ans = RDataFactory.createDoubleVector(answerData, !seenNA); - } - return ans; } - private int ncols(RDoubleVector x) { - assert x.isMatrix(); - return getDimsNode.getDimensions(x)[1]; - } - - private int nrows(RDoubleVector x) { - assert x.isMatrix(); - return getDimsNode.getDimensions(x)[0]; - } + /* + * method = "complete" or "all.obs" (only difference: na_fail): -------- ------- + */ - private void complete1(int n, int ncx, RDoubleVector x, RIntVector ind, boolean naFail) { - int i; - int j; - for (i = 0; i < n; i++) { - ind.updateDataAt(i, 1, check); - } - for (j = 0; j < ncx; j++) { - // z = &x[j * n]; - for (i = 0; i < n; i++) { - if (Double.isNaN(x.getDataAt(j * n + i))) { - if (naFail) { - throw error("missing observations in cov/cor"); - } else { - ind.updateDataAt(i, 0, check); - } + /* This uses two passes for better accuracy */ + private static void MEAN(int n, int ncx, double[] x, double[] xm, boolean[] ind, int nobs) { + /* variable means */ + for (int i = 0; i < ncx; i++) { + int xx = i * n; + double sum = 0; + for (int k = 0; k < n; k++) { + if (ind[k]) { + sum += x[xx + k]; } } - } - } - - private void complete2(int n, int ncx, int ncy, RDoubleVector x, RDoubleVector y, RIntVector ind, boolean naFail) { - int i; - int j; - for (i = 0; i < n; i++) { - ind.updateDataAt(i, 1, check); - } - for (j = 0; j < ncx; j++) { - // z = &x[j * n]; - for (i = 0; i < n; i++) { - if (Double.isNaN(x.getDataAt(j * n + i))) { - if (naFail) { - throw error("missing observations in cov/cor"); - } else { - ind.updateDataAt(i, 0, check); + double tmp = sum / nobs; + if (Double.isFinite(tmp)) { + sum = 0; + for (int k = 0; k < n; k++) { + if (ind[k]) { + sum += (x[xx + k] - tmp); } } + tmp = tmp + sum / nobs; } + xm[i] = tmp; } + } - for (j = 0; j < ncy; j++) { - // z = &y[j * n]; - for (i = 0; i < n; i++) { - if (Double.isNaN(y.getDataAt(j * n + i))) { - if (naFail) { - throw error("missing observations in cov/cor"); - } else { - ind.updateDataAt(i, 0, check); + /* This uses two passes for better accuracy */ + private static void MEAN_(int n, int ncx, double[] x, double[] xm, boolean[] has_na) { + /* variable means (has_na) */ + for (int i = 0; i < ncx; i++) { + double tmp; + if (has_na[i]) { + tmp = RRuntime.DOUBLE_NA; + } else { + int xx = i * n; + double sum = 0; + for (int k = 0; k < n; k++) { + sum += x[xx + k]; + } + tmp = sum / n; + if (Double.isFinite(tmp)) { + sum = 0; + for (int k = 0; k < n; k++) { + sum += (x[xx + k] - tmp); } + tmp = tmp + sum / n; } } + xm[i] = tmp; } } - private static boolean covComplete1(int n, int ncx, RDoubleVector x, double[] xm, RIntVector indInput, double[] ans, boolean cor, boolean kendall) { + private static void cov_complete1(int n, int ncx, double[] x, double[] xm, boolean[] ind, double[] ans, boolean[] sd_0, boolean cor, boolean kendall) { int n1 = -1; - int nobs; - boolean isSd0 = false; /* total number of complete observations */ - nobs = 0; + int nobs = 0; for (int k = 0; k < n; k++) { - if (indInput.getDataAt(k) != 0) { + if (ind[k]) { nobs++; } } - if (nobs <= 1) { /* too many missing */ - for (int i = 0; i < ans.length; i++) { - ans[i] = RRuntime.DOUBLE_NA; + if (nobs <= 1) {/* too many missing */ + for (int i = 0; i < ncx; i++) { + for (int j = 0; j < ncx; j++) { + ANS(ans, ncx, i, j, RRuntime.DOUBLE_NA); + } } - return isSd0; - } - - RIntVector ind = indInput; - if (nobs == ind.getLength()) { - // No values of ind are zeroed. - ind = null; + return; } if (!kendall) { - mean(x, xm, ind, n, ncx, nobs); + MEAN(n, ncx, x, xm, ind, nobs); /* -> xm[] */ n1 = nobs - 1; } for (int i = 0; i < ncx; i++) { + int xx = i * n; + if (!kendall) { double xxm = xm[i]; for (int j = 0; j <= i; j++) { + int yy = j * n; double yym = xm[j]; - double sum = 0.0; + double sum = 0; for (int k = 0; k < n; k++) { - if (ind == null || ind.getDataAt(k) != 0) { - sum += (x.getDataAt(i * n + k) - xxm) * (x.getDataAt(j * n + k) - yym); + if (ind[k]) { + sum += (x[xx + k] - xxm) * (x[yy + k] - yym); } } - double r = sum / n1; - ans[i + j * ncx] = r; - ans[j + i * ncx] = r; + double result = sum / n1; + ANS(ans, ncx, j, i, result); + ANS(ans, ncx, i, j, result); } } else { /* Kendall's tau */ - throw new UnsupportedOperationException("kendall's unsupported"); + for (int j = 0; j <= i; j++) { + int yy = j * n; + double sum = 0; + for (int k = 0; k < n; k++) { + if (ind[k]) { + for (n1 = 0; n1 < n; n1++) { + if (ind[n1]) { + sum += RMath.sign(x[xx + k] - x[xx + n1]) * RMath.sign(x[yy + k] - x[yy + n1]); + } + } + } + } + ANS(ans, ncx, j, i, sum); + ANS(ans, ncx, i, j, sum); + } } } if (cor) { for (int i = 0; i < ncx; i++) { - xm[i] = Math.sqrt(ans[i + i * ncx]); + xm[i] = Math.sqrt(ANS(ans, ncx, i, i)); } for (int i = 0; i < ncx; i++) { for (int j = 0; j < i; j++) { + double result; if (xm[i] == 0 || xm[j] == 0) { - isSd0 = true; - ans[i + j * ncx] = RRuntime.DOUBLE_NA; - ans[j + i * ncx] = RRuntime.DOUBLE_NA; + sd_0[0] = true; + result = RRuntime.DOUBLE_NA; } else { - double sum = ans[i + j * ncx] / (xm[i] * xm[j]); - if (sum > 1.0) { - sum = 1.0; + double current = ANS(ans, ncx, i, j); + if (RRuntime.isNA(current)) { + result = RRuntime.DOUBLE_NA; + } else { + result = CLAMP(current / (xm[i] * xm[j])); } - ans[i + j * ncx] = sum; - ans[j + i * ncx] = sum; } + ANS(ans, ncx, j, i, result); + ANS(ans, ncx, i, j, result); } - ans[i + i * ncx] = 1.0; + ANS(ans, ncx, i, i, 1); } } - - return isSd0; } - private static boolean covComplete2(int n, int ncx, int ncy, RDoubleVector x, RDoubleVector y, double[] xm, double[] ym, RIntVector indInput, double[] ans, boolean cor, boolean kendall) { + private static void cov_na_1(int n, int ncx, double[] x, double[] xm, boolean[] has_na, double[] ans, boolean[] sd_0, boolean cor, boolean kendall) { int n1 = -1; - int nobs; - boolean isSd0 = false; - - /* total number of complete observations */ - nobs = 0; - for (int k = 0; k < n; k++) { - if (indInput.getDataAt(k) != 0) { - nobs++; - } - } - if (nobs <= 1) { /* too many missing */ - for (int i = 0; i < ans.length; i++) { - ans[i] = RRuntime.DOUBLE_NA; + if (n <= 1) { /* too many missing */ + for (int i = 0; i < ncx; i++) { + for (int j = 0; j < ncx; j++) { + ANS(ans, ncx, i, j, RRuntime.DOUBLE_NA); + } } - return isSd0; - } - - RIntVector ind = indInput; - if (nobs == ind.getLength()) { - // No values of ind are zeroed. - ind = null; + return; } if (!kendall) { - mean(x, xm, ind, n, ncx, nobs); - mean(y, ym, ind, n, ncy, nobs); - n1 = nobs - 1; + MEAN_(n, ncx, x, xm, has_na);/* -> xm[] */ + n1 = n - 1; } for (int i = 0; i < ncx; i++) { - if (!kendall) { - double xxm = xm[i]; - for (int j = 0; j < ncy; j++) { - double yym = ym[j]; - double sum = 0; - for (int k = 0; k < n; k++) { - if (ind == null || ind.getDataAt(k) != 0) { - sum += (x.getDataAt(i * n + k) - xxm) * (y.getDataAt(j * n + k) - yym); + if (has_na[i]) { + for (int j = 0; j <= i; j++) { + ANS(ans, ncx, j, i, RRuntime.DOUBLE_NA); + ANS(ans, ncx, i, j, RRuntime.DOUBLE_NA); + } + } else { + int xx = i * n; + + if (!kendall) { + double xxm = xm[i]; + for (int j = 0; j <= i; j++) { + if (has_na[j]) { + ANS(ans, ncx, j, i, RRuntime.DOUBLE_NA); + ANS(ans, ncx, i, j, RRuntime.DOUBLE_NA); + } else { + int yy = j * n; + double yym = xm[j]; + double sum = 0; + for (int k = 0; k < n; k++) { + sum += (x[xx + k] - xxm) * (x[yy + k] - yym); + } + double result = sum / n1; + ANS(ans, ncx, j, i, result); + ANS(ans, ncx, i, j, result); + } + } + } else { /* Kendall's tau */ + for (int j = 0; j <= i; j++) { + if (has_na[j]) { + ANS(ans, ncx, j, i, RRuntime.DOUBLE_NA); + ANS(ans, ncx, i, j, RRuntime.DOUBLE_NA); + } else { + int yy = j * n; + double sum = 0; + for (int k = 0; k < n; k++) { + for (n1 = 0; n1 < n; n1++) { + sum += RMath.sign(x[xx + k] - x[xx + n1]) * RMath.sign(x[yy + k] - x[yy + n1]); + } + } + ANS(ans, ncx, j, i, sum); + ANS(ans, ncx, i, j, sum); } } - ans[i + j * ncx] = (sum / n1); } - } else { /* Kendall's tau */ - throw new UnsupportedOperationException("kendall's unsupported"); } } if (cor) { - covsdev(x, xm, ind, n, ncx, n1, kendall); /* -> xm[.] */ - covsdev(y, ym, ind, n, ncy, n1, kendall); /* -> ym[.] */ - for (int i = 0; i < ncx; i++) { - for (int j = 0; j < ncy; j++) { - double divisor = (xm[i] * ym[j]); - if (divisor == 0.0) { - isSd0 = true; - ans[i + j * ncx] = RRuntime.DOUBLE_NA; - } else { - double value = ans[i + j * ncx] / divisor; - if (value > 1) { - value = 1; + if (!has_na[i]) { + xm[i] = Math.sqrt(ANS(ans, ncx, i, i)); + } + } + for (int i = 0; i < ncx; i++) { + if (!has_na[i]) { + for (int j = 0; j < i; j++) { + double result; + if (xm[i] == 0 || xm[j] == 0) { + sd_0[0] = true; + result = RRuntime.DOUBLE_NA; + } else { + double current = ANS(ans, ncx, i, j); + if (RRuntime.isNA(current)) { + result = RRuntime.DOUBLE_NA; + } else { + result = CLAMP(current / (xm[i] * xm[j])); + } } - ans[i + j * ncx] = value; + ANS(ans, ncx, j, i, result); + ANS(ans, ncx, i, j, result); } } + ANS(ans, ncx, i, i, 1); } } - return isSd0; } - private static void covsdev(RDoubleVector vector, double[] vectorM, RIntVector ind, int n, int len, int n1, boolean kendall) { - for (int i = 0; i < len; i++) { + private static void COV_SDEV1(int n, int n1, int nc, double[] array, double[] m, boolean[] ind, boolean kendall) { + for (int i = 0; i < nc; i++) { /* Var(X[i]) */ + int xx = i * n; double sum = 0; if (!kendall) { - double xxm = vectorM[i]; + double xxm = m[i]; for (int k = 0; k < n; k++) { - if (ind == null || ind.getDataAt(k) != 0) { - double value = vector.getDataAt(i * n + k); - sum += (value - xxm) * (value - xxm); + if (ind[k]) { + sum += (array[xx + k] - xxm) * (array[xx + k] - xxm); } } sum /= n1; } else { /* Kendall's tau */ - throw new UnsupportedOperationException("kendall's unsupported"); - } - vectorM[i] = Math.sqrt(sum); - } - } - - private static void mean(RDoubleVector vector, double[] vectorM, RIntVector ind, int n, int len, int nobs) { - /* variable means */ - for (int i = 0; i < len; i++) { - double sum = 0.0; - for (int k = 0; k < n; k++) { - if (ind == null || ind.getDataAt(k) != 0) { - sum += vector.getDataAt(i * n + k); - } - } - double tmp = sum / nobs; - if (!Double.isInfinite(tmp)) { - sum = 0.0; for (int k = 0; k < n; k++) { - if (ind == null || ind.getDataAt(k) != 0) { - sum += (vector.getDataAt(i * n + k) - tmp); + if (ind[k]) { + for (int n1_ = 0; n1_ < n; n1_++) { + if (ind[n1_] && array[xx + k] != array[xx + n1_]) { + sum++; /* = sign(. - .)^2 */ + } + } } } - tmp = tmp + sum / nobs; - } - vectorM[i] = tmp; - } - } - - private static boolean[] findNAs(int n, int nc, RDoubleVector v) { - boolean[] hasNA = new boolean[nc]; - double[] data = v.getDataWithoutCopying(); - for (int j = 0; j < nc; j++) { - for (int i = 0; i < n; i++) { - if (Double.isNaN(data[j * n + i])) { - hasNA[j] = true; - break; - } } + m[i] = Math.sqrt(sum); } - return hasNA; } - private boolean covNA1(int n, int ncx, RDoubleVector x, double[] xm, double[] ans, boolean cor, boolean iskendall) { - double sum; - double xxm; - double yym; + private static void cov_complete2(int n, int ncx, int ncy, double[] x, double[] y, double[] xm, double[] ym, boolean[] ind, double[] ans, boolean[] sd_0, boolean cor, boolean kendall) { int n1 = -1; - boolean sd0 = false; - double[] xData = x.getDataWithoutCopying(); - boolean[] hasNAx = findNAs(n, ncx, x); - - if (n <= 1) { /* too many missing */ - tooManyMissing.enter(); - Arrays.fill(ans, RRuntime.DOUBLE_NA); - return sd0; + /* total number of complete observations */ + int nobs = 0; + for (int k = 0; k < n; k++) { + if (ind[k]) { + nobs++; + } } - - if (!iskendall) { - if (xCompleteProfile.profile(x.isComplete())) { - meanNoNA(n, ncx, xData, xm, hasNAx); - } else { - mean(n, ncx, xData, xm, hasNAx); + if (nobs <= 1) {/* too many missing */ + for (int i = 0; i < ncx; i++) { + for (int j = 0; j < ncy; j++) { + ANS(ans, ncx, i, j, RRuntime.DOUBLE_NA); + } } - n1 = n - 1; + return; } + if (!kendall) { + MEAN(n, ncx, x, xm, ind, nobs);/* -> xm[] */ + MEAN(n, ncy, y, ym, ind, nobs);/* -> ym[] */ + n1 = nobs - 1; + } for (int i = 0; i < ncx; i++) { - double[] temp = new double[n]; - if (noNAXProfile.profile(!hasNAx[i])) { - if (!iskendall) { - xxm = xm[i]; - for (int j = 0; j <= i; j++) { - double r; - if (noNAXProfile.profile(!hasNAx[j])) { - yym = xm[j]; - if (checkNAs(xxm, yym)) { - r = RRuntime.DOUBLE_NA; - } else { - sum = 0.0; - loopLength.profileCounted(n); - for (int k = 0; loopLength.inject(k < n); k++) { - double u = xData[i * n + k]; - double v = xData[j * n + k]; - temp[k] = (u - xxm) * (v - yym); - } - for (int k = 0; loopLength.inject(k < n); k++) { - sum += temp[k]; + int xx = i * n; + if (!kendall) { + double xxm = xm[i]; + for (int j = 0; j < ncy; j++) { + int yy = j * n; + double yym = ym[j]; + double sum = 0; + for (int k = 0; k < n; k++) { + if (ind[k]) { + sum += (x[xx + k] - xxm) * (y[yy + k] - yym); + } + } + ANS(ans, ncx, i, j, sum / n1); + } + } else { /* Kendall's tau */ + for (int j = 0; j < ncy; j++) { + int yy = j * n; + double sum = 0; + for (int k = 0; k < n; k++) { + if (ind[k]) { + for (n1 = 0; n1 < n; n1++) { + if (ind[n1]) { + sum += RMath.sign(x[xx + k] - x[xx + n1]) * RMath.sign(y[yy + k] - y[yy + n1]); } - r = checkNAs(sum) ? RRuntime.DOUBLE_NA : sum / n1; } - } else { - r = RRuntime.DOUBLE_NA; } - ans[j + i * ncx] = r; - ans[i + j * ncx] = r; } - } else { /* Kendall's tau */ - throw new UnsupportedOperationException("kendall's unsupported"); - } - } else { - for (int j = 0; j <= i; j++) { - ans[j + i * ncx] = RRuntime.DOUBLE_NA; - ans[i + j * ncx] = RRuntime.DOUBLE_NA; + ANS(ans, ncx, i, j, sum); } } } if (cor) { + + COV_SDEV1(n, n1, ncx, x, xm, ind, kendall); /* -> xm[.] */ + COV_SDEV1(n, n1, ncy, y, ym, ind, kendall); /* -> ym[.] */ + for (int i = 0; i < ncx; i++) { - if (noNAXProfile.profile(!hasNAx[i])) { - double u = ans[i + i * ncx]; - xm[i] = checkNAs(u) ? RRuntime.DOUBLE_NA : Math.sqrt(u); - } - } - for (int i = 0; i < ncx; i++) { - if (noNAXProfile.profile(!hasNAx[i])) { - for (int j = 0; j < i; j++) { - if (bothZeroProfile.profile(xm[i] == 0 || xm[j] == 0)) { - sd0 = true; - ans[j + i * ncx] = RRuntime.DOUBLE_NA; - ans[i + j * ncx] = RRuntime.DOUBLE_NA; + for (int j = 0; j < ncy; j++) { + double result; + if (xm[i] == 0 || ym[j] == 0) { + sd_0[0] = true; + result = RRuntime.DOUBLE_NA; + } else { + double current = ANS(ans, ncx, i, j); + if (RRuntime.isNA(current)) { + result = RRuntime.DOUBLE_NA; } else { - double u = ans[i + j * ncx]; - double v = xm[i]; - double w = xm[j]; - sum = checkNAs(u, v, w) ? RRuntime.DOUBLE_NA : u / (v * w); - if (sum > 1.0) { - sum = 1.0; - } - ans[j + i * ncx] = sum; - ans[i + j * ncx] = sum; + result = CLAMP(current / (xm[i] * ym[j])); } } + ANS(ans, ncx, i, j, result); } - ans[i + i * ncx] = 1.0; } } - - return sd0; } - private static void meanNoNA(int n, int ncx, double[] x, double[] xm, boolean[] hasNA) { - double sum; - double tmp; - /* variable means (has_na) */ - for (int i = 0; i < ncx; i++) { - if (hasNA[i]) { - tmp = RRuntime.DOUBLE_NA; - } else { - sum = 0.0; - for (int k = 0; k < n; k++) { - double u = x[i * n + k]; - sum += u; - } - tmp = sum / n; - if (RRuntime.isFinite(tmp)) { - sum = 0.0; + private static void COV_SDEV2(int n, int n1, int nc, double[] array, double[] m, boolean[] has_na, boolean kendall) { + for (int i = 0; i < nc; i++) { + if (!has_na[i]) { /* Var(X[j]) */ + int xx = i * n; + double sum = 0; + if (!kendall) { + double xxm = m[i]; for (int k = 0; k < n; k++) { - double u = x[i * n + k]; - sum += u - tmp; + sum += (array[xx + k] - xxm) * (array[xx + k] - xxm); } - tmp += sum / n; - } - } - xm[i] = tmp; - } - } - - private void mean(int n, int ncx, double[] x, double[] xm, boolean[] hasNA) { - double sum; - double tmp; - /* variable means (has_na) */ - for (int i = 0; i < ncx; i++) { - if (hasNA[i]) { - tmp = RRuntime.DOUBLE_NA; - } else { - sum = 0.0; - for (int k = 0; k < n; k++) { - double u = x[i * n + k]; - if (checkNAs(u)) { - sum = RRuntime.DOUBLE_NA; - break; - } - sum += u; - } - tmp = checkNAs(sum) ? RRuntime.DOUBLE_NA : sum / n; - if (RRuntime.isFinite(tmp)) { - sum = 0.0; + sum /= n1; + } else { /* Kendall's tau */ for (int k = 0; k < n; k++) { - double u = x[i * n + k]; - if (checkNAs(u)) { - sum = RRuntime.DOUBLE_NA; - break; + for (int n1_ = 0; n1_ < n; n1_++) { + if (array[xx + k] != array[xx + n1_]) { + sum++; /* = sign(. - .)^2 */ + } } - sum += u - tmp; - } - if (checkNAs(sum)) { - tmp = RRuntime.DOUBLE_NA; - } else { - tmp += sum / n; } } + m[i] = Math.sqrt(sum); } - xm[i] = tmp; } } - private boolean covNA2(int n, int ncx, int ncy, RDoubleVector x, RDoubleVector y, double[] xm, double[] ym, double[] ans, boolean cor, boolean iskendall) { - double sum; - double xxm; - double yym; + private static void cov_na_2(int n, int ncx, int ncy, double[] x, double[] y, double[] xm, double[] ym, boolean[] has_na_x, boolean[] has_na_y, double[] ans, boolean[] sd_0, boolean cor, + boolean kendall) { int n1 = -1; - boolean sd0 = false; - - double[] xData = x.getDataWithoutCopying(); - double[] yData = y.getDataWithoutCopying(); - boolean[] hasNAx = findNAs(n, ncx, x); - boolean[] hasNAy = findNAs(n, ncy, y); - - if (n <= 1) { /* too many missing */ - tooManyMissing.enter(); + if (n <= 1) {/* too many missing */ for (int i = 0; i < ncx; i++) { for (int j = 0; j < ncy; j++) { - ans[i + j * ncx] = RRuntime.DOUBLE_NA; + ANS(ans, ncx, i, j, RRuntime.DOUBLE_NA); } } - return sd0; + return; } - if (!iskendall) { - if (xCompleteProfile.profile(x.isComplete())) { - meanNoNA(n, ncx, xData, xm, hasNAx); - } else { - mean(n, ncx, xData, xm, hasNAx); - } - if (yCompleteProfile.profile(y.isComplete())) { - meanNoNA(n, ncy, yData, ym, hasNAy); - } else { - mean(n, ncy, yData, ym, hasNAy); - } + if (!kendall) { + MEAN_(n, ncx, x, xm, has_na_x);/* -> xm[] */ + MEAN_(n, ncy, y, ym, has_na_y);/* -> ym[] */ n1 = n - 1; } - for (int i = 0; i < ncx; i++) { - if (noNAXProfile.profile(!hasNAx[i])) { - if (!iskendall) { - xxm = xm[i]; + if (has_na_x[i]) { + for (int j = 0; j < ncy; j++) { + ANS(ans, ncx, i, j, RRuntime.DOUBLE_NA); + } + } else { + int xx = i * n; + if (!kendall) { + double xxm = xm[i]; for (int j = 0; j < ncy; j++) { - double r; - if (noNAYProfile.profile(!hasNAy[j])) { - yym = ym[j]; - if (checkNAs(xxm, yym)) { - r = RRuntime.DOUBLE_NA; - } else { - sum = 0.0; - for (int k = 0; k < n; k++) { - double u = xData[i * n + k]; - double v = yData[j * n + k]; - sum += (u - xxm) * (v - yym); - } - r = checkNAs(sum) ? RRuntime.DOUBLE_NA : sum / n1; - } + if (has_na_y[j]) { + ANS(ans, ncx, i, j, RRuntime.DOUBLE_NA); } else { - r = RRuntime.DOUBLE_NA; + int yy = j * n; + double yym = ym[j]; + double sum = 0; + for (int k = 0; k < n; k++) { + sum += (x[xx + k] - xxm) * (y[yy + k] - yym); + } + ANS(ans, ncx, i, j, sum / n1); } - ans[i + j * ncx] = r; } } else { /* Kendall's tau */ - throw new UnsupportedOperationException("kendall's unsupported"); - } - } else { - for (int j = 0; j < ncy; j++) { - ans[i + j * ncx] = RRuntime.DOUBLE_NA; + for (int j = 0; j < ncy; j++) { + if (has_na_y[j]) { + ANS(ans, ncx, i, j, RRuntime.DOUBLE_NA); + } else { + int yy = j * n; + double sum = 0; + for (int k = 0; k < n; k++) { + for (n1 = 0; n1 < n; n1++) { + sum += RMath.sign(x[xx + k] - x[xx + n1]) * RMath.sign(y[yy + k] - y[yy + n1]); + } + } + ANS(ans, ncx, i, j, sum); + } + } } } } if (cor) { - covsdev(n, n1, ncx, x, hasNAx, xm, iskendall); - covsdev(n, n1, ncy, y, hasNAy, ym, iskendall); + + COV_SDEV2(n, n1, ncx, x, xm, has_na_x, kendall); /* -> xm[.] */ + COV_SDEV2(n, n1, ncy, y, ym, has_na_y, kendall); /* -> ym[.] */ for (int i = 0; i < ncx; i++) { - if (noNAXProfile.profile(!hasNAx[i])) { + if (!has_na_x[i]) { for (int j = 0; j < ncy; j++) { - if (noNAYProfile.profile(!hasNAy[j])) { - if (xm[i] == 0.0 || ym[j] == 0.0) { - sd0 = true; - ans[i + j * ncx] = RRuntime.DOUBLE_NA; + if (!has_na_y[j]) { + double result; + if (xm[i] == 0 || ym[j] == 0) { + sd_0[0] = true; + result = RRuntime.DOUBLE_NA; } else { - double u = xm[i]; - double v = ym[j]; - if (checkNAs(u, v)) { - ans[i + j * ncx] = RRuntime.DOUBLE_NA; + double current = ANS(ans, ncx, i, j); + if (RRuntime.isNA(current)) { + result = RRuntime.DOUBLE_NA; } else { - ans[i + j * ncx] /= u * v; - } - if (ans[i + j * ncx] > 1.0) { - ans[i + j * ncx] = 1.0; + result = CLAMP(current / (xm[i] * ym[j])); } } + ANS(ans, ncx, i, j, result); } } } } } + } + + /* + * complete[12]() returns indicator vector ind[] of complete.cases(), or -------------- + * if(na_fail) signals error if any NA/NaN is encountered + */ + + /* + * This might look slightly inefficient, but it is designed to optimise paging in virtual memory + * systems ... (or at least that's my story, and I'm sticking to it.) + */ + private static void NA_LOOP(int n, int z, double[] x, boolean[] ind, boolean na_fail) { + for (int i = 0; i < n; i++) { + if (ISNAN(x[z + i])) { + if (na_fail) { + error("missing observations in cov/cor"); + } else { + ind[i] = false; + } + } + } + } - return sd0; + private static void complete1(int n, int ncx, double[] x, boolean[] ind, boolean na_fail) { + for (int i = 0; i < n; i++) { + ind[i] = true; + } + for (int j = 0; j < ncx; j++) { + int z = j * n; + NA_LOOP(n, z, x, ind, na_fail); + } } - private void covsdev(int n, int n1, int ncx, RDoubleVector x, boolean[] hasNA, double[] xm, boolean iskendall) { - for (int i = 0; i < ncx; i++) { - if (!hasNA[i]) { /* Var(X[j]) */ - double sum = 0.0; - if (!iskendall) { - double xxm = xm[i]; - if (checkNAs(xxm)) { - sum = RRuntime.DOUBLE_NA; - } else { - for (int k = 0; k < n; k++) { - double u = x.getDataAt(i * n + k); - double v = x.getDataAt(i * n + k); - if (checkNAs(u, v)) { - sum = RRuntime.DOUBLE_NA; - break; - } - sum += (u - xxm) * (v - xxm); + static void complete2(int n, int ncx, int ncy, double[] x, double[] y, boolean[] ind, boolean na_fail) { + complete1(n, ncx, x, ind, na_fail); + + for (int j = 0; j < ncy; j++) { + int z = j * n; + NA_LOOP(n, z, y, ind, na_fail); + } + } + + static void find_na_1(int n, int ncx, double[] x, boolean[] has_na) { + for (int j = 0; j < ncx; j++) { + int z = j * n; + has_na[j] = false; + for (int i = 0; i < n; i++) { + if (ISNAN(x[z + i])) { + has_na[j] = true; + break; + } + } + } + } + + static void find_na_2(int n, int ncx, int ncy, double[] x, double[] y, boolean[] has_na_x, boolean[] has_na_y) { + find_na_1(n, ncx, x, has_na_x); + find_na_1(n, ncy, y, has_na_y); + } + + /* + * co[vr](x, y, use = { 1, 2, 3, 4, 5 } "all.obs", "complete.obs", "pairwise.complete", + * "everything", "na.or.complete" kendall = TRUE/FALSE) + */ + public RDoubleVector corcov(RDoubleVector x, RDoubleVector y, int method, boolean kendall) throws RError { + int n, ncx, ncy; + + /* Arg.1: x */ + if (isFactorX.executeIsFactor(x)) { + error("'x' is a factor"); + // maybe only warning: "Calling var(x) on a factor x is deprecated and will become an + // error.\n Use something like 'all(duplicated(x)[-1L])' to test for a constant vector." + } + /* length check of x -- only if(empty_err) --> below */ + int[] xDims = getDimsXNode.getDimensions(x); + boolean ansmat = matrixProfile.profile(GetDimAttributeNode.isMatrix(xDims)); + if ((ansmat)) { + n = xDims[0]; + ncx = xDims[1]; + } else { + n = x.getLength(); + ncx = 1; + } + /* Arg.2: y */ + if (y == null) {/* y = x : var() */ + ncy = ncx; + } else { + if (isFactorY.executeIsFactor(y)) { + error("'y' is a factor"); + // maybe only warning: "Calling var(x) on a factor x is deprecated and will become + // an error.\n Use something like 'all(duplicated(x)[-1L])' to test for a constant + // vector." + } + int[] yDims = getDimsYNode.getDimensions(y); + if (GetDimAttributeNode.isMatrix(yDims)) { + if (yDims[0] != n) { + error("incompatible dimensions"); + } + ncy = yDims[1]; + ansmat = true; + } else { + if (y.getLength() != n) { + error("incompatible dimensions"); + } + ncy = 1; + } + } + + /* "default: complete" */ + boolean na_fail = false; + boolean everything = false; + boolean empty_err = true; + boolean pair = false; + switch (method) { + case 1: /* use all : no NAs */ + na_fail = true; + break; + case 2: /* complete */ + /* did na.omit in R */ + if (x.getLength() == 0) { + error("no complete element pairs"); + } + break; + case 3: /* pairwise.complete */ + pair = true; + break; + case 4: /* "everything": NAs are propagated */ + everything = true; + empty_err = false; + break; + case 5: /* "na.or.complete": NAs are propagated */ + empty_err = false; + break; + default: + error("invalid 'use' (computational method)"); + } + if (empty_err && x.getLength() == 0) { + error("'x' is empty"); + } + + double[] xData = x.getDataWithoutCopying(); + double[] ans = new double[ncx * ncy]; + boolean[] sd_0 = new boolean[1]; + + evaluate(y, kendall, isCor, n, ncx, ncy, na_fail, everything, empty_err, pair, xData, ans, sd_0); + + if (sd_0[0]) { /* only in cor() */ + warning(RError.Message.SD_ZERO); + } + + boolean seenNA = false; + for (int i = 0; i < ans.length; i++) { + if (RRuntime.isNA(ans[i])) { + naInRes.enter(); + seenNA = true; + break; + } + } + + if (ansmat) { /* set dimnames() when applicable */ + RList newDimNames = null; + if (y == null) { + RList dimNames = getDimsNamesXNode.getDimNames(x); + if (dimNames != null) { + Object names = dimNames.getDataAt(1); + if (names != RNull.instance) { + newDimNames = RDataFactory.createList(new Object[]{names, names}); + } + } + } else { + RList dimNamesX = getDimsNamesXNode.getDimNames(x); + RList dimNamesY = getDimsNamesYNode.getDimNames(y); + Object namesX = dimNamesX.getLength() >= 2 ? dimNamesX.getDataAt(1) : RNull.instance; + Object namesY = dimNamesY.getLength() >= 2 ? dimNamesY.getDataAt(1) : RNull.instance; + if (namesX != RNull.instance || namesY != RNull.instance) { + newDimNames = RDataFactory.createList(new Object[]{namesX, namesY}); + } + } + RDoubleVector result = RDataFactory.createDoubleVector(ans, !seenNA, new int[]{ncx, ncy}); + if (newDimNames != null) { + setDimNamesNode.setDimNames(result, newDimNames); + } + return result; + } else { + return RDataFactory.createDoubleVector(ans, !seenNA); + } + } + + @TruffleBoundary + private static void evaluate(RDoubleVector y, boolean kendall, boolean cor, int n, int ncx, int ncy, boolean na_fail, boolean everything, boolean empty_err, boolean pair, double[] xData, + double[] ans, boolean[] sd_0) { + if (y == null) { + if (everything) { /* NA's are propagated */ + double[] xm = new double[ncx]; + boolean[] ind = new boolean[ncx]; + find_na_1(n, ncx, xData, /* --> has_na[] = */ ind); + cov_na_1(n, ncx, xData, xm, ind, ans, sd_0, cor, kendall); + } else if (!pair) { /* all | complete "var" */ + double[] xm = new double[ncx]; + boolean[] ind = new boolean[n]; + complete1(n, ncx, xData, ind, na_fail); + cov_complete1(n, ncx, xData, xm, ind, ans, sd_0, cor, kendall); + if (empty_err) { + boolean indany = false; + for (int i = 0; i < n; i++) { + if (ind[i]) { + indany = true; + break; } } - if (!checkNAs(sum)) { - sum /= n1; + if (!indany) { + error("no complete element pairs"); } - } else { /* Kendall's tau */ - throw new UnsupportedOperationException("kendall's unsupported"); } - xm[i] = checkNAs(sum) ? RRuntime.DOUBLE_NA : Math.sqrt(sum); + } else { /* pairwise "var" */ + cov_pairwise1(n, ncx, xData, ans, sd_0, cor, kendall); + } + } else { /* Co[vr] (x, y) */ + double[] yData = y.getDataWithoutCopying(); + if (everything) { + double[] xm = new double[ncx]; + double[] ym = new double[ncy]; + boolean[] ind = new boolean[ncx]; + boolean[] has_na_y = new boolean[ncy]; + find_na_2(n, ncx, ncy, xData, yData, ind, has_na_y); + cov_na_2(n, ncx, ncy, xData, yData, xm, ym, ind, has_na_y, ans, sd_0, cor, kendall); + } else if (!pair) { /* all | complete */ + double[] xm = new double[ncx]; + double[] ym = new double[ncy]; + boolean[] ind = new boolean[n]; + complete2(n, ncx, ncy, xData, yData, ind, na_fail); + cov_complete2(n, ncx, ncy, xData, yData, xm, ym, ind, ans, sd_0, cor, kendall); + if (empty_err) { + boolean indany = false; + for (int i = 0; i < n; i++) { + if (ind[i]) { + indany = true; + break; + } + } + if (!indany) { + error("no complete element pairs"); + } + } + } else { /* pairwise */ + cov_pairwise2(n, ncx, ncy, xData, yData, ans, sd_0, cor, kendall); } } } - private RuntimeException error(String message) { - throw error(Message.GENERIC, message); + private final boolean isCor; + + public Covcor(boolean isCor) { + this.isCor = isCor; } - private boolean checkNAs(double... xs) { - for (double x : xs) { - check.enable(x); - if (check.check(x)) { - return true; - } - } - return false; + static { + Casts casts = new Casts(Covcor.class); + casts.arg(0).mustNotBeMissing().mustBe(nullValue().not(), Message.IS_NULL, "x").asDoubleVector(); + casts.arg(1).mustNotBeMissing().asDoubleVector(); + casts.arg(2).asIntegerVector().findFirst(); + casts.arg(3).asLogicalVector().findFirst().map(toBoolean()); } - private boolean checkNAs(double x) { - check.enable(x); - return check.check(x); + @Specialization + public Object call(RAbstractDoubleVector x, @SuppressWarnings("unused") RNull y, int method, boolean iskendall) { + return corcov(x.materialize(), null, method, iskendall); } + + @Specialization + public Object call(RAbstractDoubleVector x, RAbstractDoubleVector y, int method, boolean iskendall) { + return corcov(x.materialize(), y.materialize(), method, iskendall); + } + + private final BranchProfile naInRes = BranchProfile.create(); + private final ConditionProfile matrixProfile = ConditionProfile.createBinaryProfile(); + + @Child private GetDimAttributeNode getDimsXNode = GetDimAttributeNode.create(); + @Child private GetDimAttributeNode getDimsYNode = GetDimAttributeNode.create(); + @Child private GetDimNamesAttributeNode getDimsNamesXNode = GetDimNamesAttributeNode.create(); + @Child private GetDimNamesAttributeNode getDimsNamesYNode = GetDimNamesAttributeNode.create(); + @Child private SetDimNamesAttributeNode setDimNamesNode = SetDimNamesAttributeNodeGen.create(); + @Child private IsFactorNode isFactorX = new IsFactorNode(); + @Child private IsFactorNode isFactorY = new IsFactorNode(); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java index 0b7bea50bf7e33cc7c76a4dfb782b1d26091f899..39146e8235b4014f1139a75ad00cb489a2347732 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java @@ -10,7 +10,7 @@ */ package com.oracle.truffle.r.nodes.builtin.base; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asIntegerVector; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asIntegerVectorClosure; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.complexValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; @@ -18,7 +18,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.BranchProfile; @@ -56,7 +55,7 @@ public abstract class APerm extends RBuiltinNode.Arg3 { static { Casts casts = new Casts(APerm.class); casts.arg("a").mustNotBeNull(RError.Message.FIRST_ARG_MUST_BE_ARRAY); - casts.arg("perm").allowNull().mustBe(numericValue().or(stringValue()).or(complexValue())).mapIf(numericValue().or(complexValue()), asIntegerVector()); + casts.arg("perm").allowNull().mustBe(numericValue().or(stringValue()).or(complexValue())).mapIf(numericValue().or(complexValue()), asIntegerVectorClosure()); casts.arg("resize").mustBe(numericValue().or(logicalValue()), Message.INVALID_LOGICAL, "resize").asLogicalVector().findFirst(); } @@ -129,7 +128,7 @@ public abstract class APerm extends RBuiltinNode.Arg3 { for (int i = 0; i < result.getLength(); i++) { int pos = toPos(applyPermute(posV, perm, true), dim); result.transferElementSameType(i, vector, pos); - posV = incArray(posV, pDim); + incArray(posV, pDim); } RList dimNames = getDimNamesNode.getDimNames(vector); @@ -219,7 +218,6 @@ public abstract class APerm extends RBuiltinNode.Arg3 { /** * Apply permute to an equal sized array. */ - @TruffleBoundary private static int[] applyPermute(int[] a, int[] perm, boolean reverse) { int[] newA = a.clone(); if (reverse) { @@ -235,25 +233,21 @@ public abstract class APerm extends RBuiltinNode.Arg3 { } /** - * Increment a stride array. + * Increment a stride array. Note: First input array may be modified. */ - @TruffleBoundary - private static int[] incArray(int[] a, int[] dim) { - int[] newA = a.clone(); - for (int i = 0; i < newA.length; i++) { - newA[i]++; - if (newA[i] < dim[i]) { + private static void incArray(int[] a, int[] dim) { + for (int i = 0; i < a.length; i++) { + a[i]++; + if (a[i] < dim[i]) { break; } - newA[i] = 0; + a[i] = 0; } - return newA; } /** * Stride array to a linear position. */ - @TruffleBoundary private static int toPos(int[] a, int[] dim) { int pos = a[0]; for (int i = 1; i < a.length; i++) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java index 50d0689a9aa446411dd26e17617ca41b4df9d3af..22761219ac9546f0177dac0fba74038d96a6fbb7 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java @@ -633,6 +633,7 @@ public class BasePackage extends RBuiltinPackage { add(Rank.class, RankNodeGen::create); add(RNGFunctions.RNGkind.class, RNGFunctionsFactory.RNGkindNodeGen::create); add(RNGFunctions.SetSeed.class, RNGFunctionsFactory.SetSeedNodeGen::create); + add(RNGFunctions.FastRSetSeed.class, RNGFunctionsFactory.FastRSetSeedNodeGen::create); add(RVersion.class, RVersionNodeGen::create); add(RawFunctions.CharToRaw.class, RawFunctionsFactory.CharToRawNodeGen::create); add(RawFunctions.RawToChar.class, RawFunctionsFactory.RawToCharNodeGen::create); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RNGFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RNGFunctions.java index 146b768b00d6e5e06d36ed4f3d07fb6438f9ec89..0d8a7a3ed9f02a2c78dd0abb9b43c22a6bd485c0 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RNGFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RNGFunctions.java @@ -33,15 +33,20 @@ import static com.oracle.truffle.r.runtime.RError.Message.UNIMPLEMENTED_TYPE_IN_ import static com.oracle.truffle.r.runtime.RVisibility.OFF; import static com.oracle.truffle.r.runtime.builtins.RBehavior.MODIFIES_STATE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; +import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RIntVector; +import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.rng.RRNG; public class RNGFunctions { @@ -97,6 +102,48 @@ public class RNGFunctions { } } + @RBuiltin(name = ".fastr.set.seed", visibility = OFF, kind = PRIMITIVE, parameterNames = {"data"}, behavior = MODIFIES_STATE) + public abstract static class FastRSetSeed extends RBuiltinNode.Arg1 { + + static { + Casts.noCasts(FastRSetSeed.class); + } + + @Specialization + @TruffleBoundary + protected RNull setSeed(RAbstractIntVector data) { + int[] arr = new int[data.getLength()]; + for (int i = 0; i < arr.length; i++) { + arr[i] = data.getDataAt(i); + } + RContext.getInstance().stateRNG.currentSeeds = arr; + return RNull.instance; + } + + protected boolean isSetOperation(Object param) { + return !(param instanceof RMissing); + } + + @Specialization(guards = {"isSetOperation(data)"}) + @TruffleBoundary + protected RNull setSeed(Object data) { + RContext.getInstance().stateRNG.currentSeeds = data; + return RNull.instance; + } + + @Specialization + @TruffleBoundary + protected Object getSeed(@SuppressWarnings("unused") RMissing data) { + Object seeds = RContext.getInstance().stateRNG.currentSeeds; + if (seeds instanceof int[]) { + int[] seedsArr = (int[]) seeds; + return RDataFactory.createIntVector(seedsArr, RDataFactory.INCOMPLETE_VECTOR); + } + assert seeds != null; + return seeds; + } + } + private static final class CastsHelper { public static void kindInteger(Casts casts, String name, Message error, Object... messageArgs) { casts.arg(name).mapNull(constant(RRNG.NO_KIND_CHANGE)).mustBe(numericValue(), error, messageArgs).asIntegerVector().findFirst(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java index abad492f9edd0a6c2fb3d83f0a84797ae82fcc5d..6bfbaee4764141396cf2a3c124e30af2bb92d6ab 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java @@ -22,7 +22,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.BranchProfile; -import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.profiles.LoopConditionProfile; import com.oracle.truffle.r.nodes.attributes.CopyOfRegAttributesNode; import com.oracle.truffle.r.nodes.attributes.CopyOfRegAttributesNodeGen; @@ -32,12 +31,18 @@ import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAt import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNamesAttributeNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.function.opt.ReuseNonSharedNode; import com.oracle.truffle.r.nodes.profile.VectorLengthProfile; import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RComplex; +import com.oracle.truffle.r.runtime.data.RComplexVector; import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RDoubleVector; +import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RLogicalVector; +import com.oracle.truffle.r.runtime.data.RRawVector; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RVector; import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; @@ -54,7 +59,6 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode; public abstract class Transpose extends RBuiltinNode.Arg1 { private final BranchProfile hasDimNamesProfile = BranchProfile.create(); - private final ConditionProfile isMatrixProfile = ConditionProfile.createBinaryProfile(); private final VectorLengthProfile lengthProfile = VectorLengthProfile.create(); private final LoopConditionProfile loopProfile = LoopConditionProfile.createCountingProfile(); @@ -66,6 +70,7 @@ public abstract class Transpose extends RBuiltinNode.Arg1 { @Child private GetDimNamesAttributeNode getDimNamesNode = GetDimNamesAttributeNode.create(); @Child private GetNamesAttributeNode getAxisNamesNode = GetNamesAttributeNode.create(); @Child private GetDimAttributeNode getDimNode; + @Child private ReuseNonSharedNode reuseNonShared = ReuseNonSharedNode.create(); static { Casts.noCasts(Transpose.class); @@ -78,22 +83,20 @@ public abstract class Transpose extends RBuiltinNode.Arg1 { void apply(A array, T vector, int i, int j); } + @FunctionalInterface + private interface Swap { + /** Swap element at (i, j) with element at (j, i). */ + void swap(int i, int j); + } + protected <T extends RAbstractVector, A> RVector<?> transposeInternal(T vector, Function<Integer, A> createArray, WriteArray<T, A> writeArray, BiFunction<A, Boolean, RVector<?>> createResult) { int length = lengthProfile.profile(vector.getLength()); int firstDim; int secondDim; - if (isMatrixProfile.profile(vector.isMatrix())) { - if (getDimNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - getDimNode = insert(GetDimAttributeNode.create()); - } - int[] dims = getDimNode.getDimensions(vector); - firstDim = dims[0]; - secondDim = dims[1]; - } else { - firstDim = length; - secondDim = 1; - } + assert vector.isMatrix(); + int[] dims = getDimensions(vector); + firstDim = dims[0]; + secondDim = dims[1]; RBaseNode.reportWork(this, length); A array = createArray.apply(length); @@ -110,36 +113,144 @@ public abstract class Transpose extends RBuiltinNode.Arg1 { copyRegAttributes.execute(vector, r); // set new dimensions int[] newDim = new int[]{secondDim, firstDim}; - putDimensions.execute(initAttributes.execute(r), RDataFactory.createIntVector(newDim, RDataFactory.COMPLETE_VECTOR)); - // set new dim names - RList dimNames = getDimNamesNode.getDimNames(vector); - if (dimNames != null) { - hasDimNamesProfile.enter(); - assert dimNames.getLength() == 2; - RStringVector axisNames = getAxisNamesNode.getNames(dimNames); - RStringVector transAxisNames = axisNames == null ? null : RDataFactory.createStringVector(new String[]{axisNames.getDataAt(1), axisNames.getDataAt(0)}, true); - RList newDimNames = RDataFactory.createList(new Object[]{dimNames.getDataAt(1), dimNames.getDataAt(0)}, transAxisNames); - putDimNames.execute(r.getAttributes(), newDimNames); - } + putNewDimensions(vector, r, newDim); return r; } - @Specialization + protected RVector<?> transposeSquareMatrixInPlace(RVector<?> vector, Swap swapper) { + int length = lengthProfile.profile(vector.getLength()); + assert vector.isMatrix(); + int[] dims = getDimensions(vector); + assert dims.length == 2; + assert dims[0] == dims[1]; + int dim = dims[0]; + RBaseNode.reportWork(this, length); + + loopProfile.profileCounted(length); + for (int i = 0; loopProfile.inject(i < dim); i++) { + for (int j = 0; j < i; j++) { + swapper.swap(i * dim + j, j * dim + i); + } + } + // don't need to set new dimensions; it is a square matrix + putNewDimNames(vector, vector); + return vector; + } + + private int[] getDimensions(RAbstractVector vector) { + assert vector.isMatrix(); + if (getDimNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getDimNode = insert(GetDimAttributeNode.create()); + } + return getDimNode.getDimensions(vector); + } + + protected boolean isSquare(RAbstractVector vector) { + if (vector.isMatrix()) { + int[] dims = getDimensions(vector); + assert dims.length >= 2; + return dims[0] == dims[1]; + } + return false; + } + + @Specialization(guards = "isSquare(x)") + protected RVector<?> transposeSquare(RAbstractIntVector x) { + RIntVector reused = (RIntVector) reuseNonShared.execute(x).materialize(); + int[] store = reused.getDataWithoutCopying(); + return transposeSquareMatrixInPlace(reused, (i, j) -> { + int tmp = store[i]; + store[i] = store[j]; + store[j] = tmp; + }); + } + + @Specialization(guards = "isSquare(x)") + protected RVector<?> transposeSquare(RAbstractLogicalVector x) { + RLogicalVector reused = (RLogicalVector) reuseNonShared.execute(x).materialize(); + byte[] store = reused.getDataWithoutCopying(); + return transposeSquareMatrixInPlace(reused, (i, j) -> { + byte tmp = store[i]; + store[i] = store[j]; + store[j] = tmp; + }); + } + + @Specialization(guards = "isSquare(x)") + protected RVector<?> transposeSquare(RAbstractDoubleVector x) { + RDoubleVector reused = (RDoubleVector) reuseNonShared.execute(x).materialize(); + double[] store = reused.getDataWithoutCopying(); + return transposeSquareMatrixInPlace(reused, (i, j) -> { + double tmp = store[i]; + store[i] = store[j]; + store[j] = tmp; + }); + } + + @Specialization(guards = "isSquare(x)") + protected RVector<?> transposeSquare(RAbstractComplexVector x) { + RComplexVector reused = (RComplexVector) reuseNonShared.execute(x).materialize(); + double[] store = reused.getDataWithoutCopying(); + return transposeSquareMatrixInPlace(reused, (i, j) -> { + double tmpReal = store[i * 2]; + double tmpImg = store[i * 2 + 1]; + store[i * 2] = store[j * 2]; + store[i * 2 + 1] = store[j * 2 + 1]; + store[j * 2] = tmpReal; + store[j * 2 + 1] = tmpImg; + }); + } + + @Specialization(guards = "isSquare(x)") + protected RVector<?> transposeSquare(RAbstractStringVector x) { + RStringVector reused = (RStringVector) reuseNonShared.execute(x).materialize(); + String[] store = reused.getDataWithoutCopying(); + return transposeSquareMatrixInPlace(reused, (i, j) -> { + String tmp = store[i]; + store[i] = store[j]; + store[j] = tmp; + }); + } + + @Specialization(guards = "isSquare(x)") + protected RVector<?> transposeSquare(RAbstractListVector x) { + RList reused = (RList) reuseNonShared.execute(x).materialize(); + Object[] store = reused.getDataWithoutCopying(); + return transposeSquareMatrixInPlace(reused, (i, j) -> { + Object tmp = store[i]; + store[i] = store[j]; + store[j] = tmp; + }); + } + + @Specialization(guards = "isSquare(x)") + protected RVector<?> transposeSquare(RAbstractRawVector x) { + RRawVector reused = (RRawVector) reuseNonShared.execute(x).materialize(); + byte[] store = reused.getDataWithoutCopying(); + return transposeSquareMatrixInPlace(reused, (i, j) -> { + byte tmp = store[i]; + store[i] = store[j]; + store[j] = tmp; + }); + } + + @Specialization(guards = {"x.isMatrix()", "!isSquare(x)"}) protected RVector<?> transpose(RAbstractIntVector x) { return transposeInternal(x, l -> new int[l], (a, v, i, j) -> a[i] = v.getDataAt(j), RDataFactory::createIntVector); } - @Specialization + @Specialization(guards = {"x.isMatrix()", "!isSquare(x)"}) protected RVector<?> transpose(RAbstractLogicalVector x) { return transposeInternal(x, l -> new byte[l], (a, v, i, j) -> a[i] = v.getDataAt(j), RDataFactory::createLogicalVector); } - @Specialization + @Specialization(guards = {"x.isMatrix()", "!isSquare(x)"}) protected RVector<?> transpose(RAbstractDoubleVector x) { return transposeInternal(x, l -> new double[l], (a, v, i, j) -> a[i] = v.getDataAt(j), RDataFactory::createDoubleVector); } - @Specialization + @Specialization(guards = {"x.isMatrix()", "!isSquare(x)"}) protected RVector<?> transpose(RAbstractComplexVector x) { return transposeInternal(x, l -> new double[l * 2], (a, v, i, j) -> { RComplex d = v.getDataAt(j); @@ -148,21 +259,48 @@ public abstract class Transpose extends RBuiltinNode.Arg1 { }, RDataFactory::createComplexVector); } - @Specialization + @Specialization(guards = {"x.isMatrix()", "!isSquare(x)"}) protected RVector<?> transpose(RAbstractStringVector x) { return transposeInternal(x, l -> new String[l], (a, v, i, j) -> a[i] = v.getDataAt(j), RDataFactory::createStringVector); } - @Specialization + @Specialization(guards = {"x.isMatrix()", "!isSquare(x)"}) protected RVector<?> transpose(RAbstractListVector x) { return transposeInternal(x, l -> new Object[l], (a, v, i, j) -> a[i] = v.getDataAt(j), (a, c) -> RDataFactory.createList(a)); } - @Specialization + @Specialization(guards = {"x.isMatrix()", "!isSquare(x)"}) protected RVector<?> transpose(RAbstractRawVector x) { return transposeInternal(x, l -> new byte[l], (a, v, i, j) -> a[i] = v.getRawDataAt(j), (a, c) -> RDataFactory.createRawVector(a)); } + @Specialization(guards = "!x.isMatrix()") + protected RVector<?> transpose(RAbstractVector x) { + RVector<?> reused = reuseNonShared.execute(x); + putNewDimensions(reused, reused, new int[]{1, x.getLength()}); + return reused; + + } + + private void putNewDimensions(RAbstractVector source, RVector<?> dest, int[] newDim) { + putDimensions.execute(initAttributes.execute(dest), RDataFactory.createIntVector(newDim, RDataFactory.COMPLETE_VECTOR)); + putNewDimNames(source, dest); + } + + private void putNewDimNames(RAbstractVector source, RVector<?> dest) { + // set new dim names + RList dimNames = getDimNamesNode.getDimNames(source); + if (dimNames != null) { + hasDimNamesProfile.enter(); + assert dimNames.getLength() == 2; + RStringVector axisNames = getAxisNamesNode.getNames(dimNames); + RStringVector transAxisNames = axisNames == null ? null : RDataFactory.createStringVector(new String[]{axisNames.getDataAt(1), axisNames.getDataAt(0)}, true); + RList newDimNames = RDataFactory.createList(new Object[]{dimNames.getDataAt(1), + dimNames.getDataAt(0)}, transAxisNames); + putDimNames.execute(dest.getAttributes(), newDimNames); + } + } + @Fallback protected RVector<?> transpose(@SuppressWarnings("unused") Object x) { throw error(Message.ARGUMENT_NOT_MATRIX); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java index 2eb33a9b1299a8e003ef3c6a189b701c63599768..5960ab3be7d4a1c7c74fe33c98b62aaaadeebfec 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java @@ -62,12 +62,12 @@ import com.oracle.truffle.r.library.tools.ToolsTextFactory.DoTabExpandNodeGen; import com.oracle.truffle.r.library.utils.CountFieldsNodeGen; import com.oracle.truffle.r.library.utils.Crc64NodeGen; import com.oracle.truffle.r.library.utils.DownloadNodeGen; -import com.oracle.truffle.r.library.utils.UnzipNodeGen; import com.oracle.truffle.r.library.utils.MenuNodeGen; import com.oracle.truffle.r.library.utils.ObjectSizeNodeGen; import com.oracle.truffle.r.library.utils.RprofNodeGen; import com.oracle.truffle.r.library.utils.RprofmemNodeGen; import com.oracle.truffle.r.library.utils.TypeConvertNodeGen; +import com.oracle.truffle.r.library.utils.UnzipNodeGen; import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; import com.oracle.truffle.r.nodes.builtin.RInternalCodeBuiltinNode; import com.oracle.truffle.r.nodes.objects.GetPrimNameNodeGen; @@ -581,7 +581,7 @@ public class CallAndExternalFunctions { return getExternalModelBuiltinNode("updateform"); case "Cdqrls": - return new RInternalCodeBuiltinNode(RContext.getInstance(), "stats", RInternalCode.loadSourceRelativeTo(RandFunctionsNodes.class, "lm.R"), "Cdqrls"); + return new RInternalCodeBuiltinNode("stats", RInternalCode.loadSourceRelativeTo(RandFunctionsNodes.class, "lm.R"), "Cdqrls"); case "dnorm": return StatsFunctionsNodes.Function3_1Node.create(new DNorm()); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java index 40e7c89190b120ecd29164dbe0d3adeb38019c92..881a395fcde021c36f781208e3960553207e47c7 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java @@ -39,7 +39,6 @@ import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RInternalCode; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RExternalPtr; import com.oracle.truffle.r.runtime.data.RList; @@ -173,7 +172,7 @@ abstract class LookupAdapter extends RBuiltinNode.Arg3 implements Lookup { } protected static RExternalBuiltinNode getExternalModelBuiltinNode(String name) { - return new RInternalCodeBuiltinNode(RContext.getInstance(), "stats", RInternalCode.loadSourceRelativeTo(RandFunctionsNodes.class, "model.R"), name); + return new RInternalCodeBuiltinNode("stats", RInternalCode.loadSourceRelativeTo(RandFunctionsNodes.class, "model.R"), name); } protected static final int CallNST = DLL.NativeSymbolType.Call.ordinal(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java index 1fec8cd3b23c6b2290daafc56f8784015f74b0b5..08dc511069deb09535a9407207f0a7d224cb8414 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java @@ -140,16 +140,26 @@ public class FastRContext { EvalThread[] threads = new EvalThread[length]; int[] data = new int[length]; int[] multiSlotIndices = new int[length]; + + // first, create context infos + ChildContextInfo[] childContextInfos = new ChildContextInfo[length]; for (int i = 0; i < length; i++) { - ChildContextInfo info = createContextInfo(contextKind); - threads[i] = new EvalThread(RContext.getInstance().threads, info, RSource.fromTextInternalInvisible(exprs.getDataAt(i % exprs.getLength()), RSource.Internal.CONTEXT_EVAL), - FastROptions.SpawnUsesPolyglot.getBooleanValue()); - data[i] = info.getId(); - multiSlotIndices[i] = info.getMultiSlotInd(); + childContextInfos[i] = createContextInfo(contextKind); + data[i] = childContextInfos[i].getId(); + multiSlotIndices[i] = childContextInfos[i].getMultiSlotInd(); } + + // convert shared slots to multi slots if (contextKind == ContextKind.SHARE_ALL) { REnvironment.convertSearchpathToMultiSlot(multiSlotIndices); } + + // create eval threads which may already set values to shared slots + for (int i = 0; i < length; i++) { + threads[i] = new EvalThread(RContext.getInstance().threads, childContextInfos[i], + RSource.fromTextInternalInvisible(exprs.getDataAt(i % exprs.getLength()), RSource.Internal.CONTEXT_EVAL), + FastROptions.SpawnUsesPolyglot.getBooleanValue()); + } for (int i = 0; i < length; i++) { threads[i].start(); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java index e699b28a722a88eee6ce7197b16fa856e64056bb..25dd64ff7977d1cae004fd2689f1500d9070ecc8 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java @@ -165,12 +165,14 @@ abstract class BaseWriteVariableNode extends WriteVariableNode { * @param value The value to set. * @param frameSlot The frame slot of the value. * @param invalidateProfile The invalidation profile. + * @param mode + * @param storedObjectProfile */ - protected static Object handleActiveBinding(VirtualFrame execFrame, Frame lookupFrame, Object value, FrameSlot frameSlot, BranchProfile invalidateProfile, - ConditionProfile isActiveBindingProfile) { + protected Object handleActiveBinding(VirtualFrame execFrame, Frame lookupFrame, Object value, FrameSlot frameSlot, BranchProfile invalidateProfile, + ConditionProfile isActiveBindingProfile, ValueProfile storedObjectProfile, Mode mode) { Object object; try { - object = lookupFrame.getObject(frameSlot); + object = FrameSlotChangeMonitor.getObject(frameSlot, lookupFrame); } catch (FrameSlotTypeException e) { object = null; } @@ -178,7 +180,8 @@ abstract class BaseWriteVariableNode extends WriteVariableNode { if (isActiveBindingProfile.profile(object != null && ActiveBinding.isActiveBinding(object))) { return ((ActiveBinding) object).writeValue(value); } else { - FrameSlotChangeMonitor.setObjectAndInvalidate(lookupFrame, frameSlot, value, false, invalidateProfile); + Object newValue = shareObjectValue(lookupFrame, frameSlot, storedObjectProfile.profile(value), mode, false); + FrameSlotChangeMonitor.setObjectAndInvalidate(lookupFrame, frameSlot, newValue, false, invalidateProfile); } return value; } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteLocalFrameVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteLocalFrameVariableNode.java index 86d28f126c57d23da16604efa3726315ee20d2fd..58f07b278db0aeecb981f7d3c5d9772d348343d0 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteLocalFrameVariableNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteLocalFrameVariableNode.java @@ -102,7 +102,7 @@ public abstract class WriteLocalFrameVariableNode extends BaseWriteVariableNode FrameSlotChangeMonitor.setObjectAndInvalidate(frame, frameSlot, newValue, false, invalidateProfile); } else { // it's a local variable lookup; so use 'frame' for both, executing and looking up - return handleActiveBinding(frame, frame, value, frameSlot, invalidateProfile, isActiveBindingProfile); + return handleActiveBinding(frame, frame, value, frameSlot, invalidateProfile, isActiveBindingProfile, storedObjectProfile, mode); } return value; } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java index a389e83a421b23979dea86644709a63e9e5aa1a1..90f278cc2dd0b4fed1799c3b25bbf719138274c3 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java @@ -111,7 +111,7 @@ abstract class WriteSuperFrameVariableNode extends BaseWriteVariableNode { Object newValue = shareObjectValue(profiledFrame, frameSlot, storedObjectProfile.profile(value), mode, true); FrameSlotChangeMonitor.setObjectAndInvalidate(profiledFrame, frameSlot, newValue, true, invalidateProfile); } else { - handleActiveBinding(frame, profiledFrame, value, frameSlot, invalidateProfile, isActiveBindingProfile); + handleActiveBinding(frame, profiledFrame, value, frameSlot, invalidateProfile, isActiveBindingProfile, storedObjectProfile, mode); } } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java index 5b9aa4568a6e5ed0f5ea01ef1c78fa11fbe08479..3db82a9b2c9413691c66c98adcb2397232c94c56 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java @@ -575,18 +575,17 @@ public final class ReadVariableNode extends RBaseNode { LookupResult lookup = FrameSlotChangeMonitor.lookup(variableFrame, identifier); if (lookup != null) { try { - if (lookup.getValue() instanceof RPromise) { - evalPromiseSlowPathWithName(identifierAsString, frame, (RPromise) lookup.getValue()); + Object value = lookup.getValue(); + if (value instanceof RPromise) { + evalPromiseSlowPathWithName(identifierAsString, frame, (RPromise) value); } - if (lookup != null) { - if (lookup instanceof FrameAndSlotLookupResult) { - if (checkTypeSlowPath(frame, lookup.getValue())) { - return new FrameAndSlotLookupLevel((FrameAndSlotLookupResult) lookup); - } - } else { - if (lookup.getValue() == null || checkTypeSlowPath(frame, lookup.getValue())) { - return new LookupLevel(lookup); - } + if (lookup instanceof FrameAndSlotLookupResult) { + if (checkTypeSlowPath(frame, value)) { + return new FrameAndSlotLookupLevel((FrameAndSlotLookupResult) lookup); + } + } else { + if (value == null || checkTypeSlowPath(frame, value)) { + return new LookupLevel(lookup); } } } catch (InvalidAssumptionException e) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java index db90dae6c50d38ff99d11dd4e0073fa4f1846018..71a7e7c7183b7deb12ec8bcccd4e06d9167c3026 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java @@ -243,7 +243,7 @@ final class CachedReplaceVectorNode extends CachedVectorNode { } if (!isList() && value instanceof RAbstractVector) { - value = ((RAbstractVector) value).castSafe(castType, valueIsNA); + value = ((RAbstractVector) value).castSafe(castType, valueIsNA, false); } vector = share(vector, value); @@ -352,7 +352,7 @@ final class CachedReplaceVectorNode extends CachedVectorNode { if (castType == RType.List) { return CastListNodeGen.create(true, false, true); } else { - return CastTypeNode.createCast(castType, true, true, true); + return CastTypeNode.createCast(castType, true, true, true, false); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java index 65e0a251a686ca0150292f619be37dd2f3af7466..144f9715275a59198d1cb573a887ef75bcf9c106 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java @@ -63,7 +63,12 @@ public abstract class CastTypeNode extends RBaseNode { @TruffleBoundary public static CastNode createCast(RType type) { - return createCast(type, false, false, false); + return createCast(type, false, false, false, false); + } + + @TruffleBoundary + public static CastNode createCast(RType type, boolean reuseNonShared) { + return createCast(type, false, false, false, reuseNonShared); } public static CastTypeNode create() { @@ -71,16 +76,16 @@ public abstract class CastTypeNode extends RBaseNode { } @TruffleBoundary - public static CastNode createCast(RType type, boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { + public static CastNode createCast(RType type, boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean reuseNonShared) { switch (type) { case Character: return CastStringNodeGen.create(preserveNames, preserveDimensions, preserveAttributes); case Complex: return CastComplexNodeGen.create(preserveNames, preserveDimensions, preserveAttributes); case Double: - return CastDoubleNodeGen.create(preserveNames, preserveDimensions, preserveAttributes); + return CastDoubleNodeGen.create(preserveNames, preserveDimensions, preserveAttributes, false, reuseNonShared); case Integer: - return CastIntegerNodeGen.create(preserveNames, preserveDimensions, preserveAttributes); + return CastIntegerNodeGen.create(preserveNames, preserveDimensions, preserveAttributes, false, reuseNonShared); case Logical: return CastLogicalNodeGen.create(preserveNames, preserveDimensions, preserveAttributes); case Raw: diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java index 70f34a3d31d1afd35087958cefe70a8de97c20a1..d22c10086a9be1b3f9388fb1bce0ac9bc72c2122 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java @@ -332,8 +332,16 @@ public final class CastBuilder { return new CoercionStep<>(RType.Integer, true); } + public static <T> PipelineStep<T, RAbstractIntVector> asIntegerVectorClosure() { + return new CoercionStep<>(RType.Integer, true, false, false, false, true, true); + } + public static <T> PipelineStep<T, RAbstractIntVector> asIntegerVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { - return new CoercionStep<>(RType.Integer, true, preserveNames, preserveDimensions, preserveAttributes, true); + return new CoercionStep<>(RType.Integer, true, preserveNames, preserveDimensions, preserveAttributes, true, false); + } + + public static <T> PipelineStep<T, RAbstractIntVector> asIntegerVectorClosure(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { + return new CoercionStep<>(RType.Integer, true, preserveNames, preserveDimensions, preserveAttributes, true, true); } public static <T> PipelineStep<T, Double> asDouble() { @@ -344,10 +352,18 @@ public final class CastBuilder { return new CoercionStep<>(RType.Double, true); } + public static <T> PipelineStep<T, RAbstractDoubleVector> asDoubleVectorClosure() { + return new CoercionStep<>(RType.Double, true, false, false, false, true, true); + } + public static <T> PipelineStep<T, RAbstractDoubleVector> asDoubleVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { return new CoercionStep<>(RType.Double, true, preserveNames, preserveDimensions, preserveAttributes); } + public static <T> PipelineStep<T, RAbstractDoubleVector> asDoubleVectorClosure(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { + return new CoercionStep<>(RType.Double, true, preserveNames, preserveDimensions, preserveAttributes, true, true); + } + public static <T> PipelineStep<T, String> asString() { return new CoercionStep<>(RType.Character, false); } @@ -377,7 +393,7 @@ public final class CastBuilder { } public static <T> PipelineStep<T, RAbstractLogicalVector> asLogicalVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { - return new CoercionStep<>(RType.Logical, true, preserveNames, preserveDimensions, preserveAttributes, false); + return new CoercionStep<>(RType.Logical, true, preserveNames, preserveDimensions, preserveAttributes, false, false); } public static PipelineStep<Byte, Boolean> asBoolean() { @@ -389,7 +405,7 @@ public final class CastBuilder { } public static <T> PipelineStep<T, RAbstractVector> asVector(boolean preserveNonVector) { - return new CoercionStep<>(RType.Any, true, false, false, false, preserveNonVector); + return new CoercionStep<>(RType.Any, true, false, false, false, preserveNonVector, false); } /** diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RInternalCodeBuiltinNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RInternalCodeBuiltinNode.java index 05e91851108907a73d5716dc0e76df049bb96fa4..d742c32b3c49adf12a1751084d89d2ea0bdb08ad 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RInternalCodeBuiltinNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RInternalCodeBuiltinNode.java @@ -22,8 +22,6 @@ */ package com.oracle.truffle.r.nodes.builtin; -import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.r.nodes.function.CallMatcherNode; @@ -40,20 +38,17 @@ import com.oracle.truffle.r.runtime.data.RFunction; */ public final class RInternalCodeBuiltinNode extends RExternalBuiltinNode { - private final RContext context; private final String basePackage; private final Source code; private final String functionName; @Child private CallMatcherNode call = CallMatcherNode.create(true); - @CompilationFinal private RFunction function; static { Casts.noCasts(RInternalCodeBuiltinNode.class); } - public RInternalCodeBuiltinNode(RContext context, String basePackage, Source code, String functionName) { - this.context = context; + public RInternalCodeBuiltinNode(String basePackage, Source code, String functionName) { this.basePackage = basePackage; this.code = code; this.functionName = functionName; @@ -66,15 +61,13 @@ public final class RInternalCodeBuiltinNode extends RExternalBuiltinNode { @Override public Object call(VirtualFrame frame, RArgsValuesAndNames actualArgs) { + RInternalCode internalCode = RInternalCode.lookup(RContext.getInstance(), basePackage, code); + RFunction function = internalCode.lookupFunction(functionName); if (function == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - RInternalCode internalCode = RInternalCode.lookup(context, basePackage, code); - this.function = internalCode.lookupFunction(functionName); - if (this.function == null) { - throw RInternalError.shouldNotReachHere("Could not load RInternalCodeBuiltin function '" + functionName + "'."); - } + throw RInternalError.shouldNotReachHere("Could not load RInternalCodeBuiltin function '" + functionName + "'."); } return call.execute(frame, actualArgs.getSignature(), actualArgs.getArguments(), function, functionName, null); } + } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java index 7f4776692ec9714a69e551a85df015bd8896763d..4e9bdc24d38dd198fe16a92a601791aa425af6d8 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java @@ -176,21 +176,28 @@ public abstract class PipelineStep<T, R> { */ public final boolean vectorCoercion; + /** + * Allows the cast node to create and use wrappers for vectors. Only use if you know the + * vector to be casted won't escape and preferably if the vector is just used read-only. + */ + public final boolean useClosure; + public CoercionStep(RType type, boolean vectorCoercion) { - this(type, vectorCoercion, false, false, false, true); + this(type, vectorCoercion, false, false, false, true, false); } public CoercionStep(RType type, boolean vectorCoercion, boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { - this(type, vectorCoercion, preserveNames, preserveDimensions, preserveAttributes, true); + this(type, vectorCoercion, preserveNames, preserveDimensions, preserveAttributes, true, false); } - public CoercionStep(RType type, boolean vectorCoercion, boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean preserveNonVector) { + public CoercionStep(RType type, boolean vectorCoercion, boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean preserveNonVector, boolean useClosure) { this.type = type; this.vectorCoercion = vectorCoercion; this.preserveNames = preserveNames; this.preserveAttributes = preserveAttributes; this.preserveDimensions = preserveDimensions; this.preserveNonVector = preserveNonVector; + this.useClosure = useClosure; } public RType getType() { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java index 12aaa0ec1f3df2f353fbc0bc633110f87b42698f..e0c252dfd5387ebc560c2f338682add035352804 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java @@ -226,11 +226,11 @@ public final class PipelineToCastNode { RType type = step.getType(); switch (type) { case Integer: - return step.vectorCoercion ? CastIntegerNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes) - : CastIntegerBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes); + return step.vectorCoercion ? CastIntegerNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, false, step.useClosure) + : CastIntegerBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, false, step.useClosure); case Double: - return step.vectorCoercion ? CastDoubleNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes) - : CastDoubleBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes); + return step.vectorCoercion ? CastDoubleNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, false, step.useClosure) + : CastDoubleBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, false, step.useClosure); case Character: return step.vectorCoercion ? CastStringNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes) : CastStringBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/InitialPhaseBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/InitialPhaseBuilder.java index c66079bf6e6e723802b7c99c7355f7918945afdb..0773eb292340d60d60a681cadc752f56aeca219a 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/InitialPhaseBuilder.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/InitialPhaseBuilder.java @@ -159,6 +159,20 @@ public class InitialPhaseBuilder<T> extends ArgCastBuilder<T, InitialPhaseBuilde return asIntegerVector(false, false, false); } + public CoercedPhaseBuilder<RAbstractIntVector, Integer> asIntegerVectorClosure(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { + pipelineBuilder().appendAsVectorClosure(RType.Integer, preserveNames, preserveDimensions, preserveAttributes); + return new CoercedPhaseBuilder<>(pipelineBuilder(), Integer.class); + } + + public CoercedPhaseBuilder<RAbstractIntVector, Integer> asIntegerVectorClosure() { + return asIntegerVectorClosure(false, false, false); + } + + public CoercedPhaseBuilder<RAbstractDoubleVector, Double> asDoubleVectorClosure(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { + pipelineBuilder().appendAsVectorClosure(RType.Double, preserveNames, preserveDimensions, preserveAttributes); + return new CoercedPhaseBuilder<>(pipelineBuilder(), Double.class); + } + public CoercedPhaseBuilder<RAbstractDoubleVector, Double> asDoubleVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { pipelineBuilder().appendAsVector(RType.Double, preserveNames, preserveDimensions, preserveAttributes); return new CoercedPhaseBuilder<>(pipelineBuilder(), Double.class); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java index 56374865240205f24e9b8a7a99656277ed34a29e..c40a4f293f33174ced113f85aa4b89a345390bc3 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java @@ -76,12 +76,17 @@ public final class PipelineBuilder { } public void appendAsVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean preserveNonVector) { - append(new CoercionStep<>(RType.Any, true, preserveNames, preserveDimensions, preserveAttributes, preserveNonVector)); + append(new CoercionStep<>(RType.Any, true, preserveNames, preserveDimensions, preserveAttributes, preserveNonVector, false)); } public void appendAsVector(RType type, boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { assert type == RType.Integer || type == RType.Double || type == RType.Complex || type == RType.Character || type == RType.Logical || type == RType.Raw; - append(new CoercionStep<>(type, true, preserveNames, preserveDimensions, preserveAttributes, true)); + append(new CoercionStep<>(type, true, preserveNames, preserveDimensions, preserveAttributes, true, false)); + } + + public void appendAsVectorClosure(RType type, boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { + assert type == RType.Integer || type == RType.Double || type == RType.Complex || type == RType.Character || type == RType.Logical || type == RType.Raw; + append(new CoercionStep<>(type, true, preserveNames, preserveDimensions, preserveAttributes, true, true)); } public void appendNotNA(Object naReplacement, Message message, Object[] messageArgs) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/BinaryMapNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/BinaryMapNode.java index 009a71466344b12089f6fe90ff57ad6707b7c615..164d40610dfc4da9704996e4c9fdb816c29071a2 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/BinaryMapNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/BinaryMapNode.java @@ -127,8 +127,8 @@ public final class BinaryMapNode extends RBaseNode { RAbstractVector left = leftClass.cast(originalLeft); RAbstractVector right = rightClass.cast(originalRight); - RAbstractVector leftCast = left.castSafe(argumentType, leftIsNAProfile); - RAbstractVector rightCast = right.castSafe(argumentType, rightIsNAProfile); + RAbstractVector leftCast = left.castSafe(argumentType, leftIsNAProfile, false); + RAbstractVector rightCast = right.castSafe(argumentType, rightIsNAProfile, false); assert leftCast != null; assert rightCast != null; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastBaseNode.java index d94c36c1dc1816afdcf4ff0f4ebcca750a72ee7c..8216976903f773de772b3b7bea546ad3d34e26cd 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastBaseNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastBaseNode.java @@ -28,6 +28,7 @@ import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNamesAttributeNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode; @@ -42,8 +43,8 @@ import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RTypedValue; -import com.oracle.truffle.r.runtime.data.RVector; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.env.REnvironment; public abstract class CastBaseNode extends CastNode { @@ -52,6 +53,8 @@ public abstract class CastBaseNode extends CastNode { private final ConditionProfile hasDimNamesProfile = ConditionProfile.createBinaryProfile(); private final NullProfile hasDimensionsProfile = NullProfile.create(); private final NullProfile hasNamesProfile = NullProfile.create(); + private final ValueProfile reuseClassProfile; + @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create(); @Child private GetDimAttributeNode getDimNode; @Child private SetDimNamesAttributeNode setDimNamesNode; @@ -61,6 +64,9 @@ public abstract class CastBaseNode extends CastNode { private final boolean preserveDimensions; private final boolean preserveAttributes; + /** {@code true} if a cast should wrap the input in a closure. */ + private final boolean useClosure; + /** * GnuR provides several, sometimes incompatible, ways to coerce given value to given type. This * flag tells the cast node that it should behave in a way compatible with functions exposed by @@ -73,6 +79,10 @@ public abstract class CastBaseNode extends CastNode { } protected CastBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI) { + this(preserveNames, preserveDimensions, preserveAttributes, forRFFI, false); + } + + protected CastBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI, boolean useClosure) { this.preserveNames = preserveNames; this.preserveDimensions = preserveDimensions; this.preserveAttributes = preserveAttributes; @@ -80,6 +90,8 @@ public abstract class CastBaseNode extends CastNode { if (preserveDimensions) { getDimNamesNode = GetDimNamesAttributeNode.create(); } + this.useClosure = useClosure; + reuseClassProfile = useClosure ? ValueProfile.createClassProfile() : null; } public final boolean preserveNames() { @@ -90,10 +102,18 @@ public abstract class CastBaseNode extends CastNode { return preserveDimensions; } - public final boolean preserveAttributes() { + public final boolean preserveRegAttributes() { return preserveAttributes; } + public final boolean preserveAttributes() { + return preserveAttributes || preserveNames || preserveDimensions; + } + + public final boolean reuseNonShared() { + return useClosure; + } + protected abstract RType getTargetType(); protected RError throwCannotCoerceListError(String type) { @@ -121,7 +141,7 @@ public abstract class CastBaseNode extends CastNode { } } - protected void preserveDimensionNames(RAbstractContainer operand, RVector<?> ret) { + protected void preserveDimensionNames(RAbstractContainer operand, RAbstractContainer ret) { if (preserveDimensions()) { RList dimNames = getDimNamesNode.getDimNames(operand); if (hasDimNamesProfile.profile(dimNames != null)) { @@ -161,4 +181,13 @@ public abstract class CastBaseNode extends CastNode { } return RNull.instance; } + + protected boolean useClosure() { + return useClosure; + } + + protected RAbstractVector castWithReuse(RType targetType, RAbstractVector v, ConditionProfile naProfile) { + assert useClosure(); + return reuseClassProfile.profile(v.castSafe(targetType, naProfile, preserveAttributes())); + } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastComplexNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastComplexNode.java index 88151421902d9518fbfeb23035b5ca4e27bcce3e..6ffad041e4fb8487ba00969848c3f334541226bc 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastComplexNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastComplexNode.java @@ -76,7 +76,7 @@ public abstract class CastComplexNode extends CastBaseNode { private Object castComplexRecursive(Object o) { if (recursiveCastComplex == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - recursiveCastComplex = insert(CastComplexNodeGen.create(preserveNames(), preserveDimensions(), preserveAttributes())); + recursiveCastComplex = insert(CastComplexNodeGen.create(preserveNames(), preserveDimensions(), preserveRegAttributes())); } return recursiveCastComplex.executeComplex(o); } @@ -151,7 +151,7 @@ public abstract class CastComplexNode extends CastBaseNode { } RComplexVector ret = RDataFactory.createComplexVector(ddata, !seenNA, getPreservedDimensions(operand), getPreservedNames(operand)); preserveDimensionNames(operand, ret); - if (preserveAttributes()) { + if (preserveRegAttributes()) { ret.copyRegAttributesFrom(operand); } return ret; @@ -204,7 +204,7 @@ public abstract class CastComplexNode extends CastBaseNode { } RComplexVector ret = RDataFactory.createComplexVector(ddata, !seenNA, getPreservedDimensions(operand), getPreservedNames(operand)); preserveDimensionNames(operand, ret); - if (preserveAttributes()) { + if (preserveRegAttributes()) { ret.copyRegAttributesFrom(operand); } return ret; @@ -258,7 +258,7 @@ public abstract class CastComplexNode extends CastBaseNode { } } RComplexVector ret = RDataFactory.createComplexVector(result, !seenNA, getPreservedDimensions(list), getPreservedNames(list)); - if (preserveAttributes()) { + if (preserveRegAttributes()) { ret.copyRegAttributesFrom(list); } return ret; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleBaseNode.java index 9abeb67a8dbd105abcaf074d9907ab0aae07ff15..15a9514d39ce31cb0f683a2a18472e2e6b626c5b 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleBaseNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleBaseNode.java @@ -44,8 +44,8 @@ public abstract class CastDoubleBaseNode extends CastBaseNode { super(preserveNames, preserveDimensions, preserveAttributes); } - protected CastDoubleBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI) { - super(preserveNames, preserveDimensions, preserveAttributes, forRFFI); + protected CastDoubleBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI, boolean useClosure) { + super(preserveNames, preserveDimensions, preserveAttributes, forRFFI, useClosure); } @Override diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java index f0e17bb98d59f24aaf75f02466000cf858f55606..142974974969bfdce18caf7c210511097739755e 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java @@ -31,20 +31,22 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.RComplexVector; import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RDoubleSequence; import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.RRawVector; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; +import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.interop.ForeignArray2R; import com.oracle.truffle.r.runtime.interop.ForeignArray2RNodeGen; @@ -52,12 +54,12 @@ import com.oracle.truffle.r.runtime.interop.ForeignArray2RNodeGen; @ImportStatic(RRuntime.class) public abstract class CastDoubleNode extends CastDoubleBaseNode { - protected CastDoubleNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI) { - super(preserveNames, preserveDimensions, preserveAttributes, forRFFI); + protected CastDoubleNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI, boolean withReuse) { + super(preserveNames, preserveDimensions, preserveAttributes, forRFFI, withReuse); } protected CastDoubleNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { - super(preserveNames, preserveDimensions, preserveAttributes); + super(preserveNames, preserveDimensions, preserveAttributes, false, false); } @Child private CastDoubleNode recursiveCastDouble; @@ -65,7 +67,7 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode { private Object castDoubleRecursive(Object o) { if (recursiveCastDouble == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - recursiveCastDouble = insert(CastDoubleNodeGen.create(preserveNames(), preserveDimensions(), preserveAttributes())); + recursiveCastDouble = insert(CastDoubleNodeGen.create(preserveNames(), preserveDimensions(), preserveRegAttributes(), false, reuseNonShared())); } return recursiveCastDouble.executeDouble(o); } @@ -73,7 +75,7 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode { private RDoubleVector vectorCopy(RAbstractContainer operand, double[] data, boolean isComplete) { RDoubleVector ret = RDataFactory.createDoubleVector(data, isComplete, getPreservedDimensions(operand), getPreservedNames(operand)); preserveDimensionNames(operand, ret); - if (preserveAttributes()) { + if (preserveRegAttributes()) { ret.copyRegAttributesFrom(operand); } return ret; @@ -92,15 +94,35 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode { } @Specialization - protected RDoubleVector doIntVector(RAbstractIntVector operand) { + protected RAbstractDoubleVector doIntVector(RAbstractIntVector x, + @Cached("createClassProfile()") ValueProfile operandTypeProfile) { + RAbstractIntVector operand = operandTypeProfile.profile(x); + if (useClosure()) { + return (RAbstractDoubleVector) castWithReuse(RType.Double, operand, naProfile.getConditionProfile()); + } return createResultVector(operand, index -> naCheck.convertIntToDouble(operand.getDataAt(index))); } @Specialization - protected RDoubleVector doLogicalVectorDims(RAbstractLogicalVector operand) { + protected RAbstractDoubleVector doLogicalVector(RAbstractLogicalVector x, + @Cached("createClassProfile()") ValueProfile operandTypeProfile) { + RAbstractLogicalVector operand = operandTypeProfile.profile(x); + if (useClosure()) { + return (RAbstractDoubleVector) castWithReuse(RType.Double, operand, naProfile.getConditionProfile()); + } return createResultVector(operand, index -> naCheck.convertLogicalToDouble(operand.getDataAt(index))); } + @Specialization + protected RAbstractDoubleVector doRawVector(RAbstractRawVector x, + @Cached("createClassProfile()") ValueProfile operandTypeProfile) { + RAbstractRawVector operand = operandTypeProfile.profile(x); + if (useClosure()) { + return (RAbstractDoubleVector) castWithReuse(RType.Double, operand, naProfile.getConditionProfile()); + } + return createResultVector(operand, index -> RRuntime.raw2double(operand.getDataAt(index))); + } + @Specialization protected RDoubleVector doStringVector(RStringVector operand, @Cached("createBinaryProfile()") ConditionProfile emptyStringProfile, @@ -132,7 +154,7 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode { } RDoubleVector ret = RDataFactory.createDoubleVector(ddata, !seenNA, getPreservedDimensions(operand), getPreservedNames(operand)); preserveDimensionNames(operand, ret); - if (preserveAttributes()) { + if (preserveRegAttributes()) { ret.copyRegAttributesFrom(operand); } return ret; @@ -157,18 +179,7 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode { } @Specialization - protected RDoubleVector doRawVector(RRawVector operand) { - return createResultVector(operand, index -> RRuntime.raw2double(operand.getDataAt(index))); - } - - @Specialization - protected RDoubleVector doDoubleVector(RDoubleVector operand) { - return operand; - } - - @Specialization - protected RDoubleSequence doDoubleVector(RDoubleSequence operand) { - // sequence does not have attributes - nothing to copy or drop + protected RAbstractDoubleVector doDoubleVector(RAbstractDoubleVector operand) { return operand; } @@ -206,7 +217,7 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode { } } RDoubleVector ret = RDataFactory.createDoubleVector(result, !seenNA, getPreservedDimensions(list), getPreservedNames(list)); - if (preserveAttributes()) { + if (preserveRegAttributes()) { ret.copyRegAttributesFrom(list); } return ret; @@ -229,15 +240,19 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode { } public static CastDoubleNode create() { - return CastDoubleNodeGen.create(true, true, true); + return CastDoubleNodeGen.create(true, true, true, false, false); + } + + public static CastDoubleNode createWithReuse() { + return CastDoubleNodeGen.create(true, true, true, false, true); } public static CastDoubleNode createForRFFI(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { - return CastDoubleNodeGen.create(preserveNames, preserveDimensions, preserveAttributes, true); + return CastDoubleNodeGen.create(preserveNames, preserveDimensions, preserveAttributes, true, false); } public static CastDoubleNode createNonPreserving() { - return CastDoubleNodeGen.create(false, false, false); + return CastDoubleNodeGen.create(false, false, false, false, false); } protected ForeignArray2R createForeignArray2RNode() { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerBaseNode.java index dc79c02b5f39ffc9223f8325157dececc441c961..f2239927848c6102bf34bd31802ae2bd9f7656e6 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerBaseNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerBaseNode.java @@ -41,12 +41,12 @@ public abstract class CastIntegerBaseNode extends CastBaseNode { @Child private CastIntegerNode recursiveCastInteger; - protected CastIntegerBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI) { - super(preserveNames, preserveDimensions, preserveAttributes, forRFFI); + protected CastIntegerBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI, boolean useClosure) { + super(preserveNames, preserveDimensions, preserveAttributes, forRFFI, useClosure); } protected CastIntegerBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { - super(preserveNames, preserveDimensions, preserveAttributes); + super(preserveNames, preserveDimensions, preserveAttributes, false, false); } @Override @@ -57,7 +57,7 @@ public abstract class CastIntegerBaseNode extends CastBaseNode { protected Object castIntegerRecursive(Object o) { if (recursiveCastInteger == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - recursiveCastInteger = insert(CastIntegerNodeGen.create(preserveNames(), preserveDimensions(), preserveAttributes())); + recursiveCastInteger = insert(CastIntegerNodeGen.create(preserveNames(), preserveDimensions(), preserveRegAttributes(), false, reuseNonShared())); } return recursiveCastInteger.executeInt(o); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java index aff2149c234a85ef32c501a5c04ebbd60f18964f..b937b63904c6c33163604e8d7008802d65a44041 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java @@ -28,8 +28,10 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.RDataFactory; @@ -56,12 +58,12 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode { private final BranchProfile warningBranch = BranchProfile.create(); - protected CastIntegerNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI) { - super(preserveNames, preserveDimensions, preserveAttributes, forRFFI); + protected CastIntegerNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI, boolean useClosure) { + super(preserveNames, preserveDimensions, preserveAttributes, forRFFI, useClosure); } protected CastIntegerNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { - super(preserveNames, preserveDimensions, preserveAttributes); + super(preserveNames, preserveDimensions, preserveAttributes, false, false); } public abstract Object executeInt(int o); @@ -86,7 +88,7 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode { private RIntVector vectorCopy(RAbstractVector operand, int[] idata, boolean isComplete) { RIntVector ret = RDataFactory.createIntVector(idata, isComplete, getPreservedDimensions(operand), getPreservedNames(operand)); preserveDimensionNames(operand, ret); - if (preserveAttributes()) { + if (preserveRegAttributes()) { ret.copyRegAttributesFrom(operand); } return ret; @@ -160,18 +162,32 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode { } @Specialization - public RIntVector doLogicalVector(RAbstractLogicalVector operand) { + public RAbstractIntVector doLogicalVector(RAbstractLogicalVector x, + @Cached("createClassProfile()") ValueProfile operandTypeProfile) { + RAbstractLogicalVector operand = operandTypeProfile.profile(x); + if (useClosure()) { + return (RAbstractIntVector) castWithReuse(RType.Integer, operand, naProfile.getConditionProfile()); + } return createResultVector(operand, index -> naCheck.convertLogicalToInt(operand.getDataAt(index))); } @Specialization - protected RIntVector doDoubleVector(RAbstractDoubleVector operand) { - naCheck.enable(operand); + protected RAbstractIntVector doDoubleVector(RAbstractDoubleVector x, + @Cached("createClassProfile()") ValueProfile operandTypeProfile) { + RAbstractDoubleVector operand = operandTypeProfile.profile(x); + if (useClosure()) { + return (RAbstractIntVector) castWithReuse(RType.Integer, operand, naProfile.getConditionProfile()); + } return vectorCopy(operand, naCheck.convertDoubleVectorToIntData(operand), naCheck.neverSeenNA()); } @Specialization - protected RIntVector doRawVector(RAbstractRawVector operand) { + protected RAbstractIntVector doRawVector(RAbstractRawVector x, + @Cached("createClassProfile()") ValueProfile operandTypeProfile) { + RAbstractRawVector operand = operandTypeProfile.profile(x); + if (useClosure()) { + return (RAbstractIntVector) castWithReuse(RType.Integer, operand, naProfile.getConditionProfile()); + } return createResultVector(operand, index -> RRuntime.raw2int(operand.getDataAt(index))); } @@ -209,7 +225,7 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode { } } RIntVector ret = RDataFactory.createIntVector(result, !seenNA, getPreservedDimensions(list), getPreservedNames(list)); - if (preserveAttributes()) { + if (preserveRegAttributes()) { ret.copyRegAttributesFrom(list); } return ret; @@ -242,15 +258,19 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode { } public static CastIntegerNode create() { - return CastIntegerNodeGen.create(true, true, true); + return CastIntegerNodeGen.create(true, true, true, false, false); + } + + public static CastIntegerNode createWithReuse() { + return CastIntegerNodeGen.create(true, true, true, false, true); } public static CastIntegerNode createForRFFI(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { - return CastIntegerNodeGen.create(preserveNames, preserveDimensions, preserveAttributes, true); + return CastIntegerNodeGen.create(preserveNames, preserveDimensions, preserveAttributes, true, false); } public static CastIntegerNode createNonPreserving() { - return CastIntegerNodeGen.create(false, false, false); + return CastIntegerNodeGen.create(false, false, false, false, false); } protected ForeignArray2R createForeignArray2RNode() { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java index a569b25f638246f6848612d73d5f7a973779927e..72b6158aa0612f0ee0b8e4538a46d27534daaf22 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java @@ -96,7 +96,7 @@ public abstract class CastListNode extends CastBaseNode { } RList ret = RDataFactory.createList(data, getPreservedDimensions(operand), getPreservedNames(operand)); preserveDimensionNames(operand, ret); - if (preserveAttributes()) { + if (preserveRegAttributes()) { ret.copyRegAttributesFrom(operand); } return ret; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java index 9080f05e09a9f6421d18f00831fee0b042d63316..823521698e1a50cd5f95e8f73db19f7fc1962a65 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java @@ -67,7 +67,7 @@ public abstract class CastLogicalNode extends CastLogicalBaseNode { protected Object castLogicalRecursive(Object o) { if (recursiveCastLogical == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - recursiveCastLogical = insert(CastLogicalNodeGen.create(preserveNames(), preserveDimensions(), preserveAttributes())); + recursiveCastLogical = insert(CastLogicalNodeGen.create(preserveNames(), preserveDimensions(), preserveRegAttributes())); } return recursiveCastLogical.execute(o); } @@ -93,7 +93,7 @@ public abstract class CastLogicalNode extends CastLogicalBaseNode { private RLogicalVector vectorCopy(RAbstractVector operand, byte[] bdata, boolean isComplete) { RLogicalVector ret = RDataFactory.createLogicalVector(bdata, isComplete, getPreservedDimensions(operand), getPreservedNames(operand)); preserveDimensionNames(operand, ret); - if (preserveAttributes()) { + if (preserveRegAttributes()) { ret.copyRegAttributesFrom(operand); } return ret; @@ -182,7 +182,7 @@ public abstract class CastLogicalNode extends CastLogicalBaseNode { } } RLogicalVector ret = RDataFactory.createLogicalVector(result, !seenNA, getPreservedDimensions(list), getPreservedNames(list)); - if (preserveAttributes()) { + if (preserveRegAttributes()) { ret.copyRegAttributesFrom(list); } return ret; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java index c66438279a68fe416dead3725adc170253c3d9ac..44b0149e20f5b7a5f4ccdaa3dc216fadb01a3d16 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java @@ -69,7 +69,7 @@ public abstract class CastRawNode extends CastBaseNode { protected Object castRawRecursive(Object o) { if (recursiveCastRaw == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - recursiveCastRaw = insert(CastRawNodeGen.create(preserveNames(), preserveDimensions(), preserveAttributes())); + recursiveCastRaw = insert(CastRawNodeGen.create(preserveNames(), preserveDimensions(), preserveRegAttributes())); } return recursiveCastRaw.executeRaw(o); } @@ -157,7 +157,7 @@ public abstract class CastRawNode extends CastBaseNode { private RRawVector vectorCopy(RAbstractVector operand, byte[] bdata) { RRawVector ret = RDataFactory.createRawVector(bdata, getPreservedDimensions(operand), getPreservedNames(operand)); preserveDimensionNames(operand, ret); - if (preserveAttributes()) { + if (preserveRegAttributes()) { ret.copyRegAttributesFrom(operand); } return ret; @@ -306,7 +306,7 @@ public abstract class CastRawNode extends CastBaseNode { data[i] = ((RRaw) castRawRecursive(value.getDataAt(i))).getValue(); } RRawVector result = RDataFactory.createRawVector(data, getPreservedDimensions(value), getPreservedNames(value)); - if (preserveAttributes()) { + if (preserveRegAttributes()) { result.copyRegAttributesFrom(value); } return result; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringNode.java index 1f413ee259640ac3c92cebc25bf33a3190a21733..ebec5af6e485d4e7016ec3162bad1b624eaaeb59 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringNode.java @@ -64,7 +64,7 @@ public abstract class CastStringNode extends CastStringBaseNode { private RStringVector vectorCopy(RAbstractContainer operand, String[] data) { RStringVector ret = RDataFactory.createStringVector(data, operand.isComplete(), getPreservedDimensions(operand), getPreservedNames(operand)); preserveDimensionNames(operand, ret); - if (preserveAttributes()) { + if (preserveRegAttributes()) { ret.copyRegAttributesFrom(operand); } return ret; @@ -133,7 +133,7 @@ public abstract class CastStringNode extends CastStringBaseNode { private Object castStringRecursive(Object o) { if (recursiveCastString == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - recursiveCastString = insert(CastStringNodeGen.create(preserveNames(), preserveDimensions(), preserveAttributes())); + recursiveCastString = insert(CastStringNodeGen.create(preserveNames(), preserveDimensions(), preserveRegAttributes())); } return recursiveCastString.executeString(o); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalCode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalCode.java index 2a29784e9d0ce13e72fedcfe15f6ef086edab9b0..90d023e31c62ba4bf10880c1224d146134ad2096 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalCode.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalCode.java @@ -72,6 +72,7 @@ public final class RInternalCode { } } + @TruffleBoundary public synchronized RFunction lookupFunction(String name) { REnvironment env = this.evaluatedEnvironment; if (env == null) { @@ -83,6 +84,7 @@ public final class RInternalCode { return fun; } + @TruffleBoundary public static RInternalCode lookup(RContext context, String basePackage, Source source) { ContextStateImpl state = context.stateInternalCode; RInternalCode code = state.get(source); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplex.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplex.java index e928ee140a045b2c9bc89268f8e28fe1964c11b2..af6a3028bc427305beaf140ce954cc6adc365b8d 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplex.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplex.java @@ -52,7 +52,7 @@ public final class RComplex extends RScalarVector implements RAbstractComplexVec } @Override - public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) { + public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) { switch (type) { case Complex: return this; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java index 5e7b39ec4557d4a3b697acabcdb3d287f08a7a4e..f8c0488a44e0c579aa393c39f7e671c8471297b4 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java @@ -64,14 +64,14 @@ public final class RComplexVector extends RVector<double[]> implements RAbstract } @Override - public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) { + public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) { switch (type) { case Complex: return this; case Character: - return RClosures.createToStringVector(this); + return RClosures.createToStringVector(this, keepAttributes); case List: - return RClosures.createToListVector(this); + return RClosures.createToListVector(this, keepAttributes); default: return null; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDouble.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDouble.java index 1a034e6bf2826b734c754652aeed229adb94dc5d..6a66889e9cdeacff4129c7ab932ead664ee736bb 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDouble.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDouble.java @@ -53,7 +53,7 @@ public final class RDouble extends RScalarVector implements RAbstractDoubleVecto } @Override - public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) { + public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) { switch (type) { case Integer: return this; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java index 2cf039de0743c86ed84b3f189fd24d5a9522dc78..a94cce37d00277922034d1d28749b204d1ebf17c 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java @@ -70,19 +70,19 @@ public final class RDoubleSequence extends RSequence implements RAbstractDoubleV } @Override - public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) { + public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) { // TODO might be possible to implement some of these without closures switch (type) { case Integer: - return RClosures.createToIntVector(this); + return RClosures.createToIntVector(this, keepAttributes); case Double: return this; case Complex: - return RClosures.createToComplexVector(this); + return RClosures.createToComplexVector(this, keepAttributes); case Character: - return RClosures.createToStringVector(this); + return RClosures.createToStringVector(this, keepAttributes); case List: - return RClosures.createToListVector(this); + return RClosures.createToListVector(this, keepAttributes); default: return null; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java index e4eace8649f0ecd70396b1798ab2db31860fe6db..52366b1ae86c5a4e41c6927140452ebbe52043c8 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java @@ -48,18 +48,18 @@ public final class RDoubleVector extends RVector<double[]> implements RAbstractD } @Override - public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) { + public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) { switch (type) { case Integer: - return RClosures.createToIntVector(this); + return RClosures.createToIntVector(this, keepAttributes); case Double: return this; case Complex: - return RClosures.createToComplexVector(this); + return RClosures.createToComplexVector(this, keepAttributes); case Character: - return RClosures.createToStringVector(this); + return RClosures.createToStringVector(this, keepAttributes); case List: - return RClosures.createToListVector(this); + return RClosures.createToListVector(this, keepAttributes); default: return null; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java index a5aea4b6f6ca4347adebbbf7248a22d8d0c3dc83..402dc97ac493f9fb5c52e46240f1c83a041e45ae 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java @@ -48,18 +48,18 @@ public final class RIntSequence extends RSequence implements RAbstractIntVector } @Override - public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) { + public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) { switch (type) { case Integer: return this; case Double: return RDataFactory.createDoubleSequence(getStart(), getStride(), getLength()); case Complex: - return RClosures.createToComplexVector(this); + return RClosures.createToComplexVector(this, keepAttributes); case Character: - return RClosures.createToStringVector(this); + return RClosures.createToStringVector(this, keepAttributes); case List: - return RClosures.createToListVector(this); + return RClosures.createToListVector(this, keepAttributes); default: return null; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java index 8fa15af2a36250faf14c7d2bd464ece0d2be187c..d95bb428e4a28c9fed63b1a57ae8527276bf708f 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java @@ -48,18 +48,18 @@ public final class RIntVector extends RVector<int[]> implements RAbstractIntVect } @Override - public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) { + public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) { switch (type) { case Integer: return this; case Double: - return RClosures.createToDoubleVector(this); + return RClosures.createToDoubleVector(this, keepAttributes); case Complex: - return RClosures.createToComplexVector(this); + return RClosures.createToComplexVector(this, keepAttributes); case Character: - return RClosures.createToStringVector(this); + return RClosures.createToStringVector(this, keepAttributes); case List: - return RClosures.createToListVector(this); + return RClosures.createToListVector(this, keepAttributes); default: return null; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteger.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteger.java index 3a618e1ff53c4c1f638f1543806c1e276cc4829d..eb0ea1f399ffd83e2dd88f286e7ec133c0467735 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteger.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteger.java @@ -62,7 +62,7 @@ public final class RInteger extends RScalarVector implements RAbstractIntVector } @Override - public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) { + public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) { switch (type) { case Integer: return this; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogical.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogical.java index b0a64de5abacb4d56adc4cb4dd8111e27687eb0e..7fade92f1bed1c2e7ebb42f3232d09a46e5c6184 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogical.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogical.java @@ -55,7 +55,7 @@ public final class RLogical extends RScalarVector implements RAbstractLogicalVec } @Override - public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) { + public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) { switch (type) { case Logical: return this; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java index 3a1a9ebb4f4cbaaa1541878964a135926363ebcf..3bde20df8e776d6571b91dd07dee09db4b6c2988 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java @@ -48,20 +48,20 @@ public final class RLogicalVector extends RVector<byte[]> implements RAbstractLo } @Override - public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) { + public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) { switch (type) { case Logical: return this; case Integer: - return RClosures.createToIntVector(this); + return RClosures.createToIntVector(this, keepAttributes); case Double: - return RClosures.createToDoubleVector(this); + return RClosures.createToDoubleVector(this, keepAttributes); case Complex: - return RClosures.createToComplexVector(this); + return RClosures.createToComplexVector(this, keepAttributes); case Character: - return RClosures.createToStringVector(this); + return RClosures.createToStringVector(this, keepAttributes); case List: - return RClosures.createToListVector(this); + return RClosures.createToListVector(this, keepAttributes); default: return null; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRaw.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRaw.java index 0c55726d53efdf18f95c15a6b20d7f417302a930..b88afcc338f6d90911ef2b781574012345ee81fb 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRaw.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRaw.java @@ -45,7 +45,7 @@ public final class RRaw extends RScalarVector implements RAbstractRawVector { } @Override - public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) { + public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) { switch (type) { case Raw: return this; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java index 85c9947b3c887b134cd18a779929d3fa630e9e36..26252b7da5746b0efdfd06af7ed539a09ff6c070 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java @@ -48,18 +48,18 @@ public final class RRawVector extends RVector<byte[]> implements RAbstractRawVec } @Override - public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) { + public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) { switch (type) { case Raw: return this; case Integer: - return RClosures.createToIntVector(this); + return RClosures.createToIntVector(this, keepAttributes); case Double: - return RClosures.createToDoubleVector(this); + return RClosures.createToDoubleVector(this, keepAttributes); case Complex: - return RClosures.createToComplexVector(this); + return RClosures.createToComplexVector(this, keepAttributes); case Character: - return RClosures.createToStringVector(this); + return RClosures.createToStringVector(this, keepAttributes); default: return null; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarList.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarList.java index 48e050c17b68e3dafd469bbb20dea8e73cc5e2be..1ea23adc66f510252e67c8aa0696a03e7e9d2993 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarList.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarList.java @@ -57,7 +57,7 @@ public final class RScalarList extends RScalarVector implements RAbstractListVec } @Override - public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) { + public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) { switch (type) { case List: return this; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RString.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RString.java index 98b4b5653f6f931907b8fb5b23b83b26ad582e82..abf51a343f797352297a0a94155670ef897b5d5b 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RString.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RString.java @@ -48,7 +48,7 @@ public final class RString extends RScalarVector implements RAbstractStringVecto } @Override - public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) { + public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) { switch (type) { case Character: return this; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java index 712b3deb8dc0cb22f6c21155f4b7fd08e5253fe6..38fdbb99181b237ae911db36a6074201c5ed22c3 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java @@ -49,12 +49,12 @@ public final class RStringVector extends RVector<String[]> implements RAbstractS } @Override - public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) { + public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) { switch (type) { case Character: return this; case List: - return RClosures.createToListVector(this); + return RClosures.createToListVector(this, keepAttributes); default: return null; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RClosures.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RClosures.java index 91dddf4b5fe7e541eeaaafa46cffb8c54bd08338..1cc4294efa9d58eb83760855b4e1a146a83c62dd 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RClosures.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RClosures.java @@ -43,133 +43,197 @@ public class RClosures { // Logical to ... - public static RAbstractIntVector createToIntVector(RLogicalVector vector) { - return new RLogicalToIntVectorClosure(vector); + public static RAbstractIntVector createToIntVector(RLogicalVector vector, boolean keepAttributes) { + return new RLogicalToIntVectorClosure(vector, keepAttributes); } - public static RAbstractDoubleVector createToDoubleVector(RLogicalVector vector) { - return new RLogicalToDoubleVectorClosure(vector); + public static RAbstractDoubleVector createToDoubleVector(RLogicalVector vector, boolean keepAttributes) { + return new RLogicalToDoubleVectorClosure(vector, keepAttributes); } - public static RAbstractComplexVector createToComplexVector(RLogicalVector vector) { - return new RLogicalToComplexVectorClosure(vector); + public static RAbstractComplexVector createToComplexVector(RLogicalVector vector, boolean keepAttributes) { + return new RLogicalToComplexVectorClosure(vector, keepAttributes); } - public static RAbstractStringVector createToStringVector(RLogicalVector vector) { - return new RLogicalToStringVectorClosure(vector); + public static RAbstractStringVector createToStringVector(RLogicalVector vector, boolean keepAttributes) { + return new RLogicalToStringVectorClosure(vector, keepAttributes); } - public static RAbstractListVector createToListVector(RLogicalVector vector) { - return new RLogicalToListVectorClosure(vector); + public static RAbstractListVector createToListVector(RLogicalVector vector, boolean keepAttributes) { + return new RLogicalToListVectorClosure(vector, keepAttributes); } // Int to ... - public static RAbstractComplexVector createToComplexVector(RIntSequence vector) { - return new RIntSequenceToComplexVectorClosure(vector); + public static RAbstractComplexVector createToComplexVector(RIntSequence vector, boolean keepAttributes) { + return new RIntSequenceToComplexVectorClosure(vector, keepAttributes); } - public static RAbstractStringVector createToStringVector(RIntSequence vector) { - return new RIntSequenceToStringVectorClosure(vector); + public static RAbstractStringVector createToStringVector(RIntSequence vector, boolean keepAttributes) { + return new RIntSequenceToStringVectorClosure(vector, keepAttributes); } - public static RAbstractListVector createToListVector(RIntSequence vector) { - return new RIntSequenceToListVectorClosure(vector); + public static RAbstractListVector createToListVector(RIntSequence vector, boolean keepAttributes) { + return new RIntSequenceToListVectorClosure(vector, keepAttributes); } - public static RAbstractDoubleVector createToDoubleVector(RIntVector vector) { - return new RIntToDoubleVectorClosure(vector); + public static RAbstractDoubleVector createToDoubleVector(RIntVector vector, boolean keepAttributes) { + return new RIntToDoubleVectorClosure(vector, keepAttributes); } - public static RAbstractComplexVector createToComplexVector(RIntVector vector) { - return new RIntToComplexVectorClosure(vector); + public static RAbstractComplexVector createToComplexVector(RIntVector vector, boolean keepAttributes) { + return new RIntToComplexVectorClosure(vector, keepAttributes); } - public static RAbstractStringVector createToStringVector(RIntVector vector) { - return new RIntToStringVectorClosure(vector); + public static RAbstractStringVector createToStringVector(RIntVector vector, boolean keepAttributes) { + return new RIntToStringVectorClosure(vector, keepAttributes); } - public static RAbstractListVector createToListVector(RIntVector vector) { - return new RIntToListVectorClosure(vector); + public static RAbstractListVector createToListVector(RIntVector vector, boolean keepAttributes) { + return new RIntToListVectorClosure(vector, keepAttributes); } // Double to ... public static RAbstractComplexVector createToComplexVector(RDoubleSequence vector) { - return new RDoubleSequenceToComplexVectorClosure(vector); + return new RDoubleSequenceToComplexVectorClosure(vector, false); + } + + public static RAbstractComplexVector createToComplexVector(RDoubleSequence vector, boolean keepAttributes) { + return new RDoubleSequenceToComplexVectorClosure(vector, keepAttributes); } public static RAbstractStringVector createToStringVector(RDoubleSequence vector) { - return new RDoubleSequenceToStringVectorClosure(vector); + return new RDoubleSequenceToStringVectorClosure(vector, false); + } + + public static RAbstractStringVector createToStringVector(RDoubleSequence vector, boolean keepAttributes) { + return new RDoubleSequenceToStringVectorClosure(vector, keepAttributes); } public static RAbstractIntVector createToIntVector(RDoubleSequence vector) { - return new RDoubleSequenceToIntVectorClosure(vector); + return new RDoubleSequenceToIntVectorClosure(vector, false); + } + + public static RAbstractIntVector createToIntVector(RDoubleSequence vector, boolean keepAttributes) { + return new RDoubleSequenceToIntVectorClosure(vector, keepAttributes); } public static RAbstractListVector createToListVector(RDoubleSequence vector) { - return new RDoubleSequenceToListVectorClosure(vector); + return new RDoubleSequenceToListVectorClosure(vector, false); + } + + public static RAbstractListVector createToListVector(RDoubleSequence vector, boolean keepAttributes) { + return new RDoubleSequenceToListVectorClosure(vector, keepAttributes); } public static RAbstractComplexVector createToComplexVector(RDoubleVector vector) { - return new RDoubleToComplexVectorClosure(vector); + return new RDoubleToComplexVectorClosure(vector, false); + } + + public static RAbstractComplexVector createToComplexVector(RDoubleVector vector, boolean keepAttributes) { + return new RDoubleToComplexVectorClosure(vector, keepAttributes); } public static RAbstractStringVector createToStringVector(RDoubleVector vector) { - return new RDoubleToStringVectorClosure(vector); + return new RDoubleToStringVectorClosure(vector, false); + } + + public static RAbstractStringVector createToStringVector(RDoubleVector vector, boolean keepAttributes) { + return new RDoubleToStringVectorClosure(vector, keepAttributes); } public static RAbstractIntVector createToIntVector(RDoubleVector vector) { - return new RDoubleToIntVectorClosure(vector); + return new RDoubleToIntVectorClosure(vector, false); + } + + public static RAbstractIntVector createToIntVector(RDoubleVector vector, boolean keepAttributes) { + return new RDoubleToIntVectorClosure(vector, keepAttributes); } public static RAbstractListVector createToListVector(RDoubleVector vector) { - return new RDoubleToListVectorClosure(vector); + return new RDoubleToListVectorClosure(vector, false); + } + + public static RAbstractListVector createToListVector(RDoubleVector vector, boolean keepAttributes) { + return new RDoubleToListVectorClosure(vector, keepAttributes); } // Raw to ... public static RAbstractIntVector createToIntVector(RRawVector vector) { - return new RRawToIntVectorClosure(vector); + return new RRawToIntVectorClosure(vector, false); + } + + public static RAbstractIntVector createToIntVector(RRawVector vector, boolean keepAttributes) { + return new RRawToIntVectorClosure(vector, keepAttributes); } public static RAbstractDoubleVector createToDoubleVector(RRawVector vector) { - return new RRawToDoubleVectorClosure(vector); + return new RRawToDoubleVectorClosure(vector, false); + } + + public static RAbstractDoubleVector createToDoubleVector(RRawVector vector, boolean keepAttributes) { + return new RRawToDoubleVectorClosure(vector, keepAttributes); } public static RAbstractComplexVector createToComplexVector(RRawVector vector) { - return new RRawToComplexVectorClosure(vector); + return new RRawToComplexVectorClosure(vector, false); + } + + public static RAbstractComplexVector createToComplexVector(RRawVector vector, boolean keepAttributes) { + return new RRawToComplexVectorClosure(vector, keepAttributes); } public static RAbstractStringVector createToStringVector(RRawVector vector) { - return new RRawToStringVectorClosure(vector); + return new RRawToStringVectorClosure(vector, false); + } + + public static RAbstractStringVector createToStringVector(RRawVector vector, boolean keepAttributes) { + return new RRawToStringVectorClosure(vector, keepAttributes); } public static RAbstractListVector createToListVector(RRawVector vector) { - return new RRawToListVectorClosure(vector); + return new RRawToListVectorClosure(vector, false); + } + + public static RAbstractListVector createToListVector(RRawVector vector, boolean keepAttributes) { + return new RRawToListVectorClosure(vector, keepAttributes); } // Complex to ... public static RAbstractStringVector createToStringVector(RComplexVector vector) { - return new RComplexToStringVectorClosure(vector); + return new RComplexToStringVectorClosure(vector, false); + } + + public static RAbstractStringVector createToStringVector(RComplexVector vector, boolean keepAttributes) { + return new RComplexToStringVectorClosure(vector, keepAttributes); } public static RAbstractListVector createToListVector(RComplexVector vector) { - return new RComplexToListVectorClosure(vector); + return new RComplexToListVectorClosure(vector, false); + } + + public static RAbstractListVector createToListVector(RComplexVector vector, boolean keepAttributes) { + return new RComplexToListVectorClosure(vector, keepAttributes); } // Character to ... - public static RAbstractListVector createToListVector(RStringVector vector) { - return new RStringToListVectorClosure(vector); + public static RAbstractListVector createToListVector(RStringVector vector, boolean keepAttributes) { + return new RStringToListVectorClosure(vector, keepAttributes); } // Factor to vector public static RAbstractVector createFactorToVector(RAbstractIntVector factor, boolean withNames, RAbstractVector levels) { + return createFactorToVector(factor, withNames, levels, false); + } + + public static RAbstractVector createFactorToVector(RAbstractIntVector factor, boolean withNames, RAbstractVector levels, boolean keepAttributes) { if (levels instanceof RAbstractStringVector) { - return new RFactorToStringVectorClosure(factor, (RAbstractStringVector) levels, withNames); + return new RFactorToStringVectorClosure(factor, (RAbstractStringVector) levels, withNames, keepAttributes); } else { throw RError.error(RError.SHOW_CALLER, Message.MALFORMED_FACTOR); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToComplexVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToComplexVectorClosure.java index 5cad98744466bd4b3cbba1d60dd3105eca592304..3932e3c982f38996b40e23e04baf91063b7f6c74 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToComplexVectorClosure.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToComplexVectorClosure.java @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.runtime.data.closures; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.RComplexVector; @@ -37,6 +38,10 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; abstract class RToComplexVectorClosure extends RToVectorClosure implements RAbstractComplexVector { + protected RToComplexVectorClosure(boolean keepAttributes) { + super(keepAttributes); + } + @Override public final RVector<?> createEmptySameType(int newLength, boolean newIsComplete) { return RDataFactory.createComplexVector(new double[newLength << 1], newIsComplete); @@ -52,12 +57,24 @@ abstract class RToComplexVectorClosure extends RToVectorClosure implements RAbst result[index] = data.getRealPart(); result[index + 1] = data.getImaginaryPart(); } - return RDataFactory.createComplexVector(result, getVector().isComplete()); + RComplexVector materialized = RDataFactory.createComplexVector(result, getVector().isComplete()); + copyAttributes(materialized); + return materialized; + } + + @TruffleBoundary + private void copyAttributes(RComplexVector materialized) { + if (keepAttributes) { + materialized.initAttributes(getVector().getAttributes()); + } } @Override - public final RComplexVector copyWithNewDimensions(int[] newDimensions) { - return materialize().copyWithNewDimensions(newDimensions); + public final RAbstractComplexVector copyWithNewDimensions(int[] newDimensions) { + if (keepAttributes) { + return materialize().copyWithNewDimensions(newDimensions); + } + return this; } } @@ -65,7 +82,8 @@ final class RLogicalToComplexVectorClosure extends RToComplexVectorClosure imple private final RLogicalVector vector; - RLogicalToComplexVectorClosure(RLogicalVector vector) { + RLogicalToComplexVectorClosure(RLogicalVector vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } @@ -85,7 +103,8 @@ final class RIntToComplexVectorClosure extends RToComplexVectorClosure implement private final RIntVector vector; - RIntToComplexVectorClosure(RIntVector vector) { + RIntToComplexVectorClosure(RIntVector vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } @@ -105,7 +124,8 @@ final class RIntSequenceToComplexVectorClosure extends RToComplexVectorClosure i private final RIntSequence vector; - RIntSequenceToComplexVectorClosure(RIntSequence vector) { + RIntSequenceToComplexVectorClosure(RIntSequence vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } @@ -125,7 +145,8 @@ final class RDoubleToComplexVectorClosure extends RToComplexVectorClosure implem private final RDoubleVector vector; - RDoubleToComplexVectorClosure(RDoubleVector vector) { + RDoubleToComplexVectorClosure(RDoubleVector vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } @@ -145,7 +166,8 @@ final class RDoubleSequenceToComplexVectorClosure extends RToComplexVectorClosur private final RDoubleSequence vector; - RDoubleSequenceToComplexVectorClosure(RDoubleSequence vector) { + RDoubleSequenceToComplexVectorClosure(RDoubleSequence vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } @@ -165,7 +187,8 @@ final class RRawToComplexVectorClosure extends RToComplexVectorClosure implement private final RRawVector vector; - RRawToComplexVectorClosure(RRawVector vector) { + RRawToComplexVectorClosure(RRawVector vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToDoubleVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToDoubleVectorClosure.java index 435498a961450703b5a71b82ba97343a63c8e0a5..79a57bf9fb9f29b3870406259ebeba2f9302e7ef 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToDoubleVectorClosure.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToDoubleVectorClosure.java @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.runtime.data.closures; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RDoubleVector; @@ -34,6 +35,10 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; abstract class RToDoubleVectorClosure extends RToVectorClosure implements RAbstractDoubleVector { + protected RToDoubleVectorClosure(boolean keepAttributes) { + super(keepAttributes); + } + @Override public final RVector<?> createEmptySameType(int newLength, boolean newIsComplete) { return RDataFactory.createDoubleVector(new double[newLength], newIsComplete); @@ -47,12 +52,24 @@ abstract class RToDoubleVectorClosure extends RToVectorClosure implements RAbstr double data = getDataAt(i); result[i] = data; } - return RDataFactory.createDoubleVector(result, getVector().isComplete()); + RDoubleVector materialized = RDataFactory.createDoubleVector(result, getVector().isComplete()); + copyAttributes(materialized); + return materialized; + } + + @TruffleBoundary + private void copyAttributes(RDoubleVector materialized) { + if (keepAttributes) { + materialized.initAttributes(getVector().getAttributes()); + } } @Override - public final RDoubleVector copyWithNewDimensions(int[] newDimensions) { - return materialize().copyWithNewDimensions(newDimensions); + public final RAbstractDoubleVector copyWithNewDimensions(int[] newDimensions) { + if (keepAttributes) { + return materialize().copyWithNewDimensions(newDimensions); + } + return this; } } @@ -60,7 +77,8 @@ final class RLogicalToDoubleVectorClosure extends RToDoubleVectorClosure impleme private final RLogicalVector vector; - RLogicalToDoubleVectorClosure(RLogicalVector vector) { + RLogicalToDoubleVectorClosure(RLogicalVector vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } @@ -83,7 +101,8 @@ final class RIntToDoubleVectorClosure extends RToDoubleVectorClosure implements private final RIntVector vector; - RIntToDoubleVectorClosure(RIntVector vector) { + RIntToDoubleVectorClosure(RIntVector vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } @@ -106,7 +125,8 @@ final class RIntSequenceToDoubleVectorClosure extends RToDoubleVectorClosure imp private final RIntSequence vector; - RIntSequenceToDoubleVectorClosure(RIntSequence vector) { + RIntSequenceToDoubleVectorClosure(RIntSequence vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } @@ -129,7 +149,8 @@ final class RRawToDoubleVectorClosure extends RToDoubleVectorClosure implements private final RRawVector vector; - RRawToDoubleVectorClosure(RRawVector vector) { + RRawToDoubleVectorClosure(RRawVector vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToIntVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToIntVectorClosure.java index 187b1260e7fcfd8951a4f6ec9346a295471144a3..6c925729975a0d1b883decff1924b03548041c2a 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToIntVectorClosure.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToIntVectorClosure.java @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.runtime.data.closures; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RComplex; @@ -37,6 +38,10 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; abstract class RToIntVectorClosure extends RToVectorClosure implements RAbstractIntVector { + protected RToIntVectorClosure(boolean keepAttributes) { + super(keepAttributes); + } + @Override public final RVector<?> createEmptySameType(int newLength, boolean newIsComplete) { return RDataFactory.createIntVector(new int[newLength], newIsComplete); @@ -50,12 +55,24 @@ abstract class RToIntVectorClosure extends RToVectorClosure implements RAbstract int data = getDataAt(i); result[i] = data; } - return RDataFactory.createIntVector(result, getVector().isComplete()); + RIntVector materialized = RDataFactory.createIntVector(result, getVector().isComplete()); + copyAttributes(materialized); + return materialized; + } + + @TruffleBoundary + private void copyAttributes(RIntVector materialized) { + if (keepAttributes) { + materialized.copyAttributesFrom(getVector()); + } } @Override - public final RIntVector copyWithNewDimensions(int[] newDimensions) { - return materialize().copyWithNewDimensions(newDimensions); + public final RAbstractIntVector copyWithNewDimensions(int[] newDimensions) { + if (keepAttributes) { + return materialize().copyWithNewDimensions(newDimensions); + } + return this; } } @@ -63,7 +80,8 @@ final class RLogicalToIntVectorClosure extends RToIntVectorClosure implements RA private final RLogicalVector vector; - RLogicalToIntVectorClosure(RLogicalVector vector) { + RLogicalToIntVectorClosure(RLogicalVector vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } @@ -85,8 +103,10 @@ final class RLogicalToIntVectorClosure extends RToIntVectorClosure implements RA final class RDoubleToIntVectorClosure extends RToIntVectorClosure implements RAbstractIntVector { private final RDoubleVector vector; + private boolean naReported; - RDoubleToIntVectorClosure(RDoubleVector vector) { + RDoubleToIntVectorClosure(RDoubleVector vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } @@ -103,7 +123,10 @@ final class RDoubleToIntVectorClosure extends RToIntVectorClosure implements RAb } int result = (int) value; if (result == Integer.MIN_VALUE || value > Integer.MAX_VALUE) { - RError.warning(RError.SHOW_CALLER2, RError.Message.NA_INTRODUCED_COERCION); + if (!naReported) { + RError.warning(RError.SHOW_CALLER2, RError.Message.NA_INTRODUCED_COERCION); + naReported = true; + } return RRuntime.INT_NA; } return result; @@ -113,8 +136,10 @@ final class RDoubleToIntVectorClosure extends RToIntVectorClosure implements RAb final class RDoubleSequenceToIntVectorClosure extends RToIntVectorClosure implements RAbstractIntVector { private final RDoubleSequence vector; + private boolean naReported; - RDoubleSequenceToIntVectorClosure(RDoubleSequence vector) { + RDoubleSequenceToIntVectorClosure(RDoubleSequence vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } @@ -131,7 +156,10 @@ final class RDoubleSequenceToIntVectorClosure extends RToIntVectorClosure implem } int result = (int) value; if (result == Integer.MIN_VALUE || value > Integer.MAX_VALUE) { - RError.warning(RError.SHOW_CALLER2, RError.Message.NA_INTRODUCED_COERCION); + if (!naReported) { + RError.warning(RError.SHOW_CALLER2, RError.Message.NA_INTRODUCED_COERCION); + naReported = true; + } return RRuntime.INT_NA; } return result; @@ -145,7 +173,8 @@ final class RComplexToIntVectorClosure extends RToIntVectorClosure implements RA private final RComplexVector vector; - RComplexToIntVectorClosure(RComplexVector vector) { + RComplexToIntVectorClosure(RComplexVector vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } @@ -169,7 +198,8 @@ final class RRawToIntVectorClosure extends RToIntVectorClosure implements RAbstr private final RRawVector vector; - RRawToIntVectorClosure(RRawVector vector) { + RRawToIntVectorClosure(RRawVector vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToListVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToListVectorClosure.java index 8a03a34c89bb72bc9b4f3e8ecf5b98c502ab0ace..f6ef8f334c63b9c3fde8cf8f676d23d21fb9352f 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToListVectorClosure.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToListVectorClosure.java @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.runtime.data.closures; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.RComplexVector; import com.oracle.truffle.r.runtime.data.RDataFactory; @@ -40,6 +41,10 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector; abstract class RToListVectorClosure extends RToVectorClosure implements RAbstractListVector { + protected RToListVectorClosure(boolean keepAttributes) { + super(keepAttributes); + } + @Override public Object getDataAtAsObject(int index) { return getDataAt(index); @@ -53,12 +58,24 @@ abstract class RToListVectorClosure extends RToVectorClosure implements RAbstrac Object data = getDataAt(i); result[i] = data; } - return RDataFactory.createList(result); + RList materialized = RDataFactory.createList(result); + copyAttributes(materialized); + return materialized; + } + + @TruffleBoundary + private void copyAttributes(RList materialized) { + if (keepAttributes) { + materialized.copyAttributesFrom(getVector()); + } } @Override public RAbstractVector copyWithNewDimensions(int[] newDimensions) { - return materialize().copyWithNewDimensions(newDimensions); + if (!keepAttributes) { + return materialize().copyWithNewDimensions(newDimensions); + } + return this; } @Override @@ -71,7 +88,8 @@ final class RLogicalToListVectorClosure extends RToListVectorClosure { private final RLogicalVector vector; - RLogicalToListVectorClosure(RLogicalVector vector) { + RLogicalToListVectorClosure(RLogicalVector vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } @@ -90,7 +108,8 @@ final class RIntToListVectorClosure extends RToListVectorClosure { private final RIntVector vector; - RIntToListVectorClosure(RIntVector vector) { + RIntToListVectorClosure(RIntVector vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } @@ -109,7 +128,8 @@ final class RIntSequenceToListVectorClosure extends RToListVectorClosure { private final RIntSequence vector; - RIntSequenceToListVectorClosure(RIntSequence vector) { + RIntSequenceToListVectorClosure(RIntSequence vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } @@ -128,7 +148,8 @@ final class RDoubleToListVectorClosure extends RToListVectorClosure { private final RDoubleVector vector; - RDoubleToListVectorClosure(RDoubleVector vector) { + RDoubleToListVectorClosure(RDoubleVector vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } @@ -147,7 +168,8 @@ final class RDoubleSequenceToListVectorClosure extends RToListVectorClosure { private final RDoubleSequence vector; - RDoubleSequenceToListVectorClosure(RDoubleSequence vector) { + RDoubleSequenceToListVectorClosure(RDoubleSequence vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } @@ -166,7 +188,8 @@ final class RComplexToListVectorClosure extends RToListVectorClosure { private final RComplexVector vector; - RComplexToListVectorClosure(RComplexVector vector) { + RComplexToListVectorClosure(RComplexVector vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } @@ -185,7 +208,8 @@ final class RStringToListVectorClosure extends RToListVectorClosure { private final RStringVector vector; - RStringToListVectorClosure(RStringVector vector) { + RStringToListVectorClosure(RStringVector vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } @@ -204,7 +228,8 @@ final class RRawToListVectorClosure extends RToListVectorClosure { private final RRawVector vector; - RRawToListVectorClosure(RRawVector vector) { + RRawToListVectorClosure(RRawVector vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToStringVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToStringVectorClosure.java index e9a127adbd78625542c2c120db0d0964957c899e..904f0fa5bf53ca92e785bc1fc93564f2bf519a25 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToStringVectorClosure.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToStringVectorClosure.java @@ -44,6 +44,10 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector; abstract class RToStringVectorClosure extends RToVectorClosure implements RAbstractStringVector { + protected RToStringVectorClosure(boolean keepAttributes) { + super(keepAttributes); + } + @Override public final RVector<?> createEmptySameType(int newLength, boolean newIsComplete) { return RDataFactory.createStringVector(new String[newLength], newIsComplete); @@ -57,22 +61,24 @@ abstract class RToStringVectorClosure extends RToVectorClosure implements RAbstr String data = getDataAt(i); result[i] = data; } - return RDataFactory.createStringVector(result, getVector().isComplete(), getDimensionsMaterialized(), getNamesMaterialized()); + RStringVector materialized = RDataFactory.createStringVector(result, getVector().isComplete()); + copyAttributes(materialized); + return materialized; } @TruffleBoundary - private int[] getDimensionsMaterialized() { - return getDimensions(); - } - - @TruffleBoundary - private RStringVector getNamesMaterialized() { - return getNames(); + private void copyAttributes(RStringVector materialized) { + if (keepAttributes) { + materialized.copyAttributesFrom(getVector()); + } } @Override - public final RStringVector copyWithNewDimensions(int[] newDimensions) { - return materialize().copyWithNewDimensions(newDimensions); + public final RAbstractStringVector copyWithNewDimensions(int[] newDimensions) { + if (!keepAttributes) { + return materialize().copyWithNewDimensions(newDimensions); + } + return this; } } @@ -80,7 +86,8 @@ final class RLogicalToStringVectorClosure extends RToStringVectorClosure { private final RLogicalVector vector; - RLogicalToStringVectorClosure(RLogicalVector vector) { + RLogicalToStringVectorClosure(RLogicalVector vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } @@ -104,7 +111,8 @@ final class RIntToStringVectorClosure extends RToStringVectorClosure { private final RIntVector vector; - RIntToStringVectorClosure(RIntVector vector) { + RIntToStringVectorClosure(RIntVector vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } @@ -127,7 +135,8 @@ final class RIntSequenceToStringVectorClosure extends RToStringVectorClosure { private final RIntSequence vector; - RIntSequenceToStringVectorClosure(RIntSequence vector) { + RIntSequenceToStringVectorClosure(RIntSequence vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } @@ -150,7 +159,8 @@ final class RDoubleToStringVectorClosure extends RToStringVectorClosure { private final RDoubleVector vector; - RDoubleToStringVectorClosure(RDoubleVector vector) { + RDoubleToStringVectorClosure(RDoubleVector vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } @@ -174,7 +184,8 @@ final class RDoubleSequenceToStringVectorClosure extends RToStringVectorClosure private final RDoubleSequence vector; - RDoubleSequenceToStringVectorClosure(RDoubleSequence vector) { + RDoubleSequenceToStringVectorClosure(RDoubleSequence vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } @@ -198,7 +209,8 @@ final class RComplexToStringVectorClosure extends RToStringVectorClosure { private final RComplexVector vector; - RComplexToStringVectorClosure(RComplexVector vector) { + RComplexToStringVectorClosure(RComplexVector vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } @@ -221,7 +233,8 @@ final class RRawToStringVectorClosure extends RToStringVectorClosure { private final RRawVector vector; - RRawToStringVectorClosure(RRawVector vector) { + RRawToStringVectorClosure(RRawVector vector, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; } @@ -245,7 +258,8 @@ final class RFactorToStringVectorClosure extends RToStringVectorClosure { private final RAbstractStringVector levels; private final boolean withNames; - RFactorToStringVectorClosure(RAbstractIntVector vector, RAbstractStringVector levels, boolean withNames) { + RFactorToStringVectorClosure(RAbstractIntVector vector, RAbstractStringVector levels, boolean withNames, boolean keepAttributes) { + super(keepAttributes); this.vector = vector; this.levels = levels; this.withNames = withNames; @@ -257,7 +271,7 @@ final class RFactorToStringVectorClosure extends RToStringVectorClosure { } @Override - public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) { + public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, @SuppressWarnings("hiding") boolean keepAttributes) { switch (type) { case Character: return this; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java index 9d00bf9472669b9f2513206cfe1f9856c987bbe6..2f0146bee3eb5b7fc9c887c825786dfca23454fe 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java @@ -23,7 +23,8 @@ package com.oracle.truffle.r.runtime.data.closures; import com.oracle.truffle.api.object.DynamicObject; -import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RTypedValue; @@ -33,6 +34,13 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector; abstract class RToVectorClosure implements RAbstractVector { + /** If {@code true}, attributes should be preserved when materializing. */ + protected final boolean keepAttributes; + + protected RToVectorClosure(boolean keepAttributes) { + this.keepAttributes = keepAttributes; + } + public abstract RAbstractVector getVector(); @Override @@ -122,22 +130,22 @@ abstract class RToVectorClosure implements RAbstractVector { @Override public final RAbstractVector copy() { - throw RInternalError.shouldNotReachHere(); + return materialize().copy(); } @Override public final RVector<?> copyResized(int size, boolean fillNA) { - throw RInternalError.shouldNotReachHere(); + return materialize().copyResized(size, fillNA); } @Override public final RVector<?> copyResizedWithDimensions(int[] newDimensions, boolean fillNA) { - throw RInternalError.shouldNotReachHere(); + return materialize().copyResizedWithDimensions(newDimensions, fillNA); } @Override public final RAbstractVector copyDropAttributes() { - throw RInternalError.shouldNotReachHere(); + return materialize().copyDropAttributes(); } @Override @@ -169,4 +177,11 @@ abstract class RToVectorClosure implements RAbstractVector { public boolean isS4() { return false; } + + @Override + public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttrs) { + // Closures are trimmed to use a concrete type in order to avoid polymorphism. Therefore, + // first materialize and then cast and do not create a closure over a closure. + return materialize().castSafe(type, isNAProfile, keepAttrs); + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractVector.java index 2d16b9fbeaaadc411d77f097171a685915f6d079..71f6d47c49f979d040449e7f9f0384763c502cab 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractVector.java @@ -68,9 +68,27 @@ public interface RAbstractVector extends RAbstractContainer { * implementation may decide to just wrap the original vector with a closure. This method is * optimized for invocation with a compile-time constant {@link RType}. * + * @see #castSafe(RType, ConditionProfile, boolean) + */ + default RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) { + return castSafe(type, isNAProfile, false); + } + + /** + * Casts a vector to another {@link RType}. If a safe cast to the target {@link RType} is not + * supported <code>null</code> is returned. Instead of materializing the cast for each index the + * implementation may decide to just wrap the original vector with a closure. This method is + * optimized for invocation with a compile-time constant {@link RType}. + * + * @param type + * @param isNAProfile + * @param keepAttributes If {@code true}, the cast itself will keep the attributes. This is, + * however, a rather slow operation and you should set this to {@code false} and use + * nodes for copying attributes if possible. + * * @see RType#getPrecedence() */ - default RAbstractVector castSafe(RType type, @SuppressWarnings("unused") ConditionProfile isNAProfile) { + default RAbstractVector castSafe(RType type, @SuppressWarnings("unused") ConditionProfile isNAProfile, @SuppressWarnings("unused") boolean keepAttributes) { if (type == getRType()) { return this; } else { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java index dcb01ee548ac70950daf8f94469abd7aa8adf2c2..eb109fbe93ed659235e053747d6d184eed4293d6 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java @@ -930,7 +930,8 @@ public abstract class REnvironment extends RAttributeStorage { slots = namespacesFrame.getFrameDescriptor().getSlots().toArray(slots); for (int i = 0; i < slots.length; i++) { REnvironment namespaceEnv = (REnvironment) FrameSlotChangeMonitor.getValue(slots[i], namespacesFrame); - if (namespaceEnv != Base.baseNamespaceEnv()) { + // Could be 'null' due to multi slot data and an error during package loading + if (namespaceEnv != Base.baseNamespaceEnv() && namespaceEnv != null) { // base namespace frame redirects all accesses to base frame and this would // result in processing the slots twice fun.apply(namespaceEnv.getFrame(), true); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java index 47d82e72ec4d51d22f415a1e825236a9454ed16c..20c8cd97be5cb81f6d65261874828e7dc7d321cc 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java @@ -853,6 +853,10 @@ public final class FrameSlotChangeMonitor { public static void setObjectAndInvalidate(Frame frame, FrameSlot frameSlot, Object newValue, boolean isNonLocal, BranchProfile invalidateProfile) { assert !ActiveBinding.isActiveBinding(newValue); + setAndInvalidate(frame, frameSlot, newValue, isNonLocal, invalidateProfile); + } + + private static void setAndInvalidate(Frame frame, FrameSlot frameSlot, Object newValue, boolean isNonLocal, BranchProfile invalidateProfile) { FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot); if (FastROptions.SharedContexts.getBooleanValue() && info.possibleMultiSlot() && !RContext.isSingle()) { info.setMultiSlot(frame, frameSlot, newValue); @@ -877,12 +881,7 @@ public final class FrameSlotChangeMonitor { } public static void setActiveBinding(Frame frame, FrameSlot frameSlot, ActiveBinding newValue, boolean isNonLocal, BranchProfile invalidateProfile) { - frame.setObject(frameSlot, newValue); - FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot); - if (info.needsInvalidation()) { - info.setValue(newValue, frameSlot); - } - checkAndInvalidate(frame, frameSlot, isNonLocal, invalidateProfile); + setAndInvalidate(frame, frameSlot, newValue, isNonLocal, invalidateProfile); getContainsNoActiveBindingAssumption(frame.getFrameDescriptor()).invalidate(); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/RMath.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/RMath.java index 22dadebc92a20f82539d9fb72d3a4dd438ae4672..5db1157cc3a5b0c284dab5db488af80a56d9b158 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/RMath.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/RMath.java @@ -34,6 +34,13 @@ import com.oracle.truffle.r.runtime.nmath.RMathError.MLError; */ public final class RMath { + public static double sign(double x) { + if (Double.isNaN(x)) { + return x; + } + return ((x > 0) ? 1 : ((x == 0) ? 0 : -1)); + } + public static boolean mlValid(double d) { return !Double.isNaN(d); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/na/NAProfile.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/na/NAProfile.java index 9369eff3db4e8c5cdcd68a02b152227caed1b70d..084aec76db8bdbee914f6ec4a35ae48b8657ff8f 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/na/NAProfile.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/na/NAProfile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, 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 @@ -58,6 +58,10 @@ public final class NAProfile { return profile.profile(RRuntime.isNA(value)); } + public ConditionProfile getConditionProfile() { + return profile; + } + public void ifNa(double value, Runnable runnable) { if (isNA(value)) { runnable.run(); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RRNG.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RRNG.java index eecc1c27b5f9536182fffd46fdddde09a55d3c1b..954b4408215496c42ecfb13cedfdc609bcdd657f 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RRNG.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RRNG.java @@ -18,13 +18,10 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.context.RContext; -import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RTypedValue; -import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.ffi.BaseRFFI; import com.oracle.truffle.r.runtime.rng.mm.MarsagliaMulticarry; import com.oracle.truffle.r.runtime.rng.mt.MersenneTwister; @@ -100,7 +97,7 @@ public class RRNG { public static final Integer SAME_SEED = null; private static final Kind DEFAULT_KIND = Kind.MERSENNE_TWISTER; private static final NormKind DEFAULT_NORM_KIND = NormKind.INVERSION; - private static final String RANDOM_SEED = ".Random.seed"; + public static final String RANDOM_SEED = ".Random.seed"; private static final double UINT_MAX = (double) Integer.MAX_VALUE * 2; public static final class ContextStateImpl implements RContext.ContextState { @@ -108,6 +105,13 @@ public class RRNG { private final RandomNumberGenerator[] allGenerators; private NormKind currentNormKind; + /** + * Stores the current RNG seed. The type is Object because the user may assign an arbitrary + * value to variable {@value RRNG#RANDOM_SEED}. Allowed types are therefore any R value or + * an {@code int[]}. + */ + public Object currentSeeds = RMissing.instance; + private ContextStateImpl() { this.currentNormKind = DEFAULT_NORM_KIND; this.allGenerators = new RandomNumberGenerator[Kind.VALUES.length]; @@ -282,11 +286,7 @@ public class RRNG { @TruffleBoundary private static Object getDotRandomSeed() { - Object seed = REnvironment.globalEnv().get(RANDOM_SEED); - if (seed instanceof RPromise) { - seed = RContext.getRRuntimeASTAccess().forcePromise(RANDOM_SEED, seed); - } - return seed; + return RContext.getInstance().stateRNG.currentSeeds; } /** @@ -327,14 +327,20 @@ public class RRNG { } else if (seeds instanceof RIntVector) { RIntVector seedsVec = (RIntVector) seeds; tmp = seedsVec.getLength() == 0 ? RRuntime.INT_NA : seedsVec.getDataAt(0); + } else if (seeds instanceof int[]) { + int[] seedsArr = (int[]) seeds; + tmp = seedsArr.length == 0 ? RRuntime.INT_NA : seedsArr[0]; } else { - assert seeds != RMissing.instance; assert seeds instanceof RTypedValue; - RError.warning(RError.NO_CALLER, RError.Message.SEED_TYPE, ((RTypedValue) seeds).getRType().getName()); + // allow RMissing to indicate that ".Random.seed" has not been initialized yet + if (seeds != RMissing.instance) { + RError.warning(RError.NO_CALLER, RError.Message.SEED_TYPE, ((RTypedValue) seeds).getRType().getName()); + } handleInvalidSeed(); return; } if (tmp == RRuntime.INT_NA || tmp < 0 || tmp > 1000) { + assert seeds != RMissing.instance; String type = seeds instanceof RTypedValue ? ((RTypedValue) seeds).getRType().getName() : "unknown"; RError.warning(RError.NO_CALLER, RError.Message.SEED_TYPE, type); handleInvalidSeed(); @@ -386,6 +392,12 @@ public class RRNG { // no change of the .Random.seed variable return; } + } else if (seedsObj instanceof int[]) { + seeds = (int[]) seedsObj; + if (seeds == currentGenerator().getSeeds()) { + // no change of the .Random.seed variable + return; + } } else { // seedsObj is not valid, which should have been reported and fixed in getRNGKind return; @@ -410,7 +422,6 @@ public class RRNG { public static void putRNGState() { int[] seeds = currentGenerator().getSeeds(); seeds[0] = currentKind().ordinal() + 100 * currentNormKind().ordinal(); - RIntVector vector = RDataFactory.createIntVector(seeds, RDataFactory.INCOMPLETE_VECTOR); - REnvironment.globalEnv().safePut(RANDOM_SEED, vector.makeSharedPermanent()); + RContext.getInstance().stateRNG.currentSeeds = seeds; } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test index dc5be133758935e9793c7928f2c44168ad2c843e..35e626cff237e38f505e8f81d7783ab4d59a2614 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test @@ -1,6 +1,6 @@ ##com.oracle.truffle.r.test.S4.TestR5.testAllocation# -#env0 <- new.env(); setRefClass('Foo17R5', where = env0); ls(topenv(parent.frame()), all.names = T); ls(env0, all.names = T) -[1] "env0" +#env0 <- new.env(); setRefClass('Foo17R5', where = env0); grep('Foo17R5', ls(topenv(parent.frame()), all.names = T), value = TRUE); ls(env0, all.names = T) +character(0) [1] ".__C__Foo17R5" ".__global__" ".requireCachedGenerics" ##com.oracle.truffle.r.test.S4.TestR5.testAllocation# @@ -31,8 +31,8 @@ In methods::initRefFields(.Object, classDef, selfEnv, list(...)) : unnamed arguments to $new() must be objects from a reference class; got an object of class “numeric†##com.oracle.truffle.r.test.S4.TestR5.testAllocation# -#{ setRefClass('Foo16R5'); ls(topenv(parent.frame()), all.names = T) } -[1] ".__C__Foo16R5" ".__global__" ".requireCachedGenerics" +#{ setRefClass('Foo16R5'); grep('Foo16R5', ls(topenv(parent.frame()), all.names = T), value = TRUE) } +[1] ".__C__Foo16R5" ##com.oracle.truffle.r.test.S4.TestR5.testAttributes# #{ clazz <- setRefClass('Foo13R5'); clazz$methods() } @@ -6928,6 +6928,12 @@ NAs introduced by coercion #{ as.integer(c(1.0,2.5,3.9)) } [1] 1 2 3 +##com.oracle.truffle.r.test.builtins.TestBuiltin_asinteger.testAsInteger# +#{ as.integer(c(100, -1e-13, Inf, -Inf, NaN, 3.14159265358979, NA)) } +[1] 100 0 NA NA NA 3 NA +Warning message: +NAs introduced by coercion to integer range + ##com.oracle.truffle.r.test.builtins.TestBuiltin_asinteger.testAsInteger#Output.IgnoreWarningContext# #{ as.integer(c(3+3i, 4+4i)) } [1] 3 4 @@ -69567,6 +69573,86 @@ Error in t.default(new.env()) : argument is not a matrix b 1 c 2 +##com.oracle.truffle.r.test.builtins.TestBuiltin_t.testTransposeNonSquare# +#{ m <- matrix(1:8, 2, 4) ; t(m) } + [,1] [,2] +[1,] 1 2 +[2,] 3 4 +[3,] 5 6 +[4,] 7 8 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_t.testTransposeNonSquare# +#{ m <- matrix(as.raw(c(1:8)), 2, 4); t(m) } + [,1] [,2] +[1,] 01 02 +[2,] 03 04 +[3,] 05 06 +[4,] 07 08 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_t.testTransposeNonSquare# +#{ m <- matrix(c('1', '2', '3', '4', '5', '6', '7', '8'), 2, 4); t(m) } + [,1] [,2] +[1,] "1" "2" +[2,] "3" "4" +[3,] "5" "6" +[4,] "7" "8" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_t.testTransposeNonSquare# +#{ m <- matrix(c(T, F, F, F, T, F, F, T), 2, 4); t(m) } + [,1] [,2] +[1,] TRUE FALSE +[2,] FALSE FALSE +[3,] TRUE FALSE +[4,] FALSE TRUE + +##com.oracle.truffle.r.test.builtins.TestBuiltin_t.testTransposeNonSquare# +#{ m <- matrix(list(a=1,b=2,c=3,d=4,e=5,f=6,g=7,h=8), 2, 4); t(m) } + [,1] [,2] +[1,] 1 2 +[2,] 3 4 +[3,] 5 6 +[4,] 7 8 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_t.testTransposeNonSquare# +#{ m <- matrix(seq(0.1,0.8,0.1), 2, 4) ; t(m) } + [,1] [,2] +[1,] 0.1 0.2 +[2,] 0.3 0.4 +[3,] 0.5 0.6 +[4,] 0.7 0.8 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_t.testTransposeSquare# +#{ m <- matrix(1:64, 8, 8) ; sum(m * t(m)) } +[1] 72976 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_t.testTransposeSquare# +#{ m <- matrix(as.raw(c(1,2,3,4)), 2, 2); t(m) } + [,1] [,2] +[1,] 01 02 +[2,] 03 04 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_t.testTransposeSquare# +#{ m <- matrix(c('1', '2', '3', '4'), 2, 2); t(m) } + [,1] [,2] +[1,] "1" "2" +[2,] "3" "4" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_t.testTransposeSquare# +#{ m <- matrix(c(T, T, F, F), 2, 2); t(m) } + [,1] [,2] +[1,] TRUE TRUE +[2,] FALSE FALSE + +##com.oracle.truffle.r.test.builtins.TestBuiltin_t.testTransposeSquare# +#{ m <- matrix(list(a=1,b=2,c=3,d=4), 2, 2); t(m) } + [,1] [,2] +[1,] 1 2 +[2,] 3 4 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_t.testTransposeSquare# +#{ m <- matrix(seq(0.01,0.64,0.01), 8, 8) ; sum(m * t(m)) } +[1] 7.2976 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_t.testt1# #argv <- structure(list(x = c(-2.13777446721376, 1.17045456767922, 5.85180137819007)), .Names = 'x');do.call('t', argv) [,1] [,2] [,3] @@ -75123,6 +75209,10 @@ imaginary parts discarded in coercion #{ as.vector(list(1,2,3), mode="integer") } [1] 1 2 3 +##com.oracle.truffle.r.test.builtins.TestMiscBuiltins.testCasts# +#{ env <- new.env(); env$x<-7; env$.y<-42; length(as.list(env, all.names=TRUE)) } +[1] 2 + ##com.oracle.truffle.r.test.builtins.TestMiscBuiltins.testCasts# #{ k <- as.list(3:6) ; l <- as.list(1) ; list(k,l) } [[1]] @@ -75261,10 +75351,6 @@ $x [1] 7 -##com.oracle.truffle.r.test.builtins.TestMiscBuiltins.testCasts# -#{ x<-7; .y<-42; length(as.list(environment(), all.names=TRUE)) } -[1] 2 - ##com.oracle.truffle.r.test.builtins.TestMiscBuiltins.testCasts# #{ x<-7; as.list(environment()) } $x @@ -148043,6 +148129,330 @@ Error: argument 'files' must be character Error in stats::complete.cases(data.frame(col1 = c(1, 2, NA), col2 = c(1, : not all arguments have the same length +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(1:4, c(1,7,1,-4), use='a', method='k') +[1] -0.5477226 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(1:4, c(1,7,1,-4), use='a', method='p') +[1] -0.6024641 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(1:4, c(1,7,1,-4), use='a', method='s') +[1] -0.6324555 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(1:4, c(1,7,1,-4), use='c', method='k') +[1] -0.5477226 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(1:4, c(1,7,1,-4), use='c', method='p') +[1] -0.6024641 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(1:4, c(1,7,1,-4), use='c', method='s') +[1] -0.6324555 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(1:4, c(1,7,1,-4), use='e', method='k') +[1] -0.5477226 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(1:4, c(1,7,1,-4), use='e', method='p') +[1] -0.6024641 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(1:4, c(1,7,1,-4), use='e', method='s') +[1] -0.6324555 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(1:4, c(1,7,1,-4), use='n', method='k') +[1] -0.5477226 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(1:4, c(1,7,1,-4), use='n', method='p') +[1] -0.6024641 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(1:4, c(1,7,1,-4), use='n', method='s') +[1] -0.6324555 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(1:4, c(1,7,1,-4), use='p', method='k') +[1] -0.5477226 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(1:4, c(1,7,1,-4), use='p', method='p') +[1] -0.6024641 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(1:4, c(1,7,1,-4), use='p', method='s') +[1] -0.6324555 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(mtcars[,1:4], use='a', method='k') + mpg cyl disp hp +mpg 1.0000000 -0.7953134 -0.7681311 -0.7428125 +cyl -0.7953134 1.0000000 0.8144263 0.7851865 +disp -0.7681311 0.8144263 1.0000000 0.6659987 +hp -0.7428125 0.7851865 0.6659987 1.0000000 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(mtcars[,1:4], use='a', method='p') + mpg cyl disp hp +mpg 1.0000000 -0.8521620 -0.8475514 -0.7761684 +cyl -0.8521620 1.0000000 0.9020329 0.8324475 +disp -0.8475514 0.9020329 1.0000000 0.7909486 +hp -0.7761684 0.8324475 0.7909486 1.0000000 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(mtcars[,1:4], use='a', method='s') + mpg cyl disp hp +mpg 1.0000000 -0.9108013 -0.9088824 -0.8946646 +cyl -0.9108013 1.0000000 0.9276516 0.9017909 +disp -0.9088824 0.9276516 1.0000000 0.8510426 +hp -0.8946646 0.9017909 0.8510426 1.0000000 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(mtcars[,1:4], use='c', method='k') + mpg cyl disp hp +mpg 1.0000000 -0.7953134 -0.7681311 -0.7428125 +cyl -0.7953134 1.0000000 0.8144263 0.7851865 +disp -0.7681311 0.8144263 1.0000000 0.6659987 +hp -0.7428125 0.7851865 0.6659987 1.0000000 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(mtcars[,1:4], use='c', method='p') + mpg cyl disp hp +mpg 1.0000000 -0.8521620 -0.8475514 -0.7761684 +cyl -0.8521620 1.0000000 0.9020329 0.8324475 +disp -0.8475514 0.9020329 1.0000000 0.7909486 +hp -0.7761684 0.8324475 0.7909486 1.0000000 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(mtcars[,1:4], use='c', method='s') + mpg cyl disp hp +mpg 1.0000000 -0.9108013 -0.9088824 -0.8946646 +cyl -0.9108013 1.0000000 0.9276516 0.9017909 +disp -0.9088824 0.9276516 1.0000000 0.8510426 +hp -0.8946646 0.9017909 0.8510426 1.0000000 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(mtcars[,1:4], use='e', method='k') + mpg cyl disp hp +mpg 1.0000000 -0.7953134 -0.7681311 -0.7428125 +cyl -0.7953134 1.0000000 0.8144263 0.7851865 +disp -0.7681311 0.8144263 1.0000000 0.6659987 +hp -0.7428125 0.7851865 0.6659987 1.0000000 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(mtcars[,1:4], use='e', method='p') + mpg cyl disp hp +mpg 1.0000000 -0.8521620 -0.8475514 -0.7761684 +cyl -0.8521620 1.0000000 0.9020329 0.8324475 +disp -0.8475514 0.9020329 1.0000000 0.7909486 +hp -0.7761684 0.8324475 0.7909486 1.0000000 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(mtcars[,1:4], use='e', method='s') + mpg cyl disp hp +mpg 1.0000000 -0.9108013 -0.9088824 -0.8946646 +cyl -0.9108013 1.0000000 0.9276516 0.9017909 +disp -0.9088824 0.9276516 1.0000000 0.8510426 +hp -0.8946646 0.9017909 0.8510426 1.0000000 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(mtcars[,1:4], use='n', method='k') + mpg cyl disp hp +mpg 1.0000000 -0.7953134 -0.7681311 -0.7428125 +cyl -0.7953134 1.0000000 0.8144263 0.7851865 +disp -0.7681311 0.8144263 1.0000000 0.6659987 +hp -0.7428125 0.7851865 0.6659987 1.0000000 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(mtcars[,1:4], use='n', method='p') + mpg cyl disp hp +mpg 1.0000000 -0.8521620 -0.8475514 -0.7761684 +cyl -0.8521620 1.0000000 0.9020329 0.8324475 +disp -0.8475514 0.9020329 1.0000000 0.7909486 +hp -0.7761684 0.8324475 0.7909486 1.0000000 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(mtcars[,1:4], use='n', method='s') + mpg cyl disp hp +mpg 1.0000000 -0.9108013 -0.9088824 -0.8946646 +cyl -0.9108013 1.0000000 0.9276516 0.9017909 +disp -0.9088824 0.9276516 1.0000000 0.8510426 +hp -0.8946646 0.9017909 0.8510426 1.0000000 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(mtcars[,1:4], use='p', method='k') + mpg cyl disp hp +mpg 1.0000000 -0.7953134 -0.7681311 -0.7428125 +cyl -0.7953134 1.0000000 0.8144263 0.7851865 +disp -0.7681311 0.8144263 1.0000000 0.6659987 +hp -0.7428125 0.7851865 0.6659987 1.0000000 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(mtcars[,1:4], use='p', method='p') + mpg cyl disp hp +mpg 1.0000000 -0.8521620 -0.8475514 -0.7761684 +cyl -0.8521620 1.0000000 0.9020329 0.8324475 +disp -0.8475514 0.9020329 1.0000000 0.7909486 +hp -0.7761684 0.8324475 0.7909486 1.0000000 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cor(mtcars[,1:4], use='p', method='s') + mpg cyl disp hp +mpg 1.0000000 -0.9108013 -0.9088824 -0.8946646 +cyl -0.9108013 1.0000000 0.9276516 0.9017909 +disp -0.9088824 0.9276516 1.0000000 0.8510426 +hp -0.8946646 0.9017909 0.8510426 1.0000000 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cov(1:4, c(1,7,1,-4), use='a', method='k') +[1] -6 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cov(1:4, c(1,7,1,-4), use='a', method='p') +[1] -3.5 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cov(1:4, c(1,7,1,-4), use='a', method='s') +[1] -1 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cov(1:4, c(1,7,1,-4), use='c', method='k') +[1] -6 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cov(1:4, c(1,7,1,-4), use='c', method='p') +[1] -3.5 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cov(1:4, c(1,7,1,-4), use='c', method='s') +[1] -1 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cov(1:4, c(1,7,1,-4), use='e', method='k') +[1] -6 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cov(1:4, c(1,7,1,-4), use='e', method='p') +[1] -3.5 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cov(1:4, c(1,7,1,-4), use='e', method='s') +[1] -1 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cov(1:4, c(1,7,1,-4), use='n', method='k') +[1] -6 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cov(1:4, c(1,7,1,-4), use='n', method='p') +[1] -3.5 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cov(1:4, c(1,7,1,-4), use='n', method='s') +[1] -1 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cov(mtcars[,1:4], use='a', method='k') + mpg cyl disp hp +mpg 978 -638 -752 -722 +cyl -638 658 654 626 +disp -752 654 980 648 +hp -722 626 648 966 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cov(mtcars[,1:4], use='a', method='p') + mpg cyl disp hp +mpg 36.324103 -9.172379 -633.0972 -320.7321 +cyl -9.172379 3.189516 199.6603 101.9315 +disp -633.097208 199.660282 15360.7998 6721.1587 +hp -320.732056 101.931452 6721.1587 4700.8669 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cov(mtcars[,1:4], use='a', method='s') + mpg cyl disp hp +mpg 87.88710 -74.54032 -79.87903 -78.56452 +cyl -74.54032 76.20968 75.91935 73.74194 +disp -79.87903 75.91935 87.88710 74.73387 +hp -78.56452 73.74194 74.73387 87.74194 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cov(mtcars[,1:4], use='c', method='k') + mpg cyl disp hp +mpg 978 -638 -752 -722 +cyl -638 658 654 626 +disp -752 654 980 648 +hp -722 626 648 966 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cov(mtcars[,1:4], use='c', method='p') + mpg cyl disp hp +mpg 36.324103 -9.172379 -633.0972 -320.7321 +cyl -9.172379 3.189516 199.6603 101.9315 +disp -633.097208 199.660282 15360.7998 6721.1587 +hp -320.732056 101.931452 6721.1587 4700.8669 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cov(mtcars[,1:4], use='c', method='s') + mpg cyl disp hp +mpg 87.88710 -74.54032 -79.87903 -78.56452 +cyl -74.54032 76.20968 75.91935 73.74194 +disp -79.87903 75.91935 87.88710 74.73387 +hp -78.56452 73.74194 74.73387 87.74194 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cov(mtcars[,1:4], use='e', method='k') + mpg cyl disp hp +mpg 978 -638 -752 -722 +cyl -638 658 654 626 +disp -752 654 980 648 +hp -722 626 648 966 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cov(mtcars[,1:4], use='e', method='p') + mpg cyl disp hp +mpg 36.324103 -9.172379 -633.0972 -320.7321 +cyl -9.172379 3.189516 199.6603 101.9315 +disp -633.097208 199.660282 15360.7998 6721.1587 +hp -320.732056 101.931452 6721.1587 4700.8669 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cov(mtcars[,1:4], use='e', method='s') + mpg cyl disp hp +mpg 87.88710 -74.54032 -79.87903 -78.56452 +cyl -74.54032 76.20968 75.91935 73.74194 +disp -79.87903 75.91935 87.88710 74.73387 +hp -78.56452 73.74194 74.73387 87.74194 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cov(mtcars[,1:4], use='n', method='k') + mpg cyl disp hp +mpg 978 -638 -752 -722 +cyl -638 658 654 626 +disp -752 654 980 648 +hp -722 626 648 966 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cov(mtcars[,1:4], use='n', method='p') + mpg cyl disp hp +mpg 36.324103 -9.172379 -633.0972 -320.7321 +cyl -9.172379 3.189516 199.6603 101.9315 +disp -633.097208 199.660282 15360.7998 6721.1587 +hp -320.732056 101.931452 6721.1587 4700.8669 + +##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCombinations# +#cov(mtcars[,1:4], use='n', method='s') + mpg cyl disp hp +mpg 87.88710 -74.54032 -79.87903 -78.56452 +cyl -74.54032 76.20968 75.91935 73.74194 +disp -79.87903 75.91935 87.88710 74.73387 +hp -78.56452 73.74194 74.73387 87.74194 + ##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCovcor# #.Call(stats:::C_cov, 1:5, 1:5, 4, FALSE) [1] 2.5 @@ -156014,7 +156424,7 @@ non-integer value 12345678909876543212L qualified with L; using numeric value [619] -346017954 -1916029881 -1735526436 1461823277 580724746 -622095869 [625] -686746776 705745481 -##com.oracle.truffle.r.test.rng.TestRRNG.testDirectSeedAssignment#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.rng.TestRRNG.testDirectSeedAssignment#Output.IgnoreWarningContext#Output.MayIgnoreWarningContext# #.Random.seed <- c(401, 1, 2); invisible(runif(3)) Warning message: In runif(3) : @@ -156024,7 +156434,7 @@ In runif(3) : #.Random.seed <- c(401L, 1L, 2L); runif(3) [1] 0.5641106 0.2932388 0.6696743 -##com.oracle.truffle.r.test.rng.TestRRNG.testDirectSeedAssignment#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.rng.TestRRNG.testDirectSeedAssignment#Output.IgnoreWarningContext#Output.MayIgnoreWarningContext# #.Random.seed <- c(999, 1, 2); invisible(runif(3)) Warning message: In runif(3) : diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java index 650fb03db0860ee18a8e074044891c0b9b4e0fd1..e263c2eaa1b6fd3eaf8f67315d8dd993f3691f35 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java @@ -49,8 +49,8 @@ public class TestR5 extends TestBase { assertEval("{ DummyClass2 <- setRefClass('DummyClass2'); obj <- DummyClass2$new(); is(obj, 'refObject') }"); assertEval("{ fooClass <- setRefClass('Foo6R5', fields = list( a = 'numeric')); fooClass$new(a = 1) }"); assertEval("{ fooClass <- setRefClass('Foo7R5', fields = list( a = 'numeric')); fooClass$new(1) }"); - assertEval("{ setRefClass('Foo16R5'); ls(topenv(parent.frame()), all.names = T) }"); - assertEval("env0 <- new.env(); setRefClass('Foo17R5', where = env0); ls(topenv(parent.frame()), all.names = T); ls(env0, all.names = T)"); + assertEval("{ setRefClass('Foo16R5'); grep('Foo16R5', ls(topenv(parent.frame()), all.names = T), value = TRUE) }"); + assertEval("env0 <- new.env(); setRefClass('Foo17R5', where = env0); grep('Foo17R5', ls(topenv(parent.frame()), all.names = T), value = TRUE); ls(env0, all.names = T)"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asinteger.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asinteger.java index 19aeddb65d4d96a5da38c47f76af20880fac9004..a50e12c6b81ab1ec737b653fa8a9dbb25323af97 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asinteger.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asinteger.java @@ -147,5 +147,6 @@ public class TestBuiltin_asinteger extends TestBase { assertEval("{ as.integer(as.character(NA)) }"); assertEval("{ as.integer(\"1\", as.character(NA)) }"); assertEval("{ as.integer.cls <- function(x) 42; as.integer(structure(c(1,2), class='cls')); }"); + assertEval("{ as.integer(c(100, -1e-13, Inf, -Inf, NaN, 3.14159265358979, NA)) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_t.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_t.java index b4640e1d0567158ad6dba2e8ccfc5be46df9f85a..ca5b37d80674154befc4b2ec214dc4a11909ea31 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_t.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_t.java @@ -48,4 +48,26 @@ public class TestBuiltin_t extends TestBase { assertEval("t(as.raw(c(1,2,3,4)))"); assertEval("t(matrix(1:6, 3, 2, dimnames=list(x=c(\"x1\",\"x2\",\"x3\"),y=c(\"y1\",\"y2\"))))"); } + + @Test + public void testTransposeSquare() { + // test square matrices + assertEval("{ m <- matrix(1:64, 8, 8) ; sum(m * t(m)) }"); + assertEval("{ m <- matrix(seq(0.01,0.64,0.01), 8, 8) ; sum(m * t(m)) }"); + assertEval("{ m <- matrix(c(T, T, F, F), 2, 2); t(m) }"); + assertEval("{ m <- matrix(c('1', '2', '3', '4'), 2, 2); t(m) }"); + assertEval("{ m <- matrix(as.raw(c(1,2,3,4)), 2, 2); t(m) }"); + assertEval("{ m <- matrix(list(a=1,b=2,c=3,d=4), 2, 2); t(m) }"); + } + + @Test + public void testTransposeNonSquare() { + // test square matrices + assertEval("{ m <- matrix(1:8, 2, 4) ; t(m) }"); + assertEval("{ m <- matrix(seq(0.1,0.8,0.1), 2, 4) ; t(m) }"); + assertEval("{ m <- matrix(c(T, F, F, F, T, F, F, T), 2, 4); t(m) }"); + assertEval("{ m <- matrix(c('1', '2', '3', '4', '5', '6', '7', '8'), 2, 4); t(m) }"); + assertEval("{ m <- matrix(as.raw(c(1:8)), 2, 4); t(m) }"); + assertEval("{ m <- matrix(list(a=1,b=2,c=3,d=4,e=5,f=6,g=7,h=8), 2, 4); t(m) }"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestMiscBuiltins.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestMiscBuiltins.java index a298e3af601c7bf86a6088d86fa9236510b0457b..d2da41043eeffeee9a0cb48b3914c734195706a9 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestMiscBuiltins.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestMiscBuiltins.java @@ -90,7 +90,7 @@ public class TestMiscBuiltins extends TestBase { assertEval("{ x<-7; as.list(environment()) }"); assertEval("{ x<-7; .y<-42; as.list(environment()) }"); // not sorted so can't compare list print - assertEval("{ x<-7; .y<-42; length(as.list(environment(), all.names=TRUE)) }"); + assertEval("{ env <- new.env(); env$x<-7; env$.y<-42; length(as.list(env, all.names=TRUE)) }"); assertEval("{ x<-7; f<-function() x<<-42; f_copy<-as.list(environment())[[\"f\"]]; f_copy(); x }"); // as.matrix diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_covcor.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_covcor.java index 5f548a2355f67085dc227c71caed04103bece6e7..fe08b63966fe6a4eac773b268a55517cbedc9367 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_covcor.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_covcor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -40,4 +40,15 @@ public class TestExternal_covcor extends TestBase { assertEval(".Call(stats:::C_cov, NULL, 1:5, 4, FALSE)"); assertEval(".Call(stats:::C_cov, 1:3, 1:5, 4, FALSE)"); } + + @Test + public void testCombinations() { + String[] useCor = new String[]{"e", "a", "c", "n", "p"}; + String[] useCov = new String[]{"e", "a", "c", "n"}; + String[] methods = new String[]{"p", "k", "s"}; + assertEval(template("cor(mtcars[,1:4], use='%0', method='%1')", useCor, methods)); + assertEval(template("cor(1:4, c(1,7,1,-4), use='%0', method='%1')", useCor, methods)); + assertEval(template("cov(mtcars[,1:4], use='%0', method='%1')", useCov, methods)); + assertEval(template("cov(1:4, c(1,7,1,-4), use='%0', method='%1')", useCov, methods)); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rng/TestRRNG.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rng/TestRRNG.java index b578868551d8e969ee14175f6d268f234077b164..dc4faf27a83efd6bd9e3d5fb6a04a696f129ae6c 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rng/TestRRNG.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rng/TestRRNG.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -32,9 +32,9 @@ public class TestRRNG extends TestBase { // changes generator to MarsagliaMulticarry and sets its 2 seeds assertEval(".Random.seed <- c(401L, 1L, 2L); runif(3)"); // wrong values: not integer - assertEval(Output.IgnoreWarningContext, ".Random.seed <- c(401, 1, 2); invisible(runif(3))"); + assertEval(Output.IgnoreWarningContext, Output.MayIgnoreWarningContext, ".Random.seed <- c(401, 1, 2); invisible(runif(3))"); // wrong values: wrong generator number - assertEval(Output.IgnoreWarningContext, ".Random.seed <- c(999, 1, 2); invisible(runif(3))"); + assertEval(Output.IgnoreWarningContext, Output.MayIgnoreWarningContext, ".Random.seed <- c(999, 1, 2); invisible(runif(3))"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java index a419f8ff22805537f4df67539b1f2b4e7cfd2fb4..fb0161aacfad939b1c3475d327fdcde757e78a67 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java @@ -488,7 +488,7 @@ public class FastRDebugTest { assertEquals(line, currentLine); final String currentCode = suspendedEvent.getSourceSection().getCode().trim(); assertEquals(code, currentCode); - compareScope(line, code, false, true, expectedFrame); + compareScope(line, code, false, false, expectedFrame); } catch (RuntimeException | Error e) { final DebugStackFrame frame = suspendedEvent.getTopStackFrame();