Closed
Description
rust-cpython can convert Python lists to Rust vectors, but it can't yet convert arrays created by the array module. It also doesn't support numpy arrays, which is probably a bigger project, but also valuable goal.
For example, I have an example where I am writing a dot product function:
mod dot {
pub fn dot(a : &Vec<f32>, b : &Vec<f32>) -> f32 {
let mut out = 0.;
for (x, y) in a.iter().zip(b.iter()) {
out += x*y;
}
out
}
} // mod
fn dot<'p>(py: Python<'p>, args: &PyTuple<'p>) -> PyResult<'p, f32> {
if args.len() < 2 {
// TODO: write a macro for making PyErr so it's less painful.
let msg = "dot takes two arrays of float";
let pyerr = PyErr::new_lazy_init(py.get_type::<exc::ValueError>(), Some(msg.to_py_object(py).into_object()));
return Err(pyerr);
}
let arg0 = match args.get_item(0).extract::<Vec<f32>>() {
Ok(x) => x,
Err(_) => {
let msg = "Could not convert argument 0 to array of float";
let pyerr = PyErr::new_lazy_init(py.get_type::<exc::ValueError>(), Some(msg.to_py_object(py).into_object()));
return Err(pyerr);
}
};
let arg1 = match args.get_item(1).extract::<Vec<f32>>() {
Ok(x) => x,
Err(_) => {
let msg = "Could not convert argument 0 to array of float";
let pyerr = PyErr::new_lazy_init(py.get_type::<exc::ValueError>(), Some(msg.to_py_object(py).into_object()));
return Err(pyerr);
}
};
if arg0.len() != arg1.len() {
let msg = "arg0 and arg1 must be the same length";
let pyerr = PyErr::new_lazy_init(py.get_type::<exc::ValueError>(), Some(msg.to_py_object(py).into_object()));
return Err(pyerr);
}
Ok(dot::dot(&arg0, &arg1))
}
py_module_initializer!(librust_python_example, |_py, m| {
try!(m.add("__doc__", "Dot product"));
try!(m.add("dot", py_fn!(dot)));
Ok(())
});
It works pretty well for a toy example:
In [1]: def dot(a, b):
return sum(map(lambda x: x[0]*x[1], zip(a,b)))
...:
In [2]: import numpy as np
In [3]: import librust_python_example as r
In [4]: timeit dot([0,2,3], [1,2,3])
100000 loops, best of 3: 1.86 µs per loop
In [5]: timeit np.dot([0,2,3], [1,2,3])
100000 loops, best of 3: 3.89 µs per loop
In [6]: timeit r.dot([0,2,3], [1,2,3])
1000000 loops, best of 3: 920 ns per loop
However, it won't convert numpy array
s or array.array
s:
In [8]: r.dot(np.arange(3), np.arange(3))
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-8-0e9a2e3217bb> in <module>()
----> 1 r.dot(np.arange(3), np.arange(3))
ValueError: Could not convert argument 0 to array of float
In [9]: import array
In [10]: r.dot(array.array('f', [0,2,3]), array.array('f', [1,2,3]))
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-10-3eab6b6f9184> in <module>()
----> 1 r.dot(array.array('f', [0,2,3]), array.array('f', [1,2,3]))
ValueError: Could not convert argument 0 to array of float
Metadata
Metadata
Assignees
Labels
No labels