Skip to content

Commit e0ada95

Browse files
author
Darren Dale
committed
do not support in-place operations that involve changing the units. Supporting them
would have allowed, for example: q=[1,2,3,4]*J qq=q[:2] qq*=10*m which would modify the magnitude of the first elements in q, but not q's units. Removing support for in-place modification of units allows a single immutable Dimensionality class to be used throughout quantities. Proper ndarray subclassing seems to have yielded improved performance. tests were taking ~2 seconds, now down to ~0.7 seconds
1 parent 7527457 commit e0ada95

7 files changed

Lines changed: 154 additions & 323 deletions

File tree

.eric4project/quantities.e4q

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<!DOCTYPE UserProject SYSTEM "UserProject-4.0.dtd">
33
<!-- eric4 user project file for project quantities -->
4-
<!-- Saved: 2009-01-15, 08:46:35 -->
4+
<!-- Saved: 2009-01-17, 23:42:15 -->
55
<!-- Copyright (C) 2009 , -->
66
<UserProject version="4.0">
77
</UserProject>

.eric4project/quantities.e4t

Lines changed: 19 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<!DOCTYPE Tasks SYSTEM "Tasks-4.2.dtd">
33
<!-- eric4 tasks file for project quantities -->
4-
<!-- Saved: 2009-01-15, 08:46:35 -->
4+
<!-- Saved: 2009-01-17, 23:42:15 -->
55
<Tasks version="4.2">
66
<Task priority="1" completed="False" bugfix="False">
77
<Summary>TODO: move to physical constants</Summary>
@@ -49,75 +49,48 @@
4949
</Resource>
5050
</Task>
5151
<Task priority="1" completed="False" bugfix="False">
52-
<Summary>TODO: what is an appropriate value?</Summary>
53-
<Description></Description>
54-
<Created>2009-01-14, 17:08:40</Created>
55-
<Resource>
56-
<Filename>quantities/uncertainquantity.py</Filename>
57-
<Linenumber>11</Linenumber>
58-
</Resource>
59-
</Task>
60-
<Task priority="1" completed="False" bugfix="False">
61-
<Summary>TODO: use view:</Summary>
62-
<Description></Description>
63-
<Created>2009-01-14, 17:08:40</Created>
64-
<Resource>
65-
<Filename>quantities/uncertainquantity.py</Filename>
66-
<Linenumber>39</Linenumber>
67-
</Resource>
68-
</Task>
69-
<Task priority="1" completed="False" bugfix="False">
70-
<Summary>TODO: use .view:</Summary>
71-
<Description></Description>
72-
<Created>2009-01-14, 17:08:40</Created>
73-
<Resource>
74-
<Filename>quantities/uncertainquantity.py</Filename>
75-
<Linenumber>83</Linenumber>
76-
</Resource>
77-
</Task>
78-
<Task priority="1" completed="False" bugfix="False">
79-
<Summary>TODO: use .view:</Summary>
52+
<Summary>TODO: needs uncertainty: http://en.wikipedia.org/wiki/Astronomical_unit</Summary>
8053
<Description></Description>
81-
<Created>2009-01-14, 17:08:40</Created>
54+
<Created>2009-01-14, 17:09:35</Created>
8255
<Resource>
83-
<Filename>quantities/uncertainquantity.py</Filename>
84-
<Linenumber>89</Linenumber>
56+
<Filename>quantities/units/length.py</Filename>
57+
<Linenumber>111</Linenumber>
8558
</Resource>
8659
</Task>
8760
<Task priority="1" completed="False" bugfix="False">
88-
<Summary>TODO: use .view:</Summary>
61+
<Summary>TODO: what is an appropriate value?</Summary>
8962
<Description></Description>
90-
<Created>2009-01-14, 17:08:40</Created>
63+
<Created>2009-01-17, 21:28:53</Created>
9164
<Resource>
9265
<Filename>quantities/uncertainquantity.py</Filename>
93-
<Linenumber>102</Linenumber>
66+
<Linenumber>11</Linenumber>
9467
</Resource>
9568
</Task>
9669
<Task priority="1" completed="False" bugfix="False">
97-
<Summary>TODO: use .view:</Summary>
70+
<Summary>TODO: use view:</Summary>
9871
<Description></Description>
99-
<Created>2009-01-14, 17:08:40</Created>
72+
<Created>2009-01-17, 21:28:53</Created>
10073
<Resource>
10174
<Filename>quantities/uncertainquantity.py</Filename>
102-
<Linenumber>115</Linenumber>
75+
<Linenumber>41</Linenumber>
10376
</Resource>
10477
</Task>
10578
<Task priority="1" completed="False" bugfix="False">
106-
<Summary>TODO: needs uncertainty: http://en.wikipedia.org/wiki/Astronomical_unit</Summary>
79+
<Summary>TODO: what is an appropriate value?</Summary>
10780
<Description></Description>
108-
<Created>2009-01-14, 17:09:35</Created>
81+
<Created>2009-01-17, 23:40:05</Created>
10982
<Resource>
110-
<Filename>quantities/units/length.py</Filename>
111-
<Linenumber>111</Linenumber>
83+
<Filename>quantities/quantity.py</Filename>
84+
<Linenumber>39</Linenumber>
11285
</Resource>
11386
</Task>
11487
<Task priority="1" completed="False" bugfix="False">
115-
<Summary>TODO: use a regexp:</Summary>
88+
<Summary>TODO: do we want this kind of magic?</Summary>
11689
<Description></Description>
117-
<Created>2009-01-14, 17:20:12</Created>
90+
<Created>2009-01-17, 23:40:05</Created>
11891
<Resource>
119-
<Filename>quantities/dimensionality.py</Filename>
120-
<Linenumber>12</Linenumber>
92+
<Filename>quantities/quantity.py</Filename>
93+
<Linenumber>347</Linenumber>
12194
</Resource>
12295
</Task>
12396
</Tasks>

