1- // MicroPython native module wrapper for EML PLS Regression
1+ // MicroPython native module wrapper for PLS Regression
22#include "py/dynruntime.h"
33
44#include <string.h>
55
6+ // NOTE: make sure we do not use sqrtf() wrapper which uses errno, does not work in native module
67#define sqrtf __ieee754_sqrtf
78
89#include "eml_plsr.h"
@@ -17,12 +18,6 @@ void *memset(void *s, int c, size_t n) {
1718}
1819#endif
1920
20- // Hack for errno missing
21- __attribute__((visibility ("default" )))
22- int errno ;
23- int * __errno (void ) { return & errno ; }
24- int * __errno_location (void ) { return & errno ; }
25-
2621
2722// MicroPython type for PLSR model
2823typedef struct _mp_obj_plsr_model_t {
@@ -98,65 +93,6 @@ static mp_obj_t plsr_model_del(mp_obj_t self_obj) {
9893}
9994static MP_DEFINE_CONST_FUN_OBJ_1 (plsr_model_del_obj , plsr_model_del ) ;
10095
101- // Fit the model
102- static mp_obj_t plsr_model_fit (size_t n_args , const mp_obj_t * args ) {
103- // Args: self, X, y, max_iter (optional), tolerance (optional)
104- if (n_args < 3 || n_args > 5 ) {
105- mp_raise_ValueError (MP_ERROR_TEXT ("Expected 3-5 arguments: self, X, y, [max_iter], [tolerance]" ));
106- }
107-
108- mp_obj_plsr_model_t * o = MP_OBJ_TO_PTR (args [0 ]);
109- eml_plsr_t * self = & o -> model ;
110-
111- // Extract X buffer
112- mp_buffer_info_t X_bufinfo ;
113- mp_get_buffer_raise (args [1 ], & X_bufinfo , MP_BUFFER_READ );
114- if (X_bufinfo .typecode != 'f' ) {
115- mp_raise_ValueError (MP_ERROR_TEXT ("X expecting float32 array" ));
116- }
117- const float * X = X_bufinfo .buf ;
118- const int X_len = X_bufinfo .len / sizeof (float );
119-
120- // Extract y buffer
121- mp_buffer_info_t y_bufinfo ;
122- mp_get_buffer_raise (args [2 ], & y_bufinfo , MP_BUFFER_READ );
123- if (y_bufinfo .typecode != 'f' ) {
124- mp_raise_ValueError (MP_ERROR_TEXT ("y expecting float32 array" ));
125- }
126- const float * y = y_bufinfo .buf ;
127- const int y_len = y_bufinfo .len / sizeof (float );
128-
129- // Validate dimensions
130- if (X_len != o -> n_samples * o -> n_features ) {
131- mp_raise_ValueError (MP_ERROR_TEXT ("X dimensions don't match model" ));
132- }
133- if (y_len != o -> n_samples ) {
134- mp_raise_ValueError (MP_ERROR_TEXT ("y dimensions don't match model" ));
135- }
136-
137- // Get optional parameters
138- uint16_t max_iter = 100 ; // Default
139- float tolerance = 1e-6f ; // Default
140-
141- if (n_args >= 4 ) {
142- max_iter = mp_obj_get_int (args [3 ]);
143- }
144- if (n_args >= 5 ) {
145- tolerance = mp_obj_get_float_to_f (args [4 ]);
146- }
147-
148- // Perform training
149- EmlError err = eml_plsr_fit (self , X , y , max_iter , tolerance );
150-
151- if (err == EmlPostconditionFailed ) {
152- mp_raise_ValueError (MP_ERROR_TEXT ("PLSR did not converge" ));
153- } else if (err != EmlOk ) {
154- mp_raise_ValueError (MP_ERROR_TEXT ("PLSR training failed" ));
155- }
156-
157- return mp_const_none ;
158- }
159- static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (plsr_model_fit_obj , 3 , 5 , plsr_model_fit ) ;
16096
16197// Start iterative fitting
16298static mp_obj_t plsr_model_fit_start (size_t n_args , const mp_obj_t * args ) {
@@ -311,39 +247,6 @@ static mp_obj_t plsr_model_get_convergence_metric(mp_obj_t self_obj) {
311247}
312248static MP_DEFINE_CONST_FUN_OBJ_1 (plsr_model_get_convergence_metric_obj , plsr_model_get_convergence_metric ) ;
313249
314- // Get current iteration
315- static mp_obj_t plsr_model_get_current_iter (mp_obj_t self_obj ) {
316- mp_obj_plsr_model_t * o = MP_OBJ_TO_PTR (self_obj );
317- eml_plsr_t * self = & o -> model ;
318-
319- return mp_obj_new_int (self -> current_iter );
320- }
321- static MP_DEFINE_CONST_FUN_OBJ_1 (plsr_model_get_current_iter_obj , plsr_model_get_current_iter ) ;
322-
323- // Get number of components
324- static mp_obj_t plsr_model_get_n_components (mp_obj_t self_obj ) {
325- mp_obj_plsr_model_t * o = MP_OBJ_TO_PTR (self_obj );
326-
327- return mp_obj_new_int (o -> n_components );
328- }
329- static MP_DEFINE_CONST_FUN_OBJ_1 (plsr_model_get_n_components_obj , plsr_model_get_n_components ) ;
330-
331- // Get number of features
332- static mp_obj_t plsr_model_get_n_features (mp_obj_t self_obj ) {
333- mp_obj_plsr_model_t * o = MP_OBJ_TO_PTR (self_obj );
334-
335- return mp_obj_new_int (o -> n_features );
336- }
337- static MP_DEFINE_CONST_FUN_OBJ_1 (plsr_model_get_n_features_obj , plsr_model_get_n_features ) ;
338-
339- // Get number of samples
340- static mp_obj_t plsr_model_get_n_samples (mp_obj_t self_obj ) {
341- mp_obj_plsr_model_t * o = MP_OBJ_TO_PTR (self_obj );
342-
343- return mp_obj_new_int (o -> n_samples );
344- }
345- static MP_DEFINE_CONST_FUN_OBJ_1 (plsr_model_get_n_samples_obj , plsr_model_get_n_samples ) ;
346-
347250// Module setup
348251mp_map_elem_t plsr_model_locals_dict_table [8 ];
349252static MP_DEFINE_CONST_DICT (plsr_model_locals_dict , plsr_model_locals_dict_table ) ;
@@ -368,11 +271,7 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a
368271 plsr_model_locals_dict_table [5 ] = (mp_map_elem_t ){ MP_OBJ_NEW_QSTR (MP_QSTR_is_converged ), MP_OBJ_FROM_PTR (& plsr_model_is_converged_obj ) };
369272 plsr_model_locals_dict_table [6 ] = (mp_map_elem_t ){ MP_OBJ_NEW_QSTR (MP_QSTR_is_complete ), MP_OBJ_FROM_PTR (& plsr_model_is_complete_obj ) };
370273 plsr_model_locals_dict_table [7 ] = (mp_map_elem_t ){ MP_OBJ_NEW_QSTR (MP_QSTR_get_convergence_metric ), MP_OBJ_FROM_PTR (& plsr_model_get_convergence_metric_obj ) };
371- #if 0
372- plsr_model_locals_dict_table [8 ] = (mp_map_elem_t ){ MP_OBJ_NEW_QSTR (MP_QSTR_get_n_components ), MP_OBJ_FROM_PTR (& plsr_model_get_n_components_obj ) };
373- plsr_model_locals_dict_table [9 ] = (mp_map_elem_t ){ MP_OBJ_NEW_QSTR (MP_QSTR_get_n_features ), MP_OBJ_FROM_PTR (& plsr_model_get_n_features_obj ) };
374- plsr_model_locals_dict_table [10 ] = (mp_map_elem_t ){ MP_OBJ_NEW_QSTR (MP_QSTR_get_n_samples ), MP_OBJ_FROM_PTR (& plsr_model_get_n_samples_obj ) };
375- #endif
274+
376275
377276 MP_OBJ_TYPE_SET_SLOT (& plsr_model_type , locals_dict , (void * )& plsr_model_locals_dict , 8 );
378277
0 commit comments