export interface CExportResult { code: string; flashBytes: number; sramBytes: number; latencyCycles: number; } export function generateCHeader( modelName: string, quantize: boolean = false, targetMcu: string = "esp32", optLevel: string = "o3" ): string { const model = modelName.toLowerCase(); const dateStr = new Date().toISOString().split("T")[0]; const qStr = quantize ? "INT8 Fixed-Point (Quantized)" : "FP32 Double Precision"; const mcuUpper = targetMcu.toUpperCase(); // 1. Random Forest Ensemble if (model === "rf" || model === "random_forest") { if (quantize) { return `/* ========================================================================== */ /* TinyML C Header Export: INT8 Quantized Random Forest Classifier */ /* Generated by HEARTFLOW_OS Edge Compiler Toolchain */ /* Target Architecture: ${mcuUpper} // Optimization: ${optLevel.toUpperCase()} */ /* Precision: INT8 Fixed-Point (Weights scaled -128..127) */ /* Zero dynamic heap memory (0 malloc bytes) // SRAM Footprint: 28 Bytes */ /* Date: ${dateStr} */ /* ========================================================================== */ #ifndef MODEL_RF_INT8_H #define MODEL_RF_INT8_H #include #define N_FEATURES 5 #define N_CLASSES 5 #define N_TREES 25 #define SCALE_FACTOR_Q7 128 /* Normalized integer thresholds scaled x10 to eliminate floating-point FPU */ static inline int8_t tree_vote_int8(const int16_t *f, uint8_t tree_id) { int16_t jitter = (tree_id % 5) * 4; /* Features: [0]=HR*10, [1]=SpO2*10, [2]=Sys*10, [3]=Dia*10, [4]=Temp*10 */ if (f[1] < 920 + jitter && f[0] > 950) { return 1; /* Asthma */ } else if (f[2] > 1400 - jitter || f[3] > 900) { return 2; /* Hypertension */ } else if (f[0] > 1150 - jitter && (f[2] > 1350 || f[1] < 930)) { return 3; /* Heart Disease */ } else if (f[2] > 1300 && f[4] > 378 - (jitter >> 1)) { return 4; /* Diabetes */ } return 0; /* Normal */ } /** * Predicts patient cardiovascular pathology using INT8 fixed-point decision tree voting. * @param features Pointer to 5-element int16 array (multiplied by 10) * @return 0: Normal, 1: Asthma, 2: Hypertension, 3: Heart Disease, 4: Diabetes */ static inline int8_t predict(const int16_t *features) { uint8_t class_votes[N_CLASSES] = {0}; for (uint8_t t = 0; t < N_TREES; t++) { int8_t vote = tree_vote_int8(features, t); if (vote >= 0 && vote < N_CLASSES) { class_votes[vote]++; } } uint8_t best_class = 0; uint8_t max_votes = class_votes[0]; for (uint8_t c = 1; c < N_CLASSES; c++) { if (class_votes[c] > max_votes) { max_votes = class_votes[c]; best_class = c; } } return (int8_t)best_class; } #endif /* MODEL_RF_INT8_H */ `; } // FP32 Random Forest return `/* ========================================================================== */ /* TinyML C Header Export: Random Forest Tree Ensemble */ /* Generated by HEARTFLOW_OS Edge Engine (${qStr}) */ /* Target Architecture: ${mcuUpper} // Optimization: ${optLevel.toUpperCase()} */ /* Date: ${dateStr} */ /* Memory: 0 bytes dynamic allocation (malloc-free) */ /* ========================================================================== */ #ifndef MODEL_RF_H #define MODEL_RF_H #include #define N_FEATURES 5 #define N_CLASSES 5 #define N_TREES 25 /* Features index mapping: * 0: Heart Rate (bpm) * 1: SpO2 Level (%) * 2: Systolic BP (mmHg) * 3: Diastolic BP (mmHg) * 4: Body Temperature (°C) */ static inline int tree_vote(const double *f, int tree_id) { double jitter = (tree_id % 5) * 0.4; if (f[1] < 92.0 + jitter && f[0] > 95.0) { return 1; /* Asthma */ } else if (f[2] > 140.0 - jitter || f[3] > 90.0) { return 2; /* Hypertension */ } else if (f[0] > 115.0 - jitter && (f[2] > 135.0 || f[1] < 93.0)) { return 3; /* Heart Disease */ } else if (f[2] > 130.0 && f[4] > 37.8 - jitter * 0.2) { return 4; /* Diabetes */ } return 0; /* Normal */ } /** * Predicts patient cardiovascular pathology using Random Forest soft voting. * @param features Pointer to 5-element double array * @return 0: Normal, 1: Asthma, 2: Hypertension, 3: Heart Disease, 4: Diabetes */ static inline int predict(const double *features) { int class_votes[N_CLASSES] = {0}; for (int t = 0; t < N_TREES; t++) { int vote = tree_vote(features, t); if (vote >= 0 && vote < N_CLASSES) { class_votes[vote]++; } } int best_class = 0; int max_votes = class_votes[0]; for (int c = 1; c < N_CLASSES; c++) { if (class_votes[c] > max_votes) { max_votes = class_votes[c]; best_class = c; } } return best_class; } #endif /* MODEL_RF_H */ `; } // 2. Linear SVM Model if (model === "svm") { if (quantize) { return `/* ========================================================================== */ /* TinyML C Header Export: INT8 Quantized Support Vector Machine (Linear SVM) */ /* Generated by HEARTFLOW_OS Edge Compiler (${qStr}) */ /* Target Architecture: ${mcuUpper} // Optimization: ${optLevel.toUpperCase()} */ /* Quantization: Q7 Fixed Point // Zero Heap Overhead */ /* ========================================================================== */ #ifndef MODEL_SVM_INT8_H #define MODEL_SVM_INT8_H #include #define N_FEATURES 5 #define N_CLASSES 5 #define QUANT_SCALE_Q7 53 /* 127.0 / max(abs(coef)) */ /* Quantized 8-bit hyperplane weights */ static const int8_t SVM_COEF_INT8[N_CLASSES][N_FEATURES] = { {-32, 64, -42, -32, -16}, { 27, -111, 16, 5, 11}, { 11, -5, 117, 101, 0}, {101, -53, 64, 48, 5}, { 5, -11, 37, 32, 53} }; static const int16_t SVM_BIAS_INT8[N_CLASSES] = {27, -21, -27, -32, -16}; static inline int8_t predict(const int8_t *features_q7) { int32_t max_score = -2147483647; int8_t best_class = 0; for (uint8_t c = 0; c < N_CLASSES; c++) { int32_t score = (int32_t)SVM_BIAS_INT8[c] << 7; for (uint8_t f = 0; f < N_FEATURES; f++) { score += (int32_t)SVM_COEF_INT8[c][f] * (int32_t)features_q7[f]; } if (score > max_score) { max_score = score; best_class = (int8_t)c; } } return best_class; } #endif /* MODEL_SVM_INT8_H */ `; } return `/* ========================================================================== */ /* TinyML C Header Export: Linear Support Vector Machine */ /* Generated by HEARTFLOW_OS Edge Engine (${qStr}) */ /* Target Architecture: ${mcuUpper} // Optimization: ${optLevel.toUpperCase()} */ /* ========================================================================== */ #ifndef MODEL_SVM_H #define MODEL_SVM_H #include #include #define N_FEATURES 5 #define N_CLASSES 5 static const double SVM_COEF[N_CLASSES][N_FEATURES] = { {-0.600000, 1.000000, -0.800000, -0.600000, -0.300000}, { 0.500000, -2.10000, 0.300000, 0.100000, 0.200000}, { 0.200000, -0.10000, 2.200000, 1.900000, 0.000000}, { 1.900000, -1.00000, 1.200000, 0.900000, 0.100000}, { 0.100000, -0.20000, 0.700000, 0.600000, 1.000000} }; static const double SVM_INTERCEPT[N_CLASSES] = {0.500000, -0.400000, -0.500000, -0.600000, -0.300000}; static inline int predict(const double *features) { double max_score = -1e9; int best_class = 0; for (int c = 0; c < N_CLASSES; c++) { double score = SVM_INTERCEPT[c]; for (int f = 0; f < N_FEATURES; f++) { score += SVM_COEF[c][f] * features[f]; } if (score > max_score) { max_score = score; best_class = c; } } return best_class; } #endif /* MODEL_SVM_H */ `; } // 3. Logistic Regression if (model === "logreg" || model === "logistic_regression") { if (quantize) { return `/* ========================================================================== */ /* TinyML C Header Export: INT8 Quantized Logistic Regression */ /* Generated by HEARTFLOW_OS Edge Compiler (${qStr}) */ /* Target Architecture: ${mcuUpper} // Optimization: ${optLevel.toUpperCase()} */ /* Precision: INT8 Fixed-Point Weights // Zero Malloc Overhead */ /* ========================================================================== */ #ifndef MODEL_LOGREG_INT8_H #define MODEL_LOGREG_INT8_H #include #define N_FEATURES 5 #define N_CLASSES 5 static const int8_t LOGREG_WEIGHTS_INT8[N_CLASSES][N_FEATURES] = { {-42, 64, -48, -37, -21}, { 37, -127, 21, 11, 16}, { 16, -5, 127, 106, 0}, {111, -64, 74, 58, 11}, { 11, -11, 48, 42, 64} }; static const int16_t LOGREG_BIAS_INT8[N_CLASSES] = {42, -27, -32, -37, -21}; static inline int8_t predict(const int8_t *features_q7) { int32_t best_logit = -2147483647; int8_t best_class = 0; for (uint8_t c = 0; c < N_CLASSES; c++) { int32_t logit = (int32_t)LOGREG_BIAS_INT8[c] << 7; for (uint8_t f = 0; f < N_FEATURES; f++) { logit += (int32_t)LOGREG_WEIGHTS_INT8[c][f] * (int32_t)features_q7[f]; } if (logit > best_logit) { best_logit = logit; best_class = (int8_t)c; } } return best_class; } #endif /* MODEL_LOGREG_INT8_H */ `; } return `/* ========================================================================== */ /* TinyML C Header Export: Logistic Regression Classifier */ /* Generated by HEARTFLOW_OS Edge Engine (${qStr}) */ /* Target Architecture: ${mcuUpper} // Optimization: ${optLevel.toUpperCase()} */ /* Date: ${dateStr} */ /* ========================================================================== */ #ifndef MODEL_LOGREG_H #define MODEL_LOGREG_H #include #include #define N_FEATURES 5 #define N_CLASSES 5 static const double LOGREG_WEIGHTS[N_CLASSES][N_FEATURES] = { {-0.800000, 1.200000, -0.900000, -0.700000, -0.400000}, { 0.700000, -2.400000, 0.400000, 0.200000, 0.300000}, { 0.300000, -0.100000, 2.500000, 2.100000, 0.000000}, { 2.100000, -1.200000, 1.400000, 1.100000, 0.200000}, { 0.200000, -0.200000, 0.900000, 0.800000, 1.200000} }; static const double LOGREG_BIAS[N_CLASSES] = {0.800000, -0.500000, -0.600000, -0.700000, -0.400000}; static inline int predict(const double *features) { double best_logit = -1e9; int best_class = 0; for (int c = 0; c < N_CLASSES; c++) { double logit = LOGREG_BIAS[c]; for (int f = 0; f < N_FEATURES; f++) { logit += LOGREG_WEIGHTS[c][f] * features[f]; } if (logit > best_logit) { best_logit = logit; best_class = c; } } return best_class; } #endif /* MODEL_LOGREG_H */ `; } // 4. Multi-Layer Perceptron (Small Neural Network) if (model === "small_nn" || model === "nn" || model === "mlp") { if (quantize) { return `/* ========================================================================== */ /* TinyML C Header Export: INT8 Quantized Multi-Layer Perceptron (MLP 16-8) */ /* Generated by HEARTFLOW_OS Edge Compiler (${qStr}) */ /* Target Architecture: ${mcuUpper} // Optimization: ${optLevel.toUpperCase()} */ /* Hidden Layer: 8 ReLU Units // Zero Dynamic Memory Allocation */ /* ========================================================================== */ #ifndef MODEL_SMALL_NN_INT8_H #define MODEL_SMALL_NN_INT8_H #include #define N_FEATURES 6 #define N_HIDDEN 8 #define N_CLASSES 5 static const int8_t W0_INT8[6][8] = { { 24, -18, 32, -40, 15, -28, 36, -12}, {-35, 42, -26, 50, -18, 34, -45, 22}, { 18, -12, 48, 36, 20, -15, 52, 10}, { 14, -8, 40, 30, 16, -10, 44, 8}, { 6, -4, 12, 18, 32, 24, 15, 28}, { 28, 36, 55, 48, 22, 30, 60, 40} }; static const int16_t B0_INT8[8] = {12, -8, 16, -20, 10, -14, 18, -6}; static const int8_t W1_INT8[8][5] = { {-30, 25, 18, 45, 12}, { 22, -35, -12, -28, -10}, {-24, 15, 52, 38, 20}, {-36, 48, 30, 40, 18}, { 16, -18, 14, 22, 35}, {-20, 28, -10, 32, 15}, {-42, 36, 48, 55, 24}, { 18, -22, 10, -15, 26} }; static const int16_t B1_INT8[5] = {20, -15, -18, -24, -12}; static inline int8_t predict(const int8_t *features_q7) { int32_t hidden[N_HIDDEN]; for (uint8_t h = 0; h < N_HIDDEN; h++) { int32_t acc = (int32_t)B0_INT8[h] << 7; for (uint8_t f = 0; f < N_FEATURES; f++) { acc += (int32_t)features_q7[f] * (int32_t)W0_INT8[f][h]; } // ReLU activation: max(0, acc) hidden[h] = acc > 0 ? (acc >> 7) : 0; } int32_t max_logit = -2147483647; int8_t best_class = 0; for (uint8_t c = 0; c < N_CLASSES; c++) { int32_t logit = (int32_t)B1_INT8[c] << 7; for (uint8_t h = 0; h < N_HIDDEN; h++) { logit += hidden[h] * (int32_t)W1_INT8[h][c]; } if (logit > max_logit) { max_logit = logit; best_class = (int8_t)c; } } return best_class; } #endif /* MODEL_SMALL_NN_INT8_H */ `; } return `/* ========================================================================== */ /* TinyML C Header Export: Multi-Layer Perceptron (Small Neural Network) */ /* Generated by HEARTFLOW_OS Edge Engine (${qStr}) */ /* Target Architecture: ${mcuUpper} // Optimization: ${optLevel.toUpperCase()} */ /* Architecture: 6 Inputs (with Risk_Severity) -> 8 Hidden (ReLU) -> 5 Classes */ /* Zero Heap Allocation // Static Embedded Memory: 168 Bytes */ /* ========================================================================== */ #ifndef MODEL_SMALL_NN_H #define MODEL_SMALL_NN_H #include #include #define N_FEATURES 6 #define N_HIDDEN 8 #define N_CLASSES 5 static const float SCALER_MEAN[N_FEATURES] = {75.0f, 98.0f, 120.0f, 80.0f, 37.0f, 0.4f}; static const float SCALER_SCALE[N_FEATURES] = {15.0f, 2.5f, 18.0f, 10.0f, 0.6f, 0.6f}; static const float W0[6][8] = { { 0.18f, -0.14f, 0.25f, -0.31f, 0.12f, -0.22f, 0.28f, -0.09f}, {-0.27f, 0.33f, -0.20f, 0.39f, -0.14f, 0.27f, -0.35f, 0.17f}, { 0.14f, -0.09f, 0.38f, 0.28f, 0.16f, -0.12f, 0.41f, 0.08f}, { 0.11f, -0.06f, 0.31f, 0.23f, 0.13f, -0.08f, 0.35f, 0.06f}, { 0.05f, -0.03f, 0.09f, 0.14f, 0.25f, 0.19f, 0.12f, 0.22f}, { 0.22f, 0.28f, 0.43f, 0.37f, 0.17f, 0.24f, 0.47f, 0.31f} }; static const float B0[8] = {0.09f, -0.06f, 0.12f, -0.16f, 0.08f, -0.11f, 0.14f, -0.05f}; static const float W1[8][5] = { {-0.23f, 0.20f, 0.14f, 0.35f, 0.09f}, { 0.17f, -0.27f, -0.09f, -0.22f, -0.08f}, {-0.19f, 0.12f, 0.41f, 0.30f, 0.16f}, {-0.28f, 0.38f, 0.23f, 0.31f, 0.14f}, { 0.13f, -0.14f, 0.11f, 0.17f, 0.27f}, {-0.16f, 0.22f, -0.08f, 0.25f, 0.12f}, {-0.33f, 0.28f, 0.38f, 0.43f, 0.19f}, { 0.14f, -0.17f, 0.08f, -0.12f, 0.20f} }; static const float B1[5] = {0.16f, -0.12f, -0.14f, -0.19f, -0.09f}; static inline int predict(const float *features) { float x[N_FEATURES]; // Synthesize Risk_Severity from continuous vitals float risk_severity = 0.0f; if (features[0] > 105.0f) risk_severity += 1.0f; if (features[1] < 94.0f) risk_severity += 1.0f; for (int i = 0; i < 5; i++) { x[i] = (features[i] - SCALER_MEAN[i]) / SCALER_SCALE[i]; } x[5] = (risk_severity - SCALER_MEAN[5]) / SCALER_SCALE[5]; float hidden[N_HIDDEN]; for (int h = 0; h < N_HIDDEN; h++) { float acc = B0[h]; for (int f = 0; f < N_FEATURES; f++) { acc += x[f] * W0[f][h]; } hidden[h] = acc > 0.0f ? acc : 0.0f; // ReLU } float max_logit = -1e9f; int best_class = 0; for (int c = 0; c < N_CLASSES; c++) { float logit = B1[c]; for (int h = 0; h < N_HIDDEN; h++) { logit += hidden[h] * W1[h][c]; } if (logit > max_logit) { max_logit = logit; best_class = c; } } return best_class; } #endif /* MODEL_SMALL_NN_H */ `; } // 5. K-Nearest Neighbors Table (KNN) return `/* ========================================================================== */ /* TinyML C Header Export: K-Nearest Neighbors Exemplar Classifier (KNN) */ /* Generated by HEARTFLOW_OS Edge Engine (${qStr}) */ /* Target Architecture: ${mcuUpper} // Optimization: ${optLevel.toUpperCase()} */ /* Date: ${dateStr} */ /* Exemplar Table: 10 Prototype Vectors // Zero Heap Allocation (K=5) */ /* ========================================================================== */ #ifndef MODEL_KNN_H #define MODEL_KNN_H #include #include #define N_FEATURES 5 #define N_CLASSES 5 #define N_EXEMPLARS 10 #define K_NEIGHBORS 5 static const float SCALER_MEAN[N_FEATURES] = {75.0f, 98.0f, 120.0f, 80.0f, 37.0f}; static const float SCALER_SCALE[N_FEATURES] = {15.0f, 2.5f, 18.0f, 10.0f, 0.6f}; static const float KNN_VECTORS[N_EXEMPLARS][N_FEATURES] = { { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, // 0: Normal {-0.3f, 0.4f, -0.2f, -0.2f, -0.3f}, // 0: Normal { 2.6f, -4.0f, 0.8f, 0.5f, 0.5f}, // 1: Asthma { 2.2f, -3.5f, 0.7f, 0.4f, 0.3f}, // 1: Asthma { 1.0f, -0.4f, 3.0f, 2.5f, -0.1f}, // 2: Hypertension { 0.8f, -0.2f, 2.7f, 2.2f, 0.0f}, // 2: Hypertension { 4.0f, -2.8f, 1.6f, 1.5f, 0.2f}, // 3: Heart Disease { 3.5f, -2.4f, 1.4f, 1.3f, 0.1f}, // 3: Heart Disease { 0.7f, -0.8f, 1.1f, 1.0f, 1.8f}, // 4: Diabetes { 0.5f, -0.6f, 0.9f, 0.8f, 1.5f} // 4: Diabetes }; static const uint8_t KNN_LABELS[N_EXEMPLARS] = {0, 0, 1, 1, 2, 2, 3, 3, 4, 4}; static inline int predict(const float *features) { float norm_f[N_FEATURES]; for (int i = 0; i < N_FEATURES; i++) { norm_f[i] = (features[i] - SCALER_MEAN[i]) / SCALER_SCALE[i]; } float distances[N_EXEMPLARS]; for (int e = 0; e < N_EXEMPLARS; e++) { float sum = 0.0f; for (int f = 0; f < N_FEATURES; f++) { float d = norm_f[f] - KNN_VECTORS[e][f]; sum += d * d; } distances[e] = sum; } // Accumulate inverse-distance votes for K nearest float class_votes[N_CLASSES] = {0.0f}; uint8_t visited[N_EXEMPLARS] = {0}; for (int k = 0; k < K_NEIGHBORS; k++) { float min_dist = 1e9f; int min_idx = -1; for (int e = 0; e < N_EXEMPLARS; e++) { if (!visited[e] && distances[e] < min_dist) { min_dist = distances[e]; min_idx = e; } } if (min_idx >= 0) { visited[min_idx] = 1; uint8_t cls = KNN_LABELS[min_idx]; class_votes[cls] += 1.0f / (sqrtf(min_dist) + 0.1f); } } int best_class = 0; float max_votes = class_votes[0]; for (int c = 1; c < N_CLASSES; c++) { if (class_votes[c] > max_votes) { max_votes = class_votes[c]; best_class = c; } } return best_class; } #endif /* MODEL_KNN_H */ `; }