quantities/dimensionality.py

Lines changed: 25 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,22 @@
1010
from quantities.registry import unit_registry
1111

1212

13-
class BaseDimensionality(object):
13+
class Dimensionality(object):
1414

1515
"""
1616
"""
1717

18+
def __init__(self, dict=None):
19+
self.__data = {}
20+
if dict is not None:
21+
self.__data.update(dict)
22+
1823
@property
1924
def simplified(self):
2025
if len(self):
21-
rq = 1*unit_registry['dimensionless']
26+
rq = (1*unit_registry['dimensionless']).copy()
2227
for u, d in self.iteritems():
23-
rq *= u.reference_quantity**d
28+
rq = rq * u.reference_quantity**d
2429
return rq.dimensionality
2530
else:
2631
return self
@@ -40,7 +45,7 @@ def __add__(self, other):
4045
'can not add units of %s and %s'\
4146
%(str(self), str(other))
4247
)
43-
return Dimensionality(self)
48+
return self.copy()
4449

4550
def __sub__(self, other):
4651
try:
@@ -50,94 +55,58 @@ def __sub__(self, other):
5055
'can not subtract units of %s and %s'\
5156
%(str(self), str(other))
5257
)
53-
return Dimensionality(self)
58+
return self.copy()
5459

5560
def __mul__(self, other):
56-
new = Dimensionality(self)
61+
new = dict(self)
5762
for unit, power in other.iteritems():
5863
try:
5964
new[unit] += power
6065
if new[unit] == 0:
6166
new.pop(unit)
6267
except KeyError:
6368
new[unit] = power
64-
return new
69+
return Dimensionality(new)
6570

6671
def __truediv__(self, other):
67-
new = Dimensionality(self)
72+
new = dict(self)
6873
for unit, power in other.iteritems():
6974
try:
7075
new[unit] -= power
7176
if new[unit] == 0:
7277
new.pop(unit)
7378
except KeyError:
7479
new[unit] = -power
75-
return new
80+
return Dimensionality(new)
7681

7782
def __div__(self, other):
7883
return self.__truediv__(other)
7984

8085
def __pow__(self, other):
8186
assert isinstance(other, (int, float))
82-
new = Dimensionality(self)
87+
new = dict(self)
8388
for i in new:
8489
new[i] *= other
85-
return new
90+
return Dimensionality(new)
8691

