Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/artiq
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 59194176a942
Choose a base ref
...
head repository: m-labs/artiq
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 70fc0f6ce7fd
Choose a head ref
  • 4 commits
  • 7 files changed
  • 1 contributor

Commits on Oct 5, 2014

  1. Remove microcycle unit

    Introducing it complicates things and has no advantage with good rational arithmetic support.
    sbourdeauducq committed Oct 5, 2014
    Copy the full SHA
    2944592 View commit details
  2. Copy the full SHA
    2a19d7d View commit details
  3. Copy the full SHA
    6c44fe0 View commit details
  4. Copy the full SHA
    70fc0f6 View commit details
Showing with 91 additions and 89 deletions.
  1. +1 −1 artiq/__init__.py
  2. +1 −1 artiq/language/core.py
  3. +81 −74 artiq/language/units.py
  4. +1 −2 artiq/transforms/inline.py
  5. +1 −1 artiq/transforms/interleave.py
  6. +5 −8 artiq/transforms/lower_units.py
  7. +1 −2 artiq/transforms/tools.py
2 changes: 1 addition & 1 deletion artiq/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from artiq.language.core import *
from artiq.language.units import microcycle, ps, ns, us, ms, s
from artiq.language.units import ps, ns, us, ms, s
from artiq.language.units import Hz, kHz, MHz, GHz
2 changes: 1 addition & 1 deletion artiq/language/core.py
Original file line number Diff line number Diff line change
@@ -306,7 +306,7 @@ def delay(duration):


def now():
"""Retrieves the current RTIO time, in microcycles.
"""Retrieves the current RTIO time, in seconds.
"""
return _time_manager.get_time()
155 changes: 81 additions & 74 deletions artiq/language/units.py
Original file line number Diff line number Diff line change
@@ -5,27 +5,54 @@
_smallest_prefix = _Fraction(1, 10**12)


class Unit:
"""Represents a fundamental unit (second, hertz, ...).
def mul_dimension(l, r):
if l is None:
return r
if r is None:
return l
if {l, r} == {"Hz", "s"}:
return None

"""
def __init__(self, name):
self.name = name

def __eq__(self, other):
return isinstance(other, Unit) and self.name == other.name
def _rmul_dimension(l, r):
return mul_dimension(r, l)


class DimensionError(Exception):
"""Exception raised when attempting operations on incompatible units
(e.g. adding seconds and hertz).
def div_dimension(l, r):
if l == r:
return None
if r is None:
return l
if l is None:
if r == "s":
return "Hz"
if r == "Hz":
return "s"

