Skip to content
Open
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
2 changes: 1 addition & 1 deletion src/formatting.typ
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@
sign: none,
int: int,
frac: frac,
digits: it.digits,
digits: auto,
group: false,
positive-sign: false,
decimal-separator: it.decimal-separator,
Expand Down
25 changes: 14 additions & 11 deletions src/num.typ
Original file line number Diff line number Diff line change
Expand Up @@ -117,27 +117,30 @@
}

/// Round number and uncertainty
if it.round.precision != none {
(info.int, info.frac, info.pm) = round(
if info.pm != none and it.round.follow-uncertainty {
(info.int, info.frac, info.pm) = round-to-uncertainty(
info.int,
info.frac,
pm: info.pm,
info.pm,
sign: info.sign,
..it.round,
precision: it.round.uncertainty-precision,
)
} else {
if it.round.precision != none {
(info.int, info.frac) = round(
info.int,
info.frac,
sign: info.sign,
..it.round,
)
}
}

let digits = if it.digits == auto { info.frac.len() } else { it.digits }
if digits < 0 {
assert(false, message: "`digits` needs to be positive, got " + str(digits))
}

if info.pm != none {
let pm = info.pm
if type(pm.first()) != array { pm = (pm,) }
digits = calc.max(digits, ..pm.map(array.last).map(str.len))
}

// info.digits = digits
it.digits = digits

// Format number
Expand Down
148 changes: 96 additions & 52 deletions src/rounding.typ
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@


/// Rounds (and/or pads) a number given by an integer part and a fractional
/// part. Several rounding modes are supported.
/// part.
#let round(

/// Integer part.
Expand All @@ -216,15 +216,11 @@
/// - `"places"`: The number is rounded to the number of places after the
/// decimal point given by the `precision` parameter.
/// - `"figures"`: The number is rounded to a number of significant figures.
/// - `"uncertainty"`: Requires giving the uncertainty. The uncertainty is
/// rounded to significant figures given by the `precision` argument and
/// then the number is rounded to the same number of places as the
/// uncertainty.
mode: "places",

/// The precision to round to. See parameter `mode` for the different modes.
/// If set to `none`, no rounding is performed.
/// -> int | none
/// If set to `auto` or `none`, no rounding is performed.
/// -> int | auto | none
precision: 2,

/// Rounding direction.
Expand All @@ -242,19 +238,15 @@
/// -> bool | int
pad: true,

/// Uncertainty
pm: none,
..

) = {
if precision == none {
return (int, frac, pm)
}
if mode == "uncertainty" and pm == none {
return (int, frac, pm)
if precision in (auto, none) {
return (int, frac)
}


assert-option(mode, "round-mode", ("places", "figures", "uncertainty"))
assert-option(mode, "round-mode", ("places", "figures"))

// Removal hint
if direction == "down" {
Expand All @@ -277,55 +269,107 @@
))


if mode == "uncertainty" {
// Round uncertainties to `precision` figures.
pad-decimal(
..round-decimal(
int, frac,
precision: precision,
mode: mode,
dir: direction,
sign: sign,
ties: ties,
),
pad, mode, precision
)
}

let is-symmetric = type(pm.first()) != array
if is-symmetric {
pm = (pm,)
}

/// Find the (fractional) place of the smallest uncertainty
let places = precision + calc.max(
..pm.map(((i, f)) => count-leading-zeros(i + f) - i.len())
)

pm = pm
.map(((i, f)) => round-decimal(
i, f,
dir: direction,
precision: places,
mode: "places"
))
.map(((i, f)) => pad-decimal(
i, f,
pad,
"places",
places
))

if is-symmetric {
pm = pm.first()
}

// Then, round number to the same number of places
mode = "places"
precision = places
/// Rounds a number to the same decimal place as its uncertainty.
#let round-to-uncertainty(

/// Integer part.
/// -> str
int,

/// Fractional part.
/// -> str
frac,

/// Uncertainty, given as a tuple of integer and fractional part. Can also be a tuple of two tuples, in the case of asymmetric uncertainty.
/// -> (str, str) | ((str, str), (str, str))
uncertainty,

/// The sign of the number.
/// -> "+" | "-"
sign: "+",

/// The precision to round the uncertainty to. If `auto`, the uncertainty left as is.
/// -> auto | int
precision: auto,

/// Rounding direction.
/// -> str
direction: "nearest",

/// How to round ties.
/// -> "away-from-zero" | "towards-zero" | "to-odd" | "to-even" | "towards-infinity" | "towards-negative-infinity"
ties: "away-from-zero",

/// Determines whether the number should be padded with zeros if the number
/// has less digits than the rounding precision. If an integer is given,
/// determines the minimum number of decimal digits (`mode: "places"`) or
/// significant figures (`mode: "figures"`) to display.
/// -> bool | int
pad: true,
..

) = {
let is-symmetric = type(uncertainty.first()) != array
if is-symmetric {
uncertainty = (uncertainty,)
}

/// Find the (fractional) place of the smallest uncertainty
let places = if precision == auto {
calc.max(
..uncertainty.map(((i, f)) => f.len())
)
} else {
precision + calc.max(
..uncertainty.map(((i, f)) => count-leading-zeros(i + f) - i.len())
)
}

uncertainty = uncertainty
.map(((i, f)) => round-decimal(
i, f,
dir: direction,
precision: places,
mode: "places"
))
.map(((i, f)) => pad-decimal(
i, f,
pad,
"places",
places
))

if is-symmetric {
uncertainty = uncertainty.first()
}

// Then, round number to the same number of places as the uncertainty.
(
..pad-decimal(
..round-decimal(
int, frac,
precision: precision,
mode: mode,
precision: places,
mode: "places",
dir: direction,
sign: sign,
ties: ties,
),
pad, mode, precision
pad, "places", places
),
pm
uncertainty
)
}

4 changes: 3 additions & 1 deletion src/state.typ
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@
),
round: (
mode: "places",
precision: none,
precision: auto,
follow-uncertainty: true,
uncertainty-precision: auto,
pad: true,
direction: "nearest",
ties: "away-from-zero",
Expand Down
17 changes: 14 additions & 3 deletions tests/num/rounding/ref.typ
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,20 @@ $10#sym.space.thin 000$ \

#pagebreak()

$1.23plus.minus 0.03$ \
$1.2342plus.minus 0.0003$ \
$9plus.minus 2$
$12.4plus.minus 0.2$ \
$1.234plus.minus 0.009$ \
$1.234#sym.space.thin 22plus.minus 0.00310$ \
$9plus.minus 2$ \
$8.00plus.minus 0.02$ \
$-9plus.minus 2$ \
$8.8plus.minus 0.02$ \
$0.30plus.minus 0.12$ \
$0.3plus.minus 0.12$ \

$12.38plus.minus 0.2$ \
$12plus.minus 0.2$ \
$1.2plus.minus 0.00034$ \
$8.8plus.minus 2$ \

#pagebreak()

Expand Down
Loading
Loading