skip to content
==> include/tui/solver.h <==
1/* @ajax/tui-solver: the Cassowary constraint solver (Badros, Borning, Stuckey), ported from kasuari
2 * 0.4.13, the one ratatui lays out with. Constraints are linear expressions over variables, an
3 * operator (<=, ==, >=) and a strength; required ones must hold, the others are met in order of
4 * strength (lexicographically, through the weights), as nearly as the required ones allow.
5 *
6 * Variables are small integers the caller picks (0, 1, 2, ...). Every add re-optimises, as
7 * kasuari's does, so the values are always the optimum of what was added so far. */
8#ifndef TUI_SOLVER_H
9#define TUI_SOLVER_H
10
11#include <stdbool.h>
12#include <stddef.h>
13#include <stdint.h>
14
15/* kasuari's strengths. */
16#define TUI_STRENGTH_REQUIRED 1001001000.0
17#define TUI_STRENGTH_STRONG 1000000.0
18#define TUI_STRENGTH_MEDIUM 1000.0
19#define TUI_STRENGTH_WEAK 1.0
20
21/* Strength::new: clamped to [0, REQUIRED]. */
22static inline double tui_strength(double v) {
23    return v < 0 ? 0 : v > TUI_STRENGTH_REQUIRED ? TUI_STRENGTH_REQUIRED : v;
24}
25
26typedef enum { TUI_LE, TUI_EQ, TUI_GE } tui_relation;
27
28#define TUI_EXPR_TERMS 8
29
30typedef struct {
31    uint32_t var;
32    double coeff;
33} tui_term;
34
35/* terms are kept in the order they were added (duplicates allowed, as kasuari's). */
36typedef struct {
37    tui_term terms[TUI_EXPR_TERMS];
38    int n;
39    double constant;
40} tui_expr;
41
42static inline tui_expr tui_expr_const(double c) {
43    tui_expr e = {0};
44    e.constant = c;
45    return e;
46}
47static inline tui_expr tui_expr_var(uint32_t v) {
48    tui_expr e = {0};
49    e.terms[0] = (tui_term){v, 1.0};
50    e.n = 1;
51    return e;
52}
53/* a - b, b's terms negated and appended (Expression -= Expression). */
54tui_expr tui_expr_sub(tui_expr a, tui_expr b);
55tui_expr tui_expr_add(tui_expr a, tui_expr b);
56tui_expr tui_expr_scale(tui_expr a, double k); /* k * a */
57tui_expr tui_expr_div(tui_expr a, double k);   /* a / k, term by term */
58
59typedef struct tui_solver tui_solver;
60
61tui_solver *tui_solver_new(void);
62void tui_solver_free(tui_solver *s);
63/* lhs (op) rhs at strength: the constraint lhs - rhs (op) 0. False when it can't be satisfied
64 * (kasuari's UnsatisfiableConstraint) or the solver hit an internal error. */
65bool tui_solver_add(tui_solver *s, tui_expr lhs, tui_relation op, double strength, tui_expr rhs);
66/* A variable's current value (0 for one the solver never saw). */
67double tui_solver_value(const tui_solver *s, uint32_t var);
68
69#endif