forked from M-Labs/artiq
language/units: do not quantize
This commit is contained in:
parent
98b23eadf8
commit
a2691ab07a
|
@ -1,30 +1,53 @@
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
from fractions import Fraction
|
||||||
|
|
||||||
_prefixes_str = "pnum_kM"
|
_prefixes_str = "pnum_kMG"
|
||||||
|
_smallest_prefix = Fraction(1, 10**12)
|
||||||
|
|
||||||
Unit = namedtuple("Unit", "base_prefix name")
|
Unit = namedtuple("Unit", "name")
|
||||||
|
|
||||||
class DimensionError(Exception):
|
class DimensionError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class Quantity:
|
class Quantity:
|
||||||
def __init__(self, amount, unit):
|
def __init__(self, amount, unit):
|
||||||
self.amount = int(amount)
|
self.amount = amount
|
||||||
self.unit = unit
|
self.unit = unit
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
r_amount = self.amount
|
r_amount = self.amount
|
||||||
r_prefix = self.unit.base_prefix
|
if isinstance(r_amount, int) or isinstance(r_amount, Fraction):
|
||||||
if r_amount:
|
r_prefix = 0
|
||||||
while not r_amount % 1000 and r_prefix < len(_prefixes_str):
|
r_amount = r_amount/_smallest_prefix
|
||||||
r_amount //= 1000
|
if r_amount:
|
||||||
r_prefix += 1
|
numerator = r_amount.numerator
|
||||||
return str(r_amount) + " " + _prefixes_str[r_prefix] + self.unit.name
|
while numerator % 1000 == 0 and r_prefix < len(_prefixes_str):
|
||||||
|
numerator /= 1000
|
||||||
|
r_amount /= 1000
|
||||||
|
r_prefix += 1
|
||||||
|
prefix_str = _prefixes_str[r_prefix]
|
||||||
|
if prefix_str == "_":
|
||||||
|
prefix_str = ""
|
||||||
|
return str(r_amount) + " " + prefix_str + self.unit.name
|
||||||
|
else:
|
||||||
|
return str(r_amount) + " " + self.unit.name
|
||||||
|
|
||||||
def __rmul__(self, other):
|
def __mul__(self, other):
|
||||||
if isinstance(other, Quantity):
|
if isinstance(other, Quantity):
|
||||||
return NotImplemented
|
return NotImplemented
|
||||||
return Quantity(self.amount*other, self.unit)
|
return Quantity(self.amount*other, self.unit)
|
||||||
|
def __rmul__(self, other):
|
||||||
|
if isinstance(other, Quantity):
|
||||||
|
return NotImplemented
|
||||||
|
return Quantity(other*self.amount, self.unit)
|
||||||
|
def __truediv__(self, other):
|
||||||
|
if isinstance(other, Quantity):
|
||||||
|
return NotImplemented
|
||||||
|
return Quantity(self.amount/other, self.unit)
|
||||||
|
def __floordiv__(self, other):
|
||||||
|
if isinstance(other, Quantity):
|
||||||
|
return NotImplemented
|
||||||
|
return Quantity(self.amount//other, self.unit)
|
||||||
|
|
||||||
def __neg__(self):
|
def __neg__(self):
|
||||||
return Quantity(-self.amount, self.unit)
|
return Quantity(-self.amount, self.unit)
|
||||||
|
@ -76,17 +99,16 @@ def check_unit(value, unit):
|
||||||
raise DimensionError
|
raise DimensionError
|
||||||
return value.amount
|
return value.amount
|
||||||
|
|
||||||
def _register_unit(base_prefix, name, prefixes):
|
def _register_unit(name, prefixes):
|
||||||
base_prefix_exp = _prefixes_str.index(base_prefix)
|
unit = Unit(name)
|
||||||
unit = Unit(base_prefix_exp, name)
|
globals()[name+"_unit"] = unit
|
||||||
globals()["base_"+name+"_unit"] = unit
|
amount = _smallest_prefix
|
||||||
for prefix in prefixes:
|
for prefix in _prefixes_str:
|
||||||
prefix_exp = _prefixes_str.index(prefix)
|
if prefix in prefixes:
|
||||||
exp_d = prefix_exp - base_prefix_exp
|
quantity = Quantity(amount, unit)
|
||||||
assert(exp_d >= 0)
|
full_name = prefix + name if prefix != "_" else name
|
||||||
quantity = Quantity(1000**exp_d, unit)
|
globals()[full_name] = quantity
|
||||||
full_name = prefix + name if prefix != "_" else name
|
amount *= 1000
|
||||||
globals()[full_name] = quantity
|
|
||||||
|
|
||||||
_register_unit("p", "s", "pnum_")
|
_register_unit("s", "pnum_")
|
||||||
_register_unit("_", "Hz", "_kM")
|
_register_unit("Hz", "_kMG")
|
||||||
|
|
Loading…
Reference in New Issue