"""
pass

def _rdiv_dimension(l, r):
return div_dimension(r, l)


def addsub_dimension(x, y):
if x == y:
return x
else:
return None


def _format(amount, unit):
if amount is NotImplemented:
return NotImplemented
if unit is None:
return amount
else:
return Quantity(amount, unit)


class Quantity:
"""Represents an amount in a given fundamental unit (:class:`Unit`).
"""Represents an amount in a given fundamental unit (identified by a
string).
The amount can be of any Python numerical type (integer, float,
Fraction, ...).
@@ -51,112 +78,92 @@ def __repr__(self):
prefix_str = _prefixes_str[r_prefix]
if prefix_str == "_":
prefix_str = ""
return str(r_amount) + " " + prefix_str + self.unit.name
return str(r_amount) + " " + prefix_str + self.unit
else:
return str(r_amount) + " " + self.unit.name
return str(r_amount) + " " + self.unit

# mul/div
def __mul__(self, other):
def _binop(self, other, opf_name, dim_function):
opf = getattr(self.amount, opf_name)
if isinstance(other, Quantity):
return NotImplemented
return Quantity(self.amount*other, self.unit)
amount = opf(other.amount)
unit = dim_function(self.unit, other.unit)
else:
amount = opf(other)
unit = dim_function(self.unit, None)
return _format(amount, unit)

def __mul__(self, other):
return self._binop(other, "__mul__", mul_dimension)

def __rmul__(self, other):
if isinstance(other, Quantity):
return NotImplemented
return Quantity(other*self.amount, self.unit)
return self._binop(other, "__rmul__", _rmul_dimension)

def __truediv__(self, other):
if isinstance(other, Quantity):
if other.unit == self.unit:
return self.amount/other.amount
else:
return NotImplemented
else:
return Quantity(self.amount/other, self.unit)
return self._binop(other, "__truediv__", div_dimension)

def __rtruediv__(self, other):
return self._binop(other, "__rtruediv__", _rdiv_dimension)

def __floordiv__(self, other):
if isinstance(other, Quantity):
if other.unit == self.unit:
return self.amount//other.amount
else:
return NotImplemented
else:
return Quantity(self.amount//other, self.unit)
return self._binop(other, "__floordiv__", div_dimension)

def __rfloordiv__(self, other):
return self._binop(other, "__rfloordiv__", _rdiv_dimension)

# unary ops
def __neg__(self):
return Quantity(-self.amount, self.unit)
return Quantity(self.amount.__neg__(), self.unit)

def __pos__(self):
return Quantity(self.amount, self.unit)
return Quantity(self.amount.__pos__(), self.unit)

# add/sub
def __add__(self, other):
if self.unit != other.unit:
raise DimensionError
return Quantity(self.amount + other.amount, self.unit)
return self._binop(other, "__add__", addsub_dimension)

def __radd__(self, other):
if self.unit != other.unit:
raise DimensionError
return Quantity(other.amount + self.amount, self.unit)
return self._binop(other, "__radd__", addsub_dimension)

def __sub__(self, other):
if self.unit != other.unit:
raise DimensionError
return Quantity(self.amount - other.amount, self.unit)
return self._binop(other, "__sub__", addsub_dimension)

def __rsub__(self, other):
if self.unit != other.unit:
raise DimensionError
return Quantity(other.amount - self.amount, self.unit)
return self._binop(other, "__rsub__", addsub_dimension)

# comparisons
def _cmp(self, other, opf_name):
if isinstance(other, Quantity):
other = other.amount
return getattr(self.amount, opf_name)(other)

def __lt__(self, other):
if self.unit != other.unit:
raise DimensionError
return self.amount < other.amount
return self._cmp(other, "__lt__")

def __le__(self, other):
if self.unit != other.unit:
raise DimensionError
return self.amount <= other.amount
return self._cmp(other, "__le__")

def __eq__(self, other):
if self.unit != other.unit:
raise DimensionError
return self.amount == other.amount
return self._cmp(other, "__eq__")

def __ne__(self, other):
if self.unit != other.unit:
raise DimensionError
return self.amount != other.amount
return self._cmp(other, "__ne__")

def __gt__(self, other):
if self.unit != other.unit:
raise DimensionError
return self.amount > other.amount
return self._cmp(other, "__gt__")

def __ge__(self, other):
if self.unit != other.unit:
raise DimensionError
return self.amount >= other.amount
return self._cmp(other, "__ge__")


def _register_unit(name, prefixes):
unit = Unit(name)
globals()[name+"_unit"] = unit
def _register_unit(unit, prefixes):
amount = _smallest_prefix
for prefix in _prefixes_str:
if prefix in prefixes:
quantity = Quantity(amount, unit)
full_name = prefix + name if prefix != "_" else name
full_name = prefix + unit if prefix != "_" else unit
globals()[full_name] = quantity
amount *= 1000

_register_unit("s", "pnum_")
_register_unit("Hz", "_kMG")

microcycle_unit = Unit("microcycle")
microcycle = Quantity(1, microcycle_unit)
3 changes: 1 addition & 2 deletions artiq/transforms/inline.py
Original file line number Diff line number Diff line change
@@ -48,8 +48,7 @@ def __init__(self):
for kg in core_language.kernel_globals:
self.use_count[kg] = 1
for name in ("int", "round", "int64", "round64", "float", "array",
"range", "Fraction", "Quantity", "EncodedException",
"s_unit", "Hz_unit", "microcycle_unit"):
"range", "Fraction", "Quantity", "EncodedException"):
self.use_count[name] = 1

def new_name(self, base_name):
2 changes: 1 addition & 1 deletion artiq/transforms/interleave.py
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@
# -1 statement duration could not be pre-determined
# 0 statement has no effect on timeline
# >0 statement is a static delay that advances the timeline
# by the given amount (in microcycles)
# by the given amount
def _get_duration(stmt):
if isinstance(stmt, (ast.Expr, ast.Assign)):
return _get_duration(stmt.value)
13 changes: 5 additions & 8 deletions artiq/transforms/lower_units.py
Original file line number Diff line number Diff line change
@@ -24,14 +24,11 @@ def visit_Call(self, node):
self.in_core_time = old_in_core_time
elif fn == "Quantity":
if self.in_core_time:
if node.args[1].id == "microcycle_units":
node = node.args[0]
else:
node = ast.copy_location(
ast.BinOp(left=node.args[0],
op=ast.Div(),
right=value_to_ast(self.ref_period)),
node)
node = ast.copy_location(
ast.BinOp(left=node.args[0],
op=ast.Div(),
right=value_to_ast(self.ref_period)),
node)
else:
node = node.args[0]
else:
3 changes: 1 addition & 2 deletions artiq/transforms/tools.py
Original file line number Diff line number Diff line change
@@ -35,8 +35,7 @@ def value_to_ast(value):
if isinstance(value, units.Quantity):
return ast.Call(
func=ast.Name("Quantity", ast.Load()),
args=[value_to_ast(value.amount),
ast.Name(value.unit.name+"_unit", ast.Load())],
args=[value_to_ast(value.amount), ast.Str(value.unit)],
keywords=[], starargs=None, kwargs=None)
return None