Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make max of Random methods inclusive rather than exclusive #8768

Merged
merged 4 commits into from
Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 16 additions & 19 deletions distribution/lib/Standard/Base/0.0.0-dev/src/Random.enso
Original file line number Diff line number Diff line change
Expand Up @@ -64,18 +64,18 @@ type Random

## GROUP Random
Return a random `Integer` between `min` (inclusive) and `max`
(exclusive).
(inclusive).

Arguments:
- min: The minimum value of the range to pick from (inclusive).
- max: The maximum value of the range to pick from (exclusive).
- max: The maximum value of the range to pick from (inclusive).

> Example
Generate an integer between 1 and 10.

import Standard.Base.Random.Random

i = Random.integer 1 11
i = Random.integer 1 10
integer : Integer -> Integer -> Integer ! Illegal_Argument
integer (min:Integer) (max:Integer) = Random_Generator.global_random_generator.integer min max

Expand Down Expand Up @@ -146,8 +146,8 @@ type Random
Return a `Date` within the specified `Date_Range`.

Arguments:
- start_date: The lower bound of the range to pick from (inclusive).
- end_date: The upper bound of the range to pick from (exclusive).
- min: The lower bound of the range to pick from (inclusive).
- max: The upper bound of the range to pick from (inclusive).

> Example
Generate a random date.
Expand All @@ -156,22 +156,19 @@ type Random

d = Random.date (Date.new 2023 03 01) (Date.new 2023 10 15)
date : Date -> Date -> Boolean -> Date
date start_date:Date end_date:Date end_exclusive=True = Random_Generator.global_random_generator.date start_date end_date end_exclusive
date min:Date max:Date = Random_Generator.global_random_generator.date min max

## GROUP Random
Return a `Time_Of_Day` between `start_time` and `end_time` (inclusive).

Arguments:
- start_time: The lower bound of the range to pick from (inclusive).
- end_time: The upper bound of the range to pick from (inclusive).
- min: The lower bound of the range to pick from (inclusive).
- max: The upper bound of the range to pick from (inclusive).

The generated time is at a granularity of 1 second. Random values are
generated for hours, minutes and seconds. The `nanoseconds` field is
always 0.

Note: the time range end is inclusive because it is impossible to specify
an end time after the last second of the day.

> Example
Generate a random time.

Expand All @@ -181,8 +178,8 @@ type Random
end = Time_Of_Day.new 9 40 2
t = Random.time start end
time : Time_Of_Day -> Time_Of_Day -> Time_Of_Day
time (start_time:Time_Of_Day=(Time_Of_Day.new 0 0 0)) (end_time:Time_Of_Day=(Time_Of_Day.new 23 59 59)) =
Random_Generator.global_random_generator.time start_time end_time
time (min:Time_Of_Day=(Time_Of_Day.new 0 0 0)) (max:Time_Of_Day=(Time_Of_Day.new 23 59 59)) =
Random_Generator.global_random_generator.time min max

## GROUP Random
Return a new UUID.
Expand Down Expand Up @@ -273,7 +270,7 @@ type Random_Generator
## PRIVATE
integer : Integer -> Integer -> Integer ! Illegal_Argument
integer self (min:Integer) (max:Integer) =
range = max - min
range = max - min + 1
if range >= Java_Integer.MAX_VALUE then Error.throw (Illegal_Argument.Error "Currently only integer ranges of up to 2^31-1 are supported.") else
min + (self.java_random.nextInt range)

Expand Down Expand Up @@ -301,16 +298,16 @@ type Random_Generator

## PRIVATE
date : Date -> Date -> Boolean -> Date
date self start_date:Date end_date:Date end_exclusive=True =
date_range = start_date.up_to end_date include_end=end_exclusive.not
date_range.at (self.integer 0 date_range.length)
date self start_date:Date end_date:Date =
date_range = start_date.up_to end_date include_end=True
date_range.at (self.integer 0 (date_range.length - 1))

## PRIVATE
time : Time_Of_Day -> Time_Of_Day -> Time_Of_Day
time self (start_time:Time_Of_Day=(Time_Of_Day.new 0 0 0)) (end_time:Time_Of_Day=(Time_Of_Day.new 23 59 59)) =
## The time range end is inclusive because it is impossible to specify
an end time after the last second of the day.
seconds = self.integer 0 (end_time.to_seconds - start_time.to_seconds + 1)
seconds = self.integer 0 (end_time.to_seconds - start_time.to_seconds)
start_time.date_add seconds Time_Period.Second

## PRIVATE
Expand All @@ -323,7 +320,7 @@ type Random_Generator
case with_replacement of
True ->
len = v.length
0.up_to count . map _-> v.at (self.integer 0 len)
0.up_to count . map _-> v.at (self.integer 0 (len - 1))
False ->
if count > v.length then Error.throw (Illegal_Argument.Error "`count` cannot be greater than the size of the collection when `with_replacement` is false") else
new_array = Random_Utils.sample v count self.java_random
Expand Down
25 changes: 10 additions & 15 deletions test/Base_Tests/src/Random_Spec.enso
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ import Standard.Test.Extensions
spec = Test.group "Random" <|
Test.specify "should allow generating random integers" <|
Random.set_seed 12345
Random.integer 0 100 . should_equal 51
Random.integer 0 10000 . should_equal 9080
Random.integer 0 99 . should_equal 51
Random.integer 0 9999 . should_equal 9080

random_range = 0.up_to 1000 . map (_-> Random.integer 0 100) . compute_bulk [Statistic.Minimum, Statistic.Maximum]
random_range = 0.up_to 1000 . map (_-> Random.integer 0 99) . compute_bulk [Statistic.Minimum, Statistic.Maximum]
(random_range.at 0 >= 0) . should_equal True
(random_range.at 1 <= 100) . should_equal True
(random_range.at 1 <= 99) . should_equal True

Test.specify "should allow generating random floats" <|
Random.set_seed 12345
Expand Down Expand Up @@ -71,17 +71,12 @@ spec = Test.group "Random" <|

Test.specify "should allow generating random dates" <|
Random.set_seed 4000
Random.date (Date.new 2023 03 01) (Date.new 2023 10 15) . should_equal (Date.new 2023 6 9)
Random.date (Date.new 2023 03 01) (Date.new 2023 10 15) . should_equal (Date.new 2023 7 16)
Random.date (Date.new 2023 03 01) (Date.new 2023 10 15) . should_equal (Date.new 2023 10 12)
Random.date (Date.new 2023 03 01) (Date.new 2023 10 14) . should_equal (Date.new 2023 6 9)
Random.date (Date.new 2023 03 01) (Date.new 2023 10 14) . should_equal (Date.new 2023 7 16)
Random.date (Date.new 2023 03 01) (Date.new 2023 10 14) . should_equal (Date.new 2023 10 12)

all_from_small_range = [Date.new 2023 03 01, Date.new 2023 03 02, Date.new 2023 03 03]
dates = 0.up_to 100 . map (_-> Random.date (Date.new 2023 03 01) (Date.new 2023 03 04))
dates.should_contain_the_same_elements_as all_from_small_range

Test.specify "should allow generating random dates, with end_exclusive=False" <|
all_from_small_range = [Date.new 2023 03 01, Date.new 2023 03 02, Date.new 2023 03 03, Date.new 2023 03 04]
dates = 0.up_to 100 . map (_-> Random.date (Date.new 2023 03 01) (Date.new 2023 03 04) end_exclusive=False)
dates = 0.up_to 100 . map (_-> Random.date (Date.new 2023 03 01) (Date.new 2023 03 03))
dates.should_contain_the_same_elements_as all_from_small_range

Test.specify "should allow generating random times" <|
Expand Down Expand Up @@ -148,13 +143,13 @@ spec = Test.group "Random" <|
permutations_2 . should_contain_the_same_elements_as all_permutations

Test.specify "should not allow using a too-large integer range" <|
high = 9223372036854775807000
high = 9223372036854775806999
Random.integer 0 high . should_fail_with Illegal_Argument

Test.specify "Can call an instance directly" <|
Random.new_generator . should_be_a Random_Generator
Random.new_generator 12345 . should_be_a Random_Generator
Random.new_generator 12345 . integer 0 100 . should_equal 51
Random.new_generator 12345 . integer 0 99 . should_equal 51
Random.new_generator 12345 . float . should_equal 0.3618031071604718 epsilon=0.00000001
Random.new_generator 12345 . gaussian . should_equal -0.187808989658912 epsilon=0.00000001

Expand Down
2 changes: 1 addition & 1 deletion test/Benchmarks/src/Map/Hash_Map.enso
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type Data
create n =
create_ints =
Vector.new n _->
Random.integer 0 (n.div 100)
Random.integer 0 ((n.div 100) - 1)
Data.Value create_ints

type Scenario
Expand Down
4 changes: 2 additions & 2 deletions test/Benchmarks/src/Table/Add_Row_Number.enso
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ options = Bench.options . set_warmup (Bench.phase_conf 2 2) . set_measure (Bench
create_table : Integer -> Table
create_table num_rows =
rng = Random.new_generator 42
x = Vector.new num_rows _-> rng.integer min=0 max=50
y = Vector.new num_rows _-> rng.integer min=0 max=10000
x = Vector.new num_rows _-> rng.integer min=0 max=49
y = Vector.new num_rows _-> rng.integer min=0 max=9999
t = Table.new [["X", x], ["Y", y]]

assert condition =
Expand Down
6 changes: 3 additions & 3 deletions test/Benchmarks/src/Table/Internal/Multi_Value_Key.enso
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ Comparable.from (_:My_Pair) = My_Pair_Comparator
create_table : Integer -> Table
create_table num_rows =
rng = Random.new_generator 42
x = Vector.new num_rows _-> rng.integer min=0 max=100
x = Vector.new num_rows _-> rng.integer min=0 max=99
y = Vector.new num_rows _-> rng.integer min=0 max=20 . to_text
z = Vector.new num_rows _->
a = Random.integer min=0 max=100
b = Random.integer min=0 max=100
a = Random.integer min=0 max=99
b = Random.integer min=0 max=99
My_Pair.Value a b
t = Table.new [["X", x], ["Y", y], ["Z", z]]

Expand Down
Loading