Merge remote-tracking branch 'nickva/fix-int-range-shrink'
diff --git a/THANKS b/THANKS
index c5e9548..8d28b98 100644
--- a/THANKS
+++ b/THANKS
@@ -17,3 +17,4 @@
Zachary Kessin
Krzysztof Jurewicz
Harlan Lieberman-Berg
+Nick Vatamaniuc
diff --git a/src/triq_dom.erl b/src/triq_dom.erl
index fb853c3..6d7a1e7 100644
--- a/src/triq_dom.erl
+++ b/src/triq_dom.erl
@@ -105,7 +105,7 @@
-record(noshrink, {dom}).
-record(suchthat,{dom,pred}).
-record(bound_domain,{dom1,val1,dom2,fun2,size}).
--record(choose,{min,max}).
+-record(choose,{min,max,shrinkto}).
-record(elements,{elems,size,picked=none}).
-record(seal,{dom,seed}).
-record(unicode_binary, {size, encoding = utf8}).
@@ -597,19 +597,10 @@
}.
int(Max) ->
- int(0, Max).
+ choose(0, Max).
int(Min, Max) ->
- Diff = Max - Min,
- #?DOM{kind=int,
- shrink=fun(Dom,Val) when Val>0 -> {Dom,Val-1};
- (Dom,Val) when Val<0 -> {Dom,Val+1};
- (Dom,0) -> {Dom,0}
- end,
- pick=fun(Dom,_SampleSize) ->
- {Dom, triq_rnd:uniform(Diff) + Min}
- end
- }.
+ choose(Min, Max).
-spec byte() -> domrec(integer()).
@@ -1185,7 +1176,12 @@
-spec choose(M::integer(), N::integer()) -> domrec(integer()).
choose(M,N) when is_integer(M), is_integer(N), M=<N ->
- #?DOM{kind={choose,M,N},
+ ShrinkTo = case {M>=0, N>=0} of
+ {true, true} -> M;
+ {false, true} -> 0;
+ {false, false} -> N
+ end,
+ #?DOM{kind=#choose{min=M,max=N,shrinkto=ShrinkTo},
pick = fun choose_pick/2,
shrink = fun choose_shrink/2
}.
@@ -1194,9 +1190,28 @@
Value = triq_rnd:uniform(N-M+1) - 1 + M,
{Dom,Value}.
-choose_shrink(#?DOM{kind=#choose{min=M}}=Dom, Value) ->
- Mid = (Value - M) div 2,
- {Dom, M + Mid}.
+choose_shrink(#?DOM{kind=#choose{shrinkto=Value}}=Dom, Value) ->
+ {Dom, Value};
+choose_shrink(#?DOM{kind=#choose{shrinkto=ShrinkTo}}=Dom, Value) ->
+ DecrementProb = 2 * math:exp(-0.1 * abs(Value - ShrinkTo)),
+ case triq_rnd:uniform() < DecrementProb of
+ true ->
+ {Dom, choose_shrink_by_decrement(Value, ShrinkTo)};
+ false ->
+ {Dom, choose_shrink_by_half(Value, ShrinkTo)}
+ end.
+
+choose_shrink_by_half(Value, ShrinkTo) ->
+ Mid = (Value - ShrinkTo) div 2,
+ ShrinkTo + Mid.
+
+choose_shrink_by_decrement(Value, ShrinkTo) when Value > ShrinkTo ->
+ Value - 1;
+choose_shrink_by_decrement(Value, ShrinkTo) when Value < ShrinkTo ->
+ Value + 1;
+choose_shrink_by_decrement(Value, Value) ->
+ Value.
+
%% @doc Generates a member of the list `L'. Shrinks towards the first element
%% of the list.
diff --git a/test/triq_tests.erl b/test/triq_tests.erl
index 3dc077a..40cbc27 100644
--- a/test/triq_tests.erl
+++ b/test/triq_tests.erl
@@ -219,7 +219,14 @@
choose_test_() ->
[?_assertEqual([3], triq:counterexample(?FORALL(_, choose(3,7), false))),
?_assertEqual([7], triq:counterexample(?FORALL(I, choose(3,7), I < 7))),
- ?_assertEqual([3], triq:counterexample(?FORALL(_, choose(3,3), false)))].
+ ?_assertEqual([3], triq:counterexample(?FORALL(_, choose(3,3), false))),
+ ?_assertEqual([0], triq:counterexample(?FORALL(_, choose(-3,7), false))),
+ ?_assertEqual([-3], triq:counterexample(?FORALL(_, choose(-7,-3), false))),
+ ?_assertEqual([0], triq:counterexample(?FORALL(_, choose(-3,0), false))),
+ ?_assertEqual([0], triq:counterexample(?FORALL(_, choose(0,3), false))),
+ ?_assertEqual([1], triq:counterexample(?FORALL(_, choose(1,100), false))),
+ ?_assertEqual([5], triq:counterexample(?FORALL(_, choose(5,1 bsl 80), false))),
+ ?_assertException(error, function_clause, choose(7,3))].
%%
%% Test binary shrinking