#include "svm.h" #include #include #include #define New(t, n) (t *)malloc((n) * sizeof(t)) #define Size @{size} #define Bias @{bias} #define Gama @{gama} #define Feat @{feat} static uint8_t okay = 0; // fill first number of each sv here static float Scales[Size] = { @{scales} }; // fill element count of each sv here static uint32_t Elements[Size] = { @{elements} }; // fill the flattened sv weights here static float Weights[] = { @{weights} }; static Node *Vector[Size]; void svm_init() { int i, j, idx = 0; for (i = 0; i < Size; ++i) { Vector[i] = New(Node, Elements[i] + 1); for (j = 0; j < Elements[i]; ++j, ++idx) { Vector[i][j].idx = j + 1; Vector[i][j].val = Weights[idx]; } Vector[i][j].idx = 0; } okay = 1; } Node *input() { Node *x = New(Node, Feat + 1); int i; for (i = 0; i < Feat; ++i) { x[i].idx = i + 1; scanf("%f", &x[i].val); // NOLINT } x[Feat].idx = 0; return x; } float rbf_kernel(const Node *x, const Node *y) { float sum = 0; while (x->idx != 0 && y->idx != 0) { if (x->idx == y->idx) { float d = x->val - y->val; sum += d * d; ++x, ++y; } else { if (x->idx > y->idx) { sum += y->val * y->val; ++y; } else { sum += x->val * x->val; ++x; } } } while (x->idx != 0) { sum += x->val * x->val; ++x; } while (y->idx != -0) { sum += y->val * y->val; ++y; } return expf(-Gama * sum); } int8_t svm_predict(const Node *x) { if (okay == 0) { printf("you should call `svm_init();` first."); return 0; } float sum = -Bias; uint32_t i; for (i = 0; i < Size; ++i) sum += Scales[i] * rbf_kernel(x, Vector[i]); return sum > 0 ? 1 : -1; }