Permalink
Browse files

Smarter integer range generation for wide ranges

Also fix a typo in a test
  • Loading branch information...
1 parent 213bd73 commit 3c2ce0ea6664848a24c85284301118d75ac1d580 @manopapad committed May 25, 2012
Showing with 36 additions and 5 deletions.
  1. +1 −0 include/proper_internal.hrl
  2. +31 −1 src/proper_arith.erl
  3. +2 −2 src/proper_gen.erl
  4. +1 −1 test/ets_statem.erl
  5. +1 −1 test/proper_tests.erl
@@ -64,6 +64,7 @@
-define(ANY_SIMPLE_PROB, 3).
-define(ANY_BINARY_PROB, 1).
-define(ANY_EXPAND_PROB, 8).
+-define(SMALL_RANGE_THRESHOLD, 16#FFFF).
%%------------------------------------------------------------------------------
View
@@ -31,7 +31,7 @@
head_length/1, find_first/2, filter/2, partition/2, remove/2, insert/3,
unflatten/2]).
-export([rand_start/1, rand_reseed/0, rand_stop/0,
- rand_int/1, rand_int/2, rand_non_neg_int/1,
+ rand_int/1, rand_int/2, smart_rand_int/3, rand_non_neg_int/1,
rand_float/1, rand_float/2, rand_non_neg_float/1,
distribute/2, jumble/1, rand_choose/1, freq_choose/1]).
@@ -237,10 +237,40 @@ rand_int(Const) ->
rand_non_neg_int(Const) ->
trunc(rand_non_neg_float(Const)).
+-spec bounded_rand_non_neg_int(non_neg_integer(), non_neg_integer()) ->
+ non_neg_integer().
+bounded_rand_non_neg_int(Const, Lim) when is_integer(Lim), Lim >= 0 ->
+ X = rand_non_neg_int(Const),
+ case X > Lim of
+ true -> bounded_rand_non_neg_int(Const, Lim);
+ false -> X
+ end.
+
-spec rand_int(integer(), integer()) -> integer().
rand_int(Low, High) when is_integer(Low), is_integer(High), Low =< High ->
Low + ?RANDOM_MOD:uniform(High - Low + 1) - 1.
+%% When the range is large, skew the distribution to be more like that of an
+%% unbounded random integer.
+-spec smart_rand_int(non_neg_integer(), integer(), integer()) -> integer().
+smart_rand_int(Const, Low, High) ->
+ case High - Low =< ?SMALL_RANGE_THRESHOLD of
+ true -> rand_int(Low, High);
+ false -> wide_range_rand_int(Const, Low, High)
+ end.
+
+-spec wide_range_rand_int(non_neg_integer(), integer(), integer()) ->
+ integer().
+wide_range_rand_int(Const, Low, High) when Low >= 0 ->
+ Low + bounded_rand_non_neg_int(Const, High - Low);
+wide_range_rand_int(Const, Low, High) when High =< 0 ->
+ High - bounded_rand_non_neg_int(Const, High - Low);
+wide_range_rand_int(Const, Low, High) ->
+ case ?RANDOM_MOD:uniform(2) of
+ 1 -> smart_rand_int(Const, 0, High);
+ 2 -> smart_rand_int(Const, Low, 0)
+ end.
+
-spec rand_float(non_neg_integer()) -> float().
rand_float(Const) ->
X = rand_non_neg_float(Const),
View
@@ -341,8 +341,8 @@ integer_gen(Size, inf, High) ->
High - proper_arith:rand_non_neg_int(Size);
integer_gen(Size, Low, inf) ->
Low + proper_arith:rand_non_neg_int(Size);
-integer_gen(_Size, Low, High) ->
- proper_arith:rand_int(Low, High).
+integer_gen(Size, Low, High) ->
+ proper_arith:smart_rand_int(Size, Low, High).
%% @private
-spec float_gen(size(), proper_types:extnum(), proper_types:extnum()) ->
View
@@ -247,7 +247,7 @@ prop_parallel_ets() ->
set_up() ->
catch ets:delete(?TAB),
- Type = lists:nth(proper_arith:rand_int(4),
+ Type = lists:nth(proper_arith:rand_int(1, 4),
[set, ordered_set, bag, duplicate_bag]),
?TAB = ets:new(?TAB, [Type, public, named_table]).
View
@@ -666,7 +666,7 @@ dollar_data() ->
%% TODO: conversion of maybe_improper_list
%% TODO: use demo_is_instance and demo_translate_type
%% TODO: debug option to output tests passed, fail reason, etc.
-
+%% TODO: test expected distribution of random functions
simple_types_test_() ->
[?_test(assert_type_works(TD, true)) || TD <- simple_types_with_data()].

0 comments on commit 3c2ce0e

Please sign in to comment.