use pyo3::prelude::*;
use pyo3::types::PyAnyMethods;
#[pyfunction]
pub fn to_i128(val: &Bound<'_, PyAny>) -> PyResult<i128> {
val.extract::<i128>()
}
#[pyfunction]
pub fn from_i128(py: Python<'_>, val: i128) -> PyResult<Py<PyAny>> {
Ok(val.into_pyobject(py)?.into_any().unbind())
}
#[pyfunction]
pub fn to_u128(val: &Bound<'_, PyAny>) -> PyResult<u128> {
val.extract::<u128>()
}
#[pyfunction]
pub fn from_u128(py: Python<'_>, val: u128) -> PyResult<Py<PyAny>> {
Ok(val.into_pyobject(py)?.into_any().unbind())
}
#[pyclass(name = "I128Array")]
pub struct I128Array {
data: Vec<i128>,
}
#[pymethods]
impl I128Array {
#[new]
pub fn new(size: usize) -> Self {
Self {
data: vec![0i128; size],
}
}
pub fn get(&self, idx: usize) -> PyResult<i128> {
self.data.get(idx).copied().ok_or_else(|| {
pyo3::exceptions::PyIndexError::new_err(format!(
"index {} out of bounds for I128Array of length {}",
idx,
self.data.len()
))
})
}
pub fn set(&mut self, idx: usize, val: i128) -> PyResult<()> {
let len = self.data.len();
self.data.get_mut(idx).map(|e| *e = val).ok_or_else(|| {
pyo3::exceptions::PyIndexError::new_err(format!(
"index {} out of bounds for I128Array of length {}",
idx, len
))
})
}
pub fn len(&self) -> usize {
self.data.len()
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
pub fn sum(&self) -> i128 {
self.data.iter().sum()
}
pub fn to_list(&self) -> Vec<i128> {
self.data.clone()
}
pub fn from_list(&mut self, values: Vec<i128>) -> PyResult<()> {
if values.len() != self.data.len() {
return Err(pyo3::exceptions::PyValueError::new_err(format!(
"expected {} elements, got {}",
self.data.len(),
values.len()
)));
}
self.data.copy_from_slice(&values);
Ok(())
}
}
#[pyclass(name = "U128Array")]
pub struct U128Array {
data: Vec<u128>,
}
#[pymethods]
impl U128Array {
#[new]
pub fn new(size: usize) -> Self {
Self {
data: vec![0u128; size],
}
}
pub fn get(&self, idx: usize) -> PyResult<u128> {
self.data.get(idx).copied().ok_or_else(|| {
pyo3::exceptions::PyIndexError::new_err(format!(
"index {} out of bounds for U128Array of length {}",
idx,
self.data.len()
))
})
}
pub fn set(&mut self, idx: usize, val: u128) -> PyResult<()> {
let len = self.data.len();
self.data.get_mut(idx).map(|e| *e = val).ok_or_else(|| {
pyo3::exceptions::PyIndexError::new_err(format!(
"index {} out of bounds for U128Array of length {}",
idx, len
))
})
}
pub fn len(&self) -> usize {
self.data.len()
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
pub fn sum(&self) -> u128 {
self.data.iter().sum()
}
pub fn to_list(&self) -> Vec<u128> {
self.data.clone()
}
pub fn from_list(&mut self, values: Vec<u128>) -> PyResult<()> {
if values.len() != self.data.len() {
return Err(pyo3::exceptions::PyValueError::new_err(format!(
"expected {} elements, got {}",
self.data.len(),
values.len()
)));
}
self.data.copy_from_slice(&values);
Ok(())
}
}
pub fn register_extended_int_module(_py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::<I128Array>()?;
m.add_class::<U128Array>()?;
m.add_function(wrap_pyfunction!(to_i128, m)?)?;
m.add_function(wrap_pyfunction!(from_i128, m)?)?;
m.add_function(wrap_pyfunction!(to_u128, m)?)?;
m.add_function(wrap_pyfunction!(from_u128, m)?)?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn i128_array_basic_operations() {
let mut arr = I128Array::new(3);
assert_eq!(arr.len(), 3);
assert_eq!(arr.sum(), 0);
arr.set(0, 100).expect("set index 0");
arr.set(1, 200).expect("set index 1");
arr.set(2, 300).expect("set index 2");
assert_eq!(arr.get(1).expect("get index 1"), 200);
assert_eq!(arr.sum(), 600);
assert_eq!(arr.to_list(), vec![100i128, 200, 300]);
}
#[test]
fn i128_array_out_of_bounds() {
let arr = I128Array::new(2);
assert!(arr.get(99).is_err());
}
#[test]
fn i128_to_from_roundtrip() {
Python::attach(|py| {
let py_int = from_i128(py, i128::MAX).expect("from_i128 failed");
let val = to_i128(py_int.bind(py)).expect("to_i128 failed");
assert_eq!(val, i128::MAX);
});
}
#[test]
fn u128_roundtrip() {
Python::attach(|py| {
let py_int = from_u128(py, u128::MAX).expect("from_u128 failed");
let val = to_u128(py_int.bind(py)).expect("to_u128 failed");
assert_eq!(val, u128::MAX);
});
}
#[test]
fn u128_array_basic_operations() {
let mut arr = U128Array::new(2);
arr.set(0, u128::MAX).expect("set 0");
assert_eq!(arr.get(0).expect("get 0"), u128::MAX);
assert!(arr.get(5).is_err());
}
}