37
37
)
38
38
39
39
40
- def _to (value : Union ["Value" , "ValueArray" ], units : Union [Unit , str ]):
40
+ def _to (
41
+ value : Union ["Value" , "ValueArray" ], units : Union [Unit , str ], inplace : bool
42
+ ) -> Any :
41
43
"""
42
- Convert a value or value array to a new unit and return a copy
44
+ Convert a value or value array to a new unit and return a copy if
45
+ inplace=False
43
46
44
47
---------------------------------------------------------------------------
45
48
Arguments:
@@ -62,26 +65,29 @@ def _to(value: Union["Value", "ValueArray"], units: Union[Unit, str]):
62
65
63
66
except StopIteration :
64
67
raise TypeError (
65
- f"No viable unit conversion from { value .units } " f" -> { units } "
68
+ f"No viable unit conversion from { value .units } -> { units } "
66
69
)
67
70
68
- # Convert to the base unit, then to the new units
69
- c = float (units .conversion / value .units .conversion )
70
-
71
- if isinstance (value , Value ):
72
- return value .__class__ (float (value ) * c , units = units )
73
-
74
- elif isinstance (value , ValueArray ):
75
- value [:] = np .array (value , copy = True ) * c
76
- value .units = units
77
- return value
78
-
79
- else :
71
+ if not (isinstance (value , Value ) or isinstance (value , ValueArray )):
80
72
raise ValueError (
81
73
f"Cannot convert { value } to new units. Must be one of"
82
74
f" Value of ValueArray"
83
75
)
84
76
77
+ if isinstance (value , Value ) and inplace :
78
+ raise ValueError (
79
+ "Cannot modify a value inplace as floats are immutable"
80
+ )
81
+
82
+ # Convert to the base unit, then to the new units
83
+ c = float (units .conversion / value .units .conversion )
84
+
85
+ new_value = value if inplace else value .copy ()
86
+ new_value *= c
87
+ new_value .units = units
88
+
89
+ return None if inplace else new_value
90
+
85
91
86
92
def _units_init (value , units : Union [Unit , str , None ]):
87
93
"""Initialise the units of this value
@@ -171,6 +177,11 @@ def _other_same_units(self, other):
171
177
172
178
return other .to (self .units )
173
179
180
+ def _like_self_from_float (self , value : float ) -> "Value" :
181
+ new_value = self .__class__ (value , units = self .units )
182
+ new_value .__dict__ .update (self .__dict__ )
183
+ return new_value
184
+
174
185
def __eq__ (self , other ) -> bool :
175
186
"""Equality of two values, which may be in different units"""
176
187
@@ -210,20 +221,26 @@ def __add__(self, other) -> "Value":
210
221
if isinstance (other , np .ndarray ):
211
222
return other + float (self )
212
223
213
- return self .__class__ (
214
- float (self ) + self ._other_same_units (other ), units = self . units
224
+ return self ._like_self_from_float (
225
+ float (self ) + self ._other_same_units (other )
215
226
)
216
227
217
- def __mul__ (self , other ) -> "Value" :
228
+ def __mul__ (self , other ) -> Union [ float , "Value" ] :
218
229
"""Multiply this value with another"""
219
230
if isinstance (other , np .ndarray ):
220
231
return other * float (self )
221
232
222
- return self .__class__ (
223
- float (self ) * self ._other_same_units (other ), units = self .units
233
+ if isinstance (other , Value ):
234
+ logger .warning (
235
+ "Multiplying autode.Value returns a float with no units"
236
+ )
237
+ return float (self ) * self ._other_same_units (other )
238
+
239
+ return self ._like_self_from_float (
240
+ float (self ) * self ._other_same_units (other )
224
241
)
225
242
226
- def __rmul__ (self , other ) -> "Value" :
243
+ def __rmul__ (self , other ) -> Union [ float , "Value" ] :
227
244
return self .__mul__ (other )
228
245
229
246
def __radd__ (self , other ) -> "Value" :
@@ -232,16 +249,13 @@ def __radd__(self, other) -> "Value":
232
249
def __sub__ (self , other ) -> "Value" :
233
250
return self .__add__ (- other )
234
251
235
- def __floordiv__ (self , other ):
236
- raise NotImplementedError (
237
- "Integer division is not supported by " "autode.values.Value"
238
- )
252
+ def __floordiv__ (self , other ) -> Union [float , "Value" ]:
253
+ x = float (self ) // self ._other_same_units (other )
254
+ return x if isinstance (other , Value ) else self ._like_self_from_float (x )
239
255
240
- def __truediv__ (self , other ) -> "Value" :
241
- return self .__class__ (
242
- float (self ) / float (self ._other_same_units (other )),
243
- units = self .units ,
244
- )
256
+ def __truediv__ (self , other ) -> Union [float , "Value" ]:
257
+ x = float (self ) / self ._other_same_units (other )
258
+ return x if isinstance (other , Value ) else self ._like_self_from_float (x )
245
259
246
260
def __abs__ (self ) -> "Value" :
247
261
"""Absolute value"""
@@ -260,7 +274,7 @@ def to(self, units):
260
274
Raises:
261
275
(TypeError):
262
276
"""
263
- return _to (self , units )
277
+ return _to (self , units , inplace = False )
264
278
265
279
266
280
class Energy (Value ):
@@ -643,7 +657,21 @@ def to(self, units) -> Any:
643
657
Raises:
644
658
(TypeError):
645
659
"""
646
- return _to (self , units )
660
+ return _to (self , units , inplace = False )
661
+
662
+ def to_ (self , units ) -> None :
663
+ """
664
+ Convert this array into a set of new units, inplace. This will not copy
665
+ the array
666
+
667
+ -----------------------------------------------------------------------
668
+ Returns:
669
+ (None)
670
+
671
+ Raises:
672
+ (TypeError):
673
+ """
674
+ _to (self , units , inplace = True )
647
675
648
676
def __array_finalize__ (self , obj ):
649
677
"""See https://numpy.org/doc/stable/user/basics.subclassing.html"""
0 commit comments