tachyon_math_library/
accessors.rs1use crate::{reduce_value_codes, FunctionType, Interpolation, ValueCode, NUM_VALUES};
2use anchor_lang::prelude::*;
3use num_traits::{FromPrimitive, ToPrimitive};
4use rust_decimal::Decimal;
5
6use crate::error::ErrorCode;
7
8pub trait FunctionDataAccessors {
9 fn eval(&self, x: Decimal, interp: Interpolation, saturating: bool) -> Result<Decimal>;
10 fn eval_load(&self, x_in: Decimal, y_in: Decimal) -> Result<(Decimal, ValueCode)>;
11
12 fn get_values_array(&self) -> &[[u8; 16]; NUM_VALUES];
13 fn get_value_codes_array(&self) -> &[u8; NUM_VALUES];
14
15 fn get_values_array_mut(&mut self) -> &mut [[u8; 16]; NUM_VALUES];
16 fn get_value_codes_array_mut(&mut self) -> &mut [u8; NUM_VALUES];
17
18 fn get_function_type(&self) -> u32;
19 fn set_function_type(&mut self, ft: FunctionType) -> Result<()>;
20
21 fn get_domain_start(&self) -> Result<Decimal>;
22 fn set_domain_start(&mut self, domain_start_raw: [u8; 16]) -> Result<()>;
23
24 fn get_domain_end(&self) -> Result<Decimal>;
25 fn set_domain_end(&mut self, domain_end_raw: [u8; 16]) -> Result<()>;
26
27 fn get_interval(&self) -> Result<Decimal>;
28 fn set_interval(&mut self, interval: [u8; 16]) -> Result<()>;
29
30 fn get_num_values_loaded(&self) -> u32;
31 fn increment_num_values_loaded(&mut self) -> Result<()>;
32
33 fn get_is_initialized(&self) -> bool;
34 fn set_initialized_true(&mut self) -> Result<()>;
35
36 fn set_value(&mut self, index: u32, value: [u8; 16], value_code: u8) -> Result<()> {
37 let existing_code_u8 = self.get_value_code(index)?;
38 let existing_code = ValueCode::try_from(existing_code_u8).unwrap();
39
40 if existing_code != ValueCode::Empty {
42 return err!(ErrorCode::DataAtIndexAlreadyLoaded);
43 }
44
45 self.get_values_array_mut()[index as usize] = value;
46 self.get_value_codes_array_mut()[index as usize] = value_code;
47
48 Ok(())
49 }
50
51 fn get_value(&self, index: u32) -> Result<Decimal> {
52 Ok(Decimal::deserialize(self.get_values_array()[index as usize]))
53 }
54
55 fn get_value_code(&self, index: u32) -> Result<u8> {
56 Ok(self.get_value_codes_array()[index as usize])
57 }
58
59 fn reduce_value_codes_from_indices(&self, indices: Vec<u32>) -> Result<ValueCode> {
60 let codes = indices.into_iter().map(|x| self.get_value_code(x).unwrap()).collect::<Vec<u8>>();
61 Ok(reduce_value_codes(codes))
62 }
63
64 fn get_domain(&self) -> Result<Decimal> {
65 let domain = (self.get_domain_end()? - self.get_domain_start()?).abs();
66 Ok(domain)
67 }
68
69 fn get_x_from_index(&self, index: u32) -> Result<Decimal> {
70 let index_prop = Decimal::from_u32(index).unwrap() / (Decimal::from_u32(self.get_num_values()?).unwrap() - Decimal::ONE);
71 let x = index_prop * self.get_domain()? + self.get_domain_start()?;
72 Ok(x)
73 }
74
75 fn get_num_values(&self) -> Result<u32>;
76 fn set_num_values(&mut self, num_values: u32) -> Result<()>;
77
78 fn get_index_bounds(&self, x: Decimal) -> Result<(u32, u32, Decimal)> {
79 let domain_start = self.get_domain_start()?;
80 let domain_end = self.get_domain_end()?;
81 let num_values = Decimal::from_u32(self.get_num_values()?).unwrap();
82
83 let index_decimal = ((x - domain_start) / (domain_end - domain_start)) * (num_values - Decimal::ONE);
85
86 let lower_index = index_decimal.floor().to_u32().unwrap();
88 let upper_index = index_decimal.ceil().to_u32().unwrap();
89
90 Ok((lower_index, upper_index, index_decimal))
91 }
92}