ftp_core/holding_struct.rs
1/// Structure principale contenant tous les résultats des calculs FTP
2///
3/// # Fields
4///
5/// - `input_outstanding`: Montants outstanding
6/// - `input_profiles`: Profils de flux
7/// - `input_rate`: Taux d'entrée
8/// - `stock_amort`: Stock amorti (optionnel)
9/// - `stock_instal`: Stock installé (optionnel)
10/// - `varstock_amort`: Stock variable amorti (optionnel)
11/// - `varstock_instal`: Stock variable installé (optionnel)
12/// - `ftp_rate`: Taux FTP calculé (optionnel)
13/// - `ftp_int`: Intérêts FTP calculés (optionnel)
14/// - `market_rate`: Taux de marché (optionnel)
15///
16/// # Exemples
17///
18/// ```
19/// use ftp_core::FtpResult;
20/// use ndarray::array;
21///
22/// let result = FtpResult::new(
23/// array![[1000.0]],
24/// array![[1.0, 0.5, 0.2]],
25/// array![[0.01, 0.02]]
26/// );
27/// ```
28///
29use crate::method_flux::flux_func_stock_amort::flux_func_stock_amort;
30use crate::method_flux::flux_func_stock_var::flux_func_stock_var;
31use ndarray::Array2;
32// use pyo3::prelude::*;
33// use pyo3::types::PyType;
34// use numpy::PyArray2;
35
36// #[pyclass]
37// pub struct PyFtpResult {
38// #[pyo3(get, set)]
39// pub input_outstanding: Py<PyArray2<f64>>,
40// #[pyo3(get, set)]
41// pub input_profiles: Py<PyArray2<f64>>,
42// #[pyo3(get, set)]
43// pub input_rate: Py<PyArray2<f64>>,
44// #[pyo3(get, set)]
45// pub stock_amort: Option<Py<PyArray2<f64>>>,
46// #[pyo3(get, set)]
47// pub stock_instal: Option<Py<PyArray2<f64>>>,
48// #[pyo3(get, set)]
49// pub varstock_amort: Option<Py<PyArray2<f64>>>,
50// #[pyo3(get, set)]
51// pub varstock_instal: Option<Py<PyArray2<f64>>>,
52// #[pyo3(get, set)]
53// pub ftp_rate: Option<Py<PyArray2<f64>>>,
54// #[pyo3(get, set)]
55// pub ftp_int: Option<Py<PyArray2<f64>>>,
56// #[pyo3(get, set)]
57// pub market_rate: Option<Py<PyArray2<f64>>>,
58// }
59
60pub struct FtpResult {
61 pub input_outstanding: Array2<f64>,
62 pub input_profiles: Array2<f64>,
63 pub input_rate: Array2<f64>,
64 pub stock_amort: Option<Array2<f64>>,
65 pub stock_instal: Option<Array2<f64>>,
66 pub varstock_amort: Option<Array2<f64>>, // or new prod amort
67 pub varstock_instal: Option<Array2<f64>>, // or new prod instal
68 pub ftp_rate: Option<Array2<f64>>,
69 pub ftp_int: Option<Array2<f64>>,
70 pub market_rate: Option<Array2<f64>>,
71}
72
73//
74// impl From<FtpResult> for PyFtpResult {
75// fn from(ftp_result: FtpResult) -> Self {
76// Python::with_gil(|py| {
77// PyFtpResult {
78// input_outstanding: PyArray2::from_owned_array(py, ftp_result.input_outstanding).into(),
79// input_profiles: PyArray2::from_owned_array(py, ftp_result.input_profiles).into(),
80// input_rate: PyArray2::from_owned_array(py, ftp_result.input_rate).into(),
81// stock_amort: ftp_result.stock_amort.map(|arr| PyArray2::from_owned_array(py, arr).into()),
82// stock_instal: ftp_result.stock_instal.map(|arr| PyArray2::from_owned_array(py, arr).into()),
83// varstock_amort: ftp_result.varstock_amort.map(|arr| PyArray2::from_owned_array(py, arr).into()),
84// varstock_instal: ftp_result.varstock_instal.map(|arr| PyArray2::from_owned_array(py, arr).into()),
85// ftp_rate: ftp_result.ftp_rate.map(|arr| PyArray2::from_owned_array(py, arr).into()),
86// ftp_int: ftp_result.ftp_int.map(|arr| PyArray2::from_owned_array(py, arr).into()),
87// market_rate: ftp_result.market_rate.map(|arr| PyArray2::from_owned_array(py, arr).into()),
88// }
89// })
90// }
91// }
92
93// #[pymethods]
94// impl PyFtpResult {
95// #[new]
96// fn new(
97// input_outstanding: Py<PyArray2<f64>>,
98// input_profiles: Py<PyArray2<f64>>,
99// input_rate: Py<PyArray2<f64>>,
100// ) -> Self {
101// Self {
102// input_outstanding,
103// input_profiles,
104// input_rate,
105// stock_amort: None,
106// stock_instal: None,
107// varstock_amort: None,
108// varstock_instal: None,
109// ftp_rate: None,
110// ftp_int: None,
111// market_rate: None,
112// }
113// }
114//
115// fn __repr__(&self) -> String {
116// Python::with_gil(|py| {
117// format!(
118// "PyFtpResult(outstanding: {:?}, profiles: {:?}, rate: {:?})",
119// self.input_outstanding.as_ref(py).shape(),
120// self.input_profiles.as_ref(py).shape(),
121// self.input_rate.as_ref(py).shape()
122// )
123// })
124// }
125//
126// fn __str__(&self) -> String {
127// self.__repr__()
128// }
129//
130// /// Retourne la liste des attributs disponibles
131// fn __dir__(&self, py: Python<'_>) -> Vec<String> {
132// vec![
133// "input_outstanding".to_string(),
134// "input_profiles".to_string(),
135// "input_rate".to_string(),
136// "stock_amort".to_string(),
137// "stock_instal".to_string(),
138// "varstock_amort".to_string(), // or new prod amort
139// "varstock_instal".to_string(), // or new prod instal
140// "ftp_rate".to_string(),
141// "ftp_int".to_string(),
142// "market_rate".to_string(),
143// ]
144// }
145//
146// }
147//
148
149use crate::common::func_stock_instal::func_stock_instal;
150use crate::common::func_stock_var_instal::func_stock_var_instal;
151use crate::common::{
152 func_ftp_int::func_ftp_int, func_ftp_rate::func_ftp_rate, func_market_rate::func_market_rate,
153};
154use crate::method_stock::{func_stock_amort::func_stock_amort, func_stock_var::func_stock_var};
155
156impl FtpResult {
157 fn check_dims(&self) {
158 let (nrows_outs, ncols_outs) = self.input_outstanding.dim();
159 let (nrows_profiles, ncols_profiles) = self.input_profiles.dim();
160 let (nrows_rate, ncols_rate) = self.input_rate.dim();
161
162 if (nrows_outs != nrows_profiles)
163 || (nrows_outs != nrows_rate)
164 || (nrows_profiles != nrows_rate)
165 {
166 panic!("Toutes les matrices d'inputs doivent avoir le meme nombre de ligne");
167 }
168 if ncols_outs != 1 {
169 panic!("'input outstanding' doit avoir une colonne !");
170 }
171 if ncols_profiles - 1 != ncols_rate {
172 panic!("'input_rate' doit avoir une colonne de moins que 'input_profiles'");
173 }
174 }
175
176 fn init_arrays(&mut self, nrows: usize, ncols: usize) {
177 self.stock_amort = Some(Array2::<f64>::zeros((nrows, ncols)));
178 self.stock_instal = Some(Array2::<f64>::zeros((nrows, ncols)));
179 self.varstock_amort = Some(Array2::<f64>::zeros((nrows, ncols)));
180 self.varstock_instal = Some(Array2::<f64>::zeros((nrows, ncols)));
181 self.ftp_rate = Some(Array2::<f64>::zeros((nrows, ncols)));
182 self.ftp_int = Some(Array2::<f64>::zeros((nrows, ncols)));
183 self.market_rate = Some(Array2::<f64>::zeros((nrows, ncols)));
184 }
185
186 pub fn new(
187 input_outstanding: Array2<f64>,
188 input_profiles: Array2<f64>,
189 input_rate: Array2<f64>,
190 ) -> Self {
191 Self {
192 input_outstanding,
193 input_profiles,
194 input_rate,
195 stock_amort: None,
196 stock_instal: None,
197 varstock_amort: None,
198 varstock_instal: None,
199 ftp_rate: None,
200 ftp_int: None,
201 market_rate: None,
202 }
203 }
204
205 pub fn compute(&mut self, method: String) {
206 // Check dimensions
207 self.check_dims();
208
209 let (nrows, ncols) = self.input_profiles.dim();
210
211 self.init_arrays(nrows, ncols);
212
213 if method == "stock" {
214 // Implementation for "stock" method
215 for i in 0..nrows {
216 for j in 0..ncols {
217 func_stock_amort(self, i, j);
218 func_stock_instal(self, i, j);
219 func_stock_var(self, i, j, ncols);
220 func_stock_var_instal(self, i, j);
221 }
222
223 for j in (0..ncols).rev() {
224 if j > 0 {
225 func_ftp_rate(self, i, j - 1, ncols);
226 func_ftp_int(self, i, j - 1, ncols);
227 func_market_rate(self, i, j, ncols);
228 }
229 }
230 }
231 } else if method == "flux" {
232 // Implementation for "flux" method
233 for i in 0..nrows {
234 for j in 0..ncols {
235 flux_func_stock_var(self, i, j); // new prod
236 func_stock_var_instal(self, i, j);
237
238 flux_func_stock_amort(self, i, j);
239 func_stock_instal(self, i, j);
240 }
241
242 for j in (0..ncols).rev() {
243 if j > 0 {
244 func_ftp_rate(self, i, j - 1, ncols);
245 func_ftp_int(self, i, j - 1, ncols);
246 func_market_rate(self, i, j, ncols);
247 }
248 }
249 }
250 } else {
251 // Handle other methods or errors
252 }
253 }
254}