8792
def __repr__(self):
8893
if USE_UNICODE:
8994
return self.unicode()
9095
else:
9196
return self.string()
9297

93-
def string(self):
94-
return format_units(self)
95-
96-
def unicode(self):
97-
return format_units_unicode(self)
98-
99-
100-
class ImmutableDimensionality(BaseDimensionality):
101-
102-
def __init__(self, dict=None):
103-
self.__data = {}
104-
if dict is not None:
105-
self.__data.update(dict)
106-
107-
def __iadd__(self, other):
108-
raise TypeError('can not modify protected units')
109-
110-
def __isub__(self, other):
111-
raise TypeError('can not modify protected units')
112-
113-
def __imul__(self, other):
114-
raise TypeError('can not modify protected units')
115-
116-
def __itruediv__(self, other):
117-
raise TypeError('can not modify protected units')
118-
119-
def __idiv__(self, other):
120-
raise TypeError('can not modify protected units')
121-
122-
def __ipow__(self, other):
123-
raise TypeError('can not modify protected units')
124-
125-
# def __repr__(self):
126-
# if USE_UNICODE:
127-
# return self.unicode()
128-
# else:
129-
# return self.string()
130-
# return format_units(self.__data)
131-
13298
def __cmp__(self, dict):
133-
if isinstance(dict, ImmutableDimensionality):
99+
if isinstance(dict, Dimensionality):
134100
return cmp(self.__data, dict.__data)
135101
else:
136102
return cmp(self.__data, dict)
137103

138104
def __len__(self):
139105
return len(self.__data)
140106

107+
def __contains__(self, key):
108+
return key in self.__data
109+
141110
def __eq__(self, other):
142111
return hash(self) == hash(other)
143112

@@ -148,7 +117,7 @@ def __iter__(self):
148117
return self.__data.__iter__()
149118

150119
def copy(self):
151-
return ImmutableDimensionality(self.__data.copy())
120+
return Dimensionality(self.__data.copy())
152121

153122
def keys(self):
154123
return self.__data.keys()
@@ -176,67 +145,8 @@ def get(self, key, failobj=None):
176145
return failobj
177146
return self[key]
178147

179-
def __contains__(self, key):
180-
return key in self.__data
181-
182-
183-
class Dimensionality(BaseDimensionality, dict):
184-
185-
def copy(self):
186-
return Dimensionality(dict.copy(self))
187-
188-
def __iadd__(self, other):
189-
try:
190-
assert self == other
191-
except AssertionError:
192-
raise ValueError(
193-
'can not add units of %s and %s'\
194-
%(str(self), str(other))
195-
)
196-
return self
197-
198-
def __isub__(self, other):
199-
try:
200-
assert self == other
201-
except AssertionError:
202-
raise ValueError(
203-
'can not subtract units of %s and %s'\
204-
%(str(self), str(other))
205-
)
206-
return self
207-
208-
def __imul__(self, other):
209-
if other is self:
210-
other = other.copy()
211-
for unit, power in other.iteritems():
212-
try:
213-
self[unit] += power
214-
if self[unit] == 0:
215-
self.pop(unit)
216-
except KeyError:
217-
self[unit] = power
218-
return self
219-
220-
def __itruediv__(self, other):
221-
if other is self:
222-
other = other.copy()
223-
for unit, power in other.iteritems():
224-
try:
225-
self[unit] -= power
226-
if self[unit] == 0:
227-
self.pop(unit)
228-
except KeyError:
229-
self[unit] = -power
230-
return self
231-
232-
def __idiv__(self, other):
233-
return self.__itruediv__(other)
234-
235-
def __ipow__(self, other):
236-
assert isinstance(other, (int, float))
237-
for i in self:
238-
self[i] *= other
239-
return self
148+
def string(self):
149+
return format_units(self)
240150

241-
# def __repr__(self):
242-
# return format_units(self)
151+
def unicode(self):
152+
return format_units_unicode(self)

0 commit comments

Comments
 (0)