Download cstack/src/l1_pmat.c from Snapkitty/flash-attention-rtl: direct link, hf CLI and curl.
- Browser
- Download file 5.25 kB
-
https://huggingface.co/Snapkitty/flash-attention-rtl/resolve/main/cstack/src/l1_pmat.c
- Command line
-
hf download hf://Snapkitty/flash-attention-rtl/cstack/src/l1_pmat.c
-
curl -L -o l1_pmat.c https://huggingface.co/Snapkitty/flash-attention-rtl/resolve/main/cstack/src/l1_pmat.c
5.25 kB
| cs_status pmat_new(pmat *m, size_t rows, size_t cols) | |
| { | |
| if (!m || rows == 0 || cols == 0) return CS_ERR_ARG; | |
| if (rows > SIZE_MAX / cols || rows * cols > SIZE_MAX / sizeof(gl_t)) return CS_ERR_NOMEM; | |
| m->d = calloc(rows * cols, sizeof(gl_t)); | |
| if (!m->d) return CS_ERR_NOMEM; | |
| m->rows = rows; | |
| m->cols = cols; | |
| return CS_OK; | |
| } | |
| void pmat_free(pmat *m) | |
| { | |
| if (!m) return; | |
| free(m->d); | |
| m->d = NULL; | |
| m->rows = m->cols = 0; | |
| } | |
| cs_status pmat_identity(pmat *m, size_t n) | |
| { | |
| cs_status s = pmat_new(m, n, n); | |
| if (s != CS_OK) return s; | |
| for (size_t i = 0; i < n; i++) m->d[i * n + i] = 1; | |
| return CS_OK; | |
| } | |
| gl_t pmat_get(const pmat *m, size_t r, size_t c) { return m->d[r * m->cols + c]; } | |
| void pmat_set(pmat *m, size_t r, size_t c, gl_t v) { m->d[r * m->cols + c] = gl_reduce(v); } | |
| int pmat_equal(const pmat *a, const pmat *b) | |
| { | |
| return a->rows == b->rows && a->cols == b->cols && | |
| memcmp(a->d, b->d, a->rows * a->cols * sizeof(gl_t)) == 0; | |
| } | |
| static cs_status elementwise(const pmat *a, const pmat *b, pmat *out, int sub) | |
| { | |
| if (!a || !b || !out || !a->d || !b->d) return CS_ERR_ARG; | |
| if (a->rows != b->rows || a->cols != b->cols) return CS_ERR_RANGE; | |
| pmat r; | |
| cs_status s = pmat_new(&r, a->rows, a->cols); | |
| if (s != CS_OK) return s; | |
| for (size_t i = 0; i < a->rows * a->cols; i++) | |
| r.d[i] = sub ? gl_sub(a->d[i], b->d[i]) : gl_add(a->d[i], b->d[i]); | |
| *out = r; | |
| return CS_OK; | |
| } | |
| cs_status pmat_add(const pmat *a, const pmat *b, pmat *out) { return elementwise(a, b, out, 0); } | |
| cs_status pmat_sub(const pmat *a, const pmat *b, pmat *out) { return elementwise(a, b, out, 1); } | |
| cs_status pmat_scale(const pmat *a, gl_t k, pmat *out) | |
| { | |
| if (!a || !out || !a->d) return CS_ERR_ARG; | |
| pmat r; | |
| cs_status s = pmat_new(&r, a->rows, a->cols); | |
| if (s != CS_OK) return s; | |
| k = gl_reduce(k); | |
| for (size_t i = 0; i < a->rows * a->cols; i++) r.d[i] = gl_mul(a->d[i], k); | |
| *out = r; | |
| return CS_OK; | |
| } | |
| cs_status pmat_mul(const pmat *a, const pmat *b, pmat *out) | |
| { | |
| if (!a || !b || !out || !a->d || !b->d) return CS_ERR_ARG; | |
| if (a->cols != b->rows) return CS_ERR_RANGE; | |
| pmat r; | |
| cs_status s = pmat_new(&r, a->rows, b->cols); | |
| if (s != CS_OK) return s; | |
| for (size_t i = 0; i < a->rows; i++) | |
| for (size_t k = 0; k < a->cols; k++) { | |
| gl_t aik = a->d[i * a->cols + k]; | |
| for (size_t j = 0; j < b->cols; j++) | |
| r.d[i * r.cols + j] = gl_add(r.d[i * r.cols + j], gl_mul(aik, b->d[k * b->cols + j])); | |
| } | |
| *out = r; | |
| return CS_OK; | |
| } | |
| cs_status pmat_transpose(const pmat *a, pmat *out) | |
| { | |
| if (!a || !out || !a->d) return CS_ERR_ARG; | |
| pmat r; | |
| cs_status s = pmat_new(&r, a->cols, a->rows); | |
| if (s != CS_OK) return s; | |
| for (size_t i = 0; i < a->rows; i++) | |
| for (size_t j = 0; j < a->cols; j++) r.d[j * r.cols + i] = a->d[i * a->cols + j]; | |
| *out = r; | |
| return CS_OK; | |
| } | |
| /* Gauss-Jordan on [A | I]; accumulates the determinant. */ | |
| static cs_status eliminate(const pmat *a, pmat *inv_out, gl_t *det_out) | |
| { | |
| if (!a || !a->d) return CS_ERR_ARG; | |
| if (a->rows != a->cols) return CS_ERR_RANGE; | |
| size_t n = a->rows; | |
| pmat w, id; | |
| cs_status s = pmat_new(&w, n, n); | |
| if (s != CS_OK) return s; | |
| memcpy(w.d, a->d, n * n * sizeof(gl_t)); | |
| s = pmat_identity(&id, n); | |
| if (s != CS_OK) { pmat_free(&w); return s; } | |
| gl_t det = 1; | |
| for (size_t col = 0; col < n; col++) { | |
| size_t piv = col; | |
| while (piv < n && w.d[piv * n + col] == 0) piv++; | |
| if (piv == n) { det = 0; pmat_free(&w); pmat_free(&id); if (det_out) *det_out = 0; return CS_ERR_SINGULAR; } | |
| if (piv != col) { | |
| for (size_t j = 0; j < n; j++) { | |
| gl_t t = w.d[piv * n + j]; w.d[piv * n + j] = w.d[col * n + j]; w.d[col * n + j] = t; | |
| t = id.d[piv * n + j]; id.d[piv * n + j] = id.d[col * n + j]; id.d[col * n + j] = t; | |
| } | |
| det = gl_neg(det); | |
| } | |
| gl_t pv = w.d[col * n + col], pinv; | |
| det = gl_mul(det, pv); | |
| (void)gl_inv(pv, &pinv); | |
| for (size_t j = 0; j < n; j++) { | |
| w.d[col * n + j] = gl_mul(w.d[col * n + j], pinv); | |
| id.d[col * n + j] = gl_mul(id.d[col * n + j], pinv); | |
| } | |
| for (size_t r = 0; r < n; r++) { | |
| if (r == col) continue; | |
| gl_t f = w.d[r * n + col]; | |
| if (f == 0) continue; | |
| for (size_t j = 0; j < n; j++) { | |
| w.d[r * n + j] = gl_sub(w.d[r * n + j], gl_mul(f, w.d[col * n + j])); | |
| id.d[r * n + j] = gl_sub(id.d[r * n + j], gl_mul(f, id.d[col * n + j])); | |
| } | |
| } | |
| } | |
| if (det_out) *det_out = det; | |
| pmat_free(&w); | |
| if (inv_out) *inv_out = id; else pmat_free(&id); | |
| return CS_OK; | |
| } | |
| cs_status pmat_det(const pmat *a, gl_t *det) | |
| { | |
| if (!det) return CS_ERR_ARG; | |
| cs_status s = eliminate(a, NULL, det); | |
| if (s == CS_ERR_SINGULAR) return CS_OK; /* det of a singular matrix is 0 */ | |
| return s; | |
| } | |
| cs_status pmat_inverse(const pmat *a, pmat *out) | |
| { | |
| if (!out) return CS_ERR_ARG; | |
| return eliminate(a, out, NULL); | |
| } | |