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}