///|
fn eval_sign(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) =>
Number(if num < 0.0 { -1.0 } else if num > 0.0 { 1.0 } else { 0.0 })
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_seriessum(call : EvalCall) -> FormulaValue {
match call.values {
[v0, v1, v2, v3] => {
let x = match value_as_number(v0) {
Ok(num) => num
Err(err) => return err
}
let n = match value_as_number(v1) {
Ok(num) => num
Err(err) => return err
}
let m = match value_as_number(v2) {
Ok(num) => num
Err(err) => return err
}
let coefficients = list_from_value(v3)
let mut result = 0.0
let mut idx = 0.0
for coefficient in coefficients {
if formula_value_string(coefficient) == "" {
continue
}
let num = match value_as_number(coefficient) {
Ok(num) => num
Err(err) => return err
}
result = result + num * @math.pow(x, n + m * idx)
idx = idx + 1.0
}
Number(round_significant_digits(result, 15))
}
_ => Error(formula_error_value)
}
}
///|
fn eval_sumif(call : EvalCall) -> FormulaValue raise XlsxError {
match call.args {
[a0, _] | [a0, _, _] => {
let range_values = eval_range_expr(
call.workbook,
call.sheet_name,
a0,
call.ctx,
)
let sum_range = if call.args is [_, _, a2] {
Some(eval_range_expr(call.workbook, call.sheet_name, a2, call.ctx))
} else {
None
}
sumif_values(range_values, call.values[1], sum_range)
}
_ => Error(formula_error_value)
}
}
///|
fn eval_sumproduct(call : EvalCall) -> FormulaValue raise XlsxError {
if call.args.length() >= 1 {
let ranges : Array[RangeValues] = []
let scalars : Array[FormulaValue] = []
let mut has_range = false
let mut has_scalar = false
for i in 0.. {
has_range = true
ranges.push(
eval_range_expr(
call.workbook,
call.sheet_name,
call.args[i],
call.ctx,
),
)
}
_ =>
match call.values[i] {
Error(err) => return Error(err)
_ => {
has_scalar = true
scalars.push(call.values[i])
}
}
}
}
if has_range && has_scalar {
Error(formula_error_value)
} else if has_range {
sumproduct_values(ranges)
} else {
sumproduct_scalars(scalars)
}
} else {
Error(formula_error_value)
}
}
///|
fn eval_sumx2my2(call : EvalCall) -> FormulaValue raise XlsxError {
match call.args {
[a0, a1] => {
let left = eval_range_expr(call.workbook, call.sheet_name, a0, call.ctx)
let right = eval_range_expr(call.workbook, call.sheet_name, a1, call.ctx)
sumx_values("SUMX2MY2", left, right)
}
_ => Error(formula_error_value)
}
}
///|
fn eval_sumx2py2(call : EvalCall) -> FormulaValue raise XlsxError {
match call.args {
[a0, a1] => {
let left = eval_range_expr(call.workbook, call.sheet_name, a0, call.ctx)
let right = eval_range_expr(call.workbook, call.sheet_name, a1, call.ctx)
sumx_values("SUMX2PY2", left, right)
}
_ => Error(formula_error_value)
}
}
///|
fn eval_sumxmy2(call : EvalCall) -> FormulaValue raise XlsxError {
match call.args {
[a0, a1] => {
let left = eval_range_expr(call.workbook, call.sheet_name, a0, call.ctx)
let right = eval_range_expr(call.workbook, call.sheet_name, a1, call.ctx)
sumx_values("SUMXMY2", left, right)
}
_ => Error(formula_error_value)
}
}
///|
fn eval_sumifs(call : EvalCall) -> FormulaValue raise XlsxError {
if call.args.length() >= 3 {
if call.args.length() % 2 != 1 {
Error(formula_error_na)
} else {
let sum_range = eval_range_expr(
call.workbook,
call.sheet_name,
call.args[0],
call.ctx,
)
let ranges : Array[RangeValues] = []
let criterias : Array[FormulaCriteria] = []
for i in 0..<((call.args.length() - 1) / 2) {
let offset = 1 + i * 2
let range_values = eval_range_expr(
call.workbook,
call.sheet_name,
call.args[offset],
call.ctx,
)
ranges.push(range_values)
criterias.push(parse_formula_criteria(call.values[offset + 1]))
}
let matches = ifs_match(ranges, criterias)
let mut sum = 0.0
for cell in matches {
match sum_range.get(cell.row, cell.col) {
Some(value) =>
match value_as_number_opt(value) {
Some(num) => sum = sum + num
None => ()
}
None => return Error(formula_error_value)
}
}
Number(sum)
}
} else {
Error(formula_error_value)
}
}
///|
fn eval_combin(call : EvalCall) -> FormulaValue {
match call.values {
[v0, v1] =>
match (value_as_number(v0), value_as_number(v1)) {
(Ok(num), Ok(chosen)) => combin_values(num, chosen)
(Err(err), _) => err
(_, Err(err)) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_combina(call : EvalCall) -> FormulaValue {
match call.values {
[v0, v1] =>
match (value_as_number(v0), value_as_number(v1)) {
(Ok(num), Ok(chosen)) => {
let n = trunc_double(num)
let k = trunc_double(chosen)
if n < k {
Error(formula_error_value)
} else if n == 0.0 {
Number(n)
} else {
combin_values(n + k - 1.0, n - 1.0)
}
}
(Err(err), _) => err
(_, Err(err)) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_complex(call : EvalCall) -> FormulaValue {
match call.values {
[v0, v1] | [v0, v1, _] =>
match (value_as_number(v0), value_as_number(v1)) {
(Ok(real), Ok(imag)) => {
let mut suffix = "i"
if call.values is [_, _, v2] {
match value_as_string(v2) {
Ok(text) => {
let lower = text.to_lower()
if lower != "i" && lower != "j" {
return Error(formula_error_value)
}
suffix = lower
}
Err(err) => return err
}
}
String(complex_to_string(complex_new(real, imag), suffix))
}
(Err(err), _) => err
(_, Err(err)) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_fact(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) =>
if num < 0.0 {
Error(formula_error_num)
} else {
Number(factorial_double(num))
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_factdouble(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) =>
if num < 0.0 {
Error(formula_error_num)
} else {
Number(double_factorial_double(num))
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_mdeterm(call : EvalCall) -> FormulaValue raise XlsxError {
match call.values {
[v0] => {
let range = range_from_expr_or_value(
call.workbook,
call.sheet_name,
call.args[0],
v0,
call.ctx,
)
match number_matrix_from_range(range, true) {
Ok(matrix) => Number(matrix_det(matrix))
Err(err) => err
}
}
_ => Error(formula_error_value)
}
}
///|
fn eval_minverse(call : EvalCall) -> FormulaValue raise XlsxError {
match call.values {
[v0] => {
let range = range_from_expr_or_value(
call.workbook,
call.sheet_name,
call.args[0],
v0,
call.ctx,
)
match number_matrix_from_range(range, true) {
Ok(matrix) => {
let det_value = matrix_det(matrix)
if det_value == 0.0 {
Error(formula_error_num)
} else {
let adj = matrix_adjugate(matrix)
let scale = 1.0 / det_value
for row in 0.. err
}
}
_ => Error(formula_error_value)
}
}
///|
fn eval_mmult(call : EvalCall) -> FormulaValue raise XlsxError {
match call.values {
[v0, v1] =>
match (v0, v1) {
(Number(lhs), Number(rhs)) => Number(lhs * rhs)
_ => {
let left_range = range_from_expr_or_value(
call.workbook,
call.sheet_name,
call.args[0],
v0,
call.ctx,
)
let right_range = range_from_expr_or_value(
call.workbook,
call.sheet_name,
call.args[1],
v1,
call.ctx,
)
match
(
number_matrix_from_range(left_range, false),
number_matrix_from_range(right_range, false),
) {
(Ok(left), Ok(right)) =>
match matrix_multiply(left, right) {
Ok(matrix) => List(matrix_values(matrix))
Err(err) => err
}
(Err(err), _) => err
(_, Err(err)) => err
}
}
}
_ => Error(formula_error_value)
}
}
///|
fn eval_munit(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match munit_dimension(v0) {
Ok(dimension) => List(munit_range_values(dimension).values)
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_abs(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) => Number(abs_double(num))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_int(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) => Number(Double::floor(num))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_ln(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) => Number(@math.ln(num))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_exp(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) => Number(@math.exp(num))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_decimal(call : EvalCall) -> FormulaValue {
match call.values {
[v0, v1] =>
match (value_as_string(v0), value_as_number(v1)) {
(Ok(text), Ok(radix)) => {
let base = Double::to_int(trunc_double(radix))
let text_value = strip_hex_prefix(text)
let parsed = @string.parse_int(text_value, base~) catch {
_ => return Error(formula_error_value)
}
Number(Double::from_int(parsed))
}
(Err(err), _) => err
(_, Err(err)) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_roman(call : EvalCall) -> FormulaValue {
match call.values {
[v0] | [v0, _] =>
match value_as_number(v0) {
Ok(num) => {
let mut form = 0
if call.values is [_, v1] {
match value_as_number(v1) {
Ok(raw) => {
let mut mode = Double::to_int(trunc_double(raw))
if mode < 0 {
mode = 0
} else if mode > 4 {
mode = 4
}
form = mode
}
Err(err) => return err
}
}
String(roman_string(num, form))
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_arabic(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_string(v0) {
Ok(text) => arabic_string_value(text)
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_bin2dec(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(_) => bin2dec_string(formula_value_string(v0))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_bin2hex(call : EvalCall) -> FormulaValue {
match call.values {
[v0] | [v0, _] =>
match value_as_number(v0) {
Ok(_) => {
let decimal = bin2dec_string(formula_value_string(v0))
match decimal {
Error(_) => decimal
_ => {
let new_values : Array[FormulaValue] = [decimal]
if call.values is [_, places] {
new_values.push(places)
}
dec2x_values("BIN2HEX", new_values)
}
}
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_bin2oct(call : EvalCall) -> FormulaValue {
match call.values {
[v0] | [v0, _] =>
match value_as_number(v0) {
Ok(_) => {
let decimal = bin2dec_string(formula_value_string(v0))
match decimal {
Error(_) => decimal
_ => {
let new_values : Array[FormulaValue] = [decimal]
if call.values is [_, places] {
new_values.push(places)
}
dec2x_values("BIN2OCT", new_values)
}
}
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_hex2bin(call : EvalCall) -> FormulaValue {
match call.values {
[v0] | [v0, _] =>
match value_as_string(v0) {
Ok(text) => {
let decimal = hex2dec_string(text)
match decimal {
Error(_) => decimal
_ => {
let new_values : Array[FormulaValue] = [decimal]
if call.values is [_, places] {
new_values.push(places)
}
dec2x_values("HEX2BIN", new_values)
}
}
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_hex2dec(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_string(v0) {
Ok(text) => hex2dec_string(text)
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_hex2oct(call : EvalCall) -> FormulaValue {
match call.values {
[v0] | [v0, _] =>
match value_as_string(v0) {
Ok(text) => {
let decimal = hex2dec_string(text)
match decimal {
Error(_) => decimal
_ => {
let new_values : Array[FormulaValue] = [decimal]
if call.values is [_, places] {
new_values.push(places)
}
dec2x_values("HEX2OCT", new_values)
}
}
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_oct2bin(call : EvalCall) -> FormulaValue {
match call.values {
[v0] | [v0, _] =>
match value_as_number(v0) {
Ok(_) => {
let decimal = oct2dec_string(formula_value_string(v0))
let new_values : Array[FormulaValue] = [decimal]
if call.values is [_, places] {
new_values.push(places)
}
dec2x_values("OCT2BIN", new_values)
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_oct2dec(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(_) => oct2dec_string(formula_value_string(v0))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_oct2hex(call : EvalCall) -> FormulaValue {
match call.values {
[v0] | [v0, _] =>
match value_as_number(v0) {
Ok(_) => {
let decimal = oct2dec_string(formula_value_string(v0))
let new_values : Array[FormulaValue] = [decimal]
if call.values is [_, places] {
new_values.push(places)
}
dec2x_values("OCT2HEX", new_values)
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_besseli(call : EvalCall) -> FormulaValue {
match call.values {
[v0, v1] =>
match (value_as_number(v0), value_as_number(v1)) {
(Ok(x), Ok(n)) => number_or_num_error(bessel_i(x, n))
(Err(err), _) => err
(_, Err(err)) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_besselj(call : EvalCall) -> FormulaValue {
match call.values {
[v0, v1] =>
match (value_as_number(v0), value_as_number(v1)) {
(Ok(x), Ok(n)) => number_or_num_error(bessel_j(x, n))
(Err(err), _) => err
(_, Err(err)) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_besselk(call : EvalCall) -> FormulaValue {
match call.values {
[v0, v1] =>
match (value_as_number(v0), value_as_number(v1)) {
(Ok(x), Ok(n)) =>
if x <= 0.0 || n < 0.0 {
Error(formula_error_num)
} else {
let order = Double::floor(n)
let result = if order == 0.0 {
bessel_k0(x)
} else if order == 1.0 {
bessel_k1(x)
} else {
bessel_k2(x, n)
}
number_or_num_error(result)
}
(Err(err), _) => err
(_, Err(err)) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_bessely(call : EvalCall) -> FormulaValue {
match call.values {
[v0, v1] =>
match (value_as_number(v0), value_as_number(v1)) {
(Ok(x), Ok(n)) =>
if x <= 0.0 || n < 0.0 {
Error(formula_error_num)
} else {
let order = Double::floor(n)
let result = if order == 0.0 {
bessel_y0(x)
} else if order == 1.0 {
bessel_y1(x)
} else {
bessel_y2(x, n)
}
number_or_num_error(result)
}
(Err(err), _) => err
(_, Err(err)) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_delta(call : EvalCall) -> FormulaValue {
match call.values {
[v0] | [v0, _] => {
let number1 = match value_as_number(v0) {
Ok(num) => num
Err(err) => return err
}
let number2 = if call.values is [_, v1] {
match value_as_number(v1) {
Ok(num) => num
Err(err) => return err
}
} else {
0.0
}
Number(if number1 == number2 { 1.0 } else { 0.0 })
}
_ => Error(formula_error_value)
}
}
///|
fn eval_erf(call : EvalCall) -> FormulaValue {
match call.values {
[v0] | [v0, _] =>
match value_as_number(v0) {
Ok(lower) =>
if call.values is [_, v1] {
match value_as_number(v1) {
Ok(upper) =>
number_or_num_error(erf_double(upper) - erf_double(lower))
Err(err) => err
}
} else {
number_or_num_error(erf_double(lower))
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_erfdotprecise(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(value) => number_or_num_error(erf_double(value))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_erfc(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(value) => number_or_num_error(erfc_double(value))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_erfcdotprecise(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(value) => number_or_num_error(erfc_double(value))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_gestep(call : EvalCall) -> FormulaValue {
match call.values {
[v0] | [v0, _] => {
let number = match value_as_number(v0) {
Ok(num) => num
Err(err) => return err
}
let step = if call.values is [_, v1] {
match value_as_number(v1) {
Ok(num) => num
Err(err) => return err
}
} else {
0.0
}
Number(if number >= step { 1.0 } else { 0.0 })
}
_ => Error(formula_error_value)
}
}
///|
fn eval_acos(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) => number_or_num_error(@math.acos(num))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_acosh(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) => number_or_num_error(@math.acosh(num))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_acot(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) => number_or_num_error(@math.PI / 2.0 - @math.atan(num))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_acoth(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) => number_or_num_error(@math.atanh(1.0 / num))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_asin(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) => number_or_num_error(@math.asin(num))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_asinh(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) => number_or_num_error(@math.asinh(num))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_atan(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) => number_or_num_error(@math.atan(num))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_atanh(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) => number_or_num_error(@math.atanh(num))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_atan2(call : EvalCall) -> FormulaValue {
match call.values {
[v0, v1] =>
match (value_as_number(v0), value_as_number(v1)) {
(Ok(y), Ok(x)) => number_or_num_error(@math.atan2(x, y))
(Err(err), _) => err
(_, Err(err)) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_cos(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) => number_or_num_error(@math.cos(num))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_cosh(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) => number_or_num_error(@math.cosh(num))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_sin(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) => number_or_num_error(@math.sin(num))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_sinh(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) => number_or_num_error(@math.sinh(num))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_tan(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) => number_or_num_error(@math.tan(num))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_tanh(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) => number_or_num_error(@math.tanh(num))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_cot(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) =>
if num == 0.0 {
Error(formula_error_div)
} else {
number_or_num_error(1.0 / @math.tan(num))
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_coth(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) =>
if num == 0.0 {
Error(formula_error_div)
} else {
let exp_pos = @math.exp(num)
let exp_neg = @math.exp(-num)
number_or_num_error((exp_pos + exp_neg) / (exp_pos - exp_neg))
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_csc(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) =>
if num == 0.0 {
Error(formula_error_div)
} else {
number_or_num_error(1.0 / @math.sin(num))
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_csch(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) =>
if num == 0.0 {
Error(formula_error_div)
} else {
number_or_num_error(1.0 / @math.sinh(num))
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_sec(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) => number_or_num_error(@math.cos(num))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_sech(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) => number_or_num_error(1.0 / @math.cosh(num))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_degrees(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) =>
if num == 0.0 {
Error(formula_error_div)
} else {
Number(180.0 / @math.PI * num)
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_radians(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) => Number(@math.PI / 180.0 * num)
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_rand(call : EvalCall) -> FormulaValue {
match call.values {
[] => Number(formula_rand().double())
_ => Error(formula_error_value)
}
}
///|
fn eval_randbetween(call : EvalCall) -> FormulaValue {
match call.values {
[v0, v1] =>
match (value_as_number(v0), value_as_number(v1)) {
(Ok(bottom), Ok(top)) =>
if top < bottom {
Error(formula_error_num)
} else {
// Keep sampling overflow-safe for very wide bounds by staying in Double space.
let bottom_int = trunc_double(bottom)
let top_int = trunc_double(top)
let range = top_int - bottom_int + 1.0
let rand_value = Double::floor(formula_rand().double() * range)
Number(bottom_int + rand_value)
}
(Err(err), _) => err
(_, Err(err)) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_pi(call : EvalCall) -> FormulaValue {
match call.values {
[] => Number(@math.PI)
_ => Error(formula_error_value)
}
}
///|
fn eval_sqrtpi(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) => Number(@math.pow(num * @math.PI, 0.5))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_log(call : EvalCall) -> FormulaValue {
match call.values {
[v0] | [v0, _] =>
match value_as_number(v0) {
Ok(num) => {
let mut base = 10.0
if call.values is [_, v1] {
match value_as_number(v1) {
Ok(value) => base = value
Err(err) => return err
}
}
if num == 0.0 || base == 0.0 {
Error(formula_error_num)
} else if base == 1.0 {
Error(formula_error_div)
} else {
Number(@math.ln(num) / @math.ln(base))
}
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_log10(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) => Number(@math.log10(num))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_imabs(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match parse_complex_value(v0) {
Ok(num) =>
number_or_num_error(round_significant_digits(complex_abs(num), 15))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_imaginary(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match parse_complex_value(v0) {
Ok(num) => number_or_num_error(round_significant_digits(num.imag, 15))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_imargument(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match parse_complex_value(v0) {
Ok(num) =>
number_or_num_error(round_significant_digits(complex_arg(num), 15))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_imconjugate(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match parse_complex_value_with_suffix(v0) {
Ok((num, suffix)) =>
String(complex_to_string(complex_conj(num), suffix))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_imcos(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match parse_complex_value_with_suffix(v0) {
Ok((num, suffix)) => String(complex_to_string(complex_cos(num), suffix))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_imcosh(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match parse_complex_value_with_suffix(v0) {
Ok((num, suffix)) =>
String(complex_to_string(complex_cosh(num), suffix))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_imcot(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match parse_complex_value_with_suffix(v0) {
Ok((num, suffix)) =>
String(
complex_to_string(
complex_div(complex_cos(num), complex_sin(num)),
suffix,
),
)
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_imcsc(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match parse_complex_value_with_suffix(v0) {
Ok((num, suffix)) => {
let result = complex_div(complex_new(1.0, 0.0), complex_sin(num))
if complex_is_invalid(result) {
Error(formula_error_num)
} else {
String(complex_to_string(result, suffix))
}
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_imcsch(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match parse_complex_value_with_suffix(v0) {
Ok((num, suffix)) => {
let result = complex_div(complex_new(1.0, 0.0), complex_sinh(num))
if complex_is_invalid(result) {
Error(formula_error_num)
} else {
String(complex_to_string(result, suffix))
}
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_imdiv(call : EvalCall) -> FormulaValue {
match call.values {
[v0, v1] =>
match (parse_complex_value_with_suffix(v0), parse_complex_value(v1)) {
(Ok((left, suffix)), Ok(right)) => {
let result = complex_div(left, right)
if complex_is_invalid(result) {
Error(formula_error_num)
} else {
String(complex_to_string(result, suffix))
}
}
(Err(err), _) => err
(_, Err(err)) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_imexp(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match parse_complex_value_with_suffix(v0) {
Ok((num, suffix)) => String(complex_to_string(complex_exp(num), suffix))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_imln(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match parse_complex_value_with_suffix(v0) {
Ok((num, suffix)) => {
let result = complex_log(num)
if complex_is_invalid(result) {
Error(formula_error_num)
} else {
String(complex_to_string(result, suffix))
}
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_imlog10(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match parse_complex_value_with_suffix(v0) {
Ok((num, suffix)) => {
let result = complex_scale(complex_log(num), 1.0 / @math.ln(10.0))
if complex_is_invalid(result) {
Error(formula_error_num)
} else {
String(complex_to_string(result, suffix))
}
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_imlog2(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match parse_complex_value_with_suffix(v0) {
Ok((num, suffix)) => {
let result = complex_scale(complex_log(num), 1.0 / @math.ln(2.0))
if complex_is_invalid(result) {
Error(formula_error_num)
} else {
String(complex_to_string(result, suffix))
}
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_impower(call : EvalCall) -> FormulaValue {
match call.values {
[v0, v1] =>
match (parse_complex_value_with_suffix(v0), parse_complex_value(v1)) {
(Ok((base, suffix)), Ok(exponent)) =>
if base.real == 0.0 &&
base.imag == 0.0 &&
exponent.real == 0.0 &&
exponent.imag == 0.0 {
Error(formula_error_num)
} else {
let result = complex_pow(base, exponent)
if complex_is_invalid(result) {
Error(formula_error_num)
} else {
String(complex_to_string(result, suffix))
}
}
(Err(err), _) => err
(_, Err(err)) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_improduct(call : EvalCall) -> FormulaValue {
let mut product = complex_new(1.0, 0.0)
for value in flatten_values(call.values) {
match value {
Error(err) => return Error(err)
Empty => ()
Number(num) => product = complex_mul(product, complex_new(num, 0.0))
Bool(flag) => {
let num = if flag { 1.0 } else { 0.0 }
product = complex_mul(product, complex_new(num, 0.0))
}
String(text) =>
if text == "" {
()
} else {
match parse_complex_text(text) {
Ok(num) => product = complex_mul(product, num)
Err(err) => return err
}
}
List(_) => ()
}
}
String(complex_to_string(product, "i"))
}
///|
fn eval_imreal(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match parse_complex_value(v0) {
Ok(num) => String(format_number(num.real))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_imsec(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match parse_complex_value_with_suffix(v0) {
Ok((num, suffix)) => {
let result = complex_div(complex_new(1.0, 0.0), complex_cos(num))
String(complex_to_string(result, suffix))
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_imsech(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match parse_complex_value_with_suffix(v0) {
Ok((num, suffix)) => {
let result = complex_div(complex_new(1.0, 0.0), complex_cosh(num))
String(complex_to_string(result, suffix))
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_imsin(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match parse_complex_value_with_suffix(v0) {
Ok((num, suffix)) => String(complex_to_string(complex_sin(num), suffix))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_imsinh(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match parse_complex_value_with_suffix(v0) {
Ok((num, suffix)) =>
String(complex_to_string(complex_sinh(num), suffix))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_imsqrt(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match parse_complex_value_with_suffix(v0) {
Ok((num, suffix)) =>
String(complex_to_string(complex_sqrt(num), suffix))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_imsub(call : EvalCall) -> FormulaValue {
match call.values {
[v0, v1] =>
match (parse_complex_value(v0), parse_complex_value(v1)) {
(Ok(left), Ok(right)) =>
String(complex_to_string(complex_sub(left, right), "i"))
(Err(err), _) => err
(_, Err(err)) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_imsum(call : EvalCall) -> FormulaValue {
match call.values {
[_, ..] => {
let mut result = complex_new(0.0, 0.0)
for value in flatten_values(call.values) {
match value {
Error(err) => return Error(err)
_ =>
match parse_complex_value(value) {
Ok(num) => result = complex_add(result, num)
Err(err) => return err
}
}
}
String(complex_to_string(result, "i"))
}
[] => Error(formula_error_value)
}
}
///|
fn eval_imtan(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match parse_complex_value_with_suffix(v0) {
Ok((num, suffix)) => String(complex_to_string(complex_tan(num), suffix))
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_floor(call : EvalCall) -> FormulaValue {
match call.values {
[v0, v1] =>
match (value_as_number(v0), value_as_number(v1)) {
(Ok(num), Ok(significance)) =>
if significance < 0.0 && num >= 0.0 {
Error(formula_error_num)
} else {
let (whole, frac) = modf_double(num / significance)
let mut val = whole
if frac != 0.0 && num < 0.0 && frac < 0.0 {
val = val - 1.0
}
Number(val * significance)
}
(Err(err), _) => err
(_, Err(err)) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_ceiling(call : EvalCall) -> FormulaValue {
match call.values {
[v0] | [v0, _] =>
match value_as_number(v0) {
Ok(num) => {
let mut significance = if num < 0.0 { -1.0 } else { 1.0 }
if call.values is [_, v1] {
match value_as_number(v1) {
Ok(value) => significance = value
Err(err) => return err
}
}
if significance < 0.0 && num > 0.0 {
Error(formula_error_value)
} else if call.values is [_] {
Number(Double::ceil(num))
} else {
let (whole, frac) = modf_double(num / significance)
let mut val = whole
if frac > 0.0 {
val = val + 1.0
}
Number(val * significance)
}
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_ceilingdotmath(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) => Number(Double::ceil(num))
Err(err) => err
}
[v0, v1] | [v0, v1, _] =>
match value_as_number(v0) {
Ok(num) => {
let mut significance = if num < 0.0 { -1.0 } else { 1.0 }
let mut mode = 1.0
match value_as_number(v1) {
Ok(value) => significance = value
Err(err) => return err
}
if call.values is [_, _, v2] {
match value_as_number(v2) {
Ok(value) => mode = value
Err(err) => return err
}
}
let (whole, frac) = modf_double(num / significance)
let mut val = whole
if frac != 0.0 {
if num > 0.0 {
val = val + 1.0
} else if mode < 0.0 {
val = val - 1.0
}
}
Number(val * significance)
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_ceilingdotprecise(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) => Number(Double::ceil(num))
Err(err) => err
}
[v0, v1] =>
match value_as_number(v0) {
Ok(num) =>
match value_as_number(v1) {
Ok(significance) => {
let abs_significance = abs_double(significance)
if abs_significance == 0.0 {
Number(0.0)
} else {
let (whole, frac) = modf_double(num / abs_significance)
let mut val = whole
if frac != 0.0 && num > 0.0 {
val = val + 1.0
}
Number(val * abs_significance)
}
}
Err(err) => err
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_floordotmath(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) => Number(Double::floor(num))
Err(err) => err
}
[v0, v1] | [v0, v1, _] =>
match value_as_number(v0) {
Ok(num) => {
let mut significance = if num < 0.0 { -1.0 } else { 1.0 }
let mut mode = 1.0
match value_as_number(v1) {
Ok(value) => significance = value
Err(err) => return err
}
if call.values is [_, _, v2] {
match value_as_number(v2) {
Ok(value) => mode = value
Err(err) => return err
}
}
let (whole, frac) = modf_double(num / significance)
let mut val = whole
if frac != 0.0 && num < 0.0 && mode > 0.0 {
val = val - 1.0
}
Number(val * significance)
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_floordotprecise(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) => Number(Double::floor(num))
Err(err) => err
}
[v0, v1] =>
match value_as_number(v0) {
Ok(num) =>
match value_as_number(v1) {
Ok(significance) => {
let abs_significance = abs_double(significance)
if abs_significance == 0.0 {
Number(0.0)
} else {
let (whole, frac) = modf_double(num / abs_significance)
let mut val = whole
if frac != 0.0 && num < 0.0 {
val = val - 1.0
}
Number(val * abs_significance)
}
}
Err(err) => err
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_isodotceiling(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) => Number(Double::ceil(num))
Err(err) => err
}
[v0, v1] =>
match value_as_number(v0) {
Ok(num) =>
match value_as_number(v1) {
Ok(significance) => {
let abs_significance = abs_double(significance)
if abs_significance == 0.0 {
Number(0.0)
} else {
let (whole, frac) = modf_double(num / abs_significance)
let mut val = whole
if frac != 0.0 && num > 0.0 {
val = val + 1.0
}
Number(val * abs_significance)
}
}
Err(err) => err
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_trunc(call : EvalCall) -> FormulaValue {
match call.values {
[v0] | [v0, _] =>
match value_as_number(v0) {
Ok(num) => {
let digits = if call.values is [_, v1] {
match value_as_number(v1) {
Ok(value) => Double::to_int(value)
Err(err) => return err
}
} else {
0
}
Number(round_down_with_digits(num, digits))
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_round(call : EvalCall) -> FormulaValue {
match call.values {
[v0, v1] =>
match (value_as_number(v0), value_as_number(v1)) {
(Ok(num), Ok(digits)) =>
Number(round_with_digits(num, Double::to_int(digits)))
(Err(err), _) => err
(_, Err(err)) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_roundup(call : EvalCall) -> FormulaValue {
match call.values {
[v0, v1] =>
match (value_as_number(v0), value_as_number(v1)) {
(Ok(num), Ok(digits)) =>
Number(round_up_with_digits(num, Double::to_int(digits)))
(Err(err), _) => err
(_, Err(err)) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_rounddown(call : EvalCall) -> FormulaValue {
match call.values {
[v0, v1] =>
match (value_as_number(v0), value_as_number(v1)) {
(Ok(num), Ok(digits)) =>
Number(round_down_with_digits(num, Double::to_int(digits)))
(Err(err), _) => err
(_, Err(err)) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_sqrt(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) =>
if num < 0.0 {
Error(formula_error_num)
} else {
Number(@math.pow(num, 0.5))
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_power(call : EvalCall) -> FormulaValue {
match call.values {
[v0, v1] =>
match (value_as_number(v0), value_as_number(v1)) {
(Ok(lhs), Ok(rhs)) => Number(@math.pow(lhs, rhs))
(Err(err), _) => err
(_, Err(err)) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_even(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) => {
let sign = num < 0.0
let (whole, frac) = modf_double(num / 2.0)
let mut val = whole * 2.0
if frac != 0.0 {
if sign {
val = val - 2.0
} else {
val = val + 2.0
}
}
Number(val)
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_odd(call : EvalCall) -> FormulaValue {
match call.values {
[v0] =>
match value_as_number(v0) {
Ok(num) =>
if num == 0.0 {
Number(1.0)
} else {
let sign = num < 0.0
let (whole, frac) = modf_double((num - 1.0) / 2.0)
let mut val = whole * 2.0 + 1.0
if frac != 0.0 {
if sign {
val = val - 2.0
} else {
val = val + 2.0
}
}
Number(val)
}
Err(err) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_mround(call : EvalCall) -> FormulaValue {
match call.values {
[v0, v1] =>
match (value_as_number(v0), value_as_number(v1)) {
(Ok(num), Ok(multiple)) =>
if multiple == 0.0 {
Error(formula_error_num)
} else if (multiple < 0.0 && num > 0.0) ||
(multiple > 0.0 && num < 0.0) {
Error(formula_error_num)
} else {
let (whole, frac) = modf_double(num / multiple)
let mut rounded = whole
if trunc_double(frac + 0.5) > 0.0 {
rounded = rounded + 1.0
}
Number(rounded * multiple)
}
(Err(err), _) => err
(_, Err(err)) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_mod(call : EvalCall) -> FormulaValue {
match call.values {
[v0, v1] =>
match (value_as_number(v0), value_as_number(v1)) {
(Ok(num), Ok(divisor)) =>
if divisor == 0.0 {
Error(formula_error_div)
} else {
let quotient = num / divisor
let truncated = Double::floor(quotient)
Number(num - divisor * truncated)
}
(Err(err), _) => err
(_, Err(err)) => err
}
_ => Error(formula_error_value)
}
}
///|
fn eval_quotient(call : EvalCall) -> FormulaValue {
match call.values {
[v0, v1] =>
match (value_as_number(v0), value_as_number(v1)) {
(Ok(num), Ok(divisor)) =>
if divisor == 0.0 {
Error(formula_error_div)
} else {
Number(trunc_double(num / divisor))
}
(Err(err), _) => err
(_, Err(err)) => err
}
_ => Error(formula_error_value)
}
}