///|
/// Exact integer mathematics used by finite-domain model builders.
pub fn fm_abs(value : Int) -> Int {
if value < 0 {
-value
} else {
value
}
}
///|
pub fn fm_min(left : Int, right : Int) -> Int {
if left < right {
left
} else {
right
}
}
///|
pub fn fm_max(left : Int, right : Int) -> Int {
if left > right {
left
} else {
right
}
}
///|
pub fn fm_clamp(value : Int, lower : Int, upper : Int) -> Int {
if value < lower {
lower
} else if value > upper {
upper
} else {
value
}
}
///|
pub fn fm_gcd(left : Int, right : Int) -> Int {
let mut a = fm_abs(left)
let mut b = fm_abs(right)
while b != 0 {
let temporary = a % b
a = b
b = temporary
}
a
}
///|
pub fn fm_lcm(left : Int, right : Int) -> Int {
if left == 0 || right == 0 {
0
} else {
fm_abs(left / fm_gcd(left, right) * right)
}
}
///|
pub fn fm_sign(value : Int) -> Int {
if value < 0 {
-1
} else if value > 0 {
1
} else {
0
}
}
///|
pub fn fm_factorial(value : Int) -> Int {
let mut result = 1
if value < 0 {
return 0
}
for current in 2..<(value + 1) {
result *= current
}
result
}
///|
pub fn fm_choose(n : Int, k : Int) -> Int {
if n < 0 || k < 0 || k > n {
return 0
}
let reduced = if k > n - k { n - k } else { k }
let mut result = 1
for current in 1..<(reduced + 1) {
result = result * (n - reduced + current) / current
}
result
}
///|
pub fn fm_pow(base : Int, exponent : Int) -> Int {
if exponent < 0 {
return 0
}
let mut result = 1
for _ in 0.. Int {
if right == 0 {
return 0
}
let quotient = left / right
let remainder = left % right
if remainder != 0 && (remainder > 0) != (right > 0) {
quotient - 1
} else {
quotient
}
}
///|
pub fn fm_ceil_div(left : Int, right : Int) -> Int {
if right == 0 {
return 0
}
let quotient = left / right
let remainder = left % right
if remainder != 0 && (remainder > 0) == (right > 0) {
quotient + 1
} else {
quotient
}
}
///|
pub fn fm_range_sum(lower : Int, upper : Int) -> Int {
if lower > upper {
0
} else {
(lower + upper) * (upper - lower + 1) / 2
}
}
///|
pub fn fm_arithmetic_mean(left : Int, right : Int) -> Int {
(left + right) / 2
}
///|
pub fn fm_midpoint(lower : Int, upper : Int) -> Int {
lower + (upper - lower) / 2
}
///|
pub fn fm_distance(left : Int, right : Int) -> Int {
fm_abs(left - right)
}
///|
pub fn fm_is_even(value : Int) -> Bool {
value % 2 == 0
}
///|
pub fn fm_is_odd(value : Int) -> Bool {
value % 2 != 0
}
///|
pub fn fm_is_prime(value : Int) -> Bool {
if value < 2 {
return false
}
let mut divisor = 2
while divisor * divisor <= value {
if value % divisor == 0 {
return false
}
divisor += 1
}
true
}
///|
pub fn fm_next_prime(value : Int) -> Int {
let mut candidate = if value < 2 { 2 } else { value }
while !fm_is_prime(candidate) {
candidate += 1
}
candidate
}
///|
pub fn fm_count_primes(lower : Int, upper : Int) -> Int {
let mut result = 0
for value in lower..<(upper + 1) {
if fm_is_prime(value) {
result += 1
}
}
result
}
///|
pub fn fm_dot(left : Array[Int], right : Array[Int]) -> Int {
let limit = if left.length() < right.length() {
left.length()
} else {
right.length()
}
let mut result = 0
for index in 0.. Int {
let mut result = 0
for value in values {
result += fm_abs(value)
}
result
}
///|
pub fn fm_linf(values : Array[Int]) -> Int {
let mut result = 0
for value in values {
if fm_abs(value) > result {
result = fm_abs(value)
}
}
result
}
///|
pub fn fm_range(values : Array[Int]) -> Int {
if values.length() == 0 {
0
} else {
integer_summary(values).maximum - integer_summary(values).minimum
}
}
///|
pub fn fm_weighted_sum(values : Array[Int], weights : Array[Int]) -> Int {
fm_dot(values, weights)
}
///|
pub fn fm_weighted_average(values : Array[Int], weights : Array[Int]) -> Int {
let total = integer_sum(weights)
if total == 0 {
0
} else {
fm_dot(values, weights) / total
}
}
///|
pub fn fm_prefix(values : Array[Int]) -> Array[Int] {
sequence_cumulative(values)
}
///|
pub fn fm_suffix(values : Array[Int]) -> Array[Int] {
let result : Array[Int] = []
let mut total = 0
let input_last = values.length() - 1
for index in input_last>=..0 {
total += values[index]
result.push(total)
}
let last = result.length() - 1
let half = result.length() / 2
for index in 0.. Array[Int] {
let result : Array[Int] = []
if values.length() == 0 {
return result
}
let shift = fm_mod_positive(offset, values.length())
for index in 0.. Array[Int] {
let result : Array[Int] = []
let last = values.length() - 1
for index in last>=..0 {
result.push(values[index])
}
result
}
///|
pub fn fm_take(values : Array[Int], count : Int) -> Array[Int] {
let result : Array[Int] = []
let limit = if count < 0 {
0
} else if count > values.length() {
values.length()
} else {
count
}
for index in 0.. Array[Int] {
let result : Array[Int] = []
let start = if count < 0 {
0
} else if count > values.length() {
values.length()
} else {
count
}
for index in start.. Array[Array[Int]] {
let result : Array[Array[Int]] = []
if size <= 0 {
return result
}
let mut start = 0
while start < values.length() {
let row : Array[Int] = []
let end = if start + size > values.length() {
values.length()
} else {
start + size
}
for index in start.. Int {
let mut result = 0
for value in values {
if value == target {
result += 1
}
}
result
}
///|
pub fn fm_contains_all(values : Array[Int], required : Array[Int]) -> Bool {
for value in required {
if !values.contains(value) {
return false
}
}
true
}
///|
pub fn fm_unique(values : Array[Int]) -> Array[Int] {
integer_set(values).values()
}
///|
pub fn fm_union(left : Array[Int], right : Array[Int]) -> Array[Int] {
integer_set(left).union(integer_set(right)).values()
}
///|
pub fn fm_intersection(left : Array[Int], right : Array[Int]) -> Array[Int] {
integer_set(left).intersection(integer_set(right)).values()
}
///|
pub fn fm_difference(left : Array[Int], right : Array[Int]) -> Array[Int] {
integer_set(left).difference(integer_set(right)).values()
}
///|
pub fn fm_argmin(values : Array[Int]) -> Int? {
if values.length() == 0 {
return None
}
let mut result = 0
for index in 1.. Int? {
if values.length() == 0 {
return None
}
let mut result = 0
for index in 1.. values[result] {
result = index
}
}
Some(result)
}
///|
pub fn fm_rank(value : Int, values : Array[Int]) -> Int {
let mut result = 0
for candidate in values {
if candidate < value {
result += 1
}
}
result
}
///|
pub fn fm_quantize(value : Int, step : Int) -> Int {
if step <= 0 {
value
} else {
fm_floor_div(value, step) * step
}
}
///|
pub fn fm_bucket(value : Int, lower : Int, width : Int) -> Int {
if width <= 0 {
0
} else {
fm_floor_div(value - lower, width)
}
}
///|
pub fn fm_interpolate(
left : Int,
right : Int,
numerator : Int,
denominator : Int,
) -> Int {
if denominator == 0 {
left
} else {
left + (right - left) * numerator / denominator
}
}
///|
pub fn fm_percent(value : Int, total : Int) -> Int {
if total == 0 {
0
} else {
value * 100 / total
}
}
///|
pub fn fm_saturating_add(left : Int, right : Int, upper : Int) -> Int {
let value = left + right
if value > upper {
upper
} else {
value
}
}
///|
pub fn fm_saturating_sub(left : Int, right : Int, lower : Int) -> Int {
let value = left - right
if value < lower {
lower
} else {
value
}
}
///|
pub fn fm_signum_sum(values : Array[Int]) -> Int {
let mut result = 0
for value in values {
result += fm_sign(value)
}
result
}
///|
pub fn fm_alternating_sum(values : Array[Int]) -> Int {
let mut result = 0
for index, value in values {
if fm_is_even(index) {
result += value
} else {
result -= value
}
}
result
}
///|
pub fn fm_mod_positive(value : Int, modulus : Int) -> Int {
if modulus <= 0 {
0
} else {
let result = value % modulus
if result < 0 {
result + modulus
} else {
result
}
}
}
///|
pub fn fm_wrap(value : Int, lower : Int, upper : Int) -> Int {
if lower > upper {
lower
} else {
lower + fm_mod_positive(value - lower, upper - lower + 1)
}
}
///|
pub fn fm_clamp_array(
values : Array[Int],
lower : Int,
upper : Int,
) -> Array[Int] {
values.map(value => fm_clamp(value, lower, upper))
}
///|
pub fn fm_map_sign(values : Array[Int]) -> Array[Int] {
values.map(value => fm_sign(value))
}
///|
pub fn fm_nonzero(values : Array[Int]) -> Array[Int] {
let result : Array[Int] = []
for value in values {
if value != 0 {
result.push(value)
}
}
result
}
///|
pub fn fm_repeat(value : Int, count : Int) -> Array[Int] {
let result : Array[Int] = []
for _ in 0.. Array[Int] {
let result : Array[Int] = []
for value in 0.. Bool {
if values.length() != size {
return false
}
for value in 0.. Int {
let mut inversions = 0
for left in 0.. values[right] {
inversions += 1
}
}
}
inversions % 2
}
///|
pub fn fm_swap(values : Array[Int], left : Int, right : Int) -> Bool {
if left < 0 ||
right < 0 ||
left >= values.length() ||
right >= values.length() {
return false
}
let temporary = values[left]
values[left] = values[right]
values[right] = temporary
true
}
///|
pub fn fm_sorted(values : Array[Int]) -> Array[Int] {
let result = values.copy()
sort_integers(result)
result
}
///|
pub fn fm_is_sorted(values : Array[Int]) -> Bool {
for index in 1.. Bool {
for index in 1.. Int {
let mut result = 0
for index, value in left {
let other = if index < right.length() { right[index] } else { 0 }
result += fm_abs(value - other)
}
result
}
///|
pub fn fm_hamming(left : Array[Int], right : Array[Int]) -> Int {
assignment_hamming_distance(left, right)
}
///|
pub fn fm_checksum(values : Array[Int]) -> Int {
sequence_checksum(values)
}