summaryrefslogtreecommitdiff
path: root/candle-pyo3/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'candle-pyo3/src/lib.rs')
-rw-r--r--candle-pyo3/src/lib.rs106
1 files changed, 106 insertions, 0 deletions
diff --git a/candle-pyo3/src/lib.rs b/candle-pyo3/src/lib.rs
index 55b20308..f9fdc712 100644
--- a/candle-pyo3/src/lib.rs
+++ b/candle-pyo3/src/lib.rs
@@ -772,6 +772,112 @@ impl PyTensor {
Ok(PyTensor(self.0.copy().map_err(wrap_err)?))
}
+ #[pyo3(signature = (*args, **kwargs), text_signature = "(self, *args, **kwargs)")]
+ /// Performs Tensor dtype and/or device conversion.
+ /// &RETURNS&: Tensor
+ fn to(&self, args: &PyTuple, kwargs: Option<&PyDict>) -> PyResult<Self> {
+ let mut device: Option<PyDevice> = None;
+ let mut dtype: Option<PyDType> = None;
+ let mut other: Option<PyTensor> = None;
+
+ fn handle_duplicates<T>(
+ opt: &mut Option<T>,
+ extraction_result: PyResult<T>,
+ err_msg: &'static str,
+ ) -> PyResult<()> {
+ if let Ok(sucessfull_extraction) = extraction_result {
+ if opt.is_some() {
+ return Err(PyValueError::new_err(err_msg));
+ }
+ *opt = Some(sucessfull_extraction);
+ }
+ Ok(())
+ }
+
+ //handle args
+ for arg in args.iter() {
+ if arg.extract::<PyDevice>().is_ok() {
+ handle_duplicates(
+ &mut device,
+ arg.extract::<PyDevice>(),
+ "cannot specify multiple devices",
+ )?;
+ } else if arg.extract::<PyDType>().is_ok() {
+ handle_duplicates(
+ &mut dtype,
+ arg.extract::<PyDType>(),
+ "cannot specify multiple dtypes",
+ )?;
+ } else if arg.extract::<PyTensor>().is_ok() {
+ handle_duplicates(
+ &mut other,
+ arg.extract::<PyTensor>(),
+ "cannot specify multiple output tensors",
+ )?;
+ } else {
+ return Err(PyTypeError::new_err(format!(
+ "unsupported argument type `{:#?}`",
+ arg.get_type().name()
+ )));
+ }
+ }
+
+ if let Some(kwargs) = kwargs {
+ if let Some(any) = kwargs.get_item("dtype") {
+ handle_duplicates(
+ &mut dtype,
+ any.extract::<PyDType>(),
+ "cannot specify multiple dtypes",
+ )?;
+ }
+ if let Some(any) = kwargs.get_item("device") {
+ handle_duplicates(
+ &mut device,
+ any.extract::<PyDevice>(),
+ "cannot specify multiple devices",
+ )?;
+ }
+ if let Some(any) = kwargs.get_item("other") {
+ handle_duplicates(
+ &mut other,
+ any.extract::<PyTensor>(),
+ "cannot specify multiple output tensors",
+ )?;
+ }
+ }
+
+ if let Some(other) = other {
+ if device.is_some() {
+ return Err(PyValueError::new_err(
+ "cannot specify both an output tensor and a device",
+ ));
+ }
+ if dtype.is_some() {
+ return Err(PyValueError::new_err(
+ "cannot specify both an output tensor and a dtype",
+ ));
+ }
+ dtype = Some(other.dtype());
+ device = Some(PyDevice::from_device(other.0.device()));
+ }
+
+ let result = match (device, dtype) {
+ (Some(device), Some(dtype)) => self
+ .0
+ .to_device(&device.as_device()?)
+ .map_err(wrap_err)?
+ .to_dtype(dtype.0)
+ .map_err(wrap_err)?,
+ (Some(device), None) => self.0.to_device(&device.as_device()?).map_err(wrap_err)?,
+ (None, Some(dtype)) => self.0.to_dtype(dtype.0).map_err(wrap_err)?,
+ (None, None) => {
+ return Err(PyTypeError::new_err("No valide dtype or device specified"))
+ }
+ };
+
+ Ok(PyTensor(result))
+ }
+
#[pyo3(text_signature = "(self, dtype:Union[str,DType])")]
/// Convert the tensor to a new dtype.
/// &RETURNS&: Tensor