Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
from .math_integer_sqrt import integer_sqrt ← from math.integer-sqrt ^1.0.0 · built alongside by fune
from .math_round_div import RoundingMode ← from math.round-div ^1.0.0 · built alongside by fune
from .money_amount import Money, assert_same_currency ← from money.amount ^1.0.0 · built alongside by fune
MAX_SAFE = 2**53 - 1
def economic_order_quantity(annual_demand: int, order_cost: Money, holding_cost: Money, mode: RoundingMode) -> int:
"""Economic order quantity, sqrt(2DS / H), in whole units.
The root is never taken in floating point: the floor is an exact integer
square root and the rounding decision compares whole numbers, so an exact
half (sqrt(6.25) = 2.5) rounds by ``mode`` and not by the language.
"""
if isinstance(annual_demand, bool) or not isinstance(annual_demand, int) or annual_demand < 0:
raise ValueError(
"annualDemand must be a whole number of units, not negative, received %r" % (annual_demand,)
)
assert_same_currency(order_cost, holding_cost)
if order_cost.minor < 0:
raise ValueError("orderCost must not be negative, received %d" % order_cost.minor)
if holding_cost.minor <= 0:
raise ValueError("holdingCost must be greater than zero, received %d" % holding_cost.minor)
eight_ds = 8 * annual_demand * order_cost.minor
if eight_ds > MAX_SAFE:
raise ValueError(
"annualDemand and orderCost are too large: 8 x demand x order cost must stay within 2^53 - 1"
)
two_ds = 2 * annual_demand * order_cost.minor
h = holding_cost.minor
n = integer_sqrt(two_ds // h)
odd = 2 * n + 1
if mode == "down":
return n
if mode == "up":
return n if n * n * h == two_ds else n + 1
if mode == "half-up":
return n + 1 if odd * odd * h <= eight_ds else n
if mode == "half-even":
half = odd * odd * h
if half < eight_ds:
return n + 1
if half > eight_ds:
return n
return n if n % 2 == 0 else n + 1
raise ValueError('unknown rounding mode "%s"' % (mode,))