Skip to content
Browse files

Allow to choose RNG at configure time

  • Loading branch information...
1 parent dcf5573 commit f824a98198d1826c0f1a816e9049fda93d59e709 @thomasc thomasc committed Apr 16, 2012
Showing with 88 additions and 15 deletions.
  1. +3 −0 README.md
  2. +55 −0 configure
  3. +11 −0 include/proper_internal.hrl
  4. +0 −4 rebar.config
  5. +1 −1 src/proper.app.src
  6. +7 −7 src/proper_arith.erl
  7. +11 −3 src/proper_gen.erl
View
3 README.md
@@ -84,6 +84,8 @@ Quickstart guide
* Compile PropEr: Run `make` (or `make all` if you also want to build the
documentation; in that case, you are going to need the `syntax_tools`
application and a recent version of `EDoc`).
+ Optionally sfmt-erlang can be selected as an alternative random number
+ generator using `./configure --use-sfmt` before running `make`.
* Add PropEr's base directory to your Erlang library path, using one of the
following methods:
1. `ERL_LIBS` environment variable: Add the following line to your shell
@@ -95,6 +97,7 @@ Quickstart guide
code:load_abs("/full/path/to/proper").
+ If using the sfmt RNG be sure to add /full/path/to/proper/deps/sfmt too.
* Add the following include line to all source files that contain properties:
-include_lib("proper/include/proper.hrl").
View
55 configure
@@ -0,0 +1,55 @@
+#! /bin/sh
+
+usage()
+{
+ echo "usage: $0 --use-fmt|--use-random"
+ exit 1
+}
+
+sfmt()
+{
+ echo "Using the sfmt-erlang random module"
+ grep -q sfmt rebar.config || cat >> rebar.config <<DONE
+{deps, [
+ {sfmt, ".*", {git, "https://github.com/jj1bdx/sfmt-erlang.git",
+ {branch, "master"}}}
+ ]}.
+DONE
+ grep -q USE_SFMT rebar.config || \
+ sed -i "s/debug_info/debug_info, {d, 'USE_SFMT'}/" rebar.config
+ grep -q sfmt src/proper.app.src || \
+ sed -i 's/stdlib/stdlib,sfmt/' src/proper.app.src
+}
+
+random()
+{
+ echo "Using Erlang's random module"
+ grep -q USE_SFMT rebar.config && \
+ sed -i "s/debug_info, {d, 'USE_SFMT'}/debug_info/" rebar.config
+ grep -q sfmt rebar.config && sed -i '/^{deps/,$d' rebar.config
+ grep -q sfmt src/proper.app.src && \
+ sed -i 's/stdlib,sfmt/stdlib/' src/proper.app.src
+}
+
+cleanup()
+{
+ rm -f ebin/*
+ rm -f .eunit/*
+}
+
+if [ $# -ne 1 ]; then
+ usage
+fi
+case $1 in
+ --use-sfmt)
+ cleanup
+ sfmt
+ ;;
+ --use-random)
+ cleanup
+ random
+ ;;
+ *)
+ usage
+ ;;
+esac
View
11 include/proper_internal.hrl
@@ -35,6 +35,17 @@
-compile({parse_transform, strip_types}).
-endif.
+%%------------------------------------------------------------------------------
+%% Random generator selection
+%%------------------------------------------------------------------------------
+
+-ifdef(USE_SFMT).
+-define(RANDOM_MOD, sfmt).
+-define(SEED_NAME, sfmt_seed).
+-else.
+-define(RANDOM_MOD, random).
+-define(SEED_NAME, random_seed).
+-endif.
%%------------------------------------------------------------------------------
%% Macros
View
4 rebar.config
@@ -36,7 +36,3 @@
{pre_hooks, [{compile, "make include/compile_flags.hrl"}]}.
{post_hooks, [{clean, "./clean_doc.sh"}]}.
-{deps, [
- {sfmt, ".*", {git, "https://github.com/jj1bdx/sfmt-erlang.git",
- {branch, "master"}}}
- ]}.
View
2 src/proper.app.src
@@ -26,5 +26,5 @@
[{description, "A QuickCheck-inspired property-based testing tool for Erlang"},
{vsn, "1.0"},
{registered, []},
- {applications, [compiler,kernel,stdlib,sfmt]},
+ {applications, [compiler,kernel,stdlib]},
{env, []}]}.
View
14 src/proper_arith.erl
@@ -213,20 +213,20 @@ remove_n(N, {List,Acc}) ->
%% calling any random function from this module.
-spec rand_start(seed()) -> 'ok'.
rand_start(Seed) ->
- _ = sfmt:seed(Seed),
+ _ = ?RANDOM_MOD:seed(Seed),
%% TODO: read option for RNG bijections here
ok.
-spec rand_reseed() -> 'ok'.
rand_reseed() ->
%% TODO: This should use the pid of the process somehow, in case two
%% spawned functions call it simultaneously?
- _ = sfmt:seed(now()),
+ _ = ?RANDOM_MOD:seed(now()),
ok.
-spec rand_stop() -> 'ok'.
rand_stop() ->
- erase(sfmt_seed),
+ erase(?SEED_NAME),
ok.
-spec rand_int(non_neg_integer()) -> integer().
@@ -239,26 +239,26 @@ rand_non_neg_int(Const) ->
-spec rand_int(integer(), integer()) -> integer().
rand_int(Low, High) when is_integer(Low), is_integer(High), Low =< High ->
- Low + sfmt:uniform(High - Low + 1) - 1.
+ Low + ?RANDOM_MOD:uniform(High - Low + 1) - 1.
-spec rand_float(non_neg_integer()) -> float().
rand_float(Const) ->
X = rand_non_neg_float(Const),
- case sfmt:uniform(2) of
+ case ?RANDOM_MOD:uniform(2) of
1 -> X;
2 -> -X
end.
-spec rand_non_neg_float(non_neg_integer()) -> float().
rand_non_neg_float(Const) when is_integer(Const), Const >= 0 ->
- case sfmt:uniform() of
+ case ?RANDOM_MOD:uniform() of
1.0 -> rand_non_neg_float(Const);
X -> Const * zero_one_to_zero_inf(X)
end.
-spec rand_float(float(), float()) -> float().
rand_float(Low, High) when is_float(Low), is_float(High), Low =< High ->
- Low + sfmt:uniform() * (High - Low).
+ Low + ?RANDOM_MOD:uniform() * (High - Low).
-spec zero_one_to_zero_inf(float()) -> float().
%% This function must return only non-negative values and map 0.0 to 0.0, but
View
14 src/proper_gen.erl
@@ -574,16 +574,24 @@ get_ret_type(Fun) ->
erase('$get_ret_type'),
RetType.
+-ifdef(USE_SFMT).
+update_seed(Seed) ->
+ sfmt:seed(Seed).
+-else.
+update_seed(Seed) ->
+ put(random_seed, Seed).
+-endif.
+
-spec function_body([term()], proper_types:type(), fun_seed()) ->
proper_types:type() | instance().
function_body(Args, RetType, {Seed1,Seed2}) ->
case get('$get_ret_type') of
true ->
RetType;
_ ->
- SavedSeed = get(sfmt_seed),
- sfmt:seed({Seed1,Seed2,erlang:phash2(Args,?SEED_RANGE)}),
+ SavedSeed = get(?SEED_NAME),
+ update_seed({Seed1,Seed2,erlang:phash2(Args,?SEED_RANGE)}),
Ret = clean_instance(generate(RetType)),
- put(sfmt_seed, SavedSeed),
+ put(?SEED_NAME, SavedSeed),
proper_symb:internal_eval(Ret)
end.

0 comments on commit f824a98

Please sign in to comment.
Something went wrong with that request. Please try again.