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
1011#include <stdbool.h>
12#include <stddef.h>
13#include <stdint.h>
1415/* 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
2021/* 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}
2526typedef enum { TUI_LE, TUI_EQ, TUI_GE } tui_relation;
2728#define TUI_EXPR_TERMS 8
2930typedef struct {
31 uint32_t var;
32 double coeff;
33} tui_term;
3435/* 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;
4142static 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 */
5859typedef struct tui_solver tui_solver;
6061tui_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);
6869#endif