use crate::error::check_ampl_error;
use crate::ffi;
use crate::ampl::Ampl;
use libc::c_char;
use std::ffi::{CStr, CString};
use std::ptr;
pub struct Parameter {
raw: *mut ffi::AMPL,
name: String,
}
impl Parameter {
pub fn new(ampl: &mut Ampl, name: String) -> Self {
Parameter { raw: ampl.raw, name:name }
}
pub fn print(&self) {
println!("Parameter: {}", self.name);
}
pub fn indexarity(&self) -> usize {
let name = CString::new(&*self.name).unwrap();
let mut indexarity: usize = 0;
let err = unsafe { ffi::AMPL_EntityGetIndexarity(self.raw, name.as_ptr(), &mut indexarity as *mut usize) };
unsafe { check_ampl_error(err) };
indexarity
}
pub fn num_instances(&self) -> usize {
let name = CString::new(&*self.name).unwrap();
let mut num_instances: usize = 0;
let err = unsafe { ffi::AMPL_EntityGetNumInstances(self.raw, name.as_ptr(), &mut num_instances as *mut usize) };
unsafe { check_ampl_error(err) };
num_instances
}
pub fn declaration(&mut self) -> String {
let name = CString::new(&*self.name).unwrap();
let mut value_ptr: *mut c_char = ptr::null_mut();
unsafe {
let err = ffi::AMPL_EntityGetDeclaration(self.raw, name.as_ptr(), &mut value_ptr);
check_ampl_error(err);
if value_ptr.is_null() {
return String::new();
}
let value_str = CStr::from_ptr(value_ptr).to_str().unwrap().to_string();
ffi::AMPL_StringFree(&mut value_ptr);
value_str
}
}
pub fn set_all_double_values(&self, values: &[f64]) {
let name = CString::new(&*self.name).unwrap();
let err = unsafe {
ffi::AMPL_ParameterSetArgsDoubleValues(self.raw, name.as_ptr(), values.len(), values.as_ptr())
};
unsafe { check_ampl_error(err) };
}
pub fn set_some_double_values(&self, indices: &[&str], values: &[f64]) {
assert_eq!(indices.len(), values.len());
let name = CString::new(&*self.name).unwrap();
let mut tuples: Vec<*mut ffi::AMPL_TUPLE> = indices.iter().map(|&s| {
let cs = CString::new(s).unwrap();
let p = cs.as_ptr();
let mut tuple: *mut ffi::AMPL_TUPLE = ptr::null_mut();
unsafe { ffi::AMPL_TupleCreateString(&mut tuple, 1, &p) };
std::mem::forget(cs);
tuple
}).collect();
let mut vals = values.to_vec();
unsafe {
let err = ffi::AMPL_ParameterSetSomeDoubleValues(
self.raw,
name.as_ptr(),
tuples.len(),
tuples.as_mut_ptr(),
vals.as_mut_ptr(),
);
check_ampl_error(err);
for t in &mut tuples {
ffi::AMPL_TupleFree(t);
}
}
}
pub fn drop(&self) {
let name = CString::new(&*self.name).unwrap();
let err = unsafe { ffi::AMPL_EntityDrop(self.raw, name.as_ptr()) };
unsafe { check_ampl_error(err) };
}
pub fn restore(&self) {
let name = CString::new(&*self.name).unwrap();
let err = unsafe { ffi::AMPL_EntityRestore(self.raw, name.as_ptr()) };
unsafe { check_ampl_error(err) };
}
}