Skip to content
Snippets Groups Projects
Commit d376a237 authored by Mick Jordan's avatar Mick Jordan
Browse files

cleanup of UserRNG; convert UserRngRFFI to JNI

parent 48471985
No related branches found
No related tags found
No related merge requests found
/*
* Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include <rffiutils.h>
typedef void (*call_init)(int seed);
typedef double* (*call_rand)(void);
typedef int* (*call_nSeed)(void);
typedef int* (*call_seeds)(void);
JNIEXPORT void JNICALL
Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1UserRng_init(JNIEnv *env, jclass c, jlong address, jint seed) {
call_init f = (call_init) address;
f(seed);
}
JNIEXPORT double JNICALL
Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1UserRng_rand(JNIEnv *env, jclass c, jlong address) {
call_rand f = (call_rand) address;
double* dp = f();
return *dp;
}
JNIEXPORT jint JNICALL
Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1UserRng_nSeed(JNIEnv *env, jclass c, jlong address) {
call_nSeed f = (call_nSeed) address;
int *pn = f();
return *pn;
}
JNIEXPORT void JNICALL
Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1UserRng_seeds(JNIEnv *env, jclass c, jlong address, jintArray seedsArray) {
call_seeds f = (call_seeds) address;
int *pseeds = f();
int seedslen = (*env)->GetArrayLength(env, seedsArray);
int *data = (*env)->GetIntArrayElements(env, seedsArray, NULL);
for (int i = 0; i < seedslen; i++) {
data[i] = pseeds[i];
}
(*env)->ReleaseIntArrayElements(env, seedsArray, data, 0);
}
......@@ -22,82 +22,41 @@
*/
package com.oracle.truffle.r.runtime.ffi.jnr;
import static com.oracle.truffle.r.runtime.rng.user.UserRNG.Function;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.r.runtime.ffi.UserRngRFFI;
import jnr.ffi.LibraryLoader;
import jnr.ffi.Pointer;
import jnr.ffi.annotations.In;
//Checkstyle: stop method name
public class JNR_UserRng implements UserRngRFFI {
public interface UserRng {
void user_unif_init(@In int seed);
Pointer user_unif_rand();
Pointer user_unif_nseed();
Pointer user_unif_seedloc();
}
private static class UserRngProvider {
private static String libPath;
private static UserRng userRng;
UserRngProvider(String libPath) {
UserRngProvider.libPath = libPath;
}
@TruffleBoundary
private static UserRng createAndLoadLib() {
return LibraryLoader.create(UserRng.class).load(libPath);
}
static UserRng userRng() {
if (userRng == null) {
userRng = createAndLoadLib();
}
return userRng;
}
}
private static UserRng userRng() {
return UserRngProvider.userRng();
}
@Override
@SuppressWarnings("unused")
public void setLibrary(String path) {
new UserRngProvider(path);
}
public class JNI_UserRng implements UserRngRFFI {
@Override
@TruffleBoundary
public void init(int seed) {
userRng().user_unif_init(seed);
init(Function.Init.getAddress(), seed);
}
@Override
@TruffleBoundary
public double rand() {
Pointer pDouble = userRng().user_unif_rand();
return pDouble.getDouble(0);
return rand(Function.Rand.getAddress());
}
@Override
@TruffleBoundary
public int nSeed() {
return userRng().user_unif_nseed().getInt(0);
return nSeed(Function.NSeed.getAddress());
}
@Override
@TruffleBoundary
public void seeds(int[] n) {
Pointer pInt = userRng().user_unif_seedloc();
for (int i = 0; i < n.length; i++) {
n[i] = pInt.getInt(i * 4);
}
seeds(Function.Seedloc.getAddress(), n);
}
private static native void init(long address, int seed);
private static native double rand(long address);
private static native int nSeed(long address);
private static native void seeds(long address, int[] n);
}
......@@ -164,7 +164,7 @@ public class JNR_RFFIFactory extends RFFIFactory implements RFFI {
public UserRngRFFI getUserRngRFFI() {
if (userRngRFFI == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
userRngRFFI = new JNR_UserRng();
userRngRFFI = new JNI_UserRng();
}
return userRngRFFI;
}
......
/*
* Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2016, 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
......@@ -23,13 +23,10 @@
package com.oracle.truffle.r.runtime.ffi;
/**
* Explicit statically typed interface to user-supplied random number generators. TODO This could
* eventually be subsumed by {@link CRFFI}.
* Explicit statically typed interface to user-supplied random number generators.
*/
public interface UserRngRFFI {
void setLibrary(String path);
void init(int seed);
double rand();
......
......@@ -35,42 +35,68 @@ import com.oracle.truffle.r.runtime.rng.RRNG.Kind;
* Interface to a user-supplied RNG.
*/
public final class UserRNG extends RNGInitAdapter {
private static final String USER_UNIF_RAND = "user_unif_rand";
private static final String USER_UNIF_INIT = "user_unif_init";
private static final boolean OPTIONAL = true;
@SuppressWarnings("unused") private long userUnifRand;
@SuppressWarnings("unused") private long userUnifInit;
private long userUnifNSeed;
private long userUnifSeedloc;
public enum Function {
Rand(!OPTIONAL),
Init(OPTIONAL),
NSeed(OPTIONAL),
Seedloc(OPTIONAL);
private long address;
private final String symbol;
private final boolean optional;
Function(boolean optional) {
this.symbol = "user_unif_" + name().toLowerCase();
this.optional = optional;
}
private boolean isDefined() {
return address != 0;
}
public long getAddress() {
return address;
}
private void setAddress(DLLInfo dllInfo) {
this.address = findSymbol(symbol, dllInfo, optional);
}
}
private UserRngRFFI userRngRFFI;
private int nSeeds = 0;
@Override
@TruffleBoundary
public void init(int seed) {
DLLInfo dllInfo = DLL.findLibraryContainingSymbol(USER_UNIF_RAND);
DLLInfo dllInfo = DLL.findLibraryContainingSymbol(Function.Rand.symbol);
if (dllInfo == null) {
throw RError.error(RError.NO_CALLER, RError.Message.RNG_SYMBOL, USER_UNIF_RAND);
throw RError.error(RError.NO_CALLER, RError.Message.RNG_SYMBOL, Function.Rand.symbol);
}
for (Function f : Function.values()) {
f.setAddress(dllInfo);
}
userUnifRand = findSymbol(USER_UNIF_RAND, dllInfo, !OPTIONAL);
userUnifInit = findSymbol(USER_UNIF_INIT, dllInfo, OPTIONAL);
userUnifNSeed = findSymbol(USER_UNIF_INIT, dllInfo, OPTIONAL);
userUnifSeedloc = findSymbol(USER_UNIF_INIT, dllInfo, OPTIONAL);
userRngRFFI = RFFIFactory.getRFFI().getUserRngRFFI();
userRngRFFI.setLibrary(dllInfo.path);
userRngRFFI.init(seed);
if (userUnifSeedloc != 0 && userUnifNSeed == 0) {
if (Function.Init.isDefined()) {
userRngRFFI.init(seed);
}
if (Function.Seedloc.isDefined() && !Function.NSeed.isDefined()) {
RError.warning(RError.NO_CALLER, RError.Message.RNG_READ_SEEDS);
}
int ns = userRngRFFI.nSeed();
if (ns < 0 || ns > 625) {
RError.warning(RError.NO_CALLER, RError.Message.GENERIC, "seed length must be in 0...625; ignored");
} else {
nSeeds = ns;
// TODO: if we ever (initially) share iSeed (as GNU R does) we may need to assign this
// generator's iSeed here
if (Function.NSeed.isDefined()) {
int ns = userRngRFFI.nSeed();
if (ns < 0 || ns > 625) {
RError.warning(RError.NO_CALLER, RError.Message.GENERIC, "seed length must be in 0...625; ignored");
} else {
nSeeds = ns;
/*
* TODO: if we ever (initially) share iSeed (as GNU R does) we may need to assign
* this generator's iSeed here
*/
}
}
}
......@@ -95,7 +121,7 @@ public final class UserRNG extends RNGInitAdapter {
@Override
public int[] getSeeds() {
if (userUnifSeedloc == 0) {
if (!Function.Seedloc.isDefined()) {
return null;
}
int[] result = new int[nSeeds];
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment