From c227c810f17a187c4379abd596a18a5123a1f65a Mon Sep 17 00:00:00 2001 From: adrian052 Date: Mon, 23 Sep 2024 12:58:54 -0600 Subject: [PATCH 1/3] Added rational fuzzers, rational(), rational_between(min,max), rational_at_most(max), rational_at_least(min) --- lib/aiken/fuzz.ak | 86 +++++++++++++++++++++++++++++++++++++ lib/aiken/fuzz.test.ak | 96 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 179 insertions(+), 3 deletions(-) diff --git a/lib/aiken/fuzz.ak b/lib/aiken/fuzz.ak index 054bf28..7d97a3d 100644 --- a/lib/aiken/fuzz.ak +++ b/lib/aiken/fuzz.ak @@ -2,6 +2,7 @@ use aiken/builtin use aiken/collection/list use aiken/math use aiken/option +use aiken/math/rational.{Rational, new, reduce} // ## Constructing // ### Primitives @@ -242,6 +243,91 @@ pub fn int_at_most(max: Int) -> Fuzzer { } } +/// Generate a random rational value. Generate across the range `[-255; 16383]` +/// with the following distribution: +/// [-255,-101] 0.1% +/// [-100,-1] 23.3% +/// [0, 100] 68.8% +/// [101,255] 4.9% +/// >255 3.0% +pub fn rational() -> Fuzzer{ + map(both(int(),int_at_least(1)), + fn((num,den)){ + expect Some(new_fraction) = new(num,den) + new_fraction + } + ) +} + +/// Generate rational values between a lower and upper bounds (both inclusive), with the folowing distribution: +/// [-255,-101] 31.1% +/// [-100,-1] 19.2% +/// [0, 100] 19.6% +/// [101,255] 30.1% +/// +/// The upper and lower bound must be between -255 and 255. +pub fn rational_between(opt_min: Option, opt_max: Option) -> Fuzzer { + expect Some(min) = opt_min + expect Some(max) = opt_max + expect True = correct_bounds(min, max) + if min == max { + expect Some(fraction) = new(rational.numerator(min), rational.denominator(min)) + constant(fraction) + }else if rational.compare(min, max) == Greater { + rational_between(Some(max),Some(min)) + }else{ + let denominator <- and_then(int_at_least(math.max(rational.denominator(min), rational.denominator(max))+1)) + let min_numerator = binary_search_min_numerator(min, denominator,-255*denominator, 255*denominator) + let max_numerator = binary_search_max_numerator(max, denominator, -255*denominator, 255*denominator) + map(int_between(min_numerator, max_numerator), fn(numerator){ + expect Some(fraction) = new(numerator, denominator) + reduce(fraction) + }) + } +} + +/// Generate a random rational value which is at least `opt_min`. +/// The lower bound must be between -255 and 255. +pub fn rational_at_least(opt_min: Option) -> Fuzzer{ + rational_between(opt_min, new(255,1)) +} + +/// Generate a random integer which is at most `opt_max`. +/// The upper bound must be between -255 and 255. +pub fn rational_at_most(opt_max: Option){ + rational_between(opt_max, new(-255,1)) +} + +fn correct_bounds(min_fraction: Rational, max_fraction: Rational) { + expect Some(min_bound) = new(-256, 1) + expect Some(max_bound) = new(256, 1) + (rational.compare(min_fraction,min_bound) == Greater && rational.compare(min_fraction,max_bound) == Less + && rational.compare(max_fraction,min_bound) == Greater && rational.compare(max_fraction,max_bound) == Less) +} + +fn binary_search_min_numerator(min_fraction: Rational, denominator: Int, left: Int, right: Int) -> Int { + let mid = (left + right) / 2 + expect Some(new_fraction) = new(mid, denominator) + if left > right { + left + } else if rational.compare(new_fraction, min_fraction) == Less { + binary_search_min_numerator(min_fraction, denominator, mid + 1, right) + } else { + binary_search_min_numerator(min_fraction, denominator, left, mid - 1) + } +} + +fn binary_search_max_numerator(max_fraction: Rational, denominator: Int, left: Int, right: Int) -> Int { + let mid = (left + right) / 2 + expect Some(new_fraction) = new(mid, denominator) + if left > right { + right + } else if rational.compare(new_fraction, max_fraction) == Greater { + binary_search_max_numerator(max_fraction, denominator, left, mid - 1) + } else { + binary_search_max_numerator(max_fraction, denominator, mid + 1, right) + } +} // ### Data-structures /// Generate a random list of elements from a given fuzzer. The list contains diff --git a/lib/aiken/fuzz.test.ak b/lib/aiken/fuzz.test.ak index 2fb11c7..56c1780 100644 --- a/lib/aiken/fuzz.test.ak +++ b/lib/aiken/fuzz.test.ak @@ -3,10 +3,12 @@ use aiken/fuzz.{ and_then, bool, byte, bytearray, constant, either3, either4, either5, either6, either7, either8, either9, int, int_between, label, list_between, list_with_elem, map, map2, map3, map4, map5, map6, map7, map8, map9, one_of, - set, set_between, sublist, such_that, tuple, tuple3, tuple4, tuple5, tuple6, - tuple7, tuple8, tuple9, + rational, rational_at_least, rational_at_most, rational_between, set, + set_between, sublist, such_that, tuple, tuple3, tuple4, tuple5, tuple6, tuple7, + tuple8, tuple9, } use aiken/math +use aiken/math/rational.{Rational} use aiken/primitive/bytearray use aiken/primitive/string @@ -20,7 +22,7 @@ test prop_int_distribution(n via int()) { @"0" } else if n < 256 { @"]0; 255]" - } else if n < 16383 { + } else if n <= 16383 { @"[256; 16383]" } else { fail @"n > 16383" @@ -207,6 +209,94 @@ test prop_set_between_distribution(n via set_between(int_between(0, 50), 3, 13)) True } +test rational_distribution(fraction via rational()) { + fraction_distribution(fraction) +} + +test prop_fraction_between_bounds( + fraction via rational_between(rational.new(-255, 1), rational.new(255, 1)), +) { + fraction_distribution(fraction) + + expect Some(min_bound) = rational.new(-255, 1) + expect Some(max_bound) = rational.new(255, 1) + + ( + rational.compare(fraction, min_bound) == Greater || rational.compare( + fraction, + min_bound, + ) == Equal + ) && ( + rational.compare(fraction, max_bound) == Less || rational.compare( + fraction, + max_bound, + ) == Equal + ) +} + +test prop_at_least_for_positive_fractions( + fraction via rational_at_least(rational.new(1, 1)), +) { + fraction_distribution(fraction) + + expect Some(min_bound) = rational.new(1, 1) + expect Some(max_bound) = rational.new(255, 1) + + ( + rational.compare(fraction, min_bound) == Greater || rational.compare( + fraction, + min_bound, + ) == Equal + ) && ( + rational.compare(fraction, max_bound) == Less || rational.compare( + fraction, + max_bound, + ) == Equal + ) +} + +test prop_at_most_for_negative_fraction( + fraction via rational_at_most(rational.new(0, 1)), +) { + fraction_distribution(fraction) + expect Some(min_bound) = rational.new(-255, 1) + expect Some(max_bound) = rational.new(0, 1) + ( + rational.compare(fraction, min_bound) == Greater || rational.compare( + fraction, + min_bound, + ) == Equal + ) && ( + rational.compare(fraction, max_bound) == Less || rational.compare( + fraction, + max_bound, + ) == Equal + ) +} + +fn fraction_distribution(fraction: Rational) { + expect Some(bound1) = rational.new(-255, 1) + expect Some(bound2) = rational.new(-100, 1) + expect Some(bound3) = rational.new(0, 1) + expect Some(bound4) = rational.new(100, 1) + expect Some(bound5) = rational.new(256, 1) + label( + if rational.compare(fraction, bound1) == Less { + fail + } else if rational.compare(fraction, bound2) == Less { + @"[-255,-101]" + } else if rational.compare(fraction, bound3) == Less { + @"[-100,-1]" + } else if rational.compare(fraction, bound4) == Less { + @"[0, 100]" + } else if rational.compare(fraction, bound5) == Less { + @"[101,255]" + } else { + @">255" + }, + ) +} + // This property simply illustrate a case where the `set` // fuzzer would fail and not loop forever after not being // able to satisfy the demand (not enough entropy in the From 86ac9b2157d171a7ff120cee8df24d76beb7cce6 Mon Sep 17 00:00:00 2001 From: adrian052 Date: Mon, 23 Sep 2024 16:58:14 -0600 Subject: [PATCH 2/3] Refactored variable names and adjusted formatting --- lib/aiken/fuzz.ak | 114 ++++++++++++++++++++++------------------- lib/aiken/fuzz.test.ak | 61 +++++++++++----------- 2 files changed, 90 insertions(+), 85 deletions(-) diff --git a/lib/aiken/fuzz.ak b/lib/aiken/fuzz.ak index 7d97a3d..b1a2864 100644 --- a/lib/aiken/fuzz.ak +++ b/lib/aiken/fuzz.ak @@ -243,89 +243,97 @@ pub fn int_at_most(max: Int) -> Fuzzer { } } -/// Generate a random rational value. Generate across the range `[-255; 16383]` -/// with the following distribution: +/// Generates a random rational value within the range `[-255, 16383]`, +/// following the specified distribution: /// [-255,-101] 0.1% /// [-100,-1] 23.3% /// [0, 100] 68.8% /// [101,255] 4.9% /// >255 3.0% -pub fn rational() -> Fuzzer{ - map(both(int(),int_at_least(1)), - fn((num,den)){ - expect Some(new_fraction) = new(num,den) - new_fraction +pub fn rational() -> Fuzzer { + map(both(int(), int_at_least(1)), + fn((numerator, denominator)) { + expect Some(fraction) = new(numerator, denominator) + fraction } ) } -/// Generate rational values between a lower and upper bounds (both inclusive), with the folowing distribution: -/// [-255,-101] 31.1% -/// [-100,-1] 19.2% -/// [0, 100] 19.6% -/// [101,255] 30.1% +/// Generates rational values between a lower and upper bound (both inclusive), with the following distribution: +/// [-255, -101] 31.1% +/// [-100, -1] 19.2% +/// [0, 100] 19.6% +/// [101, 255] 30.1% /// -/// The upper and lower bound must be between -255 and 255. -pub fn rational_between(opt_min: Option, opt_max: Option) -> Fuzzer { - expect Some(min) = opt_min - expect Some(max) = opt_max - expect True = correct_bounds(min, max) - if min == max { - expect Some(fraction) = new(rational.numerator(min), rational.denominator(min)) +/// The upper and lower bounds must be between -255 and 255. +pub fn rational_between(optional_min: Option, optional_max: Option) -> Fuzzer { + expect Some(lower_bound) = optional_min + expect Some(upper_bound) = optional_max + expect True = correct_bounds(lower_bound, upper_bound) + + if lower_bound == upper_bound { + expect Some(fraction) = new(rational.numerator(lower_bound), rational.denominator(lower_bound)) constant(fraction) - }else if rational.compare(min, max) == Greater { - rational_between(Some(max),Some(min)) - }else{ - let denominator <- and_then(int_at_least(math.max(rational.denominator(min), rational.denominator(max))+1)) - let min_numerator = binary_search_min_numerator(min, denominator,-255*denominator, 255*denominator) - let max_numerator = binary_search_max_numerator(max, denominator, -255*denominator, 255*denominator) - map(int_between(min_numerator, max_numerator), fn(numerator){ - expect Some(fraction) = new(numerator, denominator) + } else if rational.compare(lower_bound, upper_bound) == Greater { + rational_between(Some(upper_bound), Some(lower_bound)) + } else { + let denominator <- and_then(int_at_least(math.max(rational.denominator(lower_bound), rational.denominator(upper_bound)) + 1)) + let min_numerator = binary_search_min_numerator(lower_bound, denominator, -255 * denominator, 255 * denominator) + let max_numerator = binary_search_max_numerator(upper_bound, denominator, -255 * denominator, 255 * denominator) + map(int_between(min_numerator, max_numerator), fn(numerator) { + expect Some(fraction) = new(numerator, denominator) reduce(fraction) }) } } -/// Generate a random rational value which is at least `opt_min`. +/// Generates a random rational value that is at least `optional_min`. /// The lower bound must be between -255 and 255. -pub fn rational_at_least(opt_min: Option) -> Fuzzer{ - rational_between(opt_min, new(255,1)) +pub fn rational_at_least(optional_min: Option) -> Fuzzer { + rational_between(optional_min, new(255, 1)) } -/// Generate a random integer which is at most `opt_max`. +/// Generates a random rational value that is at most `opt_max`. /// The upper bound must be between -255 and 255. -pub fn rational_at_most(opt_max: Option){ - rational_between(opt_max, new(-255,1)) +pub fn rational_at_most(optional_max: Option) { + rational_between(optional_max, new(-255, 1)) } + fn correct_bounds(min_fraction: Rational, max_fraction: Rational) { - expect Some(min_bound) = new(-256, 1) - expect Some(max_bound) = new(256, 1) - (rational.compare(min_fraction,min_bound) == Greater && rational.compare(min_fraction,max_bound) == Less - && rational.compare(max_fraction,min_bound) == Greater && rational.compare(max_fraction,max_bound) == Less) + expect Some(lower_bound) = new(-256, 1) + expect Some(upper_bound) = new(256, 1) + + (rational.compare(min_fraction, lower_bound) == Greater + && rational.compare(min_fraction, upper_bound) == Less + && rational.compare(max_fraction, lower_bound) == Greater + && rational.compare(max_fraction, upper_bound) == Less) } -fn binary_search_min_numerator(min_fraction: Rational, denominator: Int, left: Int, right: Int) -> Int { - let mid = (left + right) / 2 - expect Some(new_fraction) = new(mid, denominator) - if left > right { - left - } else if rational.compare(new_fraction, min_fraction) == Less { - binary_search_min_numerator(min_fraction, denominator, mid + 1, right) + +fn binary_search_min_numerator(min_fraction: Rational, denominator: Int, low: Int, high: Int) -> Int { + let mid_point = (low + high) / 2 + expect Some(mid_fraction) = new(mid_point, denominator) + + if low > high { + low + } else if rational.compare(mid_fraction, min_fraction) == Less { + binary_search_min_numerator(min_fraction, denominator, mid_point + 1, high) } else { - binary_search_min_numerator(min_fraction, denominator, left, mid - 1) + binary_search_min_numerator(min_fraction, denominator, low, mid_point - 1) } } -fn binary_search_max_numerator(max_fraction: Rational, denominator: Int, left: Int, right: Int) -> Int { - let mid = (left + right) / 2 - expect Some(new_fraction) = new(mid, denominator) - if left > right { - right - } else if rational.compare(new_fraction, max_fraction) == Greater { - binary_search_max_numerator(max_fraction, denominator, left, mid - 1) +fn binary_search_max_numerator(max_fraction: Rational, denominator: Int, low: Int, high: Int) -> Int { + let mid_point = (low + high) / 2 + expect Some(mid_fraction) = new(mid_point, denominator) + + if low > high { + high + } else if rational.compare(mid_fraction, max_fraction) == Greater { + binary_search_max_numerator(max_fraction, denominator, low, mid_point - 1) } else { - binary_search_max_numerator(max_fraction, denominator, mid + 1, right) + binary_search_max_numerator(max_fraction, denominator, mid_point + 1, high) } } // ### Data-structures diff --git a/lib/aiken/fuzz.test.ak b/lib/aiken/fuzz.test.ak index 56c1780..55a1147 100644 --- a/lib/aiken/fuzz.test.ak +++ b/lib/aiken/fuzz.test.ak @@ -217,19 +217,17 @@ test prop_fraction_between_bounds( fraction via rational_between(rational.new(-255, 1), rational.new(255, 1)), ) { fraction_distribution(fraction) - - expect Some(min_bound) = rational.new(-255, 1) - expect Some(max_bound) = rational.new(255, 1) - + expect Some(lower_bound) = rational.new(-255, 1) + expect Some(upper_bound) = rational.new(255, 1) ( - rational.compare(fraction, min_bound) == Greater || rational.compare( + rational.compare(fraction, lower_bound) == Greater || rational.compare( fraction, - min_bound, + lower_bound, ) == Equal ) && ( - rational.compare(fraction, max_bound) == Less || rational.compare( + rational.compare(fraction, upper_bound) == Less || rational.compare( fraction, - max_bound, + upper_bound, ) == Equal ) } @@ -238,19 +236,17 @@ test prop_at_least_for_positive_fractions( fraction via rational_at_least(rational.new(1, 1)), ) { fraction_distribution(fraction) - - expect Some(min_bound) = rational.new(1, 1) - expect Some(max_bound) = rational.new(255, 1) - + expect Some(lower_bound) = rational.new(1, 1) + expect Some(upper_bound) = rational.new(255, 1) ( - rational.compare(fraction, min_bound) == Greater || rational.compare( + rational.compare(fraction, lower_bound) == Greater || rational.compare( fraction, - min_bound, + lower_bound, ) == Equal ) && ( - rational.compare(fraction, max_bound) == Less || rational.compare( + rational.compare(fraction, upper_bound) == Less || rational.compare( fraction, - max_bound, + upper_bound, ) == Equal ) } @@ -259,37 +255,38 @@ test prop_at_most_for_negative_fraction( fraction via rational_at_most(rational.new(0, 1)), ) { fraction_distribution(fraction) - expect Some(min_bound) = rational.new(-255, 1) - expect Some(max_bound) = rational.new(0, 1) + expect Some(lower_bound) = rational.new(-255, 1) + expect Some(upper_bound) = rational.new(0, 1) ( - rational.compare(fraction, min_bound) == Greater || rational.compare( + rational.compare(fraction, lower_bound) == Greater || rational.compare( fraction, - min_bound, + lower_bound, ) == Equal ) && ( - rational.compare(fraction, max_bound) == Less || rational.compare( + rational.compare(fraction, upper_bound) == Less || rational.compare( fraction, - max_bound, + upper_bound, ) == Equal ) } fn fraction_distribution(fraction: Rational) { - expect Some(bound1) = rational.new(-255, 1) - expect Some(bound2) = rational.new(-100, 1) - expect Some(bound3) = rational.new(0, 1) - expect Some(bound4) = rational.new(100, 1) - expect Some(bound5) = rational.new(256, 1) + expect Some(bound_1) = rational.new(-255, 1) + expect Some(bound_2) = rational.new(-100, 1) + expect Some(bound_3) = rational.new(0, 1) + expect Some(bound_4) = rational.new(100, 1) + expect Some(bound_5) = rational.new(256, 1) + label( - if rational.compare(fraction, bound1) == Less { + if rational.compare(fraction, bound_1) == Less { fail - } else if rational.compare(fraction, bound2) == Less { + } else if rational.compare(fraction, bound_2) == Less { @"[-255,-101]" - } else if rational.compare(fraction, bound3) == Less { + } else if rational.compare(fraction, bound_3) == Less { @"[-100,-1]" - } else if rational.compare(fraction, bound4) == Less { + } else if rational.compare(fraction, bound_4) == Less { @"[0, 100]" - } else if rational.compare(fraction, bound5) == Less { + } else if rational.compare(fraction, bound_5) == Less { @"[101,255]" } else { @">255" From af1b923759241c5001a606434823a958fb9cf684 Mon Sep 17 00:00:00 2001 From: KtorZ Date: Fri, 18 Apr 2025 18:27:04 +0200 Subject: [PATCH 3/3] minor style and API improvements for rationales. --- lib/aiken/fuzz.ak | 106 ++++++++++++++++++++++++++++------------- lib/aiken/fuzz.test.ak | 85 +++++++++++++++++---------------- 2 files changed, 115 insertions(+), 76 deletions(-) diff --git a/lib/aiken/fuzz.ak b/lib/aiken/fuzz.ak index b1a2864..e284606 100644 --- a/lib/aiken/fuzz.ak +++ b/lib/aiken/fuzz.ak @@ -1,8 +1,8 @@ use aiken/builtin use aiken/collection/list use aiken/math -use aiken/option use aiken/math/rational.{Rational, new, reduce} +use aiken/option // ## Constructing // ### Primitives @@ -251,11 +251,12 @@ pub fn int_at_most(max: Int) -> Fuzzer { /// [101,255] 4.9% /// >255 3.0% pub fn rational() -> Fuzzer { - map(both(int(), int_at_least(1)), + map( + both(int(), int_at_least(1)), fn((numerator, denominator)) { expect Some(fraction) = new(numerator, denominator) fraction - } + }, ) } @@ -266,55 +267,86 @@ pub fn rational() -> Fuzzer { /// [101, 255] 30.1% /// /// The upper and lower bounds must be between -255 and 255. -pub fn rational_between(optional_min: Option, optional_max: Option) -> Fuzzer { - expect Some(lower_bound) = optional_min - expect Some(upper_bound) = optional_max - expect True = correct_bounds(lower_bound, upper_bound) - +pub fn rational_between( + lower_bound: Rational, + upper_bound: Rational, +) -> Fuzzer { + expect correct_bounds(lower_bound, upper_bound) + if lower_bound == upper_bound { - expect Some(fraction) = new(rational.numerator(lower_bound), rational.denominator(lower_bound)) - constant(fraction) + lower_bound |> rational.reduce |> constant } else if rational.compare(lower_bound, upper_bound) == Greater { - rational_between(Some(upper_bound), Some(lower_bound)) + rational_between(upper_bound, lower_bound) } else { - let denominator <- and_then(int_at_least(math.max(rational.denominator(lower_bound), rational.denominator(upper_bound)) + 1)) - let min_numerator = binary_search_min_numerator(lower_bound, denominator, -255 * denominator, 255 * denominator) - let max_numerator = binary_search_max_numerator(upper_bound, denominator, -255 * denominator, 255 * denominator) - map(int_between(min_numerator, max_numerator), fn(numerator) { - expect Some(fraction) = new(numerator, denominator) - reduce(fraction) - }) + let denominator <- + and_then( + int_at_least( + math.max( + rational.denominator(lower_bound), + rational.denominator(upper_bound), + ) + 1, + ), + ) + + let min_numerator = + binary_search_min_numerator( + lower_bound, + denominator, + -255 * denominator, + 255 * denominator, + ) + let max_numerator = + binary_search_max_numerator( + upper_bound, + denominator, + -255 * denominator, + 255 * denominator, + ) + map( + int_between(min_numerator, max_numerator), + fn(numerator) { + expect Some(fraction) = new(numerator, denominator) + reduce(fraction) + }, + ) } } /// Generates a random rational value that is at least `optional_min`. /// The lower bound must be between -255 and 255. -pub fn rational_at_least(optional_min: Option) -> Fuzzer { - rational_between(optional_min, new(255, 1)) +pub fn rational_at_least(lower_bound: Rational) -> Fuzzer { + expect Some(upper_bound) = new(255, 1) + rational_between(lower_bound, upper_bound) } /// Generates a random rational value that is at most `opt_max`. /// The upper bound must be between -255 and 255. -pub fn rational_at_most(optional_max: Option) { - rational_between(optional_max, new(-255, 1)) +pub fn rational_at_most(upper_bound: Rational) { + expect Some(lower_bound) = new(-255, 1) + rational_between(lower_bound, upper_bound) } - fn correct_bounds(min_fraction: Rational, max_fraction: Rational) { expect Some(lower_bound) = new(-256, 1) expect Some(upper_bound) = new(256, 1) - (rational.compare(min_fraction, lower_bound) == Greater - && rational.compare(min_fraction, upper_bound) == Less - && rational.compare(max_fraction, lower_bound) == Greater - && rational.compare(max_fraction, upper_bound) == Less) + and { + rational.compare(min_fraction, lower_bound) == Greater, + rational.compare(min_fraction, upper_bound) == Less, + rational.compare(max_fraction, lower_bound) == Greater, + rational.compare(max_fraction, upper_bound) == Less, + } } - -fn binary_search_min_numerator(min_fraction: Rational, denominator: Int, low: Int, high: Int) -> Int { - let mid_point = (low + high) / 2 +fn binary_search_min_numerator( + min_fraction: Rational, + denominator: Int, + low: Int, + high: Int, +) -> Int { + let mid_point = ( low + high ) / 2 expect Some(mid_fraction) = new(mid_point, denominator) - + if low > high { low } else if rational.compare(mid_fraction, min_fraction) == Less { @@ -324,10 +356,15 @@ fn binary_search_min_numerator(min_fraction: Rational, denominator: Int, low: In } } -fn binary_search_max_numerator(max_fraction: Rational, denominator: Int, low: Int, high: Int) -> Int { - let mid_point = (low + high) / 2 +fn binary_search_max_numerator( + max_fraction: Rational, + denominator: Int, + low: Int, + high: Int, +) -> Int { + let mid_point = ( low + high ) / 2 expect Some(mid_fraction) = new(mid_point, denominator) - + if low > high { high } else if rational.compare(mid_fraction, max_fraction) == Greater { @@ -336,6 +373,7 @@ fn binary_search_max_numerator(max_fraction: Rational, denominator: Int, low: In binary_search_max_numerator(max_fraction, denominator, mid_point + 1, high) } } + // ### Data-structures /// Generate a random list of elements from a given fuzzer. The list contains diff --git a/lib/aiken/fuzz.test.ak b/lib/aiken/fuzz.test.ak index 55a1147..939dfa8 100644 --- a/lib/aiken/fuzz.test.ak +++ b/lib/aiken/fuzz.test.ak @@ -213,61 +213,62 @@ test rational_distribution(fraction via rational()) { fraction_distribution(fraction) } +fn expect_rational(numerator: Int, denominator: Int) -> Rational { + expect Some(r) = rational.new(numerator, denominator) + r +} + test prop_fraction_between_bounds( - fraction via rational_between(rational.new(-255, 1), rational.new(255, 1)), + fraction via rational_between( + expect_rational(-255, 1), + expect_rational(255, 1), + ), ) { fraction_distribution(fraction) - expect Some(lower_bound) = rational.new(-255, 1) - expect Some(upper_bound) = rational.new(255, 1) - ( - rational.compare(fraction, lower_bound) == Greater || rational.compare( - fraction, - lower_bound, - ) == Equal - ) && ( - rational.compare(fraction, upper_bound) == Less || rational.compare( - fraction, - upper_bound, - ) == Equal - ) + and { + { + let ord = rational.compare(fraction, expect_rational(-255, 1)) + ord == Greater || ord == Equal + }, + { + let ord = rational.compare(fraction, expect_rational(255, 1)) + ord == Less || ord == Equal + }, + } } test prop_at_least_for_positive_fractions( - fraction via rational_at_least(rational.new(1, 1)), + fraction via rational_at_least(expect_rational(1, 1)), ) { fraction_distribution(fraction) - expect Some(lower_bound) = rational.new(1, 1) - expect Some(upper_bound) = rational.new(255, 1) - ( - rational.compare(fraction, lower_bound) == Greater || rational.compare( - fraction, - lower_bound, - ) == Equal - ) && ( - rational.compare(fraction, upper_bound) == Less || rational.compare( - fraction, - upper_bound, - ) == Equal - ) + + and { + { + let ord = rational.compare(fraction, expect_rational(1, 1)) + ord == Greater || ord == Equal + }, + { + let ord = rational.compare(fraction, expect_rational(255, 1)) + ord == Less || ord == Equal + }, + } } test prop_at_most_for_negative_fraction( - fraction via rational_at_most(rational.new(0, 1)), + fraction via rational_at_most(expect_rational(0, 1)), ) { fraction_distribution(fraction) - expect Some(lower_bound) = rational.new(-255, 1) - expect Some(upper_bound) = rational.new(0, 1) - ( - rational.compare(fraction, lower_bound) == Greater || rational.compare( - fraction, - lower_bound, - ) == Equal - ) && ( - rational.compare(fraction, upper_bound) == Less || rational.compare( - fraction, - upper_bound, - ) == Equal - ) + + and { + { + let ord = rational.compare(fraction, expect_rational(-255, 1)) + ord == Greater || ord == Equal + }, + { + let ord = rational.compare(fraction, expect_rational(0, 1)) + ord == Less || ord == Equal + }, + } } fn fraction_distribution(fraction: Rational) {