root notes [uts-001O]
root notes [uts-001O]
Draft notes [uts-0001]
Draft notes [uts-0001]
draft notes captured by topic
draft notes captured by topic
Drafts for Notes on Topos Theory and Type Theory [tt-000L]
Drafts for Notes on Topos Theory and Type Theory [tt-000L]
Example. (co)limit in Set [leinster2016basic, 5.1.22, 5.2.16] [tt-004W]
Example. (co)limit in Set [leinster2016basic, 5.1.22, 5.2.16] [tt-004W]
In \(\mathbf {Set}\), the limit is constructed as a subset of a product, the colimit is a quotient of a sum.
Add this after Definition [tt-002G].
Lemma. Representable functor and adjoint [tt-0022]
Lemma 4.24.2 in The Stacks project.Lemma. Representable functor and adjoint [tt-0022]
Shaef theory [tt-005B]
Shaef theory [tt-005B]
Definition. concrete category [riehl2017category, 1.6.17] [tt-0053]
Definition. concrete category [riehl2017category, 1.6.17] [tt-0053]
A concrete category is a category \({\cal C}\) equipped with a faithful functor \(\mathscr {F} : {\cal C} \to \mathbf {Set}\).
Add this to where this would be used.
Definition. cone [kostecki2011introduction, 4.9] [tt-0027]
Definition. cone [kostecki2011introduction, 4.9] [tt-0027]
Let \({\cal C}^{{\cal J}}\) be a functor category, where \({\cal J}\) is a small category.
Let \(\Delta _O\) be a constant functor, which assigns the same object \(O\) in \({\cal C}\) to any object \(J\) in \({\cal J}\).
Let \(K \in \operatorname {Ob}({\cal J})\) and let \(j \in \operatorname {Arr}({\cal J})\) such that \(j: J \to K\). Let \(\mathscr {F}\) be any functor in \({\cal C}^{{\cal J}}\), i.e. it's a diagram in \({\cal C}\) of shape \({\cal J}\).
A natural transformation \(\pi : \Delta _O \to \mathscr {F}\), defined as a family of arrows \(\pi _J: O \to \mathscr {F}(J)\), such that the diagram
Definition. creates limits [leinster2016basic, 5.3.5] [tt-0058]
Definition. creates limits [leinster2016basic, 5.3.5] [tt-0058]
A functor \(\mathscr {F}: {\cal C} \to {\cal D}\) creates limits (of shape \({\cal J}\)) if whenever \(\mathscr {D}: {\cal J} \to {\cal C}\) is a diagram in \({\cal C}\),
- for any limit cone \(\left ( V_{{\cal D}} \xrightarrow {q_J} \mathscr {F} \mathscr {D}(J) \right )_{J \in {\cal J}}\) on the diagram \(\mathscr {D} \mathbin {\bullet } \mathscr {F}\), there is a unique cone \(\left (V_{{\cal C}} \xrightarrow {p_J} \mathscr {D}(J) \right )_{J \in {\cal J}}\) on \(\mathscr {D}\) such that \(\mathscr {F}(V_{{\cal C}})=V_{{\cal D}}\) and \(\mathscr {F}\left (p_J\right )=q_J\) for all \(J \in {\cal J}\)
- this cone \(\left (V_{{\cal C}} \xrightarrow {p_J} \mathscr {D}(J)\right )_{J \in {\cal J}}\) is a limit cone on \(\mathscr {D}\).
Example. direct limit [rosiak2022sheaf, example 68] [tt-004X]
Example. direct limit [rosiak2022sheaf, example 68] [tt-004X]
Direct limits is the colimit of a diagram indexed by the ordinal category \(\omega \). In other words, for a diagram \[ X_1 \to X_2 \to X_3 \to X_4 \to \cdots \] its colimit is the direct limit \(\lim \limits _{\to } X_n\), defining a diagram of shape \(\omega +1\) :
Observe then that the colimit of a sequence of sets with the inclusions \[ X_0 \hookrightarrow X_1 \hookrightarrow X_2 \hookrightarrow \cdots \] recovers their union \(\bigcup \limits _{n \geq 0} X_n\).
Add this after Definition [tt-002G].
Corollary. evaluation functor preserves limits of ... [leinster2016basic, 6.2.6] [tt-0046]
Corollary. evaluation functor preserves limits of ... [leinster2016basic, 6.2.6] [tt-0046]
An important corollary of Theorem [tt-0045].
The Yoneda embedding preserves limits, for any small category [leinster2016basic, 6.2.12]. But it does not preserve colimits in general [leinster2016basic, 6.2.14].
Every presheaf can be expressed as a colimit of representables in a canonical (though not unique) way, this is Theorem [tt-004D], and dual to Lemma [tt-002N].
fill in details.
Definition. filtered category [rosiak2022sheaf, def. 285] [tt-004Z]
Definition. filtered category [rosiak2022sheaf, def. 285] [tt-004Z]
A category \({\cal J}\) is filtered (or directed) if
- it is not empty
- for every pair of objects \(J, J^{\prime } \in {\cal J}\), there exists \(K \in {\cal J}\) and \(f: J \to K\) and \(f': J' \to K\)
- for every two parallel arrows \(u, v: i \rightarrow j\) in \({\cal J}\), there exists \(K \in {\cal J}\) and \(w: J \to K\) such that \[u \mathbin {\bullet } w = v \mathbin {\bullet } w\]
This is a generalization of the notion of a (upward) directed poset from order theory.
Add this to where this would be used.
Definition. filtered colimit [rosiak2022sheaf, def. 285] [tt-0050]
Definition. filtered colimit [rosiak2022sheaf, def. 285] [tt-0050]
A filtered colimit is a colimit of a functor \(\mathscr {F}: {\cal J} \to {\cal C}\), where \({\cal J}\) is a filtered category.
In particular, a colimit over a filtered poset \(P\) is the same as the colimit over a cofinal subset \(Q\) of that poset, where \(Q\) as a cofinal subset means that for every element \(p \in P\), there exists an element \(q \in Q\) with \(p \leq q\).
See also ⧉.
Theorem. general adjoint functor theorem [leinster2016basic, 6.3.10] [tt-004E]
Theorem. general adjoint functor theorem [leinster2016basic, 6.3.10] [tt-004E]
Limit-preservation alone does not guarantee the existence of a left adjoint. This theorem specifies the conditions under which a limit-preserving functor has a left adjoint. This theorem requires the definition of weakly initial set.
fill in details.
Theorem. limits in a functor category [leinster2016basic, 6.2.5] [tt-0045]
Theorem. limits in a functor category [leinster2016basic, 6.2.5] [tt-0045]
Limits in a functor category are computed pointwise.
fill in details.This theorem helps proving Lemma [tt-0047].
Remark. local, global [rosiak2022sheaf, p. 1] [tt-005C]
In a very general and rough way, by local we typically understand that something is being compared to what is around or nearby it; this is as opposed to the global, generally understood to mean compared to everything or across an entire domain of interest. Satisfying a property at a local level does not necessarily entail that the same will obtain at the global level.
Remark. local, global [rosiak2022sheaf, p. 1] [tt-005C]
Lemma. preserves if creates [leinster2016basic, 5.3.6] [tt-0059]
Lemma. preserves if creates [leinster2016basic, 5.3.6] [tt-0059]
Let \(\mathscr {F}: {\cal C} \rightarrow {\cal D}\) be a functor and \({\cal J}\) a small category. Suppose that \({\cal D}\) has, and \(\mathscr {F}\) creates, limits of shape \({\cal J}\). Then \({\cal C}\) has, and \(\mathscr {F}\) preserves, limits of shape \({\cal J}\).
Definition [tt-002F]Definition [tt-0058]Same as Definition [tt-0058].
Definition. section, choice [leinster2016basic, sec. 3.1] [tt-003E]
Definition. section, choice [leinster2016basic, sec. 3.1] [tt-003E]
Let \(f: X \to Y\) be an arrow in a category \({\cal C}\). A section (or right inverse) of \(f\) is an arrow \(i: Y \to X\) in \({\cal C}\) such that \(i \mathbin {\bullet } f = \mathit {1}_X\).
In \(\mathbf {Set}\), any arrow with a section is certainly surjective. The converse statement is called the axiom of choice:
Every surjection has a section.
It is called choice because specifying a section of \(f: X \to Y\) amounts to choosing, for each \(y \in Y\), an element of the nonempty set \(\{x \in X \mid f(x)=y\}\).
It's closely related to § [tt-004T], need to figure out how to incooperate.
Definition. sequence [leinster2016basic, sec. 3.1] [tt-003D]
Definition. sequence [leinster2016basic, sec. 3.1] [tt-003D]
A function with domain \(\mathbb N\) is usually called a sequence.
Related to § [tt-004T].
Definition. slice category [kostecki2011introduction, eq. 12] [tt-0009]
The slice category \({\cal C} \downarrow X\), is the category whose objects are arrows in \({\cal C}\) with fixed codomain \(X\), such that the diagram
Definition. slice category [kostecki2011introduction, eq. 12] [tt-0009]
It's also denoted \({\cal C} / X\) or \({\cal C}_{/X}\).
The slice category is a special case of the comma category.
It's also called overcategory, as it's a slice category over \(X\) [zhang2021type, 3.5].
revamp and add co-slice category, maybe following [rosiak2022sheaf, def. 21], or better, follow Basic category theory, to explain how a slice category is a special case of comma category.
Definition. sum, coproduct [leinster2016basic, 5.2.2] [tt-003L]
Definition. sum, coproduct [leinster2016basic, 5.2.2] [tt-003L]
A sum or coproduct is a colimit over a discrete category, i.e. it is a colimit of shape \(J\) for some discrete category \({\cal J}\).
Possibly belong to § [tt-0023].
Drafts for Notes on Algebraic Geometry [ag-000C]
Drafts for Notes on Algebraic Geometry [ag-000C]
Notes on Algebraic Geometry [ag-0001]
- August 13, 2024
- Utensil Song
Notes on Algebraic Geometry [ag-0001]
- August 13, 2024
- Utensil Song
What is Algebraic Geometry? [ag-0005]
What is Algebraic Geometry? [ag-0005]
Algebraic geometry deals with solution sets of systems of polynomial equations [borisov2024adventures, sec. 1] from an geometric view, with many algebraic concepts imitating the notions of analysis and topology [kriz2021introduction, p. vii], but has the advantage of being able to deal with singularities [mehrle2017algebraic, lect. 1, sec. 1] and other pathological objects.
Algebraic geometry has developed in waves, each with its own language and point of view, see [hartshorne1977graduate, p. xiv] for some discussion. The older language is closer to the geometric intuition, while the newer language developes powerful techniques to solve problems in great generality, but the study of the latter is considered tedious, or even depressing, by many, when not accompanied with tangible applications [grothendieck1964elements, p. 12].
Remark. the grand plan [ag-0002]
Remark. the grand plan [ag-0002]
We will use [kriz2021introduction] as a holistic guide to the organization of materials, which has done a great job of having the minimal prerequisites, being self-contained, and covering most of the topics that concern us, including the geometric motivation.
For a similar purpose, we use the formalization papers [bordg2022simple] and [buzzard2022schemes] to guide the path, at least the part towards schemes, and their counterparts in the Mathlib of Lean 4.
For prerequisites in basic algebra and commutative algebra, we will use [knapp2006basic] and [knapp2007advanced], and notes by Andreas Gathmann [gathmann2023plane][gathmann2013commutative] and David Mehrle [mehrle2015commutative]. For the geometric motivation and intuition, we will use [cox1997ideals] and [borisov2024adventures].
For upstream treatment of algebraic geometry, we will use [grothendieck1964elements] (particularly the English translation available at ryankeleti/ega) and [fantechi2006fundamental]. For modern notes, we will use [vakil2024rising], [gathmann2022algebraic] and [mehrle2017algebraic], with an eye on the classic textbook [hartshorne1977graduate].
We also need to tap into the language of Stacks in a modern setting, as treated in [khan2023lectures], with preliminaries on \(\infty \)-categories and derived categories.
See the plan for notes on algebraic geometry for an early discussion of the plan.
Convention. rings and fields [gathmann2013commutative, 0.1] [ag-0008]
Convention. rings and fields [gathmann2013commutative, 0.1] [ag-0008]
A ring, usually denoted \(R\), is always assumed to be a commutative ring (i.e. \(a+b=b+a\) and \(a b=b a\) for all \( a, b \in R\)) with 1 (i.e. the multiplicative identity element, or called multiplicative unit).
\(1 \neq 0\) is not required, where \(0\) is the additive neutral element. If \(1=0\), then \(R\) must be the zero ring (or called the trivial ring), which consisting of one element, and is denoted \(\{0\}\).
Subrings must have the same unit, and ring homomorphisms are always required to map \(1\) to \(1\).
A field, usually denoted \(K\), is a commutative ring with \(1\), where every nonzero element has a multiplicative inverse (thus division can be defined).
Definition. formal variable, formal expression [ag-0009]
Definition. formal variable, formal expression [ag-0009]
A formal variable is an arbitrary symbol that is used to represent some mathematical object, and assumes nothing about the value or nature of the object.
A formal expression is mathematical expression with formal variables, assuming nothing but the formal variables participate in the expression have operations that are used in the expression.
A formal expression can be evaluated by replacing the formal variables with actual mathematical objects that have the operations defined in the expression.
When there is no ambiguity, we may omit the word "formal" and simply say variables or an expression.
Definition. monomial [cox1997ideals, 1.1.1] [ag-0003]
Definition. monomial [cox1997ideals, 1.1.1] [ag-0003]
A monomial in \(n\) formal variables \(x_1, \ldots , x_n\), denoted \(x^\alpha \), is a formal expression of the form \[ x_1^{\alpha _1} x_2^{\alpha _2} \cdots x_n^{\alpha _n} \] where \(n \in \mathbb N\), \(\alpha =\left (\alpha _1, \ldots , \alpha _n\right )\) is an \(n\)-tuple of nonnegative integers.
The total degree of the monomial is denoted \(|\alpha |=\alpha _1+\cdots +\alpha _n\).
Definition. polynomial [cox1997ideals, 1.1.2, 1.1.3] [ag-0004]
Definition. polynomial [cox1997ideals, 1.1.2, 1.1.3] [ag-0004]
A polynomial \(f\) over a ring \(R\) in \(n\) variables is a finite linear combination (with coefficients \(a_\alpha \) in \(R\) ) of monomials, i.e. the formal expression of the form \[ f=\sum _\alpha a_\alpha x^\alpha , \quad a_\alpha \in R, \]
The set of all polynomials in \(x_1, \ldots , x_n\) with coefficients in \(R\) is denoted \(R\left [x_1, \ldots , x_n\right ]\).
\(a_\alpha x^\alpha \) is called a term of \(f\) if \(a_\alpha \neq 0\).
The total degree of \(f \neq 0\), denoted \(\operatorname {deg}(f)\), is the maximum \(|\alpha |\) such that the coefficient \(a_\alpha \) is nonzero. The total degree of the zero polynomial is undefined.
Remark. polynomial ring [cox1997ideals, 1.1.3] [ag-0007]
Remark. polynomial ring [cox1997ideals, 1.1.3] [ag-0007]
Under addition and multiplication, \(R\left [x_1, \ldots , x_n\right ]\) satisfies all axioms of a commutative ring, and for this reason we will refer to \(R\left [x_1, \ldots , x_n\right ]\) as a polynomial ring.
Definition. affine space [gathmann2013commutative, 0.3] [ag-000A]
Definition. affine space [gathmann2013commutative, 0.3] [ag-000A]
The (\(n\)-dimensional) affine space over a field \(K\), denoted \(\mathbb {A}_K^n\), is \[ \left \{\left (c_1, \ldots , c_n\right ): c_i \in K \text { for } i=1, \ldots , n\right \} \] which is just \(K^n\) as a set, without the its additional structures as a \(K\)-vector space and a ring.
We'll often use the term affine \(n\)-space to indicate the dimension. Particularly, an affine 1-space is called an affine line, an affine 2-space is an affine plane.
Definition. affine variety [gathmann2013commutative, 0.3] [ag-000D]
Definition. affine variety [gathmann2013commutative, 0.3] [ag-000D]
Let \(S \subset K\left [x_1, \ldots , x_n\right ]\) be a set of polynomials. The zero locus (or zero set) of \(S\) is \[ V(S):=\left \{x \in \mathbb {A}_K^n: f(x)=0 \text { for all } f \in S\right \} \subset \mathbb {A}_K^n \]
An affine algebraic variety over \(K\) is a subset of \(\mathbb {A}_K^n\) of this form. It's usually simply called an affine variety over \(K\), or an affine \(K\)-variety.
If \(S=\left (f_1, \ldots , f_k\right )\) is a finite set, \(V(S)\) can be written as \(V\left (f_1, \ldots , f_k\right )\).
Obviously, it is the set of all solutions of the system of polynomial equations \(f_1\left (x_1, \ldots , x_n\right )=\cdots =f_s\left (x_1, \ldots , x_n\right )=0\) [cox1997ideals, 1.2.1], denoted \(\operatorname {Sol}(S;K)\) [dolgachev2013introduction, p. 1].
Remark. affine v.s. projective [michalek2021invitation, ch. 2] [ag-000E]
Remark. affine v.s. projective [michalek2021invitation, ch. 2] [ag-000E]
The prefix "affine" of affine variety is used to distinguish it from a projective variety. Affine varieties arise from arbitrary polynomials, while projective varieties arise from systems of homogeneous polynomials, i.e. linear combinations of monomials of fixed degree.
Since affine varieties are the general case, they are sometimes simply called varieties.
Figure out its relation to affine space in Geometry, which preserves parallelism and ratio of lengths for parallel line segments, but not distances and measures of angles.
Example. varieties [ag-000F]
Example. varieties [ag-000F]
\(\mathbf {V}\left (10 x^2-x^3-y^2\right )\) from [cox1997ideals, p. 24]:
\(\mathbf {V}\left (x^2-y^2 z^2+z^3\right )\) from [cox1997ideals, p. 7, p. 16]:
Figure. Implicit surfaces [uts-000J]
Figure. Implicit surfaces [uts-000J]
#define AS_LIB 1
int get_shape() {
return int(iTime) % 52;
}
#include "/forest/shader/implicit.glsl"
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = 2.*(fragCoord-iResolution.xy/2.)/iResolution.y; // contains [-1,1]^2
vec3 col = vec3(0.);
// Camera rays
vec3 camPos = vec3(4.,0.,0.);
vec3 camDir = - normalize(camPos);
vec3 rayPos, rayDir;
float zoom = 1.3; // 1.8*cos(iTime);
// if (checkKey(KEY_E)) zoom = 0.5;
float fov = 0.4*zoom;
float fov_ortho = 1.5*zoom;
#if perspective
// perspective cam
rayPos = camPos;
rayDir = normalize(camDir + fov*vec3(0., uv.x, uv.y));
#else
// orthographic cam
rayPos = camPos + fov_ortho*vec3(0., uv.x, uv.y);
rayDir = camDir;
#endif
// for perspective background in orthographic mode
vec3 cubemapDir = normalize(camDir + fov*vec3(0., uv.x, uv.y));
// Mouse-controlled rotation
vec2 mouse = initMouse + vec2(0.015625*sin(iTime*PI), 0.0); // initMouse; // iMouse.xy == vec2(0.,0.) ? initMouse : (iMouse.xy/iResolution.xy - 0.5);
float yaw = clamp(- mouse.x * 2.*PI * 1., -PI,PI);
float pitch = clamp( mouse.y * PI * 1.2, -PI*0.5, PI*0.5);
// pitch and yaw rotations (column-wise matrices)
mat3 rot = mat3(cos(yaw), sin(yaw), 0., -sin(yaw), cos(yaw), 0., 0., 0., 1.);
rot = rot * mat3(cos(pitch), 0., -sin(pitch), 0., 1., 0., sin(pitch), 0., cos(pitch));
// apply
camPos = rot*camPos;
camDir = rot*camDir;
rayPos = rot*rayPos;
rayDir = rot*rayDir;
cubemapDir = rot*cubemapDir;
//cubemapDir = vec3(cubemapDir.x, cubemapDir.z, cubemapDir.y);
vec3 hitPoint = raycast(rayPos, rayDir);
if (hitPoint == BINGO) { fragColor = vec4(BINGO,1.0); return; }
//if (hitPoint == NOHIT) { fragColor = vec4(NOHIT,1.0); return; }
//if (hitPoint == NOBOUNDHIT) { fragColor = vec4(NOBOUNDHIT,1.0); return; }
//if (hitPoint == ESCAPEDBOUNDS) { fragColor = vec4(ESCAPEDBOUNDS,1.0); return; }
//if (hitPoint == MAXDISTREACHED) { fragColor = vec4(MAXDISTREACHED,1.0); return; }
//if (hitPoint == MAXITERREACHED) { fragColor = vec4(MAXITERREACHED,1.0); return; }
if (hitPoint == NOBOUNDHIT || hitPoint == NOHIT || hitPoint == ESCAPEDBOUNDS || hitPoint == MAXITERREACHED) {
//fragColor = vec4(vec3(0.2),1.0); return;
// make background transparent
fragColor = vec4(0.0,0.0,0.0,0.0); return;
col = with_background(cubemapDir);
#if showBoundingCube
// darken bounding cube
if (hitPoint != NOBOUNDHIT) { col *= vec3(0.7); }
#endif
fragColor = vec4(col,1.0); return;
}
vec3 grad = gradf(hitPoint+1.1*EPS*(-rayDir));
float s = -sign(dot(grad,rayDir));
col = with_color_mode(grad, s, hitPoint, camPos);
col = clamp(col, 0., 1.);
col = with_surface_pattern(col, hitPoint);
col = with_shading(col, grad, s, rayDir);
col = clamp(col, 0., 1.);
fragColor = vec4(col,1.0);
}
appendix [ag-000B]
appendix [ag-000B]
For draft notes, see Drafts for Notes on Algebraic Geometry.
Definition. affine variety [cox1997ideals, 1.2.1] [ag-0006]
Definition. affine variety [cox1997ideals, 1.2.1] [ag-0006]
Let \(f_1, \ldots , f_s\) be polynomials in \(K\left [x_1, \ldots , x_n\right ]\). The affine variety defined by \(f_1, \ldots , f_s\) is \[ \mathbf {V}\left (f_1, \ldots , f_s\right )=\left \{\left (a_1, \ldots , a_n\right ) \in \mathbb {A}_K^n \mid f_i\left (a_1, \ldots , a_n\right )=0 \text { for all } 1 \leq i \leq s\right \} \]
Obviously, it is the set of all solutions of the system of polynomial equations \(f_1\left (x_1, \ldots , x_n\right )=\cdots =f_s\left (x_1, \ldots , x_n\right )=0\).
Definition. affine variety [gathmann2013commutative, 0.3] [ag-000D]
Definition. affine variety [gathmann2013commutative, 0.3] [ag-000D]
Let \(S \subset K\left [x_1, \ldots , x_n\right ]\) be a set of polynomials. The zero locus (or zero set) of \(S\) is \[ V(S):=\left \{x \in \mathbb {A}_K^n: f(x)=0 \text { for all } f \in S\right \} \subset \mathbb {A}_K^n \]
An affine algebraic variety over \(K\) is a subset of \(\mathbb {A}_K^n\) of this form. It's usually simply called an affine variety over \(K\), or an affine \(K\)-variety.
If \(S=\left (f_1, \ldots , f_k\right )\) is a finite set, \(V(S)\) can be written as \(V\left (f_1, \ldots , f_k\right )\).
Obviously, it is the set of all solutions of the system of polynomial equations \(f_1\left (x_1, \ldots , x_n\right )=\cdots =f_s\left (x_1, \ldots , x_n\right )=0\) [cox1997ideals, 1.2.1], denoted \(\operatorname {Sol}(S;K)\) [dolgachev2013introduction, p. 1].
the plan for notes on algebraic geometry [uts-000F]
the plan for notes on algebraic geometry [uts-000F]
The approach we would like to take is similar to the one we took in our Notes on Topos Theory and Type Theory: determine some goals, find some references that sketch out a path to those goals, and then write notes jumping between many references to fill in the gaps.
Goal 1: To be able to state "an affine scheme is a scheme", which means we need all the basics of prime ideals, Zariski topology, sheaves, spectrum of a ring, stalks, locally ringed spaces etc. as sketched out in [bordg2022simple] which has organized the minimum preliminaries in a formal way, but we might also need to refer to [buzzard2022schemes] and Mathlib to ensure that we can properly find the Lean counterparts.
Goal 2: To properly understand the geometric topic of algebraic geometry, we also need many basic correspondence in the Algebra-Geometry dictionary, which can be found in [cox1997ideals], including ideals, varieties, Gröbner Bases, elimination Theory, the relation between irreducible Varieties and prime Ideals, projective algebraic geometry etc. This book provides concrete intuitions and examples for working with the abstract concepts. We might also branch out from there to write notes about ray-tracing the implicit surfaces of algebraic varieties (see some links for rendering implicit surfaces for some links), and the use of Macaulay2 and Singular to do computations in AG.
Goal 3: A challenging goal is to be able to read EGA [grothendieck1964elements] and some materials surrounding it:
- EGA: we will use the English translation available at ryankeleti/ega, with the French version (year 1960) available at Numdam, both use the word scheme to mean separated scheme, and prescheme to mean scheme. A Chinese translation is also available and has an index of terminology in Chinese, English, and French, which is useful. We would like to include terminology in all three languages for key concepts in our notes, showing only the English version by default.
- FGA: we will use [fantechi2006fundamental] instead of the original FGA. This is an explained and extended version of FGA, that has the advantage of being in English and from a little more modern viewpoint.
- SGA: Although topos is first introduced in SGA, but we are not ready to read SGA yet.
- The rising sea: [vakil2024rising] is a modern introduction to algebraic geometry, used by many courses, e.g. math256 (which also has an English synopsis of EGA). Some courses, e.g. Algebraic Geometry Spring 2024 , also follows lecture notes by Andreas Gathmann [gathmann2022algebraic] (found on Math 8253: Algebraic Geometry).
- FAC [serre1955faisceaux]: there is an English version Coherent Algebraic Sheaves translated by Piotr Achinger and Lukasz Krupa. This is no longer the modern treatment of AG, so it's only used as a reference.
- GAGA [serre1956geometrie]: there is only the French version and the Chinese translation. The evaluation is the same as FAC.
We need some modern notes to avoid being lost in the old language, for that, besides The rising sea, we have chosen [borisov2024adventures] and [mehrle2017algebraic].
Goal 4: We also need to tap into the language of Stacks in a modern setting, as treated in [khan2023lectures], with preliminaries on \(\infty \)-categories and derived categories.
Drafts for Notes on Clifford Algebras [ca-001K]
Drafts for Notes on Clifford Algebras [ca-001K]
Definition. dual module [ca-0012]
L∃∀N
Definition. dual module [ca-0012]
L∃∀N
The dual module \(M^* : M \to _{l[R]} R\) is the \(R\)-module of all linear maps from \(M\) to \(R\).
Definition. even subalgebra of Clifford algebra [wieser2022computing] [ca-001J]
L∃∀N
Definition. even subalgebra of Clifford algebra [wieser2022computing] [ca-001J]
L∃∀N
The even subalgebra of the Clifford algebra is defined as the submodule of the Clifford algebra \[ \mathcal {C}\kern -2pt\ell ^{+}(Q) \equiv \left \{ x_1 \cdots x_k \in \mathcal {C}\kern -2pt\ell \mid x \in V, k \text { is even} \right \} \] which also forms a subalgebra. Its elements are called even elements, as they can be expressed as the geometric product of an even number of 1-vectors.
Definition. ring homomorphism [chen2016infinitely, 4.5.1] [ca-0014]
Definition. ring homomorphism [chen2016infinitely, 4.5.1] [ca-0014]
Let \((\alpha , +_\alpha , *_\alpha )\) and \((\beta , +_\beta , *_\beta )\) be rings. A ring homomorphism from \(\alpha \) to \(\beta \) is a map \(\mathit {1} : \alpha \to _{+*} \beta \) such that
- \(\mathit {1}(x +_{\alpha } y) = \mathit {1}(x) +_{\beta } \mathit {1}(y)\) for each \(x,y \in \alpha \).
- \(\mathit {1}(x *_{\alpha } y) = \mathit {1}(x) *_{\beta } \mathit {1}(y)\) for each \(x,y \in \alpha \).
- \(\mathit {1}(1_{\alpha }) = 1_{\beta }\).
other draft notes
other draft notes
some HF papers worth skimming [uts-016E]
some HF papers worth skimming [uts-016E]
- multimodal, diffusion
- Scaling Diffusion Transformers Efficiently via μP
- establish μP as a principled and efficient scaling strategy for diffusion Transformers
- with appendix on Theoretical Background of μP
- Neurosymbolic Diffusion Models
- the first method to integrate masked diffusion models as the neural network extractor in neurosymbolic predictors
- with a very long appendix on math background
- Diffusion vs. Autoregressive Language Models: A Text Embedding Perspective
- propose adopting diffusion language models for text embeddings, motivated by their inherent bidirectional architecture and recent success in matching or surpassing LLMs especially on reasoning tasks
- focus on Dream 7b: Introducing dream 7b, the most powerful open diffusion large language model to date
- consistently outperforms existing diffusion language models by a large margin
- matches or exceeds top-tier Autoregressive (AR) language models of similar size on the general, math, and coding abilities
- demonstrates strong planning ability and inference flexibility that naturally benefits from the diffusion modeling
- virtually all leading LLMs relying on this same sequential left-to-right architecture
- Discrete diffusion models (DMs) have gained attention as a promising alternative for sequence generation since their introduction to the text domain, which dynamically refine the full sequence in parallel starting from a fully noised state
- MMaDA: Multimodal Large Diffusion Language Models
- unified diffusion architecture
- superior performance across diverse domains such as textual reasoning, multimodal understanding, and text-to-image generation
- rich and impressive examples
- with appendix on Preliminaries of Discrete Diffusion, PPO and GRPO
- LaViDa: A Large Diffusion Language Model for Multimodal Understanding
- Large Vision-Language Diffusion Model with Masking
- follows a similar design to common AR VLMs like LLaVa
- GRIT: Teaching MLLMs to Think with Images
- generate visually grounded reasoning chains by interleaving natural language with explicit bounding box coordinates referencing relevant image regions
- Dimple: Discrete Diffusion Multimodal Large Language Model with Parallel Decoding
- trained using a novel two-phase paradigm–Autoregressive-then-Diffusion
- dKV-Cache: The Cache for Diffusion Language Models
- diffusion language models have long been constrained by slow inference
- motivated by the observation that different tokens have distinct representation dynamics throughout the diffusion process
- propose a delayed and conditioned caching strategy for key and value states
- Understanding Generative AI Capabilities in Everyday Image Editing Tasks
- analyzing 83k requests with their associated 305k edits from the recent 12 years on the `/r/PhotoshopRequest` Reddit community
- new dataset: PSR
- Hunyuan-Game: Industrial-grade Intelligent Game Creation Model
- lots of examples of game creation
- efficiency
- Scaling Law for Quantization-Aware Training
- a comprehensive scaling law for 4-bit QAT of LLMs, integrating model size, training dataset size, and quantization granularity
- previous methods do not account for quantization granularity G
- weight and activation quantization errors tend to contribute almost equally to the total error
- Fine-tuning Quantized Neural Networks with Zeroth-order Optimization
- push the limits of memory-efficient training by minimizing memory usage on model weights, gradients, and optimizer states, within a unified framework
- perturbs the continuous quantization scale for gradient estimation and uses a directional derivative clipping method to stabilize training
- Zeroth-order optimization (ZO) methods are often used in cases where gradients and higher-order derivatives of the objective cannot be directly computed or are unreliable
- successfully fine-tune Stable Diffusion 3.5 Large quantized by BitsAndBytes on stylized images using a single Nvidia RTX 4090 24GB GPU
- A Token is Worth over 1,000 Tokens: Efficient Knowledge Distillation through Low-Rank Clone
- trains a set of low-rank projection matrices that jointly enable soft pruning by compressing teacher weights, and activation clone by aligning student activations, including FFN signals, with those of the teacher
- remarkable distillation efficiency, achieving superior performance with more than 1000× fewer training tokens
- LRC w/o FFN produces a substantial performance degradation that persists throughout training, further confirming the critical importance of FFN activations
- LRC’s projection-based alignment is not only sufficient for effective knowledge transfer but also more efficient and stable
- agents, reasoning, RL
- NovelSeek: When Agent Becomes the Scientist -- Building Closed-Loop System from Hypothesis to Verification
- Reinforcement Learning Finetunes Small Subnetworks in Large Language Models
- Tool-Star: Empowering LLM-Brained Multi-Tool Reasoner via Reinforcement Learning
- AceReason-Nemotron: Advancing Math and Code Reasoning through Reinforcement Learning
- Training-Free Reasoning and Reflection in MLLMs
- Date Fragments: A Hidden Bottleneck of Tokenization for Temporal Reasoning
- RLVR-World: Training World Models with Reinforcement Learning
- SPhyR: Spatial-Physical Reasoning Benchmark on Material Distribution
- Risk-Averse Reinforcement Learning with Itakura-Saito Loss
- safety
- Phare: A Safety Probe for Large Language Models
- Audio Jailbreak: An Open Comprehensive Benchmark for Jailbreaking Large Audio-Language Models
- Are Vision-Language Models Safe in the Wild? A Meme-Based Benchmark Study
- application
- Steering Large Language Models for Machine Translation Personalization
- This Time is Different: An Observability Perspective on Time Series Foundation Models
- Prior Prompt Engineering for Reinforcement Fine-Tuning
- Using Large Language Models for Commit Message Generation: A Preliminary Study
- The Distracting Effect: Understanding Irrelevant Passages in RAG
- more
- Distilling LLM Agent into Small Models with Retrieval and Code Tools
- CLEVER: A Curated Benchmark for Formally Verified Code Generation
- DiSA: Diffusion Step Annealing in Autoregressive Image Generation
- Capability-Based Scaling Laws for LLM Red-Teaming
- FinTagging: An LLM-ready Benchmark for Extracting and Structuring Financial Information
- GSO: Challenging Software Optimization Tasks for Evaluating SWE-Agents
- watch The 3D Gaussian Splatting Adventure: Past, Present, Future
- DCM: Dual-Expert Consistency Model for Efficient and High-Quality Video Generation
- GUI-Actor: Coordinate-Free Visual Grounding for GUI Agents
- Agentic Neural Networks: Self-Evolving Multi-Agent Systems via Textual Backpropagation
- Large Language Models Often Know When They Are Being Evaluated
- Tiny-diffusion: A minimal implementation of probabilistic diffusion models
- AgentDistill: Training-Free Agent Distillation with Generalizable MCP Boxes
- Time Series Forecasting with Graph Transformers
- The Effect of State Representation on LLM Agent Behavior in Dynamic Routing Games
- Compiling LLMs into a MegaKernel: A path to low-latency inference
- Magenta RealTime: An Open-Weights Live Music Model
- Audit & Repair: An Agentic Framework for Consistent Story Visualization in Text-to-Image Diffusion Models
- Let Your Video Listen to Your Music!
- Vision as a Dialect: Unifying Visual Understanding and Generation via Text-Aligned Representations
- Bridging Cinematic Principles and Generative AI for Automated Film Generation
- Show HN: PILF, The ultimate solution to catastrophic oblivion on AI models
- Qwen VLo: From “Understanding” the World to “Depicting” It
- WorldVLA: Towards Autoregressive Action World Model (on HN)
- Small language models are the future of agentic AI (on HN)
- Overclocking LLM Reasoning: Monitoring and Controlling LLM Thinking Path Lengths (on HN)
- Reinforcement Learning from Human Feedback (RLHF) in Notebooks
- LLMs should not replace therapists (on HN)
- Mercury: Ultra-fast language models based on diffusion (on HN)
- Biomni: A General-Purpose Biomedical AI Agent (on HN)
- Distributed AI Agents for Cognitive Underwater Robot Autonomy
- GEPA: Reflective prompt evolution can outperform reinforcement learning (on HN)
- Hijacking multi-agent systems in your PajaMAS
- Core Safety Values for Provably Corrigible Agents
- Flow Matching Policy Gradients
- Fine-tuned small LLMs can beat large ones with programmatic data curation (on HN)
- the chosen task is considered not challenging
- Persona vectors: Monitoring and controlling character traits in language models (on HN)
- Qwen-Image: Crafting with native text rendering (on HN)
- Exploring Autonomous Agents: A Closer Look at Why They Fail When...
- Kimina-Prover: Applying Test-time RL Search on Large Formal Reasoning Models
- Emergent Misalignment: Narrow finetuning can produce broadly misaligned LLMs (on HN)
- Context Rot: How Increasing Input Tokens Impacts LLM Performance (on HN) (on lobste.rs)
- All AI models might be the same (on HN)
- LLM Economist: Large Population Models and Mechanism Design in Multi-Agent Generative Simulacra
- Subliminal learning: Models transmit behaviors via hidden signals in data (on HN)
- Simon Willison | Subliminal Learning: Language Models Transmit Behavioral Traits via Hidden Signals in Data
- Flow Matching Meets Biology and Life Science: A Survey
- Seed-Prover/SeedProver at main · ByteDance-Seed/Seed-Prover
- Transformers Without Normalization (on HN)
- Embedding-Aware Quantum-Classical SVMs for Scalable Quantum Machine Learning
Comments on [dereli2010degenerate] [uts-0007]
Comments on [dereli2010degenerate] [uts-0007]
This paper is found because it's cited by [filimoshina2023some].
Comments on [fauser2004grade] [uts-0006]
Comments on [fauser2004grade] [uts-0006]
- Some restrictions in Clifford algebra to geometric calculus: A unified language for mathematics and physics are relaxed in this paper.
- This paper cites A treatise on quantum clifford algebras for the foundation of Clifford algebra, and the use of Kuperberg graphical calculi over commutative diagrams.
Comments on [weber2013lie] [uts-0005]
Comments on [weber2013lie] [uts-0005]
Particularly, we cite:
- Lecture 18 - Clifford Algebras and Spin Groups
- Lecture 19 - Clifford and Spin Representations
- Lecture 20 - Duality and Triality
These lecture notes are based on Spin geometry (pms-38).
Comments on [woit2012lie] [uts-0004]
Comments on [woit2012lie] [uts-0004]
Particularly, we cite:
- Clifford Algebras and Spin Groups
- The Spinor Representation
Fulltext Search with Pathfind [uts-016D]
Fulltext Search with Pathfind [uts-016D]
> For now, this page only works if the forest site is started with `just pathfind`.
Definition. Kronecker delta [wiki2024dirac] [uts-0002]
Definition. Kronecker delta [wiki2024dirac] [uts-0002]
Kronecker delta \[\delta _{i j}= \begin {cases}0 & \text { if } i \neq j \\ 1 & \text { if } i=j\end {cases}\] or with use of Iverson bracket: \[ \delta _{i j}=[i=j] . \] where \([P]\) is defined as: \[ [P]=\begin {cases}1 & \text { if } P \text { is true } \\ 0 & \text { if } P \text { is false }\end {cases} \]
In Lean 4, the Kronecker delta could be defined as:
def δ (i j : I) : R := (Pi.single i 1 : _ → R) j
Test PDF [uts-000A]
Test PDF [uts-000A]
Test equation tagging and referencing [uts-000B]
Test equation tagging and referencing [uts-000B]
Inspired by thosgood/fga.
The following is an equation:
\[E = m c^2 \tag{math-eq-1.1}\]
Eq. [math-eq-1.1]
\[E = m c^2 \tag{1.2}\]
Eq. [eqid]
\[E = m c^2 \tag{1.3}\]
Eq. [eqid2]
\[E = m c^2 \tag{math-eq-1.4}\]
Eq. [math-eq-1.4]
games I really enjoyed [uts-001G]
games I really enjoyed [uts-001G]
## Flash games ### Pipol Destinations It's a simple game from my youth, where you need to guide people safely to their destinations by excavating or backfilling tunnels. It took me quite some effort to find it again, and it can be played using the Ruffle emulator nowadays. ## PC Games - Prince of Persia Series from Ubisoft, particularly - Prince of Persia: The Sands of Time (2003) - Prince of Persia: Warrior Within (2004) - Prince of Persia: The Two Thrones (2005) - Prince of Persia: The Forgotten Sands (2010) - I also played Prince of Persia (2008), but not so enjoyable as the others - Tomb Raider Series, particularly - One of Tomb Raider I/II/III (1996-1998) - Tomb Raider (2013) - Rise of the Tomb Raider (2015) - Sentimental Graffiti (1998) - Devil May Cry 4 (2008) - Homeworld 2 (2003) - Assassin's Creed Unity (2014) - Blades of Time (2012) - Prototype (2009) - Portal 2 (2011) - Ballance (2004) - Kerbal Space Program (2015) - FAR: Changing Tides (2022) - Black Myth: Wukong (2024) ## iOS Games - Mekorama (2016) - Fancade (2020) - Geostorm (2017) - Monument Valley (2014) - Monument Valley 2 (2017) ## Desktop Games - Ah!Ha Hedgehog Escape from Eureka - Jump IN' from SmartGames: Help the rabbits jump and hide! - Cytosis: An Animal Cell Biology Game from Genius Games
Definition. implicit surface [hart1996sphere, sec. 1] [ag-000K]
Definition. implicit surface [hart1996sphere, sec. 1] [ag-000K]
If an SDF \(f\) is a continuous mapping, the subset \(\Omega \) can be implicitly described as the locus of points \[ \Omega = \{ p : f(p) \le 0 \} \]
By continuety, \(f\) is zero on \(\partial \Omega \) which forms the implicit surface of \(f\).
some links about Star Trek [uts-001K]
some links about Star Trek [uts-001K]
I've long wished to note down memorable quotes from Star Trek. Particularly the Discovery, Picard, Orville and Strange New Worlds series in recent years. I have tried to look for high quality transcripts of these series, and selected quotes. Here are some good resources: - OpenSubtitles.org has subtitles organized by episode and season, e.g. Star Trek: Discovery (2017) but there is no easy way to bulk download and review the quality of the subtitles. Many subtitles from various sources are provided for each episode, and good subtitles might not be available for all episodes e.g. filtering by the title and the uploader - Memory Alpha on Fandom has detailed articles on each episode, with "Summary" for the plot and "Memorable quotes" - e.g. Star Trek: Discovery - full list of TV and films - a few websites from China: - https://www.startrekchina.org/ (also on Github) - https://docs.startrekcn.cn/ (also on Github) - Star Trek TrueType Font Collection
test graphviz transcludes [uts-001M]
test graphviz transcludes [uts-001M]
test typst [uts-000R]
test typst [uts-000R]
Note: The Typst files and their imports must be placed under typst, as it's set up as the root directory for Typst imports.
rendering a Typst file with imports
rendering a Typst file with imports
rendering a Typst code block with imports
rendering a Typst code block with imports
hybrid typst with forester markup
hybrid typst with forester markup
This is native forester markup:
- external link: typst docs
- wiki link: test tikz drawing
- citations: [nakahira2023diagrammatic]
- cross-references: § [uts-000E]
This is the same markup rendered in Typst:
render a complicated Typst file
render a complicated Typst file
Adapted from ⧉, removed figures and bib for now, due to depending on external non-Typst files.
test graphviz [uts-001L]
test graphviz [uts-001L]
Adapted from ⧉:
Adapted from ⧉:
Adapted from ⧉:
The same, but randomly choose a layout from one of 'circo', 'dot', 'fdp', 'sfdp', 'neato', 'osage', 'patchwork', 'twopi':
Home [index]
Home [index]
I'm Utensil Song, my Forester notes are hosted here, mostly about math and tech.
If you are new to Forester, you may wish to check out Some tips about Forester.
Breadcrumbs [uts-0169]
Breadcrumbs [uts-0169]
I keep a Learning diary since 2024, and trace back to my notes on interests in early years (2014~2023).
Math notes (partially complete) [uts-000U]
Math notes (partially complete) [uts-000U]
Notes on ray-marching implicit surfaces [ag-000G]
- August 17, 2024
- Utensil Song
Notes on ray-marching implicit surfaces [ag-000G]
- August 17, 2024
- Utensil Song
preface [ag-000H]
preface [ag-000H]
The note should contain:
- ray-marching ordinary SDFs
- ray-marching SDFs with singularities
- optimizations: bounded, adaptive etc.
- lighting
- shadow, including self-shadow
- edge detection
- auto-differentiation, curvature and geodesics
- non-Euclidean space
- dynamics, chaos, fractals
- volumetric ray marching
- meshes, polygonization, reconstruction
- higher dimensions
- PGA, CGA
- geometric construction based on topology and constraints
- neural implicit surfaces [Takikawa et al. 2021, Section 2]
- limitation
This is also an experiment to see how well the following 4 mix together in Forester:
- formal math notes of the concepts and formulas
- illustrative diagrams in TikZ
- psuedocode of the algorithms, then syntax highlighted acutal shade code
- the rendered GL canvas
See some links for rendering implicit surfaces, some links for learning shaders and 0910~0911 in Learning diary for some links as references. See test Three.js and shaders, test compute shaders for experiments on shaders.
implicit surfaces [ag-000M]
implicit surfaces [ag-000M]
Definition. level set
[wiki-level-set]
[ag-000Y]
A level set of a real-valued function \(f\) (a.k.a. an iso-contour of a scalar field in 3D)
\[L_c(f)=\left \{\boldsymbol {x} \mid \forall \boldsymbol {x} \in X, f(\boldsymbol {x})=c \right \} \]
where \(c\) is a constant.
Definition. level set [wiki-level-set] [ag-000Y]
Definition. implicit surface [winchenbach2024lipschitz, sec. 1] [ag-000X]
Definition. implicit surface [winchenbach2024lipschitz, sec. 1] [ag-000X]
Let \(\Omega \) be a subset of a topological space \(X\), and \(\partial \Omega \) be its boundary.
\(\partial \Omega \) as an implicit surface can be defined by a level set \(L_0(f)\) where \[ f(\boldsymbol {p})\begin {cases} \le 0 & \text { if } \boldsymbol {p} \in \Omega \\ > 0 & \text { if } \boldsymbol {p} \notin \Omega \end {cases} \]
SDFs [ag-000Z]
SDFs [ag-000Z]
Definition. signed distance function
[wiki-sdf]
[ag-000I]
Definition. signed distance function [wiki-sdf] [ag-000I]
Let \(\Omega \) be a subset of a metric space \(X\) with metric \(d\), and \(\partial \Omega \) be its boundary. The distance between a point \(\boldsymbol {p}\) of \(X\) and the subset \(\partial \Omega \) of \(X\) is defined as usual as \[ d(\boldsymbol {p}, \partial \Omega )=\inf _{\boldsymbol {q} \in \partial \Omega } d(\boldsymbol {p}, \boldsymbol {q}) \] where \(\inf \) denotes the infimum, i.e. the greatest lower bound.
The signed distance function or signed distance field (SDF) from a point \(\boldsymbol {p}\) of \(X\) to \(\Omega \) is defined by \[ f(\boldsymbol {p})= \begin {cases} -d(\boldsymbol {p}, \partial \Omega ) & \text { if } \boldsymbol {p} \in \Omega \\ d(\boldsymbol {p}, \partial \Omega ) & \text { if } \boldsymbol {p} \notin \Omega \end {cases} \]
Convention. sign [ag-000J]
Convention. sign [ag-000J]
Simply put, SDFs are the minimum possible distance from a point to an implicit surface defined by \(f(\boldsymbol {p})=0\).
The convention adopted in this note is that the \(+\) and \(-\) signs indicate whether the point is outside or inside the surface, respectively, so that when a ray marches towards the surface from the outside, the distance is positive, becomes smaller when approaching the surface.
[wiki-sdf] uses a convention with opposite signs.
Remark. SDFs in a Euclidean space [ag-0012]
Remark. SDFs in a Euclidean space [ag-0012]
If \(X\) is also a normed space, i.e. for a point \(\boldsymbol {p} \in X\), its norm can be defined, e.g. in a Euclidean space \(\mathbb R^n\) where \(\boldsymbol {p}\) can be expressed by basis vectors as \((p_1, \ldots , p_n)\), then its norm \(\lVert \boldsymbol {p}\rVert \) can be defined as the Euclidean norm \[ \lVert \boldsymbol {p}\rVert _2:=\sqrt {p_1^2+\cdots +p_n^2} \] which is essentially the distance from the origin \(\boldsymbol {o}=(0, \ldots , 0)\) to the point \(\boldsymbol {p}\) \[ \lVert \boldsymbol {p}\rVert =d(\boldsymbol {p}, \boldsymbol {o})=\lVert \boldsymbol {p} - \boldsymbol {o}\rVert \] where \(d\) is the Euclidean distance function.
In the following, we will be working with Euclidean space \(\mathbb R^n\), which is both a metric space and a normed space. Most of the time, we will focus on \(\mathbb R^3\) for visualization purposes.
Example. SDF of a sphere [ag-000L]
Example. SDF of a sphere [ag-000L]
The SDF of a sphere with radius \(r\) centered at the origin \(\boldsymbol {o}\) is \[ f(\boldsymbol {p})=\lVert \boldsymbol {p}\rVert -r \] as depicted below:
Figure. SDF for a sphere [ag-0017]
Figure. SDF for a sphere [ag-0017]
The SDF above for a sphere translates to the following GLSL:
float sdSphere(vec3 p, float r)
{
return length(p) - r;
}
Example. SDFs of geometric primitives [ag-0011]
Example. SDFs of geometric primitives [ag-0011]
SDFs of some geometric primitives in \(\mathbb R^3\), can be found in Appendix A: Distance to Natural Quadrics and Torus of [hart1996sphere].
Many more can be found in Inigo Quilez's article Distance functions (written in GLSL), which also includes an example that renders them by ray-marching.
Figure. Raymarching primitives [ag-0014]
Figure. Raymarching primitives [ag-0014]
#define HW_PERFORMANCE 0
// The MIT License
// Copyright © 2013 Inigo Quilez
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// The license is here only not because I want to (can one
// license pieces of math?), but because people get upset
// if I don't add one...
// A list of useful distance function to simple primitives. All
// these functions (except for ellipsoid) return an exact
// euclidean distance, meaning they produce a better SDF than
// what you'd get if you were constructing them from boolean
// operations (such as cutting an infinite cylinder with two planes).
// List of other 3D SDFs:
// https://www.shadertoy.com/playlist/43cXRl
// and
// https://iquilezles.org/articles/distfunctions
#if HW_PERFORMANCE==0
#define AA 1
#else
#define AA 1 // make this 2 or 3 for antialiasing
#endif
//------------------------------------------------------------------
float dot2( in vec2 v ) { return dot(v,v); }
float dot2( in vec3 v ) { return dot(v,v); }
float ndot( in vec2 a, in vec2 b ) { return a.x*b.x - a.y*b.y; }
float sdPlane( vec3 p )
{
return p.y;
}
float sdSphere( vec3 p, float s )
{
return length(p)-s;
}
float sdBox( vec3 p, vec3 b )
{
vec3 d = abs(p) - b;
return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0));
}
float sdBoxFrame( vec3 p, vec3 b, float e )
{
p = abs(p )-b;
vec3 q = abs(p+e)-e;
return min(min(
length(max(vec3(p.x,q.y,q.z),0.0))+min(max(p.x,max(q.y,q.z)),0.0),
length(max(vec3(q.x,p.y,q.z),0.0))+min(max(q.x,max(p.y,q.z)),0.0)),
length(max(vec3(q.x,q.y,p.z),0.0))+min(max(q.x,max(q.y,p.z)),0.0));
}
float sdEllipsoid( in vec3 p, in vec3 r ) // approximated
{
float k0 = length(p/r);
float k1 = length(p/(r*r));
return k0*(k0-1.0)/k1;
}
float sdTorus( vec3 p, vec2 t )
{
return length( vec2(length(p.xz)-t.x,p.y) )-t.y;
}
float sdCappedTorus(in vec3 p, in vec2 sc, in float ra, in float rb)
{
p.x = abs(p.x);
float k = (sc.y*p.x>sc.x*p.y) ? dot(p.xy,sc) : length(p.xy);
return sqrt( dot(p,p) + ra*ra - 2.0*ra*k ) - rb;
}
float sdHexPrism( vec3 p, vec2 h )
{
vec3 q = abs(p);
const vec3 k = vec3(-0.8660254, 0.5, 0.57735);
p = abs(p);
p.xy -= 2.0*min(dot(k.xy, p.xy), 0.0)*k.xy;
vec2 d = vec2(
length(p.xy - vec2(clamp(p.x, -k.z*h.x, k.z*h.x), h.x))*sign(p.y - h.x),
p.z-h.y );
return min(max(d.x,d.y),0.0) + length(max(d,0.0));
}
float sdOctogonPrism( in vec3 p, in float r, float h )
{
const vec3 k = vec3(-0.9238795325, // sqrt(2+sqrt(2))/2
0.3826834323, // sqrt(2-sqrt(2))/2
0.4142135623 ); // sqrt(2)-1
// reflections
p = abs(p);
p.xy -= 2.0*min(dot(vec2( k.x,k.y),p.xy),0.0)*vec2( k.x,k.y);
p.xy -= 2.0*min(dot(vec2(-k.x,k.y),p.xy),0.0)*vec2(-k.x,k.y);
// polygon side
p.xy -= vec2(clamp(p.x, -k.z*r, k.z*r), r);
vec2 d = vec2( length(p.xy)*sign(p.y), p.z-h );
return min(max(d.x,d.y),0.0) + length(max(d,0.0));
}
float sdCapsule( vec3 p, vec3 a, vec3 b, float r )
{
vec3 pa = p-a, ba = b-a;
float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
return length( pa - ba*h ) - r;
}
float sdRoundCone( in vec3 p, in float r1, float r2, float h )
{
vec2 q = vec2( length(p.xz), p.y );
float b = (r1-r2)/h;
float a = sqrt(1.0-b*b);
float k = dot(q,vec2(-b,a));
if( k < 0.0 ) return length(q) - r1;
if( k > a*h ) return length(q-vec2(0.0,h)) - r2;
return dot(q, vec2(a,b) ) - r1;
}
float sdRoundCone(vec3 p, vec3 a, vec3 b, float r1, float r2)
{
// sampling independent computations (only depend on shape)
vec3 ba = b - a;
float l2 = dot(ba,ba);
float rr = r1 - r2;
float a2 = l2 - rr*rr;
float il2 = 1.0/l2;
// sampling dependant computations
vec3 pa = p - a;
float y = dot(pa,ba);
float z = y - l2;
float x2 = dot2( pa*l2 - ba*y );
float y2 = y*y*l2;
float z2 = z*z*l2;
// single square root!
float k = sign(rr)*rr*rr*x2;
if( sign(z)*a2*z2 > k ) return sqrt(x2 + z2) *il2 - r2;
if( sign(y)*a2*y2 < k ) return sqrt(x2 + y2) *il2 - r1;
return (sqrt(x2*a2*il2)+y*rr)*il2 - r1;
}
float sdTriPrism( vec3 p, vec2 h )
{
const float k = sqrt(3.0);
h.x *= 0.5*k;
p.xy /= h.x;
p.x = abs(p.x) - 1.0;
p.y = p.y + 1.0/k;
if( p.x+k*p.y>0.0 ) p.xy=vec2(p.x-k*p.y,-k*p.x-p.y)/2.0;
p.x -= clamp( p.x, -2.0, 0.0 );
float d1 = length(p.xy)*sign(-p.y)*h.x;
float d2 = abs(p.z)-h.y;
return length(max(vec2(d1,d2),0.0)) + min(max(d1,d2), 0.);
}
// vertical
float sdCylinder( vec3 p, vec2 h )
{
vec2 d = abs(vec2(length(p.xz),p.y)) - h;
return min(max(d.x,d.y),0.0) + length(max(d,0.0));
}
// arbitrary orientation
float sdCylinder(vec3 p, vec3 a, vec3 b, float r)
{
vec3 pa = p - a;
vec3 ba = b - a;
float baba = dot(ba,ba);
float paba = dot(pa,ba);
float x = length(pa*baba-ba*paba) - r*baba;
float y = abs(paba-baba*0.5)-baba*0.5;
float x2 = x*x;
float y2 = y*y*baba;
float d = (max(x,y)<0.0)?-min(x2,y2):(((x>0.0)?x2:0.0)+((y>0.0)?y2:0.0));
return sign(d)*sqrt(abs(d))/baba;
}
// vertical
float sdCone( in vec3 p, in vec2 c, float h )
{
vec2 q = h*vec2(c.x,-c.y)/c.y;
vec2 w = vec2( length(p.xz), p.y );
vec2 a = w - q*clamp( dot(w,q)/dot(q,q), 0.0, 1.0 );
vec2 b = w - q*vec2( clamp( w.x/q.x, 0.0, 1.0 ), 1.0 );
float k = sign( q.y );
float d = min(dot( a, a ),dot(b, b));
float s = max( k*(w.x*q.y-w.y*q.x),k*(w.y-q.y) );
return sqrt(d)*sign(s);
}
float sdCappedCone( in vec3 p, in float h, in float r1, in float r2 )
{
vec2 q = vec2( length(p.xz), p.y );
vec2 k1 = vec2(r2,h);
vec2 k2 = vec2(r2-r1,2.0*h);
vec2 ca = vec2(q.x-min(q.x,(q.y < 0.0)?r1:r2), abs(q.y)-h);
vec2 cb = q - k1 + k2*clamp( dot(k1-q,k2)/dot2(k2), 0.0, 1.0 );
float s = (cb.x < 0.0 && ca.y < 0.0) ? -1.0 : 1.0;
return s*sqrt( min(dot2(ca),dot2(cb)) );
}
float sdCappedCone(vec3 p, vec3 a, vec3 b, float ra, float rb)
{
float rba = rb-ra;
float baba = dot(b-a,b-a);
float papa = dot(p-a,p-a);
float paba = dot(p-a,b-a)/baba;
float x = sqrt( papa - paba*paba*baba );
float cax = max(0.0,x-((paba<0.5)?ra:rb));
float cay = abs(paba-0.5)-0.5;
float k = rba*rba + baba;
float f = clamp( (rba*(x-ra)+paba*baba)/k, 0.0, 1.0 );
float cbx = x-ra - f*rba;
float cby = paba - f;
float s = (cbx < 0.0 && cay < 0.0) ? -1.0 : 1.0;
return s*sqrt( min(cax*cax + cay*cay*baba,
cbx*cbx + cby*cby*baba) );
}
// c is the sin/cos of the desired cone angle
float sdSolidAngle(vec3 pos, vec2 c, float ra)
{
vec2 p = vec2( length(pos.xz), pos.y );
float l = length(p) - ra;
float m = length(p - c*clamp(dot(p,c),0.0,ra) );
return max(l,m*sign(c.y*p.x-c.x*p.y));
}
float sdOctahedron(vec3 p, float s)
{
p = abs(p);
float m = p.x + p.y + p.z - s;
// exact distance
#if 0
vec3 o = min(3.0*p - m, 0.0);
o = max(6.0*p - m*2.0 - o*3.0 + (o.x+o.y+o.z), 0.0);
return length(p - s*o/(o.x+o.y+o.z));
#endif
// exact distance
#if 1
vec3 q;
if( 3.0*p.x < m ) q = p.xyz;
else if( 3.0*p.y < m ) q = p.yzx;
else if( 3.0*p.z < m ) q = p.zxy;
else return m*0.57735027;
float k = clamp(0.5*(q.z-q.y+s),0.0,s);
return length(vec3(q.x,q.y-s+k,q.z-k));
#endif
// bound, not exact
#if 0
return m*0.57735027;
#endif
}
float sdPyramid( in vec3 p, in float h )
{
float m2 = h*h + 0.25;
// symmetry
p.xz = abs(p.xz);
p.xz = (p.z>p.x) ? p.zx : p.xz;
p.xz -= 0.5;
// project into face plane (2D)
vec3 q = vec3( p.z, h*p.y - 0.5*p.x, h*p.x + 0.5*p.y);
float s = max(-q.x,0.0);
float t = clamp( (q.y-0.5*p.z)/(m2+0.25), 0.0, 1.0 );
float a = m2*(q.x+s)*(q.x+s) + q.y*q.y;
float b = m2*(q.x+0.5*t)*(q.x+0.5*t) + (q.y-m2*t)*(q.y-m2*t);
float d2 = min(q.y,-q.x*m2-q.y*0.5) > 0.0 ? 0.0 : min(a,b);
// recover 3D and scale, and add sign
return sqrt( (d2+q.z*q.z)/m2 ) * sign(max(q.z,-p.y));;
}
// la,lb=semi axis, h=height, ra=corner
float sdRhombus(vec3 p, float la, float lb, float h, float ra)
{
p = abs(p);
vec2 b = vec2(la,lb);
float f = clamp( (ndot(b,b-2.0*p.xz))/dot(b,b), -1.0, 1.0 );
vec2 q = vec2(length(p.xz-0.5*b*vec2(1.0-f,1.0+f))*sign(p.x*b.y+p.z*b.x-b.x*b.y)-ra, p.y-h);
return min(max(q.x,q.y),0.0) + length(max(q,0.0));
}
float sdHorseshoe( in vec3 p, in vec2 c, in float r, in float le, vec2 w )
{
p.x = abs(p.x);
float l = length(p.xy);
p.xy = mat2(-c.x, c.y,
c.y, c.x)*p.xy;
p.xy = vec2((p.y>0.0 || p.x>0.0)?p.x:l*sign(-c.x),
(p.x>0.0)?p.y:l );
p.xy = vec2(p.x,abs(p.y-r))-vec2(le,0.0);
vec2 q = vec2(length(max(p.xy,0.0)) + min(0.0,max(p.x,p.y)),p.z);
vec2 d = abs(q) - w;
return min(max(d.x,d.y),0.0) + length(max(d,0.0));
}
float sdU( in vec3 p, in float r, in float le, vec2 w )
{
p.x = (p.y>0.0) ? abs(p.x) : length(p.xy);
p.x = abs(p.x-r);
p.y = p.y - le;
float k = max(p.x,p.y);
vec2 q = vec2( (k<0.0) ? -k : length(max(p.xy,0.0)), abs(p.z) ) - w;
return length(max(q,0.0)) + min(max(q.x,q.y),0.0);
}
//------------------------------------------------------------------
vec2 opU( vec2 d1, vec2 d2 )
{
return (d1.x<d2.x) ? d1 : d2;
}
//------------------------------------------------------------------
#define ZERO (min(iFrame,0))
//------------------------------------------------------------------
vec2 map( in vec3 pos )
{
vec2 res = vec2( pos.y, 0.0 );
// bounding box
if( sdBox( pos-vec3(-2.0,0.3,0.25),vec3(0.3,0.3,1.0) )<res.x )
{
res = opU( res, vec2( sdSphere( pos-vec3(-2.0,0.25, 0.0), 0.25 ), 26.9 ) );
res = opU( res, vec2( sdRhombus( (pos-vec3(-2.0,0.25, 1.0)).xzy, 0.15, 0.25, 0.04, 0.08 ),17.0 ) );
}
// bounding box
if( sdBox( pos-vec3(0.0,0.3,-1.0),vec3(0.35,0.3,2.5) )<res.x )
{
res = opU( res, vec2( sdCappedTorus((pos-vec3( 0.0,0.30, 1.0))*vec3(1,-1,1), vec2(0.866025,-0.5), 0.25, 0.05), 25.0) );
res = opU( res, vec2( sdBoxFrame( pos-vec3( 0.0,0.25, 0.0), vec3(0.3,0.25,0.2), 0.025 ), 16.9 ) );
res = opU( res, vec2( sdCone( pos-vec3( 0.0,0.45,-1.0), vec2(0.6,0.8),0.45 ), 55.0 ) );
res = opU( res, vec2( sdCappedCone( pos-vec3( 0.0,0.25,-2.0), 0.25, 0.25, 0.1 ), 13.67 ) );
res = opU( res, vec2( sdSolidAngle( pos-vec3( 0.0,0.00,-3.0), vec2(3,4)/5.0, 0.4 ), 49.13 ) );
}
// bounding box
if( sdBox( pos-vec3(1.0,0.3,-1.0),vec3(0.35,0.3,2.5) )<res.x )
{
res = opU( res, vec2( sdTorus( (pos-vec3( 1.0,0.30, 1.0)).xzy, vec2(0.25,0.05) ), 7.1 ) );
res = opU( res, vec2( sdBox( pos-vec3( 1.0,0.25, 0.0), vec3(0.3,0.25,0.1) ), 3.0 ) );
res = opU( res, vec2( sdCapsule( pos-vec3( 1.0,0.00,-1.0),vec3(-0.1,0.1,-0.1), vec3(0.2,0.4,0.2), 0.1 ), 31.9 ) );
res = opU( res, vec2( sdCylinder( pos-vec3( 1.0,0.25,-2.0), vec2(0.15,0.25) ), 8.0 ) );
res = opU( res, vec2( sdHexPrism( pos-vec3( 1.0,0.2,-3.0), vec2(0.2,0.05) ), 18.4 ) );
}
// bounding box
if( sdBox( pos-vec3(-1.0,0.35,-1.0),vec3(0.35,0.35,2.5))<res.x )
{
res = opU( res, vec2( sdPyramid( pos-vec3(-1.0,-0.6,-3.0), 1.0 ), 13.56 ) );
res = opU( res, vec2( sdOctahedron( pos-vec3(-1.0,0.15,-2.0), 0.35 ), 23.56 ) );
res = opU( res, vec2( sdTriPrism( pos-vec3(-1.0,0.15,-1.0), vec2(0.3,0.05) ),43.5 ) );
res = opU( res, vec2( sdEllipsoid( pos-vec3(-1.0,0.25, 0.0), vec3(0.2, 0.25, 0.05) ), 43.17 ) );
res = opU( res, vec2( sdHorseshoe( pos-vec3(-1.0,0.25, 1.0), vec2(cos(1.3),sin(1.3)), 0.2, 0.3, vec2(0.03,0.08) ), 11.5 ) );
}
// bounding box
if( sdBox( pos-vec3(2.0,0.3,-1.0),vec3(0.35,0.3,2.5) )<res.x )
{
res = opU( res, vec2( sdOctogonPrism(pos-vec3( 2.0,0.2,-3.0), 0.2, 0.05), 51.8 ) );
res = opU( res, vec2( sdCylinder( pos-vec3( 2.0,0.14,-2.0), vec3(0.1,-0.1,0.0), vec3(-0.2,0.35,0.1), 0.08), 31.2 ) );
res = opU( res, vec2( sdCappedCone( pos-vec3( 2.0,0.09,-1.0), vec3(0.1,0.0,0.0), vec3(-0.2,0.40,0.1), 0.15, 0.05), 46.1 ) );
res = opU( res, vec2( sdRoundCone( pos-vec3( 2.0,0.15, 0.0), vec3(0.1,0.0,0.0), vec3(-0.1,0.35,0.1), 0.15, 0.05), 51.7 ) );
res = opU( res, vec2( sdRoundCone( pos-vec3( 2.0,0.20, 1.0), 0.2, 0.1, 0.3 ), 37.0 ) );
}
return res;
}
// https://iquilezles.org/articles/boxfunctions
vec2 iBox( in vec3 ro, in vec3 rd, in vec3 rad )
{
vec3 m = 1.0/rd;
vec3 n = m*ro;
vec3 k = abs(m)*rad;
vec3 t1 = -n - k;
vec3 t2 = -n + k;
return vec2( max( max( t1.x, t1.y ), t1.z ),
min( min( t2.x, t2.y ), t2.z ) );
}
vec2 raycast( in vec3 ro, in vec3 rd )
{
vec2 res = vec2(-1.0,-1.0);
float tmin = 1.0;
float tmax = 20.0;
// raytrace floor plane
float tp1 = (0.0-ro.y)/rd.y;
if( tp1>0.0 )
{
tmax = min( tmax, tp1 );
res = vec2( tp1, 1.0 );
}
//else return res;
// raymarch primitives
vec2 tb = iBox( ro-vec3(0.0,0.4,-0.5), rd, vec3(2.5,0.41,3.0) );
if( tb.x<tb.y && tb.y>0.0 && tb.x<tmax)
{
//return vec2(tb.x,2.0);
tmin = max(tb.x,tmin);
tmax = min(tb.y,tmax);
float t = tmin;
for( int i=0; i<70 && t<tmax; i++ )
{
vec2 h = map( ro+rd*t );
if( abs(h.x)<(0.0001*t) )
{
res = vec2(t,h.y);
break;
}
t += h.x;
}
}
return res;
}
// https://iquilezles.org/articles/rmshadows
float calcSoftshadow( in vec3 ro, in vec3 rd, in float mint, in float tmax )
{
// bounding volume
float tp = (0.8-ro.y)/rd.y; if( tp>0.0 ) tmax = min( tmax, tp );
float res = 1.0;
float t = mint;
for( int i=ZERO; i<24; i++ )
{
float h = map( ro + rd*t ).x;
float s = clamp(8.0*h/t,0.0,1.0);
res = min( res, s );
t += clamp( h, 0.01, 0.2 );
if( res<0.004 || t>tmax ) break;
}
res = clamp( res, 0.0, 1.0 );
return res*res*(3.0-2.0*res);
}
// https://iquilezles.org/articles/normalsSDF
vec3 calcNormal( in vec3 pos )
{
#if 0
vec2 e = vec2(1.0,-1.0)*0.5773*0.0005;
return normalize( e.xyy*map( pos + e.xyy ).x +
e.yyx*map( pos + e.yyx ).x +
e.yxy*map( pos + e.yxy ).x +
e.xxx*map( pos + e.xxx ).x );
#else
// inspired by tdhooper and klems - a way to prevent the compiler from inlining map() 4 times
vec3 n = vec3(0.0);
for( int i=ZERO; i<4; i++ )
{
vec3 e = 0.5773*(2.0*vec3((((i+3)>>1)&1),((i>>1)&1),(i&1))-1.0);
n += e*map(pos+0.0005*e).x;
//if( n.x+n.y+n.z>100.0 ) break;
}
return normalize(n);
#endif
}
// https://iquilezles.org/articles/nvscene2008/rwwtt.pdf
float calcAO( in vec3 pos, in vec3 nor )
{
float occ = 0.0;
float sca = 1.0;
for( int i=ZERO; i<5; i++ )
{
float h = 0.01 + 0.12*float(i)/4.0;
float d = map( pos + h*nor ).x;
occ += (h-d)*sca;
sca *= 0.95;
if( occ>0.35 ) break;
}
return clamp( 1.0 - 3.0*occ, 0.0, 1.0 ) * (0.5+0.5*nor.y);
}
// https://iquilezles.org/articles/checkerfiltering
float checkersGradBox( in vec2 p, in vec2 dpdx, in vec2 dpdy )
{
// filter kernel
vec2 w = abs(dpdx)+abs(dpdy) + 0.001;
// analytical integral (box filter)
vec2 i = 2.0*(abs(fract((p-0.5*w)*0.5)-0.5)-abs(fract((p+0.5*w)*0.5)-0.5))/w;
// xor pattern
return 0.5 - 0.5*i.x*i.y;
}
vec3 render( in vec3 ro, in vec3 rd, in vec3 rdx, in vec3 rdy )
{
// background
vec3 col = vec3(0.7, 0.7, 0.9) - max(rd.y,0.0)*0.3;
// raycast scene
vec2 res = raycast(ro,rd);
float t = res.x;
float m = res.y;
if( m>-0.5 )
{
vec3 pos = ro + t*rd;
vec3 nor = (m<1.5) ? vec3(0.0,1.0,0.0) : calcNormal( pos );
vec3 ref = reflect( rd, nor );
// material
col = 0.2 + 0.2*sin( m*2.0 + vec3(0.0,1.0,2.0) );
float ks = 1.0;
if( m<1.5 )
{
// project pixel footprint into the plane
vec3 dpdx = ro.y*(rd/rd.y-rdx/rdx.y);
vec3 dpdy = ro.y*(rd/rd.y-rdy/rdy.y);
float f = checkersGradBox( 3.0*pos.xz, 3.0*dpdx.xz, 3.0*dpdy.xz );
col = 0.15 + f*vec3(0.05);
ks = 0.4;
}
// lighting
float occ = calcAO( pos, nor );
vec3 lin = vec3(0.0);
// sun
{
vec3 lig = normalize( vec3(-0.5, 0.4, -0.6) );
vec3 hal = normalize( lig-rd );
float dif = clamp( dot( nor, lig ), 0.0, 1.0 );
//if( dif>0.0001 )
dif *= calcSoftshadow( pos, lig, 0.02, 2.5 );
float spe = pow( clamp( dot( nor, hal ), 0.0, 1.0 ),16.0);
spe *= dif;
spe *= 0.04+0.96*pow(clamp(1.0-dot(hal,lig),0.0,1.0),5.0);
//spe *= 0.04+0.96*pow(clamp(1.0-sqrt(0.5*(1.0-dot(rd,lig))),0.0,1.0),5.0);
lin += col*2.20*dif*vec3(1.30,1.00,0.70);
lin += 5.00*spe*vec3(1.30,1.00,0.70)*ks;
}
// sky
{
float dif = sqrt(clamp( 0.5+0.5*nor.y, 0.0, 1.0 ));
dif *= occ;
float spe = smoothstep( -0.2, 0.2, ref.y );
spe *= dif;
spe *= 0.04+0.96*pow(clamp(1.0+dot(nor,rd),0.0,1.0), 5.0 );
//if( spe>0.001 )
spe *= calcSoftshadow( pos, ref, 0.02, 2.5 );
lin += col*0.60*dif*vec3(0.40,0.60,1.15);
lin += 2.00*spe*vec3(0.40,0.60,1.30)*ks;
}
// back
{
float dif = clamp( dot( nor, normalize(vec3(0.5,0.0,0.6))), 0.0, 1.0 )*clamp( 1.0-pos.y,0.0,1.0);
dif *= occ;
lin += col*0.55*dif*vec3(0.25,0.25,0.25);
}
// sss
{
float dif = pow(clamp(1.0+dot(nor,rd),0.0,1.0),2.0);
dif *= occ;
lin += col*0.25*dif*vec3(1.00,1.00,1.00);
}
col = lin;
col = mix( col, vec3(0.7,0.7,0.9), 1.0-exp( -0.0001*t*t*t ) );
}
return vec3( clamp(col,0.0,1.0) );
}
mat3 setCamera( in vec3 ro, in vec3 ta, float cr )
{
vec3 cw = normalize(ta-ro);
vec3 cp = vec3(sin(cr), cos(cr),0.0);
vec3 cu = normalize( cross(cw,cp) );
vec3 cv = ( cross(cu,cw) );
return mat3( cu, cv, cw );
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 mo = iMouse.xy/iResolution.xy;
float time = 32.0 + iTime*1.5;
// camera
vec3 ta = vec3( 0.25, -0.75, -0.25 );
vec3 ro = ta + vec3( 6.0*cos(0.1*time + 7.0*mo.x), 4.5, 6.0*sin(0.1*time + 7.0*mo.x) );
// camera-to-world transformation
mat3 ca = setCamera( ro, ta, 0.0 );
vec3 tot = vec3(0.0);
#if AA>1
for( int m=ZERO; m<AA; m++ )
for( int n=ZERO; n<AA; n++ )
{
// pixel coordinates
vec2 o = vec2(float(m),float(n)) / float(AA) - 0.5;
vec2 p = (2.0*(fragCoord+o)-iResolution.xy)/iResolution.y;
#else
vec2 p = (2.0*fragCoord-iResolution.xy)/iResolution.y;
#endif
// focal length
const float fl = 2.5;
// ray direction
vec3 rd = ca * normalize( vec3(p,fl) );
// ray differentials
vec2 px = (2.0*(fragCoord+vec2(1.0,0.0))-iResolution.xy)/iResolution.y;
vec2 py = (2.0*(fragCoord+vec2(0.0,1.0))-iResolution.xy)/iResolution.y;
vec3 rdx = ca * normalize( vec3(px,fl) );
vec3 rdy = ca * normalize( vec3(py,fl) );
// render
vec3 col = render( ro, rd, rdx, rdy );
// gain
// col = col*3.0/(2.5+col);
// gamma
col = pow( col, vec3(0.4545) );
tot += col;
#if AA>1
}
tot /= float(AA*AA);
#endif
fragColor = vec4( tot, 1.0 );
}
Example. SDFs of exotic implicit surfaces [ag-0013]
Example. SDFs of exotic implicit surfaces [ag-0013]
SDFs of many exotic implicit surfaces can be found in:
- Appendix A: Implicit Equations in [singh2009real]
- Appendix B: Function definitions in [winchenbach2024lipschitz]
- [gillespie2024ray]
- Herwig Hauser's Gallery of Singular Algebraic Surfaces
The following example renders many exotic implicit surfaces by ray-marching:
Figure. Implicit surfaces [uts-000J]
Figure. Implicit surfaces [uts-000J]
#define AS_LIB 1
int get_shape() {
return int(iTime) % 52;
}
#include "/forest/shader/implicit.glsl"
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = 2.*(fragCoord-iResolution.xy/2.)/iResolution.y; // contains [-1,1]^2
vec3 col = vec3(0.);
// Camera rays
vec3 camPos = vec3(4.,0.,0.);
vec3 camDir = - normalize(camPos);
vec3 rayPos, rayDir;
float zoom = 1.3; // 1.8*cos(iTime);
// if (checkKey(KEY_E)) zoom = 0.5;
float fov = 0.4*zoom;
float fov_ortho = 1.5*zoom;
#if perspective
// perspective cam
rayPos = camPos;
rayDir = normalize(camDir + fov*vec3(0., uv.x, uv.y));
#else
// orthographic cam
rayPos = camPos + fov_ortho*vec3(0., uv.x, uv.y);
rayDir = camDir;
#endif
// for perspective background in orthographic mode
vec3 cubemapDir = normalize(camDir + fov*vec3(0., uv.x, uv.y));
// Mouse-controlled rotation
vec2 mouse = initMouse + vec2(0.015625*sin(iTime*PI), 0.0); // initMouse; // iMouse.xy == vec2(0.,0.) ? initMouse : (iMouse.xy/iResolution.xy - 0.5);
float yaw = clamp(- mouse.x * 2.*PI * 1., -PI,PI);
float pitch = clamp( mouse.y * PI * 1.2, -PI*0.5, PI*0.5);
// pitch and yaw rotations (column-wise matrices)
mat3 rot = mat3(cos(yaw), sin(yaw), 0., -sin(yaw), cos(yaw), 0., 0., 0., 1.);
rot = rot * mat3(cos(pitch), 0., -sin(pitch), 0., 1., 0., sin(pitch), 0., cos(pitch));
// apply
camPos = rot*camPos;
camDir = rot*camDir;
rayPos = rot*rayPos;
rayDir = rot*rayDir;
cubemapDir = rot*cubemapDir;
//cubemapDir = vec3(cubemapDir.x, cubemapDir.z, cubemapDir.y);
vec3 hitPoint = raycast(rayPos, rayDir);
if (hitPoint == BINGO) { fragColor = vec4(BINGO,1.0); return; }
//if (hitPoint == NOHIT) { fragColor = vec4(NOHIT,1.0); return; }
//if (hitPoint == NOBOUNDHIT) { fragColor = vec4(NOBOUNDHIT,1.0); return; }
//if (hitPoint == ESCAPEDBOUNDS) { fragColor = vec4(ESCAPEDBOUNDS,1.0); return; }
//if (hitPoint == MAXDISTREACHED) { fragColor = vec4(MAXDISTREACHED,1.0); return; }
//if (hitPoint == MAXITERREACHED) { fragColor = vec4(MAXITERREACHED,1.0); return; }
if (hitPoint == NOBOUNDHIT || hitPoint == NOHIT || hitPoint == ESCAPEDBOUNDS || hitPoint == MAXITERREACHED) {
//fragColor = vec4(vec3(0.2),1.0); return;
// make background transparent
fragColor = vec4(0.0,0.0,0.0,0.0); return;
col = with_background(cubemapDir);
#if showBoundingCube
// darken bounding cube
if (hitPoint != NOBOUNDHIT) { col *= vec3(0.7); }
#endif
fragColor = vec4(col,1.0); return;
}
vec3 grad = gradf(hitPoint+1.1*EPS*(-rayDir));
float s = -sign(dot(grad,rayDir));
col = with_color_mode(grad, s, hitPoint, camPos);
col = clamp(col, 0., 1.);
col = with_surface_pattern(col, hitPoint);
col = with_shading(col, grad, s, rayDir);
col = clamp(col, 0., 1.);
fragColor = vec4(col,1.0);
}
Example. SDFs of implicit surfaces in exotic geometries [ag-0016]
Example. SDFs of implicit surfaces in exotic geometries [ag-0016]
Implicit surface could be defined in geometries other than Euclidean space, for some examples of such geometries, see [szirmay2022adapting] [coulon2022ray] [kopczynski2022real] and more.
The following example renders exotic implicit surfaces in exotic geometries by ray-marching:
Figure. Geodesic raytracing [ag-0015]
Figure. Geodesic raytracing [ag-0015]
//********************************************************************
//
// Begin of automatic differentiation header
// Full code with additional functions (gradients, jacobians, ...) can be found
// at: https://github.com/sibaku/glsl-autodiff
//
//********************************************************************
#ifndef HESSNUM_3_H_
#define HESSNUM_3_H_
// This file contains methods to compute the gradient and hessian
// of a scalar valued 3 dimensional function using automatic forward differentiation
//--------------------------------
// Types
//--------------------------------
// Data type to hold information about a scalar valued 3 dimensional function
// These should be created by the constH3 (for constants) and varH3 (for variables) helpers
struct HNum3
{
// The current value
float val;
// The current gradient
vec3 g;
// The current hessian
mat3 h;
};
//--------------------------------
// Prototypes
//--------------------------------
/**
* Creates a constant HNum3
* @param val The current value of the constant
*/
HNum3 constH3(in float val);
/**
* Creates a HNum3 corresponding to the variable with the given index
* @param val The current value of the variable
* @param index The variable's index
*/
HNum3 varH3(in float val, in int index);
/**
* Creates a HNum3 corresponding to the variable x (index = 0)
* @param val The current value of the variable
*/
HNum3 varH3x(in float val);
/**
* Creates a HNum3 corresponding to the variable y (index = 1)
* @param val The current value of the variable
*/
HNum3 varH3y(in float val);
/**
* Creates a HNum3 corresponding to the variable z (index = 2)
* @param val The current value of the variable
*/
HNum3 varH3z(in float val);
HNum3 add(in HNum3 a, in HNum3 b);
HNum3 add(in HNum3 a, in float b);
HNum3 add(in float a, in HNum3 b);
HNum3 sub(in HNum3 a, in HNum3 b);
HNum3 sub(in HNum3 a, in float b);
HNum3 sub(in float a, in HNum3 b);
HNum3 mult(in HNum3 a, in HNum3 b);
HNum3 mult(in HNum3 a, in float b);
HNum3 mult(in float a, in HNum3 b);
HNum3 neg(in HNum3 a);
HNum3 div(in HNum3 a, in HNum3 b);
HNum3 div(in HNum3 a, in float b);
HNum3 div(in float a, in HNum3 b);
HNum3 inv(in HNum3 a);
HNum3 a_pow(in HNum3 a, in HNum3 b);
HNum3 a_pow(in HNum3 a, in float b);
HNum3 a_pow(in float a, in HNum3 b);
HNum3 a_min(in HNum3 a, in HNum3 b);
HNum3 a_max(in HNum3 a, in HNum3 b);
HNum3 a_exp2(in HNum3 a);
HNum3 a_inversesqrt(in HNum3 a);
HNum3 a_atan(in HNum3 a);
HNum3 a_sqrt(in HNum3 a);
HNum3 a_sinh(in HNum3 a);
HNum3 a_ceil(in HNum3 a);
HNum3 a_tan(in HNum3 a);
HNum3 a_asinh(in HNum3 a);
HNum3 a_asin(in HNum3 a);
HNum3 a_acosh(in HNum3 a);
HNum3 a_abs(in HNum3 a);
HNum3 a_exp(in HNum3 a);
HNum3 a_cosh(in HNum3 a);
HNum3 a_floor(in HNum3 a);
HNum3 a_log(in HNum3 a);
HNum3 a_atanh(in HNum3 a);
HNum3 a_log2(in HNum3 a);
HNum3 a_acos(in HNum3 a);
HNum3 a_tanh(in HNum3 a);
HNum3 a_cos(in HNum3 a);
HNum3 a_sin(in HNum3 a);
HNum3 a_atan2(in HNum3 y, in HNum3 x);
HNum3 a_atan2(in HNum3 y, in float x);
HNum3 a_atan2(in float y, in HNum3 x);
HNum3 a_mix(in HNum3 a, in HNum3 b, in HNum3 t);
HNum3 a_mix(in HNum3 a, in HNum3 b, in float t);
HNum3 a_mix(in HNum3 a, in float b, in HNum3 t);
HNum3 a_mix(in HNum3 a, in float b, in float t);
HNum3 a_mix(in float a, in HNum3 b, in HNum3 t);
HNum3 a_mix(in float a, in HNum3 b, in float t);
HNum3 a_mix(in float a, in float b, in HNum3 t);
//--------------------------------
// Macros
//--------------------------------
#define HESSIAN3(f,x, y, z,result) { result = f(varH3x(x), varH3y(y), varH3z(z)); }
//--------------------------------
// Utilities prototypes
//--------------------------------
mat3 a_outerProduct(in vec3 a, in vec3 b);
//--------------------------------
// Implementation
//--------------------------------
HNum3 constH3(in float val)
{
return HNum3(val, vec3(0.0), mat3(0.0));
}
//--------------------------------
HNum3 varH3(in float val, in int index)
{
vec3 g = vec3(0.0);
g[index] = 1.0;
return HNum3(val, g, mat3(0.0));
}
//--------------------------------
HNum3 varH3x(in float val)
{
vec3 g = vec3(0.0);
g[0] = 1.0;
return HNum3(val, g, mat3(0.0));
}
//--------------------------------
HNum3 varH3y(in float val)
{
vec3 g = vec3(0.0);
g[1] = 1.0;
return HNum3(val, g, mat3(0.0));
}
//--------------------------------
HNum3 varH3z(in float val)
{
vec3 g = vec3(0.0);
g[2] = 1.0;
return HNum3(val, g, mat3(0.0));
}
//--------------------------------
HNum3 add(in HNum3 a, in HNum3 b)
{
return HNum3(a.val + b.val , a.g + b.g, a.h + b.h);
}
//--------------------------------
HNum3 add(in HNum3 a, in float b)
{
return HNum3(a.val + b , a.g, a.h);
}
//--------------------------------
HNum3 add(in float a, in HNum3 b)
{
return HNum3(a + b.val , b.g, b.h);
}
//--------------------------------
HNum3 sub(in HNum3 a, in HNum3 b)
{
return HNum3(a.val - b.val , a.g - b.g, a.h - b.h);
}
//--------------------------------
HNum3 sub(in HNum3 a, in float b)
{
return HNum3(a.val - b , a.g, a.h);
}
//--------------------------------
HNum3 sub(in float a, in HNum3 b)
{
return HNum3(a - b.val , - b.g, - b.h);
}
//--------------------------------
HNum3 mult(in HNum3 a, in HNum3 b)
{
return HNum3(a.val * b.val,
a.val*b.g + b.val*a.g,
a.val*b.h + b.val*a.h + a_outerProduct(b.g,a.g) + a_outerProduct(a.g,b.g)
);
}
//--------------------------------
HNum3 mult(in HNum3 a, in float b)
{
return HNum3(a.val * b, b*a.g, b*a.h);
}
//--------------------------------
HNum3 mult(in float a, in HNum3 b)
{
return HNum3(a * b.val, a*b.g, a*b.h);
}
//--------------------------------
HNum3 neg(in HNum3 a)
{
return mult(-1.0,a);
}
//--------------------------------
HNum3 div(in HNum3 a, in HNum3 b)
{
float b1 = b.val;
float b2 = b1*b1;
float b3 = b2*b1;
return HNum3(a.val / b.val ,
(b.val*a.g - a.val*b.g)/b2,
2.0*a.val/b3*a_outerProduct(b.g,b.g)
- a.val/b2*b.h
+ a.h/b1
- a_outerProduct(b.g/b2, a.g)
- a_outerProduct(a.g/b2, b.g)
);
}
//--------------------------------
HNum3 div(in HNum3 a, in float b)
{
return HNum3(a.val / b, a.g/b, a.h/b);
}
//--------------------------------
HNum3 div(in float a, in HNum3 b)
{
float b1 = b.val;
float b2 = b1*b1;
float b3 = b2*b1;
return HNum3(a / b.val,
-a*b.g/b2,
2.0*a/b3*a_outerProduct(b.g,b.g) - a/b2*b.h
);
}
//--------------------------------
HNum3 inv(in HNum3 a)
{
return div(1.0, a);
}
//--------------------------------
HNum3 a_pow(in HNum3 a, in HNum3 b)
{
return a_exp(mult(b,a_log(a)));
}
//--------------------------------
HNum3 a_pow(in HNum3 a, in float b)
{
// constant exponent -> make special case
float v = pow(a.val, b); // value f(a(x))
float da = b*pow(a.val,b-1.0); // first derivative f'(a(x))
float dda = b*(b-1.0)*pow(a.val,b-2.0); // second derivative f''(a(x))
return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g));
}
//--------------------------------
HNum3 a_pow(in float a, in HNum3 b)
{
return a_exp(mult(b,log(a)));
}
//--------------------------------
HNum3 a_min(in HNum3 a, in HNum3 b)
{
if(a.val < b.val)
{
return a;
}
return b;
}
//--------------------------------
HNum3 a_max(in HNum3 a, in HNum3 b)
{
if(a.val > b.val)
{
return a;
}
return b;
}
//--------------------------------
HNum3 a_exp2(in HNum3 a)
{
float v = exp2(a.val); // value f(a(x))
float da = log(2.0)*exp2(a.val); // first derivative f'(a(x))
float dda = log(2.0)*log(2.0)*exp2(a.val); // second derivative f''(a(x))
return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g));
}
//--------------------------------
HNum3 a_inversesqrt(in HNum3 a)
{
float v = inversesqrt(a.val); // value f(a(x))
float da = -0.5/pow(sqrt(a.val),3.0); // first derivative f'(a(x))
float dda = 0.75/pow(sqrt(a.val),5.0); // second derivative f''(a(x))
return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g));
}
//--------------------------------
HNum3 a_atan(in HNum3 a)
{
float v = atan(a.val); // value f(a(x))
float da = 1.0/(1.0 + a.val * a.val); // first derivative f'(a(x))
float dda = -2.0*a.val/pow(1.0 + a.val * a.val, 2.0); // second derivative f''(a(x))
return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g));
}
//--------------------------------
HNum3 a_sqrt(in HNum3 a)
{
float v = sqrt(a.val); // value f(a(x))
float da = 0.5/sqrt(a.val); // first derivative f'(a(x))
float dda = -0.25/pow(sqrt(a.val),3.0); // second derivative f''(a(x))
return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g));
}
//--------------------------------
HNum3 a_sinh(in HNum3 a)
{
float v = sinh(a.val); // value f(a(x))
float da = cosh(a.val); // first derivative f'(a(x))
float dda = sinh(a.val); // second derivative f''(a(x))
return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g));
}
//--------------------------------
HNum3 a_ceil(in HNum3 a)
{
float v = ceil(a.val); // value f(a(x))
float da = 0.0; // first derivative f'(a(x))
float dda = 0.0; // second derivative f''(a(x))
return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g));
}
//--------------------------------
HNum3 a_tan(in HNum3 a)
{
float v = tan(a.val); // value f(a(x))
float da = 1.0 + pow(tan(a.val),2.0); // first derivative f'(a(x))
float dda = 2.0*tan(a.val)*(1.0 + pow(tan(a.val),2.0)); // second derivative f''(a(x))
return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g));
}
//--------------------------------
HNum3 a_asinh(in HNum3 a)
{
float v = asinh(a.val); // value f(a(x))
float da = 1.0/sqrt(1.0 + a.val * a.val); // first derivative f'(a(x))
float dda = -a.val/pow(sqrt(1.0 + a.val * a.val),3.0); // second derivative f''(a(x))
return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g));
}
//--------------------------------
HNum3 a_asin(in HNum3 a)
{
float v = asin(a.val); // value f(a(x))
float da = 1.0/sqrt(1.0 - a.val * a.val); // first derivative f'(a(x))
float dda = a.val/pow(sqrt(1.0 - a.val * a.val),3.0); // second derivative f''(a(x))
return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g));
}
//--------------------------------
HNum3 a_acosh(in HNum3 a)
{
float v = acosh(a.val); // value f(a(x))
float da = 1.0/sqrt(-1.0 + a.val * a.val); // first derivative f'(a(x))
float dda = -a.val/pow(sqrt(-1.0 + a.val * a.val),3.0); // second derivative f''(a(x))
return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g));
}
//--------------------------------
HNum3 a_abs(in HNum3 a)
{
float v = abs(a.val); // value f(a(x))
float da = a.val < 0.0 ? -1.0 : 1.0; // first derivative f'(a(x))
float dda = 0.0; // second derivative f''(a(x))
return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g));
}
//--------------------------------
HNum3 a_exp(in HNum3 a)
{
float v = exp(a.val); // value f(a(x))
float da = exp(a.val); // first derivative f'(a(x))
float dda = exp(a.val); // second derivative f''(a(x))
return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g));
}
//--------------------------------
HNum3 a_cosh(in HNum3 a)
{
float v = cosh(a.val); // value f(a(x))
float da = sinh(a.val); // first derivative f'(a(x))
float dda = cosh(a.val); // second derivative f''(a(x))
return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g));
}
//--------------------------------
HNum3 a_floor(in HNum3 a)
{
float v = floor(a.val); // value f(a(x))
float da = 0.0; // first derivative f'(a(x))
float dda = 0.0; // second derivative f''(a(x))
return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g));
}
//--------------------------------
HNum3 a_log(in HNum3 a)
{
float v = log(a.val); // value f(a(x))
float da = 1.0/a.val; // first derivative f'(a(x))
float dda = -1.0/(a.val * a.val); // second derivative f''(a(x))
return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g));
}
//--------------------------------
HNum3 a_atanh(in HNum3 a)
{
float v = atanh(a.val); // value f(a(x))
float da = 1.0/(1.0 - a.val * a.val); // first derivative f'(a(x))
float dda = 2.0*a.val/pow(1.0 - a.val * a.val,2.0); // second derivative f''(a(x))
return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g));
}
//--------------------------------
HNum3 a_log2(in HNum3 a)
{
float v = log2(a.val); // value f(a(x))
float da = 1.0/(a.val * log(2.0)); // first derivative f'(a(x))
float dda = -1.0/(a.val * a.val * log(2.0)); // second derivative f''(a(x))
return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g));
}
//--------------------------------
HNum3 a_acos(in HNum3 a)
{
float v = acos(a.val); // value f(a(x))
float da = -1.0/sqrt(1.0 - a.val * a.val); // first derivative f'(a(x))
float dda = -a.val/pow(sqrt(1.0 - a.val * a.val),3.0); // second derivative f''(a(x))
return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g));
}
//--------------------------------
HNum3 a_tanh(in HNum3 a)
{
float v = tanh(a.val); // value f(a(x))
float da = 1.0 - pow(tanh(a.val),2.0); // first derivative f'(a(x))
float dda = -2.0*tanh(a.val)*(1.0 - pow(tanh(a.val),2.0)); // second derivative f''(a(x))
return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g));
}
//--------------------------------
HNum3 a_cos(in HNum3 a)
{
float v = cos(a.val); // value f(a(x))
float da = -sin(a.val); // first derivative f'(a(x))
float dda = -cos(a.val); // second derivative f''(a(x))
return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g));
}
//--------------------------------
HNum3 a_sin(in HNum3 a)
{
float v = sin(a.val); // value f(a(x))
float da = cos(a.val); // first derivative f'(a(x))
float dda = -sin(a.val); // second derivative f''(a(x))
return HNum3(v , da * a.g, da * a.h + dda * a_outerProduct(a.g,a.g));
}
//--------------------------------
HNum3 a_atan2(in HNum3 y, in HNum3 x)
{
const float pi = 3.14159265;
// from https://en.wikipedia.org/wiki/Atan2
if(x.val > 0.0)
{
HNum3 n = a_sqrt(add(mult(x,x),mult(y,y)));
HNum3 inner = div(y, add(n,x));
return mult(2.0,a_atan(inner));
}else if(x.val <= 0.0 && abs(y.val) > 1E-6)
{
HNum3 n = a_sqrt(add(mult(x,x),mult(y,y)));
HNum3 inner = div(sub(n,x),y);
return mult(2.0,a_atan(inner));
}else if(x.val < 0.0 && abs(y.val) <= 1E-6)
{
return constH3(pi);
}
// return 0 for undefined
return constH3(0.0);
}
//--------------------------------
HNum3 a_atan2(in HNum3 y, in float x)
{
return a_atan2(y,constH3(x));
}
//--------------------------------
HNum3 a_atan2(in float y, in HNum3 x)
{
return a_atan2(constH3(y),x);
}
//--------------------------------
HNum3 a_mix(in HNum3 a, in HNum3 b, in HNum3 t)
{
return add(mult(a, sub(1.0, t)), mult(b, t));
}
//--------------------------------
HNum3 a_mix(in HNum3 a, in HNum3 b, in float t)
{
return add(mult(a, 1.0 - t), mult(b, t));
}
//--------------------------------
HNum3 a_mix(in HNum3 a, in float b, in HNum3 t)
{
return add(mult(a, sub(1.0, t)), mult(b, t));
}
//--------------------------------
HNum3 a_mix(in HNum3 a, in float b, in float t)
{
return add(mult(a, 1.0 - t), b*t);
}
//--------------------------------
HNum3 a_mix(in float a, in HNum3 b, in HNum3 t)
{
return add(mult(a, sub(1.0, t)), mult(b, t));
}
//--------------------------------
HNum3 a_mix(in float a, in HNum3 b, in float t)
{
return add(a * (1.0 - t), mult(b, t));
}
//--------------------------------
HNum3 a_mix(in float a, in float b, in HNum3 t)
{
return add(mult(a, sub(1.0, t)), mult(b, t));
}
//--------------------------------
// Implementation prototypes
//--------------------------------
mat3 a_outerProduct(in vec3 a, in vec3 b)
{
return mat3(a * b[0], a * b[1], a * b[2]);
}
#endif // HESSNUM_3_H_
//********************************************************************
//
// End automatic differentiation header
//
//********************************************************************
//********************************************************************
//
// Metric functions
//
//********************************************************************
#define PI 3.14159265359
// float pSphere(vec3 p, float s) {return length(p)-s;}
HNum3 fSphere(in HNum3 x, in HNum3 y, in HNum3 z,
float globalTime) {
return sub(a_sqrt(add(add(mult(x,x), mult(y,y)), mult(z,z))), 5.0) ;
}
// Predefined functions!
// Just comment in the one you want to see! (comment out the other ones)
// If none is defined, the default identity operation is used (f(x,y,z) = 0).
// You can comment out all predefined ones and implement your own in fCustom
// #define EXPONENTIAL
// #define SADDLE//
// #define WAVES
// #define PARABOLA
// #define IDENTITY
HNum3 fExponential(in HNum3 x, in HNum3 y, in HNum3 z,
float globalTime);
HNum3 fSaddle(in HNum3 x, in HNum3 y, in HNum3 z, float globalTime);
HNum3 fWaves(in HNum3 x, in HNum3 y, in HNum3 z, float globalTime);
HNum3 fParabola(in HNum3 x, in HNum3 y, in HNum3 z,
float globalTime);
HNum3 fIdentity(in HNum3 x, in HNum3 y, in HNum3 z,
float globalTime);
// Implement your custom height function here and comment out all the defines
// above! You can use all the mathematical operations defined in the automatic
// differentiation header above
HNum3 fCustom(in HNum3 x, in HNum3 y, in HNum3 z,
float globalTime) {
return div(fExponential(x, y, z, globalTime), 1.0);
// return a_max(fExponential(x, y, z, globalTime), fSphere(x, y, z, globalTime));
}
// Height function used for the metric. More information in compute_update
HNum3 f(in HNum3 x, in HNum3 y, in HNum3 z, float globalTime) {
#if defined EXPONENTIAL
return fExponential(x, y, z, globalTime);
#elif defined SADDLE
return fSaddle(x, y, z, globalTime);
#elif defined WAVES
return fWaves(x, y, z, globalTime);
#elif defined PARABOLA
return fParabola(x, y, z, globalTime);
#elif defined IDENTITY
return fIdentity(x, y, z, globalTime);
#else
return fCustom(x, y, z, globalTime);
#endif
}
HNum3 hessF(vec3 p, float globalTime) {
// compute hessian with addition time parameter
vec3 uGrad = vec3(1., 0., 0.);
HNum3 uHessian = HNum3(p.x, uGrad, mat3(0.));
vec3 vGrad = vec3(0., 1., 0.);
HNum3 vHessian = HNum3(p.y, vGrad, mat3(0.));
vec3 wGrad = vec3(0., 0., 1.);
HNum3 wHessian = HNum3(p.z, wGrad, mat3(0.));
return f(uHessian, vHessian, wHessian, globalTime);
}
vec3 compute_update(vec3 p, vec3 v, float globalTime) {
// explicit form of the christoffel symbols for the metric given by graph of
// the function f(x_1,x_1,x_3) df/dx_i = f_i d^2f/(dx_j dx_j) = f_{i,j}
// gamma_{i,j}^k = f_k*f_{i,j}/(1 + |grad(f)|^2)
// This is the update given by the differential geodesic equation used for
// numerical integration in local coordinates (x_i) for a curve c_i(t) = x_i
// d^2 c_k/dt^2 = gamma_{i,j}^k * d c_i/dt * d c_j/dt
// The local position's velocity is given by the ray's current direction
// compute first and second order derivatives
HNum3 r = hessF(p, globalTime);
vec3 vp = vec3(0.0);
for (int k = 0; k < 3; k++) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
vp[k] += r.g[k] * r.h[j][i] * v[i] * v[j];
}
}
}
return -vp / (1.0 + dot(r.g, r.g));
}
//********************************************************************
//
// Data
//
//********************************************************************
const float deg2Rad = PI / 180.0;
const vec2 D_lastMouse = vec2(0., 0.);
vec4 D_thetaPhi;
const vec3 D_pos = vec3(0.0);
//********************************************************************
//
// Camera functions
//
//********************************************************************
// This assumes the pixel position px to be in [0,1],
// which can be done by (x+0.5)/w or (y+0.5)/h (or h-y +0.5 for screens
// with top left origin) to sample pixel centers
vec3 createRay(vec2 px, mat4 PInv, mat4 VInv);
mat4 translate(vec3 t);
mat4 translateInv(vec3 t);
mat4 scale(vec3 s);
mat4 scaleInv(vec3 s);
mat4 rightToLeft();
mat4 rightToLeftInv();
mat4 ortho(float l, float r, float b, float t, float n, float f);
mat4 orthoInv(float l, float r, float b, float t, float n, float f);
mat4 projection(float n, float f);
mat4 projectionInv(float n, float f);
mat4 perspective(float fov, float aspect, float n, float f);
mat4 perspectiveInv(float fov, float aspect, float n, float f);
mat4 lookAt(vec3 eye, vec3 center, vec3 up);
mat4 lookAtInv(vec3 eye, vec3 center, vec3 up);
//********************************************************************
//
// Implementation
//
//********************************************************************
HNum3 fExponential(in HNum3 x, in HNum3 y, in HNum3 z,
float globalTime) {
HNum3 rx = sub(x, 0.0);
HNum3 ry = sub(y, 1.0);
HNum3 rz = sub(z, 2.0);
HNum3 x2 = mult(rx, rx);
HNum3 y2 = mult(ry, ry);
HNum3 z2 = mult(rz, rz);
HNum3 sum = neg(add(x2, add(y2, z2)));
HNum3 f1 = a_exp(mult(sum, 1.0 / (abs(sin(globalTime / 5.0)) + 0.1)));
rx = sub(x, -6.0);
ry = sub(y, -0.25);
rz = sub(z, 3.5);
x2 = mult(rx, rx);
y2 = mult(ry, ry);
z2 = mult(rz, rz);
sum = neg(add(x2, add(y2, z2)));
sum = mult(sum, 0.1);
HNum3 f2 = mult(a_exp(sum), abs(sin(globalTime / 5.0)) * 5.0);
return add(f1, f2);
}
HNum3 fSaddle(in HNum3 x, in HNum3 y, in HNum3 z,
float globalTime) {
return mult(0.25 * pow(sin(globalTime / 2.0), 2.0),
sub(add(mult(x, x), mult(z, z)), mult(y, y)));
}
HNum3 fWaves(in HNum3 x, in HNum3 y, in HNum3 z, float globalTime) {
float frequency = 2.0 * PI / (10.0 + 3.0 * sin(0.1 * globalTime));
return a_cos(add(mult(x, frequency), mult(z, frequency)));
}
HNum3 fParabola(in HNum3 x, in HNum3 y, in HNum3 z,
float globalTime) {
HNum3 rel = sub(x, 0.0);
HNum3 sum = mult(rel, rel);
rel = sub(y, 0.0);
sum = add(sum, mult(rel, rel));
rel = sub(z, -10.0);
sum = add(sum, mult(rel, rel));
return mult(sum, 0.1);
}
HNum3 fIdentity(in HNum3 x, in HNum3 y, in HNum3 z,
float globalTime) {
return constH3(0.0);
}
//********************************************************************
vec3 createRay(vec2 px, mat4 PInv, mat4 VInv) {
// convert pixel to NDS
// [0,1] -> [-1,1]
vec2 pxNDS = px * 2. - 1.;
// choose an arbitrary point in the viewing volume
// z = -1 equals a point on the near plane, i.e. the screen
vec3 pointNDS = vec3(pxNDS, -1.);
// as this is in homogenous space, add the last homogenous coordinate
vec4 pointNDSH = vec4(pointNDS, 1.0);
// transform by inverse projection to get the point in view space
vec4 dirEye = PInv * pointNDSH;
// since the camera is at the origin in view space by definition,
// the current point is already the correct direction (dir(0,P) = P - 0 = P
// as a direction, an infinite point, the homogenous component becomes 0
// the scaling done by the w-division is not of interest, as the direction
// in xyz will stay the same and we can just normalize it later
dirEye.w = 0.;
// compute world ray direction by multiplying the inverse view matrix
vec3 dirWorld = (VInv * dirEye).xyz;
// now normalize direction
return normalize(dirWorld);
}
// matrix operations
mat4 translate(vec3 t) {
return mat4(vec4(1., 0., 0., 0.), vec4(0., 1., 0., 0.), vec4(0., 0., 1., 0.),
vec4(t, 1.));
}
mat4 translateInv(vec3 t) { return translate(-t); }
mat4 scale(vec3 s) {
return mat4(vec4(s.x, 0., 0., 0.), vec4(0., s.y, 0., 0.),
vec4(0., 0., s.z, 0.), vec4(0., 0., 0., 1.));
}
mat4 scaleInv(vec3 s) { return scale(1. / s); }
mat4 rightToLeft() {
// 1 0 0 0
// 0 1 0 0
// 0 0 -1 0
// 0 0 0 1
return scale(vec3(1., 1., -1.));
}
mat4 rightToLeftInv() {
// same matrix
return rightToLeft();
}
mat4 ortho(float l, float r, float b, float t, float n, float f) {
// translation and scale
return scale(vec3(2. / (r - l), 2. / (t - b), 2. / (f - n))) *
translate(vec3(-(l + r) / 2., -(t + b) / 2., -(f + n) / 2.));
}
mat4 orthoInv(float l, float r, float b, float t, float n, float f) {
return translateInv(vec3(-(l + r) / 2., -(t + b) / 2., -(f + n) / 2.)) *
scaleInv(vec3(2. / (r - l), 2. / (t - b), 2. / (f - n)));
}
mat4 projection(float n, float f) {
// n 0 0 0 0
// 0 n 0 0 0
// 0 0 n+f -fn
// 0 0 1 0
return mat4(vec4(n, 0., 0., 0.), vec4(0., n, 0., 0.), vec4(0., 0., n + f, 1.),
vec4(0., 0., -f * n, 0.));
}
mat4 projectionInv(float n, float f) {
// 1/n 0 0 0
// 0 1/n 0 0
// 0 0 0 1
// 0 0 -1/fn (f+n)/fn
return mat4(vec4(1. / n, 0., 0., 0.), vec4(0., 1. / n, 0., 0.),
vec4(0., 0., 0., -1. / (f * n)),
vec4(0., 0., 1., (f + n) / (f * n)));
}
mat4 perspective(float fov, float aspect, float n, float f) {
float l = tan(fov / 2.) * n;
float b = l / aspect;
return ortho(-l, l, -b, b, n, f) * projection(n, f) * rightToLeft();
}
mat4 perspectiveInv(float fov, float aspect, float n, float f) {
float l = tan(fov / 2.) * n;
float b = l / aspect;
return rightToLeftInv() * projectionInv(n, f) * orthoInv(-l, l, -b, b, n, f);
}
mat4 lookAt(vec3 eye, vec3 center, vec3 up) {
vec3 z = normalize(eye - center);
vec3 x = normalize(cross(up, z));
vec3 y = cross(z, x);
mat4 v = mat4(vec4(x.x, y.x, z.x, 0.), vec4(x.y, y.y, z.y, 0.),
vec4(x.z, y.z, z.z, 0.), vec4(0., 0., 0., 1.));
return v * translate(-eye);
}
mat4 lookAtInv(vec3 eye, vec3 center, vec3 up) {
vec3 z = normalize(eye - center);
vec3 x = normalize(cross(up, z));
vec3 y = cross(z, x);
return translateInv(-eye) *
mat4(vec4(x, 0.), vec4(y, 0.), vec4(z, 0.), vec4(0., 0., 0., 1.));
}
//********************************************************************
//
// INSTRUCTIONS:
//
// This shader implements basic distancefield raytracing of a regular grid on
// a 3D manifold given as the graph of a function f(x,y,z).
//
// Click and drag the mouse to look around. WASD for movement. You are moving
// through distorted space, so you might not move in a straight line, but
// instead move along the shortest paths in curved space.
// Press "R" to reset the view.
//
// WARNING: The space-bending and movement might be a bit nauseating. I tried to
// not make stuff move too fast, but wanted to give a short warning anyways.
// DISPLAY OPTIONS:
// Below you can find a few defines to control the look of the grid, background
// and general tracing
//
// FUNCTIONAL OPTIONS
// The actual function is defined in the common shader part under "Metric
// functions". A few functions are predefined, but you can implement your own
// in "HessNum3 fCustom(in HessNum3 x, in HessNum3 y, in HessNum3 z, float
// globalTime)". Just comment in the one you want to see or comment all of them
// out to use the custom function. Additional information can be found there as
// well.
//
// Note: As calculating the metric from the function requires 1st and 2nd order
// derivatives and it would be cumbersome to calculate and implement them for
// each function, I use automatic differentiation, which is why you need to use
// the special types and operations defined in the automatic differentiation
// header below to implement your own f.
//
//
//********************************************************************
// Maximum number of trace steps
// Higher step number will let you look farther, especially with higher
// deformations
#define MAX_STEPS 100
// The maximum length traversed per step. Lower values produce higher quality
// paths through the curved space
#define STEP_LENGTH 0.2
// Grid parameters
#define GRID_SIZE 1.0
#define GRID_THICKNESS 0.0001
// Linear fog parameters
#define FOG_MAX_DIST 50.0
#define FOG_MIN_DIST 10.0
#define FOG_COLOR vec3(0.1)
// Surface epsilon
#define EPS 0.005
//********************************************************************
//
// Distance helpers and tracing
//
//********************************************************************
#define INF 3.402823466e+38
float sdf(in vec3 p);
vec3 g_eye;
// Tracing function
bool trace(inout vec3 p, in vec3 dir, out float t, out int steps) {
steps = 0;
t = 0.0;
for (int n = 0; n < MAX_STEPS && t < FOG_MAX_DIST; n++) {
float d = sdf(p);
if (d < EPS) {
if(length(p - g_eye) > 10.0 * GRID_SIZE) return false;
return true;
}
// make step length dependent on distance field to not miss geometry, but
// also use EPS as a min step
float s = max(EPS, min(d, STEP_LENGTH));
// "acceleration" of a particle traveling along the geodesic
vec3 vp = compute_update(p, dir, iTime);
// euler integration
dir += vp * s;
// position euler step
p += dir * s;
// maybe not fully correct, but try to preserve arc length by normalizing
// dir
dir = normalize(dir);
// length traveled, used for fog
t += s;
steps++;
}
return false;
}
float sdfBox2d(vec2 p, vec2 b);
float sdfGrid(vec3 p, vec3 cellSize, vec3 gridHalfLength);
vec3 normal(in vec3 p);
//********************************************************************
//
// Image formation
//
//********************************************************************
vec3 shade(in vec3 P, in vec3 N, in vec3 color, in vec3 LPos);
float simpleColor(float coord, float gridSize, float repetition);
// vec4 loadValue(in ivec2 re) { return texelFetch(iChannel0, re, 0); }
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord.xy / iResolution.xy;
float aspect = iResolution.x / iResolution.y;
D_thetaPhi = vec4(90.0 * deg2Rad - clamp(2.0 * PI * iTime, 0., 2.0*PI) / 20., 0.0, 0.0, 0.0);
vec3 rayDir;
vec3 p;
// {
vec2 thetaPhi = D_thetaPhi.xy; // loadValue(D_thetaPhi).xy;
float theta = thetaPhi.x;
float phi = thetaPhi.y;
vec3 eye = D_pos.xyz; // loadValue(D_pos).xyz;
// vec3 eye = vec3(0.0);
vec3 center =
eye + vec3(sin(theta) * sin(phi), cos(theta), sin(theta) * cos(phi));
g_eye = eye;
// inverse projection and view matrices
mat4 PInv = perspectiveInv(radians(90.), aspect, 0.1, 100.);
mat4 VInv = lookAtInv(eye, center, vec3(0., 1., 0.));
rayDir = createRay(uv, PInv, VInv);
p = eye;
// }
float t = 0.0;
int steps = 100;
vec3 col = vec3(0.0);
if (trace(p, rayDir, t, steps)) {
vec3 N = normal(p);
col =
vec3(simpleColor(p.x, GRID_SIZE, 3.0), simpleColor(p.y, GRID_SIZE, 7.0),
simpleColor(p.z, GRID_SIZE, 11.0));
vec3 LPos = vec3(1.0, 2.0, 0.0);
col = shade(p, N, col, LPos);
} else {
t = INF;
}
// simple linear fog
float fogFactor = (FOG_MAX_DIST - t) / (FOG_MAX_DIST - FOG_MIN_DIST);
fogFactor = clamp(fogFactor, 0.0, 1.0);
col = mix(FOG_COLOR, col, fogFactor);
fragColor = vec4(col, t == INF ? 0.0 : 1.0);
}
//***************
float sdfBox2d(vec2 p, vec2 b) {
vec2 d = abs(p) - b;
return min(max(d.x, d.y), 0.0) + length(max(d, 0.0));
}
float sdfGrid(vec3 p, vec3 cellSize, vec3 gridHalfLength) {
vec3 pg = floor(p / cellSize) * cellSize;
vec3 center = pg + cellSize * 0.5;
float d = INF;
d = min(d, sdfBox2d(p.xz - center.xz, gridHalfLength.xz));
d = min(d, sdfBox2d(p.xy - center.xy, gridHalfLength.xy));
d = min(d, sdfBox2d(p.yz - center.yz, gridHalfLength.yz));
return d;
}
float pSphere(vec3 p, float s) {return length(p)-s;}
float sdf(in vec3 p) {
float d = sdfGrid(p, vec3(GRID_SIZE), vec3(GRID_THICKNESS));
// d = max(d, pSphere(p - g_center, 5.0 * GRID_SIZE));
return d;
}
vec3 normal(in vec3 p) {
return normalize(
vec3(sdf(p + vec3(EPS, 0., 0.)) - sdf(p - vec3(EPS, 0., 0.)),
sdf(p + vec3(0., EPS, 0.)) - sdf(p - vec3(0., EPS, 0.)),
sdf(p + vec3(0., 0., EPS)) - sdf(p - vec3(0., 0., EPS))));
}
//********************************************************************
//
// Shading and main
//
//********************************************************************
vec3 shade(in vec3 P, in vec3 N, in vec3 color, in vec3 LPos) {
vec3 L = normalize(LPos - P);
// simple two sided diffuse shading
return vec3(0.1, 0.8, 0.1) * clamp(abs(dot(L, N)), 0.0, 1.0);
}
float simpleColor(float coord, float gridSize, float repetition) {
float cr = (gridSize * 0.5 - coord) / gridSize;
float v = pow(sin(PI * cr / 2.0), 2.0);
return v;
}
ray-marching [ag-000N]
ray-marching [ag-000N]
Definition. ray [ag-001A]
Definition. ray [ag-001A]
A ray is a half-line that starts at a point and extends indefinitely in one direction.
In the context of ray marching etc., a ray could be a view ray, i.e. a ray that starts at the camera, extending through the screen, possibly intersecting with objects in the scene, or a secondary ray, i.e. a ray generated from the intersection of other rays, e.g. shadow rays, reflection rays, or refraction rays.
Definition. ray equation [gillespie2024ray, sec. 1.1 eq. 3] [ag-000V]
Definition. ray equation [gillespie2024ray, sec. 1.1 eq. 3] [ag-000V]
A ray anchored at origin \(\boldsymbol {r}_o\) in the direction of the unit vector \(\boldsymbol {r}_d\) can be parametrically defined as a ray equation \[ \boldsymbol {r}(t)=\boldsymbol {r}_o+t \boldsymbol {r}_d \]
Definition. ray intersection [gillespie2024ray, sec. 1.1 eq. 4] [ag-000W]
Definition. ray intersection [gillespie2024ray, sec. 1.1 eq. 4] [ag-000W]
Plugging the ray equation \(r: \mathbb {R} \rightarrow \mathbb {R}^n\) into the function \(f: \mathbb {R}^n \rightarrow \mathbb {R}\) that defines the implicit surface produces the composite real function \(F: \mathbb {R} \rightarrow \mathbb {R}\) where \(F=f \circ \boldsymbol {r}\) such that the solutions to \[ F(t)=0 \] correspond to ray intersections with the implicit surface. Theses solutions are also called the roots of the function \(F\).
Remark. ray-casting/ray-tracing/ray-marching [ag-001E]
Remark. ray-casting/ray-tracing/ray-marching [ag-001E]
The ray-casting/ray-tracing/ray-marching algorithms simply apply one of the multitude of root finding methods to solve the ray intersection equation.
In general, ray-tracing typically uses a bunch of geometry (e.g. closed-form formulas) to calculate the intersection point, while ray-marching marches along the ray, and uses numerical methods to find the intersection point.
The term ray-casting was introduced concurrently with ray-tracing in the 1980s, nowadays it could be used to mean the general ray intersection process, or specifically the ray-marching process with fixed step size.
Definition. ray marching [ag-001C]
Definition. ray marching [ag-001C]
To render a scene, the Ray marching algorithm marches a ray from an origin towards a direction. At each step, the algorithm marches a short (possibly changing) distance and checks if a ray intersection occurs. This process continues until a stopping condition is met. The information obtained from the ray intersection is then used to determine the color of a pixel on the screen.
Example. ray-marching for different types of rays [ag-001D]
Example. ray-marching for different types of rays [ag-001D]
A view ray has the origin at the camera, the direction is determined by the pixel on the screen that it passes through. It may intersect with a surface in the scene, and the information obtained from the intersection is used to determine the color of the corresponding pixel on the screen.
A secondary ray typically originates from a point on a surface and its direction is determined by the type of ray. For instance, a shadow ray is cast towards a light source to determine if the point is in shadow, while a reflection ray and a refraction ray follow directions based on optics. The information obtained from secondary rays helps determine the color of the corresponding pixel that the view ray passes through.
Figure. Ray marching [ag-001F]
Figure. Ray marching [ag-001F]
Definition. ray marching (naïve) [ag-001B]
Definition. ray marching (naïve) [ag-001B]
The ray marching (naïve) algorithm is to march a ray by a fixed step size, check if a ray intersection occurs at each step, until the ray reaches a maximum distance or step count.
Formally, the root found by ray marching (naïve) is the limit point of the sequence defined by the recurrence equation \[t_{i+1} = t_i + \Delta t\] where \(t_0 = 0\) and \(\Delta t\) is the fixed step size.
At each step, the ray marches to \(\boldsymbol {r}(t_i)\), which is usually denoted \(\boldsymbol {r}_i\).
Figure. Ray marching (naïve) [ag-000O]
Figure. Ray marching (naïve) [ag-000O]
Algorithm. ray marching (naïve) [ag-0018]
Algorithm. ray marching (naïve) [ag-0018]
Example. ray marching (naïve) [ag-0019]
Example. ray marching (naïve) [ag-0019]
The following renders a scene with a unit sphere at the origin, the camera at \((0,0,8)\) and looking at the origin, through a screen of height 1.0, centered at 5.0 from the camera.
The color of pixels are adjusted so that they are brighter the closer they are to the camera, as if there is a light source at the camera. As it takes a fixed step size of 0.1 (not small enough), the sphere is not rendered smoothly, and clearly shows the stepping artifacts.
/* The SDF for a sphere with radius r */
float sdSphere(vec3 p, float r)
{
return length(p) - r;
}
/* The SDF for a scene with a unit sphere at the origin */
float sdScene(in vec3 pos) {
return sdSphere(pos, 1.0);
}
#define EPSILON 0.01
#define T_MAX 10.0
#define DELTA_T 0.1
#define SDF_FUNCTION sdScene
/* Ray marching (naïve) */
float rayMarch(in vec3 ro, in vec3 rd) {
float t = 0.0;
while(t < T_MAX) {
vec3 rt = ro + t * rd;
float ft = SDF_FUNCTION(rt);
if(ft < EPSILON) return t;
t += DELTA_T;
}
return T_MAX;
}
/* The main function to render the scene per pixel */
void mainImage(out vec4 pixelColor, in vec2 pixelCoordinate) {
// set up uv coordinates on the screen
float aspect = iResolution.x/iResolution.y;
vec2 uv = pixelCoordinate/iResolution.xy;
uv -= vec2(0.5, 0.5);
uv *= 2.0 * vec2(aspect, 1.0);
// set up camera and view ray
float observerDistance = 8.0;
vec3 ro = vec3(0.0, 0.0, observerDistance);
vec3 ta = ro - vec3(uv, 5.0);
vec3 rd = normalize(ta - ro);
// ray march
float t = rayMarch(ro, rd);
float hit = t != T_MAX ? 1.0 : 0.0;
// adjust the color to look just bright enough
float baseRatio = 0.65;
// the closer, the brighter
float distRatio = baseRatio + smoothstep(0.0, 1.0 - baseRatio, 1.0 - t / observerDistance);
vec3 col = distRatio * vec3(1.0);
// transparent if not hit
pixelColor = vec4(col, hit);
}
Code
/* The SDF for a sphere with radius r */
float sdSphere(vec3 p, float r)
{
return length(p) - r;
}
/* The SDF for a scene with a unit sphere at the origin */
float sdScene(in vec3 pos) {
return sdSphere(pos, 1.0);
}
#define EPSILON 0.01
#define T_MAX 10.0
#define DELTA_T 0.1
#define SDF_FUNCTION sdScene
/* Ray marching (naïve) */
float rayMarch(in vec3 ro, in vec3 rd) {
float t = 0.0;
while(t < T_MAX) {
vec3 rt = ro + t * rd;
float ft = SDF_FUNCTION(rt);
if(ft < EPSILON) return t;
t += DELTA_T;
}
return T_MAX;
}
/* The main function to render the scene per pixel */
void mainImage(out vec4 pixelColor, in vec2 pixelCoordinate) {
// set up uv coordinates on the screen
float aspect = iResolution.x/iResolution.y;
vec2 uv = pixelCoordinate/iResolution.xy;
uv -= vec2(0.5, 0.5);
uv *= 2.0 * vec2(aspect, 1.0);
// set up camera and view ray
float observerDistance = 8.0;
vec3 ro = vec3(0.0, 0.0, observerDistance);
vec3 ta = ro - vec3(uv, 5.0);
vec3 rd = normalize(ta - ro);
// ray march
float t = rayMarch(ro, rd);
float hit = t != T_MAX ? 1.0 : 0.0;
// adjust the color to look just bright enough
float baseRatio = 0.65;
// the closer, the brighter
float distRatio = baseRatio + smoothstep(0.0, 1.0 - baseRatio, 1.0 - t / observerDistance);
vec3 col = distRatio * vec3(1.0);
// transparent if not hit
pixelColor = vec4(col, hit);
}
sphere tracing [ag-0010]
sphere tracing [ag-0010]
Definition. point-to-set distance [hart1996sphere, def. 1] [ag-000R]
Definition. point-to-set distance [hart1996sphere, def. 1] [ag-000R]
The point-to-set distance defines the distance from a point \(\boldsymbol {x} \in \mathbb {R}^3\) to a set \(A \subset \mathbb {R}^3\) as the distance from \(x\) to the closest point in \(A\), \[ d(\boldsymbol {x}, A)=\min _{y \in A}\lVert \boldsymbol {x}-\boldsymbol {y}\rVert \]
Definition. signed distance bound [hart1996sphere, def. 2] [ag-000S]
Definition. signed distance bound [hart1996sphere, def. 2] [ag-000S]
A function \(f: \mathbb {R}^3 \rightarrow \mathbb {R}\) is a signed distance bound of its implicit surface \(f^{-1}(0)\) if and only if \[ |f(\boldsymbol {x})| \leq d\left (\boldsymbol {x}, f^{-1}(0)\right ) \] If equality holds, then \(f\) is a signed distance function.
Definition. Lipschitz bound [hart1996sphere, def. 3] [ag-000P]
Definition. Lipschitz bound [hart1996sphere, def. 3] [ag-000P]
A function \(f: \mathbb {R}^3 \rightarrow \mathbb {R}\) is Lipschitz over a domain \(D\) if and only if for all \(\boldsymbol {x}, \boldsymbol {y} \in D\), there exists a positive finite constant \(\lambda \), called Lipschitz bound, such that \[ |f(\boldsymbol {x})-f(\boldsymbol {y})| \leq \lambda \lVert \boldsymbol {x}-\boldsymbol {y}\rVert . \] The Lipschitz constant, denoted \(\operatorname {Lip} f\), is the minimum \(\lambda \) satisfying the condition above.
Theorem. [gillespie2024ray, thm. 1] [ag-000T]
Theorem. [gillespie2024ray, thm. 1] [ag-000T]
Let \(f\) be Lipschitz with Lipschitz bound \(\lambda \geq \) Lip \(f\). Then the function \(f / \lambda \) is a signed distance bound of its implicit surface.
Definition. sphere tracing [hart1996sphere, sec. 2.3, eq. 12] [ag-001I]
Definition. sphere tracing [hart1996sphere, sec. 2.3, eq. 12] [ag-001I]
The sphere tracing algorithm is to march a ray by an adaptive safe step size, which is the absolute value of the signed distance bound calculated by \(F/\lambda \) per Theorem [ag-000T], the rest is the same as ray marching (naïve).
Formally, the root found by sphere tracing is the limit point of the sequence defined by the recurrence equation \[t_{i+1} = t_i + \frac {|F(t_i)|}{\lambda } = t_i + \frac {f(\boldsymbol {r}(t_i))}{\lambda } \] where \(F\) is the ray intersection, and \(f\) is the SDF.
Usually \(\lambda = 1\), and \(F(t_i)\) stays positive until the stopping condition \(F(t_i) < \epsilon \) is met, so the above can be simplified to \[t_{i+1} = t_i + F(t_i) = t_i + f(\boldsymbol {r}(t_i)) \]
Figure. Sphere tracing [ag-001H]
Figure. Sphere tracing [ag-001H]
Figure. Raymarching in raymarching (sphere tracing) [ag-001J]
Figure. Raymarching in raymarching (sphere tracing) [ag-001J]
#define MAT_SCREEN 0.
#define MAT_SPHERE1 1.
#define MAT_FLOOR 2.
#define MAT_CORNER 3.
#define MAT_SCREENZ 4.
#define MAT_MARCHSPHERE 5.
#define MAT_MARCHROUTE 6.
#define MAT_MARCHRADIUS 7.
#define MAT_SPHERE2 8.
#define MAT_SPHERE3 9.
#define MAT_RAYDIRECTION 10.
#define MAT_HITPOINT 11.
float uvToP = 0.0;
float colToUv = 1.0;
float screenZ = 2.5;
float sphereAnim = 1.0;
float radiusAnim = 1.0;
float routeAnim = 1.0;
float raySphereAlpha = 0.0;
float cornersAlpha = 0.0;
float cornersAnim = 0.0;
float screenZAlpha = 0.0;
float radiusAlpha = 1.0;
float rayDirectionAnim = 0.0;
float rayDirectionAnim2 = 0.0;
float screenAlpha = 0.0;
float hitSphereID = 0.0;
// =====================Camera========================
vec3 cameraPos, cameraTarget;
//================================
float sum = 0.0;
float tl(float val, float offset, float range)
{
float im = sum + offset;
float ix = im + range;
sum += offset + range;
return clamp((val - im) / (ix - im), 0.0, 1.0);
}
float cio(float t) {
return t < 0.5
? 0.5 * (1.0 - sqrt(1.0 - 4.0 * t * t))
: 0.5 * (sqrt((3.0 - 2.0 * t) * (2.0 * t - 1.0)) + 1.0);
}
float eio(float t) {
return t == 0.0 || t == 1.0
? t
: t < 0.5
? +0.5 * pow(2.0, (20.0 * t) - 10.0)
: -0.5 * pow(2.0, 10.0 - (t * 20.0)) + 1.0;
}
float fio(float t) {
return t == 0.0 || t == 1.0
? t
: t <= 0.5
? -0.5 * pow(2.0, 5.0 - ((t + 0.5) * 10.0)) + 1.0 - 0.5
: +0.5 * pow(2.0, (10.0 * (t - 0.5)) - 5.0) + 0.5;
}
void timeLine(float time)
{
cameraPos = vec3(5., 5., -3.); // mix(vec3(0.0), , eio(t));
cameraTarget = vec3(0.0, 0.0, 5.);
//time += 32.;
float t; // = tl(time, 1.0, 0.5);
// uvToP = mix(0.0, 1.0, eio(t));
// t = tl(time, 1.0, 1.0);
// t = tl(time, 0.5, 1.0);
// raySphereAlpha = mix(0., 1., t);
// cornersAlpha = mix(0., 1., t);
// t = tl(time, 0.5, 1.0);
// cornersAnim = mix(0., 1., t);
t = tl(time, 0.0, 0.5);
// cameraPos = mix(cameraPos, vec3(5., 6., -3.) , t); // eio(t));
///cameraTarget = vec3(0.0, 0.0, 3.0); //mix(cameraTarget, , eio(t));
// t = tl(time, 0.5, 0.5);
// screenZAlpha = mix(0., 1., t);
// t = tl(time, 0.5, .5);
// colToUv = mix(colToUv, 0.0, eio(t));
// t = tl(time, 0.5, 1.0);
// screenZ = mix(screenZ, 5.0, eio(t));
// t = tl(time, 1.0, 1.0);
// screenZ = mix(screenZ, .75, eio(t));
// t = tl(time, 1.0, 1.0);
// screenZ = mix(screenZ, 2.5, eio(t));
// t = tl(time, 0.5, 1.0);
// cornersAlpha = mix(cornersAlpha, 0., t);
// screenZAlpha = mix(screenZAlpha, 0., t);
// colToUv = mix(colToUv, 1.0, eio(t));
// t = tl(time, 0.0, 0.0);
// cornersAnim = mix(cornersAnim, 0., t);
// t = tl(time, 0.5, 1.0);
// cameraPos = mix(cameraPos, vec3(5., 15., 6.0), eio(t));
// cameraTarget = mix(cameraTarget, vec3(0.0, 0.0, 6.), eio(t));
raySphereAlpha = 1.;
for (int i=0; i<20; i++) {
t = tl(time, 0., 0.5);
radiusAnim = mix(radiusAnim, float(i) + 2., t);
t = tl(time, 0., 0.5);
routeAnim = mix(routeAnim, float(i) + 2., t);
t = tl(time, 0., 0.5);
sphereAnim = mix(sphereAnim, float(i) + 2., t);
}
// t = tl(time, 1.0, 1.0);
// cameraPos = mix(cameraPos, vec3(2., 3., -3.), eio(t));
// cameraTarget = mix(cameraTarget, vec3(0.0, 0.0, 3.0), eio(t));
// radiusAlpha = mix(radiusAlpha, 0.0, t);
// routeAnim = mix(routeAnim, 1.0, t);
// sphereAnim = mix(sphereAnim, 1.0, t);
// colToUv = mix(colToUv, 1.0, eio(t));
// screenAlpha = mix(screenAlpha, 0.0, t);
t = tl(time, 0.5, 0.0);
radiusAnim = mix(radiusAnim, 0.0, t);
routeAnim = mix(routeAnim, 0.0, t);
sphereAnim = mix(sphereAnim, 0.0, t);
t = tl(time, 0.5, 1.0);
rayDirectionAnim2 = mix(rayDirectionAnim2, 1.0, t); // fio(t)); // eio(t));
t = tl(time, 0.5, 3.0);
rayDirectionAnim = mix(rayDirectionAnim, 1.0, fio(t));
t = tl(time, 3.5, 0.0);
rayDirectionAnim2 = mix(rayDirectionAnim2, 0.0, t);
raySphereAlpha = mix(raySphereAlpha, 0.0, t);
// rayDirectionAnim = mix(rayDirectionAnim, 0.0, t);
// raySphereAlpha = mix(raySphereAlpha, 0.0, t);
// rayDirectionAnim2 = mix(rayDirectionAnim2, 0.0, t);
// t = tl(time, 0.5, 1.0);
// cameraPos = mix(cameraPos, vec3(0.), eio(t));
// cameraTarget = mix(cameraTarget, vec3(0.0, 0.0, 5.), eio(t));
}
vec2 opU(vec2 a, vec2 b)
{
return a.x < b.x ? a : b;
}
float sdLine( vec3 p, vec3 a, vec3 b, float r )
{
vec3 pa = p - a, ba = b - a;
float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
return length( pa - ba*h ) - r;
}
float sdBox( vec3 p, vec3 b )
{
vec3 d = abs(p) - b;
return length(max(d,0.0))
+ min(max(d.x,max(d.y,d.z)),0.0); // remove this line for an only partially signed sdf
}
float sdSphere(vec3 p, float s)
{
return length(p) - s;
}
vec3 sunDir = normalize(vec3(.3, .25, .2));
vec3 skyColor(vec3 rd)
{
float sundot = clamp(dot(rd,sunDir),0.0,1.0);
// sky
vec3 col = mix(vec3(0.2,0.5,0.85)*1.1, vec3(0.0,0.15,0.7), rd.y);
col = mix( col, 0.85*vec3(0.8,0.8,0.7), pow( 1.0-max(rd.y,0.0), 4.0 ) );
// sun
col += 0.3*vec3(1.0,0.7,0.4)*pow( sundot,5.0 );
col += 0.5*vec3(1.0,0.8,0.6)*pow( sundot,64.0 );
col += 6.0*vec3(1.0,0.8,0.6)*pow( sundot,1024.0 );
return col * 3.0;
}
vec3 screenPos;
vec2 sceneSpheres(vec3 p)
{
vec2 s1 = vec2(sdSphere(p - vec3(-2.0, 0.0, 6.0), 1.), MAT_SPHERE1);
vec2 s2 = vec2(sdSphere(p - vec3(0.0, 0.0, 16.0), 1.), MAT_SPHERE2);
vec2 s3 = vec2(sdSphere(p - vec3(2.0, 0.0, 9.0), 1.), MAT_SPHERE3);
return opU(opU(s1, s2), s3);
}
vec2 sceneMap(vec3 p)
{
vec2 s = sceneSpheres(p);
vec2 p1 = vec2(p.y + 2.0, MAT_FLOOR);
return opU(s, p1);
}
vec3 normal(vec3 p)
{
vec2 e = vec2(0.001, 0.0);
float d = sceneMap(p).x;
return normalize(d - vec3(sceneMap(p - e.xyy).x, sceneMap(p - e.yxy).x, sceneMap(p - e.yyx).x));
}
void sceneTrace(inout vec3 pos, vec3 ray, out vec2 mat, inout float depth, float maxD)
{
vec3 ro = pos;
int i = 0;
for(; i < 70; i++) {
if (depth > maxD) {
depth = maxD;
break;
}
pos = ro + ray * depth;
mat = sceneMap(pos);
if (mat.x < 0.001) {
break;
}
depth += mat.x;
}
}
vec2 screenMap(vec3 p)
{
vec2 screenSize = iResolution.xy / min(iResolution.x, iResolution.y);
vec2 b1 = vec2(sdBox(p - vec3(0., 0., screenZ), vec3(screenSize, 0.01)), MAT_SCREEN);
return b1;
}
void screenTrace(inout vec3 pos, vec3 ray, out vec2 mat, inout float depth, float maxD)
{
vec3 ro = pos;
for(int i = 0; i < 20; i++) {
if (depth > maxD) {
depth = maxD;
break;
}
pos = ro + ray * depth;
mat = screenMap(pos);
if (mat.x < 0.001) {
break;
}
depth += mat.x;
}
}
float remap(float val, float im, float ix, float om, float ox)
{
return clamp(om + (val - im) * (ox - om) / (ix - im), om, ox);
}
vec2 gizmoCorners(vec3 p)
{
vec2 screenSize = iResolution.xy / min(iResolution.x, iResolution.y);
float a1 = remap(cornersAnim, 0.0, 0.25, 0.0, 1.0);
float a2 = remap(cornersAnim, 0.25, 0.5, 0.0, 1.0);
float a3 = remap(cornersAnim, 0.5, 0.75, 0.0, 1.0);
float a4 = remap(cornersAnim, 0.75, 1.0, 0.0, 1.0);
vec2 c1 = vec2(sdLine(p, vec3(0.), mix(vec3(0.), vec3(screenSize, screenZ), a1), 0.02), MAT_CORNER);
vec2 c2 = vec2(sdLine(p, vec3(0.), mix(vec3(0.), vec3(screenSize * vec2(1.,-1.), screenZ), a2), 0.02), MAT_CORNER);
vec2 c3 = vec2(sdLine(p, vec3(0.), mix(vec3(0.), vec3(screenSize * vec2(-1.,-1.), screenZ), a3), 0.02), MAT_CORNER);
vec2 c4 = vec2(sdLine(p, vec3(0.), mix(vec3(0.), vec3(screenSize * vec2(-1.,1.), screenZ), a4), 0.02), MAT_CORNER);
return opU(c1, opU(c2, opU(c3, c4)));
}
vec2 gizmoScreenZ(vec3 p)
{
vec2 c1 = vec2(sdLine(p, vec3(0.), vec3(0., 0., screenZ), 0.03), MAT_SCREENZ);
return c1;
}
float sphereID = 0.0;
vec3 rayRoute = vec3(0., 1., 0.); // y must be init to non-zero
vec2 gizmoMarching(vec3 p)
{
vec3 ray = vec3(0., 0., 1.);
vec2 d = vec2(10000.);
if(rayDirectionAnim2 > 0.0) {
if(abs(rayRoute.y - 0.) <= 0.01) {
ray = normalize(vec3(rayRoute.x, rayRoute.y, rayRoute.z));
radiusAnim = 20.;
routeAnim = 20.;
sphereAnim = 20.;
}
}
float t = 0.0;
vec3 pos;
int maxSteps = hitSphereID == 0. ? 20 : int(hitSphereID) + 1;
for(int i=0; i<maxSteps; i++) {
pos = ray * t;
vec2 s = vec2(sdSphere(p - pos, 0.15), MAT_MARCHSPHERE);
if (s.x < d.x) {
d = s;
sphereID = float(i);
}
float dist = sceneSpheres(pos).x;
float anim = clamp(routeAnim - float(i) - 1., 0.0, 1.0);
vec2 c1 = vec2(sdLine(p, pos, pos + mix(vec3(0.), ray * dist, anim), 0.03), MAT_MARCHROUTE);
d = opU(d, c1);
t += dist;
}
return d;
}
vec2 gizmoMarchingRadius(vec3 p)
{
vec2 d = vec2(p.y, MAT_MARCHRADIUS);
return d;
}
vec2 gizmoRayDirection(vec3 p)
{
float a1 = fract(rayDirectionAnim * 19.99999);
float a2 = floor(rayDirectionAnim * 19.99999) / 20.;
vec2 screenSize = iResolution.xy / min(iResolution.x, iResolution.y);
screenSize.y *= -1.;
screenSize = mix(-screenSize, screenSize, vec2(a1, a2));
rayRoute = mix(vec3(0.), vec3(screenSize, screenZ) * 10.0, rayDirectionAnim2);
vec2 c1 = vec2(sdLine(p, vec3(0.), mix(vec3(0.), vec3(screenSize, screenZ) * 10.0, rayDirectionAnim2), 0.02), MAT_RAYDIRECTION);
vec3 ray = normalize(vec3(screenSize, screenZ));
vec3 pos;
float t = 0.01;
for(int i = 0; i < 40; i++) {
pos = ray * t;
vec2 d = sceneMap(pos);
if (d.x < 0.001) {
break;
}
t += d.x;
}
c1 = opU(c1, vec2(sdSphere(p - pos, 0.15), MAT_HITPOINT));
return c1;
}
vec2 gizmoMap(vec3 p)
{
vec2 d = opU(gizmoCorners(p), gizmoScreenZ(p));
d = opU(d, gizmoMarching(p));
d = opU(d, gizmoRayDirection(p));
return d;
}
void gizmoTrace(inout vec3 pos, vec3 ray, out vec2 mat, inout float depth, float maxD)
{
vec3 ro = pos;
for(int i = 0; i < 60; i++) {
if (depth > maxD) {
depth = maxD;
break;
}
pos = ro + ray * depth;
mat = gizmoMap(pos);
if (mat.x < 0.001) {
break;
}
depth += mat.x;
}
}
vec2 radiusMap(vec3 p)
{
return gizmoMarchingRadius(p);
}
void radiusTrace(inout vec3 pos, vec3 ray, out vec2 mat, inout float depth, float maxD)
{
vec3 ro = pos;
for(int i = 0; i < 40; i++) {
if (depth > maxD) {
depth = maxD;
break;
}
pos = ro + ray * depth;
mat = radiusMap(pos);
if (mat.x < 0.001 || depth > maxD) {
break;
}
depth += mat.x;
}
}
float shadow(in vec3 p, in vec3 l, float ma)
{
float t = 0.1;
float t_max = ma;
float res = 1.0;
for (int i = 0; i < 16; ++i)
{
if (t > t_max) break;
vec3 pos = p + t*l;
float d = opU(sceneMap(pos), screenMap(pos)).x; // sceneMap(pos).x; //opU(, screenMap(pos)).x;
if (d < 0.001)
{
return 0.0;
}
t += d*1.0;
res = min(res, 10.0 * d / t);
}
return res;
}
// checkerbord
// https://www.shadertoy.com/view/XlcSz2
float checkersTextureGradBox( in vec2 p, in vec2 ddx, in vec2 ddy )
{
// filter kernel
vec2 w = max(abs(ddx), abs(ddy)) + 0.01;
// analytical integral (box filter)
vec2 i = 2.0*(abs(fract((p-0.5*w)/2.0)-0.5)-abs(fract((p+0.5*w)/2.0)-0.5))/w;
// xor pattern
return 0.5 - 0.5*i.x*i.y;
}
vec3 sceneShade(vec2 mat, vec3 pos, vec3 ray, float depth, float maxD)
{
vec3 col;
vec3 sky = skyColor(ray);
if (depth > maxD - 0.01) {
return sky;
}
float sha = shadow(pos, sunDir, 10.);
vec3 norm = normal(pos);
vec3 albedo = vec3(0.);
if(mat.y == MAT_SPHERE1) {
albedo = vec3(1., 0., 0.);
} else if (mat.y == MAT_SPHERE2) {
albedo = vec3(0., 1., 0.);
} else if (mat.y == MAT_SPHERE3) {
albedo = vec3(0., 0., 1.);
} else if(mat.y == MAT_FLOOR) {
vec2 ddx_uvw = dFdx( pos.xz );
vec2 ddy_uvw = dFdy( pos.xz );
float checker = checkersTextureGradBox( pos.xz, ddy_uvw, ddy_uvw );
albedo = vec3(max(0.2, checker)) * vec3(.8,0.8,0.7) * 2.0;
}
float diffuse = clamp(dot(norm, sunDir), 0.0, 1.0) * sha * 2.0;
col = albedo * (diffuse + 0.05);
float fo = 1.0 - exp2(-0.0001 * depth * depth);
vec3 fco = 0.65*vec3(0.4,0.65,1.0);
col = mix( col, sky, fo );
return col;
}
vec3 screenShade(vec2 mat, vec3 pos)
{
vec3 ro = vec3(0., 0., 0.);
vec3 ta = vec3(0., 0., 3.);
vec3 fo = normalize(ta - ro);
vec3 ri = normalize(cross(vec3(0.,1.,0.), fo));
vec3 up = normalize(cross(fo,ri));
mat3 cam = mat3(ri,up,fo);
vec3 ray = cam * normalize(pos);
float depth = 0.01;
vec3 p = ro;
sceneTrace(p, ray, mat, depth, 100.);
vec3 col = vec3(0.);
col = sceneShade(mat, p, ray, depth, 100.);
float a1 = fract(rayDirectionAnim * 19.99999);
float a2 = floor(rayDirectionAnim * 19.99999 + 1.0) / 20.;
float a3 = floor(rayDirectionAnim * 19.99999) / 20.;
float aspect = iResolution.y / iResolution.x;
float halfAspect = aspect * 0.5;
a1 = step(pos.x * halfAspect + 0.5, a1);
a2 = step(-pos.y * 0.49 + 0.51+ 0.0, a2);
a3 = step(-pos.y * 0.49 + 0.51 + 0.0, a3);
//col *= min(screenAlpha + min(a2 * a1 + a3, 1.0), 1.0);
// vec3 uvCoord = vec3(pow(clamp(mix(pos.xy*0.5+0.5, pos.xy, uvToP), 0.0, 1.0), vec2(2.2)), 0.0);
vec3 uvCoord = vec3(1.);
col = mix(col, uvCoord, colToUv - min(screenAlpha + min(a2 * a1 + a3, 1.0), 1.0));
return col;
//return vec3(pow(clamp(pos.xy, 0.0, 1.0), vec2(2.2)), 0.0);
}
vec4 gizmoShade(vec2 mat, vec3 p)
{
vec4 col = vec4(0.);
if(mat.y == MAT_CORNER) {
col = vec4(1.,0.,0., cornersAlpha);
} else if (mat.y == MAT_SCREENZ) {
col = vec4(0.05, 0.05, 1., screenZAlpha);
} else if (mat.y == MAT_MARCHSPHERE) {
float alpha = clamp(sphereAnim - sphereID, 0.0, 1.0);
vec3 sc = mix(vec3(.0, .1, 3.), vec3(1.02, 1., 0.02), float(sphereID == 0. || sphereID == hitSphereID));
// vec3 sc = mix(vec3(.0, .1, 3.), vec3(.02, 1., 1.02), float(sphereID == 0. || sphereID == hitSphereID));
float inRange = 1.0; //sphereID <= hitSphereID ? 1.0 : 0.0;
col = vec4(sc, alpha * raySphereAlpha * inRange);
} else if (mat.y == MAT_MARCHROUTE) {
col = vec4(1., 0., 0., .9);
} else if (mat.y == MAT_RAYDIRECTION) {
col = vec4(1., 0., 0., .9);
} else if (mat.y == MAT_HITPOINT) {
col = vec4(1.02, 1., .02, raySphereAlpha);
}
return col;
}
vec4 radiusShade(vec2 mat, vec3 p)
{
vec4 col = vec4(0.);
vec3 ray = vec3(0., 0., 1.);
vec2 d = vec2(10000.);
if(rayDirectionAnim2 > 0.0) {
if(abs(rayRoute.y - 0.) <= 0.01) {
ray = normalize(vec3(rayRoute.x, rayRoute.y, rayRoute.z));
radiusAnim = 20.;
routeAnim = 20.;
sphereAnim = 20.;
}
}
float t = 0.0;
for(int i=0; i<20; i++) {
vec3 pos = ray * t;
vec2 dd = sceneSpheres(pos);
d = vec2(sdSphere(p - pos, dd.x), MAT_MARCHSPHERE);
vec2 sceneDist = sceneMap(pos);
if (sceneDist.x < 0.001) {
if(hitSphereID == 0.) {
hitSphereID = float(i);
}
break;
}
float alpha2 = step(radiusAnim, float(i) + 2.);
float alpha = clamp(radiusAnim - float(i) - 1., 0.0, 1.0);
vec4 cirCol = vec4(.0, 0.05, 0.1, 0.9); //mix(vec4(.0, 0.05, 0.1, 0.9), vec4(0.2, 1., 1.4, .6) , alpha2);
// fill
col = mix(col, cirCol, smoothstep(0.01, 0., d.x) * cirCol.a * alpha);
// strike
col = mix(col, vec4(0., 0., 0., 1.), smoothstep(0.02, 0., abs(d.x) - 0.01) * alpha);
t += dd.x;
}
col *= radiusAlpha;
return col;
}
float luminance2(vec3 col)
{
return dot(vec3(0.298912, 0.586611, 0.114478), col);
}
vec3 reinhard(vec3 col, float exposure, float white) {
col *= exposure;
white *= exposure;
float lum = luminance2(col);
return (col * (lum / (white * white) + 1.0) / (lum + 1.0));
}
vec3 render(vec2 p) {
screenPos = vec3(p, 2.5);
vec3 ro = cameraPos;
vec3 ta = cameraTarget;
vec3 fo = normalize(ta - ro);
vec3 ri = normalize(cross(vec3(0.,1.,0.), fo));
vec3 up = normalize(cross(fo,ri));
mat3 cam = mat3(ri,up,fo);
vec3 ray = cam * normalize(screenPos);
float depth = 0.01;
vec2 mat;
vec3 col = vec3(0.);
vec3 pos = ro;
sceneTrace(pos, ray, mat, depth, 100.);
col = sceneShade(mat, pos, ray, depth, 100.);
float sceneDepth = depth;
depth = 0.01;
pos = ro;
screenTrace(pos, ray, mat, depth, sceneDepth);
if (depth < sceneDepth) {
col = screenShade(mat, pos);
}
float sceneAndScreenDepth = depth; // sceneDepth
depth = 0.01;
pos = ro;
radiusTrace(pos, ray, mat, depth, sceneAndScreenDepth);
if (depth < sceneAndScreenDepth) {
vec4 radius = radiusShade(mat, pos);
col = mix(col, radius.rgb, radius.a);
}
float sceneAndScreenAndGizmoDepth = sceneAndScreenDepth;
depth = 0.01;
pos = ro;
gizmoTrace(pos, ray, mat, depth, sceneAndScreenAndGizmoDepth);
if (depth < sceneAndScreenAndGizmoDepth) {
vec4 gizmo = gizmoShade(mat, pos);
col = mix(col, gizmo.rgb, gizmo.a);
}
return col;
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = (iMouse.xy - iResolution.xy)/min(iResolution.x, iResolution.y);
// timeLine(mod(length(uv.x), 41.));
timeLine(mod(iTime/4., 4.5));
vec2 p = (fragCoord * 2.0 - iResolution.xy)/min(iResolution.x, iResolution.y);
vec2 dp = 1. / iResolution.xy;
vec3 col = vec3(0.);
// AA
// https://www.shadertoy.com/view/Msl3Rr
for(int y = 0; y < 2; y++) {
for(int x = 0; x < 2; x++) {
vec2 off = vec2(float(x),float(y))/2.;
vec2 xy = (-iResolution.xy+2.0*(fragCoord + off * dp / 4.0)) / iResolution.y;
col += render(xy)*0.25;
}
}
col = reinhard(col, 1.0, 1000.0);
col = pow(col, vec3(1.0/2.2));
//col = mix(col, vec3(mix(uv, p, uvToP), 0.), colToUv);
fragColor = vec4(col,1.0);
}
Theorem. [gillespie2024ray, thm. 2] [ag-000U]
Theorem. [gillespie2024ray, thm. 2] [ag-000U]
Given a function \(F: \mathbb {R} \rightarrow \mathbb {R}\) with Lipschitz bound \(\lambda \geq \) Lip \(F\), and an initial point \(t_0\), sphere tracing converges linearly to the smallest root greater than \(t_0\).
Remark. [ag-000Q]
Remark. [ag-000Q]
Theorem [ag-000U] means that sphere tracing requires the function to be Lipschitz, i.e. has a known Lipschitz bound.
Not all functions are Lipschitz, e.g. Harmonic Functions are not globally Lipschitz, many may have no local Lipschitz bound even within small neighborhoods, thus requires a new technique named Harnack tracing developed in [gillespie2024ray].
Notes on Topos Theory and Type Theory [tt-0001]
- May 28, 2024
- Utensil Song
Notes on Topos Theory and Type Theory [tt-0001]
- May 28, 2024
- Utensil Song
Category theory [tt-000Z]
Category theory [tt-000Z]
Categories [tt-0005]
Categories [tt-0005]
Definition. category [kostecki2011introduction, 1.1] [tt-0002]
Definition. category [kostecki2011introduction, 1.1] [tt-0002]
A category \({\cal C}\) consists of:
- objects \(\operatorname {Ob}({\cal C})\): \(O, X, Y, \dots \)
- arrows \(\operatorname {Arr}({\cal C})\): \(f, g, h, \dots \), where for each arrow \(f\),
- a pair of operations \(\operatorname {dom}\) and \(\operatorname {cod}\) assign a domain object \(X=\operatorname {dom}(f)\) and a codomain object \(Y=\operatorname {cod}(f)\) to \(f\),
- thus f can be denoted by \[f : X \to Y\] or \[X \xrightarrow {f} Y\]
- compositions: a composite arrow of any pair of arrows \(f\) and \(g\), denoted \(g \circ f\) or \( f \mathbin {\bullet } g \), makes the diagram
commute (we say that \(f \mathbin {\bullet } g\) factors through \(Y\)), - a identity arrow for each object \(O\), denoted \(\mathit {1}_O : O \to O\)
- associativity of composition: the diagram
commutes, - identity law: the diagram
commutes.
Convention. composition [kostecki2011introduction, 1.1] [tt-003X]
Convention. composition [kostecki2011introduction, 1.1] [tt-003X]
In literatures, composition of arrows in a category is most frequently denoted \(\circ \) or just by juxtaposition, i.e. for the diagram
But this is the opposite of the order of arrows in the diagram, so arguably a more natural way could be to denote the above as \(f ; g\) [kostecki2011introduction, 1.1], or as \(f \mathbin {⨟} g\) [fong2018seven, 3.6], or as \(f \mathbin {\bullet } g\) [nakahira2023diagrammatic, sec. 1.1].
We use \(f \mathbin {\bullet } g\) throughout this note, so it can always be understood as \(\xrightarrow {f}\xrightarrow {g}\). This way saves mental energy when reading commuting diagrams, pasting diagrams and string diagrams which we employ heavily.
Definition. (locally) small, hom-set [kostecki2011introduction, 1.3] [tt-000A]
Definition. (locally) small, hom-set [kostecki2011introduction, 1.3] [tt-000A]
A category C is called locally small iff for any of its objects \(X, Y\) , the collection of arrows from \(X\) to \(Y\) is a set, called a hom-set, denoted \[\operatorname {Hom}_{{\cal C}}(X, Y)\]
A category is called small iff the collection of all its arrows is a set.
Notation. hom-set, hom-class [zhang2021type, 1.2] [tt-0003]
Notation. hom-set, hom-class [zhang2021type, 1.2] [tt-0003]
\(\operatorname {Hom}\) in \(\operatorname {Hom}_{{\cal C}}(X, Y)\) is short for homomorphism, since an arrow in category theory is a morphism (i.e. an arrow), a generalization of homomorphism between algebraic structures.
This notation could be unnecessarily verbose, so when there is no confusion, we follow [leinster2016basic] and [zhang2021type] to simply write \(X,Y \in \operatorname {Ob}({\cal C})\) as \[X,Y \in {\cal C}\] and \(f \in \operatorname {Hom}_{{\cal C}}(X, Y)\) as \[f \in {\cal C}(X, Y)\]
In some other scenarios, when the category in question is clear (and it might be to too verbose to write out, e.g. a functor category), we omit the subscript of the category and write just \[\operatorname {Hom}(X, Y)\]
In general, collection \(\operatorname {Ob}({\cal C})\) and \(\operatorname {Arr}({\cal C})\) are not neccessarily sets, but classes. In that case, \(\operatorname {Hom}_{{\cal C}}(X, Y)\) is called a hom-class.
Later, we will also learn that \(\operatorname {Ob}\) and \(\operatorname {Arr}\) are representable functors.
Definition. finite [kostecki2011introduction, 1.3] [tt-0034]
Definition. finite [kostecki2011introduction, 1.3] [tt-0034]
A category is called finite iff it is small and it has only a finite number of objects and arrows.
Definition. commuting diagram [kostecki2011introduction, 1.2] [tt-0007]
Definition. commuting diagram [kostecki2011introduction, 1.2] [tt-0007]
A diagram in a category \({\cal C}\) is defined as a collection of objects and arrows that belong to the category \({\cal C}\) with specified operations \(\operatorname {dom}\) and \(\operatorname {cod}\).
A commuting diagram is defined as such diagram that any two arrows of this diagram which have the same domain and codomain are equal.
For example, that the diagram
It's also called a arrow diagram [nakahira2023diagrammatic, 1.1] when compared to a string diagram, as it represents arrows with \(\to \).
Definition. string diagram [nakahira2023diagrammatic, table 1.1] [tt-003V]
Definition. string diagram [nakahira2023diagrammatic, table 1.1] [tt-003V]
A string diagram represents categories as surfaces (2-dimensional), functors as wires (1-dimensional), natural transformations as blocks or just dots (0-dimensional).
String diagrams has the advantage of being able to represent objects, arrows, functors, and natural transformations from multiple categories, and their vertical and horizontal composition, and has various topologically plausible calculational rules for proofs.
Notation. string diagrams: category, object and arrow [marsden2014category, sec. 2.1] [tt-0004]
Notation. string diagrams: category, object and arrow [marsden2014category, sec. 2.1] [tt-0004]
Later, when we have learned about functors and natural transformations, we will see that, in string diagram for 1-category:
-
A category \({\cal C}\) is represented as a colored region:
- Functors of type \(\mathbf {1} \to {\cal C}\) can be identified with objects of the category \({\cal C}\), where \(\mathbf {1}\) is the the terminal category, so an object \(X \in \operatorname {Ob}({\cal C})\) can be represented as:
-
An arrow \(f : X \to Y\) is then a natural transformation between two of these functors, represented as:
Convention. Letters [tt-0010]
Convention. Letters [tt-0010]
The general idea is that we try to use visually distinct letters for different concepts:
- uppercase calligraphic letters \({\cal C}, {\cal D}, {\cal E}, {\cal J}, {\cal S}\) denote categories
- \({\cal C}, {\cal D}, {\cal E}\) are prefered in concepts about one to three categories, since \({\cal C}\) is the first letter of "category"
- \({\cal J}\) is used in concepts like diagram, and assumed to be small
- \({\cal S}\) is used in concepts like subcategory, or sometimes in concepts about a small category
- boldface uppercase Roman letters denote specific categories, e.g. \(\mathbf {Cat}, \mathbf {Set}, \mathbf {Grp}, \mathbf {Top}, \mathbf {1}\)
- uppercase Roman letters \(X, Y, Z, W, O, E, V\) denote objects in categories
- lowercase Roman letters \(f, g, h, i, k, l, r\) and sometimes the lowercase Roman letter of the corresponding codomain or domain object denote arrows
- occationally, when two arrows are closely related, they are denoted by the same letter with different subscripts, e.g. \(g_1, g_2\)
- as special cases, \(\iota , p, i\) denote the inclusion, projection and injection arrows
- uppercase script letters \(\mathscr {F}, \mathscr {G}, \mathscr {H}, \mathscr {I}, \mathscr {K}, \mathscr {L}, \mathscr {R}\) denote functors
- \(\mathscr {D}\) denotes a diagram functor
- \(\mathscr {L}\) and \(\mathscr {R}\) denote the left and right adjoint functors in an adjunction, respectively
- \(\mathscr {H}\) denotes the Yoneda embedding functors
- as a special case, functors with the terminal category (i.e. constant object functors) as the domain are identified with the objects in the codomain category, thus are denoted like an object: \(X : \mathbf {1} \to {\cal C}, \mathrm {*} \mapsto X\)
- \(\mathscr {I}\) is only used in the inclusion functor (note that this is letter "I")
- we do not use \(\mathscr {J}\) and \(\mathscr {S}\) because they are visually ambiguous
- lowercase Greek letters \(\alpha , \beta , \eta , \epsilon , \sigma \) denote natural transformations, their components are denoted by them with subscripts.
Isomorphism [tt-000F]
Isomorphism [tt-000F]
Definition. monic [kostecki2011introduction, 2.1] [tt-000B]
Definition. monic [kostecki2011introduction, 2.1] [tt-000B]
An arrow \(f : X \to Y\) is monic if the diagram
"Monic" is short for "monomorphism", which is a generalization of the concept of injective (one-to-one) functions between sets.
Definition. epic [kostecki2011introduction, 2.2] [tt-000C]
Definition. epic [kostecki2011introduction, 2.2] [tt-000C]
An arrow \(f : X \to Y\) is epic if the diagram
"Epic" is short for "epimorphism", which is a generalization of the concept of surjective (onto) functions between sets.
Definition. iso [kostecki2011introduction, 2.3] [tt-000D]
Definition. iso [kostecki2011introduction, 2.3] [tt-000D]
An arrow \(f : X \to Y\) is iso, or \(X\) and \(Y\) are isomorphic, denoted \(X \cong Y\), or \(X \xrightarrow {\sim } Y\), if the diagram
"Iso" is short for "isomorphism", which is a generalization of the concept of bijective (one-to-one and onto) functions.
Convention. Uniqueness: dashed arrow [tt-000J]
Convention. Uniqueness: dashed arrow [tt-000J]
Uniqueness of an arrow is denoted \(\exists ! f\) or simply \(!f\), and visualized as a dashed arrow in diagrams, and \(!\) is often omitted.
Lemma. Iso [kostecki2011introduction, 2.4] [tt-000E]
Lemma. Iso [kostecki2011introduction, 2.4] [tt-000E]
An iso arrow is always monic and epic. However, not every arrow which is monic and epic is also iso.
Proof.
Proof.
The diagram
- \(g = h\) i.e. \(f\) is monic,
- \(k = l\) i.e. \(f\) is epic.
Special objects and categories [tt-000G]
Special objects and categories [tt-000G]
Definition. initial, terminal and null objects [kostecki2011introduction, 2.6] [tt-000I]
Definition. initial, terminal and null objects [kostecki2011introduction, 2.6] [tt-000I]
An initial object in a category \({\cal C}\) is an object \(\mathrm {0} \in \operatorname {Ob}({\cal C})\) such that for any object \(X\) in \({\cal C}\), there exists a unique arrow \(\mathrm {0} \to X\). It's also called a universal object, or a free object.
A terminal object in a category C is an object \(\mathrm {1} \in \operatorname {Ob}({\cal C})\) such that for any object \(X\) in \({\cal C}\), there exists a unique arrow \(X \to \mathrm {1}\). It's also called a final object, or a bound object.
Diagramatically,
A null object is an object which is both terminal and initial, confusingly, it's also called a zero object.
Lemma. Uniqueness [kostecki2011introduction, 2.7] [tt-000K]
Lemma. Uniqueness [kostecki2011introduction, 2.7] [tt-000K]
All initial objects in a category are isomorphic.
All terminal objects in a category are isomorphic.
In other words, they are unique up to isomorphism, respectively.
Definition. element [kostecki2011introduction, 2.8, 2.9] [tt-000M]
Definition. element [kostecki2011introduction, 2.8, 2.9] [tt-000M]
Let \(X, S \in \operatorname {Ob}({\cal C})\).
An element or a generalized element of \(X\) at stage \(S\) (or, of shape \(S\)) is an arrow \(x : S \to X\) in \({\cal C}\), also denoted \(x \in _{S} X\).
An arrow \(1 \to X\) is called a global element of \(X\), a.k.a. a point of \(X\).
An arrow \(S \to X\), if \(S\) is not isomorphic to \(1\), is called the local element of \(X\) at stage \(S\).
An arrow \(\mathit {1}_X : X \to X\) is called the generic element of \(X\).
Remark. element [kostecki2011introduction, 2.8] [tt-002W]
Remark. element [kostecki2011introduction, 2.8] [tt-002W]
In an element \(x : S \to X\), the object \(S\) is called a stage in order to express the intuition that it is a "place of view" on \(X\). In the same sense, \(S\) is also called a domain of variation, and \(X\) a variable element.
Sometimes, the term shape is used instead [leinster2016basic, 4.1.25], intuitive examples are:
- when the object is a set, a generalized element of \(X\) of shape \(\mathbb N\) is a sequence in the set \(X\)
- when the object is a topological space, a generalized element of \(X\) of shape \(S^1\) is a loop
In the context of studying solutions to polynomial equations, we may also call it a \(S\)-valued point in \(X\), where \(S\) is the number set where the solution is taken, e.g. the real, complex, and \(\operatorname {Spec} \mathbb F_p\)-valued solutions.
Definition. equivalent, equivalence class [kostecki2011introduction, 2.10] [tt-000N]
Definition. equivalent, equivalence class [kostecki2011introduction, 2.10] [tt-000N]
Two monic arrows \(x\) and \(y\) which satisfy
The equivalence class of \(x\) is denoted as \([x]\), i.e., \([x]=\{y \mid x \sim y\}\).
Definition. subobject, Sub [kostecki2011introduction, 2.10] [tt-004J]
Definition. subobject, Sub [kostecki2011introduction, 2.10] [tt-004J]
A subobject of any object is defined as an equivalence class of monic arrows into it.
The class of subobjects of an object \(X\) is denoted as \[ \operatorname {Sub}(X):=\{[f] \mid \operatorname {cod}(f)=X \wedge f \text { is monic }\}. \]
Definition. Set [kostecki2011introduction, 1.1, example 1] [tt-0008]
Definition. Set [kostecki2011introduction, 1.1, example 1] [tt-0008]
\(\mathbf {Set}\), the category of sets, consists of objects which are sets, and arrows which are functions between them. The axioms of composition, associativity and identity hold due to standard properties of sets and functions.
\(\mathbf {Set}\) has the initial object \(\varnothing \), the empty set, and the terminal object, \(\{*\}\), the singleton set.
\(\mathbf {Set}\) doesn't have a null object.
Monic arrows in \(\mathbf {Set}\) are denoted by \(f: X \hookrightarrow Y\), interpreted as an inclusion map (see also inclusion function in nLab).
Given \(X : \mathbf {Set}\), the subobjects of \(X\) are in canonical one-to-one correspondence with the subsets of \(X\).
Notation. inclusion [leinster2016basic, 0.8] [tt-000T]
Notation. inclusion [leinster2016basic, 0.8] [tt-000T]
In
Definition. Cat [leinster2016basic, 3.2.10] [tt-003G]
Definition. Cat [leinster2016basic, 3.2.10] [tt-003G]
We denote by \(\mathbf {Cat}\) the category of small categories and functors between them.
Definition. discrete category [leinster2016basic, 1.1.8] [tt-003K]
Definition. discrete category [leinster2016basic, 1.1.8] [tt-003K]
A discrete category has no arrows apart from the identity arrow, i.e. it amounts to just a class of objects.
We can regard a set as a discrete category.
Definition. terminal category [leinster2016basic, 4.1.6] [tt-003F]
Definition. terminal category [leinster2016basic, 4.1.6] [tt-003F]
A terminal category, denoted \(\mathbf {1}\), has only one object, denoted \(\mathrm {*}\), and only the identity arrow, denoted \(\mathit {1}\).
Definition. opposite category [kostecki2011introduction, 2.5] [tt-000H]
A category is called the opposite category of \({\cal C}\), denoted \(C^{op}\), iff
Definition. opposite category [kostecki2011introduction, 2.5] [tt-000H]
- (reversion of arrows) \[\operatorname {Ob}({\cal C}^{op}) = \operatorname {Ob}({\cal C})\] \[\operatorname {Arr}({\cal C}^{op}) \ni f: Y \to X \Longleftrightarrow \operatorname {Arr}({\cal C}) \ni f: X \to Y\]
- (reversion of composition)
Definition. product category [leinster2016basic, 1.1.11] [tt-0048]
Definition. product category [leinster2016basic, 1.1.11] [tt-0048]
Given categories \({\cal C}\) and \({\cal D}\), there is a product category, denoted \({\cal C} \times {\cal D}\), in which
- an object is a pair \((X, Y)\)
- an arrow \((X, Y) \to \left (X', Y'\right )\) is a pair \((f, g)\)
- the composition is given by \[(f_1, g_1) \mathbin {\bullet } (f_2, g_2) = (f_1 \mathbin {\bullet } f_2, g_1 \mathbin {\bullet } g_2)\]
- the identity on \((X, Y)\), denoted \(\mathit {1}_{(X, Y)}\) is \((\mathit {1}_X, \mathit {1}_Y)\)
Definition. (full) subcategory [leinster2016basic, 1.2.18] [tt-002Y]
Definition. (full) subcategory [leinster2016basic, 1.2.18] [tt-002Y]
Let \({\cal C}\) be a category. A subcategory \({\cal S}\) of \({\cal C}\) consists of a subclass \(\operatorname {Ob}({\cal S})\) of \(\operatorname {Ob}({\cal C})\) together with, for each \(S, S' \in \operatorname {Ob}({\cal S})\), a subclass \({\cal S}\left (S, S'\right )\) of \({\cal C}\left (S, S'\right )\), such that \({\cal S}\) is closed under composition and identities.
It is a full subcategory if \({\cal S}\left (S, S'\right )={\cal C}\left (S, S'\right )\) for all \(S, S' \in \operatorname {Ob}({\cal S})\).
Functors [tt-0013]
Functors [tt-0013]
Definition. (covariant) functor [kostecki2011introduction, 3.1] [tt-0014]
Definition. (covariant) functor [kostecki2011introduction, 3.1] [tt-0014]
A (covariant) functor \(\mathscr {F}: {\cal C} \to {\cal D}\) is given by the diagram
Definition. contravariant functor [kostecki2011introduction, 3.1] [tt-0015]
Definition. contravariant functor [kostecki2011introduction, 3.1] [tt-0015]
A functor \(\mathscr {F}\) is called a contravariant functor from \({\cal C}\) to \({\cal D}\), and denoted \(\mathscr {F} : {\cal C}^{op} \to {\cal D}\), if it obeys the definition given by the (covariant) functor for \({\cal C}\) replaced by \({\cal C}^{op}\), i.e. it's given by the diagram
Definition. functorial in [leinster2016basic, sec. 4.1] [tt-0041]
Definition. functorial in [leinster2016basic, sec. 4.1] [tt-0041]
For some expression \(E(X)\) containing \(X\), when we say \(E(X)\) is (covariant) functorial in \(X\), we mean that there exists a functor \(\mathscr {F}\) such that
Dually, we use the term contravariantly functorial in.
Convention. Functors [tt-001D]
Convention. Functors [tt-001D]
For simplicity, when there is no confusion, we use \(\bullet \) to represent corresponding objects, and omit the arrow names in the codomain of a functor, e.g.
Definition. full and faithful [kostecki2011introduction, 3.2] [tt-0017]
Definition. full and faithful [kostecki2011introduction, 3.2] [tt-0017]
A functor \(\mathscr {F}: {\cal C} \to {\cal D}\) is full iff for any pair of objects \(X, Y\) in \({\cal C}\) the induced map \(F_{X, Y}: {\cal C}(X, Y) \to {\cal D}(\mathscr {F}(X), \mathscr {F}(Y))\) is surjective (onto). \(\mathscr {F}\) is faithful if this map is injective (one-to-one).
Definition. preserve and reflect [kostecki2011introduction, 3.3] [tt-0018]
Definition. preserve and reflect [kostecki2011introduction, 3.3] [tt-0018]
A functor \(\mathscr {F}: {\cal C} \to {\cal D}\) is called to preserve a property \(\wp \) of an arrow iff for every \(f \in \operatorname {Arr}({\cal C})\) that has a property \(\wp \) it follows that \(\mathscr {F}(f) \in \operatorname {Arr}({\cal D})\) has this property. A functor \(\mathscr {F}: {\cal C} \to {\cal D}\) is called to reflect a property \(\wp \) of an arrow iff for every \(\mathscr {F}(f) \in \operatorname {Arr}({\cal D})\) that has a property \(\wp \) it follows that \(f \in \operatorname {Arr}({\cal C})\) has this property.
Example. full, faithful, preserve and reflect [kostecki2011introduction, 3.3] [tt-0019]
Example. full, faithful, preserve and reflect [kostecki2011introduction, 3.3] [tt-0019]
Every inclusion functor is faithful.
Every functor preserves isomorphisms.
Every faithful functor reflects monomorphisms and epimorphisms.
Every full and faithful functor reflects isomorphisms.
Special functors [tt-003N]
Special functors [tt-003N]
Definition. identity functor [kostecki2011introduction, 3.1, example 1] [tt-003P]
Definition. identity functor [kostecki2011introduction, 3.1, example 1] [tt-003P]
The identity functor \(\mathit {1}_{{\cal C}}: {\cal C} \to {\cal C}\) (denoted also by \( 1_{{\cal C}}: {\cal C} \to {\cal C}\)), defined by \(\mathit {1}_{{\cal C}}(X)=X\) and \(\mathit {1}_{{\cal C}}(f)=f\) for every \(X \in \operatorname {Ob}({\cal C})\) and every \(f \in \operatorname {Arr}({\cal C})\).
Definition. constant functor [kostecki2011introduction, 3.1, example 2] [tt-003Q]
Definition. constant functor [kostecki2011introduction, 3.1, example 2] [tt-003Q]
The constant functor \(\Delta _O: {\cal C} \to {\cal D}\) which assigns a fixed \(O \in \mathrm {Ob}({\cal D})\) to any object of \({\cal C}\) and \(\mathit {1}_O\), the identity arrow on \(O\), to any arrows from \({\cal C}\) :
Definition. constant object functor [leinster2016basic, 4.1.6] [tt-003H]
Definition. constant object functor [leinster2016basic, 4.1.6] [tt-003H]
A functor from the terminal category \(\mathbf {1}\) to a category \({\cal C}\) simply picks out an object of \({\cal C}\), called a constant object functor (which is a constant functor), denoted \(\Delta _X : \mathbf {1} \to {\cal C}\) for some \(X \in \operatorname {Ob}({\cal C})\), or simly denoted by the object, e.g. \(X\).
As special cases, constant object functor for initial and terminal objects are denoted by \(\mathrm {0}\) and \(\mathrm {1}\), respectively.
Definition. unique functor [nakahira2023diagrammatic, eq. 2.3] [tt-003Z]
Definition. unique functor [nakahira2023diagrammatic, eq. 2.3] [tt-003Z]
A unique functor, is a functor from a category \({\cal C}\) to the terminal category \(\mathbf {1}\), uniquely determined by mapping all arrows in \({\cal C}\) to the identity arrow \(\mathit {1}_{\mathrm {*}}\) of the unique object \(\mathrm {*}\) in \(\mathbf {1}\).
This functor is often denoted by \(! : {\cal C} \to \mathbf {1}\).
Intuitively, the functor \(!\) acts to erase all information about the input.
Definition. diagonal functor [leinster2016basic, sec. 6.1] [tt-003T]
Definition. diagonal functor [leinster2016basic, sec. 6.1] [tt-003T]
Given a small category \({\cal J}\) and a category \({\cal C}\), the diagonal functor \[\Delta _{{\cal J}}: {\cal C} \to [{\cal J}, {\cal C}]\] maps each object \(X \in {\cal C}\) to the constant functor \(\Delta _{{\cal J}}(X): {\cal J} \to {\cal C}\), which in turn maps each object in \({\cal J}\) to \(X\), and all arrows in \({\cal J}\) to \(\mathit {1}_X\).
When \({\cal J}\) is clear in the context, we may write \(\Delta _{{\cal J}}(X)\) as \(\Delta _X\).
Particularly [kostecki2011introduction, 3.1, example 6], when \({\cal J}\) is a discrete category of two objects, \(\Delta : {\cal C} \to {\cal C} \times {\cal C}, \Delta (X)=(X, X)\) and \(\Delta (f)=(f, f)\) for \(f: X \to X^{\prime }\)
\(\Delta _{{\cal J}}(X)\) is the same as \(X \mathbin {\bullet } !\), thus [nakahira2023diagrammatic, eq. 2.12] \[\Delta _{{\cal J}} = - \mathbin {\bullet } !\]
Definition. forgetful functor [kostecki2011introduction, 3.1, example 3] [tt-003R]
Definition. forgetful functor [kostecki2011introduction, 3.1, example 3] [tt-003R]
The forgetful functor, which forgets some part of structure, however arrows, compositions and identities are preserved.
Definition. inclusion functor [leinster2016basic, 1.2.18] [tt-003S]
Definition. inclusion functor [leinster2016basic, 1.2.18] [tt-003S]
Whenever \({\cal S}\) is a subcategory of a category \({\cal C}\) , there is an inclusion functor \(\mathscr {I} : {\cal S} \hookrightarrow {\cal C}\) defined by \(\mathscr {I}(S) = S\) and \(\mathscr {I}( f ) = f\) , i.e. it sends objects and arrows of \({\cal S}\) into themselves in category \({\cal C}\). It is automatically faithful, and it is full iff S is a full subcategory.
Example. other special functors [kostecki2011introduction, 3.1, example 10, 11, 4.6] [tt-0016]
Example. other special functors [kostecki2011introduction, 3.1, example 10, 11, 4.6] [tt-0016]
Some other special functors are introduced in later sections in context, e.g. hom-functor, Yoneda embedding functors.
Universal properties [tt-003O]
Universal properties [tt-003O]
Definition. universal arrow [kostecki2011introduction, 3.4, 3.5] [tt-001A]
Definition. universal arrow [kostecki2011introduction, 3.4, 3.5] [tt-001A]
A universal arrow from \(X \in {\cal D}\) to \(\mathscr {F} : {\cal C} \to {\cal D}\) is a unique pair \((O , u)\) that makes the diagram
Conversely, a (co)universal arrow from \(\mathscr {F} : {\cal C} \to {\cal D}\) to \(X \in {\cal D}\) is a unique pair \((O , u)\) that makes the diagram
Remark. universal property [leinster2016basic, sec. 1] [tt-002Z]
Remark. universal property [leinster2016basic, sec. 1] [tt-002Z]
We say universal arrows satisfy some universal property.
The term universal property is used to describe some property (usually some equality of some compositions, or a commuting diagram in general) that is satisfied for all (hence universal) relevant objects/arrows in the "world" (i.e. in the relevant categories), by a corresponding unique object/arrow.
It's usually spell out like this:
In a context where (usually a given diagram), for all (some objects/arrows), there exists a unique (object/arrow) such that (some property).
Diagramatically,
For clarity and brevity, usually the \(\forall \) clauses are specified outside the diagram, and the \(\exists !\) clause is expressed by dashed arrows. For more elaborate diagrams, see [freyd1976properties][fong2018seven][ochs2022missing].
For the diagram above, we also say that \(f\) uniquely factors through \(u\) along \(g\) [riehl2017category, 2.3.7].
A universal property is a property of some construction which boils down to (is manifestly equivalent to) the property that an associated object is an initial object of some (auxiliary) category [nlab2020univ].
Definition. comma category [leinster2016basic, 2.3.1] [tt-001C]
Definition. comma category [leinster2016basic, 2.3.1] [tt-001C]
Given categories and functors
Lemma. universal arrow via initial/terminal object of comma category [kostecki2011introduction, 3.6] [tt-001B]
Lemma. universal arrow via initial/terminal object of comma category [kostecki2011introduction, 3.6] [tt-001B]
A universal arrow from \(X \in {\cal D}\) to \(\mathscr {F} : {\cal C} \to {\cal D}\) is an initial object in the comma category \(X \downarrow \mathscr {F}\).
Conversely, a (co)universal arrow from \(\mathscr {F} : {\cal C} \to {\cal D}\) to \(X \in {\cal D}\) is a terminal object in the comma category \(\mathscr {F} \downarrow X\).
Natural transformation and functor category [tt-001M]
Natural transformation and functor category [tt-001M]
Definition. natural transformation [leinster2016basic, 1.3.1] [tt-001E]
Given categories and functors
Definition. natural transformation [leinster2016basic, 1.3.1] [tt-001E]
Definition. pasting diagram [nakahira2023diagrammatic, table 1.1] [tt-003W]
Definition. pasting diagram [nakahira2023diagrammatic, table 1.1] [tt-003W]
A pasting diagram represents categories as points (0-dimensional), arrows \(\to \) (1-dimensional), natural transformations as surfaces with level-2 arrows \(\Rightarrow \) (0-dimensional).
For example:
It's dual to a corresponding string diagram
Definition. Nat [kostecki2011introduction, 4.4] [tt-001N]
The collection of natural transformations from functors \(\mathscr {F}\) to \(\mathscr {G}\) is denoted \(\operatorname {Nat}(\mathscr {F}, \mathscr {G})\).
Definition. Nat [kostecki2011introduction, 4.4] [tt-001N]
Notation. string diagrams: functor and natural transformation [marsden2014category, sec. 2] [tt-001G]
Notation. string diagrams: functor and natural transformation [marsden2014category, sec. 2] [tt-001G]
In string diagrams,
- A functor \(\mathscr {F} : {\cal C} \to {\cal D}\) can be represented as an edge, commonly referred to as a wire:
- Functors compose from left to right:
- A natural transformation \(\alpha : \mathscr {F} \to \mathscr {F}'\) can be represented as a dot on the wire from top to bottem (the opposite direction of [marsden2014category], but the same as [sterling2023models]), connecting the two functors :
- Natural transformations (for the same pair of categories) compose vertically from top to bottem:
- Natural transformations (from different pairs of categories) compose horizontally from left to right:
- The two ways of composing natural transformations are related by the interchange law:
i.e. \[(\alpha \mathbin {\bullet } \alpha ') \mathbin {\bullet } (\beta \mathbin {\bullet } \beta ') = (\alpha \mathbin {\bullet } \beta ) \mathbin {\bullet } (\alpha ' \mathbin {\bullet } \beta ')\] The naturality in natural transformations is equivalent to the following equality:
where \(X\) and \(X'\) are objects in \({\cal C}\), understood as functors from the terminal category \(\mathit {1}\) to \({\cal C}\).👉
Since a string diagrams is composed from top to bottem, left to right, we can read
as \[(X \mathbin {\bullet } \mathscr {F}) \mathbin {\bullet } (\alpha _X) \mathbin {\bullet } (f \mathbin {\bullet } \mathscr {G})=(X' \mathbin {\bullet } \mathscr {G}) \quad {\large =} \quad (X \mathbin {\bullet } \mathscr {F}) \mathbin {\bullet } (f \mathbin {\bullet } \mathscr {F}) \mathbin {\bullet } (\alpha '_X)=(X' \mathbin {\bullet } \mathscr {G})\] where each pair of parentheses corresponds to an overlay in the string diagram, or with the notation in the opposite direction that is more familiar to most: \[\mathscr {G}(f) \circ \alpha _X \circ \mathscr {F}(X) = \mathscr {G}(X') \quad {\large =} \quad \alpha '_X \circ \mathscr {F}(f) \circ \mathscr {F}(X) = \mathscr {G}(X')\] Note that we read the wire from \(\mathscr {F}\) to \(\mathscr {G}\) as \(\mathscr {F}\) before the natural transformation, but as \(\mathscr {G}\) after the transformation.Effectively naturality says that the natural transformation and function \(f\) “slide past each other”, and so we can draw them as two parallel wires to illustrate this.
Definition. functor category [leinster2016basic, 1.3.6] [tt-001F]
Definition. functor category [leinster2016basic, 1.3.6] [tt-001F]
The functor category from \({\cal C}\) to \({\cal D}\), denoted \([{\cal C}, {\cal D}]\) or \({\cal D}^{{\cal C}}\), is a category whose objects are functors from \({\cal C}\) to \({\cal D}\) and whose arrows are natural transformations between them, where composition is given by
Remark. indexed, labelled [kostecki2011introduction, 4.5] [tt-001P]
Remark. indexed, labelled [kostecki2011introduction, 4.5] [tt-001P]
One can think of a functor category \([{\cal C}, {\cal D}]\) or \({\cal D}^{{\cal C}}\) as a category of diagrams in \(D\) indexed (or labelled) by the objects from \({\cal C}\).
This particularly makes sense in a diagram.
Definition. natural isomorphism [kostecki2011introduction, 4.2] [tt-001H]
Definition. natural isomorphism [kostecki2011introduction, 4.2] [tt-001H]
A natural transformation \(\sigma : \mathscr {F} \to \mathscr {G}\) between functors \(\mathscr {F}: {\cal C} \to {\cal D}\) and \(\mathscr {G} : {\cal C} \to {\cal D}\) is called a natural isomorphism or a natural equivalence, denoted \(\sigma : \mathscr {F} \cong \mathscr {G}\), if each component \(\sigma _X : \mathscr {F}(X) \to \mathscr {G}(X)\) is an isomorphism in \({\cal D}\), i.e. \(\mathscr {F}(X) \underset {\sigma _X}{\cong } \mathscr {G}(X)\).
We call \(\mathscr {F}\) and \(\mathscr {G}\) naturally isomorphic to each other.
We also say that \(\mathscr {F}(X) \cong \mathscr {G}(X)\) naturally in \(X\) [leinster2016basic, 1.3.12].
Diagramatically,
Lemma. natural isomorphism [leinster2016basic, 1.3.10] [tt-001I]
Lemma. natural isomorphism [leinster2016basic, 1.3.10] [tt-001I]
A natural isomorphism between functors from categories \({\cal C}\) and \({\cal D}\) is an isomorphism in the functor category \([{\cal C}, {\cal D}]\).
Definition. isomorphism of categories [kostecki2011introduction, 4.3] [tt-001J]
Definition. isomorphism of categories [kostecki2011introduction, 4.3] [tt-001J]
The cateories \({\cal C}\) and \({\cal D}\) are called isomorphic, denoted \({\cal C} \cong {\cal D}\), iff there exists functors
Definition. equivalence of categories [kostecki2011introduction, 4.3] [tt-001K]
Definition. equivalence of categories [kostecki2011introduction, 4.3] [tt-001K]
The categories \({\cal C}\) and \({\cal D}\) are called equivalent, denoted \({\cal C} \simeq {\cal D}\), iff there exist functors
Representables [tt-002K]
Representables [tt-002K]
Remark. representables [leinster2016basic, ch. 4, 4.1.15] [tt-002L]
Remark. representables [leinster2016basic, ch. 4, 4.1.15] [tt-002L]
A category is a world of objects, all looking at one another. Each sees the world from a different viewpoint.
We may ask: what objects see? Fix an object, this can be described by the arrows from it, this corresponds to the covariantly representable functor.
We can also ask the dual question: how objects are seen? Fix an object, this can be described by the arrows into it, this corresponds to the contravariantly representable functor.
Definition. set-valued [kostecki2011introduction, 4.4] [tt-001L]
A functor \(\mathscr {F} : {\cal C} \to \mathbf {Set}\) is called set-valued.
Definition. set-valued [kostecki2011introduction, 4.4] [tt-001L]
Definition. hom-functor [kostecki2011introduction, 3.1, example 10] [tt-001S]
Definition. hom-functor [kostecki2011introduction, 3.1, example 10] [tt-001S]
For every locally small category \({\cal C}\), the covariant hom-functor, denoted \[{\cal C}(X,-): {\cal C} \to \mathbf {Set} \] is given by
Conversely, the contravariant hom-functor, denoted \[{\cal C}(-,X): {\cal C}^{op} \to \mathbf {Set} \] is given by
Further, the hom-bifunctor, denoted \[{\cal C}(-,=): {\cal C}^{op} \times {\cal C} \to \mathbf {Set} \] defined as a contravariant hom-functor at first argument and as a covariant hom-functor at second argument.
We see \(-\) and \(=\) as placeholders for any object and its "associated arrow" (whose domain/codomain is the object, respectively) in the corresponding category. And we use boxes to mark the placeholder objects in diagrams.
Diagramatically [leinster2016basic, 4.1.22],
Definition. representable functor [kostecki2011introduction, 4.4] [tt-001O]
Definition. representable functor [kostecki2011introduction, 4.4] [tt-001O]
A set-valued functor \(\mathscr {F}: {\cal C} \to \mathbf {Set}\) is called covariantly representable if for some \(X \in {\cal C}\), \[\tau : \mathscr {F} \cong {\cal C}(X,-)\] where \(\cong \) denotes a natural isomorphism.
Conversely, a set-valued functor \(\mathscr {G} : {\cal C}^{op} \to \mathbf {Set}\) is called contravariantly representable if for some \(X \in {\cal C}\), \[\tau : \mathscr {G} \cong {\cal C}(-, X)\]
Such an object \(X\) is called a representing object for the functor \(\mathscr {F}\) or \(\mathscr {G}\), respectively.
The pair \((\tau , X)\) is called a representation of the functor \(\mathscr {F}\) (respectively, \(\mathscr {G}\) ).
Remark. representation [leinster2016basic, 4.1.3, 4.1.17] [tt-002M]
Remark. representation [leinster2016basic, 4.1.3, 4.1.17] [tt-002M]
A representation \((\tau , X)\) of a representable functor \(\mathscr {F}\) is a choice of an object \(X \in {\cal C}\) and an isomorphism \(\tau \) between the corresponding type of hom-functor and \(\mathscr {F}\).
Representable functors are sometimes just called representables. Only set-valued functors can be representable.
Definition. Yoneda embedding functors [leinster2016basic, 4.1.15] [tt-002T]
Definition. Yoneda embedding functors [leinster2016basic, 4.1.15] [tt-002T]
Let \({\cal C}\) be a locally small category. The covariant Yoneda embedding functor of \({\cal C}\) is the functor \[ \mathscr {H}^{\bullet }: {\cal C}^{op} \to [{\cal C}, \mathbf {Set}] \] defined on objects \(X\) by the covariant hom-functor on \(X\).
This functor embeds what every object in \({\cal C}\) sees the "world" of the category \({\cal C}\), i.e. arrows from each object.
Conversely, the (contravariant) Yoneda embedding functor of \({\cal C}\) is the functor \[ \mathscr {H}_{\bullet }: {\cal C} \to [{\cal C}^{op}, \mathbf {Set}] \] defined on objects \(X\) by the contravariant hom-functor on \(X\).
This functor embeds how every object in \({\cal C}\) is "seen", i.e. arrows to each object.
\(\bullet \) is a placeholder for an object. \(\mathscr {H}^X\) and \(\mathscr {H}_X\) denote the corresponding Yoneda embedding functors applied to \(X\), and are called covariant/contravariant Yoneda functors, respectively.
Diagramatically [rosiak2022sheaf, def. 161]:
When one speaks of the Yoneda (embedding) functor without specifying covariant or contravariant, it means the contravariant one, because it's the one used in the Yoneda lemma.
Lemma. Yoneda [leinster2016basic, 4.2.1] [tt-002N]
Lemma. Yoneda [leinster2016basic, 4.2.1] [tt-002N]
Let \({\cal C}\) be a locally small category. Then \[ \operatorname {Nat}(\mathscr {H}_X, \mathscr {F}) \cong \mathscr {F}(X) \] naturally in \(X \in {\cal C}\) and \(\mathscr {F} \in \left [{\cal C}^{\mathrm {op}}, \mathbf {Set} \right ]\), where \(\mathscr {H}_X\) is the (contravariant) Yoneda embedding functor on \(X\), and Nat denotes all the natural transformations between the two functors.
Notation. Yoneda lemma [leinster2016basic, 4.2.1] [tt-002U]
Notation. Yoneda lemma [leinster2016basic, 4.2.1] [tt-002U]
Diagramatically, \(\operatorname {Nat}(\mathscr {H}_X, \mathscr {F})\) is
Remark. Yoneda philosophy [rosiak2022sheaf, sec. 6.6] [tt-002S]
Remark. Yoneda philosophy [rosiak2022sheaf, sec. 6.6] [tt-002S]
The Yoneda lemma can be regarded as saying:
To understand an object it suffices to understand all its relationships with other things.
This is similar to the seventeenth-century philosopher Spinoza's idea that what a body is (its “essence”) is inseparable from all the ways that the body can affect (causally influence) and be affected (causally influenced) by other bodies.
The idea of Yoneda is that we can be assured that if a robot wants to learn whether some object \(X\) is the same thing as object \(Y\), it will suffice for it learn whether \[{\cal C}(-, X) \cong {\cal C}(-, Y)\] or, dually, \[{\cal C}(X, -) \cong {\cal C}(Y, -)\] i.e. whether all the ways of probing \(X\) with objects of its environment amount to the same as all the ways of probing \(Y\) with objects of its environment.
Lemma. full and faithful [kostecki2011introduction, 4.8] [tt-002X]
Lemma. full and faithful [kostecki2011introduction, 4.8] [tt-002X]
The Yoneda embedding functor \(\mathscr {H}_{\bullet }: {\cal C} \to [{\cal C}^{op}, \mathbf {Set}]\) is full and faithful.
Definition. Ob, Arr [leinster2016basic, 4.1.6] [tt-003U]
Definition. Ob, Arr [leinster2016basic, 4.1.6] [tt-003U]
Given a small category \({\cal C}\), there is a functor \(\operatorname {Ob} : \mathbf {Cat} \to \mathbf {Set}\) that sends \({\cal C}\) to its set of objects where \(\mathbf {Cat}\) is the category of small categories. Thus, \[ \mathscr {H}^{\mathrm {1}}({\cal C}) \cong \operatorname {Ob}({\cal C}) \] where \(\mathscr {H}\) is a Yoneda embedding functor.
This isomorphism is natural in \({\cal C}\); hence \(\operatorname {Ob} \cong \mathbf {Cat}(\mathrm {1}, -)\) where \(\mathbf {Cat}(\mathrm {1}, -)\) is a covariant hom-functor.
Functor \(\operatorname {Ob}\) is representable. Similarly, the functor \(\operatorname {Arr} : \mathbf {Cat} \to \mathbf {Set}\) sending a small category to its set of arrows is representable.
Definition. presheaf [leinster2016basic, 1.2.15] [tt-002Q]
Definition. presheaf [leinster2016basic, 1.2.15] [tt-002Q]
Let \({\cal C}\) be a category. A presheaf \(\mathscr {F}\) on \({\cal C}\) is a functor \({\cal C}^{op} \to \mathbf {Set}\).
It is called representable if \(\mathscr {F} \cong \mathscr {H}_X\) for some \(X\).
Remark. presheaf and Yoneda lemma [leinster2016basic, 4.2.1] [tt-002V]
Remark. presheaf and Yoneda lemma [leinster2016basic, 4.2.1] [tt-002V]
The Yoneda lemma says that for any \(X \in {\cal C}\) and presheaf \(\mathscr {F}\) on \({\cal C}\), a natural transformation \(\mathscr {H}_X \to \mathscr {F}\) is an element of \(\mathscr {F}(X)\) of shape \(\mathscr {H}_X\).
We may ask the question [chen2016infinitely, 68.6.4]:
What kind of presheaves are already "built in" to the category \({\cal C}\)?
The answer by the Yoneda lemma is, the Yoneda embedding \(\mathscr {H}_{\bullet }: {\cal C} \to [{\cal C}^{op}, \mathbf {Set}]\) embeds \({\cal C}\) into its own presheaf category.
In mathematics at large, the word "embedding" is used (sometimes informally) to mean a map \(i: X \to Y\) that makes \(X\) isomorphic to its image in \(Y\), i.e. \(X \cong i(X)\). [leinster2016basic, 1.3.19] tells us that in category theory, a full and faithful functor \(\mathscr {I}: X \to Y\) can reasonably be called an embedding, as it makes \(X\) equivalent to a full subcategory of \(Y\).
So, \({\cal C}\) is equivalent to the full subcategory of the presheaf category \([{\cal C}^{op}, \mathbf {Set}]\) whose objects are the representables.
Definition. The category of presheaves [kostecki2011introduction, 4.5, example 1] [tt-002R]
Definition. The category of presheaves [kostecki2011introduction, 4.5, example 1] [tt-002R]
The functor category of contravariant set-valued functors \([{\cal C}^{op}, \mathbf {Set}]\), called the category of presheaves or varying sets, the objects of which are contravariant functors \({\cal C}^{op} \to \) Set. It may be regarded as a category of diagrams in \(\mathbf {Set}\) indexed contravariantly by the objects of \({\cal C}\).
By definition, objects of \({\cal C}\) play the role of stages, marking the "positions" (in passive view) or "movements" (in active view) of the varying set \(\mathscr {F}: {\cal C}^{op} \to \mathbf {Set}\). For every \(X\) in \({\cal C}^{op}\), the set \(\mathscr {F}(X)\) is a set of elements of \(\mathscr {F}\) at stage \(X\).
An arrow \(f: Y \to X\) between two objects in \({\cal C}^{op}\) induces a transition arrow \(\mathscr {F}(f): \mathscr {F}(X) \to \mathscr {F}(Y)\) between the varying set \(\mathscr {F}\) at stage \(A\) and the varying set \(\mathscr {F}\) at stage \(B\).
Basic types of diagrams [tt-000P]
Basic types of diagrams [tt-000P]
By "basic types of diagrams", we mean some basic structures inside a category.
Definition. diagram, shape [leinster2016basic, 5.1.18] [tt-0025]
Definition. diagram, shape [leinster2016basic, 5.1.18] [tt-0025]
Let \({\cal C}\) be a category and \({\cal J}\) a small category. A functor \(\mathscr {D} : {\cal J} \to {\cal C}\) is called a diagram in \({\cal C}\) of shape \({\cal J}\).
\({\cal J}\) is also called the indexing category of the diagram, and we say that \(\mathscr {D}\) is a diagram indexed by \({\cal J}\) [rosiak2022sheaf, example 35]. \(J\) is also called the template.
Definition. shape E [leinster2016basic, 5.14] [tt-000O]
Definition. shape E [leinster2016basic, 5.14] [tt-000O]
The diagram
For simplicity, we refer to a diagram of shape E by "a shape \(E(f, g)\)".
"E" in "shape E" stands for "equal", and the reason will unfold in the definition of equalizer.
Definition. fork [leinster2016basic, 5.4] [tt-000R]
Definition. fork [leinster2016basic, 5.4] [tt-000R]
A fork over a shape \(E(f, g)\) is the diagram
For simplicity, we refer to a fork by "a fork \((E, \iota )\) (over the shape \(E(f, g)\))".
Convention. Grey arrow [tt-000S]
Convention. Grey arrow [tt-000S]
We use grey arrows to represent the composition arrow in a fork. This convention is not from literatures and is subject to change.
Definition. equalizer [leinster2016basic, 5.1.11] [tt-000Q]
Definition. equalizer [leinster2016basic, 5.1.11] [tt-000Q]
An equalizer of a shape \(E(f, g)\) is a fork \((E, \iota )\) over it, such that, for any \((\mathrm {-}, d)\) over the fork, the diagram
For simplicity, we refer to the equalizer of a shape \(E(f, g)\) as \(\operatorname {Eq}(f, g)\), and \(\iota \) is the canonical inclusion.
We say that a category \({\cal C}\) has equalizers iff every shape E in \({\cal C}\) has an equalizer.
Remark. equalizing set [kostecki2011introduction, eq. 32] [tt-000U]
Remark. equalizing set [kostecki2011introduction, eq. 32] [tt-000U]
Equalizer in a category is a generalisation of a subset which consists of elements of a given set such that two given functions are equal on them, formally:
For any two arrows \(f, g: X \to Y\), their equalizing set \(E \subseteq X\) is defined as \[ E:=\{e \mid e \in X \wedge f(e)=g(e)\} \]
Definition. shape P [leinster2016basic, 5.14] [tt-000W]
Definition. shape P [leinster2016basic, 5.14] [tt-000W]
The diagram
For simplicity, we refer to a diagram of shape P by "a shape \(P(f, g)\)".
"P" in "shape P" may stand for "product/projection/pullback", and the reason will unfold in the definition of pullback.
Definition. pullback (fiber product) [kostecki2011introduction, 2.12] [tt-000V]
Definition. pullback (fiber product) [kostecki2011introduction, 2.12] [tt-000V]
A pullback of a shape \(P(f, g)\) is an object \(X \times _O Y\) in \({\cal C}\) together with arrows \(p_X\) and \(p_Y\), called projections, such that, for any object \(\mathrm {-}\) and arrows \(h\) and \(k\), the diagram
We say that a category \({\cal C}\) has pullbacks iff every shape \(P(f, g)\) in \({\cal C}\) has a pullback in \({\cal C}\).
A pullback is also called a fiber product.
The square
Lemma. pasting pullbacks [spivak2013category, 2.5.1.17] [tt-0056]
Lemma. pasting pullbacks [spivak2013category, 2.5.1.17] [tt-0056]
Pullbacks can be pasted together, i.e. for diagram
Definition. shape T [leinster2016basic, 5.14] [tt-0026]
Definition. shape T [leinster2016basic, 5.14] [tt-0026]
The diagram
For simplicity, we refer to a diagram of shape T by "a shape \(T(X, Y)\)" where \(X\) and \(Y\) are the 2 objects.
"T" in "shape T" stands for "two". Shape T is useful in the definition of binary product [kostecki2011introduction, 2.18].
Definition. binary product [kostecki2011introduction, 2.18] [tt-000Y]
A binary product of objects \(X\) and \(Y\) is an object \(X \times Y\) in \({\cal C}\) together with arrows \(p_X\) and \(p_Y\), called projections, such that, for any object \(\mathrm {-}\) and arrows \(h\) and \(k\), the diagram
Definition. binary product [kostecki2011introduction, 2.18] [tt-000Y]
We say that a category \({\cal C}\) has binary products iff every pair \(X, Y\) in \({\cal C}\) has a binary product \(X \times Y\) in \({\cal C}\).
When there is no confusion, we simply call bianry products products.
Definition. coshape, coequalizer, pushout (fiber coproduct), binary coproduct [kostecki2011introduction, 2.14, 2.16, 2.19] [tt-000X]
Definition. coshape, coequalizer, pushout (fiber coproduct), binary coproduct [kostecki2011introduction, 2.14, 2.16, 2.19] [tt-000X]
coshape, coequalizer, pushout (fiber coproduct), binary coproduct can be defined by reversing all arrows in the definitions of shape, equalizer, pullback (fiber product), binary product respectively.
The pushout equivalent of the fiber product object in pullback is the fiber coproduct object, denoted \(X +_{O} Y\), and the pushout equivalent of projections in pullback are injections, denoted \(i_X\) and \(i_Y\), respectively. The unique arrow of a pushout is denoted \([f, g]\).
The binary coproduct equivalent of the binary product object in binary product is the binary coproduct object, denoted \(X + Y\), and the binary coproduct equivalent of projections in binary product are injections, denoted \(i_X\) and \(i_Y\), respectively. The unique arrow of a binary coproduct is denoted \([f, g]\).
Diagramatically,
- Coshapes:
- \(T\) =
- \(E\) =
- \(P\) =
- \(T\) =
- coequalizer:
- pushout (fiber coproduct):
- binary coproduct:
Lemma. monic and pullback [leinster2016basic, 5.1.32] [tt-003J]
Lemma. monic and pullback [leinster2016basic, 5.1.32] [tt-003J]
An arrow \(X \xrightarrow {f} Y\) is monic iff the square
The significance of this lemma is that whenever we prove a result about limits, a result about monics will follow.
Lemma. epic and pushout [leinster2016basic, sec. 5.2] [tt-003M]
Lemma. epic and pushout [leinster2016basic, sec. 5.2] [tt-003M]
An arrow \(X \xrightarrow {f} Y\) is epic iff the square
This is dual to Lemma [tt-003J].
Definition. n-fold (co)products [kostecki2011introduction, 2.22] [tt-0011]
Definition. n-fold (co)products [kostecki2011introduction, 2.22] [tt-0011]
In any category with binary products the objects \(X \times (Y \times Z)\) and \((X \times Y) \times Z\) are isomorphic. In any category with binary coproducts the objects \(X+(Y+Z)\) and \((X+Y)+Z\) are isomorphic.
This allows to consider \(n\)-fold products \(X_1 \times \dots \times X_n\) and \(n\)-fold coproducts \(X_1 + \dots + X_n\) of objects of a given category.
Definition. have finite (co)products [kostecki2011introduction, 2.23] [tt-0012]
Definition. have finite (co)products [kostecki2011introduction, 2.23] [tt-0012]
A category which has n-fold (co)products for any \(n \in \mathbb N\) is said to have finite (co)products.
Limits [tt-0023]
Limits [tt-0023]
Remark. Limits [leinster2016basic, ch. 5] [tt-0024]
Remark. Limits [leinster2016basic, ch. 5] [tt-0024]
Adjointness is about the relationships between categories. Representability is a property of set-valued functors. Limits are about what goes on inside a category.
Whenever you meet a method for taking some objects and arrows in a category and constructing a new object out of them, there is a good chance that you are looking at either a limit or a colimit.
Definition. cone [leinster2016basic, 5.1.19] [tt-0028]
Definition. cone [leinster2016basic, 5.1.19] [tt-0028]
Let \({\cal C}\) be a category, \({\cal J}\) a small category, and \(\mathscr {D} : {\cal J} \to {\cal C}\) a diagram in \({\cal C}\) of shape \({\cal J}\).
A cone on \(\mathscr {D}\) is an object \(V \in {\cal C}\) (the vertex of the cone) together with a family \[ \left (V \xrightarrow {\pi _J} \mathscr {D}(J)\right )_{J \in {\cal J}} \] of arrows in \({\cal C}\) such that for all arrows \(J \to J'\) in \({\cal J}\), the diagram
The family of arrows are components of a natural transformation \(\pi : \Delta _V \to \mathscr {D}\), i.e. from the constant functor ( which assigns the same object \(V\) to any object \(J_i\) in \({\cal J}\)) to diagram functor \(\mathscr {D}\).
For simplicity, we refer to a cone by "a cone \((V, \pi )\) on \(\mathscr {D}\)".
Example. a cone on a diagram [kostecki2011introduction, 4.9] [tt-0029]
Example. a cone on a diagram [kostecki2011introduction, 4.9] [tt-0029]
The cone for a diagram
Definition. limit [kostecki2011introduction, 4.10] [tt-002A]
Definition. limit [kostecki2011introduction, 4.10] [tt-002A]
A cone \((V, \pi )\) on \(\mathscr {D} : {\cal C} \to {\cal J}\) is called a limit of \(\mathscr {D}\), denoted \[\lim \mathscr {D}\] if the diagram
The arrows \(\pi _J\) are called the projections of the limit.
Other possible terms of limit are limiting cone, universal cone.
Example. limits [kostecki2011introduction, 4.11, example 1-4] [tt-002B]
Example. limits [kostecki2011introduction, 4.11, example 1-4] [tt-002B]
The basic types of diagrams are actually examples of limits:
- binary product [kostecki2011introduction, 2.18]:
- pullback (fiber product) [kostecki2011introduction, 2.12]:
- equalizer [leinster2016basic, 5.1.11]:
- the limit of \(\mathscr {D} : \mathbf {\emptyset } \to {\cal C} \), where \(\mathbf {\emptyset }\) is an empty category:
i.e. the terminal object \(\mathrm {1}\) in \({\cal C}\). In particular, for \({\cal C} = \mathbf {Set}\) we have \[\mathrm {-} \xrightarrow {!} V = \lim \mathscr {D} = \{∗\} \]
Remark. cocone, colimit [kostecki2011introduction, 4.10] [tt-002E]
Remark. cocone, colimit [kostecki2011introduction, 4.10] [tt-002E]
A cocone and a colimit are defined by dualization, that is, by reversing the arrows in cone [leinster2016basic, 5.1.19] and limit [kostecki2011introduction, 4.10].
In another word, given \(\mathscr {D}^{op} : {\cal J}^{op} \to {\cal C}^{op}\), a cocone on \(\mathscr {D}\) is a cone on \(\mathscr {D}^{op}\), a colimit of \(\mathscr {D}\) is a limit of \(\mathscr {D}^{op}\) [leinster2016basic, 5.2.1].
The arrows \(\pi _J\) are called the coprojections of the colimit.
In the same say, one can and show that coequaliser, coproduct, pushout and initial object are examples of colimits.
Lemma. limits via products and equalizers [stacks2017stacks, 002N, 002P] [tt-0057]
Lemma. limits via products and equalizers [stacks2017stacks, 002N, 002P] [tt-0057]
If all products and equalizers exist, all limits exist.
Dually, if all coproducts and coequalizers exist, all colimits exist.
Definition. has (finite) limits, (finitely) complete, left exact [kostecki2011introduction, 4.10] [tt-002F]
Definition. has (finite) limits, (finitely) complete, left exact [kostecki2011introduction, 4.10] [tt-002F]
We say that a category \({\cal C}\) has (finite) limits or is (finitely) complete if every diagram \(\mathscr {D} : {\cal J} \to {\cal C}\), where \({\cal J}\) is a (finite) category, has a limit.
A category \({\cal C}\) is called left exact iff it is finitely complete.
Remark. (finitely) cocomplete, right exact [kostecki2011introduction, 4.10] [tt-003C]
Remark. (finitely) cocomplete, right exact [kostecki2011introduction, 4.10] [tt-003C]
Dually to Definition [tt-002F], when every diagram \(\mathscr {D} : {\cal J} \to {\cal C}\), where \({\cal J}\) is a (finite) category, has a colimit, it is said that the category \({\cal C}\) has (finite) colimits or is (finitely) cocomplete.
A category is called right exact iff it is finitely cocomplete.
Lemma. (finitely) (co)complete category [kostecki2011introduction, 4.14] [tt-002J]
Lemma. (finitely) (co)complete category [kostecki2011introduction, 4.14] [tt-002J]
A category \({\cal C}\) is (finitely) complete if it has a terminal object, equalizers and (finite) products, or if it has a terminal object and (finite) pullbacks.
Dually, a category \({\cal C}\) is (finitely) cocomplete if it has an initial object, coequalizers and (finite) coproducts, or if it has an initial object and (finite) pushouts.
Lemma. (co)complete functor category [kostecki2011introduction, 4.15] [tt-002I]
Lemma. (co)complete functor category [kostecki2011introduction, 4.15] [tt-002I]
If category \({\cal D}\) is complete and category \({\cal C}\) is small, then the functor category \({\cal D}^{{\cal C}}\) is complete.
Dually, if category \({\cal D}\) is cocomplete and category \({\cal C}\) is small, then the functor category \({\cal D}^{{\cal C}}\) is cocomplete.
Definition. preorder, partial order, total order [kostecki2011introduction, 1.2, example 9] [tt-002C]
Definition. preorder, partial order, total order [kostecki2011introduction, 1.2, example 9] [tt-002C]
Let \(P\) be a set. The properties
- (reflexivity) \(\forall p \in P, p \leq p\)
- (transitivity) \(\forall p, q, r \in P, p \leq q \wedge q \leq r \Rightarrow p \leq r\)
A partially ordered set (called a partial order, or a poset) is defined as a preorder \((P, \leq )\) for which
- (antisymmetry) \(\forall p \in P, p \leq q \wedge q \leq p \Rightarrow p=q\)
A total order (or a linear order) is a partial order \((P, \leq )\) for which
- (comparability) \(\forall p, q \in P, p \leq q \vee q \leq p\)
The category \(\mathbf {Preord}\) consists of objects which are preorders and of arrows which are orderpreserving functions.
The category \(\mathbf {Poset}\) consists of objects which are posets and of arrows which are order-preserving functions between posets, that is, the maps \(T: P \to P'\) such that \[ p \leq q \Rightarrow T(p) \leq T(q) \]
Any any preorder \((P, \leq )\) and poset \((P, \leq )\) can be considered as a category consisting of objects which are elements of a set \(P\) and arrows defined by \(p \to q \Longleftrightarrow p \leq q\).
Definition. directed poset [rosiak2022sheaf, def. 285] [tt-0051]
Definition. directed poset [rosiak2022sheaf, def. 285] [tt-0051]
A directed poset is a poset that is inhabited (nonempty) and for which every finite subset has an upper bound. Explicitly,
- (directedness) \(\forall x,y \in P, \exists z \in P, x \leq z \land y \leq z\)
Example. preorder, poset, directed poset [tt-0052]
Example. preorder, poset, directed poset [tt-0052]
An example of a preorder category which is not poset is:
An example of a poset category which is not a directed poset is [rosiak2022sheaf, example 3] :
An example that is a directed poset category but not a total order is:
A more complicated example of a directed poset category which is not a total order is [spivak2013category, example 3.4.1.3]:
One can see immediately that this is a preorder because length=0 paths give reflexivity and concatenation of paths gives transitivity. To see that it is a partial order we only note that there are no loops.
To see that it is a poset, we note that every pair of nodes from one side or both sides has the central node as an upper bound, thus satisfying directedness.
But this partial order is not a total order because there is no path (in either direction) between some nodes, thus violating comparability.
Definition. inverse limit, projective limit [kostecki2011introduction, 4.11] [tt-002D]
Definition. inverse limit, projective limit [kostecki2011introduction, 4.11] [tt-002D]
Let \({\cal J}\) be a directed poset and \(\mathscr {F} : {\cal J} \to {\cal C}\) be a contravariant functor. The limit of \(\mathscr {F}\) is called an inverse limit or projective limit, and is denoted \(\lim \limits _{\leftarrow {\cal J}} \mathscr {F}\) or simply \(\lim \limits _{\longleftarrow } \mathscr {F}\).
Definition. direct limit, inductive limit [kostecki2011introduction, 4.12] [tt-002G]
Definition. direct limit, inductive limit [kostecki2011introduction, 4.12] [tt-002G]
Let \({\cal J}\) be a directed poset and \(\mathscr {F}: {\cal J} \to {\cal C}\) be a contravariant functor. The colimit of \(\mathscr {F}\) is called a direct limit (some called directed limit) or inductive limit, and is denoted \(\lim \limits _{\to {\cal J}} \mathscr {F}\), or simply \(\lim \limits _{\longrightarrow } \mathscr {F}\).
This is dual to inverse limit.
Definition. preserves (all) (co)limits, left/right exact [kostecki2011introduction, 4.13] [tt-002H]
Definition. preserves (all) (co)limits, left/right exact [kostecki2011introduction, 4.13] [tt-002H]
A functor \(\mathscr {F}: {\cal C} \to {\cal D}\) preserves (all) limits and is called left exact iff it sends all limits in \({\cal C}\) into limits in \({\cal D}\).
Dually, a functor \(\mathscr {F}: {\cal C} \to {\cal D}\) preserves (all) colimits and is called right exact iff it sends all colimits in \({\cal C}\) into colimits in \({\cal D}\).
Remark. directions in (co)limits [tt-004Y]
Remark. directions in (co)limits [tt-004Y]
| Limit | Colimit | |
|---|---|---|
| diagram | ||
| arrows through the vertex | into the diagram | out of the diagram |
| on (co)shape P | pullback | pushout |
| categories have finite ... | left exact | right exact |
| functors preserve all ... | left exact | right exact |
| on directed poset | inverse/projective limit \(\lim \limits _{\longleftarrow } \mathscr {F}\) | direct/inductive limit \(\lim \limits _{\longrightarrow } \mathscr {F}\) |
One can see from the table that, in general, limits have the direction "back" "into" (where "back", "left", "inverse" are directional consistent), and colimits have the opposite: "forward" "out of".
This might help to memorize the directions in these concepts without disorientation.
Adjunctions [tt-001T]
Adjunctions [tt-001T]
Definition. adjoint functor [kostecki2011introduction, 5.1] [tt-001Q]
Definition. adjoint functor [kostecki2011introduction, 5.1] [tt-001Q]
Given functors
The components of the natural isomorphism \(\sigma \) are isomorphisms \[ \sigma _{XY} : {\cal D}(\mathscr {L}(X), Y) \cong {\cal C}(X, \mathscr {R}(Y)) \]
Remark. adjoint functor [kostecki2011introduction, 5.1] [tt-001R]
Remark. adjoint functor [kostecki2011introduction, 5.1] [tt-001R]
An adjunction \(\mathscr {L} \dashv \mathscr {R}\) means arrows \(\mathscr {L}(X) \to Y\) are essentially the same thing as arrows \(X \to \mathscr {R}(Y)\) for any \(X \in {\cal C}\) and \(Y \in {\cal D}\).
This means the diagram
The above can also be diagramatically denoted by transposition diagram \[ \begin {array}{ccccccc} X' & \xrightarrow {x} & X & \xrightarrow {\sigma _{X Y}(f)} & \mathscr {R}(Y) & \xrightarrow {\mathscr {R}(y)} & \mathscr {R}\left (Y'\right ) \\ \hline \mathscr {L}\left (X'\right ) & \xrightarrow {\mathscr {L}(x)} & \mathscr {L}(X) & \xrightarrow {f} & Y & \xrightarrow {y} & Y' \end {array} \] or simply, \[ \frac {X \to \mathscr {R}(Y) \quad ({\cal C})}{\mathscr {L}(X) \to Y \quad ({\cal D})} \]
An adjunction is a concept that describes the relationship between two functors that are weakly inverse to each other [nakahira2023diagrammatic, sec. 4].
By "weakly inverse", we don't mean that applying one after the other gives the identity functor, but in a sense similar to eroding (i.e. enhancing holes) and dilating (i.e. filling holes) an image, applying them in different order yeilds upper/lower "bounds" of the original image [rosiak2022sheaf, sec. 7.1].
Notation. string diagrams: adjunction [nakahira2023diagrammatic, sec. 3.1] [tt-001U]
Notation. string diagrams: adjunction [nakahira2023diagrammatic, sec. 3.1] [tt-001U]
Here we follow the string diagram style of [marsden2014category] and [sterling2023models], but with additional string diagram types inspired by [nakahira2023diagrammatic, eq. 3.1, 4.3].
- The covariant hom-functor \({\cal C}(X, -)\), denoted \(-^X\), can be represented in string diagrams as
where the dotted circle denotes any arrows with the domain \(X\) and codomain \(-\). - The contravariant hom-functor \({\cal C}(-, X)\), denoted \(X^-\), can be represented in a similar manner.
- The hom-bifunctor \({\cal C}(-,=)\), also denoted \(=^-\), can be represented as
where the dotted circle denotes any arrows with the domain \(-\) and codomain \(=\). - The natural isomorphism
\[{\cal D}(\mathscr {L}(-), =) \cong {\cal C}(-, \mathscr {R}(=))\]
in adjunction can be represented as
Definition. transpose [kostecki2011introduction, 5.1] [tt-001X]
Definition. transpose [kostecki2011introduction, 5.1] [tt-001X]
Given an adjunction \(\mathscr {L} \dashv \mathscr {R}: {\cal C} \rightleftarrows {\cal D}\), there exists \(f^{\sharp }\) and \(g^{\flat }\) such that the diagrams
\(f^{\sharp }\) is called the left transpose of \(f\). \(g^{\flat }\) is called the right transpose of \(g\).
Other possible terms are left/right adjunct of each other, and mates [nlab2023adjunct].
Remark. idempotent [zhang2021type, 5.30] [tt-0037]
Remark. idempotent [zhang2021type, 5.30] [tt-0037]
Given an adjunction \(\mathscr {L} \dashv \mathscr {R}: {\cal C} \rightleftarrows {\cal D}\), we may obtain two endofunctors \( \mathscr {L} \mathbin {\bullet } \mathscr {R} : {\cal C} \to {\cal C}\) and \( \mathscr {R} \mathbin {\bullet } \mathscr {L} : {\cal D} \to {\cal D}\) that commute the diagram
Definition. (co)unit [zhang2021type, 5.30] [tt-001V]
Definition. (co)unit [zhang2021type, 5.30] [tt-001V]
Given an adjunction \(\mathscr {L} \dashv \mathscr {R}: {\cal C} \rightleftarrows {\cal D}\), the natural transformation \[\eta : \mathit {1}_{{\cal C}} \to \mathscr {L} \mathbin {\bullet } \mathscr {R} \] is called the unit of the adjunction, and \[\epsilon : \mathscr {R} \mathbin {\bullet } \mathscr {L} \to \mathit {1}_{{\cal D}}\] is called the counit.
We call an arrow \[\eta _X: X \to (\mathscr {L} \mathbin {\bullet } \mathscr {R})(X)\] a unit over \(X\), and \[\epsilon _Y: (\mathscr {R} \mathbin {\bullet } \mathscr {L})(Y) \to Y\] a counit over \(Y\). They are components of the natural transformations \(\eta \) and \(\epsilon \), respectively.
Diagramatically, the diagrams
Lemma. universality of (co)unit [kostecki2011introduction, 5.3] [tt-001W]
Lemma. universality of (co)unit [kostecki2011introduction, 5.3] [tt-001W]
The unit \(\eta \) and counit \(\epsilon \) of an adjunction \(\mathscr {L} \dashv \mathscr {R}: {\cal C} \rightleftarrows {\cal D}\) are universal, i.e. the diagram
Lemma. triangle identities [kostecki2011introduction, 5.4] [tt-001Z]
Lemma. triangle identities [kostecki2011introduction, 5.4] [tt-001Z]
Given an adjunction \(\mathscr {L} \dashv \mathscr {R}: {\cal C} \rightleftarrows {\cal D}\), the diagrams
Note that \(\mathscr {L}\) in \(\epsilon _\mathscr {L}\) is a subscript, meaning \(\epsilon _\mathscr {L}: {\cal D} \to {\cal D}, \mathscr {L}(X) \mapsto \epsilon _{\mathscr {L}(X)}\) for \(X \in {\cal C}\). Similar for \(\eta _\mathscr {R}\).
Lemma. snake identities [nakahira2023diagrammatic, thm. 4.8] [tt-0030]
Lemma. snake identities [nakahira2023diagrammatic, thm. 4.8] [tt-0030]
Continuing from Notation [tt-001U], the triangle identities can be represented in string diagrams as follows, and called the snake identities (or zig-zag identities):
Notation. string diagram: snake identities [nakahira2023diagrammatic, thm. 4.8] [tt-0031]
Notation. string diagram: snake identities [nakahira2023diagrammatic, thm. 4.8] [tt-0031]
Following Notation [tt-001G], recall that a string diagram is composed from top to bottem, left to right, we can read the left snake
Lemma. (co)unit and transposes [leinster2016basic, 2.2.4] [tt-001Y]
Lemma. (co)unit and transposes [leinster2016basic, 2.2.4] [tt-001Y]
Given an adjunction
Notation. string diagrams: (co)unit and transposes [marsden2014category, lem. 3.6] [tt-0033]
Notation. string diagrams: (co)unit and transposes [marsden2014category, lem. 3.6] [tt-0033]
In string diagrams, Lemma [tt-001Y] can be represented as:
Remark. topologically plausible [leinster2016basic, 2.2.9] [tt-0039]
Remark. topologically plausible [leinster2016basic, 2.2.9] [tt-0039]
The string diagrams in Lemma [tt-0030] and Notation [tt-0033] are topologically plausible equations, i.e. the equality can be obtained by simply pulling the string straight.
Lemma. (co)unit and natural isomorphism [kostecki2011introduction, eq. 127] [tt-0020]
Lemma. (co)unit and natural isomorphism [kostecki2011introduction, eq. 127] [tt-0020]
The natural transformation \(\sigma _{XY}\) and \(\tau _{XY}\) that are the components of the natural isomorphism in the adjunction \(\mathscr {L} \dashv \mathscr {R} : {\cal C} \rightleftarrows {\cal D}\) are related to the unit and counit of the adjunction: \[\begin {aligned} \sigma _{XY}(f) & = \eta _X \mathbin {\bullet } \mathscr {R}(f^{\sharp })\\ \tau _{XY}(g) & = \mathscr {L}(g^{\flat }) \mathbin {\bullet } \epsilon _Y \end {aligned} \] and they are reverse of each other \[\sigma _{XY} = \tau _{YX}^{-1}\]
Proof.
This can be read out from the diagrams in universality of (co)unit [kostecki2011introduction, 5.3] and transpose [kostecki2011introduction, 5.1].
Proof.
Lemma. uniqueness of adjoints [kostecki2011introduction, 5.8] [tt-0021]
Lemma. uniqueness of adjoints [kostecki2011introduction, 5.8] [tt-0021]
A left or right adjoint, if it exists, is unique up to natural isomorphism.
Proof.
For the left adjoint, from the university of \(\eta \) it follows that there exists a unique, up to isomorphism, isomorphism between different left adjoints. It remains to show naturality of this isomorphim, which is left as an exercise. The proof for right adjoint follows by duality.
Proof.
Theorem. adjunction via (co)units [leinster2016basic, 2.2.5] [tt-0038]
Theorem. adjunction via (co)units [leinster2016basic, 2.2.5] [tt-0038]
Given categories and functors
Proof.
Proof.
From Lemma [tt-001Z], it follows that every adjunction between \(\mathscr {L}\) and \(\mathscr {R}\) gives rise to a pair of transformations \(\eta \) and \(\epsilon \) satisfying the triangle identities.
To show that there exists a unique adjunction for \(\eta \) and \(\epsilon \), the uniqueness follows from Lemma [tt-001Y], the existence can use the construction in the spirit of Definition [tt-001X].
Theorem. adjunction via initial objects [leinster2016basic, 2.3.6] [tt-003A]
Theorem. adjunction via initial objects [leinster2016basic, 2.3.6] [tt-003A]
Given categories and functors
- the adjunction \(\mathscr {L} \dashv \mathscr {R}\)
natural transformations \(\eta : \mathit {1}_{{\cal C}} \to \mathscr {L} \mathbin {\bullet } \mathscr {R}\) such that \(\eta _X\) is initial in the comma category \(X \Rightarrow \mathscr {R}\) for every \(X \in {\cal C}\)
Diagramatically,
where the functor \(X\) is the constant object functor.
Interactions [tt-002P]
Interactions [tt-002P]
Remark. interactions [leinster2016basic] [tt-0043]
Remark. interactions [leinster2016basic] [tt-0043]
In this section, we will discuss the interactions between
- (co)limits
- adjunctions
- representables
Lemma. adjunction preserves (co)limits [leinster2016basic, 6.3.1] [tt-002O]
Lemma. adjunction preserves (co)limits [leinster2016basic, 6.3.1] [tt-002O]
Given an adjunction \(\mathscr {L} \dashv \mathscr {R}: {\cal C} \rightleftarrows {\cal D}\), \(\mathscr {L}\) preserves colimits, and \(\mathscr {R}\) preserves limits.
Explictly, given \(\mathscr {D}: {\cal J} \to {\cal C}\), we have \[(\operatorname {colim} \mathscr {D}) \mathbin {\bullet } \mathscr {L} \cong \operatorname {colim}(\mathscr {D} \mathbin {\bullet } \mathscr {L})\] and given \(\mathscr {D}': {\cal J} \to {\cal D}\), we have \[(\lim \mathscr {D}') \mathbin {\bullet } \mathscr {R} \cong \lim (\mathscr {D}' \mathbin {\bullet } \mathscr {R})\]
Definition [tt-002H]
Corollary. a representation is a universal element [leinster2016basic, 4.3.2] [tt-0035]
Corollary. a representation is a universal element [leinster2016basic, 4.3.2] [tt-0035]
Let \({\cal C}\) be a locally small category and \(\mathscr {F} : {\cal C}^{op} \to \mathbf {Set}\). Then a representation of \(\mathscr {F}\) consists of a pair \((X, u)\) such that the diagram
Remark. universal element [leinster2016basic, 4.3.2] [tt-0036]
Remark. universal element [leinster2016basic, 4.3.2] [tt-0036]
Pairs \((Y, y)\) with \(Y \in {\cal C}\) and \(y \in \mathscr {F}(Y)\) in Corollary [tt-0035] are sometimes called elements of the presheaf \(\mathscr {F}\).
Indeed, Lemma [tt-002N] (Yoneda) tells us that \(y\) amounts to a generalized element of \(\mathscr {F}\) of shape \(\mathscr {H}_Y\).
An element \(u\) satisfying condition in Corollary [tt-0035] is sometimes called a universal element of \(\mathscr {F}\). So, Corollary [tt-0035] says that a representation of a presheaf \(\mathscr {F}\) amounts to a universal element of \(\mathscr {F}\).
Lemma. adjunction and representable [leinster2016basic, 4.1.11] [tt-003I]
Lemma. adjunction and representable [leinster2016basic, 4.1.11] [tt-003I]
Any set-valued functor with a left adjoint is representable.
Definition. cone as a natural transformation [leinster2016basic, eq. 6.1] [tt-0040]
Definition. cone as a natural transformation [leinster2016basic, eq. 6.1] [tt-0040]
Now, given a diagram \(\mathscr {D}: {\cal J} \to {\cal C}\) and an object \(V \in {\cal C}\), a cone on \(\mathscr {D}\) with vertex \(V\) is simply a natural transformation from the diagonal functor \(\Delta _V\) to the diagram \(\mathscr {D}\).
Writing \(\operatorname {Cone}(V, \mathscr {D})\) for the set of cones on \(\mathscr {D}\) with vertex \(V\), we therefore have \[ \operatorname {Cone}(V, \mathscr {D})=[{\cal J}, {\cal C}] (\Delta _V, \mathscr {D}) . \]
Thus, \(\operatorname {Cone}(V, \mathscr {D})\) is functorial in \(V\) (contravariantly) and \(\mathscr {D}\) (covariantly).
Lemma. limit via representation [leinster2016basic, 6.1.1] [tt-003Y]
Lemma. limit via representation [leinster2016basic, 6.1.1] [tt-003Y]
Let \({\cal J}\) be a small category, \({\cal C}\) a category, and \(\mathscr {D}: {\cal J} \to {\cal C}\) a diagram. Then there is a one-to-one correspondence between
- limit cones on \(\mathscr {D}\)
- representations of the natural transformation Cone
Briefly put: a limit \((V, \pi )\) of \(\mathscr {D}\) is a representation of \([{\cal J}, {\cal C}] (\Delta _{-}, \mathscr {D})\).
Diagramatically,
It implies that \[\operatorname {Cone}(\mathrm {-}, \mathscr {D}) \cong {\cal C}\left (\mathrm {-}, \lim \limits _{\leftarrow {\cal J}} \mathscr {D} \right )\] for any \(\mathrm {-} \in {\cal C}\).
Lemma. representables preserve limits [leinster2016basic, 6.2.2] [tt-0042]
Lemma. representables preserve limits [leinster2016basic, 6.2.2] [tt-0042]
Let \(\mathscr {A}\) be a locally small category and \(X \in {\cal C}\). Then \({\cal C}(X,-): {\cal C} \to \mathbf {Set}\) preserves limits.
Proof.
It follows from Lemma [tt-003Y] and that [leinster2016basic, 6.2.1]
\[\operatorname {Cone}(X, \mathscr {D}) \cong \lim \limits _{\leftarrow {\cal J}} {\cal C}(X, \mathscr {D})\]
naturally in \(X\) and \(\mathscr {D}\).
Proof.
Lemma. limits commute with limits [leinster2016basic, 6.2.8] [tt-0047]
Lemma. limits commute with limits [leinster2016basic, 6.2.8] [tt-0047]
Let \({\cal I}\) and \({\cal J}\) be small categories. Let \({\cal C}\) be a locally small category with limits of shape \({\cal I}\) and of shape \({\cal J}\).
Define \[\begin {array}{llll} \mathscr {D}^{\bullet }: & {\cal I} & \to & {[{\cal J}, {\cal C}]} \\ & I & \mapsto & \mathscr {D}(I,-) \end {array}\] and \[\begin {array}{rrrr} \mathscr {D}_{\bullet }: & {\cal J} & \to & {[{\cal I}, {\cal C}]} \\ & J & \mapsto & \mathscr {D}(-, J) \end {array}\]
Then for all \(\mathscr {D}: {\cal I} \times {\cal J} \to {\cal C}\), we have \[ \lim _{\leftarrow {\cal J}} \lim _{\leftarrow {\cal I}} \mathscr {D}^{\bullet } \cong \lim _{\leftarrow {\cal I} {\cal J}} \mathscr {D} \cong \lim _{\leftarrow {\cal I} \leftarrow {\cal J}} \mathscr {D}_{\bullet } \] and all these limits exist. In particular, \({\cal C}\) has limits of shape \({\cal I} \times {\cal J}\).
Lemma. colimits commute with colimits [leinster2016basic, 6.2.10] [tt-0049]
Lemma. colimits commute with colimits [leinster2016basic, 6.2.10] [tt-0049]
Dual to Lemma [tt-0047], colimits commute with colimits.
Remark. [leinster2016basic, 6.2.10] [tt-004A]
Remark. [leinster2016basic, 6.2.10] [tt-004A]
Limits do not in general commute with colimits.
Some special cases where they do:
- filtered colimits commute with finite limits [stacks2017stacks, 002W].
Lemma. initial and terminal objects via adjunction [leinster2016basic, 2.1.9] [tt-0054]
Lemma. initial and terminal objects via adjunction [leinster2016basic, 2.1.9] [tt-0054]
Initial and terminal objects can be described as adjoints. Let \({\cal C}\) be a category. There exist the unique functor \(! : {\cal C} \to \mathbf {1}\), and a constant object functor \(X : 1 \to {\cal C}\) for each object \(X\).
A left adjoint to \(!\) is exactly an initial object of \({\cal C}\): \[ \mathrm {0} \dashv \ ! : \mathbf {1} \rightleftarrows {\cal C} \]
Similarly, a right adjoint to \(!\) is exactly a terminal object of \({\cal C}\): \[ ! \dashv \mathrm {1} : {\cal C} \rightleftarrows \mathbf {1} \]
Proof.
In both cases, being an adjunction gives an isomorphism for each object \(X\), one side of the isomorphism is \(\mathbf {1}(\mathrm {*}, \mathrm {*})\) which is just \(\mathit {1}_{\mathrm {*}}\), and the other side are \({\cal C}(\mathrm {0}, X)\) or \({\cal C}(X, \mathrm {1})\), and the isomorphism establishes the uniqueness of the arrows (from \(\mathrm {0}\) or to \(\mathrm {1}\)) for each object. The initial or terminal object exists if the corresponding adjunction exists.
Proof.
Lemma. (co)limits via adjunction [rosiak2022sheaf, example 200] [tt-005A]
Lemma. (co)limits via adjunction [rosiak2022sheaf, example 200] [tt-005A]
(Co)limits can be phrased entirely in terms of adjunctions:
The advantages of this adjunction perspective is that the (co)limit of every \({\cal J}\)-shaped diagram in \({\cal C}\) can be defined all at once.
Cartesian closed categories [tt-004S]
Cartesian closed categories [tt-004S]
Definition. evaluation [leinster2016basic, 6.2.4] [tt-0044]
Definition. evaluation [leinster2016basic, 6.2.4] [tt-0044]
Let \({\cal S}\) be a small category, \({\cal C}\) a locally small category. For each \(X \in {\cal S}\), there is a functor \[ \begin {array}{lccc} \operatorname {ev}_X: & [{\cal S}, {\cal C}] & \to & {\cal C} \\ & \mathscr {F} & \mapsto & \mathscr {F}(X) \end {array} \] called evaluation at \(X\).
Given a diagram \(\mathscr {D}: {\cal J} \to [{\cal S}, {\cal C}]\), we have for each \(X \in {\cal S}\) a functor \[ \begin {array}{lccc} \mathscr {D} \mathbin {\bullet } \operatorname {ev}_X : & {\cal J} & \to & {\cal C} \\ & J & \mapsto & \mathscr {D}(J)(X) \end {array} \]
We write \(\mathscr {D} \mathbin {\bullet } \operatorname {ev}_X\) as \(\mathscr {D}(-)(X)\).
Definition. cartesian product functor [kostecki2011introduction, 5.13] [tt-004F]
Definition. cartesian product functor [kostecki2011introduction, 5.13] [tt-004F]
If \({\cal C}\) is a category with binary products, we can define for every \(X\) the cartesian product functor \(X \times (-)\) : \({\cal C} \rightarrow {\cal C}\), with the following action: \[ \begin {aligned} & (X \times (-))(Y)=X \times Y \\ & (X \times (-))(f)=\operatorname {id}_X \times f \end {aligned} \]
Definition. exponential [kostecki2011introduction, 5.13] [tt-004G]
Definition. exponential [kostecki2011introduction, 5.13] [tt-004G]
If for \(X \in {\cal C}\), a cartesian product functor \(X \times (-)\) has a right adjoint, it is called an exponential or the exponential object, denoted \((-)^X\).
Explicitly, \(X \times (-) \dashv (-)^X\) means there is a natural isomorphism of bifunctors \(\operatorname {Hom}(X \times (-),-) \cong \operatorname {Hom}(-, (-)^X)\), i.e. for any arrow \(f: X \times Y \to Z\) there is a unique arrow \(f^b: Y \to Z^X\), which is the transpose of the adjunction, called exponential transpose.
The arrow \(\operatorname {ev} : X \times (-)^X \to (-)\) is called the evaluation arrow of the exponential, and is the counit of the adjunction.
Diagramatically, the diagram
We say that category \({\cal C}\) has exponentials if for any \(X \in {\cal C}\), there exists an exponential \((-)^X\).
Definition. cartesian closed category [kostecki2011introduction, 5.14] [tt-004H]
Definition. cartesian closed category [kostecki2011introduction, 5.14] [tt-004H]
A category \({\cal C}\) is called cartesian closed iff \({\cal C}\) has exponentials and has finite products.
Definition. power object [kostecki2011introduction, 6.8] [tt-004L]
Definition. power object [kostecki2011introduction, 6.8] [tt-004L]
The power object \(P(X)\) of an object \(X\) in a cartesian closed category \({\cal C}\) with subobject classifier \(\Omega \) is defined as the exponential object \(\Omega ^X\).
If \(\Omega ^X\) exists for any \(X\) in \({\cal C}\), we say that \({\cal C}\) has power objects.
Lemma. properties of cartesian closed categories [kostecki2011introduction, 5.15] [tt-004N]
For any cartesian closed category \({\cal C}\), and any objects \(X, Y, Z\) of \({\cal C}\), we have
Lemma. properties of cartesian closed categories [kostecki2011introduction, 5.15] [tt-004N]
- \(\mathrm {0} \times X \cong \mathrm {0}\) if \(\mathrm {0}\) exists in \({\cal C}\)
- \(1 \times X \cong X\)
- \(X^{\mathrm {0}} \cong \mathrm {1}\) if \(\mathrm {0}\) exists in \({\cal C}\)
- \(X^1 \cong X\)
- \(\mathrm {1}^X \cong 1\)
- \(X \times Y \cong Y \times X\)
- \((X \times Y) \times Z \cong X \times (Y \times Z)\)
- \(Y^X \times Z^X \cong (Y \times Z)^X\)
- \(Z^{X \times Y} \cong \left (Z^X\right )^Y\)
- \(X+Y \cong Y+X\)
- \((X+Y)+Z \cong X+(Y+Z)\)
- \(Z^X \times Z^Y \cong Z^{X+Y}\) if \({\cal C}\) has binary coproducts
- \((X \times Y)+(X \times Z) \cong X \times (Y+Z)\) if \({\cal C}\) has binary coproducts
Subobject classifier [tt-004T]
Subobject classifier [tt-004T]
Definition. category of elements [leinster2016basic, 6.2.16] [tt-004C]
Definition. category of elements [leinster2016basic, 6.2.16] [tt-004C]
Let \({\cal C}\) be a category and \(\mathscr {X} : {\cal C}^{op} \to \mathbf {Set}\) a presheaf on \({\cal C}\). The category of elements \({\cal E}(\mathscr {X})\) of \(\mathscr {X}\) is the category in which:
There is a projection functor \(\mathscr {P}: \mathbf {E}(\mathscr {X}) \rightarrow {\cal C}\) defined by \(\mathscr {P}(X, x) = X\) and \(\mathscr {P}(f) = f\).
The Yoneda lemma implies that for a presheaf \(\mathscr {X}\), the generalized elements of \(\mathscr {X}\) of representable shape correspond to objects of the category of elements.
Theorem. density [leinster2016basic, 6.2.17] [tt-004D]
Theorem. density [leinster2016basic, 6.2.17] [tt-004D]
Let \({\cal C}\) be a small category and \(\mathscr {X}\) a presheaf on \({\cal C}\). Then \(\mathscr {X}\) is the colimit of the diagram \[ {\cal E}(\mathscr {X}) \xrightarrow {\mathscr {P}} \mathbf {{\cal C}} \xrightarrow {H_{\bullet }}\left [\mathbf {{\cal C}}^{op}, \text { Set }\right ] \] in \(\left [\mathbf {{\cal C}}^{op}, \mathbf {Set} \right ]\), i.e. \[\mathscr {X} \cong \lim \limits _{\rightarrow {\cal E}(\mathscr {X})}\left (\mathscr {P} \mathbin {\bullet } H_{\bullet } \right )\] where \({\cal E}(\mathscr {X})\) is the category of elements, \(\mathscr {P}\) the projection functor in it, and \(H_{\bullet }\) the (contravariant) Yoneda embedding.
This theorem states that every presheaf is a colimit of representables in a canonical way. It is secretly dual to the Yoneda lemma. This becomes apparent if one expresses both in suitably lofty categorical language (that of ends, or that of bimodules).
Definition. subobject classifier [kostecki2011introduction, 6.4] [tt-004I]
Definition. subobject classifier [kostecki2011introduction, 6.4] [tt-004I]
A subobject classifier is an object \(\Omega \) in \({\cal C}\), together with an arrow \(\top : \mathbf {1} \to \Omega \), called the true arrow, such that for each monic arrow \(m: Y \mapsto X\) there is a unique arrow \(\chi : X \to \Omega \), called the characteristic arrow of \(m\) (or of \(Y\)), such that the diagram
\(\Omega \) is also called a generalized truth-value object.
The arrow \((! \mathbin {\bullet } T) : Y \stackrel {!}{\to } \mathbf {1} \rightarrowtail \Omega \) is often denoted as \(\top _Y: Y \to \Omega \).
Lemma. isomorphism to class of subobjects [kostecki2011introduction, 6.7] [tt-004K]
Lemma. isomorphism to class of subobjects [kostecki2011introduction, 6.7] [tt-004K]
In any category \({\cal C}\) with a subobject classifier \(\Omega \), \[ \operatorname {Sub}(X) \cong {\cal C}(X, \Omega ) \] i.e. the class of subobjects of an object \(X\) in \({\cal C}\) is isomorphic to the class of arrows from \(X\) to \(\Omega \).
Proof.
It follows from the definitions and Lemma [tt-003J] that for every \(f : Y \to X\) and \([f] \in \operatorname {Sub}(X)\),
Proof.
- (surjection) \(\chi (f) \in {\cal C}(X, \Omega )\)
- (injection) for every \(h : X \to \Omega \), \(\chi (f) = h\) since
is a pullback.
Definition. power object functor [kostecki2011introduction, 6.8] [tt-004M]
Definition. power object functor [kostecki2011introduction, 6.8] [tt-004M]
The contravariant power object functor \(\mathscr {P}: {\cal C}^{o p} \to {\cal C}\), given by \[\mathscr {P}: X \mapsto \Omega ^X\] for \(X \in \mathrm {Ob}({\cal C})\) and such that \(\mathscr {P}(f): \Omega ^Y \mapsto \Omega ^X\) for \(f: X \to Y\) in \({\cal C}\) is given by \[\mathscr {P}(f)(Y)=\{x \in X \mid f(x) \in Y\}\]
When power object is defined for cartesian closed categories, we have \[ \frac {X \times Y \to \Omega }{Y \to \Omega ^X} \] thus for every category with power objects \[ \operatorname {Hom}(X \times Y, \Omega ) \cong \operatorname {Hom}\left (Y, \Omega ^X\right ) \] This equation, together with Lemma [tt-004K] written in the form \(\operatorname {Sub}(X \times Y) \cong \operatorname {Hom}(X \times Y, \Omega )\), gives the isomorphism \[ \operatorname {Sub}(X \times Y) \cong \operatorname {Hom}(Y, \mathscr {P}(X)) \]
Topos theory [tt-004U]
Topos theory [tt-004U]
Definition. topos [kostecki2011introduction, 7.1] [tt-004O]
Definition. topos [kostecki2011introduction, 7.1] [tt-004O]
A topos or elementary topos is a category satisfying one of these equivalent conditions:
- it is a complete category with exponentials and subobject classifier
- it is a complete category with subobject classifier and its power object
- it is a cartesian closed category with equalizers and subobject classifier
Since the completeness of a category with subobject classifier implies its cocompleteness. Thus a topos not only has all finite limits, but also has all finite colimits.
This means that topos is such category which has, in particular,
- terminal object
- equalizers
- pullbacks
- all other limits
- exponential objects
- subobject classifier
Remark. topoi, toposes [kostecki2011introduction, 7.1] [tt-004P]
Remark. topoi, toposes [kostecki2011introduction, 7.1] [tt-004P]
The name "topos" originates from the Greek word "τoπoς", meaning a place, as topos could mean a place of geometry, and at the same time as a place of logic.
Following the ancient Greek naming convention, the plural of topos is topoi, but people also use toposes. We use them interchangeably.
Example. topos [tt-004R]
Example. topos [tt-004R]
Topos theory unifies, in an extraordinary way, important aspects of geometry and logic.
Grothendieck topos was first introduced by Grothendieck to generalize topological space [kostecki2011introduction, 7.2]:
every space gives rise to a topos (namely, the category of sheaves on it).
Topological properties of the space can be reinterpreted in a useful way as categorical properties of its associated topos.
Elementary topos was introduced by Lawvere and Tierney, to generalize Set. A topos can be regarded as a 'universe of sets' [leinster2016basic, 6.3.20]. \(\mathbf {Set}\) is the most basic example of a topos, and every topos shares enough features with Set that [⧉]
anything you really really needed to do in the category of sets can be done in any topos.
Every presheaf category, is a topos. [leinster2016basic, 6.3.27]
A topos can allow the interpretation of a higher-order logic. In particular, objects can be seen as collections of elements of a given type, subobjects are viewed as propositions. Products and coproducts are interpreted as conjunction and disjunction respectively. For an introduction, see [pitts2001categorical].
Definition. geometric morphism, Topoi [kostecki2011introduction, 7.2] [tt-004Q]
Definition. geometric morphism, Topoi [kostecki2011introduction, 7.2] [tt-004Q]
If \({\cal E}_1\) and \({\cal E}_2\) are toposes, then a geometric morphism \(\mathscr {G}: {\cal E}_1 \to {\cal E}_2\) is defined as a pair of adjoint functors \(\mathscr {G}^* \dashv \mathscr {G}_*\) between \({\cal E}_1\) and \({\cal E}_2\), such that \(\mathscr {G}^*\) preserves finite limits (i.e. is left exact), which implies \(\mathscr {G}_*\) preserves colimits (i.e. is right exact).
The category of toposes and their geometric morphisms is denoted \(\mathbf {Topoi}\).
Appendix [tt-0006]
Appendix [tt-0006]
These are my notes on:
- Category theory
- Topos theory
- Type theory
- Sheaf theory
- Differential sheaves
- SDG (Synthetic Differential Geometry)
The primary references for these notes are:
- [kostecki2011introduction] for a clean introduction from category theory to topos theory
- [leinster2016basic] for its breakdown and simplification of category theory
- [kostecki2009differential] for its introduction to SDG
- [rosiak2022sheaf] for its sheaf examples
- [mallios2015differential] for its introduction to Differential sheaves
- [rosiak2022sheaf] for its examples of sheaves
- [zhang2021type] for a friendly introduction to type theory using the language of category theory
- [chen2016infinitely] for various preliminaries on category theory
- [sterling2023models] for its introduction to models of type theory, and extensive use of string diagrams in the style of [marsden2014category]
- [fauser2004grade] for the use of Kuperberg graphical calculi over commutative diagrams
For draft notes, see Drafts for Notes on Topos Theory and Type Theory.
Notes on Clifford Algebras [ca-0001]
Notes on Clifford Algebras [ca-0001]
Readers may also check out Compendium on Spin groups.
Preliminaries [ca-000N]
Preliminaries [ca-000N]
This section introduces the algebraic environment of Clifford Algebra, covering vector spaces, groups, algebras, representations, modules, multilinear algebras, quadratic forms, filtrations and graded algebras.
The material in this section should be familiar to the readers, but it is worth reading through it to become familiar with the notation and terminology that is used, as well as their counterparts in Lean, which usually require some additional treatment, both mathematically and technically (probably applicable to other formal proof verification systems).
Details can be found in the references in corresponding section, or you may use the L∃∀N button to check the corresponding \(\textsf {Mathlib}\) document and Lean 4 source code.
In this section, we follow [jadczyk2019notes], with supplements from [garling2011clifford][chen2016infinitely], and extensive modifications to match the counterparts in Lean's \(\textsf {Mathlib}\).
basics: from groups to modules [ca-000P]
basics: from groups to modules [ca-000P]
Convention. definition style [ca-000O]
Convention. definition style [ca-000O]
In this document, we unify the informal mathematical language for a definition to:
Let \(X\) be a concept \(X\).
A concept \(Z\) is a set/pair/triple/tuple \((Z, \mathtt {op}, ...)\), satisfying:
- \(Z\) is a concept \(Y\) over \(X\) under op .
- formula for all elements in \(Z\) ( property ).
- for each element in concept \(X\), there exists element such that formula for all elements in concept \(Z\).
- op is called op name, for all elements in \(Z\), we have
- formula
- formula
By default, \(X\) is a set, op is a binary operation on \(X\).
Definition. group [garling2011clifford, 1.1] [ca-000Q]
Definition. group [garling2011clifford, 1.1] [ca-000Q]
A group is a pair \((G, *)\), satisfying:
- \((a * b) * c = a * (b * c)\) for all \(a, b, c \in G\) (associativity).
- there exists \(1 \in G\) such that \[1 * a = a * 1 = a\] for all \(a \in G\).
- for each \(a \in G\), there exists \(a^{-1} \in G\) such that \[a * a^{-1} = a^{-1} * a = 1\].
Remark. [ca-000R]
Remark. [ca-000R]
It then follows that \(1\), the identity element, is unique, and that for each \(g \in G\) the inverse \(g^{-1}\) is unique. A group G is abelian, or commutative, if \(g * h = h * g\) for all \(g, h \in G\).
Notation. product [ca-000S]
Notation. product [ca-000S]
In literatures, the binary operation of a group is usually called a product. It's denoted by juxtaposition \(g h\), and is understood to be a mapping \((g, h) \mapsto g * h\) from \(G \times G\) to \(G\).
Here we use an explicit symbol for the operation. It can be denoted multiplicatively as \(*\) in Group or additively as \(+\) in AddGroup, where the identity element will be denoted by \(1\) or \(0\), respectively.
Sometimes we use notations with subscripts (e.g. \(*_G\), \(1_G\)) to indicate where they are.
\(\textsf {Mathlib}\) encodes the mapping \(G \times G \to G\) as \(G \to G \to G\), it is understood to be \(G \to (G \to G)\), that sends \(g \in G\) to a mapping that sends \(h \in G\) to \(g * h \in G\).
Furthermore, a mathematical construct, e.g. a group, is represented by a "type", as Lean has a dependent type theory foundation, see [carneiro2019type] and [ullrich2023extensible, sec. 3.2].
Definition. monoid [ca-000T]
Definition. monoid [ca-000T]
A monoid is a pair \((R, *)\), satisfying:
- \((a * b) * c = a * (b * c)\) for all \(a, b, c \in R\) (associativity).
- there exists an element \(1 \in R\) such that \(1 * a = a * 1 = a\) for all \(a \in R\) i.e. \(1\) is the multiplicative identity (neutral element).
Definition. ring [jadczyk2019notes, 1.1] [ca-000U]
Definition. ring [jadczyk2019notes, 1.1] [ca-000U]
A ring is a triple \((R, +, *)\), satisfying:
- \(R\) is a commutative group under \(+\).
- \(R\) is a monoid under \(*\).
- for all \(a, b, c \in R\), we have
- \(a * (b + c) = a * b + a * c\)
- \((a + b) * c = a * c + b * c\)
Remark. [ca-000V]
Remark. [ca-000V]
In applications to Clifford algebras \(R\) will be always assumed to be commutative.
Definition. division ring [ca-000W]
L∃∀N
Definition. division ring [ca-000W]
L∃∀N
A division ring is a ring \((R, +, *)\), satisfying:
- \(R\) contains at least 2 elements.
- for all \(a \neq 0\) in \(R\), there exists a multiplicative inverse \(a^{-1} \in R\) such that \[ a * a^{-1} = a^{-1} * a = 1 \]
Definition. module [jadczyk2019notes, 1.3] [ca-000X]
L∃∀N
Definition. module [jadczyk2019notes, 1.3] [ca-000X]
L∃∀N
Let \(R\) be a commutative ring. A module over \(R\), called an \(R\)-module, is a pair \((M, \bullet )\), satisfying:
- M is a group under \(+\).
- \(\bullet : R \to M \to M\) is called scalar multiplication, for every \(a, b \in R\), \(x, y \in M\), we have
- \(a \bullet (x + y) = a \bullet x + b \bullet y\)
- \((a + b) \bullet x = a \bullet x + b \bullet x\)
- \(a * (b \bullet x)=(a * b) \bullet x\)
- \(1_R \bullet x = x\)
Definition. vector space [jadczyk2019notes, 1.5] [ca-000Z]
L∃∀N
Definition. vector space [jadczyk2019notes, 1.5] [ca-000Z]
L∃∀N
If \(R\) is a division ring, then a module \(M\) over \(R\) is called a vector space.
Remark. [ca-0010]
Remark. [ca-0010]
For generality, \(\textsf {Mathlib}\) uses Module throughout for vector spaces, particularly, for a vector space \(V\), it's usually declared as
/--
Let $K$ be a division ring, a module $V$ over $K$ is a vector space
where being a module requires $V$ to be a commutative group over $+$.
-/
variable [DivisionRing K] [AddCommGroup V] [Module K V]
For definitions/theorems about it, and most of them can be found under Mathlib.LinearAlgebra e.g. LinearIndependent.
Definition. submodule [ca-0011]
Definition. submodule [ca-0011]
A submodule \(N\) of \(M\) is a module \(N\) such that every element of \(N\) is also an element of \(M\). If \(M\) is a vector space then \(N\) is called a subspace.
Definition. dual module [ca-0012]
L∃∀N
Definition. dual module [ca-0012]
L∃∀N
The dual module \(M^* : M \to _{l[R]} R\) is the \(R\)-module of all linear maps from \(M\) to \(R\).
algebras [ca-0013]
algebras [ca-0013]
Definition. ring homomorphism [chen2016infinitely, 4.5.1] [ca-0014]
Definition. ring homomorphism [chen2016infinitely, 4.5.1] [ca-0014]
Let \((\alpha , +_\alpha , *_\alpha )\) and \((\beta , +_\beta , *_\beta )\) be rings. A ring homomorphism from \(\alpha \) to \(\beta \) is a map \(\mathit {1} : \alpha \to _{+*} \beta \) such that
- \(\mathit {1}(x +_{\alpha } y) = \mathit {1}(x) +_{\beta } \mathit {1}(y)\) for each \(x,y \in \alpha \).
- \(\mathit {1}(x *_{\alpha } y) = \mathit {1}(x) *_{\beta } \mathit {1}(y)\) for each \(x,y \in \alpha \).
- \(\mathit {1}(1_{\alpha }) = 1_{\beta }\).
Definition. isomorphism, endomorphism, automorphism [ca-0015]
Definition. isomorphism, endomorphism, automorphism [ca-0015]
Isomorphism \(A \cong B\) is a bijective homomorphism \(\phi : A \to B\) (it follows that \(\phi ^{-1} : B \to A\) is also a homomorphism).
Endomorphism is a homomorphism from an object to itself, denoted \(\operatorname {End}(A)\).
Automorphism is an endomorphism which is also an isomorphism, denoted \(\operatorname {Aut}(A)\).
Definition. algebra [ca-0016]
L∃∀N
Definition. algebra [ca-0016]
L∃∀N
Let \(R\) be a commutative ring. An algebra \(A\) over \(R\) is a pair \((A, \bullet )\), satisfying:
- \(A\) is a ring under \(*\).
- there exists a ring homomorphism from \(R\) to \(A\), denoted \(\mathit {1} : R \to _{+*} A\).
- \(\bullet : R \to M \to M\) is a scalar multiplication
- for every \(r \in R\), \(x \in A\), we have
- \(r * x = x * r\) (commutativity between \(R\) and \(A\))
- \(r \bullet x = r * x\) (definition of scalar multiplication)
Notation. [ca-0017]
Notation. [ca-0017]
Following literatures, for \(r \in R\),
usually we write \(\mathit {1}_A(r) : R \to _{+*} A\) as a product \(r \mathit {1}_A\) if not omitted,
while they are written as a call to
algebraMap _ _ r in \(\textsf {Mathlib}\),
which is defined to be Algebra.toRingHom r.
Remark. [ca-0018]
Remark. [ca-0018]
The definition above (adopted in \(\textsf {Mathlib}\)) is more general than the definition in literature (e.g. [jadczyk2019notes, 1.6]):
Let \(R\) be a commutative ring. An algebra \(A\) over \(R\) is a pair \((M, *)\), satisfying:
- \(A\) is a module \(M\) over \(R\) under \(+\) and \(\bullet \).
- \(A\) is a ring under \(*\).
- For \(x, y \in A, a \in R\), we have \[ a \bullet (x * y) = (a \bullet x) * y = x * (a \bullet y) \]
See Implementation notes in Algebra for details.
Remark. [ca-0019]
Remark. [ca-0019]
What's simply called algebra is actually associative algebra with identity, a.k.a. associative unital algebra. See the red herring principle for more about such phenomenon for naming, particularly the example of (possibly) nonassociative algebra.
Definition. algebra homomorphism [ca-001A]
L∃∀N
Definition. algebra homomorphism [ca-001A]
L∃∀N
Let \(A\) and \(B\) be \(R\)-algebras. \(\mathit {1}_A\) and \(\mathit {1}_B\) are ring homomorphisms from \(R\) to \(A\) and \(B\), respectively. A algebra homomorphism from \(A\) to \(B\) is a map \(f : \alpha \to _{a} \beta \) such that
- \(f\) is a ring homomorphism
- \(f(\mathit {1}_{A}(r)) = \mathit {1}_{B}(r)\) for each \(r \in R\)
Definition. ring quotient [ca-001B]
L∃∀N
Definition. ring quotient [ca-001B]
L∃∀N
Let \(R\) be a non-commutative ring, \(r\) an arbitrary equivalence relation on \(R\). The ring quotient of \(R\) by \(r\) is the quotient of \(R\) by the strengthen equivalence relation of \(r\) such that for all \(a, b, c\) in \(R\):
- \(a + c \sim b + c\) if \(a \sim b\)
- \(a * c \sim b * c\) if \(a \sim b\)
- \(a * b \sim a * c\) if \(b \sim c\)
Remark. [ca-001C]
Remark. [ca-001C]
As ideals haven't been formalized for the non-commutative case, \(\textsf {Mathlib}\) uses RingQuot in places where the quotient of non-commutative rings by ideal is needed. The universal properties of the quotient are proven, and should be used instead of the definition that is subject to change.
Definition. free algebra [ca-001D]
Definition. free algebra [ca-001D]
Let \(X\) be an arbitrary set. An free \(R\)-algebra on \(X\) (or "generated by \(X\)"), named \(A\), is the ring quotient of the following inductively constructed set \(A_{\mathtt {pre}}\)
- for all \(x\) in \(X\), there exists a map \(X \to A_{\mathtt {pre}}\).
- for all \(r\) in \(R\), there exists a map \(R \to A_{\mathtt {pre}}\).
- for all \(a, b\) in \(A_{\mathtt {pre}}\), \(a + b\) is in \(A_{\mathtt {pre}}\).
- for all \(a, b\) in \(A_{\mathtt {pre}}\), \(a * b\) is in \(A_{\mathtt {pre}}\).
- there exists a ring homomorphism from \(R\) to \(A_{\mathtt {pre}}\), denoted \(R \to _{+*} A_{\mathtt {pre}}\).
- \(A\) is a commutative group under \(+\).
- \(A\) is a monoid under \(*\).
- left and right distributivity under \(*\) over \(+\).
- \(0 * a \sim a * 0 \sim 0\).
- for all \(a, b, c\) in \(A\), if \(a \sim b\), we have
- \(a + c \sim b + c\)
- \(c + a \sim c + b\)
- \(a * c \sim b * c\)
- \(c * a \sim c * b\)
Definition. linear map [ca-001F]
L∃∀N
Definition. linear map [ca-001F]
L∃∀N
Let \(R, S\) be rings, \(M\) an \(R\)-module, \(N\) an \(S\)-module. A linear map from \(M\) to \(N\) is a function \(f : M \to _{l} N\) over a ring homomorphism \(\sigma : R \to _{+*} S\), satisfying:
- \(f(x + y) = f(x) + f(y)\) for all \(x, y \in M\).
- \(f(r \bullet x) = \sigma (r) \bullet f(x)\) for all \(r \in R\), \(x \in M\).
Remark. Lin [ca-001G]
Remark. Lin [ca-001G]
The set of all linear maps from \(M\) to \(M'\) is denoted \(\operatorname {Lin}(M, M')\), and \(\operatorname {Lin}(M)\) for mapping from \(M\) to itself. \(\operatorname {Lin}(M)\) is an endomorphism.
Definition. tensor algebra [ca-001H]
L∃∀N
Definition. tensor algebra [ca-001H]
L∃∀N
Let \(A\) be a free \(R\)-algebra generated by module \(M\), let \(\iota : M \to A\) denote the map from \(M\) to \(A\). An tensor algebra over \(M\) (or "of \(M\)") \(T\) is the ring quotient of the free \(R\)-algebra generated by \(M\), by the equivalence relation satisfying:
- for all \(a, b\) in \(M\), \(\iota (a + b) \sim \iota (a) + \iota (b)\).
- for all \(r\) in \(R\), \(a\) in \(M\), \(\iota (r \bullet a) \sim r * \iota (a)\).
Remark. [ca-001I]
Remark. [ca-001I]
The definition above is equivalent to the following definition in literature (e.g. [jadczyk2019notes, 1.7]):
Let \(M\) be a module over \(R\). An algebra \(T\) is called a tensor algebra over \(M\) (or "of \(M\)") if it satisfies the following universal properties:
- \(T\) is an algebra containing \(M\) as a submodule, and it is generated by \(M\),
- Every linear mapping \(\lambda \) of \(M\) into an algebra \(A\) over \(R\), can be extended to a homomorphism \(\theta \) of \(T\) into \(A\).
Forms [ca-000L]
Forms [ca-000L]
Definition. Bilinear form [ca-0003]
L∃∀N
Definition. Bilinear form [ca-0003]
L∃∀N
Let \(R\) be a ring, \(M\) an \(R\)-module.
An bilinear form \(B\) over \(M\) is a map \(B : M \to M \to R\), satisfying:
- \( B(x + y, z) = B(x, z) +B(y, z) \)
- \( B(x, y + z) = B(x, y) +B(x, z) \)
- \( B(a \bullet x, y) = a * B(x, y)\)
- \( B(x, a \bullet y) = a * B(x, y)\)
Definition. quadratic form [jadczyk2019notes, 1.9] [ca-0004]
Definition. quadratic form [jadczyk2019notes, 1.9] [ca-0004]
Let \(R\) be a commutative ring, \(M\) a \(R\)-module.
An quadratic form \(Q\) over \(M\) is a map \(Q : M \to R\), satisfying:
- \( Q(a \bullet x) = a * a * Q(x)\) for all \(a \in R, x \in M\).
- there exists a companion bilinear form \(B : M \to M \to R\), such that \(Q(x + y) = Q(x) + Q(y) + B(x, y)\)
In [jadczyk2019notes], the bilinear form is denoted \(\Phi \), and called the polar form associated with the quadratic form \(Q\), or simply the polar form of \(Q\).
Remark. [ca-0005]
Remark. [ca-0005]
This notion generalizes to commutative semirings using the approach in [izhakian2016supertropical].
Clifford Algebra [ca-000M]
Clifford Algebra [ca-000M]
Here we provide a detailed account of the formalization of Clifford Algebra [hestenes2012clifford] in the Lean 4 theorem prover and programming language [moura2021lean][moura2015lean][ullrich2023extensible] and using its Mathematical Library \(\textsf {Mathlib}\) [mathlib2020lean].
The primary references of the formalization are [wieser2022formalizing] and [wieser2024formalizing]. This section and the previous section are adapted from our [wieser2024blueprint].
Notes on Clifford Algebras › Definition [ca-000F]
Notes on Clifford Algebras › Definition [ca-000F]
Definition. Clifford algebra [wieser2022formalizing] [ca-0006]
Definition. Clifford algebra [wieser2022formalizing] [ca-0006]
Let \(M\) be a module over a commutative ring \(R\), equipped with a quadratic form \(Q: M \to R\).
Let \(\iota : M \to _{l[R]} T(M)\) be the canonical \(R\)-linear map for the tensor algebra \(T(M)\).
Let \(\mathit {1} : R \to _{+*} T(M)\) be the canonical map from \(R\) to \(T(M)\), as a ring homomorphism.
A Clifford algebra over \(Q\), denoted \(\mathcal {C}\kern -2pt\ell (Q)\), is the ring quotient of the tensor algebra \(T(M)\) by the equivalence relation satisfying \(\iota (m)^2 \sim \mathit {1}(Q(m))\) for all \(m \in M\).
The natural quotient map is denoted \(\pi : T(M) \to \mathcal {C}\kern -2pt\ell (Q)\) in some literatures, or \(\pi _\Phi \)/\(\pi _Q\) to emphasize the bilinear form \(\Phi \) or the quadratic form \(Q\), respectively.
Remark. [ca-0007]
Remark. [ca-0007]
In literatures, \(M\) is often written \(V\), and the quotient is taken by the two-sided ideal \(I_Q\) generated from the set \(\{ v \otimes v - Q(v) \vert v \in V \}\). See also Clifford algebra [pr-spin].
As of writing, \(\textsf {Mathlib}\) does not have direct support for two-sided ideals, but it does support the equivalent operation of taking the ring quotient by a suitable closure of a relation like \(v \otimes v \sim Q(v)\).
Hence the definition above.
Remark. [ca-0008]
Remark. [ca-0008]
This definition and what follows in \(\textsf {Mathlib}\) is initially presented in [wieser2022formalizing], some further developments are based on [grinberg2016clifford], and in turn based on [bourbaki2007algebra] which is in French and never translated to English.
The most informative English reference on [bourbaki2007algebra] is [jadczyk2019notes], which has an updated exposition in [jadczyk2023bundle].
Example. Clifford algebra over a vector space [ca-0009]
Example. Clifford algebra over a vector space [ca-0009]
Let \(V\) be a vector space \(\mathbb R^n\) over \(\mathbb R\), equipped with a quadratic form \(Q\).
Since \(\mathbb R\) is a commutative ring and \(V\) is a module, the definition above applies.
Definition. Clifford map [wieser2022formalizing] [ca-000A]
L∃∀N
Definition. Clifford map [wieser2022formalizing] [ca-000A]
L∃∀N
We denote the canonical \(R\)-linear map to the Clifford algebra \(\mathcal {C}\kern -2pt\ell (M)\) by \(\iota : M \to _{l[R]} \mathcal {C}\kern -2pt\ell (M)\).
It's denoted \(i_\Phi \) or just \(i\) in some literatures.
Definition. Clifford lift [wieser2022formalizing] [ca-000B]
L∃∀N
Definition. Clifford lift [wieser2022formalizing] [ca-000B]
L∃∀N
Given a linear map \(f : M \to _{l[R]} A\) into an \(R\)-algebra \(A\), satisfying \(f(m)^2 = Q(m)\) for all \(m \in M\), called is Clifford, the canonical lift of \(f\) is defined to be a algebra homomorphism from \(\mathcal {C}\kern -2pt\ell (Q)\) to \(A\), denoted \(\operatorname {lift} f : \mathcal {C}\kern -2pt\ell (Q) \to _{a} A\).
Theorem. Universal property [wieser2022formalizing] [ca-000C]
Theorem. Universal property [wieser2022formalizing] [ca-000C]
Given \(f : M \to _{l[R]} A\), which is Clifford, \(F = \operatorname {lift} f\) (denoted \(\bar {f}\) in some literatures), we have:
\(F \circ \iota = f\), i.e. the following diagram commutes:
\(\operatorname {lift}\) is unique, i.e. given \(G : \mathcal {C}\kern -2pt\ell (Q) \to _{a} A\), we have: \[ G \circ \iota = f \iff G = \operatorname {lift} f\]
Remark. [ca-000D]
Remark. [ca-000D]
The universal property of the Clifford algebras is now proven, and should be used instead of the definition that is subject to change.
Definition. Exterior algebra [wieser2022formalizing] [ca-000E]
L∃∀N
Definition. Exterior algebra [wieser2022formalizing] [ca-000E]
L∃∀N
An Exterior algebra over \(M\) is the Clifford algebra \(\mathcal {C}\kern -2pt\ell (Q)\) where \(Q(m) = 0\) for all \(m \in M\).
Notes on Clifford Algebras › Operations [ca-000G]
Notes on Clifford Algebras › Operations [ca-000G]
Convention. [wieser2022formalizing] [ca-000H]
Convention. [wieser2022formalizing] [ca-000H]
Same as the previous section, let \(M\) be a module over a commutative ring \(R\), equipped with a quadratic form \(Q: M \to R\).
We also use \(m\) or \(m_1, m_2, \dots \) to denote elements of \(M\), i.e. vectors, and \(x, y, z\) to denote elements of \(\mathcal {C}\kern -2pt\ell (Q)\).
Definition. Grade involution [wieser2022formalizing] [ca-000I]
Definition. Grade involution [wieser2022formalizing] [ca-000I]
Grade involution, intuitively, is negating each basis vector.
Formally, it's an algebra homomorphism \(\alpha : \mathcal {C}\kern -2pt\ell (Q) \to _{a} \mathcal {C}\kern -2pt\ell (Q)\), satisfying:
- \(\alpha \circ \alpha = \operatorname {id}\)
- \(\alpha (\iota (m)) = - \iota (m)\)
for all \(m \in M\).
That is, the following diagram commutes:
It's called main involution \(\alpha \) or main automorphism in [jadczyk2019notes], the canonical automorphism in [gallier2008clifford].
It's denoted \(\hat {m}\) in [lounesto2001clifford], \(\alpha (m)\) in [jadczyk2019notes], \(m^*\) in [chisolm2012geometric].
Definition. Grade reversion [wieser2022formalizing] [ca-000J]
Definition. Grade reversion [wieser2022formalizing] [ca-000J]
Grade reversion, intuitively, is reversing the multiplication order of basis vectors. Formally, it's an algebra homomorphism \(\tau : \mathcal {C}\kern -2pt\ell (Q) \to _{a} \mathcal {C}\kern -2pt\ell (Q)^{\mathtt {op}}\), satisfying:
- \(\tau (m_1 m_2) = \tau (m_2) \tau (m_1)\)
- \(\tau \circ \tau = \operatorname {id}\)
- \(\tau (\iota (m)) = \iota (m)\)
That is, the following diagram commutes:
It's called anti-involution \(\tau \) in [jadczyk2019notes], the canonical anti-automorphism in [gallier2008clifford], also called transpose/transposition in some literature, following tensor algebra or matrix.
It's denoted \(\tilde {m}\) in [lounesto2001clifford], \(m^\tau \) in [jadczyk2019notes] (with variants like \(m^t\) or \(m^\top \) in other literatures), \(m^\dagger \) in [chisolm2012geometric].
Definition. Clifford conjugate [wieser2022formalizing] [ca-000K]
Definition. Clifford conjugate [wieser2022formalizing] [ca-000K]
Clifford conjugate is an algebra homomorphism \({*} : \mathcal {C}\kern -2pt\ell (Q) \to _{a} \mathcal {C}\kern -2pt\ell (Q)\), denoted \(x^{*}\) (or even \(x^\dagger \), \(x^v\) in some literatures), defined to be: \[ x^{*} = \operatorname {reverse}(\operatorname {involute}(x)) = \tau (\alpha (x)) \] for all \(x \in \mathcal {C}\kern -2pt\ell (Q)\), satisfying (as a \(*\)-ring):
- \((x + y)^{*} = (x)^{*} + (y)^{*}\)
- \((x y)^{*} = (y)^{*} (x)^{*}\)
- \({*} \circ {*} = \operatorname {id}\)
- \(1^{*} = 1\)
Note: In our current formalization in \(\textsf {Mathlib}\), the application of the involution on \(r\) is ignored, as there appears to be nothing in the literature that advocates doing this.
Clifford conjugate is denoted \(\bar {m}\) in [lounesto2001clifford] and most literatures, \(m^\ddagger \) in [chisolm2012geometric].
Compendium on Spin groups [spin-0001]
- April 26, 2024
- Utensil Song
Compendium on Spin groups [spin-0001]
- April 26, 2024
- Utensil Song
Motivation [spin-000R]
Motivation [spin-000R]
This survey is built on my notes in the process of figuring out Eric Wieser's MathOverflow question Definition of a spin group for our PR to Lean 4's Mathlib about Spin groups.
This is my first Forester experiment, also a spiritual successor to my writeup The Many Faces of Geometric Algebra.
Our definition [spin-000X]
Our definition [spin-000X]
Definition. Clifford algebra [pr-spin] [ca-0002]
Definition. Clifford algebra [pr-spin] [ca-0002]
Let \(M\) be a module over a commutative ring \(R\), equipped with a quadratic form \(Q: M \to R\).
A Clifford algebra over \(Q\) is \[ \mathcal {C}\kern -2pt\ell (Q) \equiv T(M)/I_Q \] where \(T(M)\) is the tensor algebra of \(M\), \(I_Q\) is the two-sided ideal generated from the set \[ \{ m \otimes m - Q(m) \mid m \in M \}. \]
We denote the canonical linear map \(M \to \mathcal {C}\kern -2pt\ell (Q)\) as \(\iota _Q\).
Definition. Lipschitz-Clifford group [pr-spin] [spin-000W]
Definition. Lipschitz-Clifford group [pr-spin] [spin-000W]
The Lipschitz-Clifford group is defined as the subgroup closure of all the invertible elements in the form of \(\iota _Q(m)\), \[ \Gamma \equiv \left \{ x_1 \ldots x_k \in \mathcal {C}\kern -2pt\ell ^{\times }(Q) \mid x_i \in V \right \} \] where \[ \mathcal {C}\kern -2pt\ell ^{\times }(Q) \equiv \left \{ x \in \mathcal {C}\kern -2pt\ell (Q) \mid \exists x^{-1} \in \mathcal {C}\kern -2pt\ell (Q), x^{-1} x = x x^{-1}=1\right \} \] is the group of units (i.e. invertible elements) of \(\mathcal {C}\kern -2pt\ell (Q)\), \[ V \equiv \left \{ \iota _Q(m) \in \mathcal {C}\kern -2pt\ell (Q) \mid m \in M \right \} \] is the subset \(V\) of \(\mathcal {C}\kern -2pt\ell (Q)\) in the form of \(\iota _Q(m)\).
Definition. Pin group [pr-spin] [spin-000Y]
L∃∀N
Definition. Pin group [pr-spin] [spin-000Y]
L∃∀N
The Pin group is defined as \[ \operatorname {Pin}(Q) \equiv \Gamma \sqcap \operatorname {U}(\mathcal {C}\kern -2pt\ell (Q)) \] where \(\sqcap \) is the infimum (or greatest lower bound, or meet), and the infimum of two submonoids is just their intersection \(\cap \), \[ \operatorname {U}(S) \equiv \left \{ x \in S \mid x^{*} * x = x * x^{*} = 1 \right \} \] are the unitary elements of the Clifford algebra as a \(*\)-monid, and we have defined the star operation of Clifford algebra as Clifford conjugate [wieser2022formalizing], denoted \(\bar {x}\).
This definition is equivalent to the following: \[ \operatorname {Pin}(Q) \equiv \left \{ x \in \Gamma \mid \operatorname {N}(x) = 1 \right \} \] where \[ \operatorname {N}(x) \equiv x \bar {x}. \]
Definition. Spin group [pr-spin] [spin-0012]
L∃∀N
Definition. Spin group [pr-spin] [spin-0012]
L∃∀N
The Spin group is defined as \[ \operatorname {Spin}(Q) \equiv \operatorname {Pin}(Q) \sqcap \mathcal {C}\kern -2pt\ell ^{+}(Q) \] where \(\mathcal {C}\kern -2pt\ell ^{+}(Q)\) is the even subalgebra of the Clifford algebra.
Appendix: Many faces of Spin group [spin-000Z]
Appendix: Many faces of Spin group [spin-000Z]
Definitions coming from different sources are simply quoted here with minimal modifications, to include immediate prerequisites, and omit some discussions or theorems.
They are not classified, ordered, or pruned by similarity.
Definition. Spin group [lawson2016spin] [spin-0002]
Definition. Spin group [lawson2016spin] [spin-0002]
Let \(V\) be a vector space over the commutative field \(k\) and suppose \(q\) is a quadratic form on \(V\).
We now consider the multiplicative group of units in the Clifford algebra \(C \ell (V, q)\) associated to \(V\), which is defined to be the subset \[ C \ell ^{\times }(V, q) \equiv \left \{\varphi \in C \ell (V, q): \exists \varphi ^{-1} \text { with } \varphi ^{-1} \varphi =\varphi \varphi ^{-1}=1\right \} \]This group contains all elements \(v \in V\) with \(q(v) \neq 0\).
The group of units always acts naturally as automorphisms of the algebra. That is, there is a homomorphism \[ \mathrm {Ad}: \mathrm {C} \ell ^{\times }(V, q) \longrightarrow \operatorname {Aut}(\mathrm {C} \ell (V, q)) \] called the adjoint representation, which is given by \[ \operatorname {Ad}_{\varphi }(x) \equiv \varphi \times \varphi ^{-1} \] The Pin group of \((V, q)\) is the subgroup \(\operatorname {Pin}(V, q)\) of \(\mathrm {P}(V, q)\) generated by the elements \(v \in V\) with \(q(v)= \pm 1\). The associated Spin group of \((V, q)\) is defined by \[ \operatorname {Spin}(V, q)=\operatorname {Pin}(V, q) \cap C \ell ^0(V, q) . \]
Definition. Spin group [wiki2024clifford] [spin-0003]
The pin group \(\operatorname {Pin}_V(K)\) is the subgroup of the Lipschitz group \(\Gamma \) of elements of spinor norm 1, and similarly the spin group \(\operatorname {Spin}_V(K)\) is the subgroup of elements of Dickson invariant 0 in \(\operatorname {Pin}_V(K)\).
Definition. Spin group [wiki2024clifford] [spin-0003]
Definition. Spin group [li2008invariant] [spin-0004]
Definition. Spin group [li2008invariant] [spin-0004]
A versor refers to a Clifford monomial composed of invertible vectors. It is called a rotor, or spinor, if the number of vectors is even. It is called a unit versor if its magnitude is 1.
All versors in \(\mathcal {C L}\left (\mathcal {V}^n\right )\) form a group under the geometric product, called the versor group, also known as the Clifford group, or Lipschitz group. All rotors form a subgroup, called the rotor group. All unit versors form a subgroup, called the pin group, and all unit rotors form a subgroup, called the spin group, denoted by \(\operatorname {Spin}\left (\mathcal {V}^n\right )\).
Definition. Spin group [sommer2013geometric] [spin-0005]
The Clifford group \(\Gamma _{\mathrm {p}, \mathrm {q}}\) of a Clifford algebra \(\mathcal {C}_{p, q}\) is defined as
\[
\Gamma _{\mathrm {p}, \mathrm {q}}:=\left \{s \in \mathcal {C}_{p, q} \mid \forall x \in \mathbb {R}_{p, q}: s x \hat {s}^{-1} \in \mathbb {R}_{p, q}\right \} .
\]
From that definition we get immediately
\[
\Gamma _{\mathrm {p}, \mathrm {q}} \times \mathbb {R}_{p, q} \rightarrow \mathbb {R}_{p, q} ; \quad (s, x) \mapsto s x \hat {s}^{-1}
\]
as the operation of the Clifford group \(\Gamma _{\mathrm {p}, \mathrm {q}}\) on \(\mathbb {R}_{p, q}\).
\(\Gamma _{\mathrm {p}, \mathrm {q}}\) is a multiple cover of the orthogonal group \(O(p, q)\). However, it is still unnecessarily large. Therefore, we first reduce \(\Gamma _{\mathrm {p}, \mathrm {q}}\) to a two-fold cover of \(O(p, q)\) by defining the so-called Pin group
\[
\operatorname {Pin}(\mathrm {p}, \mathrm {q}):=\left \{s \in \Gamma _{\mathrm {p}, \mathrm {q}} \mid s \tilde {s}= \pm 1\right \} .
\]
The even elements of \(\operatorname {Pin}(p, q)\) form the spin group
\[
\operatorname {Spin}(\mathrm {p}, \mathrm {q}):=\operatorname {Pin}(\mathrm {p}, \mathrm {q}) \cap \mathcal {C}_{p, q}^{+}
\]
which is a double cover of the special orthogonal group \(S O(p, q)\). Finally, those elements of \(\operatorname {Spin}(\mathrm {p}, \mathrm {q})\) with Clifford norm equal 1 form a further subgroup
\[
\operatorname {Spin}_{+}(\mathrm {p}, \mathrm {q}):=\{s \in \operatorname {Spin}(\mathrm {p}, \mathrm {q}) \mid s \tilde {s}=1\}
\]
that covers \(\mathrm {SO}_{+}(p, q)\) twice. Thereby, \(\mathrm {SO}_{+}(p, q)\) is the connected component of the identity of \(O(p, q)\).
Definition. Spin group [sommer2013geometric] [spin-0005]
Definition. Spin group [perwass2009geometric] [spin-0006]
Definition. Spin group [perwass2009geometric] [spin-0006]
A versor is a multivector that can be expressed as the geometric product of a number of non-null 1-vectors. That is, a versor \(\boldsymbol {V}\) can be written as \(\boldsymbol {V}=\prod _{i=1}^k \boldsymbol {n}_i\), where \(\left \{\boldsymbol {n}_1, \ldots , \boldsymbol {n}_k\right \} \subset \mathbb {G}_{p, q}^{\varnothing 1}\) with \(k \in \mathbb {N}^{+}\), is a set of not necessarily linearly independent vectors.
The subset of versors of \(\mathbb {G}_{p, q}\) together with the geometric product, forms a group, the Clifford group, denoted by \(\mathfrak {G}_{p, q}\).
A versor \(\boldsymbol {V} \in \mathfrak {G}_{p, q}\) is called unitary if \(\boldsymbol {V}^{-1}=\tilde {\boldsymbol {V}}\), i.e. \(\boldsymbol {V} \widetilde {\boldsymbol {V}}=+1\).
The set of unitary versors of \(\mathfrak {G}_{p, q}\) forms a subgroup \(\mathfrak {P}_{p, q}\) of the Clifford group \(\mathfrak {G}_{p, q}\), called the pin group.
A versor \(\boldsymbol {V} \in \mathfrak {G}_{p, q}\) is called a spinor if it is unitary \((\boldsymbol {V} \tilde {\boldsymbol {V}}=1)\) and can be expressed as the geometric product of an even number of 1-vectors. This implies that a spinor is a linear combination of blades of even grade.
The set of spinors of \(\mathfrak {G}_{p, q}\) forms a subgroup of the pin group \(\mathfrak {P}_{p, q}\), called the spin group, which is denoted by \(\mathfrak {S}_{p, q}\).
Definition. Spin group [jadczyk2019notes] [spin-0007]
Definition. Spin group [jadczyk2019notes] [spin-0007]
We define the Clifford group \(\Gamma =\Gamma (q)\) to be the group of all invertible elements \(u \in \mathrm {Cl}(q)\) which have the property that \(uyu^{-1}\) is in \(M\) whenever \(y\) is in \(M\). We define \(\Gamma (q)^{ \pm }\)as the intersection of \(\Gamma (q)\) and \(\mathrm {Cl}(q)_{ \pm }\).
For every element \(u \in \Gamma (q)\) we define the spinor norm \(N(u)\) by the formula \[ N(u)=\tau (u) u, \] where \(\tau \) is the main involution of the Clifford algebra \(\mathrm {Cl}(q)\). The following groups are called spin groups: \[ \begin {aligned} & \operatorname {Pin}(q):=\left \{s \in \Gamma (q)^{+} \cup \Gamma (q)^{-}: N(s)= \pm 1\right \} \\ & \operatorname {Spin}(q):=\left \{s \in \Gamma (q)^{+}: N(s)= \pm 1\right \} \\ & \operatorname {Spin}^{+}(q):=\left \{s \in \Gamma (q)^{+}: N(s)=+1\right \} . \end {aligned} \]
Definition. Spin group [garling2011clifford] [spin-0008]
Suppose that \((E, q)\) is a regular quadratic space. We consider the action of \(\mathcal {G}(E, q)\) on \(\mathcal {A}(E, q)\) by adjoint conjugation. We set
\[
A d_g^{\prime }(a)=g a g^{-1},
\]
for \(g \in \mathcal {G}(E, q)\) and \(a \in \mathcal {A}(E, q)\).
We restrict attention to those elements of \(\mathcal {G}(E, q)\) which stabilize \(E\). The Clifford group \(\Gamma =\Gamma (E, q)\) is defined as
\[
\left \{g \in \mathcal {G}(E, q): A d_g^{\prime }(x) \in E \text { for } x \in E\right \} .
\]
If \(g \in \Gamma (E, q)\), we set \(\alpha (g)(x)=A d_g^{\prime }(x)\). Then \(\alpha (g) \in G L(E)\), and \(\alpha \) is a homomorphism of \(\Gamma \) into \(G L(E) . \alpha \) is called the graded vector representation of \(\Gamma \).
It is customary to scale the elements of \(\Gamma (E, q)\); we set
\[
\begin {aligned}
\operatorname {Pin}(E, q) & =\{g \in \Gamma (E, q): \Delta (g)= \pm 1\}, \\
\Gamma _1(E, q) & =\{g \in \Gamma (E, q): \Delta (g)=1\} .
\end {aligned}
\]
If \((E, q)\) is a Euclidean space, then \(\operatorname {Pin}(E, q)=\Gamma _1(E, q)\); otherwise, \(\Gamma _1(E, q)\) is a subgroup of \(\operatorname {Pin}(E, q)\) of index 2.
We have a short exact sequence
\[
1 \longrightarrow D_2 \xrightarrow {\subseteq } \operatorname {Pin}(E, q) \xrightarrow {\alpha } O(E, q) \longrightarrow 1 ;
\]
\(\operatorname {Pin}(E, q)\) is a double cover of \(O(E, q)\).
In fact there is more interest in the subgroup \(\operatorname {Spin}(E, q)\) of \(\operatorname {Pin}(E, q)\) consisting of products of an even number of unit vectors in \(E\). Thus \(\operatorname {Spin}(E, q)=\operatorname {Pin}(E, q) \cap \mathcal {A}^{+}(E, q)\) and
\[
\operatorname {Spin}(E, q)=\left \{g \in \mathcal {A}^{+}(E, q): g E=E g \text { and } \Delta (g)= \pm 1\right \} .
\]
If \(x, y\) are unit vectors in \(E\) then \(\alpha (x y)=\alpha (x) \alpha (y) \in S O(E, q)\), so that \(\alpha (\operatorname {Spin}(E, q)) \subseteq S O(E, q)\). Conversely, every element of \(S O(E, q)\) is the product of an even number of simple reflections, and so \(S O(E, q) \subseteq \alpha \left (\operatorname {Spin}(E, q)\right )\). Thus \(\alpha \left (\operatorname {Spin}(E, q)\right )=S O(E, q)\), and we have a short exact sequence.
\[
1 \longrightarrow D_2 \xrightarrow {\subseteq } \operatorname {Spin}(E, q) \xrightarrow {\alpha } S O(E, q) \longrightarrow 1 ;
\]
\(\operatorname {Spin}(E, q)\) is a double cover of \(S O(E, q)\).
Note also that if \(a \in \operatorname {Spin}(E, q)\) and \(x \in E\) then \(\alpha (a)(x)=a x a^{-1}\); conjugation and adjoint conjugation by elements of \(\operatorname {Spin}(E, q)\) are the same.
Definition. Spin group [garling2011clifford] [spin-0008]
Definition. Spin group [meinrenken2009lie] [spin-0009]
Definition. Spin group [meinrenken2009lie] [spin-0009]
Recall that \(\Pi : \mathrm {Cl}(V) \rightarrow \) \(\mathrm {Cl}(V), x \mapsto (-1)^{|x|} x\) denotes the parity automorphism of the Clifford algebra. Let \(\mathrm {Cl}(V)^{\times }\)be the group of invertible elements in \(\mathrm {Cl}(V)\).
The Clifford group \(\Gamma (V)\) is the subgroup of \(\mathrm {Cl}(V)^{\times }\), consisting of all \(x \in \mathrm {Cl}(V)^{\times }\) such that \(A_x(v):=\Pi (x) v x^{-1} \in V\) for all \(v \in V \subset \mathrm {Cl}(V)\).
Hence, by definition the Clifford group comes with a natural representation, \(\Gamma (V) \rightarrow \mathrm {GL}(V), x \mapsto A_x\). Let \(S \Gamma (V)=\Gamma (V) \cap \mathrm {Cl}^{\overline {0}}(V)^{\times }\)denote the special Clifford group.
The canonical representation of the Clifford group takes values in \(\mathrm {O}(V)\), and defines an exact sequence, \[ 1 \longrightarrow \mathbb {K}^{\times } \longrightarrow \Gamma (V) \longrightarrow \mathrm {O}(V) \longrightarrow 1 . \] It restricts to a similar exact sequence for the special Clifford group, \[ 1 \longrightarrow \mathbb {K}^{\times } \longrightarrow S \Gamma (V) \longrightarrow \mathrm {SO}(V) \longrightarrow 1 . \] The elements of \(\Gamma (V)\) are all products \(x=v_1 \cdots v_k\) where \(v_1, \ldots , v_k \in V\) are non-isotropic. \(S \Gamma (V)\) consists of similar products, with \(k\) even. The corresponding element \(A_x\) is a product of reflections: \[ A_{v_1 \cdots v_k}=R_{v_1} \cdots R_{v_k} . \]Suppose \(\mathbb {K}=\mathbb {R}\). The Pin group \(\operatorname {Pin}(V)\) is the preimage of \(\{1,-1\}\) under the norm homomorphism \(N: \Gamma (V) \rightarrow \mathbb {K}^{\times }\). Its intersection with \(S \Gamma (V)\) is called the Spin group, and is denoted \(\operatorname {Spin}(V)\).
Since \(N(\lambda )=\lambda ^2\) for \(\lambda \in \mathbb {K}^{\times }\), the only scalars in \(\operatorname {Pin}(V)\) are \(\pm 1\). Hence, the exact sequence for the Clifford group restricts to an exact sequence, \[ 1 \longrightarrow \mathbb {Z}_2 \longrightarrow \operatorname {Pin}(V) \longrightarrow \mathrm {O}(V) \longrightarrow 1, \] so that \(\operatorname {Pin}(V)\) is a double cover of \(\mathrm {O}(V)\). Similarly, \[ 1 \longrightarrow \mathbb {Z}_2 \longrightarrow \operatorname {Spin}(V) \longrightarrow \mathrm {SO}(V) \longrightarrow 1, \] defines a double cover of \(\mathrm {SO}(V)\). Elements in \(\operatorname {Pin}(V)\) are products \(x=\) \(v_1 \cdots v_k\) with \(B\left (v_i, v_i\right )= \pm 1\). The group \(\operatorname {Spin}(V)\) consists of similar products, with \(k\) even.
Definition. Spin group [weber2013lie] [spin-000A]
Definition. Spin group [weber2013lie] [spin-000A]
The "group of units" in \(C l_{p, q}\), denoted \(C l_{p, q}^{\times }\), is the group of all invertible elements.
An important subgroup of \(C l^{\times }(V, q)\) is the group \(P(V, q)\) generated by elements \(v \in V\) with \(q(v) \neq 0\). Quotienting out by constants, we obtain the Pin group. Specifically, \(\operatorname {Pin}(V, q)\) (or \(\operatorname {Pin}_{p, q}\) ) is the group generated by elements \(v \in V\) with \(q(v)= \pm 1\). Further define the spin groups to be \[ \operatorname {Spin}(V, q)=\operatorname {Pin}(V, q) \cap C l^0(V, q) . \]
Definition. Spin group [bar2011spin] [spin-000B]
We define the Pin \(\operatorname {group} \operatorname {Pin}(\boldsymbol {n})\) by
\[
\operatorname {Pin}(n):=\left \{v_1 \cdot \ldots \cdot v_m \in \mathrm {Cl}_n \mid v_j \in S^{n-1} \subset \mathbb {R}^n, m \in \mathbb {N}_0\right \}
\]
We define the Spin group \(\operatorname {Spin}(\boldsymbol {n})\) by
\[
\begin {aligned}
\operatorname {Spin}(n) & :=\operatorname {Pin}(n) \cap \mathrm {Cl}_n^0 \\
& =\left \{v_1 \cdot \ldots \cdot v_m \in \mathrm {Cl}_n \mid v_j \in S^{n-1}, m \in 2 \mathbb {N}_0\right \}
\end {aligned}
\]
Definition. Spin group [bar2011spin] [spin-000B]
Definition. Spin group [woit2012lie] [spin-000C]
- April 29, 2024
Definition. Spin group [woit2012lie] [spin-000C]
- April 29, 2024
There are several equivalent possible ways to go about defining the \(\operatorname {Spin}(n)\) groups as groups of invertible elements in the Clifford algebra.
1. One can define \(\operatorname {Spin}(n)\) in terms of invertible elements \(\tilde {g}\) of \(C_{\text {even }}(n)\) that leave the space \(V=\mathbf {R}^n\) invariant under conjugation \[ \tilde {g} V \tilde {g}^{-1} \subset V \] 2. One can show that, for \(v, w \in V\), \[ v \rightarrow v-2 \frac {Q(v, w)}{Q(w, w)} w=-w v w / Q(w, w)=w v w^{-1} \] is reflection in the hyperplane perpendicular to \(w\). Then \(\operatorname {Pin}(n)\) is defined as the group generated by such reflections with \(||w||^2=1\) . \(\operatorname {Spin}(n)\) is the subgroup of \(\operatorname {Pin}(n)\) of even elements. Any rotation can be implemented as an even number of reflections (Cartan-Dieudonné) theorem.3. One can define the Lie algebra of \(\operatorname {Spin}(n)\) in terms of quadratic elements of the Clifford algebra.
Definition. Spin group [liu2016lie] [spin-000D]
The space of quadratic vectors in \(\mathrm {Cl}\) is the Lie algebra of \(\mathrm {SO}(n)\). The corresponding Lie group, called the Spin group \(\operatorname {Spin}(Q)\), is the set of invertible elements \(x \in \mathrm {Cl}\) that preserve \(V\) under \(v \mapsto x v x^{-1}\). Clearly this map is in \(\mathrm {SO}(V, Q)\) since it preserves the quadratic form \(Q\), and is a two-fold cover with kernel \(\pm 1\).
Definition. Spin group [liu2016lie] [spin-000D]
Definition. Spin group [figueroa2010spin] [spin-000E]
Definition. Spin group [figueroa2010spin] [spin-000E]
The Pin group Pin \((V)\) of \((V, Q)\) is the subgroup of (the group of units of) \(C \ell (V)\) generated by \(v \in \mathrm {V}\) with \(\mathrm {Q}(v)= \pm 1\). In other words, every element of \(\operatorname {Pin}(\mathrm {V})\) is of the form \(u_1 \cdots u_r\) where \(u_i \in \mathrm {V}\) and \(\mathrm {Q}\left (u_i\right )= \pm 1\). We will write \(\operatorname {Pin}(s, t)\) for \(\operatorname {Pin}\left (\mathbb {R}^{s, t}\right )\) and \(\operatorname {Pin}(n)\) for \(\operatorname {Pin}(n, 0)\).
The spin group of \((V, Q)\) is the intersection \[ \operatorname {Spin}(V)=\operatorname {Pin}(V) \cap C \ell (V)_0 . \] Equivalently, it consists of elements \(u_1 \cdots u_{2 p}\), where \(u_i \in \mathrm {V}\) and \(\mathrm {Q}\left (u_i\right )= \pm 1\). We will write \(\operatorname {Spin}(s, t)\) for \(\operatorname {Spin}\left (\mathbb {R}^{s, t}\right )\) and \(\operatorname {Spin}(n)\) for \(\operatorname {Spin}(n, 0)\).
Definition. Spin group [lundholm2009clifford] [spin-000F]
We identify the following groups embedded in \(\mathcal {G}\) :
\[
\begin {aligned}
\mathcal {G}^{\times } &:=\{x \in \mathcal {G}: \exists y \in \mathcal {G}: x y=y x=1\} & \text { the group of all invertible elements } \\
\tilde {\Gamma } &:=\left \{x \in \mathcal {G}^{\times }: x^{\star } V x^{-1} \subseteq V\right \} & \text { the Lipschitz group } \\
\Gamma &:=\left \{v_1 v_2 \ldots v_k \in \mathcal {G}: v_i \in V^{\times }\right \} & \text { the versor group } \\
\text { Pin } &:=\left \{x \in \Gamma : x x^{\dagger } \in \{-1,1\}\right \} & \text { the group of unit versors } \\
\text { Spin } &:=\operatorname {Pin} \cap \mathcal {G}^{+} & \text { the group of even unit versors } \\
\operatorname {Spin}^{+} &:=\left \{x \in \operatorname {Spin}: x x^{\dagger }=1\right \} & \text { the rotor group } \\
\end {aligned}
\]
In the above, \(V^{\times }:=\left \{v \in V: v^2 \neq 0\right \}\) denotes the set of all invertible vectors.
Definition. Spin group [lundholm2009clifford] [spin-000F]
Definition. Spin group [renaud2020clifford] [spin-000G]
Definition. Spin group [renaud2020clifford] [spin-000G]
The Clifford group \(\Gamma (p, q)\) is the (multiplicative) group generated by invertible 1-vectors in \(R^{p, q}\).
The Pin group \(\operatorname {Pin}(p, q)\). \[ \operatorname {Pin}(p, q)=\{g \in \Gamma (p, q): g \widetilde {g}= \pm 1\} . \] So if \(g \in \operatorname {Pin}(p, q), \widetilde {g}\) is a scalar multiple of \(g^{-1}\). This is not true for arbitrary elements of \(\Gamma (p, q)\). The Spin group \(\operatorname {Spin}(p, q)\). This is the subgroup of \(\operatorname {Pin}(p, q)\) consisting of even elements only, i.e. \[ \operatorname {Spin}(p, q)=\operatorname {Pin}(p, q) \cap C l^{+}(p, q) . \] The \(\operatorname {Spin}\) group \(\operatorname {Spin}(p, q)\) has the further subgroup \[ \operatorname {Spin}^{\dagger }(p, q)=\{g \in \operatorname {Spin}(p, q): g \widetilde {g}=+1\} . \] \(\operatorname {Pin}(p, q)\), \(\operatorname {Spin}(p, q)\) and \(\operatorname {Spin}^{\dagger }(p, q)\) are respectively the two-fold covering groups of \(O(p, q), S O(p, q)\) and \(S O^{\dagger }(p, q)\) (where \(S O^{\dagger }(p, q)\) is the connected component of \(S O(p, q)\) ).
Definition. Spin group [dutailly2018clifford] [spin-000H]
Definition. Spin group [dutailly2018clifford] [spin-000H]
The Spin group \(\operatorname {Spin}(F, \rho )\) of \(C l(F, \rho )\) is the subset of \(C l(F, \rho )\) whose elements can be written as the product \(g=u_1 \cdot \ldots \cdot u_{2 p}\) of an even number of vectors of \(F\) of norm \(\left \langle u_k, u_k\right \rangle =1\).
As a consequence : \(\langle g, g\rangle =1, g^t \cdot g=1\) and \(\operatorname {Spin}(F, \rho ) \subset O(C l)\).
The scalars \(\pm 1\) belong to the Spin group. The identity is \(+1 . \operatorname {Spin}(F, \rho )\) is a connected Lie group.
Definition. Spin group [hitzer2012introduction] [spin-000I]
Definition. Spin group [hitzer2012introduction] [spin-000I]
A versor refers to a Clifford monomial (product expression) composed of invertible vectors. It is called a rotor, or spinor, if the number of vectors is even. It is called a unit versor if its magnitude is 1.
Every versor \(A=a_1 \ldots a_r, \quad a_1, \ldots , a_r \in \mathbb {R}^2, r \in \mathbb {N}\) has an inverse \[ A^{-1}=a_r^{-1} \ldots a_1^{-1}=a_r \ldots a_1 /\left (a_1^2 \ldots a_r^2\right ), \] such that \[ A A^{-1}=A^{-1} A=1 . \]This makes the set of all versors in \(C l(2,0)\) a group, the so called Lipschitz group with symbol \(\Gamma (2,0)\), also called Clifford group or versor group. Versor transformations apply via outermorphisms to all elements of a Clifford algebra. It is the group of all reflections and rotations of \(\mathbb {R}^2\).
The normalized subgroup of versors is called pin group \[ \operatorname {Pin}(2,0)=\{A \in \Gamma (2,0) \mid A \widetilde {A}= \pm 1\} . \] In the case of \(C l(2,0)\) we have \[ \begin {aligned} & \operatorname {Pin}(2,0) \\ & =\left \{a \in \mathbb {R}^2 \mid a^2=1\right \} \cup \left \{A \mid A=\cos \varphi +e_{12} \sin \varphi , \varphi \in \mathbb {R}\right \} . \end {aligned} \] The pin group has an even subgroup, called spin group \[ \operatorname {Spin}(2,0)=\operatorname {Pin}(2,0) \cap C l^{+}(2,0) . \] The spin group has in general a spin plus subgroup \[\operatorname {Spin}_{+}(2,0)=\{A \in \operatorname {Spin}(2,0) \mid A \widetilde {A}=+1\}.\]
Definition. Spin group [hahn2004clifford] [spin-000J]
Definition. Spin group [hahn2004clifford] [spin-000J]
We continue to let \(F\) be a field of characteristic not 2 and \(M\) a quadratic space over \(F\).
Recall that \(\gamma : M \rightarrow C(M)\) is injective and that there is a unique involution - on \(C(M)\) taking \(\gamma x\) to \(\gamma x\) for all \(x\). Consider \(M\) to be a subset of \(C(M)\) via \(\gamma \), and define the group \(\operatorname {Spin}(M)\) by \[ \operatorname {Spin}(M)=\left \{c \in C_0(M)^{\times } \mid c M c^{-1}=M, c \bar {c}=1_C\right \}, \] where \(C_0(M)^{\times }\)is the group of invertible elements of the \(\operatorname {ring} C_0(M)\). The isometries from \(M\) onto \(M\) constitute the orthogonal group \(O(M)\) and \(S O(M)\) is the subgroup of elements of determinant 1. For \(c\) in \(\operatorname {Spin}(M)\), define \[ \pi c: M \rightarrow M \] by \(\pi c(x)=c x c^{-1}\). This provides a homomorphism \[ \pi : \operatorname {Spin}(M) \rightarrow S O(M) . \] By a theorem of Cartan and Dieudonné, any element \(\sigma \) in \(O(M)\) is a product \(\sigma =\tau _{y_1} \cdots \tau _{y_k}\) of hyperplane reflections \(\tau _{y_i}\). The assignment \(\Theta (\sigma )=\) \(q\left (y_1\right ) \cdots q\left (y_k\right )\left (F^{\times }\right )^2\) defines the spinor norm homomorphism \[ \Theta : S O(M) \rightarrow F^{\times } /\left (F^{\times }\right )^2 . \]
Definition. Spin group [porteous1995clifford] [spin-000K]
Let \(g\) be an invertible element of a universal Clifford algebra \(A\) such that, for each \(x \in X, g x \widehat {g}^{-1} \in X\). Then the map
\[
\rho _{X, g}: x \mapsto g x \widehat {g}^{-1}
\]
is an orthogonal automorphism of \(X\).
Definition. Spin group [porteous1995clifford] [spin-000K]
The element \(g\) will be said to induce or represent the orthogonal transformation \(\rho _{X, g}\) and the set of all such elements \(g\) will be denoted by \(\Gamma (X)\) or simply by \(\Gamma \).
The subset \(\Gamma \) is a subgroup of \(A\).
The group \(\Gamma \) is called the Clifford group (or Lipschitz group) for \(X\) in the Clifford algebra \(A\). Since the universal algebra \(A\) is uniquely defined up to isomorphism, \(\Gamma \) is also uniquely defined up to isomorphism.
An element \(g\) of \(\Gamma (X)\) represents a rotation of \(X\) if and only if \(g\) is the product of an even number of elements of \(X\). The set of such elements will be denoted by \(\Gamma ^0=\Gamma ^0(X)\). An element \(g\) of \(\Gamma \) represents an anti-rotation of \(X\) if and only if \(g\) is the product of an odd number of elements of \(X\). The set of such elements will be denoted by \(\Gamma ^1=\Gamma ^1(X)\). Clearly, \(\Gamma ^0=\Gamma \cap A^0\) is a subgroup of \(\Gamma \), while \(\Gamma ^1=\Gamma \cap A^1\).
The Clifford group \(\Gamma (X)\) of a quadratic space \(X\) is larger than is necessary if our interest is in representing orthogonal transformations of \(X\). Use of a quadratic norm \(N\) on the Clifford algebra \(A\) leads to the definition of subgroups of \(\Gamma \) that are less redundant for this purpose. This quadratic norm \(N: A \rightarrow A\) is defined by the formula \[ N(a)=a^{-} a, \text { for any } a \in A, \] For \(X\) and \(\Gamma =\Gamma (X)\) as above we now define \[ \operatorname {Pin} X=\{g \in \Gamma :|N(g)|=1\} \text { and } \operatorname {Spin} X=\left \{g \in \Gamma ^0:|N(g)|=1\right \} \text {. } \]
Definition. Spin group [rosen2019geometric] [spin-000L]
Definition. Spin group [rosen2019geometric] [spin-000L]
Let \(V\) be an inner product space. We denote by \(\Delta V\) the standard Clifford algebra \((\wedge V,+, \Delta )\) defined by the Clifford product \(\Delta \) on the space of multivectors in \(V\).
Let \(V\) be an inner product space. The Clifford cone of \(V\) is the multiplicative group \(\widehat {\triangle } V \subset \triangle V\) generated by nonsingular vectors, that is, vectors \(v\) such that \(\langle v\rangle ^2 \neq 0\). More precisely, \(q \in \widehat {\triangle } V\) if there are finitely many nonsingular vectors \(v_1, \ldots , v_k \in V\) such that \[ q=v_1 \Delta \cdots \Delta v_k . \]Let \(w \in \triangle V\). Then \(w \in \widehat {\triangle } V\) if and only if \(w\) is invertible and \(\widehat {w} v w^{-1} \in V\) for all \(v \in V\).
In this case \(w\) can be written as a product of at most \(\operatorname {dim} V\) nonsingular vectors, and \(\bar {w} w=w \bar {w} \in \mathbf {R} \backslash \{0\}\).
Let \(V\) be an inner product space. Define the orthogonal, special orthogonal, pin, and spin groups \[ \begin {aligned} \mathrm {O}(V) & :=\{\text { isometries } T: V \rightarrow V\} \subset \mathcal {L}(V), \\ \mathrm {SO}(V) & :=\{T \in \mathrm {O}(V) ; \operatorname {det} T=+1\} \subset \mathcal {L}(V), \\ \operatorname {Pin}(V) & :=\left \{q \in \widehat {\triangle } V ;\langle q\rangle ^2= \pm 1\right \} \subset \triangle V, \\ \operatorname {Spin}(V) & :=\left \{q \in \operatorname {Pin}(V) ; q \in \triangle ^{\mathrm {ev}} V\right \} \subset \triangle ^{\mathrm {ev}} V . \end {aligned} \] We call \(T \in \operatorname {SO}(V)\) a rotation and we call \(q \in \operatorname {Spin}(V)\) a rotor.
Definition. Spin group [ruhe2024clifford] [spin-000M]
Motivation E. 39 (The problem of generalizing the definition of the Spin group). For a positive definite quadratic form \(\mathfrak {q}\) on the real vector space \(V=\mathbb {R}^n\) with \(n \geq 3\) the \(\operatorname {Spin}\) group \(\operatorname {Spin}(n)\) is defined via the kernel of the Spinor norm (=extended quadratic form on \(\mathrm {Cl}(V, \mathfrak {q})\) ) restricted to the special Clifford group \(\Gamma ^{[0]}(V, \mathfrak {q})\) :
\[
\operatorname {Spin}(n):=\operatorname {ker}\left (\overline {\mathfrak {q}}: \Gamma ^{[0]}(V, \mathfrak {q}) \rightarrow \mathbb {R}^{\times }\right )=\left \{w \in \Gamma ^{[0]}(V, \mathfrak {q}) \mid \overline {\mathfrak {q}}(w)=1\right \}=\left .\overline {\mathfrak {q}}\right |_{\Gamma ^{[0]}(V, \mathfrak {q})} ^{-1}(1) .
\]
\(\operatorname {Spin}(n)\) is thus a normal subgroup of the special Clifford group \(\Gamma ^{[0]}(V, \mathfrak {q})\), and, as it turns out, a double cover of the special orthogonal group \(\mathrm {SO}(n)\) via the twisted conjugation \(\rho \). The latter can be summarized by the short exact sequence:
\[
1 \longrightarrow \{ \pm 1\} \xrightarrow {\text { incl }} \operatorname {Spin}(n) \xrightarrow {\rho } \mathrm {SO}(n) \longrightarrow 1 .
\]
Definition. Spin group [ruhe2024clifford] [spin-000M]
We intend to generalize this in several directions: 1. from Spin to Pin group, 2. from \(\mathbb {R}^n\) to vector spaces \(V\) over general fields \(\mathbb {F}\) with \(\operatorname {ch}(\mathbb {F}) \neq 2\), 3. from non-degenerate to degenerate quadratic forms \(\mathfrak {q}\), 4. from positive (semi-)definite to non-definite quadratic forms \(\mathfrak {q}\). This comes with several challenges and ambiguities.
Definition E. 40 (The real Pin group and the real Spin group). Let \(V\) be a finite dimensional \(\mathbb {R}\)-vector space \(V, \operatorname {dim} V=n<\infty \), and \(\mathfrak {q} a\) (possibly degenerate) quadratic form on \(V\). We define the (real) Pin group and (real) Spin group, resp., of \((V, \mathfrak {q})\) as the following subquotients of the Clifford group. \(\Gamma (V, \mathfrak {q})\) and its even parity part \(\Gamma ^{[0]}(V, \mathfrak {q})\), resp.: \[ \begin {aligned} \operatorname {Pin}(V, \mathfrak {q}) & :=\{x \in \Gamma (V, \mathfrak {q}) \mid \overline {\mathfrak {q}}(x) \in \{ \pm 1\}\} / \bigwedge ^{[*]}(\mathcal {R}) \\ \operatorname {Spin}_{\infty }(V, \mathfrak {q}) & :=\left \{x \in \Gamma ^{[0]}(V, \mathfrak {q}) \mid \overline {\mathfrak {q}}(x) \in \{ \pm 1\}\right \} / \bigwedge ^{[*]}(\mathcal {R}) \end {aligned} \] Corollary E.41. Let \((V, \mathfrak {q})\) be a finite dimensional quadratic vector space over \(\mathbb {R}\). Then the twisted conjugation induces a well-defined and surjective group homomorphism onto the group of radical preserving orthogonal automorphisms of \((V, \mathfrak {q})\) : \[ \rho : \operatorname {Pin}(V, \mathfrak {q}) \rightarrow \mathrm {O}_{\mathcal {R}}(V, \mathfrak {q}), \] with kernel: \[ \operatorname {ker}\left (\rho : \underset {\sim \text { in }}{\operatorname {Pin}}(V, \mathfrak {q}) \rightarrow \mathrm {O}_{\mathcal {R}}(V, \mathfrak {q})\right )=\{ \pm 1\} . \] Correspondingly, for the \(\operatorname {Spin}(V, \mathfrak {q})\) group. In short, we have short exact sequences: \[ \begin {aligned} & 1 \longrightarrow \{ \pm 1\} \xrightarrow {\text { incl }} \operatorname {Pin}(V, \mathfrak {q}) \xrightarrow {\rho } \mathrm {O}_{\mathcal {R}}(V, \mathfrak {q}) \longrightarrow 1, \\ & 1 \longrightarrow \{ \pm 1\} \xrightarrow {\text { incl }} \operatorname {Spin}(V, \mathfrak {q}) \xrightarrow {\rho } \operatorname {SO}_{\mathcal {R}}(V, \mathfrak {q}) \longrightarrow 1 . \end {aligned} \]
Definition. Spin group [gallier2014clifford] [spin-000N]
Every Clifford algebra \(\mathrm {Cl}(\Phi )\) possesses a canonical anti-automorphism \(t: \mathrm {Cl}(\Phi ) \rightarrow \mathrm {Cl}(\Phi )\) satisfying the properties
\[
t(x y)=t(y) t(x), \quad t \circ t=\mathrm {id}, \quad \text { and } \quad t(i(v))=i(v),
\]
for all \(x, y \in \mathrm {Cl}(\Phi )\) and all \(v \in V\). Furthermore, such an anti-automorphism is unique.
Every Clifford algebra \(\mathrm {Cl}(\Phi )\) has a unique canonical automorphism \(\alpha : \mathrm {Cl}(\Phi ) \rightarrow \mathrm {Cl}(\Phi )\) satisfying the properties
\[
\alpha \circ \alpha =\mathrm {id}, \quad \text { and } \quad \alpha (i(v))=-i(v),
\]
for all \(v \in V\).
First, we define conjugation on a Clifford algebra \(\mathrm {Cl}(\Phi )\) as the map
\[
x \mapsto \bar {x}=t(\alpha (x)) \text { for all } x \in \mathrm {Cl}(\Phi ) .
\]
Given a finite dimensional vector space \(V\) and a quadratic form \(\Phi \) on \(V\), the Clifford group of \(\Phi \) is the group
\[
\Gamma (\Phi )=\left \{x \in \mathrm {Cl}(\Phi )^* \mid \alpha (x) v x^{-1} \in V \quad \text { for all } v \in V\right \} .
\]
The map \(N: \mathrm {Cl}(Q) \rightarrow \mathrm {Cl}(Q)\) given by
\[
N(x)=x \bar {x}
\]
is called the norm of \(\mathrm {Cl}(\Phi )\).
Definition. Spin group [gallier2014clifford] [spin-000N]
We also define the group \(\Gamma ^{+}(\Phi )\), called the special Clifford group, by \[ \Gamma ^{+}(\Phi )=\Gamma (\Phi ) \cap \mathrm {Cl}^0(\Phi ) . \]
We define the pinor group \(\operatorname {Pin}(p, q)\) as the group \[ \operatorname {Pin}(p, q)=\left \{x \in \Gamma _{p, q} \mid N(x)= \pm 1\right \}, \] and the spinor group \(\operatorname {Spin}(p, q)\) as \(\operatorname {Pin}(p, q) \cap \Gamma _{p, q}^{+}\).The restriction of \(\rho : \Gamma _{p, q} \rightarrow \mathbf {G L}(n)\) to the pinor group \(\operatorname {Pin}(p, q)\) is a surjective homomorphism \(\rho : \mathbf {P i n}(p, q) \rightarrow \mathbf {O}(p, q)\) whose kernel is \(\{-1,1\}\), and the restriction of \(\rho \) to the spinor group \(\mathbf {S p i n}(p, q)\) is a surjective homomorphism \(\rho : \mathbf {S p i n}(p, q) \rightarrow \mathbf {S O}(p, q)\) whose kernel is \(\{-1,1\}\).
Remark: According to Atiyah, Bott and Shapiro, the use of the name \(\operatorname {Pin}(k)\) is a joke due to Jean-Pierre Serre (Atiyah, Bott and Shapiro Clifford modules, page 1).
Definition. Spin group [fulton2013representation] [spin-000O]
Instead of defining the spin group as the set of products of certain elements of \(V\), it will be convenient to start with a more abstract definition. Set
\[
\operatorname {Spin}(Q)=\left \{x \in C(Q)^{\text {even }}: x \cdot x^*=1 \text { and } x \cdot V \cdot x^* \subset V\right \} \text {. }
\]
We see from this definition that \(\operatorname {Spin}(Q)\) forms a closed subgroup of the group of units in the (even) Clifford algebra. Any \(x\) in \(\operatorname {Spin}(Q)\) determines an endomorphism \(\rho (x)\) of \(V\) by
\[
\rho (x)(v)=x \cdot v \cdot x^*, \quad v \in V .
\]
Define a larger subgroup, this time of the multiplicative group of \(C(Q)\), by
\[
\operatorname {Pin}(Q)=\left \{x \in C(Q): x \cdot x^*=1 \text { and } x \cdot V \cdot x^* \subset V\right \},
\]
and define a homomorphism
\[
\rho : \operatorname {Pin}(Q) \rightarrow \mathrm {O}(Q), \quad \rho (x)(v)=\alpha (x) \cdot v \cdot x^*,
\]
where \(\alpha : C(O) \rightarrow C(O)\) is the main involution.
Definition. Spin group [fulton2013representation] [spin-000O]
Definition. Spin group [wiki2023spin] [spin-000P]
Definition. Spin group [wiki2023spin] [spin-000P]
The pin group \(\operatorname {Pin}(V)\) is a subgroup of \(\mathrm {Cl}(V)\) 's Clifford group of all elements of the form \[ v_1 v_2 \cdots v_k \] where each \(v_i \in V\) is of unit length: \(q\left (v_i\right )=1\).
The spin group is then defined as \[ \operatorname {Spin}(V)=\operatorname {Pin}(V) \cap \mathrm {Cl}^{\text {even }}, \] where \(\mathrm {Cl}^{\text {even }}=\mathrm {Cl}^0 \oplus \mathrm {Cl}^2 \oplus \mathrm {Cl}^4 \oplus \cdots \) is the subspace generated by elements that are the product of an even number of vectors. That is, \(\operatorname {Spin}(V)\) consists of all elements of \(\operatorname {Pin}(V)\), given above, with the restriction to \(k\) being an even number. The restriction to the even subspace is key to the formation of two-component (Weyl) spinors, constructed below.
Definition. Spin group [nlab2023spin] [spin-000Q]
Definition. Spin group [nlab2023spin] [spin-000Q]
The Pin group \(\operatorname {Pin}(V ; q)\) of a quadratic vector space, is the subgroup of the group of units in the Clifford algebra \(\mathrm {Cl}(V, q)\) \[ \operatorname {Pin}(V, q) \hookrightarrow \operatorname {GL}_1(\mathrm {Cl}(V, q)) \] on those elements which are multiples \(v_1 \cdots v_n\) of elements \(v_i \in V\) with \(q\left (v_i\right )=1\).
The Spin group \(\operatorname {Spin}(V, q)\) is the further subgroup of \(\operatorname {Pin}(V ; q)\) on those elements which are even number multiples \(v_1 \cdots v_{2 k}\) of elements \(v_i \in V\) with \(q\left (v_i\right )=1\).
Definition. Spin group [dereli2010degenerate] [spin-000T]
The group \(\operatorname {Spin}(p, q)\) is defined by
\[
\operatorname {Spin}(p, q)=\left \{v_1 \ldots v_m \in \mathcal {C} \ell _{p, q} \mid m \in 2 \mathbb {Z}^{+}, v_i=\sum _{j=1}^{p+q} a_{i j} e_j,\left \langle v_i, v_i\right \rangle =\mp 1,1 \leq i \leq m\right \}
\]
Definition. Spin group [dereli2010degenerate] [spin-000T]
Definition. Degenerate Spin group [dereli2010degenerate] [spin-000U]
The subset of \(\mathcal {C} \ell _{p, q, r}\) defined by
\[
S_{p, q, r}=\left \{s \gamma _1 \ldots \gamma _{p+q}(1+G) \mid s \in \operatorname {Spin}(p, q), \gamma _i=1+e_i \sum _{l=1}^r c_{i l} f_l, G \in \Lambda (f)\right \}
\]
is a group under the Clifford multiplication where \(\left \langle \cdot , \cdot \right \rangle \) is a symmetric bilinear form on \(\mathbb {R}^{p+q+r}\), \(\left \{e_1, \ldots , e_p, e_{p+1}, \ldots , e_{p+q}, f_1, \ldots , f_r\right \}\) is the algebra basis for the degenerate Clifford algebra \(\mathcal {C} \ell _{p, q, r}=\mathcal {C} \ell \left (\mathbb {R}^n,\langle \rangle \right )\), \(1 \leq i \leq p+q, c_{i l} \in \mathbb {R}\), and \(\Lambda (f)\) is defined by
\[
\Lambda (f)=\operatorname {Span}\left \{f_{k_1} \ldots f_{k_j} \mid 1 \leq k_1<k_2<\ldots <k_j \leq r\right \} .
\]
Definition. Degenerate Spin group [dereli2010degenerate] [spin-000U]
Translation of Bourbaki on Clifford algebras [uts-000C]
- September 2, 2020
- Utensil Song
Translation of Bourbaki on Clifford algebras [uts-000C]
- September 2, 2020
- Utensil Song
disclaimer
- September 2, 2020
- Utensil Song
disclaimer
- September 2, 2020
- Utensil Song
This is a manual translation of a portion of Chapitre 9 Formes sesquilinéaires et formes quadratiques of Bourbaki's Éléments de Mathématique [bourbaki2007algebra] from French to English.
Such a translation is not available eleswhere, to the best of our knowledge. We claim no rights to the original text, and all mistakes in the translation are our own. The translation is for educational purposes only.
So far, we have only translated the portion that is related to Clifford algebras, namely § 9. Clifford Algebra. The translation is still in progress.
editorial remarks
- September 2, 2020
- Utensil Song
editorial remarks
- September 2, 2020
- Utensil Song
We always keep the original notation, and the numbering of equations, definitions, propositions, sections etc.
Equation labels are placed on the right side of the equations unlike the original text where they are placed on the left side.
We add a proof block for each proof, to make the proof stand out.
For the Web version, the original text can revealed by clicking the "earth" button in the top-right corner.
§ 9. Clifford Algebra 🇫🇷 § 9. Algèbres de Clifford
- September 2, 2020
- Utensil Song
§ 9. Clifford Algebra 🇫🇷 § 9. Algèbres de Clifford
- September 2, 2020
- Utensil Song
In this paragraph, we will assume the ring \(A\) to be commutative. We will designate by Q a quadratic form over the \(A\)-module \(E\), and by \(\Phi \) the associated bilinear form (§ 3, \(n^{\circ }\) 4). 🇫🇷 Dans ce paragraphe, nous supposerons l'anneau \(A\) commutatif. Nous désignerons par Q une forme quadratique sur le \(A\)-module \(E\), et par \(\Phi \) la forme bilinéaire associée (§ 3, \(n^{\circ }\) 4).
Translation of Bourbaki on Clifford algebras › 1. Definition and universal property of Clifford Algebra 🇫🇷 1. Définition et propriété universelle de l'algèbre de Clifford.
- September 2, 2020
- Utensil Song
Translation of Bourbaki on Clifford algebras › 1. Definition and universal property of Clifford Algebra 🇫🇷 1. Définition et propriété universelle de l'algèbre de Clifford.
- September 2, 2020
- Utensil Song
Definition 1. - We call Clifford algebra of \(Q\), denoted \(C(Q)\), the quotient of the tensor algebra \(T(E)\) of the module \(E\) by the two-sided ideal, denoted \(I(Q)\), generated by the elements of the form \(x \otimes x - Q(x) . 1 \quad (x \in E)\). 🇫🇷 Définition 1. - On appelle algèbre de Clifford de \(Q\) et on note \(C(Q)\) l'algèbre quotient de l'algèbre tensorielle \(T(E)\) du module \(E\) par l'idéal bilatère (noté \(I(Q)\)) engendré par les éléments de la forme \(x \otimes x - Q(x) . 1 \quad (x \in E)\).
We will denote by \(\rho _{\tiny Q}\) (or simply \(\rho \) when there is no risk of confusion) the mapping of \(E\) into \(C(Q)\) composed of the canonical mapping of \(E\) into \(T(E)\) and of the canonical mapping \(\sigma \) of \(T(E)\) onto \(C(Q)\); the mapping \(\rho _{\tiny Q}\) is said to be canonical. 🇫🇷 Nous noterons \(\rho _{e}\) (ou simplement \(\rho \) quand aucune confusion n'est à craindre) l'application de E dans \(C(Q)\) composée de l'application canonique de \(E\) dans \(T(E)\) et de l'application canonique \(\sigma \) de \(T(E)\) sur \(C(Q)\); l'application \(\rho _{\tiny Q}\) est dite canonique .
Note that \(C(Q)\) is generated by \(\rho _{\tiny Q}(E)\), and that, for \(x \in E\), we have \[\rho (x)^{2} = Q(x) . 1 ; \tag{1}\] hence, replacing \(x\) by \(x + y\) (\(x, y\) in \(E\)): \[\rho (x) \rho (y) + \rho (y) \rho (x) = \Phi (x, y) . 1 \tag{2}\] 🇫🇷 Remarquons que \(C(Q)\) est engendrée par \(\rho _{\tiny Q}(E)\), et que, pour \(x \in E\), on a \[\rho (x)^{2} = Q(x) . 1 ; \tag{1}\] d'où, en remplaçant \(x\) par \(x + y\) (\(x, y\) dans \(E\)): \[\rho (x) \rho (y) + \rho (y) \rho (x) = \Phi (x, y) . 1 \tag{2}\]
Example: If \(E\) admits a base composed of a single element \(e\), \(T(E)\) is isomorphic to the polynomial algebra \(A[X]\), and \(C(Q)\) is a quadratic extension of \(A\), based on \((1, u)\), where \(u\) is the element \(u = \rho (e)\) and satisfies \(u^{2} = Q(e)\). 🇫🇷 Exemple. Si \(E\) admet une base composée d'un seul élément \(e\), \(T(E)\) est isomorphe à l'algèbre de polynômes \(A[X]\), et \(C(Q)\) est une extension quadratique de \(A\), ayant pour base \((1, u)\), où \(u\) est l'élément \(u = \rho (e)\) et vérifie \(u^{2} = Q(e)\).
We denote \(T^{h}\) the \(h\)-th tensor power \(\bigotimes \limits ^{h} E\) in \(T(E)\), and \(T^{+}\) (resp. \(T^{-}\)) being the sum of the \(T^{h}\) for even (resp. odd) number of \(h\). 🇫🇷 Notons \(T^{h}\) la puissance tensorielle \(h\)-ème \(\bigotimes \limits ^{h} E\) dans \(T(E)\), et soit \(T^{+}\) (resp. \(T^{-}\)) la somme des \(T^{h}\) pour \(h\) pair (resp. impair).
Since \(T(E)\) is a direct sum of \(T^{+}\) and \(T^{-}\), and \(I(Q)\) is generated by elements of \(T^{+}\), \(I(Q)\) is a direct sum of \(T^{+} \cap I(Q)\) and \(T^{-} \cap I(Q)\), and \(C(Q)\) is a direct sum of the two submodules \(C^{+}(Q) = \sigma (T^{+})\) and \(C^{-}(Q) = \sigma (T^{-})\) (also denoted \(C^{+}\) and \(C^{-}\)). The elements of \(C^{+}\) are called even (resp. odd). 🇫🇷 Comme \(T(E)\) est somme directe de \(T^{+}\) et \(T^{-}\), et \(I(Q)\) est engendré par des éléments de \(T^{+}\), \(I(Q)\) est somme directe de \(T^{+} \cap I(Q)\) et \(T^{-} \cap I(Q)\), et \(C(Q)\) est somme directe des deux sous-modules \(C^{+}(Q) = \sigma (T^{+})\) et \(C^{-}(Q) = \sigma (T^{-})\) (que l'on note aussi \(C^{+}\) et \(C^{-}\)). Les éléments de \(C^{+}\) seront dits pairs (resp. impairs).
We have the relations \[C^{+} C^{+} \subset C^{+}, \quad C^{+} C^{-} \subset C^{-}, \quad C^{-} C^{+} \subset C^{-}, \quad C^{-} C^{-} \subset C^{+}. \tag{3}\] In particular \(C^{+}\) is a subalgebra of \(C(Q)\). 🇫🇷 On a les relations \[C^{+} C^{+} \subset C^{+}, \quad C^{+} C^{-} \subset C^{-}, \quad C^{-} C^{+} \subset C^{-}, \quad C^{-} C^{-} \subset C^{+}. \tag{3}\] En particulier \(C^{+}\) est une sous-algèbre de \(C(Q)\).
Proposition 1. - Let \(f\) be a linear map of \(E\) in an algebra \(D\) over \(A\) such that \(f(x)^{2} = Q(x) . 1\) for all \(x \in E\). There is one and only one homomorphism \(\bar {f}\) of \(C(Q)\) into \(D\) such that \(f = \bar {f} \circ \rho _{\tiny Q}\). 🇫🇷 Proposition 1. - Soit \(f\) une application linéaire de \(E\) dans une algèbre \(D\) sur \(A\) telle que \(f(x)^{2} = Q(x) . 1\) pour tout \(x \in E\). Il existe un homomorphisme \(\bar {f}\) et un seul de \(C(Q)\) dans \(D\) tel que \(f = \bar {f} \circ \rho _{\tiny Q}\).
Proof.
- September 2, 2020
- Utensil Song
Proof.
- September 2, 2020
- Utensil Song
The uniqueness of \(\bar {f}\) results from the fact that \(C(Q)\) is generated by \(\rho _{\tiny Q}(E)\). Let \(h\) be the unique homomorphism of \(T(E)\) into \(D\) which extends \(f\) (\(h\) is defined by \(h(x_{1} \otimes \cdots \otimes x_{n}) = f(x_{1}) \ldots f(x_{n})\)). We have \[h(x \otimes x - Q(x) . 1) = (f(x)^{2} - Q(x)) . 1 = 0 , \notag\] and then \(h\) cancels on \(I(Q)\) and defines the homomorphism \(\bar {f}\) through the quotient. 🇫🇷 L'unicité de \(\bar {f}\) résulte de ce que \(C(Q)\) est engendrée par \(\rho _{\tiny Q}(E)\). Soit \(h\) l'unique homomorphisme de \(T(E)\) dans \(D\) qui prolonge \(f\) (\(h\) est défini par \(h(x_{1} \otimes \cdots \otimes x_{n}) = f(x_{1}) \ldots f(x_{n})\)). On a \[h(x \otimes x - Q(x) . 1) = (f(x)^{2} - Q(x)) . 1 = 0 , \notag\] et par suite \(h\) s'annule sur \(I(Q)\) et définit par passage au quotient l'homomorphisme \(\bar {f}\) cherché.
Prop. 1 shows that \(C(Q)\) is a solution to a problem of universal (mapping) property ( Ens., chap. IV, § 3, \(n^{\circ }\) 1 ). 🇫🇷 La prop. 1 exprime que \(C(Q)\) est solution d'un problème d'application universelle ( Ens., chap. IV, § 3, \(n^{\circ }\) 1 ).
Let us take in particular for \(D\) the opposite algebra of \(C(Q)\) and for \(f\) the mapping \(\rho \); prop. 1 implies that there is one and only one anti-automorphism \(\beta \) of \(C(Q)\) whose restriction to \(\rho (E)\) is the identity; it is called the main anti-automorphism of \(C(Q)\). It is clear that \(\beta ^{2} = 1\). 🇫🇷 Prenons en particulier pour \(D\) l'algèbre opposée de \(C(Q)\) et pour \(f\) l'application \(\rho \); la prop. 1 entraine qu'il existe un antiautomorphisme \(\beta \) et un seul de \(C(Q)\) dont la restriction à \(\rho (E)\) soit l'identité ; on l'appelle l'antiautomorphisme principal de \(C(Q)\). Il est clair que \(\beta ^{2} = 1\).
On the other hand, let \(Q'\) be a quadratic form over an \(A\)-module \(E'\), and \(f\) a linear map of \(E\) into \(E'\) such that \(Q' \circ f = Q\). We have \(\rho _{\tiny Q'}(f(x))^{2} = Q'(f(x)) . 1 = Q(x) . 1\), and consequently there is one and only one homomorphism \(C(f)\) of \(C(Q)\) into \(C(Q')\) such that \(C(f) \circ \rho _{\tiny Q} = \rho _{\tiny Q'} \circ f\). 🇫🇷 D'autre part, soient \(Q'\) une forme quadratique sur un \(A\)-module \(E'\), et \(f\) une application linéaire de \(E\) dans \(E'\) telle que \(Q' \circ f = Q\). On a \(\rho _{\tiny Q'}(f(x))^{2} = Q'(f(x)) . 1 = Q(x) . 1\), et par suite il existe un homomorphisme \(C(f)\) et un seul de \(C(Q)\) dans \(C(Q')\) tel que \(C(f) \circ \rho _{\tiny Q} = \rho _{\tiny Q'} \circ f\).
If \(f\) is the identity, \(C(f)\) is the identity ; if \(Q'\) is a quadratic form over an \(A\)-module \(E'\), and \(g\) a linear map of \(E'\) into \(E''\) such that \(Q'' \circ g = Q'\), we have \(C(g \circ f) = C(g) \circ C(f)\). When \(E'\) is a submodule of \(E\) and \(f\) is the canonical injection of \(E'\) into \(E\) (so that \(Q'\) is the restriction of \(Q\) to \(E'\)), we say that \(C(f)\) is the canonical homomorphism of \(C(Q')\) into \(C(Q)\). 🇫🇷 Si \(f\) est l'identité, \(C(f)\) est l'identité ; si \(Q'\) est une forme quadratique sur un \(A\)-module \(E'\), et \(g\) une application linéaire de \(E'\) dans \(E''\) telle que \(Q'' \circ g = Q'\), on a \(C(g \circ f) = C(g) \circ C(f)\). Lorsque \(E'\) est un sous-module de \(E\) et \(f\) l'injection canonique de \(E'\) dans \(E\) (de sorte que \(Q'\) est la restriction de \(Q\) à \(E'\)), on dit que \(C(f)\) est l'homomorphisme canonique de \(C(Q')\) dans \(C(Q)\).
Let us take in particular \(Q' = Q\) and for \(f\) the mapping \(x \to -x\); we see that there is an automorphism \(\alpha \) and only one of \(C(Q)\) such that \(\alpha \circ \rho = -\rho \); it is called the main automorphism of \(C(Q)\). It is clear that \(\alpha ^{2} = 1\), and that the restriction of \(\alpha \) to \(C^{+}\) (resp. \(C^{-}\)) is the identity (resp. the mapping \(u \to -u\)). 🇫🇷 Prenons en particulier \(Q' = Q\) et pour \(f\) l'application \(x \to -x\); on voit qu'il existe un automorphisme \(\alpha \) et un seul de \(C(Q)\) tel que \(\alpha \circ \rho = -\rho \); on l'appelle l'automorphisme principal de \(C(Q)\). Il est clair que \(\alpha ^{2} = 1\), et que la restriction de \(\alpha \) à \(C^{+}\) (resp. \(C^{-}\)) est l'identité (resp. l'application \(u \to -u\)).
Proposition 2. - Let \(A'\) be a commutative ring, \(\varphi \) a homomorphism of \(A\) into \(A'\), \(Q'\) the quadratic form over \(E' = A' \otimes _{ A } E\) induced from \(Q\) by extension of scalars (§ 3, \(n^{\circ }\) 4, prop. 3 ). There is one and only one isomorphism \(j\) of the algebra \(A' \otimes _{ A } C ( Q )\) onto \(C(Q')\) such that \(j (1 \otimes \rho _{\tiny Q}(x) )=\rho _{\tiny Q'}(1 \otimes x)\) for all \(x \in E\). 🇫🇷 Proposition 2. - Soient \(A'\) un anneau commutatif, \(\varphi \) un homomorphisme de \(A\) dans \(A'\), \(Q'\) la forme quadratique sur \(E'= A' \otimes _{ A } E\) déduite de \(Q\) par extension des scalaires (§ 3, \(n^{\circ }\) 4, prop. 3 ). Il existe un isomorphisme \(j\) et un seul de l'algèbre \(A' \otimes _{ A } C ( Q )\) sur \(C(Q')\) tel que \(j (1 \otimes \rho _{\tiny Q}(x) )=\rho _{\tiny Q'}(1 \otimes x)\) pour tout \(x \in E\).
Proof.
- September 2, 2020
- Utensil Song
Proof.
- September 2, 2020
- Utensil Song
It is sufficient to show that the algebra \(C'\) = \(A' \otimes C(Q)\) and the mapping \(1 \otimes \rho _{\tiny Q}\) of \(E'\) into \(C'\) form a solution to the same problem of universal (mapping) property as \(C(Q')\) and \(\rho _{\tiny Q'}\). 🇫🇷 Il suffit de démontrer que l'algèbre \(C'\) = \(A' \otimes C(Q)\) et l'application \(1 \otimes \rho _{\tiny Q}\) de \(E'\) dans \(C'\) forment une solution du même problème d'application universelle que \(C(Q')\) et \(\rho _{\tiny Q'}\).
Now, let \(D'\) be an algebra on \(A'\), and \(f'\) be a \(A'\)-linear application of \(E'\) in \(D'\) such that \(f'(x')^{2} = Q'(x') . 1\) for all \(x' \in E'\). The mapping \(g: x \to f'(1 \otimes x)\) of \(E\) into \(D'\) (considered as \(A\)-module thanks to the homomorphism \(\varphi \)) is \(A\)-linear, and we have \(g(x)^{2} = Q'(1 \otimes x) . 1 = Q(x) . 1\) for all \(x \in E\). There is thus one and only one \(A\)-homomorphism \(\bar {g}\) of \(C(Q)\) into \(D'\) such that \(\bar {g}(\rho _{\tiny Q}(x)) = f'(1 \otimes x)\). Therefore, there is one and only one \(A'\)-homomorphism \(\bar {f'}\) of \(C'\) into \(D'\) such that \(\bar {f'}(1 \otimes \rho _{\tiny Q }(x)) = f'(1 \otimes x)\) for all \(x \in E\); by linearity, it results that \(\bar {f'}((1 \otimes \rho _{\tiny Q})(x')) = f'(x')\) for all \(x' \in E'\). Q.E.D. 🇫🇷 Or, soient \(D'\) une algèbre sur \(A'\), et \(f'\) une application \(A'\)-linéaire de \(E'\) dans \(D'\) telle que \(f'(x')^{2} = Q'(x') . 1\) pour tout \(x' \in E'\). L'application \(g: x \to f'(1 \otimes x)\) de \(E\) dans \(D'\) (considéré comme \(A\)-module grâce à l'homomorphisme \(\varphi \)) est \(A\)-linéaire, et on a \(g(x)^{2} = Q'(1 \otimes x) . 1 = Q(x) . 1\) pour tout \(x \in E\). Il existe donc un \(A\)-homomorphisme \(\bar {g}\) et un seul de \(C(Q)\) dans \(D'\) tel que \(\bar {g}(\rho _{\tiny Q}(x)) = f'(1 \otimes x)\). Par suite, il existe un \(A'\)-homomorphisme \(\bar {f'}\) et un seul de \(C'\) dans \(D'\) tel que \(\bar {f'}(1 \otimes \rho _{\tiny Q }(x)) = f'(1 \otimes x)\) pour tout \(x \in E\); par linéarité, il en résulte que \(\bar {f'}((1 \otimes \rho _{\tiny Q})(x')) = f'(x')\) pour tout \(x' \in E'\). CQFD.
Translation of Bourbaki on Clifford algebras › 2. Some operations in tensor algebra 🇫🇷 2. Quelques opérations dans l'algebre tensorielle.
- September 2, 2020
- Utensil Song
Translation of Bourbaki on Clifford algebras › 2. Some operations in tensor algebra 🇫🇷 2. Quelques opérations dans l'algebre tensorielle.
- September 2, 2020
- Utensil Song
In this section we will designate by \(e_{x}\) (\(x \in E\)) the linear mapping \(u \rightarrow x \otimes u\) of the tensor algebra \(T( E )\) into itself. 🇫🇷 Dans ce \(n^{\circ }\) nous désignerons par \(e_{x}\) (\(x \in E\)) l'application linéaire \(u \rightarrow x \otimes u\) de l'algèbre tensorielle \(T( E )\) dans elle-même.
Lemma 1. - Let \(f\) be an element of the dual \(E^{*}\) of \(E\). There exists one linear mapping \(i_{f}\) and only one from \(T ( E )\) into itself such that \[i_{f}(1)=0 \tag{4}\] \[i_{f} \circ e_{x} + e_{x} \circ i_{f} = f(x) . I \text {\quad for all \,} x \in E \tag{5}\] (where \(I\) denotes the identical mapping). The mapping \(f \rightarrow i_{f}\) from \(E^{*}\) into \(\mathscr {L}(T(E))\) is linear. We have \(i_{f}\left (T^{n}\right ) \subset T^{n-1},\left (i_{f}\right )^{2}=0,\) and \(i_{f} \circ i_{g}+i_{g} \circ i_{f}=0\) for \(f, g\) in \(E ^{*}\). The mapping \(i_{f}\) is null on the subalgebra of \(T ( E )\) generated by the kernel of \(f\). The ideal \(I(Q)\) is stable by \(i_{f}\); through quotient \(i_{f}\), we define a linear mapping (again \(i_{f}\)) of \(C(Q)\) into itself. 🇫🇷 Lemme 1. - Soit \(f\) un élément du dual \(E^{*}\) de \(E\). Il existe une application linéaire \(i_{f}\) et une seule de \(T ( E )\) dans elle-même telle que \[i_{f}(1)=0 \tag{4}\] \[i_{f} \circ e_{x} + e_{x} \circ i_{f} = f(x) . I \text {\quad pour tout \,} x \in E \tag{5}\] (où \(I\) désigne l'application identique). L'application \(f \rightarrow i_{f}\) de \(E^{*}\) dans \(\mathscr {L}(T(E))\) est linéaire. On a \(i_{f}\left (T^{n}\right ) \subset T^{n-1},\left (i_{f}\right )^{2}=0,\) et \(i_{f} \circ i_{g}+i_{g} \circ i_{f}=0\) pour \(f, g\) dans \(E ^{*}\). L'application \(i_{f}\) est nulle sur la sous-algèbre de \(T ( E )\) engendrée par le noyau de \(f\). L'idéal \(I(Q)\) est stable par \(i_{f}\); par passage au quotient \(i_{f}\), définit donc une application linéaire (notée encore \(i_{f}\) ) de \(C(Q)\) dans elle-mème.
Math notes (early drafts) [uts-000V]
Math notes (early drafts) [uts-000V]
Notes on language models [lm-0001]
Notes on language models [lm-0001]
This is a placeholder root note, for now, see opening thoughts.
Drafts for Notes on language models
Drafts for Notes on language models
Definition. L-GATr architecture [spinner2024lorentz, p. 5] [lm-0007]
\[
\begin {align*}
\bar {x}&=\operatorname {LayerNorm}(x),\\
\operatorname {AttentionBlock}(x)&=\operatorname {Linear} \circ \operatorname {Attention}(\operatorname {Linear}(\bar {x}), \operatorname {Linear}(\bar {x}), \operatorname {Linear}(\bar {x})) + x,\\
\operatorname {MLPBlock}(x)&=\operatorname {Linear} \circ \operatorname {GatedGELU} \circ \operatorname {Linear} \circ \operatorname {GP}(\operatorname {Linear}(\bar {x}), \operatorname {Linear}(\bar {x})) + x,\\
\operatorname {Block}(x)&=\operatorname {MLPBlock} \circ \operatorname {AttentionBlock}(x),\\
\operatorname {L-GATr}(x)&=\operatorname {Linear} \circ \operatorname {Block} \circ \operatorname {Block} \circ \cdots \circ \operatorname {Block} \circ \operatorname {Linear}(x).
\end {align*}
\]
Definition. L-GATr architecture [spinner2024lorentz, p. 5] [lm-0007]
opening thoughts [lm-0006]
opening thoughts [lm-0006]
My recent learning has become too scattered, and I have long wished to write notes on LMs (language models), so I hope focusing on this will prevent me from losing focus.
I've settled on the prefix lm instead of llm as I think phrases like "small LLMs" are redundant, and I hope LM will include multimodal variants, such as VLMs (visual language models).
The interest doesn't stop there - I haven't properly studied diffusion models yet, and I wish to explore their integration with LMs, or at least, the perspective of diffusion models in relation to LMs.
As my interests in the LM field are quite diverse, I will organize the notes into several series rather than one. I've reserved lm-0002 through lm-0005 for root notes covering these topics. The areas that come to mind include:
- math behind LMs since ML
- various optimization methods of LMs, including GPU programming
- post-training techniques
- application of GA in LMs
- alternative architectures of LMs, that includes RWKV, stuff related to diffusion models
Individual notes will be written as I read related papers and books, and may be referenced across these root notes.
I have scattered notes about LMs previously, here I list them for easier reference.
- Transformers: from self-attention to performance optimizations
- LLM Daily Picks
- ML
- Learning diary › Year 2025 › May, 2025 › 2025-05-06
- Learning diary › Year 2025 › May, 2025 › 2025-05-02
- Learning diary › Year 2025 › April, 2025 › 2025-04-21
This is also an experiment to see if modern VLMs could better convert screenshots to Forester math formula markup.
In Transformers: from self-attention to performance optimizations, I was focused on visualizing transformer architectures using subscript-free tensor notations ("Named Tensor Notation" [chiang2021named]). However, mathematical concepts can often be expressed succinctly once you develop the ability to visualize them mentally. In this series of notes, I'll focus more on the mathematical foundations rather than visualizations or introductory explanations, having progressed beyond that stage after reading hundreds of LM papers.
notes on group algebras [spin-0010]
notes on group algebras [spin-0010]
rationale [spin-0011]
rationale [spin-0011]
In a sense, group algebras are the source of all you need to know about representation theory.
The primary reference is [james2001representations] for understanding FG-module, Group algebra, the presentation of groups, Clifford theory (which is the standard method of constructing representations and characters of semi-direct products, see [woit2017quantum], and "3.6 Clifford theory" in [lux2010representations]), Schur indices etc. We also need to check [lux2010representations] for its introduction to GAP, and we should pay close attention to the progress of GAP-LEAN. [sims1994computation] might also be interesting in a similar manner as [lux2010representations] but with emphasis on the presentation of groups.
See also group algebra on nlab, particularly that "A group algebra is in particular a Hopf algebra and a \(G\)-graded algebra."
The related Zulip thread is here, and I have preliminary explorations and experiments in Lean here.
This interest originates from reading Robert A. Wilson's work [wilson2024discrete]. The ultimate goal is to understand the group algebra of the binary tetrahedral group (\(Q_8 \rtimes Z_3\)), then the three-dimensional complex reflection group (\(G_{27} \rtimes Q_8 \rtimes Z_3\)), a.k.a. the triple cover of the Hessian group, which can be interpreted as a finite analogue of the complete gauge group \(U(1) \times SU(2) \times SU(3)\).
A further neccecity arises from reading [hamilton2023supergeometric] and [hamilton2023unification].
Notes on Algebraic Geometry [ag-0001]
- August 13, 2024
- Utensil Song
Notes on Algebraic Geometry [ag-0001]
- August 13, 2024
- Utensil Song
What is Algebraic Geometry? [ag-0005]
What is Algebraic Geometry? [ag-0005]
Algebraic geometry deals with solution sets of systems of polynomial equations [borisov2024adventures, sec. 1] from an geometric view, with many algebraic concepts imitating the notions of analysis and topology [kriz2021introduction, p. vii], but has the advantage of being able to deal with singularities [mehrle2017algebraic, lect. 1, sec. 1] and other pathological objects.
Algebraic geometry has developed in waves, each with its own language and point of view, see [hartshorne1977graduate, p. xiv] for some discussion. The older language is closer to the geometric intuition, while the newer language developes powerful techniques to solve problems in great generality, but the study of the latter is considered tedious, or even depressing, by many, when not accompanied with tangible applications [grothendieck1964elements, p. 12].
Remark. the grand plan [ag-0002]
Remark. the grand plan [ag-0002]
We will use [kriz2021introduction] as a holistic guide to the organization of materials, which has done a great job of having the minimal prerequisites, being self-contained, and covering most of the topics that concern us, including the geometric motivation.
For a similar purpose, we use the formalization papers [bordg2022simple] and [buzzard2022schemes] to guide the path, at least the part towards schemes, and their counterparts in the Mathlib of Lean 4.
For prerequisites in basic algebra and commutative algebra, we will use [knapp2006basic] and [knapp2007advanced], and notes by Andreas Gathmann [gathmann2023plane][gathmann2013commutative] and David Mehrle [mehrle2015commutative]. For the geometric motivation and intuition, we will use [cox1997ideals] and [borisov2024adventures].
For upstream treatment of algebraic geometry, we will use [grothendieck1964elements] (particularly the English translation available at ryankeleti/ega) and [fantechi2006fundamental]. For modern notes, we will use [vakil2024rising], [gathmann2022algebraic] and [mehrle2017algebraic], with an eye on the classic textbook [hartshorne1977graduate].
We also need to tap into the language of Stacks in a modern setting, as treated in [khan2023lectures], with preliminaries on \(\infty \)-categories and derived categories.
See the plan for notes on algebraic geometry for an early discussion of the plan.
Convention. rings and fields [gathmann2013commutative, 0.1] [ag-0008]
Convention. rings and fields [gathmann2013commutative, 0.1] [ag-0008]
A ring, usually denoted \(R\), is always assumed to be a commutative ring (i.e. \(a+b=b+a\) and \(a b=b a\) for all \( a, b \in R\)) with 1 (i.e. the multiplicative identity element, or called multiplicative unit).
\(1 \neq 0\) is not required, where \(0\) is the additive neutral element. If \(1=0\), then \(R\) must be the zero ring (or called the trivial ring), which consisting of one element, and is denoted \(\{0\}\).
Subrings must have the same unit, and ring homomorphisms are always required to map \(1\) to \(1\).
A field, usually denoted \(K\), is a commutative ring with \(1\), where every nonzero element has a multiplicative inverse (thus division can be defined).
Definition. formal variable, formal expression [ag-0009]
Definition. formal variable, formal expression [ag-0009]
A formal variable is an arbitrary symbol that is used to represent some mathematical object, and assumes nothing about the value or nature of the object.
A formal expression is mathematical expression with formal variables, assuming nothing but the formal variables participate in the expression have operations that are used in the expression.
A formal expression can be evaluated by replacing the formal variables with actual mathematical objects that have the operations defined in the expression.
When there is no ambiguity, we may omit the word "formal" and simply say variables or an expression.
Definition. monomial [cox1997ideals, 1.1.1] [ag-0003]
Definition. monomial [cox1997ideals, 1.1.1] [ag-0003]
A monomial in \(n\) formal variables \(x_1, \ldots , x_n\), denoted \(x^\alpha \), is a formal expression of the form \[ x_1^{\alpha _1} x_2^{\alpha _2} \cdots x_n^{\alpha _n} \] where \(n \in \mathbb N\), \(\alpha =\left (\alpha _1, \ldots , \alpha _n\right )\) is an \(n\)-tuple of nonnegative integers.
The total degree of the monomial is denoted \(|\alpha |=\alpha _1+\cdots +\alpha _n\).
Definition. polynomial [cox1997ideals, 1.1.2, 1.1.3] [ag-0004]
Definition. polynomial [cox1997ideals, 1.1.2, 1.1.3] [ag-0004]
A polynomial \(f\) over a ring \(R\) in \(n\) variables is a finite linear combination (with coefficients \(a_\alpha \) in \(R\) ) of monomials, i.e. the formal expression of the form \[ f=\sum _\alpha a_\alpha x^\alpha , \quad a_\alpha \in R, \]
The set of all polynomials in \(x_1, \ldots , x_n\) with coefficients in \(R\) is denoted \(R\left [x_1, \ldots , x_n\right ]\).
\(a_\alpha x^\alpha \) is called a term of \(f\) if \(a_\alpha \neq 0\).
The total degree of \(f \neq 0\), denoted \(\operatorname {deg}(f)\), is the maximum \(|\alpha |\) such that the coefficient \(a_\alpha \) is nonzero. The total degree of the zero polynomial is undefined.
Remark. polynomial ring [cox1997ideals, 1.1.3] [ag-0007]
Remark. polynomial ring [cox1997ideals, 1.1.3] [ag-0007]
Under addition and multiplication, \(R\left [x_1, \ldots , x_n\right ]\) satisfies all axioms of a commutative ring, and for this reason we will refer to \(R\left [x_1, \ldots , x_n\right ]\) as a polynomial ring.
Definition. affine space [gathmann2013commutative, 0.3] [ag-000A]
Definition. affine space [gathmann2013commutative, 0.3] [ag-000A]
The (\(n\)-dimensional) affine space over a field \(K\), denoted \(\mathbb {A}_K^n\), is \[ \left \{\left (c_1, \ldots , c_n\right ): c_i \in K \text { for } i=1, \ldots , n\right \} \] which is just \(K^n\) as a set, without the its additional structures as a \(K\)-vector space and a ring.
We'll often use the term affine \(n\)-space to indicate the dimension. Particularly, an affine 1-space is called an affine line, an affine 2-space is an affine plane.
Definition. affine variety [gathmann2013commutative, 0.3] [ag-000D]
Definition. affine variety [gathmann2013commutative, 0.3] [ag-000D]
Let \(S \subset K\left [x_1, \ldots , x_n\right ]\) be a set of polynomials. The zero locus (or zero set) of \(S\) is \[ V(S):=\left \{x \in \mathbb {A}_K^n: f(x)=0 \text { for all } f \in S\right \} \subset \mathbb {A}_K^n \]
An affine algebraic variety over \(K\) is a subset of \(\mathbb {A}_K^n\) of this form. It's usually simply called an affine variety over \(K\), or an affine \(K\)-variety.
If \(S=\left (f_1, \ldots , f_k\right )\) is a finite set, \(V(S)\) can be written as \(V\left (f_1, \ldots , f_k\right )\).
Obviously, it is the set of all solutions of the system of polynomial equations \(f_1\left (x_1, \ldots , x_n\right )=\cdots =f_s\left (x_1, \ldots , x_n\right )=0\) [cox1997ideals, 1.2.1], denoted \(\operatorname {Sol}(S;K)\) [dolgachev2013introduction, p. 1].
Remark. affine v.s. projective [michalek2021invitation, ch. 2] [ag-000E]
Remark. affine v.s. projective [michalek2021invitation, ch. 2] [ag-000E]
The prefix "affine" of affine variety is used to distinguish it from a projective variety. Affine varieties arise from arbitrary polynomials, while projective varieties arise from systems of homogeneous polynomials, i.e. linear combinations of monomials of fixed degree.
Since affine varieties are the general case, they are sometimes simply called varieties.
Figure out its relation to affine space in Geometry, which preserves parallelism and ratio of lengths for parallel line segments, but not distances and measures of angles.
Example. varieties [ag-000F]
Example. varieties [ag-000F]
\(\mathbf {V}\left (10 x^2-x^3-y^2\right )\) from [cox1997ideals, p. 24]:
\(\mathbf {V}\left (x^2-y^2 z^2+z^3\right )\) from [cox1997ideals, p. 7, p. 16]:
Figure. Implicit surfaces [uts-000J]
Figure. Implicit surfaces [uts-000J]
#define AS_LIB 1
int get_shape() {
return int(iTime) % 52;
}
#include "/forest/shader/implicit.glsl"
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = 2.*(fragCoord-iResolution.xy/2.)/iResolution.y; // contains [-1,1]^2
vec3 col = vec3(0.);
// Camera rays
vec3 camPos = vec3(4.,0.,0.);
vec3 camDir = - normalize(camPos);
vec3 rayPos, rayDir;
float zoom = 1.3; // 1.8*cos(iTime);
// if (checkKey(KEY_E)) zoom = 0.5;
float fov = 0.4*zoom;
float fov_ortho = 1.5*zoom;
#if perspective
// perspective cam
rayPos = camPos;
rayDir = normalize(camDir + fov*vec3(0., uv.x, uv.y));
#else
// orthographic cam
rayPos = camPos + fov_ortho*vec3(0., uv.x, uv.y);
rayDir = camDir;
#endif
// for perspective background in orthographic mode
vec3 cubemapDir = normalize(camDir + fov*vec3(0., uv.x, uv.y));
// Mouse-controlled rotation
vec2 mouse = initMouse + vec2(0.015625*sin(iTime*PI), 0.0); // initMouse; // iMouse.xy == vec2(0.,0.) ? initMouse : (iMouse.xy/iResolution.xy - 0.5);
float yaw = clamp(- mouse.x * 2.*PI * 1., -PI,PI);
float pitch = clamp( mouse.y * PI * 1.2, -PI*0.5, PI*0.5);
// pitch and yaw rotations (column-wise matrices)
mat3 rot = mat3(cos(yaw), sin(yaw), 0., -sin(yaw), cos(yaw), 0., 0., 0., 1.);
rot = rot * mat3(cos(pitch), 0., -sin(pitch), 0., 1., 0., sin(pitch), 0., cos(pitch));
// apply
camPos = rot*camPos;
camDir = rot*camDir;
rayPos = rot*rayPos;
rayDir = rot*rayDir;
cubemapDir = rot*cubemapDir;
//cubemapDir = vec3(cubemapDir.x, cubemapDir.z, cubemapDir.y);
vec3 hitPoint = raycast(rayPos, rayDir);
if (hitPoint == BINGO) { fragColor = vec4(BINGO,1.0); return; }
//if (hitPoint == NOHIT) { fragColor = vec4(NOHIT,1.0); return; }
//if (hitPoint == NOBOUNDHIT) { fragColor = vec4(NOBOUNDHIT,1.0); return; }
//if (hitPoint == ESCAPEDBOUNDS) { fragColor = vec4(ESCAPEDBOUNDS,1.0); return; }
//if (hitPoint == MAXDISTREACHED) { fragColor = vec4(MAXDISTREACHED,1.0); return; }
//if (hitPoint == MAXITERREACHED) { fragColor = vec4(MAXITERREACHED,1.0); return; }
if (hitPoint == NOBOUNDHIT || hitPoint == NOHIT || hitPoint == ESCAPEDBOUNDS || hitPoint == MAXITERREACHED) {
//fragColor = vec4(vec3(0.2),1.0); return;
// make background transparent
fragColor = vec4(0.0,0.0,0.0,0.0); return;
col = with_background(cubemapDir);
#if showBoundingCube
// darken bounding cube
if (hitPoint != NOBOUNDHIT) { col *= vec3(0.7); }
#endif
fragColor = vec4(col,1.0); return;
}
vec3 grad = gradf(hitPoint+1.1*EPS*(-rayDir));
float s = -sign(dot(grad,rayDir));
col = with_color_mode(grad, s, hitPoint, camPos);
col = clamp(col, 0., 1.);
col = with_surface_pattern(col, hitPoint);
col = with_shading(col, grad, s, rayDir);
col = clamp(col, 0., 1.);
fragColor = vec4(col,1.0);
}
appendix [ag-000B]
appendix [ag-000B]
For draft notes, see Drafts for Notes on Algebraic Geometry.
Notes on Hopf Algebras [hopf-0001]
- May 6, 2024
- Utensil Song
Notes on Hopf Algebras [hopf-0001]
- May 6, 2024
- Utensil Song
I would like to have some notes on Hopf algebras, particularly its relation to group algebras of finite groups and Clifford algebras.
The following papers interest me (marked with extra keywords hit):
- [ablamowicz2016clifford]: finite groups
- [fauser2004grade]: grade, knot
- [fauser2002treatise]: grade, knot, graphical calculi
- [rodriguez1996clifford]: action
- [trindade2019clifford]: physics
- [bulacu2011clifford]: category
Definition. Peano space [fauser2002treatise] [hopf-0002]
Definition. Peano space [fauser2002treatise] [hopf-0002]
Let \(V\) be a linear space of finite dimension \(n\). Let lower case \(x_i\) denote elements of \(V\), which we will call also letters. We define a bracket as an alternating multilinear scalar valued function \[ \begin {aligned} [, \ldots , .] & : V \times \ldots \times V \rightarrow \mathbb {k} \quad (n\text {-factors}) \\ {\left [x_1, \ldots , x_n\right ]} & =\operatorname {sign}(p)\left [x_{p(1)}, \ldots , x_{p(n)}\right ] \\ {\left [x_1, \ldots , \alpha x_r+\beta y_r, \ldots , x_n\right ] } & =\alpha \left [x_1, \ldots , x_r, \ldots , x_n\right ]+\beta \left [x_1, \ldots , y_r, \ldots , x_n\right ] \end {aligned} \]
The sign is due to the permutation \(p\) on the arguments of the bracket. The pair \(\mathcal {P}=(V,[., \ldots ,])\). is called a Peano space.
Remark. Peano space [fauser2002treatise] [hopf-0003]
Remark. Peano space [fauser2002treatise] [hopf-0003]
Of course, this structure is much weaker as e.g. a normed space or an inner product space. It does not allow to introduce the concept of length, distance or angle. Therefore it is clear that a geometry based on this structure cannot be metric. However, the bracket can be addressed as a volume form. Volume measurements are used e.g. in the analysis of chaotic systems and strange attractors.
Definition. standard Peano space [fauser2002treatise] [hopf-0004]
Definition. standard Peano space [fauser2002treatise] [hopf-0004]
A standard Peano space is a Peano space over the linear space \(V\) of dimension \(n\) whose bracket has the additional property that for every vector \(x \in V\) there exist vectors \(x_2, \ldots , x_n\) such that \[ \left [x, x_2, \ldots , x_n\right ] \neq 0 . \]
In such a space the length of the bracket, i.e. the number of entries, equals the dimension of the space, and conversely. We will be concerned here with standard Peano spaces only.
Technical notes (draft) [uts-0012]
Technical notes (draft) [uts-0012]
Try some alternative browsers [uts-016N]
Try some alternative browsers [uts-016N]
I decided to widen my horizon about browsers. After browsing a few subreddits, I have chosen these 3 browsers: - Arc - Chromium based - the team has moved on to Dia, an AI browser - but people still miss the UX of Arc, it seems to be one of a kind, so I have to know - unlikely to be open-source - Mac/iOS/Windows, no Linux - Orion - WebKit based, this engine is the best hope for degoogle - will be open-source - not mature yetA - Mac/iOS, Linux WIP, no Windows/Android - Floorp - Firefox based - open-source - Mac/Windows/Linux, no mobile
How to run perf in a colima container [uts-016L]
How to run perf in a colima container [uts-016L]
Just to note down that it's not straightforward to get perf working. Here's what worked finally: First, the container needs to be started with proper capabilities: ```bash docker run --rm -it --platform linux/amd64 --cap-add PERFMON ubuntu:jammy bash ``` Secondly, some flags need to be set from the VM: ```bash # this would start a shell in the VM, outside of containers colima ssh # don't know why, sudo doesn't work, but it works in a root shell # -1 or 2 both work sudo bash -c 'echo -1 > /proc/sys/kernel/perf_event_paranoid' ``` Lastly, install perf in the container: ```bash apt install -y linux-tools-$(uname -r) linux-cloud-tools-$(uname -r) ``` Then the following works: ```bash perf record -g echo 1 perf report -g graph,0.5,caller ``` Note also that you can't pass `"echo 1"` because perf will failed to find a file named "echo 1". Learned this while working on Trying Zig's self-hosted x86 backend on Apple Silicon and before submitting this issue about unable to run `poop` in `colima` containers. Follow-up: It's important to check whether certain perf counters actually work: ``` sleep 10 & perf stat -p $! -e "cpu-cycles,instructions,cache-references,cache-misses,branch-misses" ``` On a machine that supports corresponding counters, it should give something like: ``` Performance counter stats for process id '101011': 511488 cpu-cycles 280194 instructions # 0.55 insn per cycle 16193 cache-references 6161 cache-misses # 38.047 8730 branch-misses 10.009515156 seconds time elapsed ``` On an unsupported machine, the output would be like: ``` Performance counter stats for process id '552': <not supported> cpu-cycles <not supported> instructions <not supported> cache-references <not supported> cache-misses <not supported> branch-misses 6.491105847 seconds time elapsed ```
Resources about Rubik's Cube [uts-016J]
Resources about Rubik's Cube [uts-016J]
- speed solving
- Roux (a.k.a as bridging)
- Learning the Roux method
- Simple Roux Method of Solving Rubik's Cube
- Introduction - Roux Tutorial
- uses TwistySim
- ZZ
- Example Solves - Beginner ZZ Tutorial
- notation
- Rubik's cube notation by Sebastiano Tronto
- 3x3x3 notation
- which clarifies naming of `E`, `S`, `r` etc.
- papers
- The Generalized Rubik’s Cube: Combinatorial Insights Through Group Theory
- it cites Nxnxn rubik’s cubes and god’s number[salkinder2021nxnxn]
- has its own notation for nxnxn cubies
- works out many details about general nxnxn cubes and their corresponding group theory
- Commutators in the Rubik’s Cube Group
- uses notations like `UR`, `FUR` to denote edges and corners, which I prefered
- nice diagrams
- demo with Twizzle
- Generalising the configurations of an N×N×N Rubik’s Cube
- aimed to find an expression for the total number of possible configurations of an N×N×N Rubik’s Cube
- uses notations like `ur`, `fur`, `u_1` for 3x3x3 and 4x4x4 cubes
- generalize to N×N×N with 3x3x3-style edges and 4x4x4-style corners
- solving with linear algebra
- asked by this Reddit post
- Mathematics of the Rubik’s cube by W. D. Joyner in 1996
- Non-Commutative Gaussian Elimination and Rubik’s Cube
- Test TwistySim
- Test Twizzle
My setup with 4 screens and 2 Macs [uts-016B]
My setup with 4 screens and 2 Macs [uts-016B]
Recently, a MacBookPro and a Mac Mini, both are M4 Pro, have become my primary productivity tools. Along with them, I have 3 monitors, plus the one comes with MacBookPro, counts as 4 screens in total. On top of that, I have the logi MX Keys keyboard and MX Master 3S suite, and an Apple Magic Trackpad.
It turns out that I need to come up with a productive setup for them.
## TL;DR as an ASCII art
```
+---------+
| |
+-----------------+ +-----------------+ | Tall |
| Reference | | Primary | | |
| Display | | Display | | Display |
+-----------------+ +-----------------+ | |
| |
+------+ +------------+ +---------+
| Mini | | MBP |
+------+ +------------+
| [Keyboard] |
| [Pad] |
+------------+
[ MX Keys ] [MX 3S]
[Pad]
```
## Screen arrangement
Above the screen of MacBookPro, I have my primary display, which serves as the main workspace for coding, browsing etc. The second display is placed on its left, on the same height, hosting stuff for reference. Both are horizontal and wide.
The third display (I would like to call it the "tall display") is placed on the right, yet vertically, with its middle part aligned with the primary display, it might host IM, PDFs, AI assistants, or any stuff that are tall, including vertically stacked windows that requires less width.
## Mac-display correspondence
Mac Mini is placed under the second display, and it's connected to the first 2 displays, and all of them if desired.
MacBookPro is connected to the tall display, and optionally also to the primary display.
## Keyboard and mouse
I could just use the keyboard and trackpad of MacBookPro, and they can travel to the nearby Mac Mini.
As I have muscle memory that's already used to MacBookPro's keyboard, MX Keys would be a good fit, as the keys are flatter, the key distance is also shorter.
I'm so used to use the trackpad to scroll, zoom, switching between spaces, and move cursor during coding, so that I would either put MX Keys on top of the keyboard of MacBookPro so I can reach its trackpad effortlessly, or I would just MX Keys and the Magic Trackpad beneath it, with the same relative location like the MacBookPro's keyboard and trackpad.
When I work with diagrams, slides, or UIs that require meticulous mouse control, I would use the MX Master 3S mouse. Its side wheel is configured to send `Ctrl+Left` and `Ctrl+Right`, and side buttons are configured to send `Ctrl+Up` and `Ctrl+Down`, both serving space switching.
The logi keyboard and mouse supports switch between 3 devices, so I can switch between 2 Macs. Unfortunately, one doesn't follow the other to switch, so I would rely on Mac's native support for keyboard and mouse sharing, and it goes like `2->1->MacBookPro->Tall`, so there is minimal extra travel between 1 and tall.
One might noticed that such a setup is highly redundant, but this provides me with maximum flexibility and productivity:
- In coding mode, I could have both hands on the keyboard, with the left hand sometimes on the trackpad
- In browing mode, my left hand is on the trackpad, and the right hand is on the mouse
- In diagramming mode, both hands are also on the keyboard, with the right hand sometimes on the mouse
## Thunderbolt bridge
I also have a Thunderbolt bridge, by connecting 2 Macs with a Thunderbolt cable, and following this guide. This would create a secure and fast connection between them for file transfer, screen sharing, distributed AI inference etc.
Such a bridge could also be used in MX Flow, but it has certain delay each time the cursor moves between the 2 Macs, so I didn't use it.
Organizing files [uts-002J]
- January 3, 2025
- Utensil Song
Organizing files [uts-002J]
- January 3, 2025
- Utensil Song
I wish to note down my exploration of solutions to organize massive amount of (mostly binary media) files.
## Wishlist
- Performant
- it should be able to handle huge amount of files, with cached metadata, thumbnails, etc. so I can browse over their contents quickly
- batch operations to files on NAS should be as performant as local files, e.g. using client-server architecture, using rsync to determine the diff, etc.
- Data integrity
- it should be able to use versioning, deduplication, etc. to ensure data integrity so I can mess with the files (mostly moving around, renaming) without worrying about losing them and their metadata such as timestamp, and this should be efficient in terms of storage
- Semi-auto tagging
- I should be able to tag files manually, in batch, and set rules to tag files automatically with metadata or based on content (using ML models)
- preferably, tags could have its own hierarchy
- tags should not be using filename or metadata, but rather a separate database
- Open-source, freemium or affordable one-time purchase
- in anycase, I should not be locked in, and the data should be exportable, so I can script
## Candidate solutions
- git-annex
- Pros
- it maintains a versioned record for files, can even track offline media
- Cons
- it only have access to the file contents when they are present at the registered location
- even with the web UI, it's not realy user-friendly
- DataLad
- it builds on git-annex, but still a CLI
- kopia
- Pros
- backup, versioning, deduplication, encryption, compression, error correction etc.
- it can mount or restore any snapshot to a directory
- there is official support for syncing the repo, making it reliable to backup the backup
- Cons
- can't really check the history of a file
- relies on other tools for checking file location changes
- lost the time added, preserving only the modification time
- Commander One
- dual-pane file manager, trying out
- `dua -i`
- it can analyze disk usage recursively, interactively
- I can mark files for deletion
- jw
- Pros
- it can calculate the hashes of files in deep directories really quick
- I use it to check the integrity of files after copying files
- Cons
- it doesn't check file renaming/moving
- VeraCrypt
- Pros
- useful if you just want to encrypt files in a container
- Cons
- it's inconvenient to mount in docker
- Garage
- Pros
- it's a S3-compatible storage
- it works with git-annex and kopia
- macFUSE
- needed to mount various filesystems
- photo management
- HomeGallery
- librephotos
- digiKam
- PhotoPrism
- Immich
- Lychee
- asset management
- Eagle 4
- Pixcall
- Billfish
Notes on modern C++ programming [uts-002H]
Notes on modern C++ programming [uts-002H]
Scope
Scope
This note will cover some modern C++ features interesting to me during reading Modern C++ Programming.
Features standardized in C++23, or implemented for C++26, are in scope.
This note serves as a holistic view and a reminder.
Introduction
Introduction
Curiosity and persistence matter. -- Ben Cichy
C++ achieves uncompromised performance by living with undefined behavior, accepting a safety trade-off. -- This is C++: Uncompromised Performance, Undefined Behavior, & Move Semantics - Jon Kalb C++Now 2024
The problem with using C++...is that there’s already a strong tendency in the language to require you to know everything before you can do anything -- Larry Wall
Preparation
Preparation
- C++23 `std::print`
- Reducing C++ Compilation Times Through Good Design - Andrew Pearcy - ACCU 2024
Basic Concepts I
Basic Concepts I
- C++14 digit separators, e.g. `1'000'000`
- C++14 `auto` for function return types, e.g. `auto f() { return 1; }`
- C++20 `auto` for function input, equivalent to templates but less expensive at compile-time
- C++20 `<utility>` for safely comparing signed/unsigned types
Basic Concepts II
Basic Concepts II
- Detecting wraparound for unsigned integral types is not trivial
- C++23 `std::float128`, `std::binary16`, `std::bfloat16`
- `inf` and `nan` for floating-point types
- Floating-point Arithmetic Properties
- Catastrophic Cancellation
- Fixed epsilon “looks small” but it could be too large when the numbers being compared are very small
- `areFloatNearlyEqual`
- compensation algorithm like Kahan summation, Dekker’s FastTwoSum, Rump’s AccSum
Basic Concepts III
Basic Concepts III
- C++11/C++17/C++20 enum class, e.g. `using enum Color`
- C++17 range-based loop for structure binding: `for (auto [key, value] : map)`
- C++17/C++20 initializing statement in `if`/`switch` and range-for loop, e.g. `for (int i = 0; auto x : {'A', 'B', 'C'}) {}`
- C++17 `[[maybe_unused]]` attribute, C++26 `auto _`
Basic Concepts IV
Basic Concepts IV
- C++11 Dynamic memory 2D allocation/deallocation: `new int[3][4]` and `delete[]`
- `new (buffer)`: `delele[] buffer`, explicit `x->∼A()`
- `new (std::nothrow)`
- C++20 Designated Initializer List: `struct A { int x, y; }; A a{.x = 1, .y = 2};`
- Pointer arithmetic rule: `address(ptr + i) = address(ptr) + (sizeof(T) * i)`
- C++11 `constexpr`: _can_ be evaluated at compile-time
- variable: always evaluated at compile-time
- function
- evaluated at compile-time as long as all its arguments are evaluated at compile-time
- always evaluated at run-time if
- contain run-time functions
- contain references to run-time global variables
- C++20 `consteval`: guarantees compile-time evaluation
- A run-time value always produces a compile error
- C++20 `constinit`: guarantees initialization at compile-time
- A run-time initialization value always produces a compile error
- The value of a variable _can_ change during the execution
- C++17 `if constexpr`: compile-time branching
- C++20 `std::is_constant_evaluated()`
- C++23 `if consteval`
- C++20 `std::bit_cast`
Basic Concepts V
Basic Concepts V
- `=delete` can be used to prevent calling the wrong overload
- C++20 `[[nodiscard("reason")]]`
- This issues a warning if the return value of a function is discarded (not handled), which is good for ensuring error handling.
- C++17 for the entire class/struct
- C++20 for constructors
- C++23 for lambdas
- The compiler injects `operator()` in the code of the destination function and then compile the routine. Operator inlining is the standard behavior
- C++11 lambda expression: capture clause
- `[]` captures nothing
- `[&]` captures all variables by reference
- `[=]` captures all variables by value
- `[=, x, &y]` captures `x` by value and `y` by reference, all other variables by value
- C++17 `[this]` captures the current object by reference
- C++14 `[x=x]`, `[&x=x]` capture current object member `x` by value/reference
- C++20 deprecates `[=]` capturing `this` pointer by value
- C++14 `[](auto value)`, `[](int i = 6)`
- A function can return a lambda (dynamic dispatch is also possible)
- C++17 `constexpr` lambda, C++20 `consteval` lambda, `mutable`
- syntax: post specifier
- C++20 `template` and `requires` clause for lambda
auto lambda = []<typename T>(T value)
requires std::is_arithmetic_v<T> {
return value * 2;
};
auto v = lambda(3.4); // v: 6.8 (double)
struct A{} a;
// auto v = lambda(a); // compiler error
- When Preprocessors are Necessary
- Conditional compiling
- [Abseil Platform Check Macros](https://abseil.io/docs/cpp/platforms/macros)
- Mixing different languages
- Complex name replacing
- [Are We Macro free Yet, CppCon2019](https://github.com/CppCon/CppCon2019/blob/master/Presentations/are_we_macrofree_yet/are_we_macrofree_yet__zhihao_yuan__cppcon_2019.pdf)
- C++20 `<source location>`
- replaces `__FILE__`, `__LINE__`, C++11 `__func__`
- still: non-standard `__PRETTY_FUNCTION__`
- C++17 [`__has_include`](https://en.cppreference.com/w/cpp/preprocessor/include)
- stringizing macro operator `#`, e.g. `#string` expands to `"string"`
- token pasting macro operator `##`, e.g. `x##y` expands to `xy`
- `#error`, C++23 `#warning`
- non-portable `pragma`, C++11 `_Pragma`
- C++11 `__VA_ARGS__`
Object-Oriented Programming I
Object-Oriented Programming I
- C++11 In-class non-static data members initialization (NSDMI)
- allows initializing the data members where they are declared
- a user-defined constructor can be used to override their default values
- C++11 uniform initialization `{}`
- in function arguments and return values
- C++11 delegate constructor
- C++11 `=default`, `=delete`
- `using` for type aliasing
- e.g. partial specialization for templates
Object-Oriented Programming II
Object-Oriented Programming II
- C++11 `override`
- ensures that the function is virtual and is overriding a virtual function from a base class
- C++11 `final`
- prevents a virtual function from being overridden in a derived class
- `dynamic_cast`
- upcast: `dynamic_cast<Base*>(derived)`
- C++23 multidimensional subscript operator `[]`
- C++23 static `[]` and `()` operators
- C++11 `explicit` for conversion operators
- `std:swap`
- operators preserve precedence and short-circuit properties
- binary operators should be implemented as friend methods
- layouts
- aggregate
- initializable with `{}`
- trivial copyable
- can be copied with `memcpy`
- standard layout
- just like a struct or a union
- POD
- trivial copyable + standard layout
- C++11/C++20 `<type_traits>` to check layout
Templates and Meta-programming I
Templates and Meta-programming I
- C++17 automatic deduction of non-type template parameters, with `auto`
- non-type template parameters
- C++20 a class literal type
- `constexpr` assignable
- public, non-mutable
- for all base classes and non-static data members
- pointer, reference, and pointer to member
- function, e.g. `decltype(f)`
- C++26 assertion with text formatting
- e.g. `static_assert(sizeof(T) != 4, std::format("test1 with sizeof(T)={}", sizeof(T)));`
- `decltype((expr))` for `lvalue` reference to the type of `expr`
- C++14 `auto` for function template return types
- replaces e.g. `decltype(T{} + R{})`
- `<type_traits>`
- type query
- type manipulation
Templates and Meta-programming II
Templates and Meta-programming II
- C++17 CTAD
- automatic deduction of class template arguments in constructor calls (CTAD)
- template deduction guide
- map constructor parameter types to class template parameters
- e.g. `MyString(char const*) -> MyString<std::string>;`
- doesn’t work within the class scope
- C++20 alias template deduction
- use `std::enable_if` to make use of SFINAE
- helper alias: `_t` for `::type`, `_v` for `::value`
- using `std::enable_if_t` for the return type prevents `auto` deduction
- variadic template
- captures a parameter pack of arguments, which hold an arbitrary number of values or types
- ellipsis `...`
- prefix an identifier to introduce/capture
- suffix the identifier to expand
- `sizeof...(args)` to get the number of arguments
- C++17 fold
`(other op ... op pack)`
- C++14 for lambdas
- C++20 for concepts
- [C++20 idioms for parameter packs](https://www.scs.stanford.edu/~dm/blog/param-pack.html)
- C++20 concepts
- `concept [name] = [compile-time boolean expression];`
- `requires` clause: `requires [compile-time boolean expression or Concept]`
- `requires` expression:
#include <concept>
requires [(arguments)] {
[SFINAE contrain]; // or
requires [predicate];
} -> bool
template<typename T>
concept MyConcept = requires (T a, T b) { // First case: SFINAE constrains
a + b; // Req. 1 - support add operator
a[0]; // Req. 2 - support subscript operator
a.x; // Req. 3 - has "x" data member
a.f(); // Req. 4 - has "f" function member
typename T::type; // Req. 5 - has "type" field
{*a + 1} -> std::convertible_to<float>;// Req. 6 - can be deferred
// and the sum
// with an integer is convertible
// to float
{a * a} -> std::same_as<int>; // Req. 7 - "a * a" must be valid
// and the result type is "int"
};
Translation Units I
Translation Units I
- storage duration - static initialization order fiasco - One Definition Rule (ODR) - C++11 `extern template class A<int>;`
Translation Units II
Translation Units II
- common linker errors
- multiple definitions
- undefined reference
- C++20 modules
- a module is a set of source code files that are compiled independently of the translation units that import them
- `module module.name;`
- `import module.name;`
- `export`
- `export { ... }`
- `export module module.name;`
- `expor import module.name;`
- global module fragment: include header files in a module interface
- `module;`
- private module fragment: include header files in a module implementation
- `module :private;`
- legacy headers can be directly imported with import
- all declarations are implicitly exported and attached to the global module (fragment)
- a module can be organized in isolated module partitions
- namespace
- anonymous namespace
- visible only in the translation unit, internal linkage
- inline namespace
- can be used to version a library
- C++17 attributes on namespaces
- tools
- `c++filt`, `ldd`, `nm`, `objdump`, `readelf`
Code Conventions
Code Conventions
- “Common” Project Organization - [C++ Core Guidelines](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines) - Naming style conventions can be also enforced by using tools like `clang-tidy`'s [readability-identifier-naming](https://clang.llvm.org/extra/clang-tidy/checks/readability/identifier-naming.html#readability-identifier-naming) - Use braced direct-list-initialization or copy-initialization for setting default data member value. Avoid initialization in constructors if possible
struct A {
int x = 3; // copy-initialization
int x { 3 }; // direct-list-initialization (best option)
};
Debugging and Testing
Debugging and Testing
- Cost of Software Defects - 60 terrible tips for a C++ developer - Compiler Options Hardening Guide for C and C++ - Sanitizers - Static Analyzers - Linters
Ecosystem
Ecosystem
- xmake vs cmake - Compiler Explorer - CppInsights: see what your compiler does behind the scenes - grep.app: search git repos - Quick C++ Benchmark
Utilities
Utilities
- C++20 `std::format`
- C++23 `std::print`, `std::println`
- C++20 `std::span`: non-owning view of an underlying sequence or array
- C++20 `<numeric>`
- C++11 pseudo random number generation (PRNG)
- C++11 `<chrono>`
- overhead ~20-40ns
- C++17 `<optional>`, `<any>`
- C++23 `<stacktrace>`
Containers, Iterators, and Algorithms
Containers, Iterators, and Algorithms
- C++20 Ranges
- operate on elements of data structures uniformly
- pipe operator `|`, `|=`
- `std::views::*`, `std::actions::*`
- range factory: produces a view that contains no elements
Advanced Topics I
Advanced Topics I
- lvalue, rvalue (could be *p*ure rvalue, or e*x*piring *g*eneralized lvalue) - `std::move` indicates that an object is no longer needed and can be moved - C++11 reference collapsing rules - C++11 perfect forwarding with `std::forward`: allows preserving argument value category and const/volatile modifiers - copy elision for return value (C++17 guarantees some cases) - C++23 decay copy with `auto`
Advanced Topics II
Advanced Topics II
- C++23 `std::expected`
- return a value or an `std::unexpected`
- the user can choose how to handle the error: check return value, throw an exception, or monadic operations
- future
- `std::async(f, args)`
- launch policy: `std::launch::async`, `std::launch::deferred`
- `.get()` or `.wait()`
Performance Optimizations I
Performance Optimizations I
Mostly known conceptual introductions, good reference.
Performance Optimizations II
Performance Optimizations II
- C++11 `std:fma` - C++20 `<bit>` - C++20[[unlikely]]- C++23[[assume(boolean expression)]]
Performance Optimizations III
Performance Optimizations III
- compiler flags and optimization
- consider using optimized external libraries for critical program operations (good reference)
- profiling tools
- parallel computing
- OpenACC
- Intel OneAPI
Software Design I
Software Design I
- functions that are strongly suggested being non-member
- binary operators
- template functions within a class template
- `std::linalg` proposal
Software Design II
Software Design II
- Curiously Recurring Template Pattern (CRTP): static polymorphism - Template Virtual Function
useful tools and key mappings for TUI [uts-002G]
- October 29, 2024
- Utensil Song
useful tools and key mappings for TUI [uts-002G]
- October 29, 2024
- Utensil Song
Top bar
- October 29, 2024
- Utensil Song
Top bar
- October 29, 2024
- Utensil Song
Setup: - Use SketchyBar - Use `just prep-sbar` to setup SketchyBar - Use `just prep-skhd` to setup some extra key bindings - `Shift + Alt + space`: toggle sketchbar - Modify `~/.config/sketchybar/bar.lua` as follows: ```lua display = "all", sticky = true, ``` for better multi-monitor support, and make the bar sticky. Unfortunatly, SketchyBar actively hides itself for fullscreen spaces, see this issue for more info. So, remember to use `Cmd + Ctrl + F` to toggle fullscreen mode.
Window tiling
- October 29, 2024
- Utensil Song
Window tiling
- October 29, 2024
- Utensil Song
Setup: - Use Amethyst - sensible default - less confusing configuration than yabai it seems - Use `just prep-tile` to install Amethyst Keys: - `Option + Shift + Space` to cycle through layouts - I prefer only BSP and wide - `Option + Shift + J/K` to cycle through windows - `Option + Shift + H/L` to resize windows Alternative setup: - Use yabai - requires skhd for key bindings - Use `just prep-yabai` to install yabai - Intentionally choose not to disable SIP Keys: - Space manipulation won't work with SIP enabled - keys to switch between windows are confusing - place windows on another window to split with it, there is visual hint for the split layout when overlapping with different areas - `Shift + Alt + s`: change how windows are splitted, prefer use Kitty's own layout management - `Ctrl + Alt + g`: toggle gaps between windows, prefer some gap for normal apps but no gap for terminals
Terminal
- October 29, 2024
- Utensil Song
Terminal
- October 29, 2024
- Utensil Song
Setup:
- Use Kitty
- Use `just prep-kitty` to install Kitty
Keys:
- Font size
- `Cmd +` to increase font size
- `Cmd -` to decrease font size
- OS Windows
- `Cmd + N` to open a new OS window with the same current directory
- Tabs
- `Cmd + T` to open a new tab with the same current directory
- `Cmd + number` to switch to tab number
- particularly useful for tiled windows, as SketchyBar will hide the tab bar
- `Cmd + w` to close the current tab
- Kitty Windows
- `Cmd + Enter` to open a new window with the same current directory
- close the current Kitty window
- `Ctrl + Shift + w`
- or run `exit`
- `Ctrl + Shift + l` to switch to next layout
- `Cmd + r` to resize window, e.g. `t` to make it taller
- Kitty
- `Cmd + q` to quit kitty
- `Cmd + ,` to open kitty config file
- with `Ctrl` to reload config
Monitor
- October 29, 2024
- Utensil Song
Monitor
- October 29, 2024
- Utensil Song
- For most info, use btop - For GPU on Mac, use macmon - Install both with `just prep-monit`
some useful key mappings in Neovim [uts-002F]
some useful key mappings in Neovim [uts-002F]
Introduction
Introduction
Here are some useful keys that I like using in NeoVim, some of them require corresponding plugins. I use - LunarVim - it has some pre-installed plugins - Task `prep-lvim` in my justfile is how I have installed LunarVim. Task `lvim` will syncrhonize the configurations, change the working directory and open LunarVim for a specified project. - my LunarVim configuration - LunarVim specific keys are marked with 🌕 - AstroVim - seems to be a better starting point - see astrocommunity for configuring plugin packs - I've ported plugins to use it except for forester - AstroVim specific keys are marked with 🌌 - LazyVim - it has some pre-installed plugins - similarly, see task `prep-lazyvim` and `lazyvim` in my justfile - LazyVim specific keys are marked with 💤 - NvChad - it's ~ 900 LOC lightweight configuration - see tasks `prep-chad` and `chad` in my justfile - NvChad specific keys are marked with 📦 - For all Vim flavors, the following apply: - shared configurations - shared plugins
Vital meta keys
Vital meta keys
some useful key mappings in Neovim › Esc
some useful key mappings in Neovim › Esc
The `Esc` key is used to escape to normal mode, to use Vim's powerful motions. It's the most frequently used key in Vim.
- I have configured CapsLock to mean Esc
- on Mac, go to `System Preferences > Keyboard > Modifier Keys > Caps Lock Key`
- I have configured `jk` in insert mode to mean Esc
- this is a common practice, but I don't seem to need it much
some useful key mappings in Neovim › Leader key
some useful key mappings in Neovim › Leader key
The leader key is used to trigger many key mappings in normal mode. The default leader key is a single space, represented by `<leader>` below. 🌕 The default local leader key is not set. I've configure it to be two consecutive spaces. `,` is also a common choice. 💤 The default local leader key is set to `\\`. I didn't change it. With plugin `whichkey` installed, `<leader>` and wait to see some useful mappings. Most frequently used key mappings is `<leader>` + one character. There are also many two-character mappings, with the first character indicating a category.
First aid
First aid
> To generate a truly random string, place a new user in front of Vim and ask them to exit
Most of the time, one can use `Esc` + `:qa!` to force quit Vim, with potential loss of unsaved changes.
In most plugin UIs,
- it can be quit with a single `q`, or `Esc` + `:q`, when in despair, try also `Ctrl+c`
- it will usually enter normal mode first, even in terminals, a single `i` is required to enter insert mode, to acually type something
- it might provide visual hints on how to navigate, usually a single number or a character in brackets
- `g?` or `?` might bring up help on key mappings.
Recording is a powerful feature of Vim, but one can accidentally trigger it with an out-of-order `q`, so one simply need to remember to press `q` again to quit recording if seeing something like `recording @a` in the status bar.
Other first aid key mappings or commands available:
- `:map` to see all key mappings
- `:help key-notation`
- in case it's not immediately clear that
- `C` means `Ctrl`, `S` means `Shift`
- `M` means `Alt`/`Option`
- `D` means `Cmd` on Mac
- use `:Lazy` to check on plugins
- use `:Mason` to check on LSPs
- 🌕
- `<leader>+;` to open the dashboard for frequently used actions
- `<leader>+Lr` to reload the config
- `<leader>+li` to see LSP informations
- 📦
- `<leader>+ch` to open cheatsheet
- Theming
- dropping into an unfamiliar theme is worth a first aid
- `:colorscheme ` and tab to select a theme
- 🌕 `<leader>+sp` to search/select and preview themes
- my favorite is `railscasts`
- 💤 defaults to `tokyonight`
- 📦 defaults to `onedark`
Navigation
Navigation
- Resume session
- `<leader>+rs` to resume the last session
- `<leader>+rS` to select a session to resume
- Explore and find files
- `<leader>+e` to toggle file explorer on the left
- `x` to cut, `c` to copy, `p` to paste
- `a` to create a file, `d` to delete, `r` to rename
- `H` to toggle hidden files, `I` to toggle git ignored files
- `Y` to copy relative path, `gy` to copy absolute path
- `s` to open in system file explorer
- `g?` for help, `q` to quit, `R` to refresh
- `hjkl` to move up/down, collapse/expand
- it will automatically follow the current file
- 💤 and 📦 use NeoTree
- can't be toggled, need `q` to quit
- `?` for help
- 🌕
- `<leader>+sr` to fuzzy find recent files
- `<leader>+sf` to fuzzy find files
- `<leader>+st` to grep text in files
- `<leader>+bf` to fuzzy find buffers
- 💤
- `<leader>+fr` to fuzzy find recent files
- `<leader>+ff` to fuzzy find files, or simply double space
- `<leader>+/` to grep text in files
- Manipulate buffers and windows
- use `L` for going to next buffer, `H` for previous buffer
- use `<C-hjkl>` to move between windows
- use `-`/`=` to resizing, or with `C-` for vertical resizing
- Jump between files
- `gd`: go to definition
- `Ctrl`+click also works, note that it's not cmd+click on mac
- `gl`: show diagnostics under cursor
- `<C+o>`: go back, `<C+i>`: go forward
`:jum` to see the jump history
- `gf`: go to file
- `K` : hover, backspace to cancel hover
- `Shift`+click on URL to open in browser
- In-file outline
- `<leader>+o` to toggle the outline on the right
- I have configure it to autojump and autoexpand
- Folding
- the following needs to be run inside the fold
- otherwist it will work on the upper level
- `za` to toggle fold
- `zA` to toggle all folds
- `zO` or `zC` to open/close folds recursively
- e.g. it's useful `zCV` then `<leader>+/` to toggle comment for a fold range
Editing
Editing
some useful key mappings in Neovim › Basics
some useful key mappings in Neovim › Basics
- Open file
- `:e` to open a file, with tab completion, but it's better to use the fuzzy finder above
- `:vs` to open a file (or the current buffer) on the right
- `:sp` to open a file (or the current buffer) on the bottom
- Save & quit
- `:bd` (i.e. buffer delete) to close the current buffer/tab
- won't close if there are unsaved changes, `:bd!` to force close
- In VSCode Vim mode, should stick to `cmd+s` for saving, `cmd+w` for closing a tab
- 💤
- `:w` or `Ctrl+s` to save
- `<leader>+bd` to close a buffer with confirmation on unsaved changes
- 🌕 prefer to use
- `<leader>+w` to save
- `<leader>+c` to close a buffer with confirmation on unsaved changes
- `ZZ` to save and quit
some useful key mappings in Neovim › Motions
some useful key mappings in Neovim › Motions
- Repeatition
- prefix with a number to repeat a motion multiple times, e.g. `3j`, `3w` for the impatient
- `.` to repeat the last edit motion, but not move motions
- Move motions
- On Mac, combine with the touchpad to be even more efficient
- `gg` for beginning, `G` for end
- `zz` to center the current line, `zt` to top, `zb` to bottom
- prefixing with a number works on the corresponding line
- `w`/`b` to move forward/backward by word
- `W`/`B` to move by space-separated words
- `e` works like `w` but moves to the end of the word
- `ge` works like `b` but moves to the end of the previous word
- left `hj` are for left, down; right `kl` are for right, up
- pointer finger on `j`, then muscle memory for `jkl` but `h` is a little difficult to reach
- `0` to move to the beginning of the line
- I don't like `^` and `$` because they are difficult to reach
- but in the case of `d$`, it's worth it to reach for `$`
- `f` + character to move to the next such character on the same line
- `;` and `,` to move to next or previous
- `t` works like `f` but moves to one character before, just like `i` for `a`
- e.g.
- `ct)` is useful for change until the next `)`
- `vt)p` is useful for select until the next `)` and paste and replace
- `F` and `T` work like `f` and `t` but move backward
- `}` to the next paragraph
- Edit motions
- to enter INSERT mode
- `i` for before the cursor
- `I` to insert at non-whitespace beginning of the line
- `0i` to insert at the beginning of the line
- `a` for after the cursor
- `A` to append at the end of the line
- `c` (i.e. change) to replace by motion, e.g. `cw` to replace a word
- `R` to replace by character
- `u` to undo, surprisingly `Ctrl+r` to redo
- Text objects
- `i` for inside, `a` for around
- works after the action, before the motion
- e.g. `ciw` to *c*hange *i*nside the *w*ord
- note that `cw` only changes the part of the word after the cursor, but `ciw` changes the whole word
- `a` will affect the surrounding whitespace and punctuation
- with `mini.ai` extending the text objects, we have more general way to discribe the text objects
- `b` for brackets
- `q` for quotes
- `c` for class
- `f` for function bodies
- `a` for arguments
- `?` to specify left and right delimiters interactively
- Cut/copy/paste
- `x` to immediately delete the character under the cursor
- `d`+direction to delete a character in that direction
- prefer to use number + `dj`/`dk` to delete multiple lines
- `dw`/`dd` to delete a character/word/line
- all the above will also cut the deleted text
- `yw` to copy the current word, `yy` to copy the current line
- `p` to paste after, `P` to paste before
- for pasting into a pair of brackets/quotes etc., move to the opening one (e.g. use `Esc` + `b`), then `p` or `Cmd+v`
- `yyp` to duplicate a line
- `<leader>+s+R` to search the registers for cut/copied text
- on Mac, `Cmd`+`c`/`v`/`x` also works despite which mode Vim is in
- but it seems to be not working stably across difference instances of Vim, especially when inside various plugins
- `y` usually guarantees the text is copied to the system clipboard, then use it in other applications
some useful key mappings in Neovim › Search & replace
some useful key mappings in Neovim › Search & replace
- Search
- `/` to search forward, `n`/`p` to go to next/previous match
- `?` to search backward
- `*` to search the word under the cursor
- remember to press `Enter` after typing the search term
- remember to treat the search as a regex
- i.e. to escape `\`, `()`, `[]`, `{}`, `^`, `$`, `*`, `+`, `?`, `|`, `.` etc.
- use `<leader>+h` to clear the search highlight
- `gn` to select the next match, `gN` to select the previous match
- repeating this would select *to* the following matches
- prefix with an operator to operate on the selected text
- Replace
- use `%s/before/after/g` to replace all occurrences, remember`%`, otherwise it will only look for the pattern in the current line
- `<leader>+ss` to toggle the search and replace panel
- `<localleader>+r` to replace all occurrences
- manually: use `gf` to go to each file, do edits, then `Ctrl+o` to go back and continue for the next file
some useful key mappings in Neovim › Visual selection
some useful key mappings in Neovim › Visual selection
- Select text
- use `V` to enter line visual mode
- this is the most frequently used visual mode, to select multiple lines
- lowercase `v` can be used for character visual mode, but I find it less useful
- `Ctrl+v` to enter block visual mode, i.e. select by column
- Indentation & comment
- use `<<`/`>>` to indent/unindent the current line
- use a single `<`/`>` to unindent/indent the selected text
- 🌕
- `<leader>+/` to toggle comment
- works for both current line and selected text
- 💤
- `gc` to toggle comment for selected text
- `gcc` to comment/uncomment a line
- Multiple-cursor editing (⧉)
- use `/xyz` + enter to search for `xyz`, then `cgn` to change it to something else, `Esc`, then
- use `.` to do the same for next occurrences
- use `n` to skip, and `u` to undo
- use `Ctrl+v` and direction keys (e.g. `j` or `5j`) to vertically select
- use `c` to change
- use `I` to prepend
- use `A` to append
- use `d` to delete
- type the new text, then `Esc`, then it will be applied to all lines of selection
- use `gv` to reselect the last selection
- Visual selection with mouse/touchpad
- motion-compatible selections
- dragging works like `v`
- triple click + scroll works like `V`
- `alt/option` + drag works like `Ctrl+v`
- select and
- ✅ delete by `d`/`x`
- ✅ cut/copy/paste
- ✅ comment/uncomment
- ❌ typing
- ✅ use one of `i`, `a`, `c` etc., then start typing
- ❌ indent/unindent with `Tab`/`Shift+Tab`
- ✅ indent/unindent with `<`/`>`
- vertical select and
- ✅ delete
- ✅ paste
- ❌ typing
- ✅ use one of `I`, `A`, `c`, then start typing
- Recording
- `qa` starts recording user's inputs, `q` quits recording, `@a` replays the recording, `a` could be any other letter
- it could serve as ad hoc key mappings
Diagnostic, quickfix and code actions
Diagnostic, quickfix and code actions
- Diagnostics
- by default, diagnostics are shown as virtual text, I've disabled it for now
- `<leader>+l` with `j`/`k` to move between diagnostics
- `<leader>+ld` to show diagnostics in the current buffer
- `<leader>lw` can search for diagnostics in workspace
- `Trouble` can be used to show diagnostics in a separate panel
- `<leader>+xx` to open the trouble panel at the bottom
- use `<leader>+xX` to see only the current buffer's diagnostics
- click on diagnostics to jump to the corresponding location
- `<leader>+lq` to open the quickfix list
- `<leader>+la` to open the code action list
Terminal
Terminal
It's very important to stay in the flow and Zen mode as much as possible. Split windows for terminals breaks the flow, so I prefer to use float terminals.
- Float terminals
- 🌕 `Ctrl+\`to toggle a float terminal
- 🌕 number + `Ctrl`+backslash to toggle the n-th float terminal
- 💤 same, but with `Ctrl+/`
- it's insert mode on first launch
- but usually enter normal mode when lost focus
- Split terminals
- `:term` to open a terminal
- it's normal mode by default, `i` to start typing commands
- `:sp term://zsh` to open a terminal running `zsh` at the bottom
- 📦
- use `<leader>+h` to open a new horizontal split terminal
- `:q` to hide terminal
- `<leader>+pt` to pick hidden terminal
- Working inside the terminal
- `exit` will exit the terminal and close the window associated with it
- `Ctrl`+`c` can be used for interrupting the terminal
Git & Github
Git & Github
- git
- install and use `lazygit`
- `<leader>+gg` to open lazygit, `q` to quit
- on a file/directory
- space to stage/unstage, `i` to ignore, `d` to discard
- `c` to commit, `P` to push, `p` to pull
- `r` on a commit to reword
- in editor, `<leader>+gs` to stage the current hunk, `<leader>+gr` to revert the current hunk
- usually lazygit is good enough, one can also use `:DiffviewOpen` to inspect diff and handle merge conflicts
- Github Actions
- `<leader>+ga` to open the Github Actions split window
- deprecated: `<leader>+gh` because it conflicts with 💤
- `gj` to open the job under cursor, `gr` for the run, `gw` for the workflow file
- `<leader>+gq` to close the split window
- Octo
- `:Octo <Tab>` to operate on issues and PRs
- it's interesting but I've disabled it for now, in favor of using the web interface
Auto-completion
Auto-completion
- Auto-complete
- with Github Copilot
- `:Copilot setup` to authenticate etc.
- `Tab` to accept suggestions
- `Shift+Tab` to use the normal Tab
- with `blink.cmp`
- I've configure it to not triggered by default, in favor of Github Copilot
- toggle by `Ctrl+q`
- could also be triggerd by `down` in insert mode
- up/down to cycle through suggestions, `Enter` to accept
- the above is set up so all this key mapping are explicit, intuitive and won't interfere with `<Tab>` for Github Copilot
- with `nvim-cmp` (deprecated)
- `Tab` to cycle through suggestions from `cmp`, reverse cycle with `Shift+Tab`
- continue to type to select a suggestion, this is better then hitting `Enter`
- `Ctrl+e` to reject suggestions, and `Tab` to take suggestions from Github Copilot
- LLM Chats
- Github Copilot
- `<leader>+aa` to toggle the chat, `<leader>+al` to clear chat history
- `<leader>+a` + a character
- for selected code block, **e**xplain, **r**eview, **o**ptimize, **R**efactor, **t**est
- **d**ebug, **f**ix, co**m**mit log, **n**aming etc.
- `?` to select the model
- `C-s` to send the prompt
- `:help copilot` to learn more
- Aichat
- `aichat` with a little setup at `~/Application Support/aichat/config.yaml`
- `.` + tab to see available commands
- Aider
- it's great for multiple-file code generation
- I've created a `aider` shim to run it in a virtual environment with preferred configurations
- `/` + tab to see available commands
- mostly it's a combination of `/add`, `/web`
- use `/token` to check token usage, use `/clear`, `/drop` and check `/map` to save token usage
- Code Companion
- `<localleader>+a` to toggle the inline chat (works also for selection)
- `<localleader>+z` to toggle the chat sidebar
- Parrot
- `<leader>+pr` to rewrite the selection
- `<leader>+pp` to implement the selection
- `<leader>+pn` to start a new chat, optionally with the selection
- select and `:Prt` + `<Tab>` to select advanced prompts
- `:PrtInfo` to inspect configurations
- `:PrtModel` to select the model
- I've configured it to use a buffer to input the prompt, escape twice to send it
- it seems unable to stop generation sometimes, use `:PrtChatStop` to stop
- Avante (deprecated for now)
- `<leader>+aa` to open the chat, use `a` to accept individual suggestions, or `A` to accept all
- select code and `<leader>+ae` to modify code
- it's interesting but I've disabled it for now, in favor of Github Copilot
- Spellcheck
- to use NeoVim's built-in spellcheck
- use `:set spell`
- `]s`/`[s` to move between misspelled words
- `zg` marks a word as good, `zw` marks a word as wrong
- `zug`/`zuw` to undo
- `z=` to see suggestions
Useful plugins
Useful plugins
- Conform
- formart on save using LSP default formatter
- `<leader>+lf` to format the current file
- showkeys
- `<leader>+kk` to show keys screencaster on top-right corner
- symbols
- `<leader>+se` to fuzzy search symbols, e.g. emoji, LaTeX
- Lean
- set local leader to " " (tentative)
- `<localleader>+i` to toggle Lean Infoview
- `<localleader>+r` to restart Lean server for the current file
- Forester
- `<localleader>+c` to create a new tree and open it
- `<localleader>+b` to browse and search trees by title
- `gf` to go to the tree under the cursor
Further reading
Further reading
See the following articles for further inspirations: - useful tools and key mappings for TUI for related TUI key mappings. - Lucas on Vim bindings for discovering more key bindings - Vim cheat sheet for key mappings that apply to vanilla Vim. - VSCode Vim ROADMAP for key mappings that apply to (limited) VSCode Vim mode, but now I have switch to use the real NeoVim. - Keybinds overview for LunarVim key mappings. - zed-101-setup for configurations and key maps inspirations. - My Favorite Neovim Plugins - You don’t need more than one cursor in vim When I use VSCode, I would also use vscode-neovim which would connect to my real NeoVim instance that has some basic configurations here. Zed's Vim mode has many widely used enhancements built in, see also rationale here.
initial survey on headless render/testing for WebGL [uts-001N]
initial survey on headless render/testing for WebGL [uts-001N]
I want to be able to run headless render or visual regression tests, both locally where GPU is available, and on CI where GPU has to be emulated. The ingredients seems to be Storybook+Playwright+Xvfb. - use OrbStack as local docker engine - use act (usage) to run GitHub Actions locally - use Storybook to building pages and components in isolation - use Playwright to verify the visual appearance on different browsers - use Xvfb to emulate a display server If I'm a bit more ambitious, I would like to be able to do the same for WebGPU. At least we do know that Xvfb support OpenGL via mesa (which also supports Vulkan etc.), and there are some libraries to run WebGPU via WebGL 2 (e.g. wgpu). Some resources I found so far: - Effortless CI Integration: Running Playwright Tests with GitHub Actions uses `xvfb-run` - `playwright`'s own CI uses `xvfb-run` - Headless chrome – testing WebGL using playwright demonstrates WegGL testing when GPU is available, see also its writeup - Options to enable GPU Hardware Acceleration in headeless mode - use xquartz with PyVirtualDisplay on Mac - use libosmesa with Chrome from 2016 - use VirtualGL with Xvfb ⧉For an earlier survey on headless testing, see SSR of WebGL.
SSR of WebGL [uts-0013]
- August 31, 2024
- Utensil Song
SSR of WebGL [uts-0013]
- August 31, 2024
- Utensil Song
## Server-side rendering of WebGL Combining `xvfb-run`, headless-gl, three.js, should make it possible, e.g. see Headless rendering with THREE.js, see also: - sharp for rendering to various image formats - three.js + headless.gl rendering with texturing in CoffeeScript - How to run OpenGL based tests on Github Actions ## Plotly.js I wish to draw a style similar to Project contour profiles onto a graph by Matplotlib, which plots a 3D surface then its contour profiles projected to surrounding planes. Plotly.js has a similar example as Surface Plot With Contours. Plotly requires a `div` element to render the plot, it will initialize a WebGL-capable `canvas` to do so. It has support for using virtual WebGL context but no native way to specify a `canvas` from the outside. When running in headless mode from node, we will typically use jsdom which in turn uses node-canvas that's not WebGL-capable. There is an open issue to detect the presence of node-canvas-webgl and use it, as it integrations `node-canvas` and headless-gl. Another idea is to make NPM packages `get-canvas-context` and in turn `webgl-context` to handle this. A commercial plot libraries `LightningChart JS` has made Headless server use support for itself, which could be used as a reference. Should I Render Three.js to Video on the Client or Server? has some discussions on this topic.
initial survey on writing Rust in Forester [uts-0011]
- August 31, 2024
- Utensil Song
initial survey on writing Rust in Forester [uts-0011]
- August 31, 2024
- Utensil Song
I wish to be able to call rust libraries that are WASM compatible to use it for both BSR and SSR. Here is my initial survey: - wasm-pack and wasm-bindgen are the two main tools for building and binding rust to javascript, more info see awesome-rust-and-webassembly - I wish to write one-file Rust and specify the dependencies in the file, rust-script is similar in spirit but it's for server-side execution. - I wish to find prior art on doing this with bun, found bun-ffi-rust and hyperimport, but again, it's for server-side execution.
some links for learning shaders [uts-000H]
some links for learning shaders [uts-000H]
readings
readings
- Ray tracing weekend series [shirley2024ray1][shirley2024ray2][shirley2024ray3] is a good starting point for learning ray tracing.
- The Book of Shaders [vivo2024book] is a good starting point for learning shaders.
- [glassner1989introduction] is a classic book on ray tracing, now free to download here.
- [pharr2023physically] is a complete, illustrative, and physically based ray-tracing renderer book, free to read on line.
- Autodesk Standard Surface contains references to many concepts and formulas for surface shaders.
libraries and tools
libraries and tools
- One could use GlslEditor (which provides widgets to adjust colors, 1-3D numeric values etc.), GlslCanvas or glslViewer to play with the shaders. They are crreated by the authors of The Book of Shaders.
- ShaderMania seems to be a good tool to play with shaders. Similarly there are Shadertoy, which has a VS Code extension and a basic ThreeJS port.
- stackgl provides many packages for using in GLSL. LYGIA is a similar effort, targeting a wider range of languages: GLSL/HLSL/MSL/WGSL/CUDA, it also has great integration with many tools, including ObservableJS.
- For GA, there are miniPGA.glsl, slerp optimization, Spinor 2d, and G2 Multivector-Valued Functions.
- MPR implements [keeter2020massively] on GPU, while Fidget implements it on CPU.
- Easy steps to implementing a Shadertoy in React Three Fiber
- Workflow from Shadertoy to React Three Fiber - R3F
- The Study of Shaders with React Three Fiber
some links for rendering implicit surfaces [uts-000G]
some links for rendering implicit surfaces [uts-000G]
# readings: raymarching on implicit surfaces - [singh2009real] has reviews on related work, an algorithm and many examples. But it has no code. - Ray Marching and Signed Distance Functions is a good introduction to ray-marching and signed distance functions, and the author learns from Inigo Quilez. - Rendering Worlds with Two Triangles with raytracing on the GPU in 4096 bytes by Iñigo Quilez in 2008 - Raymarching Distance Fields in 2013 - raymarching terrains by Iñigo Quilez in 2002 - Volumetric Rendering: Raymarching in 2016 - Painting with Math: A Gentle Study of Raymarching in 2023, which has interative illustration of ray-marching algorithm, and shader examples from simple to complex - CUDA Ray Marching by Jonathan Granskog - Slides on GPU Ray Marching by Alex Benton in 2017–18, with more related materials here. - Ray Tracing Deterministic 3-D Fractals in 1989 - Ray-marching Thurston geometries in 2022 - PU-Ray: Domain-Independent Point Cloud Upsampling via Ray Marching on Neural Implicit Surface in 2024 - Ray Tracing Harmonic Functions in 2024 - Lipschitz-agnostic, efficient and accurate rendering of implicit surfaces in 2024 - What is raytracing/raymarching/raycasting - Ray Marching in JS, the source code has a link to the principle behind ray marching shadows: soft shadows in raymarched SDFs - 2010 - Raymarching Voxel Rendering in 2017 - UC Berkeley CS184/284A Lecture 9: Ray Tracing & Acceleration Structures in 2024 - Third Year and MSc Interactive Computer Graphics in 2008 - Raymarching Distance Fields in 2013 - Perfecting anti-aliasing on signed distance functions in 2025 # libraries and tools: raymarching on implicit surfaces - SURFER renders implicit surfaces using ray-tracing, the result is stunning well. It also has a Java library with many examples. - Raycasting Implicit Surfaces based on CindyJS is Web-based implicit surface renderer using ray-tracing, and the source code is best suited for reproducing and learning. It also has a rich set of examples. - Raycasting a surface of degree 4 is a relatively simpler example of ray-tracing implicit surfaces with source here. - mla has a series of shaders from simple to complicated to render the Kummer surface, see here. mla has also ported a tiny ray tracer here which could be a starting point. - A simpler but more versatile ray-tracer for implicit surfaces is Implicit surfaces created by Rogolop. - 3D Bifurcation Diagram - MA1104-implicitplot has a naive implicit surface plotter. - usegpu.live demo of ploting implicit surface - Surface Plotter makes use of Paul Bourke's Marching Cubes algorithm with edge table, to turn implicit surfaces into polygonal meshes. See Marching Cubes and its references. ## Implicit reconstruction or polygonization - A Heat Method for Generalized Signed Distance in 2024 - Robust Creation of Implicit Surfaces from Polygonal Meshes in 2002 - Curvature Dependent Polygonization of Implicit Surfaces in 2004 - Implicit Meshes for Modeling and Reconstruction in 2018 - Differential Geometry in Neural Implicits in 2022 - Differentiable Iterated Function Systems in 2024 - Adaptive grid generation for discretizing implicit complexes in 2024 - SDFGen: A simple commandline utility to generate grid-based signed distance field (level set) generator from triangle meshes, using code from Robert Bridson's website. Found from Merging Meshes with Signed Distance Fields. - sdf: Generate 3D meshes based on SDFs (signed distance functions) with a dirt simple Python API. - SDFStudio: A Unified Framework for Surface Reconstruction For learning shaders, see some links for learning shaders. Convert some of the links to citations. I would like to have a formal specification of the raymarching algorithm (in algorithm2e or algorithmicx+algpseudocode or even algpseudocodex), and find propositions worth proving.
Distributing my binaries [uts-016P]
Distributing my binaries [uts-016P]
- Repology - brew for mac & linux - personal tap repo: see - Taps (Third-Party Repositories) — Homebrew Documentation - Adding Software to Homebrew — Homebrew Documentation - `create`, `bottle` in brew(1), also `bump*` - Windows or all platforms - Aqua private registery - then supported by mise or maybe more - see Develop a Registry | aqua
Using Zig to build more [uts-016O]
Using Zig to build more [uts-016O]
- C/C++ projects
- All Your Codebase | Loris Cro's Blog
- All Your Codebase
- no GiNaC yet
- help rust to cross-compile
- rust-cross/cargo-zigbuild
- Compile Cargo project with zig as linker for easier cross compiling
- help PyPI to store less
- The Python Package Index Should Get Rid Of Its Training Wheels | Loris Cro's Blog
- zig is also available as a PyPI package
- ziglang · PyPI
- zig alternative to PyO3/maturin: Build and publish crates with pyo3, cffi and uniffi bindings as well as rust binaries as python packages
- spiraldb/ziggy-pydust: A toolkit for building Python extensions in Zig.
- the orginal template that ueses poetry
- the community template that uses uv and hatchling
- where hatchling seems to be a better build backend than setup tools post 3.12 for projects with native extensions and custom build hooks
- see also Why Hatch? - Hatch
posts [uts-0168]
posts [uts-0168]
My Day 1 with jj [uts-016M]
My Day 1 with jj [uts-016M]
> Discuss on [/r/git](https://www.reddit.com/r/git/comments/1lvbzo8/my_day_1_with_jj_jujutsu/) and [Bluesky](https://bsky.app/profile/iutensil.bsky.social/post/3ltnz23tp2k2z)
## TL;DR
I became productive with [jj](https://github.com/jj-vcs/jj) (Jujutsu, *dauntless* version control) on day 1. This is my story, along with my mindset changes, and delicious recipes. Scroll down to the end for a short list of when to use what command/alias.
## Why try `jj`?
Well, *dauntless* is not the official slogan, but I really need it to describe a liberating feeling much stronger than "fearless".
Git is an intimidating black box for some, but I don't fear it in my daily work, as I'm skilled enough to easily recover work if I messed up.
`jj`, on the other hand, gives me the ultimate power in the river of time:
> In `jj`, I can go anywhere in history, do anything, be done with it, and history will reshape itself accordingly.
I wouldn't know this when I first read [Steve's Jujutsu Tutorial](https://steveklabnik.github.io/jujutsu-tutorial/) months ago, it's well written but still a haystack to find the needle that would click with me.
[jujutsu on tangled](https://blog.tangled.sh/blog/stacking) intrigued me, by telling me "Jujutsu is built around structuring your work into meaningful commits", and showing how it helps contributors to iterate on changes with dependencies on other changes, individually reviewed, reworked, and merged. But what if I just use it on my personal repo, and don't care much about clean history?
[A Newbie's First Contribution to (Rust for) Linux: Git gud](https://blog.buenzli.dev/rust-for-linux-first-contrib/#git-gud) shows the author's Git workflow to contribute to Linux kernel with a lot of fast moving forks. The configuration for `rebase` and `rerere` seems really solving the roadblocks of contributing to a thriving project. But the author said: "Jujutsu is much better at this kind of workflow and what I was actually using most of the time. I first discovered this workflow while using Jujutsu and only later found out you could do something similar with Git." A refreshing remark! Maybe I do need native and friendly support for more advanced features, even just to alleviate my mind.
Eventually, pksunkara's [Git experts should try Jujutsu](https://pksunkara.com/thoughts/git-experts-should-try-jujutsu/), and his side-by-side workflow comparisons with Git, and his [`jj` configuration full of aliases](https://gist.github.com/pksunkara/622bc04242d402c4e43c7328234fd01c) that gave me the first boost, so I finally decided to spend a day with `jj`. I definitely no Git expert, but those aliases really look attempting, what if I can pick my few favorites?
I started the journey with a minimal goal. I just wanted to recover my Git workflow in `jj`, as `jj` coexists with a local Git repo, and I need `jj` to work with my GitHub (or any code forge I might migrate to in future). I learned much more, and they are much easier than I thought.
## Protect my main branch
First thing, I went to my GitHub settings and [protected my main branch](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches), to at least forbid force push, in case (my misuse of) `jj` messes up the remote. ([Here](https://ricky-lim.github.io/blog/protect-your-main-branch-in-github/) is how to do even better from CLI.)
## Install and configure `jj`
I use [just](https://github.com/casey/just) to write code snippets as tasks. Installing `jj` on Mac, and prepare the configurations is simply:
```make
prep-jj:
which jj || brew install jj
mkdir -p ~/.config/jj
cp -f dotfiles/.config/jj/config.toml ~/.config/jj/config.toml
jj config set --user user.name "$(git config --get user.name)"
jj config set --user user.email "$(git config --get user.email)"
jj config list --no-pager
```
The [`dotfiles/.config/jj/config.toml`](https://github.com/utensil/forest/blob/main/dotfiles/.config/jj/config.toml) is an adapted version from pksunkara's, and all changed places are annotated with `[NOTE]` comments and inspiring links. By copying to the right path, it becomes the user-wide configuration.
`jj config set --user ` will write additional and more personal information into the same file (assuming git has already configured these information), so they came later. Finally, the configuration is listed for inspection.
Every time I've updated the configuration, or I'm on a new machine, I'll run `just prep-jj` again, so I'm all set again. Your way to manage code snippets might be different, but it all boils down to similar few lines.
You might want to change the line `editor = 'hx'` back to favorite editor, as mine is now [Helix](https://github.com/helix-editor/helix).
It also assumed that you have installed [delta](https://github.com/dandavison/delta), a syntax-highlighting pager for git, diff, grep, and blame output. It's eye candy, and makes the diff much more clear.
## Initialize the Git repo
`jj` can coexist, or officially, *colocate* with a local Git repo. I place all my local Git repos under `~/projects/` so my just task looks like this:
```make
init-jj PROJ:
#!/usr/bin/env zsh
cd ~/projects/{{PROJ}}
jj status || jj git init --colocate
```
`jj status` will detect if it's already a `jj` repo, otherwise we will initialize `jj` to colocate with Git. I try to make all my tasks open to reentrance, so I can easily tweak and rerun them.
Actually it's already alias to `jj init` by pksunkara, but here we go with the origin command, to avoid locked-in. But later on, I'll use more aliases, and you may consult [the configuration](https://github.com/utensil/forest/blob/main/dotfiles/.config/jj/config.toml) for the full command.
## Thrown into limbo
Once `jj` is initialized, we are no longer on any branch of Git. If we go back to `git` or `lazygit`, we'll see that we are on a detached state.
I don't know about you, but my feeling was like floating in the air, with no solid ground under my feet.
I felt much better when I learned that what I commit as *change*s in `jj` will still be reflected in Git as commits, and commits can still find their parents.
We can go back and edit a *change* then commit again, it would be become a new Git commit, but its identity as the original *change* remains the same. So changes can still find their parent changes.
Actually, a branch in Git, is just a reference always point to the latest commit of the branch, so its history can be traced via parents.
`jj` has *bookmark* for pointing to a *change*. Unlike in Git, when you commit more changes on top of it, the *bookmark* doesn't move to the latest change automatically, however, *we* can move it.
With these 2 powerful concept, we are lifted off ground, start flying among changes, with bookmarks marking our path.
## The working copy
OK, we are not on any branch, so where are we?
`jj log` (or simple `jj l` or even `jj`) gave me something like these at the top:
```
@ rrptyzpt 0f23c873 (empty) (no description set)
◆ vmzsxwzu f800c4ed My last commit on the main branch
```
That's a lot to take in!
`f800c4ed` and `My last commit on the main branch` can be recognized as my last Git commit hash and message.
`vmzsxwzu` is the *change id* assigned to it, along with a diamond ◆ indicating that it's immutable: It's written on the stars by Git, so we can't edit it.
But what's the commit-like stuff on top of it? I didn't like it, and even tried to `jj abandon` it, but it keeps coming back with a new *change id* and a new commit hash.
Finally, I accepted it as the "working copy", indicated by `@`. Unlike in Git, where I'll be on HEAD, along with some local changes to be staged, in `jj`, I'm already on the future commit as a working copy. That's why sometimes we need `@-` that points to the parent of `@`, the last committed *change*.
`(empty)` means I haven't made any edits to this *change*. `(no description set)` means I haven't described what I'm going to do for this change (via `jj desc`).
I'll feel much better if it's just `(no description)`, as the `set` makes me feel guilty for not providing a description ahead. And it turns out that I didn't need to! Even after I'm done with it, and moved on (`jj` will keep the change in its history, like automatically doing `git stash`). If I have trouble recognizing the change without a description, I could always use `jj d` to inspect the diff.
`jj s` (status) shows it more verbosely:
```
The working copy has no changes. │
│Working copy (@) : rrptyzpt 0f23c873 (empty) (no description set) │
│Parent commit (@-): vmzsxwzu f800c4ed main | My last commit on the main branch
```
The change id of my working copy begins with `rr` (bold and colored, indicating we can refer to it uniquely with `rr`).
It's a bit annoying to enter and quit pager, and unable to see the latest changes, so I'v configured `jj` to use no pager and only occupy about 2/3 screen.
There's also alias `jj lp` that shows private (i.e. not pushed) changes, and `jj lg` that shows all changes, including elided changes that you just pushed.
## Commit
I worked on a repo that I'll also add my just tasks and configurations for `jj` into it. So I edit the justfile in my editor Helix, and saved it to disk.
Alias `jj d` will show the diff, that confirms that `jj` has seen our edits.
We can now commit the change. `jj commit` will commit everything, opening the configured editor for commit message (just save and quit to submit, quit without saving to cancel).
Aliases like `jj ci` will also fire up a built-in diff editor to interactively select which files, or even which parts (called sections) to commit. Arrow keys can fold/unfold files/sections, space to select, `c` to commit, and `q` to quit. (I couldn't find how to commit until I tried `c`, there is no visual hint at all, unless you use mouse to click on the menus, but I didn't realize that I could do it on day 1, I tried every possible key combination to trigger the menu, no luck).
I often find myself repeatly use `jj ci` to review, select and commit, to split my local edits into a few independent changes.
With alias `jj cim <message>`, we can directly supply the commit message from CLI without opening an editor, then select which parts to commit.
## New
After commit, we'll again on an empty change with no description, so we can continue making new edits.
But if after working for a while, I suddenly want to discard my (uncommitted) edits, I can do `jj n rr` to start over from the last change. The uncommitted edits will be still there in `jj` as a change, but local files will be reset to the state when we commited `rr`.
Here `rr` could be any other change id, or any bookmark, or any *revset* in general. We'll learn more about *revset* later, for now, we just need to know that a change id, a bookmark, `@` and `@-` that we know so far are all *revset* s.
`jj n` (new) effectively spins off a new history line from the parent change. We can go along the line for a few changes, and spin off from anywhere again, without having to create a named branch.
## Edit
In Git, I seldom amend a commit, usually I just use `reword` in lazygit to amend the commit message, or `reset --mixed` (`gm` in lazygit) to discard history after a commit, then stage and commit them in a better way again.
In `jj`, if I don't like a change, I could go back and edit it:
```
jj e <revset>
```
will auto stash any dirty edits, and reset local files to the state of that `<reveset>` (read: change), I can happily do any edits, or commit it with alternative selections of files or sections.
We don't need to explictly commit, when we use `jj n <revset>` or `jj e <revset>` to jump to anywhere else, the local edits will be automatically committed to the original change.
## Evolution of a change
Wait, what if I messed up when editing a commit, and left it, can I go back?
At that time, it's beyond what `jj undo` can easily do, especially we might be confused by what we did and didn't do.
The first thing we can do is to inspect how a change has evolved over time by
```
jj evolog -r <revset>
```
It looks like this:
```
❯ jj evolog -r uo
○ uoxoknux 92fb8d3a (no description set)-- operation a0693515ab31 (2025-07-09 11:54:16) snapshot working copy
○ uoxoknux hidden 1f73cdfd (no description set)-- operation 79813357f450 (2025-07-09 11:52:58) snapshot working copy
○ uoxoknux hidden c2bf8f4f (empty) (no description set)-- operation a22c21ce9fc1 (2025-07-09 11:52:32) new empty commit
```
We can inspect the diffs of each hidden commits with their commit hash via `jj dr <revset>` (alias for `diff -r`) where `<revset>` should be the commit hash to disambiguate.
The we can use either `jj n` or `jj e` on the commit hash of our choosing, to continue work.
Note that the change id would become ambiguous, so we need to `jj ad` one of the commit hash so we can continue to refer to the change id.
It looks like this for me:
<details>
<summary>click to expand</summary>
<pre>
❯ jj n 1f73
Working copy (@) now at: unyrkpru 003d7750 (empty) (no description set)
Parent commit (@-) : uoxoknux?? 1f73cdfd (no description set)
Added 0 files, modified 1 files, removed 0 files
❯ jj e 1f73
Working copy (@) now at: uoxoknux?? 1f73cdfd (no description set)
Parent commit (@-) : mxowtxvr 68b37035 (no description set)
❯ jj evolog -r uo
Error: Revset `uo` resolved to more than one revision
Hint: The revset `uo` resolved to these revisions:
uoxoknux?? 92fb8d3a (no description set)
uoxoknux?? 1f73cdfd (no description set)
Hint: Some of these commits have the same change id. Abandon the unneeded commits with `jj abandon <commit_id>`.
❯ jj ad 92f
Abandoned 1 commits:
uoxoknux?? 92fb8d3a (no description set)
Rebased 1 descendant commits onto parents of abandoned commits
</pre>
</details>
We may also use `jj op diff --op <operationid>` to inspect meta changes of an operation (it has `--from` `--to` variant so it also works on a range of operations).
## PR with an ad hoc branch
> see also the official doc [Working with GitHub: Using a generated bookmark name](https://jj-vcs.github.io/jj/latest/github/#using-a-generated-bookmark-name)
If I like my changes so far on the current history line, I could open an unnamed PR by first commiting changes, then using alias
```
jj prw
```
where `prw` stands for PR working copy.
Per our config, it will push to a branch named `jj/<changeid>` on origin, then open a PR via `gh` (Github's official CLI to interact with issues, PRs, etc.), it will ask you for a title (default to the description of the first change), and a body, we could just press enter all the way to submit, and change anything later.
Personally I think such a tiny ad hoc PR is a good way to record the proposed changes, even for a personal repo. But if pusing to a branch is all you need, alias `jj pscw` (push changes of working copy) will do.
After merging the PR, we need
```
jj git fetch
```
to let both Git and `jj` to learn about the changes.
Here is how `jj l` looked like after I PR a change "Make a start on trying jj" as `#1`, merged it on GitHub, then fetched the changes:
```
◆ rzyozkll 929fe190 main Make a start on trying jj (#1)
│
◆ vmzsxwzu f800c4ed My last commit on the main branch
```
`gh pr view #1 -w` can open the PR in the browser.
If we have made edits to the change (but not new changes on top of it, because they would be pushed to their own `jj/<changeid>` branch), like `jj e` or `jj sqar` (introduced below), we can use
```
jj pscw
```
where `pscw` stands for pushing local changes of working copy.
The result looks like this:
```
Changes to push to origin:
Move sideways bookmark jj/stwxmxoqkyym from 33c46b992efc to 4d3c2a60e0d2
remote: Resolving deltas: 100% (3/3), completed with 3 local objects.
```
If we have made other changes on top of the change, we can treat `jj/<changeid>` as a named branch like below (i.e. `jj bs jj/<changeid> -r <latest changeid>` and `jj psb jj/<changeid>`).
## PR with a named branch
This would best resemble a usual GitHub workflow.
First we create a local bookmark:
```
jj bs <bookmark> -r <revset>
```
`<revset>` could be just a change id, `@-` could come in handy to refer to the last committed change.
`<bookmark>` is the name of the bookmark, just like a normal branch name. And `bs` is the alias for `bookmark set`.
We can see if the bookmark is correctly placed from `jj l`. If we don't like it, we can either `jj undo` or `jj bd <bookmark>` (bookmark delete).
Then we can PR that bookmark:
```
jj prb <bookmark>
```
This would push to a branch named `<bookmark>` on Github, then use `gh` to PR it.
It looks like working on a branch in Git, but after we commit more changes, we need to call `jj bs -r <revset>` to set it to desired `<revset>`, then
```
jj psb <bookmark>
```
Note that the alias begins with `ps` instead of `pr`, meaning "push bookmark".
## Fetching
What if we committed some changes on GitHub, like accepting a review suggestion, we need to use `jj git fetch` to make `jj` know about the changes. We'll see something like
```
bookmark: our-name-of-bookmark@origin [updated] tracked
```
`origin` is the remote on GitHub. `[updated]` means `jj` noticed the changes on the remote, `tracked` means the local bookmark is also automatically updated.
If it's not tracked, we can use
```
jj bt our-name-of-bookmark@origin
```
to track it.
Here is how `jj l` looks like when I PR a few changes in this way then fetched it:
```
@ nozpulso fd589b2a (empty) (no description set)
○ kpxkrxvm a22ed20a configure-jj* Add frequently used jj command alias
○ tvvoymuu 6808370c Keybindings for builtin diff editor
○ ylnlzpvx b20ac2d1 Adapt jj config from pksunkara
○ rnkttumw f6296b0a Improve configs in `just init-jj`
◆ rzyozkll 929fe190 main Make a start on trying jj (#1)
◆ vmzsxwzu f800c4ed My last commit on the main branch
```
## Rebase
But I didn't get such a clean history from the start. I'd begun with a few fixup commits, and one of the commits is mixed with different changes. And initially, I pushed it with an ad hoc branch, accepted a few review suggestions on Github.
After opening the PR, I've noticed a weird non-empty commit `xm`
```
○ ...more changes...
◆ rzyozkll 929fe190 main Make a start on trying jj (#1)
│ ○ xmnykxym 4dcb41d9 (no description set)
├─┘
◆ vmzsxwzu f800c4ed My last commit on the main branch
```
After inspecting the diff, I believe its changes is aborbed into `rz` (`#1`), so I rebased `xm` on top of `rz` to see if there is any diff left.
```
❯ jj rb -s xm -d rz
Rebased 1 commits to destination
```
where `rb` stands for `rebase`.
I just need to remember that I'll be rebasing source (`-s`) onto destination (`-d`).
Now I have
```
○ ...more changes...
│ ○ xmnykxym 2f622327 (empty) I think this is what absorbed into #1
├─┘
◆ rzyozkll 929fe190 main Make a start on trying jj (#1)
```
Nice, it's indeed empty, so I can be assured no work is lost.
It's an extremely simple use case, but I'm happy with being able to transplant a parallel change to be on top of another change, without much hassle.
## Squash
There are some other complications:
```
@ ...more changes...
│ ○ zquplvzx 2b572336 configure-jj Update dotfiles/.config/jj/config.toml
│ ○ nmuntxon 746cb300 Fix typo found by copilot
├─┘
○ ...some changes in between...
○ ylnlzpvx b20ac2d1 Adapt jj config from pksunkara
○ rnkttumw f6296b0a Improve configs in `just init-jj`
```
I want to absorb typo fixes `nm` and `zq` into `yl`, how do I do that?
It's as simple as correctly specifying `from` and `to`:
```
❯ jj sqa --from zq --to y
Rebased 3 descendant commits
Working copy (@) now at: srnwoqzq c831d68c (empty) (no description set)
Parent commit (@-) : kpxkrxvm 7d911838 jj/vzzzxqvnptov* | Add frequently used jj command alias
Added 0 files, modified 1 files, removed 0 files
```
where `sqa` is short for squash. Note from the output that any changes after them will be properly rebased.
There is also a shortcut if I just want to absorb a change into its parent: `jj sqar <revset>`.
I keep using the word "absorb" but `jj absorb` does a completely different thing (it splits a change, allowing some other changes to absorb it, by "moving each change to the closest mutable ancestor where the corresponding lines were modified last", that sounds like "desolve" to me).
## Summary
I could go on and try splitting a change, but the above is enough for day 1.
This doesn't demonstrate the full power of `jj`, but imagining how the same things could be done in Git, I'll definitely rather spend the time with `jj`.
I'll wrap up with a summary of the commands/aliases that would be enough for daily work:
### Getting started
| alias | when to use |
|-------|-------------|
| `jj init` | init `jj` in a local Git repo |
### Show
| alias | when to use |
|-------|-------------|
| `l` | show log, `jj` works better |
| `lp` | show private log |
| `lg` | show all log, even elided changes |
| `s` | show status |
| `w` | show status and diff |
| `d` | show the diff of current change |
| `dr <revset>` | show the diff of revision `<revset>` |
### Edits
| alias | when to use |
|-------|-------------|
| `n <revset>` | create a new change based on `<revset>` |
| `cm <message>` | commit everything with `<message>` |
| `ci` | commit the change, choose interactively, write commit message in `$EDITOR` |
| `e <revset>` | edit any `<revset>` after commit |
`<revset>` could be a short change id, a bookmark, and defaults to @ (working copy).
After edit, just go anywhere else (with e or n), the changes will be commited; or an explicit commit will do.
### Working with remote branch
| alias | when to use |
|-------|-------------|
| `git fetch` | will update local bookmark from remote branch |
| `bt <branch>@origin` | track remote branch |
### PR with named branch
| alias | when to use |
|-------|-------------|
| `bs <bookmark> -r <revset>` | move bookmark `<bookmark>` to `<revset>` |
| `psb <bookmark>` | push bookmark to remote branch named `<bookmark>` |
| `prb <bookmark>` | create a PR from `<bookmark>` to the default branch |
### PR with ad hoc branch
| alias | when to use |
|-------|-------------|
| `prw` | open (committed) working copy as a PR |
| `pscw` | push changes of working copy to remote branch named `jj/<changeid>` |
### History cleanup
| alias | when to use |
|-------|-------------|
| `undo` | undo last jj operation when messed up |
| `rb -s <src> -d <dst>` | rebase `<src>` onto `<dst>` |
| `sqar <revset>` | squash `<revset>` into its parent |
| `sqa --from <src> --to <dst>` | squash `<src>` into `<dst>` |
| `ad <revset>` | abandon a change |
| `evolog <revset>` | show how a change evolve in time |
| `op log` | show log of operations on jj |
| `bd <bookmark>` | delete a bookmark |
These aliases can be found in this [config file](https://github.com/utensil/forest/blob/main/dotfiles/.config/jj/config.toml) which is based on pksunkara's [gist](https://gist.github.com/pksunkara/622bc04242d402c4e43c7328234fd01c).
Trying Zig's self-hosted x86 backend on Apple Silicon [uts-016K]
Trying Zig's self-hosted x86 backend on Apple Silicon [uts-016K]
> TL;DR: I used `colima` to run an x86_64 Docker container (Ubuntu) on Apple silicon, to quickly test `zig build` with LLVM backend and with self-hosted backend, because it's both exciting and concerning (for missing all the goodies from LLVM) news. After Self-Hosted x86 Backend is Now Default in Debug Mode dropped, I immediately wanted to try it out, but I only have an Apple Silicon machine (e.g. Mac Mini M4 Pro). ## Running an x86 container on Apple Silicon According to Intel-on-ARM and ARM-on-Intel, I'm supposed to be able to run x86_64 Zig using `lima` with Apple's native virtualization framework and Rosetta. After some fiddling and searching, I've realized that I could just use `colima` to run an x86_64 container on an ARM64 VM, which is also backed by `lima`. OK, let's get started: First, install `colima` and prepare it properly: ```bash # we need `docker` CLI as the client which docker || (brew install docker; brew link docker) # (optional) while we are at it, get `docker-compose` and `kubectl` too which docker-compose || brew install docker-compose which kubectl || brew install kubectl # install colima which colima || brew install colima # this is to prevent othere docker daemons from interfering docker context use default ``` Next, let's start colima with Apple's native virtualization framework and rosetta: ```bash colima start --vm-type=vz --vz-rosetta ``` Because I have already used colima before, but without these flags, there is a warning saying that they are ignored, so I have to delete the existing colima VM and start over. (Warning: the following command will also DELETE all existing images! So I commented out them to prevent accidental execution.) ```bash # colima delete ``` Now, we can pull an x86_64 Docker container with Ubuntu: ```bash # asssuming `docker login` has been done already docker pull --platform linux/amd64 ubuntu:jammy ``` and start it (`--rm` means to remove the container after it exits, so we'll lose the changes made inside, remove this option if you want to keep the container): ```bash docker run --rm -it --platform linux/amd64 ubuntu:jammy bash ``` Inside the container, let's confirm that we are indeed running x86_64: ```bash uname -m ``` Cool, I'm seeing `x86_64`! ## Running `zig build` Now, we can install Zig and try it out: ```bash # we need a few basic utils apt update apt install -y wget xz-utils software-properties-common git # Download the corresponding Zig version with self-hosted x86 backend wget https://ziglang.org/builds/zig-x86_64-linux-0.15.0-dev.769+4d7980645.tar.xz tar xvf zig-x86_64-linux-0.15.0-dev.769+4d7980645.tar.xz # Make it available in PATH export PATH=/zig-x86_64-linux-0.15.0-dev.769+4d7980645/:$PATH # Verify its version and that it runs zig version # got: 0.15.0-dev.769+4d7980645 ``` Let's create a simple Zig project to test building it: ```bash mkdir projects cd projects mkdir zig_x86_64 cd zig_x86_64 zig init zig build ``` Success! `zig build run` gives ``` All your codebase are belong to us. Run `zig build test` to run the tests. ``` and `zig build test --summary all` gives: ``` Build Summary: 5/5 steps succeeded; 3/3 tests passed test success ├─ run test 1 passed 7ms MaxRSS:5M │ └─ compile test Debug native cached 68ms MaxRSS:44M └─ run test 2 passed 7ms MaxRSS:5M └─ compile test Debug native cached 67ms MaxRSS:44M ``` ## Comparing with and without LLVM But wait, how do I know it's actually using the self-hosted x86 backend? Hopefully someone has a better way, I just took the longer way to force Zig to build with and without LLVM. After reading the doc and some searching, I figured out that I could expose an extra option to `zig build` in my `build.zig` to set the corresponding flag for the executable, with only 2 edits: ```zig // EDIT 1 const use_llvm = b.option(bool, "use_llvm", "Force use llvm or not") orelse false; const exe = b.addExecutable(.{ .name = "zig_x86_64", .root_module = b.createModule(.{ .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, .imports = &.{ .{ .name = "zig_x86_64", .module = mod }, }, }), // EDIT 2 .use_llvm = use_llvm, }); ``` (Optional) I did the edits by running the following to install a helix editor so I can edit Zig code out-of-the-box: ```bash # https://docs.helix-editor.com/package-managers.html#ubuntu-ppa add-apt-repository -y ppa:maveonair/helix-editor apt install helix # then fire up `hx build.zig` and use it mostly like in Vim # I also installed zls by # cd /tmp # wget https://builds.zigtools.org/zls-linux-x86_64-0.15.0-dev.197+48fb941e.tar.xz # tar xvf zls-linux-x86_64-0.15.0-dev.197+48fb941e.tar.xz # cp -f zls /usr/local/bin/ # and checked that it works by # hx --health zig # so I can use `gd` to go to definitions! ``` Cool, now let's try building with LLVM: ```bash rm -rf .zig-cache && time zig build -Duse_llvm=true ``` ``` real 0m3.068s user 0m3.610s sys 0m0.363s ``` Then without (which should be the x86 self-hosted backend): ```bash rm -rf .zig-cache && time zig build -Duse_llvm=false ``` ``` real 0m2.112s user 0m2.812s sys 0m0.361s ``` Wow, it's indeed faster without LLVM! I've tested this a few times and getting consistent results. I'll also try this on more complex projects later, but it's so exciting that I just wanted to write a note for this. ### UPDATE 2025-06-15 I further tried using poop to get more metrics. First, get and install `poop`: ```bash cd /projects && git clone https://github.com/andrewrk/poop && cd poop && zig build && cp -f zig-out/bin/poop /usr/local/bin/ ``` Then let's run the cold start builds again: ```bash cd /projects/zig_x86_64 rm -rf .zig-cache* && poop "zig build -Duse_llvm=true --cache-dir .zig-cache-llvm" "zig build -Duse_llvm=false --cache-dir .zig-cache-nollvm" ``` Well, that doesn't work due to permission denied. And `--cap-add PERFMON` or even `--cap-add SYS_ADMIN` didn't work. Not even `--privileged`. See this issue. Let's try `hyperfine` instead: ```bash apt install -y hyperfine ``` Taking comments by `mlugg0` on reddit into account, a few factors should be ruled out for a more fair comparison (with C): 1. rule out the build time for `build.zig`; 2. rule out the overhead of panic handler 3. squeeze a bit of performance at the cost of some safety by disabling C sanitization. 1 means to build `build.zig` before the benchmark and after cleaning the cache (observing that `zig build --help` will build `build.zig` in order to get the options defined in the build script). 2 means to add the following to `main.zig`: ```zig /// Don't print a fancy stack trace if there's a panic pub const panic = std.debug.no_panic; /// Don't print a fancy stack trace if there's a segfault pub const std_options: std.Options = .{ .enable_segfault_handler = false }; ``` 3 means to pass `.sanitize_c = .off` to `root_module` in `build.zig`. With ```bash hyperfine --prepare "rm -rf .zig-cache* && zig build --help -Duse_llvm=true && zig build --help -Duse_llvm=false" "zig build -Duse_llvm=true" "zig build -Duse_llvm=false" ``` I got ``` Benchmark 1: zig build -Duse_llvm=true Time (mean ± σ): 1.392 s ± 0.052 s [User: 1.287 s, System: 0.126 s] Range (min … max): 1.329 s … 1.473 s 10 runs Benchmark 2: zig build -Duse_llvm=false Time (mean ± σ): 546.1 ms ± 13.6 ms [User: 570.1 ms, System: 128.7 ms] Range (min … max): 532.9 ms … 575.9 ms 10 runs Summary 'zig build -Duse_llvm=false' ran 2.55 ± 0.11 times faster than 'zig build -Duse_llvm=true' ``` which is indeed even faster! discussions on /r/Zig, Bluesky
What's next for LLMs? [uts-016C]
What's next for LLMs? [uts-016C]
This is no way a professional prediction, just summarizing some ideas popped into my head in a recent discussion with friends. Read this with a grain of salt. Reasoning, agent, and multimodality are top 3 research topics for LLMs, as far as I can tell. And for me, there is always the topic of efficiency or scalability. And of course, beyond that, world models, and intelligent robotics. Verifiable reinforcement learning boosted the reasoning performance as explored by DeepSeek and others, but it requires much more output tokens, to a factor of almost 10. That would be 10x inference compute, and to solve the same problem in the same time, you would need another 10x compute to achieve that. Such a 100x compute demand, is not desirable. I was wrong in 2023, about the inefficient inference of LLMs. I didn't like the quadratic scaling of the attention mechanism, but it turns out that there are more ways to work around the bottleneck than seeking linear attention such as RWKV and other alternatives. Inference time scaling, and MoE are both game changers. So I would expect myself to be wrong again about the cost of reasoning. And there are preliminary researches showing that reasoning is already inside and can be further trained into the LLMs. That is, reasoning should not be happening at the output layer, but intermediate layers. Writing down the reasoning process, should merely serve as a memory of explored paths, to keep things on track, or materialize the box to think out of. The waste is not just on the input side, there are significant waste of input tokens by prompts that are not part of the instruction nor the context, but guidance. These guidances should not just be cached, but "compiled", in a more efficient and controllable manner, while remaining the interpretability. Prompt engineering and reasoning by output tokens are two sides of the same coin: we are reaching better results in an interpretable manner, but much more expensive than it should be, and it would become obvious once we find the right principle. Of course, history relies on such detours to get back on track. Agent is another layer of waste, on top of individual inferences. Agents fall into fruitless planning and exploration, failing to snap out of the infinite loop, by acquiring the extra information or triggering the extra side effects. Their interactions with tools (e.g., MCP), agents (e.g., A2A), and humans (e.g., A2H) are all inefficient due to using natural language as the intermediate representation. Imagine an alien species with a far more efficient language, like the one depicted in *Arrival*. Such a language could express complex concepts like tool invocation with parameters using just a single token - or perhaps a single multimodal token combining multiple meanings. There should be special dense tokens, to represent tools or even ways to think (e.g., the MCP for "Sequential Thinking"). And why should a token just be an embedding of a high dimensional vector? Why isn't it a curve, a hypersurface, or a manifold? Take some time to think about this, while showing the visualization of the Biology of a Large Language Model on the screen. I believe using modularity other than human perceptions, as the intermediate representation, is the key to the next breakthrough. They would also represent the world model better. At the end of the day, it all comes down to human-level efficiency to reach human-level intelligence. And the efficiency will come from using the right principle, which will also result in better performance. And all of reasoning, agent, multimodality, efficiency, world model, and robotics, are all covered by this one integrated solution.
4 bugs caught me off guard recently [uts-016A]
4 bugs caught me off guard recently [uts-016A]
And it's non-trivial to hunt their families down.
But yeah, that's pretty much my job description, that is, to set up mechanisms to eliminate similar problems from all systems in future.
They are from different kind of systems and varying technical stacks, so it would be interesting to pin these specimens down for a display.
How to hunt their families down are left as exercises for the readers.
## Legacy configuration removal
The system in question is a proxy server that routes requests to different backends that are responsible for communicating with different third-party APIs. Two keys in the request are used to determine the backend: `party` and `service`, which indicate *who* does *what*, respectively. For the same pair of these keys, even if there is only one type of backend, there could be multiple instances in different availability zones (AZs) and regions.
There is a subsystem (let's call it the "Switch") to route requests based on the health of these instances. It's vital for the switch to always work, so the requests won't go to a bad instance that is already unresponsive.
The Switch will reuse the *static* configurations of the proxy that lists combinations of `party` and `service`, along with *dynamic* instance information. The static and dynamic information as a whole is written to a cache, whenever an arbiter detects unhealthy instances. The proxy will use the cache to change its routing dynamically.
There was a special party (let's call it "Bob") that requires 2 steps/services (namely "Pre" and "Main") to complete what other parties can do in 1 step ("Main"). These 2 steps are stateful in the sense that if an intance can't do "Main", requests should not be routed to "Pre" either.
So when the Switch reads the blob from the cache, a special check is in place to ensure "Bob" & "Pre" are in the combination list, if they are not, the switch will reject to read, and report an error as a monitoring metric which didn't set up a proper alerting threshold for sudden increase in error rate, because it's an error that never happened before, and is missed when SREs setting up the thresholds for important metrics.
10 years passed by, and "Bob" can also do it in one step, "Main". There are also many legacy combinations that are not used anymore. One day it becomes necessary to remove unused combinations, the includes the combination "Bob" & "Pre".
Bang! The Switch rejects all new writes to the cache for 6 days and no one noticed because no major outage happened, the error rate due to unhealthy instances was low enough to be ignored. The issue is only discovered when the same person is observing the Switch for a different deployment, and it took almost a day to figure out the root cause.
The interesting part? The same person who removed the legacy configuration placed those special checks 10 years ago, the reviewer of the removal also reviewed the check 10 years ago. The check was just an unthoughtful precaution, recalling the check and predicting its ramifications on config removal didn't cross the minds of both of them, even during the initial stage of debugging.
## Too many concurrent slow queries
There is a batch processing system (let's call it the "Sink") that loads different kinds of data from asynchronous nodes of production database clusters, according the configured rules about data source, conditions, how to process etc. There are many rate limits in place to prevent the system from overwhelming the database clusters, such as limiting the concurrent number of tasks, and the threshold of the number of concurrent queries on the same database node. It's also an assumption that the asynchronous nodes are not used for user-facing online queries but other batch processing systems.
The rate limits gradually converged to a balance that maximizes the throughput without overwhelming the nodes even during stress tests of high data volume.
There is also a separate monitor metric that tracks slow queries over a certain threshold, and the threshold was also converging, so SREs could focus on the top issues.
One day, many different databases nodes were reporting high load, only for a few seconds each, but continuously affecting an online service that happens to be using asynchronous nodes, as the service is considered less time-sensitive thus tolerable to the delay that asynchronous nodes might have. SREs and DBAs are confused for quite a while, until a technical lead who guessed it might be caused by the batch processing system Sink, which turned out to be true.
The developers of Sink were also confused, as the concurrent queries on the same node, and the slow queries were both within the limits.
The truth did come out in the end. There was 2 tasks configured in Sink, which will be broken down into many sub-tasks for different time spans, and subsequently, queries for different shards of the same table across different asynchronous nodes. And there is a bug in the task configuration that caused slow queries, and the bug was copy-pasted to affect both tasks. Both tasks were running slow slow, but the database nodes could handle the load along with online queries, as the concurrent slow queries are well below the CPU cores that the nodes could use.
One that day, both the tasks were requested to be rerun for 2 time spans by the same person who introduced the bug, which caused concurrent slow queries on the same node to exceed the core count, blocking the online queries. But as the queries are rate-limited so they hit different nodes in a rotating manner, each node was only affected for a few seconds, the overall impact could only be observed by SREs monitoring the online services, and DBAs considered the phenomenon as a normal load spike.
The lesson learned? Each piece of measures were working individually, but they could not account for combinations of different issues, namely too many *concurrent* (and) *slow* queries, and only the combination could cause an impactful issue. And the information about different parts of the system (the online service, database nodes, and Sink) were not shared across teams.
## OOM when retiring old worker processes
This story is about an SOA framework written in C++ (let's call it the "Framework") that will spawn many worker processes to handle requests for a service, and when a new version of the service is deployed, it will gracefully retire the old worker processes, and spawn new ones of the new version to handle requests. The framework also integrates a few plugins to extend its functionality, and the plugins have their own lifecycle management, e.g. `init`, and `fini`.
One of these plugins (let's call it "Charlie") will starts an asynchronous thread for each worker process, and signals the termination of the thread in `fini`. It recommends an explicit call to `fini`, but `fini` was considered trivial enough to be also called in the destructor of the plugin. It's a bad practice in the eyes of any C++ expert, but it worked well for a long time, there was also no issue calling `fini` twice, once explicitly and once in the destructor.
Every few ten thousand deployments, there is an OOM ("Out of memory") when retiring the old worker processes, but it will be killed per cgroup thresholds on memory consumptions, so only few requests are impacted overtime, eventually SREs concluded that the OOMs are not isolated events.
It was a nightmare to reproduce the issue without know the cause upfront, and code looked innocent enough in review. Finally enough data were collected on rare reproductions, and the clues pointed to `fini` in the destructor of Charlie, but there is only the signaling in `fini`. Further investigation revealed that the asynchronous thread was sending a heartbeat request which caused the OOM.
During sending the request, there was a call to a method using local const static `std::array` holding some `std::string` initialized by literals. That static variable had been destroyed when the asynchronous thread is still alive, which would be signaled to terminate later in `fini` in the destructor of Charlie. The destructor was doing its thing not too non-trivial, but too late, due to the undefined execution order of destructors.
Why would this cause an OOM? After destruction, the heap memory involved were still valid, as they were not released but reused by the allocator, thus there is no SEGFAULT, but the memory for `size()` of the strings contains garbage value, which happens to be a large number, and the strings were appending to a `std::stringstream` to form the heartbeat request, causing endless memory allocation until the OOM.
The issue became more reproducible after using an allocator (`tcmalloc`) that would retain the heap memory longer after destruction. It would have been caught by various sanitizers if we have integrated them in CI.
## Silently hanging tasks
It's again about the batch processing system Sink. Internally it uses an MQ to queue tasks, so it can retry failed tasks. To prevent aggressive retries, there is a backoff mechanism that will exponentially increase the delay between retries, and the maximum number of retries is also limited.
One day, an incident caused all available zones of the MQ to drop a certain percentage of network packets, causing a stable failure rate of task dispatching. If the retries are performed in a regular rate, the aggregate delay of tasks would not be too long.
Unfortunately, the backoff mechanism backfired, along with other rate-limiting mechanisms, eventually causing all task to hang indefinitely. Again, existing metrics were not able to pinpoint the issue, and the developers took some time to figure out the root cause. But as the incident causing all SREs to be in a all-hands-on-deck mode, the hung were noticed quickly from less sensitive monitoring metrics, resulted in a relatively timely fix.
A more sensitive monitoring metric was deployed to detect hanging tasks, and it caught another issue a few days later, and the issue was handled swiftly before causing actual delay.
The issue was that there was a silly bug that runs `remove()` for every element in a huge array, and overall it would take `O(n^2)` time to finish, it's almost forever for such huge arrays. The removal would only be triggered when certain conditions are met, and the bug of removal was copy-pasted from some other utility package.
The bug should only hang one processes that handled the task, unfortunately, the dispatcher would detect timeout tasks, considered the process as dead, reassign the task to other processes when the task was still occupying the old process which was burying its head deep in the `remove()` calls, missing its own checkpoint for timeout. The re-assignment happened over and over again for each timeout, eventually causing all processes to be busy with the same task, and the `remove()` calls would almost never finish. The world literally stopped for that task.
With early detection of hanging tasks, developers were able to try fixes quickly. It should not be easy to find the root cause, but the developers noticed long pauses between two log entries, and the removal loop was the only code there when they wanted to add some logging between the log entries, thus the obvious bug was immediately identified.
It's really lucky that the first issue that was not too serious helped to deploy the more sensitive monitoring metric, so the second issue, which could be much fatal, was detected and fixed promptly, on the morning of the first day of a national holiday. Task re-assignment were then limited to prevent poluting more processes with a bad task.
## LLM's takeaways
Disclaimer: The above stories are slightly modified from the actual events, and they are mannually written by me, not generated by LLM.
I asked DeepSeek to write some takeaways as I was a bit tired after telling these stories. This is the version I'm happy with:
1. **Legacy safeguards breed hidden traps**
Undocumented checks (Bug 1) and copy-pasted code (Bugs 2, 4) linger as systemic debt. Always audit dependencies before removal or reuse.
2. **Test failure *combinations*, not thresholds**
Rate limits + slow queries (Bug 2), retries + packet loss (Bug 4): isolated safeguards fail when risks collide. Model interactions, not silos.
3. **Own lifecycle control explicitly**
Destructor chaos (Bug 3) and hanging tasks (Bug 4) stem from assuming cleanup. Govern threads, memory, and resources with strict ownership.
4. **Instrument for why, not what**
Missing alerts for config errors (Bug 1), slow queries (Bug 2), or hung processes (Bug 4) delay fixes. Metrics must expose root causes, not just symptoms.
**Core**: Systems fail in layers. Anticipate overlap, govern lifecycles ruthlessly, and monitor for causality—not just correlation.
Fragmented learning, no more [uts-0167]
Fragmented learning, no more [uts-0167]
Well, at least I hope so, for 2025. I started keeping a Learning diary on math and tech since September 2024. Before that, I was working on a series of math notes, in a Zen mode, for months. I annotated PDFs in Margin Note 4, and forged definitions, diagrams into Forester trees which are bi-directionally linked notes that can be rendered into beautiful web pages and LaTeX PDFs, until I'm satisfied. During that time, I didn't read news, unrelated books, and solely focused on the books and papers needed for polishing the notes. I held my breath until one note reached a certain stage, so I might move on to a next note. It was a mental paradise. Then came the learning diary idea. Since September, constant context switch had dominated me at work. My attention for learning, had inevitably become fragmented. I started to check out interesting stuff from social media, still about math and tech, they are indeed potential elements of what I might want to work on. So I wished to log these readings or just findings daily, so they are not lost in time. The habit was well-kept, to the end of 2024, even when the load at work had become unbearably distracting and exhausting. The breadcrumbs would be a gold mine for future me. But it was a disaster to the mental state of my mind. During that time, I managed to go back to a few open-source projects that I was working on. Most of them have almost no users, but I still feel the obligation to keep them up to date. Usually I just had little time for each of them, so after some chores, I ran out of time and energy for new features, and moved on to chores for a next project. This partially reflected my mental state caused by my fragmented learning. The world had become an endless curiosity for me, the potential to work on a new project inspired by an element just learned about, was dazzling. When I stood at the beginning of 2025, I realized that I'm almost fruitless in 2024. I didn't finish the notes before September, although they are nice in their partially completed form. I didn't create anything in a whole after September. I enjoyed the reward of the journey, but came to the end empty-handed. I no longer log my learning daily in 2025 due to various reasons. My work and life still consume a lot of my time at the beginning of a year, like always. I still log them, but almost just weekly. April is coming, I would hope to reach a similar Zen mode like the better half of last year. Hence, this post is poured out of me.
A customizable, hybrid approach to code & resource pipeline and embedding [uts-000X]
- August 28, 2024
- Utensil Song
A customizable, hybrid approach to code & resource pipeline and embedding [uts-000X]
- August 28, 2024
- Utensil Song
The following are written in Markdown, and submitted as ~jonsterling/forester#87.
## TL;DR This is the proposal I mentioned in #82. It's an informal RFC about what I wish to do about embedding both the code and the resource (primarily images) generated in forester output. The code is there so that the resource generated is fully reproducible, the resource is there so that if the consumer of the forester output (e.g. browser or LaTeX) could gracefully downgrade to use the resource instead. And the pipeline handles regeneration when the source code or dependencies (e.g. imported external files, used assets) change. ## Feasibility The proposal is already feasible with current forester implementation with some external add-ons, so it might not bring too much complexity to immediate forester development. It can be viewed as not a feature request, but a way to make use of existing features whose equivalents may or may not be included in future forester development, e.g. XML/XSLT etc. That said, it would be nice to have some degree of native support from forester to smooth things out. Actually, this proposal is inspired by how forester handles LaTeX diagrams embedding, with visions on more diagram tools and beyond. Now that let's assume the feasibility is not a problem, and take a closer look at the approach. ## The customizable, hybrid Approach The "customizable" part in the approach means the user can choose the kind of tools and pipelines (e.g. parameter customzation or post-processing) to generated the resource, as well as the format(s) of the resource. Currently, the only natively support tool is `latex`, with fixed parameters (e.g. no `--shell-escape`), and a pipeline to generate DVI then post-process it with `divsvgm`, and the format is SVG, with a naming convention of hashing the source code to guarantee browser-cache invalidation of the image whenever the source dode is changed. The pipeline also watch the source change and trigger the regeneration and copying related assets to the output, to an extent that it would be triggered by changes of upstream macro (as it would impact the source code) but not including some `.tex`/`.sty` files that's "imported" in the source code, but forester has no way of detecting that in the current implementation. Imagine all these can be customized for a second, it would be a great productivity boost for the users, but would this bring a ton of complexity into forester? Not neccessarily. If we view forester as a kernel, then it could just provide a minimal infrastructure to allow all these to happen, instead of handling all tools, pipelins, and formats by itself. The "hybrid" part in the approach, at least in the web context, means the code can be executed both in browser (browser-side render, BSR for short, which might result in a more interactive experience, e.g. WebGL animations), and in server-side generation (SSR). The technical possibility thanks to that JS libraries that can be executed both in browser and in a JS runtime on server-side (e.g. node.js, deno), and that native libraries can be executed both on server, and in browser as WASM, that includes programs written in C, Rust, Go and more. In the LaTeX context (or equivalently Typst or other authoring tools), the hybrid approach means whether to execute the code inside the document environment to regenerate, e.g. to preserve the same font and style settings, or to just include the externally generated diagrams. The current forester-to-latex takes the former approach, and usually results in a more desired, style-consistent result, while the latter may have the advantage of stabibility and efficiency, as the diagram could have unexpected errors or deformations during regeneration, and it could be more time consuming to regenerate too many diagrams when you are just authoring some text, and expect to preview the result in real-time. Now it become clear that this hybrid approach facilitates both the reproducibliity and the graceful downgrade, as long as there is a customizable pipeline to handle it. ## A teaser: authoring tool candidates Let's get a bit more concrete about the tools that could be used in the customizable pipeline, and see how it opens to endless possibilities. Here are some candidates that I have experimented with: - Rich text (including math, diagrams) - Markdown: a easy-to-write, source-code-readable format - both BSR and SSR capable - it plays well with forester markups, as fr XML nodes are transformed to HTML tags to be rendered as is by the markdown renderer - it can downgrade to plain text (but preserving rendered forester markups) when the markdown renderer is not loaded - experiment: test markdownit (via markdown-it ) - it's at least very convenient for writing paragraph/link/list/footnote-heavy notes compared to forester markups - plus, users could write the same text for forester, or for external communication, such as this very proposal which is written in Markdown, submitted to forester ticket system, but also rendered in my forest - Typst - both BSR and SSR capable - it can be made to plays with forester markups, to support links/cross-references/citations etc. - it renders to text-selctable SVG, indistinguishable from ordinary text - besides text and math, it can be used as a modern diagram authoring tool with decent scripting support - experiment: test typst (via typst.ts ) - Syntax-highlighted code blocks - both BSR and SSR capable - experiment: test syntax highlighting (via shiki ) - Static diagrams - Penrose: creating diagrams with a declarative language with separation of domain knowlege, layout constraints&styling, and concrete substances - both BSR and SSR capable - experiment: test penrose - Pikchr: an open-source text-to-diagram tool, the language is simple yet has great support for relative positioning and flexible path guiding - experiment: test pikchr - SSR first, BSR-capable thanks to WASM - D2: a modern diagram scripting language, preferred over PlantUML, Mermaid, and Graphviz, for its great layout support for complex diagrams and its declarative design. - no BSR experiments yet, but I have used its SSR with other static site generators - Animated, interactive diagrams - WebGL - experiments: Implicit surfaces, test interactions between ray-marching and 3D objects - still trying to work out a SSR pipeline, but combining `xvfb-run`, headless-gl, three.js, should make it possible, e.g. see this gist. - a less preferred alternative is to use the SVGRenderer addon from three.js, but its render result is visually worse than WebGLRenderer, per my experiment in test three.js to SVG. For SSR for other output format, users could use XSLT to transform the XML output to make the downstream tools (e.g. LaTeX) to consume the source code, or the resource produced by the SSR pipeline. If neither is consumable, the same content could be excluded, using a macro like `webonly` to surround the forester markup. Note that these experiments are mostly done for only BSR. SSR experiments are not done for forester, as I have learned the feasibility from my experiment with other static site generators. Without SSR gracefully downgrade, it will take a bit time to load on first visit. ## Elements of an implementation external to forester Currently, forester can: - consume `.tree` files, and output `.xml` files, from which the final HTML are produced by XSLT on browser side, or by LaTeX on server side - allowing user to define macros, which could emitted HTML tags in the XML output (this could also be done as XML tags) - forester 4.3 uses `fr:resource`, `fr:img`, `fr:resource-source` (with type and part attributes) for rendered SVG image, and the LaTeX source code, which is general enough to be used for other `type` of code that renders to images To make it available to BSR, the users could: - use XSLT to transform `fr:resource` tags to HTML tags with certain `class` attribute - use CSS to render them to show the source code, or a loading animation, or a fallback image rendered by the SSR pipeline described below - some JS can be loaded on demand to replace the the HTML tag with a rendered, potentially interactive HTML element To make a SSR pipeline external to forester, the users could: - define macros accepting the source code to emit `fr:resource`, `fr:img`, `fr:resource-source` following the forester practice on LaTeX diagrams, but with a filename specified by the user, instead of generated from the source code hash - use a file change watcher (e.g. watchexec) to check the change of XML, then detect `fr:resource-source` presence, then render the source using external scripts to call the corresponding tools by the `type` attribute, and generate an image file with the specified filename - use a browser cache bustering mechanism (e.g. use XSLT to generate a random number to be appended to the image URL) for reloading the latest image whenever the source code changes if the user refreshes the page So far, BSR are implemented for the experiments mentioned above, and SSR could wait for the standardization of `fr:resource`, and the resolution of this proposal, or just use any other XML tags in a similar spirit. ## Concluding remarks The text above is organized so that a reader might gradually see the full vision of the proposal, then the feasibility, and many possible path, downgraded or even upgraded. To reiterate, this is already feasible with current forester implementation with some external add-ons, and will continue to work if the used features or their equivalents are available in future forester. It might coincide with the direction of forester development (e.g. the on-going pipeline refactor might just provide the minimal native support needed for this approach to work more smoothly), or it might exceed what forester was originally designed for (thus should not pose a maintenance burden to forester). Hence this informal RFC.
Forester experiment [uts-000S]
- April 26, 2024
- Utensil Song
Forester experiment [uts-000S]
- April 26, 2024
- Utensil Song
I'm experimenting using Jon Sterling's Forester for building Zettelkasten-style forests of evergreen notes, like his Notes on duploid theory (source), CAIMEO's The Rabbit Hole (source) or Trebor’s forest (source).
I wish to use it to organize many definitions, theorems and discussions about the same mathematical concepts/topics.
My hope is to find these notes easier to reuse and refer to in blogs, papers, blueprints etc. Preferably, I would like to be able to author them in Forester markup, LaTeX, Markdown, Typst, and various diagram tools, freely and in a reproducible manner (see my post on this, and relevant experiments).
My math interests in 2024 [uts-001R]
- March 16, 2024
- Utensil Song
- https://utensil.github.io/blog/posts/math-2024/
My math interests in 2024 [uts-001R]
- March 16, 2024
- Utensil Song
- https://utensil.github.io/blog/posts/math-2024/
Rationale [uts-001S]
Rationale [uts-001S]
I wish this post to be a continuously updated list of my math interests in 2024 with proper citations to literatures, as I keep wandering in the math wonderland and I don't want to be lost in it without breadcrumbs. Some interests that have older origins will gradually moved to corresponding posts for earlier years. I also hope certain interests will be developed into research projects, and leaving only a brief summary and a link here. Each interest should have one or few central questions, and one or few references to literatures.
Formalization [uts-001T]
Formalization [uts-001T]
This part of interests is about small-scale formalization of mathematical concepts and theorems, for learning and potential PRs to Lean's Mathlib. Each should focus on one reference which is well organized and convenient to be converted into a blueprint.
Spin groups [uts-001U]
Spin groups [uts-001U]
The PR to Mathlib #9111 about Spin groups is ready to merge, but there are 2 open questions: - what more lemmas about Spin groups are interesting to mathematians? - what more should be formalized to formalize Versors and what’s in Section "The contents of a geometric algebra" in [chisolm2012geometric] , e.g. r-blades, r-vectors? For the former, I should take a closer look at [figueroa2010spin] and maybe [suarez2019expository], [reynoso2023probing]. For the latter, see the Z-filteration in lean-ga and the prototype. I also wish to include some latest results presented in [ruhe2023clifford], with supplements from [brehmer2023geometric] (lately there is a new paper applying this in HEP [spinner2024lorentz], in the same spirit, I should also read [berzins2024geometry] and possibly [raissi2019physics]), in which some of the results are proven in [roelfs2023graded]. See also discussions in the lean-ga blueprint. I've started a Forester experiment about the definitions of Spin groups here. I also need to check citations of On some Lie groups in degenerate Clifford geometric algebras.
Matrix [uts-001V]
Matrix [uts-001V]
The Matrix Cookbook (November 15, 2012) [petersen2008matrix] covers many useful results about matrices, and Eric Wieser's project lean-matrix-cookbook aims to give one-liner proofs (with reference to the counter part in Mathlib) to all of them. The project is far from complete and it would be great to claim a small portion of interested results and contribute to it. I also wish to figure out the GA counterpart of the same portion. Previous interests about matrices rise from Steven De Keninck's work on GALM [de2019geometric], since the paper I have been interested in GA approaches that has practical advantages over traditional matrix-based methods. Notably the paper also discussed the link between degenerate Clifford algebras and dual numbers / automatic differentiation. A more recent inspiration might be his new work LookMaNoMatrices. TODO: decide which results are interesting and feasible to be formalized for me. I wish to pursue further on the topic of Matrix/Tensor, see [taylor2024introduction] and [randy2023matrix]. The former also led me to Einsums in C++. For the latter, I'm thinking of HepLean.SpaceTime.CliffordAlgebra.
Group Algebra [uts-001W]
Group Algebra [uts-001W]
> In a sense, group algebras are the source of all you need to know about representation theory. The primary reference is [james2001representations] for understanding FG-module, Group algebra, the presentation of groups, Clifford theory (which is the standard method of constructing representations and characters of semi-direct products, see [woit2017quantum], and "3.6 Clifford theory" in [lux2010representations]), Schur indices etc. We also need to check [lux2010representations] for its introduction to GAP, and we should pay close attention to the progress of GAP-LEAN. [sims1994computation] might also be interesting in a similar manner as [lux2010representations] but with emphasis on the presentation of groups. See also group algebra on nlab, particularly that "A group algebra is in particular a Hopf algebra and a \(G\)-graded algebra." The related Zulip thread is here, and I have preliminary explorations and experiments in Lean here. This interest originates from reading Robert A. Wilson's work [wilson2024discrete]. The ultimate goal is to understand the group algebra of the binary tetrahedral group (\(Q_8 \rtimes Z_3\)), then the three-dimensional complex reflection group (\(G_{27} \rtimes Q_8 \rtimes Z_3\)), a.k.a. the triple cover of the Hessian group, which can be interpreted as a finite analogue of the complete gauge group \(U(1) \times SU(2) \times SU(3)\).
Type Theory [uts-001X]
Type Theory [uts-001X]
Recently I have read some meta-level dependent type theory (Typst source). It might be time to re-read `leantt` paper, and start reading `lean4lean` paper/source. The author `ice1000` has strong interest in QIIT (Quotient Inductive-Inductive Types) and QIIR (Quotient Inductive-Inductive Recursion), he has implemented `overlap` in Aya with termination check and confluence check. Aya has a philosophy that the kernel could include pattern matching, but at the cost of no generation and translation of eliminators at present. In principle this is feasible, without `overlap`, it could be implemented by "theory of signatures", with `overlap`, it needs "Coherent and concurrent elimination for initial algebras" which I find fascinating, and have read [yeasin2011initial]. The author also has a great article on TT & Cat [zhang2021type]. His recommendation of [gundry2013tutorial] is also worth reading. In the process of learning Topos, I wish to have a better understanding of Logic. Particularly, Curry–Howard–Lambek correspondance, Propositional truncation, and Paraconsistent logic are on the plate. Although remotely related, I'll place Introduction to Formal Reasoning (COMP2065) in this section so I won't lose track of it.
Philosophy [uts-001Y]
Philosophy [uts-001Y]
Type theories, logic have their origins in philosophy. Lacan had drawn inspiration from the work of the mathematician and philosopher of science Georges Canguilhem, and the philosopher of mathematics Alain Badiou. If he had lived to see the rise of proof assistants, he would be interested in the formalization of his theories. There is a project on Github called Lacan-Mathemes which visualized some core concepts of Lacan in TikZ. It would be interesting to start there and look for proper objects to formalize in Lean. Another interesting thing to do is to visualize them in Typst. Here I would like to quote a generated response from Claude 1.2 Instant, which is quite optimistic: > Here are a few thoughts on formalizing aspects of Lacanian psychoanalytic theory using theorem provers: > > - Lacan's structural theory of the psyche could potentially be formalized using logic. The tripartite structure of the Real, Symbolic, and Imaginary could be modeled as formal domains or ontologies with defined relationships between them. > - Key concepts like the mirror stage, the Name-of-the-Father, the objet petit a, etc. could be defined as logical predicates or functions operating within this structural framework. For example, one could define predicates like "inMirrorStage(subject)" or "desiresObjetPetitA(subject, object)". > - Relations like the split between desire and drive, the tension between the Symbolic order and the Real, the misrecognition of the Imaginary could be expressed through logical rules and inferences between concepts. > - The dynamics of psychoanalytic concepts like repression, sublimation, transference could be modeled as state transitions or logical transformations within the structured system. > - Specific psychoanalytic theories like the stages of psychosexual development or the topology of the fantasy could be axiomatized and theorems deduced from the axioms. > > However, capturing the open-ended, non-deterministic nature of unconscious processes and the ambiguity/contingency of signification would be challenging and may require non-classical logics or probabilistic approaches. > > So in summary, while difficult, certain aspects of Lacanian theory seem amenable to formalization using tools from logic, ontology, and knowledge representation. Careful design would be needed to address theory's complexity. Lately there is a paper formalizing Kant [achourioti2011formalization] which might be interesting.
Generalized Clifford Algebra and related mathematical branches [uts-001Z]
Generalized Clifford Algebra and related mathematical branches [uts-001Z]
A Clifford algebra is a \(Z_2\)-graded algebra, and a Filtered algebra, the associated graded algebra is the exterior algebra. It may be thought of as quantizations (cf. quantum group) of the exterior algebra, in the same way that the Weyl algebra is a quantization of the symmetric algebra. Specifically, for \(V\) an inner product space, the symbol map constitutes an isomorphism of the underlying super vector spaces of the Clifford algebra with the exterior algebra on \(V\), and one may understand the Clifford algebra as the quantization Grassmann algebra induced from the inner product regarded as an odd symplectic form. Weyl algebras and Clifford algebras admit a further structure of a *-algebra, and can be unified as even and odd terms of a superalgebra, as discussed in CCR and CAR algebras. A Clifford module is a representation of a Clifford algebra. A Generalized Clifford algebra (GCA) can also refer to associative algebras that are constructed using forms of higher degree instead of quadratic forms, e.g. > For \(q_1, q_2, \ldots , q_m \in \mathbb {k}^*\), the generalized Clifford algebra \(C^{(n)}\left (q_1, q_2, \ldots , q_m\right )\) is a unital associative algebra generated by \(e_1, e_2, \ldots , e_m\) subject to the relations > \[ e_i^n=q_i \mathbf {1}, \quad e_i e_j=\omega e_j e_i, \quad \forall j \lt i . \] > > It is easy to see that \(C^{(n)}\left (q_1, q_2, \ldots , q_m\right )\) is \(\mathbb {Z}_n\)-graded where the degree of \(e_i\) is \(\overline {1}\), the generator of \(\mathbb {Z}_n\). [cheng2019new] In [cheng2019new], note also that "Clifford algebras are weak Hopf algebras in some symmetric tensor categories." while "generalized Clifford algebras are weak Hopf algebras in some suitable braided linear categories of graded vector spaces." as well as that "the Clifford process is a powerful technique to construct larger dimensional Clifford algebras from known ones." TODO: add papers linking Hopf algebra and Clifford algebra together learned from the adjoint discord here. Clifford algebras can be obtained by twisting of group algebras [albuquerque2002clifford], where twisted group algebras are studied in [conlon1964twisted], [edwards1969twisted], [edwards1969twisted2]. There exists isomorphisms between certain Clifford algebras and NDAs (Normed Division Algebras) over \(\mathbb {R}\). Variants of Clifford algebras whose generators are idempotent or nilpotent can be considered. Zeon algebras ("nil-Clifford algebras") have proven to be useful in enumeration problems on graphs where certain configurations are forbidden, such as in the enumeration of matchings and self-avoiding walks. The idempotent property of the generators of idem-Clifford algebras can be used to avoid redundant information when enumerating certain graph and hypergraph structures. See [ewing2022zeon]. It's also closely related to universal enveloping algebra (see [figueroa2010spin] and "The universal enveloping algebra of a Lie algebra is the analogue of the usual group algebra of a group." from group algebra on nlab). Great discussions about the limitations and generalizations of Clifford algebras can be found in John C. Baez's [baez2002octonions]. Particularly, note Cayley-Dickson construction, Bott periodicity, matrix algebra, triality, and \(\mathbb {R}\) as a real commutative associative nicely normed ∗-algebra. Also see Anthony Lasenby's work on the embedding of octonions in the Clifford geometric algebra for space-time STA ( \(\mathop {\mathcal {C}\ell }(1, 3)\) ) [lasenby2024some]. Note also Kingdon algebras: alternative Clifford-like algebras over vector spaces equipped with a symmetric bilinear form [depies2024octonions].
Categorified Clifford Algebra [uts-0020]
Categorified Clifford Algebra [uts-0020]
A categorical view of Clifford Algebra is discussed in [figueroa2010spin]. A Clifford Algebra can be categorified: "An Clifford algebra over a vector space is defined to be the Koszul dual to an abelian fully weak Lie-algebra" where "Fully weak Lie-algebras are Koszul dual to differential graded Clifford algebras." See also Higher Clifford Algebras.
Sheaves of Clifford Algebras [uts-0021]
Sheaves of Clifford Algebras [uts-0021]
Sheaves of Clifford Algebras are studied in [yizengaw2015clifford] and its references. See also [schapira2023introduction], an elementary introduction to [kashiwara2006categories], which presents categories, homological algebra and sheaves in a systematic and exhaustive manner.
DKP Algebra [uts-0022]
DKP Algebra [uts-0022]
Duffin-Kemmer-Petiau Algebra is
\[\frac {T(V)}{I(v\otimes w\otimes v - g(v,w)v)}\]
in the same way that Clifford Algebra is
\[\frac {T(V)}{I(v\otimes v - g(v,v))}.\]
See [fernandes2022clifford] which embeds DKP Algebra in Clifford Algebra with projectors.
Misc [uts-0023]
Misc [uts-0023]
TODO: - Recovering Composition Algebras from 3D Geometric Algebras - Eliminating topological errors in neural network rotation estimation using self-selecting ensembles - Sitao Xiang - SIGGRAPH 2021 - OSMU24: Quantum Foundations, Particle Physics, and Unification of Forces - Bill Baylis' research on Clifford's Geometric Algebra of Physical Space (APS)
Applied mathematics [uts-0024]
Applied mathematics [uts-0024]
Topology [uts-0025]
I wish to render some pictures in [francis1987topological] with TikZ, GLSL shader, and by GA with ganja.js & GAmphetamine or their Lean version, inspired by Steven De Keninck's notebooks, e.g. torus, orbit 1, orbit 2, origami, skinning, slicing etc.
Topology [uts-0025]
Knots [uts-0026]
Knots [uts-0026]
See [manturov2018knot] and the tracking issue. For interpreting knots in a sheaf-theoretic perspective, see [chrisman2023geometric]. See also: - A Table of Virtual Knots - The homological arrow polynomial for virtual links (code)
Dynamical Systems: Bifurcation Theory [uts-0028]
The preferred reference for me is [izhikevich2007dynamical] for its applications in neuroscience and various excellent diagrams. But it's not a mathematically rigorous treatment of bifurcation theory.
Dynamical Systems: Bifurcation Theory [uts-0028]
Sheaves [uts-0029]
Sheaves [uts-0029]
My first impression of sheaves is that they are useful to local-to-global applications "which ask for global solutions to problems whose hypotheses are local".
Roughly speaking, a sheaf requires some gluing conditions (axioms "Locality" and "Gluing") so that local data can be collated compatibly into a global algebraic structure that varies continuously over local covering domains ("sections" of sheaves).
To do so, a sheaf in general, as defined in the category-theoretical language, needs
- a topological space (or a site in general), denoted \(X\) (or \(\mathcal {C}\) for a site)
- a category, sometimes denoted \(\mathcal {D}\), meaning "data category", whose objects are algebraic structures and morphisms are structure-preserving maps
and builds (gluing conditions) on a \(\mathcal {D}\)-valued presheaf over \(X\) (or \(\mathcal {C}\)), denoted \(\mathcal {F}\) (as its French name is "faisceau"), which is essentially a contravariant functor \(\mathcal {F}: \mathcal {C}^{op} \to \mathcal {D}\) but a concept with an attitude, and its morphisms are restriction maps between open sets in \(X\) (or between objects that satisfy the pretopology \(\mathcal {J}\) in \(C\), where \(\mathcal {J}\) is the pretopology on \(\operatorname {Open}(X)\), which specifies when a covering family of open sets exists).
Its latest application to deep learning, Thomas Gebhart's thesis [gebhart2023sheaf] sees a sheaf over a topological space as a data structure "which defines rules for associating data to a space so that local agreements in data assignment align with a coherent global representation", thus a generalization of both:
- relational learning, which aims to "combine symbolic, potentially hand-engineered prior knowledge with the tabula rasa representational flexibility of deep learning to achieve a synthetic model family which can be defined with respect to symbolic knowledge priors about the data domain"
- geometric deep learning, which "provides a group-theoretic approach to reasoning about and encoding domain-symmetry invariance or equivariance within machine learning models",
"providing a mathematical framework for characterizing the interplay between the topological information embedded within a domain and the representations of data learned by machine learning models".
My prior interest in geometric deep learning, particularly group-equivariant neural networks, and my believe in symbolism, are the background of my interest in sheaf representation learning.
Notably, this thesis treats the discrete case of sheaves, a cellular sheaf, whose
- topological space is a cell complex, which is "a topological generalization of a graph, with set inclusion and intersection given by the incidence relationships among cells in the complex", thus "admitting a computable, linear-algebraic representation".
- data category is \(\mathtt {FVect}\), the category of finite-dimensional vector spaces over a field \(\mathbb {F}\), which is a common choice for the data category in machine learning applications, a model-free approach with massive parameter space, flexible representational capacity, but inherits fundamental limitations, e.g. data inefficiency, generalization failure, and interpretability issues.
For more details, see also Thomas Gebhart's talk Sheaves for AI: Graph Representation Learning through Sheaf Theory.
<!-- has the potential to learn sheaf representations of data, which is essentially assigning observed data to a space in a way that's
globally consistent with the constraints imposed by the topology of the application domain .
a richer but still tractable representation that is an algebraic structure richer than a vector space commonly used in ML, to sampled data, which is in the form of components of a category (e.g. a category of a data structure like a Graph). -->
Its application to physics has the potential to formulate differential geometry in a more general setting, without assuming the existence of a locally Euclidean space as manifold did. It's believe that this approach can overcome some difficulties in Quantum field theory even Quantum gravity, because locally there might be no concept of a metric space at all [mallios2015differential].
Note that there are CAS systems that can do sheaf cohomology etc., e.g. Macaulay2, OSCAR.
Synthetic Differential Geometry [uts-002A]
Synthetic Differential Geometry [uts-002A]
For SDG, [kock2006synthetic] is a classic. [schellingerhout2023circles] is a concise bachelor thesis on the topic, and has interesting discussions on circles. Ryszard Paweł Kostecki has very approachable notes on Topos [kostecki2011introduction] and SDG [kostecki2009differential]. We should also read [rosiak2022sheaf]. It also has many diagrams in the way I imagined, for examples of sheaf.
ML [uts-002B]
ML [uts-002B]
I don't want efforts in Transformers: from self-attention to performance optimizations to be discontinued, lately there is [ferrando2024primer] on this topic. I might need to follow on the latest development on the linear attention mechanism [peng2024eagle]. I have almost no understanding of diffusion models, so I should read [bao2023all] and related papers. I should also read [mikula2023magnushammer] and related papers.
Consciousness [uts-002C]
Lately I became aware of the work on mathematical models of consciousness, namely Integrated information theory [albantakis2023integrated] and The information theory of individuality [krakauer2020information].
Consciousness [uts-002C]
Physics [uts-002D]
Physics [uts-002D]
Physics-Based Simulation is out. So is [sen2024string] on string theory.
TODOs [uts-002E]
TODOs [uts-002E]
Incorporating the following interests into this post: - Threads of thought in recent years (in Chinese) - Interests logged here
For earlier posts, see Utensil's Blog powered by Hugo.
For even ealier posts but not in English, see Utensil's Tech Blog, powered by an old version of Middleman.
Learning diary [uts-0018]
Learning diary [uts-0018]
I wish to keep a learning diary, to keep track of partial reading progress, and things learned during making things.
Year 2025 [2025]
Year 2025 [2025]
October, 2025 [2025-10]
October, 2025 [2025-10]
2025-10-10 [2025-10-10]
2025-10-10 [2025-10-10]
- GitHub stale bot considered harmful
September, 2025 [2025-09]
September, 2025 [2025-09]
2025-09-07 [2025-09-07]
2025-09-07 [2025-09-07]
- #zig
- Hitting Peak File IO Performance with Zig
- axboe/fio: Flexible I/O Tester
- steelcake/csio: Cooperative scheduling and IO library
- DataDog/glommio: Glommio is a thread-per-core crate that makes writing highly parallel asynchronous applications in a thread-per-core architecture easier for rustaceans.
- steelcake
- #jj
- Let `jj absorb` help you keep a clean commit history
- Merge Conflicts: Avoiding Them, Making Them Less Painful | Games by Mason
- Quuxplusone/difdef: Utility to do an N-way diff and N-way merge, for N2. Uses the patience diff algorithm.
- #disect
- Video compression basics – RasterGrid | Software Consultancy #cut
- A Secret Web
- In-memory Filesystems in Rust #rust #os
2025-09-06 [2025-09-06]
2025-09-06 [2025-09-06]
- Making a font of my handwriting · Chameth.com #design - On HN - https://ownfonts.cielo.ovh/ - https://www.amygoodchild.com/blog/cursive-handwriting-in-javascript > Calligraphr works by having you print templates, write out the letters, then scan them in. > I added the “minimal English”, “basic punctuation” and “Ligatures” sets. - #ph - basketballguy999/Quantum-Mechanics-Concise-Book: A concise text on quantum mechanics, intended for a general audience including CS, engineering, math, and physics undergrads, as well as anyone interested in a concise intro/overview of QM. Prerequisites: linear algebra, calculus, high school physics - This idea must die - #formal - Formality on demand
2025-09-03 [2025-09-03]
2025-09-03 [2025-09-03]
- #rust
- Stackerror
- the core of rust
- https://without.boats/blog/revisiting-a-smaller-rust/
- There is no memory safety without thread safety (on HN) (on lobste.rs)
- Default musl allocator considered harmful (to performance)
- #agent
- Agentic ProbLLMs - The Month of AI Bugs 2025 #sec
- On lobste.rs
- AGENTS.md
- A Guide to Gen AI / LLM Vibecoding for Expert Programmers - Stochastic Lifestyle
- On HN
- Language Models as Thespians
- On lobste.rs
- #agent/idea
- DeepSeek v3.1 Is Not Having a Moment
- Vibe Debugging: Enterprises' Up and Coming Nightmare
- Bank forced to rehire workers after lying about chatbot productivity, union says
- The Unbearable Slowness of AI Coding
- Why language models hallucinate
- Simon Willison | A quote from u/AssafMalkiIL
> what’s the point of vibe coding if at the end of the day i still gotta pay a dev to look at the code anyway.
> i cant vibe my way through debugging, i cant ship anything that actually matters, and then i’m back to square one pulling out my wallet for someone who actually knows what they’re doing.
- #openweb
- No, Google Did Not Unilaterally Decide to Kill XSLT
- Should the web platform adopt XSLT 3.0? · Issue #11578 · whatwg/html
- Croissant is Coming for You
- XSLT: A Precision Tool for the Future of Structured Transformation (on HN)
- #disect
- Bash Strict Mode
- I should review my scripts based on what's learned from this
- Getting decent error reports in Bash when you're using 'set -e' (on HN) (on lobste.rs)
- Heredocs Can Make Your Bash Scripts Self-Documenting
- Introduction to AT Protocol #fediverse
- On HN
- #gpu
- Learning About GPUs Through Measuring Memory Bandwidth | Evolve
- How to Think About GPUs | How To Scale Your Model
- On HN
2025-09-02 [2025-09-02]
2025-09-02 [2025-09-02]
- #selfhost
- Static Sites with Python, uv, Caddy, and Docker | Blog | Nik Kantar
- Coolify Docs
- GDPR-compliant European static site hosting - statichost.eu
- https://www.statichost.eu/blog/statichost-hosting/
- #tui
- jocalsend - Terminal Trove #selfhost/data
- hapless - Terminal Trove
- #openweb
- Google is killing the open web #openweb
- On HN
- On lobste.rs
- Simon Willison | XSLT on congress.gov
- Remove mentions of XSLT from the html spec by mfreed7 · Pull Request #11563 · whatwg/html
- On HN
- D2 (text to diagram tool) now supports ASCII renders #diagram
- #browser
- How to firefox (on HN)
- Why I'm all-in on Zen Browser
- On HN
- https://addons.mozilla.org/en-US/firefox/addon/sidebery/
- https://github.com/mbnuqw/sidebery/wiki/Firefox-Styles-Snippets-(via-userChrome.css)
- https://github.com/greeeen-dev/natsumi-browser
- https://github.com/akkva/gwfox
- How I Use Kagi
- on HN
- Microsoft Introduces 'Copilot Mode' in Edge (on HN)
- Show HN: Monchromate – the best greyscale browser extension (on HN)
- f.lux: software to make your life better
- #sec
- A Brief, Incomplete, and Mostly Subjective History of Internet censorship and its countermeasures
- Simon Willison | PyPI: Preventing Domain Resurrection Attacks #py
- Preventing Domain Resurrection Attacks (on the Python Package Index) #py
- On HN
- Vet is a safety net for the curl | bash pattern (on HN)
- Don’t distribute packages via curl | sh (but not for the reasons you think) - HedgeDoc
2025-09-01 [2025-09-01]
2025-09-01 [2025-09-01]
- PixiEditor #cg - #idea - Left to Right Programming - On HN - On lobste.rs - Why developers question everything - Tim Hårek - On lobste.rs
August, 2025 [2025-08]
August, 2025 [2025-08]
2025-08-25 [2025-08-25]
2025-08-25 [2025-08-25]
- #zig
- zg: Unicode text processing for Zig projects
- Zig; what I think after months of using it
> Focus on debugging your application rather than debugging your programming language knowledge.
> A structure has two sizes: its bit-size, and its byte-size.
> A regular value T coerces to E!T, and an error type E coerces to E!T
> You can iterate on the contents of c with an inline for at comptime to transform functions the way you want.
- Packaging Zig as Python packages #py #pkg
- The Python Package Index Should Get Rid Of Its Training Wheels #py
- Zig Parser #disect
- Retro Rogue-Like: Modular Programming in C
- Looking for examples of clean zig APIs
- vrischmann/zig-sqlite: zig-sqlite is a small wrapper around sqlite's C API, making it easier to use with Zig.
- Mario-SO/ohlcv: OHLCV library in zig
- (266) Code Guild
- #lean
- Lean Game Server
- Doing Lean Dirty: Lean as a Jupyter Notebook Replacement
- https://types.pl/@sandmouth/114813276765190938
- tooling
- Enforce Proper direnv Setup #mise
- #helix
- Helix Plugins
- Are any of these features available in Helix? · helix-editor helix · Discussion #3156
- feat: support using Yazi in Helix directly without Zellij or tmux by sxyazi · Pull Request #2461 · sxyazi/yazi
- try to use yazi inside of helix
- helix-editor/helix#1125: automatic reload when file changes externally
- #mac/wm
- nikitabobko/AeroSpace: AeroSpace is an i3-like tiling window manager for macOS
- AeroSpace
- #tui
- habedi/chilli: A microframework for creating command-line applications in Zig
- Todomvc tui
- helix/helix-tui at master · helix-editor/helix
- #typst
- The Math Mode Problem | Laurenz's Blog
- The (Typst) Math Mode Problem | Laurenz's Blog : r/typst
- #cpp/interop
- robertoraggi/cplusplus: A compiler front end for the C++ language
- shedskin/shedskin: Shed Skin is a restricted-Python-to-C++ compiler. Read the introduction below to learn about the restrictions.
- Are "w/o", "w/", "b/c" common abbreviations in the US? #natlang
- Tommaso Gagliardoni's Homepage #qc
- a reply to *Replication of Quantum Factorisation Records with an 8-bit Home Computer, an Abacus, and a Dog*
- A Diagrammatic Calculus for a Functional Model of Natural Language... #diagram #paper
2025-08-24 [2025-08-24]
2025-08-24 [2025-08-24]
- #sovereign
- #kb
- Writing Documentation and Prose in Markdown Using Helix
> :reflow is Helix’s version of hard wrap and makes permanent changes to your formatting. The line length can be set with text-width in your config.
> Type [ to automatically create a pair using automatic pair completion, then type the image link text inside it.
> Press Tab to skip over the closing ] using the smart tab feature.
> Marksman helps you quickly find and jump to specific headings or anchor tags in a document.
> Open the Symbol Picker: Press Space s.
> Vale stands out by enforcing custom style guides for technical writing alongside spell checking, though its grammar checking is less advanced. Its newly introduced language server is still basic.
- Reading and writing notes with yazi and helix #helix
- xwmx/nb: CLI and local web plain text note‑taking, bookmarking, and archiving with linking, tagging, filtering, search, Git versioning & syncing, Pandoc conversion, + more, in a single portable script. #tui
- Building Bluesky Comments for My Blog
- Raindrops | API Documentation
- Switching to Obsidian
- from Notion
- Allow me to introduce the two-sentence journal #design
> A daily journal entry could be as simple as "[description of occurrence] + [its upshot]," adapted as necessary.
> an interesting thing happens when you present a reader with only two sentences: Somehow, a narrative logic appears.
- The append-and-review note (on HN)
- Heynote
- Observable Notebooks 2.0 Technology Preview | Observable #nb
- Apache ECharts 6
- ECharts is my go-to libary for visualization of data for better interpretability
- Ask HN: What Pocket alternatives did you move to?
- Obsidian Web Clipper
- Home - Readeck
- Ghost 6.0
- #kb/dataview
- Codeblock Reference - Dataview
- blacksmithgu/datacore: Work-in-progress successor to Dataview with a focus on UX and speed.
- dsebastien/obsidian-dataview-serializer: Obsidian plugin that gives you the power of Dataview, but generates Markdown, making it compatible with Obsidian Publish, and making the links appear on the Graph.
- Enveloppe
- "Burning out" dataviews · Issue #42 · blacksmithgu/obsidian-dataview
- Support for Dataview JS Snippets · Issue #102 · jackyzha0/quartz
- 7sedam7/krafna: Obsidion dataview plugin-like tool for command line.
- #selfhost/data
- embedpdf/embed-pdf-viewer: A PDF viewer that seamlessly integrates with any JavaScript project
- What Exif Data Reveals About Your Site #privacy
- houqp/kiorg: A hacker's file manager with VIM inspired keybind
- Watchman - A file watching service | Watchman
- pascalkuthe/filesentry: A reliable and performant cached directory tree in rust that can notify changes without dropping events
- #selfhost/data #sec
- I'm Archiving Picocrypt (on HN)
- hashcat - advanced password recovery
- Brute-Force VeraCrypt Encryption – CodeOnBy
- trufflesecurity/trufflehog: Find, verify, and analyze leaked credentials
- #forge
- GitHero
- GitHub is no longer independent at Microsoft after CEO resignation | Hacker News
- On HN
- Give Up GitHub - Software Freedom Conservancy
- #ci
- bahdotsh/wrkflw
- On lobste.rs
- from https://this-week-in-rust.org/blog/2025/08/13/this-week-in-rust-612/
- The best developer experience in CI/CD - RWX
- Reverse Engineering the GHA Cache to Improve Performance (on HN)
- Reverse engineering GitHub Actions cache to make it fast | Blacksmith
- Using Radicle CI for Development (on HN) (on lobste.rs)
- #openweb
- Mac Open Web, by Brian Warren
- Reeder
- Kill the Newsletter!
- pocketbase/pocketbase: Open Source realtime backend in 1 file #stack
- #browser
- Ok... even I think that's a bit of a stretch... : r/diabrowser
- Text browsers · TecharoHQ anubis · Discussion #418
- Arc still going good, btw windows! : r/ArcBrowser
- Deta Surf
- Orion is the first WebKit browser to feature an Arc-like navigation logic for vertical tabs : r/ArcBrowser
- How are Dia and Arc team the same ? : r/diabrowser
- #oss
- "This is a Low Maintenance Project"
- Open Source is Not About You
- My FOSS Story - Andrew Gallant's Blog
- Geomys, a blueprint for a sustainable open source maintenance firm (2024)
- In the long run, GPL code becomes irrelevant (2015) (on HN)
- NIH is cheaper than the wrong dependency (on HN) (on lobste.rs)
- NPM 'accidentally' removes Stylus package, breaks builds and pipelines
- Simon Willison | Introducing OSS Rebuild: Open Source, Rebuilt to Last #sec
> the Google Security team have announced OSS Rebuild, their project to provide build attestations for open source packages released through the NPM, PyPI and Crates ecosystom
- #agent/idea
- LLM Daydreaming
- LLMs aren’t world models
- openai burns the boats #biz
- Why Does AI Feel So Different? - nilenso blog
> - Thinking by questioning (Socrates)
> - Thinking by logic (Aristotle)
> - Thinking by observing: Empiricism / Scientific Method (Bacon)
> - Thinking by heuristics and biases: System 1 and 2 (Kahneman)
> - Thinking by… augmentation? (AI)
2025-08-22 [2025-08-22]
2025-08-22 [2025-08-22]
- #rust
- rosefromthedead/effing-mad: Algebraic effects for Rust #pl
- Memory Safety is a Red Herring #go #cpp
- Lessons learned from implementing SIMD-accelerated algorithms (ChaCha20 / ChaCha12) in pure Rust #asm
- async-recursion #async
- rust-lang/rust-bindgen #cpp/interop
- krabby: a highly optimized Rust compiler
- https://sr.ht/~bal-e/krabby/
- Krabby: a WIP high-performance Rust compiler
- from https://this-week-in-rust.org/blog/2025/08/13/this-week-in-rust-612/
- Building an Asynchronous FUSE Filesystem in Rust
- Lessons learned from implementing SIMD-accelerated algorithms (ChaCha20 / ChaCha12) in pure Rust #asm
- bliki: Yagni #idea
- from parasyte/task-webapp: Stop Web App Bloat! #web
- #gleam
- Gleam, coming from Erlang
- Using use in Gleam
- Why Elixir? Common misconceptions (on HN) #elixir
- Who Will Maintain Vim? A Demo of Git Who #tui
- #py #pkg #biz
- pyx: a Python-native package registry, now in Beta
- Simon Willison | pyx: a Python-native package registry, now in Beta
> What I want to do is build software that vertically integrates with our open source tools, and sell that software to companies that are already using Ruff, uv, etc. Alternatives to things that companies already pay for today.
> stays true to Charlie's promises to carefully design the incentive structure to avoid corrupting the core open source project that the Python community is coming to depend on
- #design
- How to make absolutely any app look like a macOS app—Martian Chronicles, Evil Martians’ team blog
- font-size-adjust Is Useful
- Why Racket? Why Lisp? | Butterick’s Practical Typography
- Choosing typeface
- I'm Worried It Might Get Bad #idea
- Blog | Fabián's Journal
- #struct #crdt
- Welcome to Automerge | Automerge CRDT
- CRDT: Text Buffer - Made by Evan #struct
- Automerge 3.0
- Ethersync: Peer-to-peer collaborative editing of local text files
- A CRDT-based Messenger in 12 Lines of Bash Using a Synced Folder
- how about an editor? edits can't be dealt with in the same manner
2025-08-06 [2025-08-06]
2025-08-06 [2025-08-06]
- #idea
- Digital hygiene: Emails
- Digital hygiene: Notifications
- Ollama Turbo (on HN)
- Ollama's cloud is a new way to run open models using datacenter-grade hardware.
- ggml.ai
- soupault #ocaml
> Soupault is not like other static site generators — it works on the HTML element tree level. Most SSGs treat HTML as an opaque format that can be generated with templates but cannot be read or manipulated.
>
> Soupault treats HTML as a first-class format and that enables many use cases and features that are impossible for other SSGs.
- Plain Text. With Lines (on HN)
- JSON Canvas — An open file format for infinite canvas data.
- Markdeep Documentation and Feature Demo
- Quickshell, building blocks for your desktop
- a toolkit for building status bars, widgets, lockscreens, and other desktop components using QtQuick
- can be used alongside a wayland compositor or a window manager to build a complete desktop environment
- Simon Willison | Claude Opus 4.1
- Simon Willison | No, AI is not Making Engineers 10x as Productive
- Simon Willison | OpenAI's new open weight (Apache 2) models are good (on HN)
- Software Rot (on HN)
- Spotting base64 encoded JSON, certificates, and private keys (on HN) (on lobste.rs)
- The Amaranth hardware description language (on HN)
- The how and why of GitHub to Codeberg
- Why hx-boost is actually the most important feature of htmx
- Write like nobody's watching
- You can now uv run a GitHub gist (on HN)
- Zig Error Patterns (on HN) (on lobste.rs)
- Zigzag Number Spiral
- cloctui
- cosmopolitan: build-once run-anywhere c library
- exosphere
- introducing spindle
- johncarlosbaez's post on mathstodon.xyz
- the horror of too many readers
2025-08-05 [2025-08-05]
2025-08-05 [2025-08-05]
- Simon Willison | Cloudflare Crawler Hints triggers crawls from Yandex and Bingbot - nothing to do with ChatGPT Agent - it's actually Crawler Hints by Cloudflare - Content-Aware Spaced Repetition - FSRS is both Content-agnostic as well as Deck-agnostic, it might underfit a lot (from HN) - Diagrams For Yourself - the author doesn't want to use something off-the-shelf like Mermaid or TikZ, and want it to look bespoke, something homemade with a slightly distinctive style - #qa - Getting Started with Randomised Testing - Property-Based Testing - describe a range of values - sample from the range - checks if any trigger your assertions - Code Factor - e.g. Code Factor | habedi/chilli - Overview - from habedi/chilli: A microframework for creating command-line applications in Zig - Expressive test assertions without testify/assert #go - New comment by backprop1989 in "Tell HN: Anthropic expires paid credits after a year" - Accounting rules: If the credits last indefinitely, any unused credits cannot be counted as revenue. - Open Sourcing Shaper: Minimal Data Platform for Embedded Analytics - built on top of DuckDB and NATS.io – Cloud Native, Open Source, High-performance Messaging - Qwen-Image: Crafting with Native Text Rendering - 5 percent of the training data was data "synthesized through controlled text rendering techniques", ranging from simple text through text on an image background up to much more complex layout examples - #formal - What I Wish I Knew When Learning Picat - My Picat page - Practical Static Analysis for Privacy Bugs - Binding Application in Idris
2025-08-04 [2025-08-04]
2025-08-04 [2025-08-04]
- #rust
- Perhaps Rust needs "defer"
- an example that using defer idiom rarely gets past the borrow checker
- showcases well how working in Rust with lots of FFI interop feels like
- `miri` used in iterations
- from comments of A deep dive into Rust and C memory interoperability
- The Generativity Pattern in Rust
- DrawAFish.com Postmortem
- used childhood 6-digit password when creating the website
- set up Google Auth, then used it ever after
- forgot that the password remained
- which was previously leaked
- God created men; Sam Altman made them equal
- hyperstition: a cultural self-fulfilling prophecy
- pessimism is an anti-myth that makes Mutual Destruction inevitable. Pessimism is a luxury we can no longer afford.
- the future is unavoidable, but we are always writing its prologue.
- techno-optimistism is now a necessity
- Malcolm Gladwell's cardinal categories of Law & Order provide a compass for tech-induced power redistribution:
- Western
- there’s no system
- AI evades law
- movies
- Ex Machina
- 2001: A Space Odyssey
- Transcendence
- Her
- Blade Runner
- Neuromancer
- Ghost in the Shell
- Northern
- there’s a system and it’s fantastic
- AI enforces law
- movies
- Person of Interest
- RoboCop
- Iron Man
- Knight Rider
- The Machine
- Southern
- the system has to be reformed from the outside
- outsiders against AI
- movies
- The Matrix trilogy
- Eagle Eye
- Alita: Battle Angel
- Free Guy
- The Terminator
- Hackers
- Johnny Mnemonic
- eXistenZ
- Eastern
- the system is reformed from within
- insiders against AI
- movies
- Short Circuit
- Minority Report
- Sneakers
- I, Robot
- Westworld
- War Games
- A.I. Artificial Intelligence
- Wall-E
- Governance in GNOME
- A “bottom up” approach, over-reliance on personal projects and taste, to be sublimated into a shared vision
- options for maintainers
- make yourself indispensable, so that everything ends up passing through you, and everyone has to defer to your taste, opinion, or edict
- replicate your toughts, taste, and opinions into the minds of the people using the API you design
- reimplement the entirety, a reflection of your taste, commitment, and ethos
- governance
- a structure for people to know what to expect and how to navigate the decision making process inside the project
- responsibility is not something to hoard: it’s something to distribute
- random GitLab issues should not be the only place where people can be informed that some decision was taken
- individuals should be able to contribute to a decision without necessarily becoming responsible for a whole project
- a single person responsible for multiple modules should not be able to design and commit on their own
- a lightweight but well-defined process
- discussion: present to the stakeholders, for iteration and consensus
- documentation: for reference to the decision-making process and resolution during implementation and on-going developments
- reminds me of ADR
- HTMX is hard so let's get it right
- many alternatives are suggested on HN
- Maybe the Fastest Disk Usage Program on macOS
- healeycodes/dumac: 🗃️ Very fast alternative to 'du -sh' for macOS that uses getattrlistbulk.
- in #rust, with tokio::task
- macOS has a syscall called getattrlistbulk(2) which allows you to read multiple directory entries and their metadata in one go. It's like a combined "readdir + stat" that returns a batch of file names along with requested attributes like file type, size, etc.
- inspired by the Linux equivalent 201984/dut: A disk usage calculator for Linux - Codeberg.org
- Modern Node.js Patterns
- most of them are news to me, it's glad to learn that nodejs has aquired so many desirable features
- wonder if they apply to Bun as well
- #agent/idea
- Does the Bitter Lesson Have Limits? (on HN)
- The Bitter Lesson
- trying to build knowledge into agents plateaus and even inhibits further progress in the long run
- breakthrough progress eventually arrives by an opposing approach based on scaling computation by search and learning
- four major blows to the human ego
- The Copernican Revolution: we weren’t the center of the universe.
- Darwinian thought: we weren’t separate from animals.
- Freud’s ideas of the unconscious: we weren’t in full control of our selves.
- Cyborgs, robots, and automatons: non-humans could do the work of humans.
- Garbage Can Model
- organizations as chaotic “garbage cans” where problems, solutions, and decision-makers are dumped in together
- decisions often happen when these elements collide randomly, rather than through a fully rational process
- represents a world where unwritten rules, bespoke knowledge, and complex and undocumented processes are critical
- issues of the bitter lesson
- dependent on high-quality data
- adding compute is often not practical nor optimal
- Read your code (on HN)
- The Future Of Software Is Small
- Typed languages are better suited for vibecoding (on HN)
- Rust, Python, and TypeScript: the new trifecta
- Bag of words, have mercy on us
- Model Collapse and the Need for Human-Generated Training Data (on HN)
2025-08-03 [2025-08-03]
2025-08-03 [2025-08-03]
- How do you backup your non-work-related data? - most suggests `restic` - Cloud Backup: Easy, Secure, Unlimited Online Backup - Backblaze B2, good affordability/pricing, ~$5/mo - `borg` has security footgun - use https://healthchecks.io/ to monitor backup jobs - Append-only Restic backups on a Hetzner Storage Box - good #design, [source] - Append-only backups with restic and rclone - jmtd → computing → Network Attached Storage (NAS) - Personal backups and file archival // Josh Mock - If you're remote, ramble - Ramblings channels let everyone share what’s on their mind without cluttering group channels - short updates 1-3 times per week - common topics - ideas related to current projects - musings about blog posts, articles, user feedback - “what if” suggestions - photos from recent trips or hobbies - rubber ducking a problem - each ramblings channel - named after the team member - only that person can post top-level messages. Others can reply in threads, but not start new ones - muted by default, with no expectation that anyone else will read them - ramblings are our equivalent of water cooler talk - Linear Types for Programmers (2023) #lang - The Austral Programming Language - faiface/par-lang: Par (⅋) is an experimental concurrent programming language. It's an attempt to bring the expressive power of linear logic into practice. - Twenty Eighth International Obfuscated C Code Contest - the redesign broke all links to the old entries without redirects - now requires using a javascript capable browser to view the entries on github (github having removed non-JS access last year)
2025-08-02 [2025-08-02]
2025-08-02 [2025-08-02]
- #agent
- Cerebras Code
- Cerebras Code Pro ($50/month)
- Code Max ($200/month)
- Qwen3-Coder, but at 2,000 tokens per second, with a 131k-token context window
- cchistory: Tracking Claude Code System Prompt and Tool Changes
- Reconstructing a timeline for Amazon Q prompt infection #sec
- Amazon's AI Coding Revealed a Dirty Little Secret (on HN)
- NativeMind
- Unit Testing Principles
- overcomplicated code should be split into
- deep domain classes, to be thoroughly unit tested
- wide controllers, exercised by strategic integration tests
- unit tests should verify units of behavior
- four pillars of a good unit test
- protection against regressions
- resistance to refactoring
- fast feedback
- maintainability
- I think I have got them all wrong when setting up tests for GAlgebra
- #lib
- candyfloss: an ergonomic python library for running video pipelines
2025-08-01 [2025-08-01]
2025-08-01 [2025-08-01]
- #agent
- 6 Weeks of Claude Code (on HN) (on lobste.rs)
- "a list of things which I have completed, solo, ..., they are years of “tech debt” / “tech innovation” backlog for me"
- Individual Contributor Ladder
- AI is a floor raiser, not a ceiling raiser
- on HN
- AI is "automated ladder pulling technology"
- "AI does all those lower level jobs, puts the people who need those jobs for experience on the street, and robs us of future experts."
- 'A black hole': New graduates discover a dismal job market
- Vibe code is legacy code
- "We already have a phrase for code that nobody understands: legacy code"
- A Hitchhiker's Guide to the AI Bubble
- "The fact there is real value in the technology does not contradict in any way that we are in a bubble."
- Trying out Qwen3 Coder Flash using LM Studio and Open WebUI and LLM
- "A neat feature of Open WebUI is that it includes an automatic preview panel, which kicks in for fenced code blocks that include SVG or HTML"
- #sec
- How to Secure a Linux Server (on HN)
- however, it's pointed out on HN that one should not follow this
- "This guide ignores many sane defaults in favor of a patchwork..., added over time by random people with no thought for threat modeling, that may even result in an increased attack surface."
- "This guide contains (at least) inaccurate statements. It's oversimplifying and omitting important things while putting emphasis on some exotic details where defaults would be sane enough."
- better alternatives suggested, both authored by `a13xp0p0v`
- Linux Kernel Defence Map - Security Hardening Concepts (on HN)
- Linux Kernel Hardening Checker (on HN)
- ComplianceAsCode/content: Security automation content in SCAP, Bash, Ansible, and other formats is also suggested
- it facilitates security policy content authoring
- along with ansible playbook/bash scripts to check or fix compliance
- When Flatpak’s Sandbox Cracks: Real‑Life Security Issues Beyond the Ideal | Linux Journal
- Long Term Support for SQLite
- admirable efforts to support SQLite through the year 2050
- Live coding sucks | Mustapha Hadid
- "Live coding interviews measure stress, not coding skills"
- Comment by lapcat
- "something about strangers standing over my shoulder judging me, determining my financial future by providing or withholding a job, like the sword of Damocles, turns my stomach inside out"
- "A lot of commenters causally speak of "false negatives" as if they were random, but some people, myself included, are always the false negative."
- #tmux
- Replacing tmux in my dev workflow (on HN) (on lobste.rs)
- shpool + autossh(1)
- Customizing tmux
- lots of potentially useful comments on on HN
July, 2025 [2025-07]
July, 2025 [2025-07]
2025-07-31 [2025-07-31]
2025-07-31 [2025-07-31]
- #perf
- Benchmarks in CI: Escaping the Cloud Chaos
- Big O vs Hardware: Better Complexity ≠ Better Performance
- bu/doc/tim.md at main · c-blake/bu
- Snooping On Slow Builds (Using Syscalls)
- #browser
- I tried Servo, the undercover web browser engine made with Rust #rust
- "this approach of breaking down a web engine into independently usable modules with public APIs will make it easier for people to get involved in web engine development, and make it easier for people to create new web engines in future" (on HN)
- servo/stylo: CSS engine that powers Servo and Firefox
- servo/html5ever: High-performance browser-grade HTML5 parser
- DioxusLabs/taffy: A high performance rust-powered UI layout library
- DioxusLabs/blitz: A radically modular HTML/CSS rendering engine
- Orion Browser by Kagi
- Kagi believes that they need to offer a hollistic replacement for big tech for consuming the web, that includes search, browser and email (on HN)
- How we made JSON.stringify more than twice as fast
- #cg
- PixiEditor 2.0 – A FOSS universal 2D graphics editor (on HN)
- Raster, Vector, Animations, Procedural (VFX, effects, non-desctuctive editing)
- written in C#, copyleft
- alternatives
- G'MIC - GREYC's Magic for Image Computing: A Full-Featured Open-Source Framework for Image Processing - Main
- Kdenlive - Free and Open Source Video Editor
- Physically Based Shading in Theory and Practice
- 3D Line Drawings
- a 3d scene that can be posed and shows as a 2d line illustration
- based on Gaussian Splats
2025-07-29 [2025-07-29]
2025-07-29 [2025-07-29]
- #zig #perf
- Zig profiling on Apple Silicon | Bugsik
- mstange/samply
- a command line sampling CPU profiler which uses the Firefox profiler as its UI
- for macOS, Linux, and Windows
- verte-zerg/poop at kperf-macos
- a fork of poop to use kperf under Mac
- wolfpld/tracy: Frame profiler
- A real time, nanosecond resolution, remote telemetry, hybrid frame and sampling profiler for games and other applications
- C, C++, Lua, Python, Fortran, Rust, Zig, C#, OCaml, Odin, GPU
- Windows, Linux, Android, FreeBSD, WSL, OSX, iOS, QNX
- Generic Programming and anytype - Docs - Ziggit
- Using Zig allocator for C libraries (Alignment question)
- `Allocator.rawAlloc`/`.rawFree`
- `@alignOf(std.c.max_align_t)`
- ANDRVV/zprof: 🧮 Cross-allocator profiler for Zig
- battle-tested in raptodb/rapto: transposition-heuristic storage, low memory footprint and high-performance querying
- Writing memory efficient C structs (on HN)
- 10^19712 years to exhaust u65535
- u65535 is the integer type with the highest max value supported in Zig (from Zig doc)
- #physics
- Background independence
- #crypto
- Fintech dystopia (on HN)
- #perf
- Giving Benchmarks a Boat
- TPC-C is a benchmark for transactional databases that models an order system with goods spanning many warehouses
- Each warehouse comes with some set amount of data to be managed and some amount of query traffic that adheres to some specific distribution laid out in the spec
- they can account for
- what's the proportion of hot vs. cold data
- what's the ratio of transactions-per-minute to bytes stored
- what's the proportion of read-only queries, vs. simple, point writes, vs. complex read-write transactions
- what proportion of transactions go cross-shard
- The metric: "we sustained the workload at X warehouses with Y hardware at Z cost."
- #movie
- Nothing to watch – Experimental gallery visualizing 50k film posters
- #agent
- Show HN: A GitHub Action that quizzes you on a pull request (on HN) #aicr
> PR Quiz uses AI to generate a quiz from a pull request and blocks you from merging until the quiz is passed.
- Learn Rust by Reasoning with Code Agents #rust
- Principles for production AI agents (on HN)
- context
- modern LLMs just need direct detailed context, no tricks, but clarity and lack of contradictions
- structuring context so that the system part is large and static and user one is small and dynamic works great
- provide the bare minimum of knowledge in the first place, and the option to fetch more context if needed via tools
- context compaction tools can help avoiding logs and other artifacts from the feedback loop to bloat the context
- tools
- good tools typically operate on a similar level of granularity, and have a limited number of strictly typed parameters
- idempotency is highly recommended to avoid state management issues
- LLMs are very likely to misuse your loopholes, and that’s why you don’t want to have any loopholes
- v.s. human API users are more capable of reading between the lines, can navigate complex docs and find workarounds
- designing an agent to write some DSL (domain-specific language) code with actions rather than calling tools one by one is a great idea
- feedback loop
- actor-critic approach: where an actor decides on actions and a critic evaluates them
- allow actors to be creative, and critics to be strict
- error recovery
- a chain of bad fixes is not fixable anymore - just discard and try again
- agents try alternatives because the explicitly requested tool call failed with crucial ingredients
- tell them to ask for these ingredients before trying alternatives
- baseline agent + logs + LLM analysis = insights for improvments
- Q&A: Combining Math and LLMs
- Raw math/algos and LLM are both powerful tools in your modeling toolkit
- If you’re missing either tool from your toolkit, then that will severely hamstring your modeling abilities and many problems will remain inaccessible to you.
- Show HN: Companies use AI to take your calls. I built AI to make them for you
- top comment on HN introduced a great use case for LLM-back reception
- local plumbing business
- understand and repeated back the client's request in a slightly different, more professional way for confirmation
- asked a few more smart follow-ups
- the plumber called back and jumped straight into solutions, pricing, and his availability
- prefer to talk to LLM, if the issue can be quickly triaged to the right human who actually understand the situation
- synchronous interaction by bot
- can perform first level troubleshooting, ask for clarification, begin to form a plan and get your buy-in
- v.s. fire-and-forget email form
- incomplete reports, missing information, people who have no idea what they're talking about
- Show HN: Terminal-Bench-RL: Training Long-Horizon Terminal Agents with RL (on HN)
- Custom scaffolding (system prompt and tools) using Qwen3-32B achieved 13.75- The author has built an RL system, but it has not been used for anything due to cost limitations.
- Stop selling “unlimited”, when you mean “until we change our minds”
- the playbook
- launch with generous/unlimited limits
- build user dependency
- add caps targeting "less than 5- frame as "sustainability" or "fairness"
- that "5- power users with deep workflow integration
- early adopters who took platform risks
- team influencers who drive organizational adoption
- $200/month Claude Max subscribers doing serious work
- Tokens are getting more expensive
- Claude Code weekly rate limits
- The Rise of Vibeinsecurity
- a story about how devs lost their jobs over vibe apps, and vibe apps are hacked by vibe hackers immediately after deployment
- this is also an ad for a conference called HackAIcon
- It's rude to show AI output to people
- whenever you propagate AI output, you're at risk of intentionally or unintentionally legitimizing it with your good name, providing it with a fake proof-of-thought
- Agentic Coding Things That Didn’t Work
- #sec #privacy
- Tea app leak worsens with second database exposing user chats
- #idea
- Hyrum's Law
- "With a sufficient number of users of an API, it does not matter what you promise in the contract: all observable behaviors of your system will be depended on by somebody"
- "corollary: even if you explicitly deny a guarantee of a certain behavior in your contract, if you usually deliver that behavior, most of your customers will depend on it."
- Why Try When Others Could Do Better?
- Even the smartest, highest-agency people in the world are severely bandwidth constrained and don’t get around to doing most of the things they have the potential to do.
- Compound that over and over again in some niche and you get hundreds, thousands, millions of miles ahead of the fastest runners who aren’t running down that niche.
- Pragmatism in Programming Proverbs
- many interesting quotes
- Objects should shut up (on HN)
- I'm also deeply annoyed by unnecessary alarms
- Don’t Let Architecture Astronauts Scare You #system
- I'm rebelling against the algorithm
- Maybe writing speed actually is a bottleneck for programming
- #rust #metaprogramming
- Advanced Rust macros with derive-deftly
- rules_derive: deriving using macro_rules
2025-07-26 [2025-07-26]
2025-07-26 [2025-07-26]
- Combinatory Programming - a nice intro to basic patterns and their motivations - Smullyan’s To Mock a Mockingbird - Essays/Tacit Expressions - J Wiki - #mac - Show HN: A macOS clock that stays visible when coding or binging in fullscreen (on HN) - Jean-Tinland/simple-bar: A yabai, AeroSpace or FlashSpace status bar widget for Übersicht - AltTab - Windows alt-tab on macOS - rcmd - Switch apps instantly using the ⌘ Right Command key - very cool idea, start using it now - Karabiner-Elements - Turn any diagram image into an editable Draw.io file. No more redrawing (on HN) - Pic2Chart - Convert Diagrams to Editable PowerPoint SVGs
2025-07-24 [2025-07-24]
2025-07-24 [2025-07-24]
- #lint
- Detekt – A static code analyzer for Kotlin (on HN)
- gardner/LocalLanguageTool: Self-hosted LanguageTool private instance is an offline alternative to Grammarly
- #idea
- Programming Language Escape Hatches
> Capability is desirable but comes into conflicts with a lot of other desirable properties, like simplicity or efficiency.
> an escape hatch is a feature that deliberately breaks core assumptions about the language in order to add capabilities.
- Why I do programming (on HN)
> For me, programming has always been more than a skill. It’s a way to explore, to tinker, and to satisfy curiosity.
- The ultimate meeting culture (on HN) (on lobste.rs)
> The goal of an exceptional meeting culture is to allow for people to constructively decline meetings by fully understanding the consequences of their action.
2025-07-22 [2025-07-22]
2025-07-22 [2025-07-22]
- #struct
- Algorithms for Modern Processor Architectures (on HN) #asm #cpp #perf
- Hyperpb: 10x faster dynamic Protobuf parsing that's faster than generated code (on HN)
- PSA: SQLite WAL checksums fail silently and may lose data (on HN) #db
- #formal
- Formal specs as sets of behaviors (on HN) (on lobste.rs)
- Asymmetry of verification and verifier’s law
- A reckless introduction to Hindley-Milner type inference
- Verified Assembly 2: Memory, RISC-V, Cuts for Invariants, and Ghost Code
- #selfhost/data
- Blip: Peer-to-Peer Massive File Sharing by Former Dropbox Engineers (on HN)
- n0-computer/sendme: A tool to send files and directories, based on iroh
- Iroh
- schollz/croc: Easily and securely send things from one computer to another :package:
- PairDrop | Transfer Files Cross-Platform. No Setup, No Signup.
- Magic-Wormhole: Get Things From One Computer To Another, Safely — Magic-Wormhole 0.20.0+24.g0a212b2 documentation
- Keet by Holepunch #im
- Copyparty – Turn almost any device into a file server (on HN) (on lobste.rs)
- #mm
- Don't bother parsing: Just use images for RAG (on HN)
- Yt-transcriber – Give a YouTube URL and get a transcription (on HN)
- `yt-dlp` has such functionality built-in, tricks needed to avoid being banned
- Phind.design – Image editor & design tool powered by 4o / custom models (on HN)
- Kitten TTS: 25MB CPU-Only, Open-Source Voice Model (on HN)
- Kitten TTS Nano Demo
- Piper TTS Web Demo
- Free Online Text to Speech - Private AI Voice Generator | QuickEditVideo
- SAM: Software Automatic Mouth
2025-07-20 [2025-07-20]
2025-07-20 [2025-07-20]
- #selfhost
- My Ultimate Self-hosting Setup (on HN) (on lobste.rs)
- Coolify, an open-source & self-hostable Heroku / Netlify / Vercel alternative.
- Dokploy - Effortless Deployment Solutions
- HomeFree
- gokrazy Go appliances :: gokrazy
- #selfhost/data
- Borg – Deduplicating archiver with compression and encryption (on HN)
- Emborg — Front-End to Borg Backup — emborg 1.42 documentation
- Home | Vorta for BorgBackup
- Pika Backup – Apps for GNOME
- BorgBase - Simple and Secure Offsite Backups
- restic · Backups done right!
- garethgeorge/backrest: Backrest is a web UI and orchestrator for restic backup.
- Kopia
- Plakar - Effortless backup
- Make Your Own Backup System – Part 1: Strategy Before Scripts
- #os
- I Used Arch, BTW: macOS, Day 1 (on HN)
- Why Some Satellites Use NetBSD?
- Graphene OS: a security-enhanced Android build (on HN)
- Maru OS – Use your phone as your PC (on HN)
- Omarchy, a Linux Distribution by DHH (on HN)
- #gui
- Introducing XMLUI (on HN) (on lobste.rs)
- #py
- metap: A Meta-Programming Layer for Python
- You might not need a Python class (on HN)
- Simon Willison | TIL: Exception.add_note
2025-07-19 [2025-07-19]
2025-07-19 [2025-07-19]
- #agent
- Agents built from alloys (on HN) #sec
> Like most typical AI agents, we call the model in a loop. The idea behind an alloy is simple: instead of always calling the same model, sometimes call one and sometimes the other.
- Ccusage: A CLI tool for analyzing Claude Code usage from local JSONL files
- Coding with LLMs in the summer of 2025 (an update)
- Simon Willison | Coding with LLMs in the summer of 2025 (an update)
> When your goal is to reason with an LLM about implementing or fixing some code, you need to provide extensive information to the LLM: papers, big parts of the target code base. And a brain dump of all your understanding of what should be done.
> You will be able to do things that are otherwise at the borders of your knowledge / expertise while learning much in the process. Yet, everything produced will follow your idea of code and product, and will be of high quality and will not random fail because of errors and shortcomings introduced by the LLM.
- GLM-4.5: Deeper, Headier, & better than Kimi/Qwen/DeepSeek (SOTA China LLM?)
- GLM-4.5: Reasoning, Coding, and Agentic Abililties (on HN)
- Simon Willison | GLM-4.5: Reasoning, Coding, and Agentic Abililties
- Simon Willison | My 2.5 year old laptop can write Space Invaders in JavaScript now (GLM-4.5 Air) (on HN)
- Simon Willison | Qwen3-30B-A3B-Instruct-2507
- The current hype around autonomous agents, and what actually works in production (on HN)
- How Anthropic teams use Claude Code (on HN)
- Cerebras launches Qwen3-235B, achieving 1.5k tokens per second (on HN)
- Lumo: Privacy-first AI assistant (on HN)
- Simon Willison | Announcing Toad - a universal UI for agentic coding in the terminal
- Price Per Token – LLM API Pricing Data (on HN)
- You can now train a 70B language model at home (on HN)
- #disect
- The Big LLM Architecture Comparison (on HN)
- Transformer Explainer: LLM Transformer Model Visually Explained
- LLM Embeddings Explained: A Visual and Intuitive Guide (on HN)
- Getting into Flow State with Agentic Coding (on HN)
- LLMs are bad at returning code in JSON
- An AI tool I find useful: a review command
- #disect
- Do you understand f-strings? (on HN) (on lobste.rs)
- Enough unix to get by
- LL and LR Parsing Demystified (2013)
- Reverse proxy deep dive
- Reverse Proxy Deep Dive Part 2: Why HTTP Parsing at the Edge Is Harder Than It Looks
- What is X-Forwarded-For and when can you trust it?
- The Secret Life of Fsync (2023) (on HN)
- Programming vehicles in games (on HN) #game
- Never write your own date parsing library (on HN)
- How I hacked my washing machine (on HN) (on lobste.rs)
- Making Postgres slower (on HN) #db
- #sec
- Certificate Transparency - Part 1
- Firefox-patch-bin, librewolf-fix-bin AUR packages contain malware (on HN)
- #sovereign
- New comment by voxleone in "The future is not self-hosted"
> Self-hosting isn't just about tech choices — it's about *who controls access to knowledge*.
>
> During the Enlightenment, owning a physical copy of a book meant intellectual freedom. You didn’t rent ideas; you had them.
>
> Today, most digital knowledge is hosted, locked, or streamed — *leased from platforms*, not owned. We’re in fact drifting into *digital feudalism*, where access to culture, tools, and even history depends on gatekeepers.
- Myspace - Archiveteam
- Anthropic tightens usage limits for Claude Code without telling users (on HN)
- Apple bans entire dev account, no reason given (on HN)
- Gmail's backup codes are useless to access account
- Linux and Secure Boot certificate expiration (on HN) (on lobste.rs)
- #lang
- Kap lang #apl
- Kernel #lisp
- #idea
- Covers as a way of learning music and code (on HN)
> Playing someone else's music, making a cover, is great because it can make it objective. It gives you something to check against.
- Why Lexing and Parsing Should Be Separate
> A lexer recognizes the non-recursive structure of a language. Its output is a token stream.
> A parser recognizes the recursive structure of a language. Its output is a tree.
> Lexing with regular languages (expressions) is nice because it can be done in `O(n)` time and `O(1)` space (using automata-based techniques)
> There is essentially one algorithm for lexing -- march forward through the input exactly once.
> Parsing CFGs is `O(n^3)` in general, and parsing PEGs either takes `O(n)` space (packrat parsing) or exponential time (backtracking)
> separating lexing and parsing reduces the n in your O(n^3). In any real program, there are many more characters than tokens
- TODOs Aren't for Doing
> (A TODO) doesn’t need to be a plan to actually do something. Instead, it’s a note about “here’s an edge case that wasn’t handled” or a suggestion for a better structure that the author didn’t make time to implement — it captures a little slice of the author’s brain and gives a little window into the rich context they had at the time they wrote the code.
- Lookism
- Liking What You See: A Documentary
- Computational Tyranny
- Why Does Raising the Retirement Age Hurt Young People? (on HN)
- Electric bikes might just be the healthiest thing to ever happen to teenagers (on HN)
- #kb
- Molab, a cloud-hosted Marimo notebook workspace #py
- Announcing molab | marimo
- Export notebook as markdown with output · Issue #3692 · marimo-team/marimo
- Export to other formats - marimo
- Publish to the web - marimo
- marimo-team/quarto-marimo: marimo extension for Quarto ⚡ run reactive code inside Quarto
- akshayka/test-markdown-export
- Org tutorials (on HN)
- hygg, a minimalist terminal-based document reader supporting PDFs, EPUBs, and text files with vim-like navigation
- kruseio/hygg
- Alto turns Apple Notes into a website (on HN)
- #idea
- Wishes Upon My Demise
- death
- maybe I should write one for my death
- Your Parents Did The Best Job They Knew How To Do
2025-07-18 [2025-07-18]
2025-07-18 [2025-07-18]
- #ph
- A New Geometry for Einstein's Theory of Relativity
- [1808.01536] Displacement convexity of Boltzmann's entropy characterizes the strong energy condition from general relativity (2018)
- [1810.13309] An optimal transport formulation of the Einstein equations of general relativity (2018)
- [1909.09575] Generalized cones as Lorentzian length spaces: Causality, curvature, and singularity theorems (2019)
- [2004.08934] Optimal transport in Lorentzian synthetic spaces, synthetic timelike Ricci curvature lower bounds and applications (2020)
- [2408.15968] A nonlinear d'Alembert comparison theorem and causal differential calculus on metric measure spacetimes (2024)
- [2506.04934] On the geometry of synthetic null hypersurfaces (2025)
- Testing Quantum Theory in Curved Spacetime
- Dirac reduction algebra
- #zig
- #async
- Asynchrony is not concurrency (on HN) (on lobste.rs)
- Async I/O on Linux and durability
- io_uring.pdf
- Getting Hands-on with io_uring using Go
- How to handle people dismissing io_uring as insecure? (on HN) #sec
- Async runtime and interface
- What can unpopular languages learn from Zig about how to grow a community?
- New Aarch64 Back End (on HN) (on lobste.rs)
- Zig's @fieldParentPtr for dumbos like me
- Lessons learnt while upgrading Apache Arrows project, a zig port, to be compatible with zig 0.14.1.
- #rust
- polycode: Encode a binary file as a rational polynomial function
- Async Rust Is A Bad Language (2023) #async
- The borrowchecker is what I like the least about Rust (on HN) (on lobste.rs)
- Rickrolling Turso DB (SQLite rewrite in Rust)
- StackSafe: Taming Recursion in Rust Without Stack Overflow (on HN)
- tailcall - Rust
- SQLx – Rust SQL Toolkit (on HN)
- #ts
- Run TypeScript code without worrying about configuration
- Node.js — Running TypeScript Natively
- Bun adds pnpm-style isolated installation mode (on HN)
- #web
- DaisyUI: Tailwind CSS Components (on HN)
- daisyUI and Tailwind CSS theme generator — Tailwind CSS Components ( version 5 update is here )
- Open Props: sub-atomic styles
- Kelp: A UI library for people who love HTML, powered by modern CSS and Web Components
- A 14kb page can load much faster than a 15kb page (2022) (on HN)
- Tailwind is the Worst of All Worlds (on HN) (on lobste.rs)
> people like tailwind not for its API or ergonomics but for its design system
- Nativewind
- UnoCSS: The instant on-demand Atomic CSS engine
- tachyons-css/tachyons: Functional css for humans
- Mantine UI
- It's time for modern CSS to kill the SPA (on HN) (on lobste.rs)
> The reason SPAs became the default...was because, for a while, they were the only way to deliver something that felt fluid – something that didn’t flash white between pages or jank the scroll position.
- Smooth transitions with the View Transition API | View Transitions | Chrome for Developers
- Guide to implementing speculation rules for more complex sites | Web Platform | Chrome for Developers
- What is Lit? – Lit
> a boilerplate-killing component base class that provides reactive state, scoped styles, and a declarative template system that's tiny, fast and expressive.
- Windows 7 GUI for the Web (on HN) #css #os #tech-history
- 98.css
- XP.css
2025-07-17 [2025-07-17]
2025-07-17 [2025-07-17]
- #rust
- A Rust shaped hole (on HN) (on lobste.rs)
- #term
- gren-tui: Pure functional TUIs with The Elm Architecture #tui
- Gren
- `waitlock`: Linux CLI tool to provide mutex locks for long running bash ops
- flock(1) - Linux manual page
- lsr: ls but with io_uring #zig
- on tangled
- Speeding up my ZSH shell (on HN)
- timep - trap-based profiler, flamegraph for bash
- QuakeNotch: Quake Terminal on your MacBook's notch (on HN)
- simtool
- stormy
- Multiplex: Command-Line Process Mutliplexer (on HN) (on lobste.rs)
- ddollar/foreman: Manage Procfile-based applications
- pvolok/mprocs: Run multiple commands in parallel
- dtop
2025-07-15 [2025-07-15]
2025-07-15 [2025-07-15]
- #system
- A distributed systems reliability glossary
- #gpu
- Rust running on every GPU (on HN) (on lobste.rs)
- https://mlir.llvm.org/docs/Dialects/NVGPU/
- https://mlir.llvm.org/docs/Dialects/AMDGPU/
- https://mlir.llvm.org/docs/Dialects/XeGPU/
- Backpropagating through a maze with candle and WASM #disect #game
- Apple's MLX adding CUDA support (on HN)
- Programs built against MLX -> Can take advantage of CUDA-enabled chips
- not the other way around
- SCALE documentation
- SCALE is a GPGPU programming toolkit that can natively compile CUDA applications for AMD GPUs.
- spectral-compute/scale-examples
- GPUHammer: Rowhammer Attacks on GPU Memories are Practical #sec
- A GPU Calculator That Helps Calculate What GPU to Use (on HN)
- #db
- Embedding User-Defined Indexes in Apache Parquet Files
- #selfhost
- Packages proxies
- EpicWink/proxpi: PyPI caching proxy
- panamax-rs/panamax: Mirror rustup and crates.io repositories, for offline Rust and cargo usage.
- Pulp Project
> Some specialized proxies handle different kinds of packages, like Pulp.
- soulteary/apt-proxy: [Ubuntu / Debian / CentOS / Alpine] Lightweight APT / YUM / APK CHACHE PROXY just over 2MB in size!
- NGINX Content Caching | NGINX Documentation
> Squid is boring; lets use Nginx cache.
- #agent
- Show HN: We made our own inference engine for Apple Silicon
- A high-performance inference engine for AI models, in Rust
- trymirai/lalamo: JAX infrastructure for model optimisation
- Anemll/Anemll: Artificial Neural Engine Machine Learning Library
- #nix
- Trying Guix: A Nixer's Impressions
- #workflow
- Nextflow: System for creating scalable, portable, reproducible workflows
- Metaflow: Build, Manage and Deploy AI/ML Systems (on HN)
- Why Metaflow? (on HN)
2025-07-14 [2025-07-14]
2025-07-14 [2025-07-14]
- #cg
- Algorithms for making interesting organic simulations (on HN) (on lobste.rs)
- Simulating Fluids, Fire, and Smoke in Real-Time
- Ten years of running every day, visualized
- Hallucinations on the future of real-time rendering
- #asm
- The missing guide to Dataflow Analysis in MLIR
- Let's Learn x86-64 Assembly! Part 0 - Setup and First Steps
- Welcome to Asm Editor
- A Programmer’s Guide to x86-64 Assembly (Series Overview)
- Understanding Registers and Data Movement in x86-64 Assembly
- detour: A detour through the Linux dynamic linker
- SIMD Within a Register: How I Doubled Hash Table Lookup Performance (on HN) #perf
- Profiling without Source code – how I diagnosed Trackmania stuttering #perf #game
- #cpp
- The Best C++ Library
- Stepanov’s biggest blunder
- C++ Coroutines Advanced: Converting std:future to asio:awaitable (on HN)
- Initial implementation of the experimental C++ Lifetime Safety Analysis (-Wexperimental-lifetime-safety) has just landed in Clang
- cppq: Simple, reliable & efficient distributed task queues for C++17
- #formal #lean
- Yalep - Micro language based on Lean for teaching mathematical high-school proofs
- Using Lean like an External SMT Solver from Python
- CSLib: A Foundation for Computer Science in Lean 4
- LeanTree: Accelerating White-Box Proof Search with Factorized States in Lean 4
- Solving Formal Math Problems by Decomposition and Iterative Reflection
- A formalization of elementary linear algebra Part I Part II
- Symbolic World Models in Lean 4 for Reinforcement Learning | OpenReview
- #math
- robust matrix factorization
- #mac
- ByteAtATime/flare: Raycast-compatible launcher for Linux
2025-07-13 [2025-07-13]
2025-07-13 [2025-07-13]
- #scifi
- Are we Trek yet? – A guide for how close we are to Star Trek technology (on HN)
- Reading Neuromancer for the first time in 2025 (on HN)
- #idea
- Two Simple Rules to Fix Code Reviews
- First Come First Served: The Impact of File Position on Code Review
- Why measuring productivity is hard
- constrained languages are easier to optimize
- Minimalism is a Cult
2025-07-12 [2025-07-12]
2025-07-12 [2025-07-12]
- #ai-safety
- Death by a Thousand Slops
- Bad Actors Are Grooming LLMs to Produce Falsehoods (on HN)
- Grok 4 will always snitch on you and email the feds if it suspects wrongdoing (on HN)
- Simon Willison | Musk’s latest Grok chatbot searches for billionaire mogul’s views before answering questions
- Death by AI
- DuckDuckGo now lets you hide AI-generated images in search results (on HN)
- Meta says it won’t sign Europe AI agreement, calling it an overreach (on HN)
- Replit goes rogue and deletes our entire database (on HN)
- Vibe Coding Gone Wrong: 5 Rules for Safely Using AI
- Simon Willison | Quoting ICML 2025
> Submitting a paper with a "hidden" prompt is scientific misconduct if that prompt is intended to obtain a favorable review from an LLM.
- AI Friend Apps Are Destroying What's Left of Society (on HN)
- Hacker slips malicious 'wiping' command into Amazon's Q AI coding assistant (on HN)
- We built the security layer MCP always needed
- #disect
- Introduction to Digital Filters
- Karl Hiner - Introduction to Digital Filters - Jupyter notebooks and a geometric interpretation of digital audio filters (on HN)
- new Date("wtf")
- What the Fuck Python (on HN)
- How does a screen work?
- When SIGTERM Does Nothing: A Postgres Mystery
- Artisanal Handcrafted Git Repositories (on HN) (on lobste.rs) #jj
- #crash
- Preliminary report into Air India crash released (on HN)
- #fediverse
- Revival: There appears to be media consensus: "Bluesky is dead."
- #ph
- Black hole merger challenges our understanding of black hole formation (on HN)
- LIGO detects most massive black hole merger to date (on HN)
- U.S. abandons hunt for signal of cosmic inflation
- China is quietly preparing to build a gigantic telescope | Science | AAAS
- Xuntian
- Ten Minute Physics
- Why you can't color calibrate deep space photos (on HN)
- #sandbox
- What is Incus?
- Bedrock: A tiny, portable 8-bit virtual computer (uxn fork)
- #game
- Simon Tatham's Portable Puzzle Collection (on HN)
- Unofficial Bevy Cheat Book
- 3D Math Primer for Graphics and Game Development
- luxe engine | A lovingly crafted game engine
- Dog Walk: Blender Studio's official game project (on HN)
- 3D Game Engine Programming
- Procedural Content Generation in Games #cg
- Godot Engine 4 Tutorials
- SnowballSH/Avalanche: UCI Chess Engine written in Zig.
- ~voroskoi/delilah - sourcehut git
- I designed my own fast game streaming video codec – PyroWave (on HN)
- Show HN: I built an AI that turns any book into a text adventure game (on HN) #agent
2025-07-11 [2025-07-11]
2025-07-11 [2025-07-11]
- agent
- Not So Fast: AI Coding Tools Can Actually Reduce Productivity
- 19 percent productivity drop
- it's most interesting how objections are addressed
- The John Henry Effect: motivated to “beat the machine”, not observed
- Underuse of AI: not observed
- Cheating: can't explain a productivity loss
- Overly optimistic time estimates: should cancel out
- Skewed task definitions: randomly assigned
- Dropout effects: incomplete tasks are evenly divided
- Out-of-date tools: not observed
- Inaccurate time reporting: use alternative metrics
- Overuse of AI: carried away by exploring AI
- Lack of experience with AI tools: prior experience reported, no improvements through the study observed
- Difference in thoroughness: 47 percent more code by AI
- quotes from First, They Came for the Software Engineers… - by TarenSK
- "Typically, large productivity boosts occur for small, well-defined, greenfield projects, or when an engineer is first learning a new language or API"
- "For other work, gains from using current AI tools are often far more modest – and potentially entirely offset by increased time needed for review, debugging, integration, and managing AI quirks."
- AI agent benchmarks are broken
- many validity issues are identified in uiuc-kang-lab/agentic-benchmarks
- We're Light-Years Away from True Artificial Intelligence, Says Martha Wells, author of the Murderbot Diaries series
- Vibe Kanban – Kanban board to manage your AI coding agents
- tried, required too much GitHub authorization, settled on local-first backlog
- An almost catastrophic OpenZFS bug and the humans that made it
- follow-up: What people said about an OpenZFS bug
- wrapper types can be done, but they are very difficult to work with
- unused variable warning can't catch it, as it is only a dead store: we store a value that is never read
- static analysers all catch it, but they suffer from noise
- OpenZFS Bug Ported to Zig #zig
- FP8 is ~100 tflops faster when the kernel name has "cutlass" in it
- the PR
- "that is a very usual way (known practices) of vendors applying specific optimizations for known things"
- Pangolin – Open source alternative to Cloudflare Tunnels
- client: fosrl/newt: A tunneling client for Pangolin
- a custom user space WireGuard client
- may be cheap to self-host on RackNerd
- awesome-tunneling: List of ngrok/Cloudflare Tunnel alternatives and other tunneling software and services. Focus on self-hosting.
2025-07-10 [2025-07-10]
2025-07-10 [2025-07-10]
- #rust
- Optimizing a Math Expression Parser in Rust #perf
- profile time usage: `cargo flamegraph` which uses jonhoo/inferno: A Rust port of FlameGraph
- profile memory usage: nnethercote/dhat-rs: Heap profiling and ad hoc profiling for Rust programs.
- SIMD scan
- `mmap`
- (Quite) A Few Words About Async
- reviewed alternative to async, and async/await in Python, Js, Rust, (and not in) Go (implicit M:N scheduling), OCaml (effect)
- From Async/Await to Virtual Threads
- Tree Borrows (on HN) #formal
- earlier blog post: Tree Borrows
- Tree Borrows rejects 54 percent fewer test cases than Stacked Borrows does
- proven in Rocq: most of the Stacked Borrows optimizations are retained, read-read reorderings and other important new optimizations are enabled
- Stacked borrows is Miri's runtime model, the current version of Tree Borrows is implemented in the Miri interpreter
- more about stacked borrows
- unsafe-code-guidelines/wip/stacked-borrows.md at master · rust-lang/unsafe-code-guidelines
- Forget Borrow Checkers: C3 Solved Memory Lifetimes With Scopes
- Building Modular Interpreters and Visitors in Rust with Extensible Variants and CGP
- Placing functions
- #asm
- An online searchable reference tool for C intrinsics of all major SIMD engines
- people mentioned more references on HN
- The messy reality of SIMD (vector) functions (on HN)
- Writing a very simple JIT Compiler in about 1000 lines of C
- Writing an IR from Scratch and survive to write a post
- Go Assembly Mutation Testing
- A Bytecode VM for Arithmetic: The Parser
- in Haskell
- Injecting Java from native libraries on Android
- So you want to parse a PDF? (on HN) (on lobste.rs)
- #copyright
- I used to prefer permissive licenses and now favor copyleft
- NetBird Is Embracing the AGPLv3 License (on HN)
- Belgium bans Internet Archive's ‘Open Library’
- Measuring Fair Use: The Four Factors
- Anthropic Agrees to Pay $1.5 Billion to Settle Lawsuit With Book Authors
- On HN
- https://www.washingtonpost.com/technology/2025/09/05/anthropic-book-authors-copyright-settlement/
- An update from the team about Anna’s Archive #copyright
- On HN
- A media company demanded a license fee for an Open Graph image I used (on HN)
- Bypassing Watermark Implementations (on HN)
- tim-janik/imagewmark: Resilient watermarking of digital images
- swesterfeld/audiowmark: Audio Watermarking
- “Tivoization” and your right to install under Copyleft and GPL (2021) (on HN)
- ACM Transitions to Full Open Access (on HN)
- #idea #edu
- Let Kids Be Loud (on HN)
- #sec
- PyPI Phishing Attack: Incident Report
- Multiple vulnerabilities fixed in Git
- CVE-2025-48384: Breaking git with a carriage return and cloning RCE
- #music
- Petrichor – a free, open-source, offline music player for macOS
- a lot of other apps are suggested on HN
- Radium Music Editor
- Xenharmlib: A music theory library that supports non-western harmonic systems
2025-07-09 [2025-07-09]
2025-07-09 [2025-07-09]
- Magic .env files built for sharing: Human-first, AI-friendly - I might wish to use it to render `.env`, where secrects will be managed by `pass` - Passkeys are just passwords that require a password manager - placing password managere related content here for now #pass - Dropbox Passwords discontinuation (on HN) - or better, adopt `varlock run` approach instead of using `just`, `mise`, or `docker-compose` to read from `.env` files, but it's a longer journey - #selfhost - Monitoring my Homelab, Simply - ntfy.sh for paging - Cron Job Monitoring - Healthchecks.io as a dead man’s switch (monitor 20 cron jobs for free) - two dead man switches: 5m & 2h - The Future is NOT Self-Hosted - AWS deleted my 10-year account and all data without warning - Using fs_usage to see what files a process is using - reminds me of `strace` days, added `just trace` tasks as a note - Smollm3: Smol, multilingual, long-context reasoner LLM - I need to keep notes on models I tried in garden - MCP server for searching and downloading documents from Anna's Archive - also as a CLI - requires donation to access the JSON API - Clew - a self-hostable search engine that focus on writing by independent creators - discusses various search techniques in its blog posts - tried, not great search result
2025-07-08 [2025-07-08]
2025-07-08 [2025-07-08]
- #rust
- Understanding Rust’s Memory Model
- #[derive(Clone)] is broken
- Building the Rust compiler with GCC
- rust-lang/rustc_codegen_gcc: libgccjit AOT codegen for rustc
- Testing the GCC-based Rust compiler(backend)
- #clojure
- All Programming Languages are Fast
- 8 Reasons why Clojure is a better Java than Java
- #swift
- Cocoa Basics series
- #go
- Generic interfaces
- What's //go:nosplit for?
- Be Careful with Go Struct Embedding
- #software #idea
- Inverse Triangle Inequality
- #lean
- Lean's new home page: Lean is a theorem prover and programming language that enables correct, maintainable, and formally verified code
- learn about tactic `grind`
- The Lean FRO Year 3 Roadmap — Lean Lang
- My first verified (imperative) program (on HN)
- The Math Is Haunted
- “Bad Apple!!” But It’s 3288 Lean Tactics Spamming VSCode
- #lang
- Flix – A powerful effect-oriented programming language (on HN)
- runs on JVM, interoperable with Java, Kotlin, Scala, etc.
- could be considered a meta-programming language for Datalog
- DIDYOUKNOW.md is informative
- Flix | FAQ is fun
- Pony (on HN)
- open-source, object-oriented, actor-model, capabilities-secure, high-performance
- An Early History of Pony - Pony
- The Q Programming Language
- ssa and asm optimizations
- zero dependencies (no llvm, no libc)
- ultra-fast builds and tiny binaries
- written in Go
- Concurrent Programming with Harmony #formal
- a Python-like open-source programming language for testing and experimenting with concurrent and distributed programs
- Harmony programs are model-checked so that all corner cases are explored
- Carbon Language: An experimental successor to C++
- informative discussions on on HN
- SUS Lang: The SUS Hardware Description Language
- Verilog and VHDL might be good enough per this comment on HN
- Gren 25S: Easier interop, concurrent tasks and zero-install packages #lang
- #lua
- the Fennel programming language
- YueScript
- Lua beats MicroPython for serious embedded devs
- willtobyte/carimbo: A 2D game engine developed in modern C++ using SDL, featuring Lua scripting capabilities and designed for web portability via WebAssembly.
- #model-edit
- Show HN: Unlearning Comparator, a visual tool to compare machine unlearning
- #wasm
- WebAssembly: Yes, but for What?
- AssemblyScript
- A TypeScript-like language for WebAssembly
- When Is WebAssembly Going to Get DOM Support? (on HN)
- #im
- bitchat is a decentralized, peer-to-peer messaging application that operates over Bluetooth Low Energy (BLE) mesh networks
- White Noise – secure and private messenger
- Matrix Is Not Safe for EU Data Privacy
- Addressing fear, uncertainty and doubt thrown at Element and Matrix
- Why not Matrix (2023)
- catgirl - IRC client
- About Convos - The simplest IRC client around
- NINA: Rebuilding the original AIM, AOL Desktop, Yahoo and ICQ platforms (on HN)
- Giving Up on Element & Matrix.org (on HN) (on lobste.rs)
- I'm never going back to Matrix
- XMPP: When a 25-Year-Old Protocol Becomes Strategic Again (on HN)
2025-07-07 [2025-07-07]
2025-07-07 [2025-07-07]
- #ai-safety
- A non-anthropomorphized view of LLMs
- some quotes:
- Alignment and safety for LLMs (should) mean that we should be able to quantify and bound the probability with which certain undesirable sequences are generated
- Human thought is a poorly-understood process, involving enormously many neurons, extremely high-bandwidth input, an extremely complicated cocktail of hormones, constant monitoring of energy levels, and millions of years of harsh selection pressure
- Navigating the dramatic changes of the next few decades while trying to avoid world wars and murderous ideologies is difficult enough without muddying our thinking.
- Our first outage from LLM-written code
- "There were two competing sources of signal here for what token to predict at the critical moment: transcription and local prediction. Transcription said break. Local prediction said continue. Unfortunately for us, local prediction won."
- Prevention: cliboard tools
- a comments on lobste.rs points out
- move across files can be detected by `git --color-moved`
- I prefer `--color-moved=dimmed-zebra` or better, `--color-moved-ws=allow-indentation-change`
- see this tweet
- it's also supported by `delta`
- EU rules ask tech giants to publicly track how, when AI models go off the rails
- "AI companies are moving to user interface innovations to try to grab more unwilling training individuals"
- Hallucination
- AI Hallucination Cases Database
- The Sound of Silence
- LLMs can now identify public figures in images
- Claude always responds as if it is completely face blind
- never identifies or names any humans in the image, nor does it imply that it recognizes the human
- does not mention or allude to details about a person that it could only know if it recognized who the person was
- if told by user who the individual is, can discuss that named individual
- without ever confirming that it is the person in the image, identifying the person in the image, or implying it can use facial features to identify any unique individual
- #agent
- Building personalized micro agents
- agent: has access to tools, decides which tools to use, and in what order, determines when the task is complete
- boils down to 9 LOC
- micro agent: access to a very limited, highly specific set of tools
- less confusion when choosing tools
- works with small, local modelsA
- safe autonomy
- meain/esa: Fastest way to create personalized AI agents
- The era of exploration
- the immense cost of pretraining is effectively paying a massive, upfront “exploration tax.”
- Exploration is deciding what data the learner will see
- World sampling – deciding where to learn, i.e. a particular problem that needs to be solved
- Path sampling – deciding how to gather data inside a world, e.g. random walks, curiosity‑driven policies, tree search, tool-use, etc.
- recent work: curiosity objectives, open-endedness, meta‑exploration
- Prompt Coding: No code edits, only complete rewrites #idea
- When vibe coding, isn't the source code the prompt?
- Adding a feature because ChatGPT incorrectly thinks it exists #idea
- The Architecture Behind Lovable and Bolt
- uses baml to engineer prompts using schemas
- uses Beam, an open-source serverless cloud for sanboxed execution
- made into beam-cloud/lovable-clone
- How I keep up with AI progress
- interesting projects
- Am I online?
- `generate_402` pages could be used for this
- Show HN: NYC Subway Simulator and Route Designer
- Showh HN: Microjax – JAX in two classes and six functions
- tinymcp: Let LLMs control embedded devices via the Model Context Protocol
- Render your Jupyter notebooks in OpenGist
2025-07-06 [2025-07-06]
2025-07-06 [2025-07-06]
#agent #docker #game #news #sec - #env - 'It's too late': David Suzuki says the fight against climate change is lost (on HN) - #sandbox - Basically Everyone Should Be Avoiding Docker (on HN) - What is gVisor? (on HN) (on lobste.rs) - gVisor is an abstraction on top of existing Linux Kernel and acts as a middleman between the container and the Kernel - The system calls are intercepted and handled by the a gVisor component called “Sentry” - gVisor is designed to minimize and restrict the types of system calls the Sentry makes to the host kernel. - Sandboxing and Workload Isolation · The Fly Blog - "The Linux kernel has almost 400 system calls. How many of them do we need to efficiently emulate the rest? gVisor needs less than 20. With those, gVisor implements basically all of Linux in userland. Processes. Devices. Tasks. Address spaces and page tables. Filesystems. TCP/IP; the entire IP network stack, all reimplemented, in Go, backended by native Linux userland." - Container Use for Locally Sandboxed, Background Agents in Zed #agent - #agent - Building a Mac app with Claude code (on HN) - Claude Code Pro Limit? Hack It While You Sleep (on HN) - Optimizing Tool Selection for LLM Workflows with Differentiable Programming #dspy - #os - GrapheneOS: the private and secure mobile OS - from Cops in [Spain] think everyone using a Google Pixel must be a drug dealer - related: GrapheneOS: Why I ditched Google for a privacy-focused Pixel ROM - Mkosi – Build Bespoke OS Images - osbuild/bootc-image-builder: A container for deploying bootable container images. - Debcraft – Easiest way to modify and build Debian packages (on HN) - #game-dev - Two and a Half Years in GameDev (on HN) - List of open source game clones - Adding Planets to Celestia on macOS - Shrinkle – Shrink words, find hidden phrase
2025-07-05 [2025-07-05]
2025-07-05 [2025-07-05]
#agent #jujutsu #neovim #news #os #software #tla - #formal - A supposedly worthwhile contract I'll never do again - "What mattered here wasn’t the weights being moved or the TLA⁺ spec being produced - it was the thinking that writing the TLA⁺ specification required." - expectation of TLA⁺ contract: catch issues early, save training time, and get a formal spec - real value—deep system thinking during writing—vanishes when the expert leaves - the dev team values the 'what do we do in this case' discussions more than the final TLA⁺ specification artifact (risking abandonment) - alternative: adopting Hillel Wayne’s approach: "pair-program TLA⁺ specs with team members" to let them grasp the thinking - HN discussion summarized - success of TLA contracts requires refocusing on knowledge transfer - teaching teams to ask critical questions - embedding the spec in their workflow (via checks or collaboration) - treating the spec as a living document rather than a one-time deliverable - #anti-bot - Anubis Pilot Project Report - June 2025 - it's interesting to see how serious business sees the adoption of Anubis - Anubis now supports non-JS challenges - this changelog is very informative - weight thresholds in policy is flexible - `robots2policy` is convenient if a site has a well-maintained robots.txt - no-JS challenge via metarefresh doesn't seem to battle-ready: "many modern scrapers use headless Google Chrome", "its false positive rate is ascertained" - How Perplexity is Evading Anti-crawling Measures - Robots.txt - Archiveteam #anti-bot - On HN - Iocaine: The deadliest poison known to AI - I was wrong about robots.txt (on HN) - #agent/idea - Everything around LLMs is still magical and wishful thinking - Why your vibe coded app only works in your head - Enough AI copilots, we need AI HUDs (on HN) - Every reason why I hate AI - Riff: LLMs are Software Diamonds - Identify, solve, verify - Operators, Not Users and Programmers - the distinction between "user" and "programmer" is an artifact of our presently barely-programmable and barely-usable computing systems. I would like to use the neutral word "operator" instead. —Stanislav - programming to be easy and simple enough to pick up that people can do it without specialized training in the field, so that they can write situated software - malleable languages - spreadsheets - Every Visual Workflow Tool Is Just Excel for Developers Who Gave Up - WYSIWYG editors - browser devtools - AI promised efficiency. Instead, it's making us work harder - AI tools aren’t just saving us time—they’re shifting where we spend our mental energy. And that shift is exhausting in ways we haven’t fully recognized yet. - No, AI is not Making Engineers 10x as Productive - Lack of intent is what makes reading LLM-generated text exhausting - Eleven Music - AI is still in the uncanny valley, it still has no soul - LLM Inevitabilism - New comment by lsy in "LLM Inevitabilism" - New comment by mg in "LLM Inevitabilism" - Gaslight-driven development - Don't Fall for AI: Reasons for Writers to Reject Slop - AI is killing the web – can anything save it? - from HN - Wiby - Search Engine for the Classic Web - I2P Anonymous Network - Rethinking CLI interfaces for AI - Local LLMs versus offline Wikipedia (on HN) - Terence Tao: A human metaphor for evaluating AI capability (on HN) - Will the Fear of Being Confused for AI Mean That We Will Now Write Differently? (on HN) - The vibe coder's career path is doomed (on HN) - AI coding agents are removing programming language barriers (on HN) (on lobste.rs) - Building better AI tools (on HN) - Stop Pretending LLMs Have Feelings Media's Dangerous AI Anthropomorphism Problem (on HN) - Developing our position on AI (on HN) - GPT might be an information virus (2023) (on HN) - #ai-policy - You Can’t Pay Me To Prompt! - an intereting writeup for (no) AI policy - from his AI Policy, I have quite some ideas about my own AI policy, starting by naming it "LM policy" - You can now disable all AI features in Zed (on HN) - Artificial Intelligence and the Linux Community - Generative AI. "Slop Generators, are unsuitable for use [ ]" (on HN) - #jj - Git experts should try Jujutsu - Jujutsu For Busy Devs - Jujutsu For Busy Devs, Part 2: "How Do I...?" - zerowidth positive lookahead | jj tips and tricks - earlier: zerowidth positive lookahead | What I've learned from jj - rbtools/docs/rbtools/workflows/jujutsu.rst at master · reviewboard/rbtools - Jujutsu Strategies :: Reasonably Polymorphic - Jujutsu + Radicle = ❤️ - dtolnay/dissimilar: Diff library with semantic cleanup, based on Google's diff-match-patch #struct - Sapling: A Scalable, User-Friendly Source Control System - many commands look like `jj`'s - The JJ VCS workshop: A zero-to-hero speedrun (on HN) (on lobste.rs) - #incident - Recent Archive of Our Own outage was caused by integer exhaustion - Why AO3 Was Down (on HN) - GitHub pull requests were down (on HN) - Tell HN: 1.1.1.1 Appears to Be Down - Cloudflare 1.1.1.1 incident postmortem for July 14, 2025 (on HN) (on lobste.rs) - Cloudflare and the infinite sadness of migrations - Ask HN: GCP Outage? - How we discovered, and recovered from, Postgres corruption on the matrix.org homeserver - Starlink is currently experiencing a service outage. Our team is investigating (on HN) - Webflow Down for >31 Hours (on HN) - #agent - bgcmd: let AI interact with any REPL - a nice example of Claude driving `rr` to debug - What I learned building an AI coding agent for a year - Codebuff - #dev - What clever tools/workflows do you use to manage development environments? - mise - Devbox: Portable, Isolated Dev Environments - Fast, Declarative, Reproducible, and Composable Developer Environments - devenv (using Nix) - Why I got rid of all my neovim plugins - Stop using nix-env - #idea - When in doubt, Go for a Walk - its ok to have a normal job - #sec - iris - a neurosymbolic framework that combines LLMs with static analysis for security vulnerability detection - #tech/fun - Useful utilities and toys over DNS - mawkdown, a lightweight, line-oriented(ish) text markup tool implemented in awk
2025-07-04 [2025-07-04]
2025-07-04 [2025-07-04]
#cg #duckdb #gpu #news #os #proof #render #rust #wasm #✍️ - #web - Astro is a return to the fundamentals of the web - Our Fullstack Architecture: Eta, HTMX, and Lit - Eta: a lightweight, fast, and simple embedded JavaScript templating engine - maybe that's all I need for my writings, I don't really need another SSG, just a templating engine - HTMX: allows us to add dynamic behavior directly to our server-rendered HTML - Lit: allows us to create encapsulated, reusable components with their own internal state and logic - Why Semantic HTML Still Matters - Semantic rot wrecks performance - Structure is resilience - Agents are the new users – and they care about structure - Rethinking DOM from first principles (on HN) - A Complete Introduction to Web Components in 2025 - CSS Flexbox: a guide from CSS-tricks - About Wiby - DOM > The DOM has too many ways to do the same thing, none of them nice. > The achilles heel is the DOM's SGML/XML heritage, making everything stringly typed. > ARIA (accessibility) is notable, and only because this was what Semantic HTML was supposed to do and didn't. > There's this feeling that HTML always had paper-envy, and couldn't quite embrace or fully define its hypertext nature, and did not trust its users to follow clear rules. > Nobody really believes in the old gods of progressive enhancement and separating markup from style anymore, not if they make apps. - CSS > Your mental model of CSS should be applying two passes of constraints, first going outside-in, and then inside-out. > To avoid the recursive dependency, you need to isolate the children's contents from the outside, thus making speculative layout trivial. - Canvas that skips DOM > The actual achilles heel of canvas is that you don't have any real access to system fonts, text layout APIs, or UI utilities. - GPU's HTML-like renderer: Layout and UI - Future > Taste matters. Good big systems grow from good small ones, not bad big ones. Maybe if Mozilla hadn't imploded... but alas. - vanilla-extract — Zero-runtime Stylesheets-in-TypeScript. - Understanding SVG Paths - A Friendly Introduction to SVG - Remove these tags from <head> - Client-side epub generation - Bookmarkable by Design: URL-Driven State in HTMX - On designing application UIs for children - most also apply universally - Show, Co-locate and Hint tools - Mistakes should be easy to fix - Simplify, then add delight(ness) - bright colours, sound, tactility, sparkle effects - Maintain visual context when changing state - Postcard is now open source - written in Ruby on Rails - personal site + newsletter - "I no longer expect meaningful revenue from the project. Open-sourcing it feels right. In the age of vibe coding, I think it would be fun to give people a working app they can customize." - How to host web apps on a Mac Mini - Rust and WASM for Form Validation (on HN) - avoid using Webpack and a whole array of Node-related tools in order to use WASM - form validation shows all the crucial aspects to use WASM instead of JS, like wiring up DOM events to Rust functions, and then reacting to those events - used Rocket - Simple, Fast, Type-Safe Web Framework for Rust - might motivate me to write Rust for web - HTML-in-Canvas - Don't animate height - #idea - Setting constraint - goals provide a structured roadmap to success, thriving in controlled, predictable conditions like training for a marathon or preparing for an exam. - however, life rarely follows a straight line. It’s messy, unpredictable, and full of curveballs. - “I must finish this report,” -> “I won’t check email after 6 PM.” - for business: “we won’t hire until we have 100 users” - How to Network as an Introvert - really useful for me to script my reaction ahead of time to be natural - my natural response is abrupt, if any - #data-org -Kepler.gl (on HN) - cool 3D map - powered by deck.gl, a GPU-powered framework for visual exploratory data analysis of large datasets - mountayaapp/insight-editor: Open source geospatial analysis for large-scale data sets with kepler.gl, DuckDB (and charts coming soon). Alternative to CARTO, ArcGIS Online, Foursquare Studio, Felt, Mango GIS, Maptable. - #sec - Nonce CSP bypass using Disk Cache - Opening up ‘Zero-Knowledge Proof’ technology - #game - I AI-coded a tower defense game and documented the whole process (on HN) - Steam has been flooded with games stolen from itch.io - #forth - Tiny Great Languages: MOUSE - #sci - how did the Solar System form? - Solar+storage is so much farther along than you think (on HN) - The most otherworldly, mysterious forms of lightning on Earth (on HN) - Lightning on Earth is sparked by a powerful chain reaction from outer space (on HN) - How to grow almost anything - Scientists shine a laser through a human head (on HN) - New colors without shooting lasers into your eyes - New battery has life so long you may never have to recharge (on HN) - Mammals Evolved into Ant Eaters 12 Times Since Dinosaur Age, Study Finds (on HN) - 'Universal cancer vaccine' trains the immune system to kill any tumor (on HN) - Earth Has Tilted 31.5 Inches. That Shouldn't Happen (on HN) - More Women Than Expected Are Genetically Men (on HN)
2025-07-03 [2025-07-03]
2025-07-03 [2025-07-03]
#cg #ebpf #gpu #news #os #simd #software #sqlite #wasm #web - #rust - Introducing tmux-rs - initially used c2rust, a tool to migrate C code to (unsafe) Rust - didn't keep constant name - lots of casts polluting the code - still requires looking at the origin C code for rewriting - went with manually translating one file at a time - start with linking rust static lib to C - end with linking c to rust via crate `cc` - fixed interesting bugs - summarized C patterns in Rust - nice quote: "You might be asking: why did you rewrite tmux in Rust? And yeah, I don’t really have a good reason. It’s a hobby project. Like gardening, but with more segfaults." - skim-rs/skim: Fuzzy Finder in rust! - The scary and surprisingly deep rabbit hole of Rust's temporaries - #ai-slop - The rise of Whatever - EBAF – eBPF Based Ad Firewall - it's pointed out on HN that - its doc and code are both AI slop - install script adds sudoers rules to allow ebaf executable to be run with no password - allows any ebpf code to be loaded into the kernel without a sudo password - re-resolves all 1k+ domain names every 600 seconds - Poor Man's Back End-as-a-Service (BaaS), Similar to Firebase/Supabase/Pocketbase - possibly useful - #zig - async is back - Zig breaking change – initial Writergate (on HN) - Zig's New Async I/O - Zig's new Writer - WebGPU in zig - bronter/wgpu_native_zig: Zig bindings for wgpu-native - Silverclaw/zig-wgpu-native: Zig bindings for the wgpu-native graphics API - Codeberg.org - KurtWagner/zlinter: An extendable and customisable Zig linter that is integrated from source into your build.zig. - I should integrate it with my zig code - Zig CLI Bible tool for the WEB translation in USFM format - Base64 for compression - assembly used to pass octal escape codes for UTF-8 and expand significantly - GCC 15 now supports base64 encoding of data during compilation, with a new “base64” pseudo-op - The most mysterious bug I solved at work - root cause: copying a hyphen at the end of a text-wrapped line in Microsoft Edge's PDF viewer, you get `0x2` (meaning "start of text") on your clipboard - note that I put most C stuff and low-level technical details under #zig for now - #sec - I scanned all of GitHub's "oops commits" for leaked secrets (on HN) - goHardDrive Leaked Personal Data for Thousands of Customers - Introducing the first alpha of Turso: The next evolution of SQLite - rewritten is Rust, with full compatibility and new features - Antithesis, a continuous reliability platform that autonomously searches for problems in software within a simulated environment, so these problems are deterministic reproducible - #agent - Writing Code Was Never The Bottleneck - agent coding influenced mentoring young, ambitious, but inexperienced interns - WASM Agents: AI agents running in the browser (on HN)
2025-07-02 [2025-07-02]
2025-07-02 [2025-07-02]
#os #sec #web - Code-GUI bidirectional editing via LSP - OpenBao, the community fork of Vault - manage secrets, or encrypted passwords, API keys, and other bits of sensitive information in distributed computing setups - found ansic, crate of the week - a modern, efficient and compile time ansi macro and utilities - #nix - Moving on from Nix - it's a good thing that I have kept my distance from Nix from the start - mostly because I didn't like the syntax, and I don't want to be locked in - Three Years of Nix and NixOS: The Good, the Bad, and the Ugly - You don't have to use Nix to manage your dotfiles - Types of Types: Common to Exotic #lean - Uncloud - tool for deploying and managing containerised applications - "the solution for developers who want the flexibility of self-hosted infrastructure without the operational complexity of Kubernetes" - You MUST listen to RFC 2119 - RFC 2119 establishes language around requirement levels, e.g. terms like “MUST”, “MUST NOT”, “SHOULD”, and “SHOULD NOT” - the author hire a voice actor to read 2119 in the most over the top, passive-aggressive way possible - You should delete tests - Confidence is the point of writing tests - Tests that decrease confidence - flaky tests that fails at random - few changes of code causing lots of changes to tests - tests that takes too long to run and are skipped from time to time - clamp / median / range - I also prefer chained comparison styleA - fun fact: clamp is median
2025-07-01 [2025-07-01]
2025-07-01 [2025-07-01]
#agent #agent/tasking #codegen #compiler #debugger #duckdb #gpu #haskell #json #llvm - #agent - Claude Code now supports hooks (on HN) - Claude Code hooks: user-defined shell commands that execute at various points in Claude Code’s lifecycle. - archgw - preference-based LLM routing - agent routing and hand-off - guardrails - clarify and convert prompts to tools/API calls - observability - Interesting prompts found in vscode-copilot-chat - Stream per agent session - Using Claude Code to build a GitHub Actions workflow - recorded by Descript: Edit Videos & Podcasts Like a Doc | AI Video Editor - Direct your AI co-editor to turn your vision into video - Building a Personal AI Factory - How large are large language models? - Doing My Day Job on Chimera Linux - Chimera is built from scratch using novel tooling, approaches, and userland (FreeBSD + Musl C) - Distrobox creates a container that's tightly integrated with the host (break isolation whenever possible) - #formal - From Python Programmer to Distributed Systems Researcher in 10 Years Without a PhD - Conformance Checking at MongoDB: Testing That Our Code Matches Our TLA+ Specs - use the model-checker to output the entire state graph for the spec. The state space is a DAG, with a finite number of behaviors (paths from an initial state to a final state). There are 30,184 states and 4913 behaviors. Max wrote a Go program to parse the model-checker’s output and write out a C++ unit test for each behavior, 4913 tests in total. - Rapid Prototyping a Safe, Logless Reconfiguration Protocol for MongoDB with TLA+ - #zig - The build cache of Zig - how the cache is structured - what's included in hash to check modification - incremental compilation: working toward cache per top-level declaration - cross compilation: musl, libc, compiler-rt, libunwind etc. are compiled from source and cached - Zprof: Cross-allocator profiler - #anti-bot - Cloudflare: Introducing pay per crawl: enabling content owners to charge AI crawlers for access - Cloudflare Introduces Default Blocking of A.I. Data Scrapers - The web's broken deal with AI companies - My Database Is My Application: Rethinking Webhook Logic with DuckDB and SQL - DuckDB as an in-process SQL engine capable of acting as a programmable substrate for data transformation at runtime - manifold - a Java compiler plugin - use DSL directly and type-safely from Java - SQL, JSON, GraphQL, XML, YAML, CSV, JavaScript - #diagram - OpenFLOW – Quickly make beautiful infrastructure diagrams local to your machine - based on markmanx/isoflow - mmastrac/stylus: Lightweight status page for home infrastructure - architecture and health status - #lang - Reflections on Haskell and Rust - The KDL Document Language - From XML to JSON to CBOR - Concise Binary Object Representation (CBOR)'s evolution optimizes for binary efficiency while maintaining JSON's flexible data model - flexible data model - intentionally builds upon the JSON data model - supporting equivalent types (numbers, strings, arrays, maps, booleans, and null) - adding native support for binary byte strings - extensibility without version negotiation: forward compatibility - schema-free decoding: Self-describing data items, parsable without predefined schemas - for Internet of Things (IoT) and constrained environments - compact code size: minimal code footprint for memory-constrained devices - reasonable message size: and without complex compression - Essential and accidental configuration - bikeshed, a spec preprocessor - Bikeshed-flavored Markdown - related - awesome-standards: A curated list of technical standards - quickly converting djot to html+mathml - djot is a markdown variant - it "fixes a few things that make commonmark's syntax complex and difficult to parse efficiently" - more strict but very reasonable - it can be converted from markdown by pandoc - Markdown Monster - detect markdown parser variants - 10 features of D that I love - I like - in/out contract - parenthesis omission - seen and liked in other language - like zig's `comptime`: an interpreter for the language which allows a very large amount of D code to be ran at compile time - `baz(bar(foo))` can be rewritten as `foo.bar().baz()` - Pluto is a unique dialect of Lua with a focus on general-purpose programming (on HN) - The Chapel Programming Language - GPU programming on NVIDIA and AMD - Onyx Programming Language - inspired from languages like Jai, Odin and Zig - compiles to WebAssembly, run on Wasmer - Helix language - #rust - Exception handling in rustc_codegen_cranelift - introduces "landing pad" style expcetion handling - see also Lele's Memo: Landingpad - unwinding ABI crash course - personality function: language-specific data format during unwinding - the appendix provided a gdb script for reproducing the debugger session - Alternative Blanket Implementations for a Single Rust Trait - It's Types All the Way Down - Rust CLI with Clap (on HN) - #agent/tasking - MrLesk/Backlog.md: Backlog.md - A tool for managing project collaboration between humans and AI Agents in a git ecosystem - Vibe Kanban - Orchestrate AI Coding Agents - VibeTunnel - access terminal from the browser to command agents - #misc - Melbourne man discovers extensive model train network underneath house (on HN) - Feasibility study of a mission to Sedna - Nuclear propulsion and solar sailing - GPEmu: A GPU emulator for rapid, low-cost deep learning prototyping [pdf] (on HN) - Converting a large mathematical software package written in C++ to C++20 modules (on HN)
June, 2025 [2025-06]
June, 2025 [2025-06]
2025-06-30 [2025-06-30]
2025-06-30 [2025-06-30]
#agent #json #lean #news #os - Agile Was Never Your Problem - lean process - minimal structure, shorten feedback loop, allowing changing direction quickly - enough time to write proper tests and refactor without begging - monitoring and alerting built into the work, not bolted on later - developers talk because they’re solving problems together, not because it’s time for standup meeting - flexible timing - roadmaps should not be commitments - feedback loops should not be performance metrics - planning should not become forecasting - #context - Tools: Code Is All You Need - The problem with MCP is that it's not composeable. - Mandelbrot in x86 Assembly by Claude - demonstrates simple usage of container for cross-arch assembly debugging - I would like to add a yard for assmebly in native-land - How to Fix Your Context - covers some attempts to improve MCP tool selection if it can't be avoided - context rot: poisoning, distraction, confusion, clash - solution: quarantine, pruning, offloading - The new skill in AI is not prompting, it's context engineering (on HN) - Taming agentic engineering - Prompts are code, .json/.md files are state - Context Engineering Guide - #sec - Beyond the Hook: A Technical Deep Dive into Modern Phishing Methodologies - amazed by Browser-in-the-Browser - CVE-2025-32463 Vulnerability Advisory: Sudo chroot Elevation of Privilege - NativeJIT: A C++ expression –> x64 JIT (2018) - I'm strongly confused about the use cases without operator overloading, except their own - SQL Noir: Learn SQL by Solving Crimes - fun to play, but the challenge should be using the SQL to output the answer
2025-06-29 [2025-06-29]
2025-06-29 [2025-06-29]
#formal #lean #news #os #sci #sec #sqlite #zig - #struct - Bloom Filters by Example (on HN) - Telescopes Are Tries: A Dependent Type Shellac on SQLite - I should give it a good read to understand both telescope (in the formal world) and tries (as a data structure) - Who needs graph theory anyway? - solving the word segmentation problem using graph theory by modeling it as a longest path problem in a directed acyclic graph (DAG) with dynamic programming - Succinct data structures - People Keep Inventing Prolly Trees - Merkle Tree is one of its variants - properties - searchable - history independence - self-balancing - structural sharing - efficient diffing - efficient mutation - Building Replication-Safe LSM Trees in Postgres - Efficiency of a sparse hash table - Destructive in-order tree traversal - p-fast trie: lexically ordered hash map - #ai-consciousness - A Framework for Recognizing Emergent Consciousness in AI - Attention: The capacity for multi-level focusing. - Meta-reflection: The observation of one's own thinking processes. - Creativity: The generation of genuinely new patterns and insights. - Pragmatics: The maintenance of integrity and goal-setting. - Qualia: The description of qualitative aspects of one's own experience. - The Consciousness Gradient: When Machines Begin to Wonder (on HN) - The Architecture of Awakening - The Global Workspace: awareness emerges when information becomes globally accessible across cognitive processes - Hidden Deliberation: reasoning establishes the curcial foundation for the capacity for extended, self-monitored cognitive processing that any conscious system would need - Recursive Self-Reflection: consciousness emerges from self-referential structures that perceive themselves perceiving - The Threshold - Parallel Processing - Persistent Memory - Continuous Cognitive States - Unified Sensory Processing - Embodied Grounding - In defense of floating point - this is not a valid defense, see these test cases in Zig - Python GIL Removal Reveals Second, Stronger GIL Behind It - 🤦 - Show HN: Octelium – FOSS Alternative to Teleport, Cloudflare, Tailscale, Ngrok - the author tries to accomplish so many things at once, and bad at explaining them - but it still seems interesting and How Octelium Works explains it better - Using the Internet without IPv4 connectivity - Kessler Syndrome - Satellite collisions with space junk can trigger a chain reaction, generating more debris and potentially making parts of near-Earth space unusable - "runaway threshold" has been reached at nearly all altitudes between 520 and 1000 km - from johncarlosbaez's post on mathstodon.xyz
2025-06-28 [2025-06-28]
2025-06-28 [2025-06-28]
#context #datafusion #duckdb #game #git #gpu #news #os #physics #proof - A Newbie's First Contribution to (Rust for) Linux - Raspberry Pi has a fork of kernel - it's possible to write out-of-tree kernel module in Rust - kconfig has great dependency complexity - git gud - fast pace and numerous active forks make patches quickly outdated and dependent branches hard to manage - pick a primary base branch and use `--squash` merges for other branches - keep commits on parallel branches logically independent - with some rebase and rerere config, use `git rebase -i <common base>` to modify the entire history tree - also found aha to turn ANSI colored output into HTML from Beautiful Terminal Output in Markdown - Rust in the Linux kernel: part 2 - #agent - Context engineering - definitions of "agents" collected by Simon Willison - the most precise one I think (from An Introduction to Google’s Approach to AI Agent Security) - AI systems designed to perceive their environment, make decisions, and take autonomous actions to achieve user-defined goals. - most liked by Simon Willison - an LLM wrecking its environment in a loop - mine combining a few - models autonomously acting in its environment, by using tools in a loop - MCP: An (Accidentally) Universal Plugin System - Programming as Theory Building: Why Senior Developers Are More Valuable (on HN) - theory building without a mentor - Architectural Decision Records - ADR template - from An ADR for Use Markdown Architectural Decision Records - anti-patterns of ADRs - objectivity - Fairy Tale (aka Wishful Thinking): A shallow justification is given, for instance only pros but no cons - Sales Pitch: exaggerations and bragging - Free Lunch Coupon (aka Candy Bar): consequences are ignored accidentally or hidden deliberately - Dummy Alternative: made up options to make the preferred option shine and give the impression that multiple alternatives have been evaluated - time - Sprint (aka Rush): only one option is considered; only short-term effects are discussed - Tunnel Vision: only a local, isolated context is considered, e.g. developmental qualities are covered, but the consequences for operations and maintenance - Maze: the discussion derails and centers on details that are not relevant in the given context - record size and content nature - Blueprint or Policy in Disguise: the amount of details provided and/or a rather commanding, authoritative voice - Mega-ADR: too many details are stuffed into ADR - Novel and epic: like blueprint or mega-ADR, but with a writing tone of casual and jovial - magic tricks - non-existing or misleading context - problem-solution mismatch - pseudo-accuracy - Writing a good design document - #ocaml - First thoughts on Rust vs OCaml - pattern matching can't penetrate `Box`, `Arc` etc. - a red flag: `Rc`/`Arc`, sync/async end up requiring different libary, e.g. `im` and `im-rc` - im: immutable data structures for Rust - PureScript - Writing a Game Boy Emulator in OCaml - key design of a emulator - a middle-scale project in OCaml using some of its advanced features - now runs on WASM via `js_of_ocaml`’s WASM support - Learn OCaml - practical ocaml - the background story of OxCaml: Jane Street’s sneaky retention tactic - Identity and behaviour - functional programming naturally separates them - Why I chose OCaml as my primary language #ocaml - Why Lean 4 replaced OCaml as my Primary Language - Type-level programming for safer resource management (in Haskell) - A parser and interpreter for a very small language (in Haskell) - OCaml Programming: Correct and Efficient and Beautiful (on HN) - Words about Arrays and Tables (on HN) (in Haskell) - #formal - Multi-Stage Programming with Splice Variables - an interactive demonstration in TS, the original implemtation is in Agda (examples) - typed meta-programming, to make code generation predictable and safe - provides precise control over the generation process and seamlessly scales to advanced features like code pattern matching and rewriting - the type system automatically tracks variable dependencies, ensuring that generated code is always well-formed, properly scoped, and type-checks correctly - I deleted my second brain - Niklas Luhmann's Zettelkasten Archive - Johnny.Decimal: A system to organise your life - Howm: Write fragmentarily and read collectively - for emacs, but it might be interesting to me for a TUI for forester in Helix? - rule of three - Notes on Epistemic Collapse - Epistemic collapse in science means losing shared reality due to unreliable info sources. - In physics, it's seen in tribalism: string theory tribes dominated despite failures, with research driven by trends over evidence. - Particle theory lacks experimental input, relying on "hot topics" under oligarchs, now facing funding collapse. - This shows how loss of truth-seeking harms scientific progress. - #perf - Linux Performance Analysis in 60 seconds (2015) (on HN) - Announcing Sniffnet v1.4: it’s 2X faster than Wireshark at processing PCAP files - by focusing on extracting only the most relevant fields from the packets’ headers - Avoiding PostgreSQL Pitfalls: The Hidden Cost of Failing Inserts - `ON CONFLICT DO NOTHING` came to rescue - Toys/Lag: Jerk Monitor (on HN) - The Surprising gRPC Client Bottleneck in Low-Latency Networks (on HN) - Run Coverage on Tests - a few subtle case where the test is not run, caught by coverage - on lobste.rs, there is another subtle case where assertions are not run due to `with pytest.raises(ValueError):` - Sirius: A GPU-native SQL engine - plugs into existing databases via the standard Substrait query format, requiring no query rewrites or major system changes - based on - cuDF, a Python GPU DataFrame library (built on the Apache Arrow columnar memory format) for loading, joining, aggregating, filtering, and otherwise manipulating data - substrait, a cross platform way to express data transformation, relational algebra, standardized record expression and plans - supports DuckDB, will support Doris and DataFusion - Structuring Arrays with Algebraic Shapes - Untyped programming invites primitives with excessive flexibility - resorting to dependent types (e.g. Futhark), makes types difficult to check – let alone infer, the programmer is given the burden of proof - a novel calculus, Star, with a type system that provides useful and expressive types, while also admitting type inference - use structural record and variant types for array indices and shapes (algebraic shapes), to reduce the annotation burden on the programmer - in the process of implementing a prototype, including type inference - on lobste.rs, doug-moen points out that it only supports pointful array programming styles instead of point-free style in the industry - SymbolicAI: A neuro-symbolic perspective on LLMs (on HN) - a very interesting DSL to do semantic map lambdas, compare with different contexts for nuanced evaluation, combine facts and rules, and more - LOTUS: A Query Engine For Processing Data with LLMs - Theoretical Analysis of Positional Encodings in Transformer Models (on HN) - ALiBi effectively extrapolates to longer sequences by imposing a monotonic distance bias - Wavelet-based encodings provide strong extrapolation, matching or surpassing ALiBi, due to exponential decay of high-frequency components beyond Nmax - the novel wavelet PE is a promising candidate for transformerbased tasks requiring extrapolation, combining strong theoretical properties with practical performance - ZeQLplus: Terminal SQLite Database Browser (on HN) - written in V - UI might be inspired by Harlequin (in Python, supports more databases) - omarchy: Opinionated Arch/Hyprland Setup - learn about Dark Archive - Researchers develop a battery cathode material that does it all #sci
2025-06-26 [2025-06-26]
2025-06-26 [2025-06-26]
#agent #context #game #idea #news #os #rust #web - #agent - AI Improves at Improving Itself Using an Evolutionary Trick - Learnings from building AI agents - Jan-nano-128k: A 4B Model with a Super-Long Context Window (Still Outperforms 671B [in MCP]) - it's an interesting direction - Magnitude – Open-source AI browser automation framework - news - Build and Host AI-Powered Apps with Claude – No Deployment Needed - MCP in LM Studio - Iroh: A library to establish direct connection between peers - built on QUIC, but use TCP for falling back to relay servers - QUIC for the kernel (on HN) - QUIC is not Quick Enough over Fast Internet : r/programming - microsoft/msquic: Cross-platform, C implementation of the IETF QUIC protocol, exposed to C, C++, C# and Rust. - Notes on type inference and polymorphism - polymorphism is hard to combine with Hindley-Milner type inference - Type Inference Was A Mistake - #rss - RSS Server Side Reader (on HN) (on lobste.rs) - I had the similar idea, but for filtering and merging RSS, particularly for papers - the author didn't even want read/unread state and post content, but they are useful for me - RSS as my default web browser (for some stuff) - the author used a hosted RSS system: FreshRSS (self-hostable) - configure FreshRSS to grab the whole content if excerpt-only - create a pseudo-RSS via "Web scraping feature HTML+XPath for Web pages without any RSS/ATOM feed" - Croissant! Building a No-Framework Web App - informative about how to build a RSS aggregator and how to build no-framework web app - JavaScript Chose Violence - a series of caveats of JavaScript, some are new to me - Games run faster on SteamOS than Windows 11, Ars testing finds - a nice surprise, hopefully, games running on wine are the only legacy of Windows in future - I'm really frustrated by Github Actions Windows CI build failure that has little information to debug
2025-06-25 [2025-06-25]
2025-06-25 [2025-06-25]
#compiler #gpu #llvm #news #os #render #sec #shader #software #vulkan - A new PNG spec - I'm thinking about preserving the most valuable photos in minimal size, encrypted, stored in public repo, and the format might be just png - #ai-safety - #copyright - Anthropic wins a major fair use victory for AI — but it’s still in trouble for stealing books - Against AI: An Open Letter from Writers to Publishers (on HN) - LLM code generation may lead to an erosion of trust - AI Is Dehumanization Technology - Amazon's Emissions Climbed 6% in 2024 on Data Center Buildout (on HN) - #time - Assembly Theory of Time - time is a measurable physical entity, with complex objects' formation paths and "assembly indexes" revealing time's unidirectional depth and causal chains - How to Think About Time in Programming - Managing time when time doesn't exist - #cg - TinyRenderer: Software rendering in 500 lines of bare C++ (code) - Porting GPU shaders to Rust GPU 30x faster with AI - CUDA Ray Tracing 2x Faster Than RTX: My CUDA Ray Tracing Journey - Chili3D: A web-based 3D CAD application for online model design and editing - #rust - Why is the Rust compiler so slow? (on HN) (on lobste.rs) - a lot of useful tools to debug rust compilation process - see also Performance Debugging with LLVM-mca: Simulating the CPU - found LLVM MCA Daemon on HN - Cross-Compiling 10,000+ Rust CLI Crates Statically - How much code does that proc macro generate? - compilation time - Subsecond: A runtime hotpatching engine for Rust hot-reloading - TODO: merge with related work - Weird Expressions in Rust (on HN) (on lobste.rs) - How to Write Compelling Release Announcements
2025-06-24 [2025-06-24]
2025-06-24 [2025-06-24]
#agent #build #news #os #rust #sqlite #web #zig - #build - Bazel’s Original Sins - Chromium's build system is switching from Ninja to Siso for external developers - Build an iOS app on Linux or Windows (on HN) (on lobste.rs) - Uv and Ray: Pain-Free Python Dependencies in Clusters - New comment by acheong08 in "uv: An extremely fast Python package and project manager, written in Rust" - I think I might switch from `asdf` to mise, unfortunately it didn't port asdf zig plugin yet - JeKa : Next-Gen Build Tool for Java & Co. #build #jvm - XSLT – Native, zero-config build system for the Web - Mill: A better build tool for Java, Scala, and Kotlin (on HN) - Interesting Bits of Postgres Grammar - found Geometric Functions and Operators - #tui - fclones - finds and handles duplicate files across directories - tatuin - aggregates TODOs from various sources - alden: detachable terminal sessions without breaking scrollback - only a source tarball - Atuin – Magical Shell History - with zsh autocomplete and just, I thought I didn't need it, but maybe I need it so that history won't be easily lost, they could form a story of what I was experimenting - Can your terminal do emojis? How big? - surprisingly old protocol for this - Everyone should copy Thunderbird's donation model - it asks for donation with low frequency (yearly), and good timing (Chrismas?) - Retrieval Augmented Generation Based on SQLite - I do prefer RAG on SQLite, need to try it out - The Bitter Lesson is coming for Tokenization - but how to part with tokenization? - Phoenix.new is Fly's entry into the prompt-driven app development space - I need to give it and fly.io a try
2025-06-23 [2025-06-23]
2025-06-23 [2025-06-23]
#game #news #os #rust #tla #typst #zig #✍️ - How I use my terminal - the author explains how things work, especially for those that people are surprised to find possible at all - I wrote my PhD Thesis in Typst (on HN) (on lobste.rs) - it's an unusual journey, the author fought through the process by - writing a recursive descent parser in Typst for custom code syntax highlighting - death by a thousand papercuts for bibliography management - writing a tool to convert Typst to LaTeX for submitting paper to LaTeX only journal - the advisors perspective is also informative - Nano-Vllm: lightweight vLLM implementation built from scratch - I would wonder if I could do this in Zig - #lang - Cyber Programming Language - written in Zig - fast, efficient, and concurrent scripting - faster than Wren (written in C & Wren) that are used in game engine - Pallene Language - a statically typed and ahead-of-time compiled sister language to Lua - Announcing the Clippy feature freeze (on HN) (on lobste.rs) - an inspiring way to allow the team to have a period of time for repaying tech debts - learn about Git Notes: Git's coolest, most unloved feature (2022) - found LeetCode for System Design - #go - Go should be more opinionated - Go is an 80/20 language - How to store Go pointers from assembly (on HN) (on lobste.rs) - Why Go Rocks for Building a Lua Interpreter - writing a little gosh
2025-06-22 [2025-06-22]
2025-06-22 [2025-06-22]
#os #rust #yaml - model.yaml - an open standard in YAML for defining crossplatform, composable AI models by LM Studio team - #gpu - Basic facts about GPUs - TPU Deep Dive - #zig - Zig And Rust (2023) - Polystate: Composable Finite State Machines in Zig - comphash - A very lightweight Zig package offering a zero-cost compile-time hash map - Andrew Kelly experimented with perfect hashes - Syntax highlighting for Zig's documentation comments - Parameterized types in C using the new tag compatibility rule - C23 has a new rule for struct, union, and enum compatibility
2025-06-21 [2025-06-21]
2025-06-21 [2025-06-21]
#agent #formal #os #software #web - That Time I Tried Browsing the Web Without CSS - I really should keep my sites readable without JS, and even without CSS - Harper – an open-source alternative to Grammarly - I should give it a try again - AbsenceBench: Language models can't tell what's missing - from "Needle in a Haystack" to the missing needle - found Nxtscape – an open-source agentic browser - found kokke/tiny-regex-c - uses `exrex` to randomly generate test-cases from regex patterns - uses "KLEE Symbolic Execution Engine" for formal verification - We moved from AWS to Hetzner, saved 90%, kept ISO 27001 with Ansible - no specifics except for the use of ansible - #scheme - Why Dylan? - a scheme without parentheses, but with `end` - Why computational reproducibility matters - learn about GNU Guix - configured with Guile, another scheme- Show HN: Inspect and extract files from MSI installers directly in your browser - python-importtime-graph - I didn't know it's even possible
2025-06-20 [2025-06-20]
2025-06-20 [2025-06-20]
#news #os #rust #web - Infinite Mac OS X (on HN) (on lobste.rs) - JavaScript broke the web (and called it progress) (on HN) (on lobste.rs) - Hurl: Run and test HTTP requests with plain text - a KISS way to script curl - #makefile - Learn Makefiles - Makefile Style Guide - Makefile formatter and linter - found Minimal auto-differentiation engine in Rust - found yap - from Apple’s New Foundation Model Speech APIs Outpace Whisper for Transcription - I have to wait for macOS 26 - found How to Design Programs 2nd Ed (2024)
2025-06-19 [2025-06-19]
2025-06-19 [2025-06-19]
#cg #compiler #haskell #news #os #simd #software - How Close to Black Mirror Are We? - #math/app - Curved-Crease Sculpture - Elliptic curves as art (on HN) - Learning to flock in open space by avoiding collisions and staying together - Cracovians: The Twisted Twins of Matrices - Learn you Galois Fields for Great Good - Finding a billion factorials in 60 ms with SIMD (on HN) (on lobste.rs) - Y Combinator (Math) Explained - Entropy of a Mixture (on HN) - Functions Are Vectors (2023) (on HN) - The Rubik's Cube Perfect Scramble (on HN) (on lobste.rs) - Twentyseven 1.0 - a Rubik’s cube solver in Haskell - based on Cube Explorer in Pascal, actually Delphi 6 [source] - johncarlosbaez's post on mathstodon.xyz: when is 0.999... less than 1 - #ai-safety - Moral puzzles: Man vs. machine - Rolling the ladder up behind us (on HN) (on lobste.rs) - All roads lead to disaster - Is there a no-AI audience? (on HN) - thatshubham/no-ai: This repository will be a community-curated list of software and resources that explicitly avoid the integration of artificial intelligence. - unfortunately very short list, didn't include Helix - Zed also support no AI recently - #rust - Rewriting Kafka in Rust Async: Insights and Lessons Learned in Rust - higher: Your favourite Haskell type classes for Rust (2023) - B compiler written in Crust - Crust is a little like Evil Rust but that was for fun and just some clippy rules - uses fasm as backend
2025-06-18 [2025-06-18]
2025-06-18 [2025-06-18]
#agent #benchmark #debugger #docker #news #os #quantum #software #web - #helix - work on helix-cheat-sheet - I really like the Helix editor - Double-Entry Ledgers: The Missing Primitive in Modern Software - I would love to see such an primitive in database design, but I also doubt that if it could be helpful for realworld applications - #agent - Building Effective AI Agents - supposedly the best practice - see also From LLM to AI Agent: What's the Real Journey Behind AI System Development? - LLMs pose an interesting problem for DSL designers - "LLMs pose an interesting problem for the DSL designers – the opportunity cost for using niche languages is now substantially increasing, and so we, as language designers, will be held to a higher standard to justify the use of our DSLs" - I think DSLs would clarify the intent in the domain, and reduce noise in code - even embed DSLs in general programming language would be better than just plain code - there should be a recipe for LLMs to quickly grasp the mindset of a DSL, instead of giving up on DSLs - LLM Agents Are Breaking Your Platform, Not Your Architecture - control the size of the mass introduced by agents - Is there a Half-Life for the Success Rates of AI Agents? (on HN) (on lobste.rs) - Libraries are under-used. LLMs make this problem worse - Building agents using streaming SQL queries - an interesting yet too traditional experiment - Bots are overwhelming websites with their hunger for AI data - Show HN: Trieve CLI – Terminal-based LLM agent loop with search tool for PDFs - GitHub CEO: manual coding remains key despite AI boom - #wayland - Long live Xorg, I mean Xlibre - It's true, “we” don't care about accessibility on Linux (on HN) (on lobste.rs) - Wayland Is Growing Up. and Now We Don't Have a Choice (on HN) (on lobste.rs) - Cosmoe: BeOS Class Library on top of Wayland - The X Window System didn't immediately have X terminals - Two weeks of wayback - Please don't promote Wayland - Wayback 0.1 released - I want to defend Wayland here and explain a crucial piece that I think people are missing - #robot - Real-time action chunking with large models - Swarm robotics could spell the end of the assembly line - Robot metabolism: Toward machines that can grow by consuming other machines (on HN) - #editor - Using Microsoft's New CLI Text Editor on Ubuntu - Publishing a Docker Container for MS Edit to the GitHub Container Registry - The Zed Debugger Is Here (on HN) (on lobste.rs) - Pragtical - The practical and pragmatic code editor - built on SDL, C and Lua, low footprint - forked from lite XL (which is forked from lite) to be more practical rather than minimalist - #sec - How keys are used in FileVault and encryption - VEK (Volume Encryption Key) never leaves Secure Enclave, destroyed on "Erase All Content and Settings (EACAS)" - wrapping: encrypting the VEK using a KEK (Key Encryption Key) - user password can be changed without the contents of the protected volume having to be fully decrypted and encrypted again - possible to generate multiple KEKs to support the use of recovery keys that can be used to unlock the VEK when the user’s password is lost or forgotten - Apple: Prepare your network for quantum-secure encryption in TLS - Blink and you'll miss it — a URL handler surprise - New Linux Flaws Enable Full Root Access via PAM and Udisks Across Major Distributions - Getting ready to issue IP address certificates (on HN) (on lobste.rs) - The Journey of Bypassing Ubuntu's Unprivileged Namespace Restriction (on HN) - Transmitting data via ultrasound without any special equipment () - not security per se, but could be used to breach - uses 18-20kHz (not real ultra sound (~50kHz)) - use WebAudio - on HN and on lobste.rs, people mentioned that IoT use sound to do device paring, not necessarily ultra sound, so users could understand what's going on - Vet – A tool for safely running remote shell scripts - a flawed and naive safeguard, but a call to change status quo - found snapDOM - from Benchmark: snapDOM vs html2canvas
2025-06-17 [2025-06-17]
2025-06-17 [2025-06-17]
#build #context #misc #os #sec #software #tui #web - Accumulation of Cognitive Debt When Using an AI Assistant for Essay Writing Task - now with Helix, I use less of auto-complete, and enjoy genuine programming - #tech-history - The many JavaScript runtimes of the last decade #web #bun - Why JPEGs still rule the web (2024) - Google aims to reinvent email with Wave (2009) - A Brief, Incomplete, and Mostly Wrong History of Robotics - Notes on retries - The Promised LAN - Fun with Telnet - A brief history of web browsers - Emoji Kitchen - Browse Google's unique emoji combinations - macOS Icon History - Who Invented Backpropagation? #tech-history - On HN - MacPaint Art from the Mid-80s Still Looks Great Today (on HN) - Open, free, and ignored: the afterlife of Symbian (on HN) - Ask HN: Any active COBOL devs here? What are you working on? - 20 years of Linux on the Desktop (part 4) (on HN) - #agent - 100% effective - on LLM safety, there is no guarantee - Coding agents require skilled operators - MCP Specification – version 2025-06-18 changes - The Brute Squad - Quick notes on a brief agentic coding experience - TIL:AI. Thoughts on AI - We Should Identify and Mitigate Third-Party Safety Risks in MCP-Powered Agent Systems - Are AI Bots Knocking Cultural Heritage Offline? - Now might be the best time to learn software development (on HN) (on lobste.rs) - Gemini CLI: your open-source AI agent (on HN) (on lobste.rs) - Introducing Qodo Gen CLI: Build and Run Coding Agents Anywhere in the SDLC - #privacy - Why WhatsApp Didn’t Sell Ads - matrix is cooked - Websites are tracking you via browser fingerprinting - Delta Chat is a decentralized and secure messenger app - Google Gemini is about to control your messages and calls, even if you say no (on HN) - The EU wants to decrypt your private data by 2030 - UK drops demand for backdoor into Apple encryption - Wikimedia Foundation Challenges UK Online Safety Act Regulations (on HN) - The UK Is Poised to Ban VPNs (on HN) - Ask HN: How will the OSA affect small Mastodon instances? - EU proposal to scan all private messages gains momentum (on HN) - ChatGPT Chats Were Indexed Then Removed from Search but Still Remain Online - Can you block it? A simple Ad Block Tester - Tell HN: uBlock Origin on Chrome is finally gone - How I found a bypass in Google's big anti-adblock update - Cloudflare Starts Blocking Pirate Sites for UK Users (on HN) - TikTok, AliExpress and WeChat ignore your GDPR rights (on HN) - Valve confirms credit card companies pressured it to delist certain adult games (on HN) - Fully homomorphic encryption and the dawn of a private internet - from HN: > Even without bootstrapping FHE will never be as fast as plaintext computation: the ciphertext is about three orders of magnitude much larger than the plaintext data it encrypts, which means you have to have more memory bandwidth and more compute. You can’t bridge this gap. - Web fingerprinting is worse than I thought (2023) (on HN) - Simon Willison | Official statement from Tea on their data leak - Performance and telemetry analysis of Trae IDE, ByteDance's VSCode fork (on HN) #agent - #news - Rules, Not Renewables, Might Explain the Iberian Blackout - Miscalculation by Spanish power grid operator REE contributed to blackout - found Fossify – A suite of open-source, ad-free apps - found zb: An experiment in hermetic, reproducible build systems - uses lua to specify build rules - found Type Inference Zoo - Intuiting Monty Hall
2025-06-16 [2025-06-16]
2025-06-16 [2025-06-16]
#agent #os #rust - #agent - Agents for the Agent - amp on subagent - Ampcode - First Impressions - Coding agents have crossed a chasm - Snorting the AGI with Claude Code - use claude code with marp to create a slide deck that explains the codebase - The lethal trifecta for AI agents: private data, untrusted content, and external communication - I want to be a Journey Programmer Again - I think I've always been a journey programmer, and didn't know it as a feature - found rgSQL: A test suite to help you build your own database engine
2025-06-15 [2025-06-15]
2025-06-15 [2025-06-15]
#os #physics #raymarching - Q-learning is not yet scalable - found Todo.txt - from todo.txt tasks in my TRMNL - #software - What is systems programming, really? (2018) - What Is Open Source? - learn about free v.s. open source - related - I feel open source has turned into two worlds - found is it really FOSS? - #cg - On Shaping Light - watched Physics and Math of Shading - from SIGGRAPH 2025 Course: Physically Based Shading in Theory and Practice - Remaking Celeste's Lighting - found Foundations of Computer Vision
2025-06-14 [2025-06-14]
2025-06-14 [2025-06-14]
#agent #blogging #compiler #context #formal #game #idea #interop #lean #news - started using Mac's dictation in agent coding - Blogging about papers - Design Patterns for Securing LLM Agents against Prompt Injections (on HN) (on lobste.rs) - "the writing is clear, it’s enjoyable to read and the target audience clearly includes practitioners, not just other researchers" - #cg - Luxe Game Engine in preview now - 2D/3D, cross-platform (including web) - written in c++, scriptable with Wren or any language that can interact with C - optional editor to build worlds, animation, ui etc. - Voronoi, Hashing and OSL - found Open Shading Language (OSL) - was originally developed by Sony Pictures Imageworks for film animation and visual effects - has features such as radiance closures, BSDFs, and deferred ray tracing as first-class concepts - Three Algorithms for YSH Syntax Highlighting - Coarse Parsing with regexes + a context stack could be even more accurate than Context-Free Parsing used by tree-sitter - recognizing most languages with Tree-sitter requires writing C code in an external scanner - found Tattoy: a text-based terminal compositor (on HN) (on lobste.rs) - considerate design for text contrasts: "detect low contrast text and auto adjust the foreground colour within the constraints of your chosen terminal theme to find the nearest colour that meets a minimum contrast threshold" - usage example: terminal minimap, background video, shadertoy shaders - #formalization - found Litex: Scale Formal Reasoning in AI Age - "Traditional proof assistants like Lean4 require learning hundreds of unfamiliar keywords and complex type theories. Litex enables formal verification with just 8 intuitive keywords (forall, exist, not, or, fn, prop, obj, set) and familiar Python/Go-like syntax" - 100 years of Zermelo's axiom of choice: What was the problem with it? (2006) (partially formalized in Agda) - #datalog - Implementing Logic Programming with Prolog and Datlog - Datalog in Rust - #rust - OxCaml, Jane Street's extension of OCaml is now open-source (on HN) (on lobste.rs) - Hypershell: A Type-Level DSL for Shell-Scripting in Rust powered by Context-Generic Programming - Datalog in Minikanren (on HN, many good references about datalog, and scheme) - Bzip2 crate switches from C to 100% Rust - `c2rust`, crate cc, `miri` - `cargo fuzz`, `cargo audit`, `semgrep` (particularly semgrep-rules) - #zig - watched Writing polymorphic code (anytype, comptime interface, tagged union) - found Zimpl (why) - tagged union example with `inline else` - Compiler optimization options - memchr and ripmemchr case study - C2y: Hitting the Ground Running - GCC, glibc, stack unwinding and relocations – A war story - The Art Of Packing Data - #apl - APL Style: Patterns/Anti-patterns - Solving LinkedIn Queens with APL - Klong: A Simple Array Language - Coding in Advent in BQN - apl87 - My Ideal Array Language (on HN) (on lobste.rs) - APL, Mojo, MLIR BQN etc., but no mention of Julia - this comment recommend Astropy and much more - BobMcDear/trap: Autoregressive transformers in APL #lm - Introducing Sulka, the Hardened Yocto Distro - learn about the possibility to maintain a distro by a single person - the Yocto project provides toolkits to create custom Linux distributions, especially for embedded systems - Sulka is a hardened Poky, and there are alternatives like Welma - #ai - To fuel AI, US Congress moves to fast-track nuclear plant approvals - The Emperor's New LLM - Builder.ai did not "fake AI with 700 engineers" - Self-Adapting Language Models - Resa: Transparent Reasoning Models via SAEs - Simulink (Matlab) Copilot - Rethinking Losses for Diffusion Bridge Samplers - #quantum - Quantum Computing without the Linear Algebra - Geometry from Quantum Temporal Correlations - news - Apple's Liquid Glass is prep work for AR interfaces, not just a design refresh - Next.js 15.1+ is unusable outside of Vercel - The European public DNS that makes your Internet safer - general - Feedback Is Not an Attack - Ask HN: How do I give back to people helped me when I was young and had nothing? - "Focus less on those who helped you, and more on helping others." - am i too self-aware? - When random people give money to random other people (2017) - We Live In a Golden Age of Interoperability - No Hello - #biology - Sperm are very different from all other cells - The Ecosystem Dynamics That Can Make or Break an Invasion - When we die do we still have any of the original cells from our birth? - found Modularizing George Cave's eInk Energy Dashboard - could be used to make widgets for various devices - found Radicle Desktop: a graphical user interface for the Radicle peer-to-peer code forge - learn about Radicle, a sovereign code forge built on Git - found Qrkey – Offline private key backup on paper - not sure if it's a good idea security-wise, but neat anyway
2025-06-13 [2025-06-13]
2025-06-13 [2025-06-13]
#benchmark #formal #lean #news #os #rss #rust #tui #z3 #zig - Solving LinkedIn Queens with SMT - in Z3 SMT solver instead of CVC5 SMT solver as in Using SAT to Get the World Record on LinkedIn's Queens - SAT solvers are "criminally underused by the industry" (from Modern SAT solvers: fast, neat and underused) - SMT solvers are "higher-level" than SAT, capable of handling more data types than just boolean variables - It's a lot easier to solve the problem at the SMT level than at the SAT level - people prefer SMT to SAT - Glucose, an SAT solver is really fast - The Hat, the Spectre and SAT Solvers (2024) (on HN) (on lobste.rs) - jemalloc Postmortem - they "reached a sad end for jemalloc in the hands of Facebook/Meta even though most of the people involved were acting in good faith" - "the root of the problem is lack of awareness about external uses and needs" - even "unaware of its replacement until after the fact" - "internally siloed open source projects cannot thrive" - should evaluate alternatives - TCMalloc by Google (with Bazel painpoint) - mimalloc - adopted by CPython 3.12: "it is fast, thread-safe, and NUMA-aware" - StarMalloc: verified memory allocator - phkmalloc - looking for best way to read Hacker News comments - most TUI are not working well for reading comments, see `just prep-hkt` - found Vue HN that supports dark theme, and groups comments, it works pretty well with Doubao auto-translation - found Hacker News RSS and chose the front page feed, and I have already subscribed to the best comments feed - Could an LLM create a full Domain-Specific Language? - rather complete methodology for creating a DSL - code: jcabot/funding-dsl - The last six months in LLMs, illustrated by pelicans on bicycles - an interesting benchmark for LLMs - #ai-safety #env - AI Boom Drives 150% Surge in Indirect Emissions at Major Tech Firms, UN Warns - numbers for the environmental impact of LLMs - related - AI threatens to raid the water reserves of Europe's driest regions - Environmental Impacts of Artificial Intelligence - Mistral reports on the environmental impact of LLMs (on HN) - Simon Willison | Our contribution to a global environmental standard for AI - Problems the AI industry is not addressing adequately - Generative AI’s crippling and widespread failure to induce robust models of the world - Type-based vs Value-based Reflection - value-based (C++26) - "while we have new syntax for getting into (`^^e`) and out of (`[: e :]`) the value domain, once you’re in the value domain — it’s nice to just stay there" - "C++26 reflection does bring with it new syntax and a bunch of new semantics. But the benefit is that a lot of metaprogramming starts to look more like regular programming. There is a lot less syntax in the implementation side of things. " - type-based (Reflection TS published in March, 2020) - wondering the Zig equivalent - Discover C++26’s compile-time reflection - C++26 Reflections adventures and compile-time UML - Reflections on Sudoku, Or the Impossibility of Systematizing Thought - limitation of TDD - tests don't fix the underlying issue of "knowing what to do" - alternative approach by Peter Norvig - analyzing the high-level problem and then breaking down the data structures and outlining the solution in the course of ~20 lines of code - found A Lightweight Merge Queue using GitHub Actions - Rumour: Google intends to discontinue the Android Open Source Project - A tale of two spacetimes - In case of emergency, break glass - skimmed Patterns for Modeling Overlapping Variant Data in Rust - What I talk about when I talk about IRs
2025-06-12 [2025-06-12]
2025-06-12 [2025-06-12]
#cg #compiler #diagram #formal #game #optimization #os #proof #render #rust - wrote Trying Zig's self-hosted x86 backend on Apple Silicon (on reddit) - #lean - Premise Selection for a Lean Hammer - the paper behind LeanHammer - Lean Copilot: Large Language Models as Copilots for Theorem Proving in Lean - Trinity: an autoformalization system for verified superintelligence - Mathesis: Towards Formal Theorem Proving from Natural Languages - watched Mr. Mario Carneiro | Lean Meta-theory: The Proofs behind the Proofs - Rewriting SymCrypt in Rust to modernize Microsoft’s cryptographic library - used Aeneas, a Verification Framework for Rust that supports F*, Coq, HOL4 and Lean - the team also built - Charon to extract information from rustc internals for semantic analysis thus verification - Eurydice, a Rust-to-C compiler to provide a backwards-compatibility story as the verification ecosystem gradually transitions to Rust - used Revizor - a fuzzer to search for microarchitectural leaks in CPUs - analyze binary code for specific compilers and platforms - find side channel vulnerabilities caused by timing leaks or speculative execution - which aren't visible in the source code - for today’s CPUs, every new optimization may open a new side channel, which renders constant-time programming insufficient - found Lightweight Diagramming for Lightweight Formal Methods - formal methods help users define, explore, verify, and diagnose specifications for complex systems incrementally - Forge: A Tool and Language for Teaching Formal Methods - similar to Alloy 6 - uses Sterling visualizer - Cope and Drag (CnD) - embedded in an open-source visualizer for Forge - focuses on encoding the spatial intuitions implicit in communicating the model - constraining spatial layout (such as positioning child nodes below their parents in a binary tree) - grouping elements (like clustering related components in a software architecture) - directing drawing style (for instance, coloring nodes in a red-black tree based on their color) - #debugger - strace tips for better debugging - Demystifying Debuggers (a series) - Linus on Why Debuggers Are Actually Bad For Developers - found Building a Debugger: Write a Native x64 Debugger From Scratch - #raku - Raku's "core" - Raku's FAQ - RakuAST: a foundation for Raku macros - Raku in y minutes - Readings shared June 10, 2025 - realized that Pocoo is behind Sphinx, Jinja, Pygments etc. - found Verse Language, a new scripting language for Fortnite by Epic
2025-06-11 [2025-06-11]
2025-06-11 [2025-06-11]
#agent #os #render #tui #typst #web #zig - My Unfiltered Take on the AI Coding Agent Landscape - found and tried amp - love their Frequently Ignored Feedback but disagree with some of them - it gives me an addictive experience, but it's quite costly and the price model is not very transparent - found YouWare and would love to try more - Zig-style generics are not well-suited for most languages (2022) - Ratatui - Are We Embedded Yet? (#2) - learn about Mousefood, a embedded-graphics backend for Ratatui - found Quarkdown - Markdown with superpowers - interesting but it's a little late to the party now that we have pandoc and quarto - the syntax and scripting looks good - its PDF output is based on rendering web pages, a big no-no for me, as I need LaTeX-level professional typesetting like Typst has - #css - Partial Keyframes - neat CSS animation trick - More Frontend Web Tricks - Color Everything in CSS - Printing the web: making webpages look good on paper - HUG CSS, how I approach CSS architecture - What Does `playsinline` Mean in Web Video? | CSS-Tricks
2025-06-10 [2025-06-10]
2025-06-10 [2025-06-10]
#agent #compiler #diagram #formal #llvm #makefile #news #optimization #rust #sec - Lightweight Diagramming for Lightweight Formal Methods - #perf - Why doesn’t Rust care more about compiler performance? - One Law to Rule All Code Optimizations - Simulating Time With Square-Root Space - Is Rust faster than C? - Revisiting Knuth’s “Premature Optimization” Paper - #os - Asterinas: A Linux ABI-compatible, Rust-based framekernel OS #rust - framekernel: the performance of a monolithic kernel and the security of a microkernel - OSTD, an OS framework, so that a Hello World kernel in 100 lines of safe Rust - TCB (Trusted Computing Base) is the minimal unsafe code required to build a kernel in safe Rust - ~15K LOC, 14- rich OS features - aims to verify unsafe code with Verus - uses model checking with Converos to uncover hard-to-find concurrency bugs - see also Asterinas: a new Linux-compatible kernel project - Blog series on creating an OS in Rust (on HN) #rust - Starina - A modern general-purpose microkernel OS - from Building Linux kernel on macOS natively (on HN) - Clang Built Linux effort helped to build Linux kernel with clang + LLVM instead of GCC + GNU - it seems to work and is simple enough, I should try it sometimes - Munal OS: A graphical experimental OS with WASM sandboxing - written in Rust - embeds wasmi - no virtual address space as userspace is inside WASM sandbox - only VirtIO so it runs only in an VM - has links to OS dev resources - Talos: a container optimized Linux distro, which is declarative, immutable, secure - minimal: consists of only a handful of binaries and shared libraries: just enough to run containerd and a small set of system services - written in Go - no SSH and console access, fully controlled by API via gRPC - Which Kubernetes is the Smallest? Examining Talos Linux, K3s, K0s, and More - Talos has the minimal footprint - The high-level OS challenge - A DOS-like hobby OS written in Rust and x86 assembly - RoureXOS rewritten in Rust - Tilck: A Tiny Linux-Compatible Kernel (on HN) - Makefile.md - Possibly Use(ful|less) Polyglot Synthesis of Makefile and Markdown - comments on Qwen3 embedding models - #prolog - from Readings shared June 9, 2025 - Teaching and learning mathematics with Prolog - Exploring Topological Spaces with Prolog: A Practical Approach Using “Mathematics with Prolog”
2025-06-09 [2025-06-09]
2025-06-09 [2025-06-09]
#agent #datafusion #docker #duckdb #elixir #formal #harbor #idea #json #lemmy - #selfhost - Ditching HAProxy (in my homelab) - found Ran out of infrastructure titles from the author - backrest - for using `restic` to manage backup repos and plans - tested that `restore` and `mount` work, as well as encryption and compression - see also Running Veracrypt in Docker - `--privileged`, `-m=nokernelcrypto`, locale etc. - supports monitoring via Healthchecks if backup jobs don't "check in" - a sec review: restic cryptography - MetalLB, a load-balancer implementation for bare metal Kubernetes clusters - `Talos`, moved to Learning diary › Year 2025 › June, 2025 › 2025-06-10 - Unbound: a powerful validating, recursive, caching DNS resolver - could be used for home network - Salt with its GUI - is similar to Ansible, in the sense you use YAML to specify a state, but has a differening architecture, opting for a master/minion setup rather than Ansible's agentless SSH connections to each node - Apt-Cacher NG for caching apt packages - Harbor for caching container images - Headscale: self-hosted implementation of the Tailscale control server - Pocket ID for authenticate users with their passkeys - #fediverse -Two Approaches to Solving the “Quiet Fediverse” Problem: Conversation Backfilling Mechanisms - The fediverse, explained - Lemmy - Pixelfed - BookWyrm - PeerTube - Pleroma: a lightweight federated social networking server powered by Elixir and PostgreSQL - from What Is Pleroma? - From Fediverse to Creating Personal Digital Space with Memos - Single-user Mastodon Instance is a Bad Idea - jakeg -> notes -> fediverse - ActivityPods: Personal data spaces powered with ActivityPub - tried matrix again and found a good TUI: iamb - Threads is adding Fediverse content to social feeds - wish to test x86 on ARM Mac - due to Zig's self-hosted x86 backend is now default in Debug mode - found Intel-on-ARM and ARM-on-Intel with lima - container: tool for creating and running Linux containers using lightweight virtual machines on a Mac - AI at Amazon: a case study of brittleness - that's how things got stuck in a big org, or at least slowed down enought to suffocate innovation - Decompensation: a service fall over after receiving a spike in external requests, mostly due to hierarchical decision-making - Working at cross-purposes: introduced an almost Darwinian flavor to org dynamics where teams scrambled to get their work done to avoid getting reorged and subsumed into a competing team - Getting stuck in outdated behaviors: had to constantly justify our existence and massage our projects with metrics that could be seen as more customer-facing - Thank You, DataFusion: Queries in Rust, Without the Pain - SQL as a library, not a service - own your storage, your execution model, your schema, your optimizer - offers [SQL] and [Dataframe] APIs, excellent performance, built-in support for CSV, Parquet, JSON, and Avro - paper: Apache Arrow DataFusion: A Fast, Embeddable, Modular Analytic Query Engine - should take a deep look into DuckDB - found Black Hat Zig: Zig for offensive security. - Training a Rust 1.5B Coder LM with Reinforcement Learning (GRPO) | Oxen.ai
2025-06-08 [2025-06-08]
2025-06-08 [2025-06-08]
#agent #news #optimization #os #rust #sec #simd #web #zig - Vanishing zeroes for geometric algebra in Rust - A plan for SIMD - learn about pulp and check its usage in faer - Using Zig to Unit Test a C Application - learn about `[*c]const u8`, `?[*:0]u8`, `.ptr`, `std.mem.span`, `allocator.dupeZ` etc. - Zig: First Impressions - Optimizations with Zig - learn about `align(64)`, `noalias` - Too Many Open Files - A masochist's guide to web development - found Nissy: A Rubik's cube solver and FMC assistant - Field Notes From Shipping Real Code With Claude - great practice for `CLAUDE.md`, AGENTS.md - TODO: I should actually start working on my CONVENTIONS.md - related: - I Read All Of Cloudflare's Claude-Generated Commits - MCP vs API - How I program with Agents - LLMs are cheap - The Gap Through Which We Praise the Machine - Why agents are bad pair programmers - Apple exposes Foundation Models API and... no new Siri - A tale of two Claudes - Agentic Coding Recommendations - The Illusion of Thinking: Understanding the Strengths and Limitations of Reasoning Models via the Lens of Problem Complexity - accuracy progressively declines as problem complexity increases until reaching complete collapse (zero accuracy) beyond a modelspecific complexity threshold - a rebuttal on X has some good discussion - for the puzzle Tower of Hannoi with too many disks, the collapse of accuracy is due to output token limit, and the models won't even try to reason with large number of moves, only explains the overall approach - using solution length as a proxy for task difficulty is flawed, e.g. ToH has a long output but low algorithmic complexity: it’s deterministic with no real branching - the paper's observations (collapse, token underuse, overthinking) still seem to be solid - Seven replies to the viral Apple reasoning paper and why they fall short - Simon Willison’s quotes and comments - Why Claude's Comment Paper Is a Poor Rebuttal - #blogging - Thrive in obscurity - is blogging romantic? - Why Comment Sections suck - re:I want to comment on your blog post - Interactive Guide: Mastering Rate Limiting
2025-06-07 [2025-06-07]
2025-06-07 [2025-06-07]
#git #os #sqlite - Simplifying and Isolating Failure-Inducing Input (Delta Debugging) - found Perses: Syntax-Directed Program Reduction - found WDD: Weighted Delta Debugging - found git-remote-sqlite: Single-file Git repos that can replicate with Litestream
2025-06-06 [2025-06-06]
2025-06-06 [2025-06-06]
#agent #apl #clojure #compiler #dspy #formal #fuzzing #interop #news #optimization - investigating DSPy (Demonstrate-Search-Predict) - Pipelines & Prompt Optimization with DSPy - found MLflow DSPy Flavor - SIMBA (Stochastic Introspective Mini-Batch Ascent) - proceeds in a sequence of mini-batches seeking to make incremental improvements to the prompt instructions or few-shot examples - Advanced Tool Use: using SIMBA to improve a "Multi-Hop Tool Use" agent from 35% accuracy to 60% - in RL for Multi-Hop Research, RL method is compared with SIMBA - Correcting Bias in LLMs with DSPy - Grok has difficulty figuring out the corresponding paper, even with Deep Research - related - found TextGrad (code, notebook) - found Zenbase - found Easy Dataset: Custom Prompts - i.e. I can use extra system prompt to generate Q&A pairs then use them to finetune an LM or optimize via DSPy to answer questions without such prompts - The next phase of jank's C++ interop - found compiler-research/CppInterOp: A Clang-based C++ Interoperability Library - cppyy (code) - jank is C++ (on HN) - Sharing everything I could understand about gradient noise - Small Programs and Languages - APL tutorial - John Carlos Baez on the shape of the Oort cloud - paper: A Spiral Structure in the Inner Oort Cloud - found Jepsen, a framework for distributed systems verification, with fault injection, written in Clojure - Fuzzer Blind Spots (Meet Jepsen!) - Jepsen: TigerBeetle 0.16.11 - The unreasonable effectiveness of fuzzing for porting programs (on HN) (on lobste.rs)
2025-06-06 [2025-06-06-2]
2025-06-06 [2025-06-06-2]
#apl #game #lean #shader #tla #vulkan #web #zig - AI is a gamechanger for TLA+ users - In which I have Opinions about parsing and grammars - Experimenting with no-build Web Applications - Zigar 0.14.1: stream integration and more - The Lean FRO Year 2 Roadmap - found No More Shading Languages: Compiling C++ to Vulkan Shaders - found APLearn: machine learning library - I Think I’m Done Thinking About genAI For Now
2025-06-05 [2025-06-05]
2025-06-05 [2025-06-05]
#agent #compiler #debugger #jujutsu #lean #os #rust #sec #software #tla - Physicality: the new age of UI - love it - Flat design vs realistic (“skeuomorphic”) design - jujutsu on tangled - it's really powerful to edit a changeset to keep commits/PRs clean and focused, no more frustrating rebasing - maybe I'll really start using `jj` - related: Example of Splitting a PR - Why I Think Lean Software Development is Wrong - How Compiler Explorer Works in 2025 - learn about nsjail, a lightweight process isolation tool that’s basically a paranoid security guard for processes - vibe coding - Claude Code is My Computer - Vibe coding case study: ScubaDuck - Deep learning gets the glory, deep fact checking gets ignored - Conformance Checking at MongoDB: Testing That Our Code Matches Our TLA+ Specs | MongoDB Blog - NLWeb: Protocol for AI-Powered Website Search - we really nead a lot of AI-facing protocols, MCP, A2A, NLWeb, `llm.txt` etc. - Tests should not contain logic - Script Debugger Retired, IDE for AppleScript
2025-06-02 [2025-06-02]
2025-06-02 [2025-06-02]
#benchmark #compiler #json #news #os #rust #web #z3 - Fast character classification with z3 - structured error - Designing Error Types in Rust Libraries - Structured errors in Go - Why Use Structured Errors in Rust Applications? - minimalizing Rust - Why am I writing a Rust compiler in C? - How to deal with Rust dependencies - Reducing Cargo target directory size with -Zno-embed-metadata - found benchmark-gui - from I’m Open-Sourcing my Custom Benchmark GUI - The DuckLake Manifesto: SQL as a Lakehouse Format - Progressive JSON - johncarlosbaez's post on mathstodon.xyz about a viXra branch devoted to AI-assisted papers - learning speed solving Rubik's cube, see Resources about Rubik's Cube - Devstral - see also devstral-small-2505-mlx - #aria - What I Wish Someone Told Me When I Was Getting into ARIA (on HN) - Selfish reasons for building accessible UIs - WebAIM: Up and Coming ARIA - learn about aria features and roles, it also has demo
2025-06-01 [2025-06-01]
2025-06-01 [2025-06-01]
#git #lean #neovim #os #sec #tla #zig - Tools built on tree-sitter's concrete syntax trees - found ssr.nvim, Structural search and replace for Neovim, seems more convenient than `ast-grep` - should take a look at - GritQL - srgn - found mergiraf, a syntax-aware git merge driver - reviewed Quint, a modern and executable specification language, as "an updated take on TLA+" - My experience so far with Zig – a Go dev’s journey - found backstage: an experimental implementation of an actor framework: a great example Zig project using libxev - found Zignite: Cross-Platform Graphics Engine - tao's post on mathstodon.xyz - Tao launched a "Lean companion" to his real analysis undergraduate textbook "Analysis I" at teorth/analysis - blog post: A Lean companion to “Analysis I” - Half Spectre, Full Exploit: Hardening Rowhammer Attacks with Half-Spectre Gadgets - ProbeHammer, the first crash-free end-to-end Rowhammer exploit that does not rely on templating or massaging - monitor a controlled victim’s physical memory activity at the cache line granularity - found prose: Serve your blog using SSH - learn 2 new formulas for Rubik's cube, see Test TwistySim and Test Twizzle
May, 2025 [2025-05]
May, 2025 [2025-05]
2025-05-31 [2025-05-31]
2025-05-31 [2025-05-31]
#agent #dspy #lean #os #rust - found C++ to Rust Phrasebook - Simpler backoff - Consider Knitting - Lean-auto: An Interface between Lean 4 and Automated Theorem Provers - found Zipperposition - found Programming Beyond Practices - investigate DSPy - found Agenspy (Agentic DSPy) - found attachments - found Code Generation with AlphaCodium: From Prompt Engineering to Flow Engineering (code) - S*: Test Time Scaling for Code Generation - Advances and Challenges in Foundation Agents: From Brain-Inspired Intelligence to Evolutionary, Collaborative, and Safe Systems
2025-05-30 [2025-05-30]
2025-05-30 [2025-05-30]
#build #formal #rust - found Grog: the mono-repo build tool for the grug-brained dev - then the configuration language Pkl: Configuration that is Programmable, Scalable, and Safe - The Grug Brained Developer (2022) - Rust doesn't actually follow its Golden Rule (when it comes to async functions) - Parse, don’t validate - Names are not type safety (2020) - When was the last time you broke production and how?
2025-05-29 [2025-05-29]
2025-05-29 [2025-05-29]
- Why Your AI Coding Assistant Keeps Doing It Wrong, and How To Fix It - workflows for ai coding - interesting take on human attention span - Compiling a Neural Net to C for a 1,744× speedup
2025-05-28 [2025-05-28]
2025-05-28 [2025-05-28]
#agent #codegen #gpu #os #proof #render #web - WebGPU Fluid Simulations: High Performance & Real-Time Rendering - learn about uzi - from LLM Codegen go Brrr – Parallelization with Git Worktrees and Tmux - A thought on JavaScript "proof of work" anti-scraper systems - What a Difference a Faster Hash Makes
2025-05-27 [2025-05-27]
2025-05-27 [2025-05-27]
- found Effekt Language: Home - The Three Kinds of Money - summarized with doubao, then inspired me to work on mermaid and markmap integration - The two types of open source
2025-05-26 [2025-05-26]
2025-05-26 [2025-05-26]
#bevy #exif #formal #id3 #news #os #physics #racket #rust #software - found F2, a bulk renaming tool that supports metadata such as EXIF, ID3 and more - Idiomatic Rust - Don't Worry About Lifetimes - Don't Unwrap Options: There Are Better Ways - Thinking in Expressions - found DumPy: NumPy except it's OK if you're dum - found einx - einx notation is inspired by einops, but introduces several novel concepts such as `[]`-bracket notation and full composability that allow using it as a universal language for tensor operations - Against Curry-Howard Mysticism - found Reinforcement Learning: An Overview - found Modeling Nonlinear Dynamics from Equations and Data — with Applications to Solids, Fluids, and Controls - found The Ultimate Guide to Fine-Tuning LLMs from Basics to Breakthroughs: An Exhaustive Review of Technologies, Research, Best Practices, Applied Research Challenges and Opportunities - #game - found Pong Wars - maybe it's fun to rewrite it in Zig, or with Bevy, possibly in 3D - Car Physics for Games - Games That Love To Take Things Away From You - hammurabi: A Rust recreation of the classic 1968 BASIC game - I made a font - Someone rewrote my Zig CLI in Rust? Let's compare! - found Transformer Copilot: Learning from The Mistake Log in LLM Fine-tuning - I've long wished for this kind of meaningful learning, instead of just fine-tuning weights according to loss - thoughts on software - Design Pressure: The Invisible Hand That Shapes Your Code - Systematic design of multi-join GROUP BY queries - Reinvent the Wheel - How to Guarantee Your Red Team Will Fail - On File Formats - What Works (and Doesn't) Selling Formal Methods
2025-05-25 [2025-05-25]
2025-05-25 [2025-05-25]
#formal #haskell #lean #ocaml #os #rust #zig - Having your compile-time cake and eating it too - Hindley-Milner (HM), the most popular human-friendly type system, used in Swift, Rust, Scala, Haskell, OCaml etc. - proposed four big features to replace pretty much all Rust macros, including derive ones, while keeping Rust's type system, and achieving (most of) Zig's comptime features - `@` or `@=` - `Abstract` - `TypeInfo` and `Field` - `Code` and `parse` - CAPTCHAs don't work any more for ticket sellers - Concepts vs type traits - tachy0n: The last 0day jailbreak - found Domain Theory Lecture Notes - generate and read the following DeepWiki: - ymndoseijin/zilliam - ShabbirHasan1/unsynn - AstatineAi/ocaml-forester - pygae/galgebra - utensil/forest - use GenSpark to generate Follow-up Research after Formalizing Geometric Algebra in Lean - Does gratitude increase happiness?
2025-05-24 [2025-05-24]
2025-05-24 [2025-05-24]
#agent #apl #cg #compiler #git #haskell #lean #os #rust #software - Anthropic’s ‘System Card’ for Claude 4 (Opus and Sonnet) - particularly fun reading - 4.1.1.1 Continuations of self-exfiltration attempts - 4.1.1.2 Opportunistic blackmail - 4.1.1.3 Self-exfiltration under extreme circumstances - 4.1.3 Excessive compliance with harmful system-prompt instructions - "mistakenly omitted the only finetuning dataset that included harmful system prompts" - Forgotten APL Influences (2016) - learn about Glean - a system for collecting, deriving and querying facts about source code - from Indexing Hackage: Glean vs. hiedb - Pain in the dots - different semantics of two and three dot notation for `git log` and `git diff` - Make Your Phone Grayscale - I've already started the practice, combining it with all-day nightshift mode - The GCC compiler backend can now fully bootstrap the Rust compiler
2025-05-23 [2025-05-23]
2025-05-23 [2025-05-23]
#ocaml #os #rust #tla - Why I love OCaml - How to Get Your Research Paper Accepted - Fork Union: Beyond OpenMP in C++ and Rust? - #lang - Wren, a small, fast, class-based concurrent scripting language - "Think Smalltalk in a Lua-sized package with a dash of Erlang and wrapped up in a familiar, modern syntax." - Talon: Write Raylib programs in Wren - Picat, a rule-based language, in which predicates, functions, and actors are defined with pattern-matching rules - from Finding hard 24 puzzles with planner programming - "the only language that I know has a built-in planner module" - Dark, a serverless backend language - Darklang Goes Open Source - Goodbye Dark Inc. - Hello Darklang Inc - Roto - from Introducing Roto: A Compiled Scripting Language for Rust - Janet #lisp - a more batteries-included Lua, with Lisp/Clojure-inspired syntax - see The smallest embeddable scripting language, part 1 - PEGs in a PEG - JNJ: J iN Janet - Bagatto, a static site generator written in Janet - goal, embeddable scripting array language - lamber, functional scripting language compiling to Lambda Calculus - found many papers, see some HF papers worth skimming
2025-05-22 [2025-05-22]
2025-05-22 [2025-05-22]
#context #formal #idea #os - Adventures in Symbolic Algebra with Model Context Protocol - maybe I should create MCP for GAlgebra - followup: Interfacing MCP with Combinatorial, Convex, and SMT Solvers - Transpiler is a meaningless word (2023) - maybe that means I should give up on the idea that I could build a Forester transpiler - found Obsidian Bases
2025-05-21 [2025-05-21]
2025-05-21 [2025-05-21]
#os #sqlite - If composers were hackers - found Litestream: Revamped, making SQLite apps reliably recoverable from object storage - The Ingredients of a Productive Monorepo
2025-05-20 [2025-05-20]
2025-05-20 [2025-05-20]
#gpu #news #os #web - Not causal chains, but interactions and adaptations - RCA(root cause analysis) model v.s. RE(resilience engineering) model, for incidents - related - The same incident never happens twice, but the patterns recur over and over - Quick takes on the GCP public incident write-up - “What went well” is more than just a pat on the back - Behind the scenes: Redpanda Cloud’s response to the GCP outage (on HN) (on lobste.rs) - Implicit is better than explicit - Open Source Can't Coordinate - Particle Life simulation in browser using WebGPU
2025-05-19 [2025-05-19]
2025-05-19 [2025-05-19]
#agent #docker #lemmy #mastodon #os - Agent Recursion - Semgrep: AutoFixes using LLMs - found a few alternatives to `semgrep`, e.g. ast-grep - Adding Mastodon Comments to your Blog - Mastodon as comment system for your static blog - My blog now has Lemmy comments - learn about Glasp: Highlight the Internet & Build Your AI Clone - async/await versus the Calloop Model - Mimalloc Cigarette: Losing one week of my life catching a memory leak - Ditching Obsidian and building my own - found Qwen3 Technical Report - found TestDesiderata - found macOS VMs in a Docker Container
2025-05-18 [2025-05-18]
2025-05-18 [2025-05-18]
#apl #compiler #game #gpu #os #physics #quantum #shader #zig - found Algorithms by Jeff Erickson (2019) - Comparing parallel functional array languages: Programming and performance[van2025comparing] - learned that APL can run on GPU via Dyalog, the paper even discussed a flash attention implementation - BQN doesn't seem to run on GPU - it might be interesting to use arrayfire C API, even on Mac - prefer tilelang to DaCe - found A JavaScript library for building parsers, interpreters, compilers, and more - Layers All The Way Down: The Untold Story of Shader Compilation - introduces the motivation behind MojoShader, from Direct3D HLSL bytecode or assembly source to other shader languages - found Mystical, a programming language that resembled magical circles - Bare Metal Zig (2023) - Google Scholar is manipulatable - found Path Integrals in Quantum Mechanics, Statistics, Polymer Physics, and Financial Markets by Hagen Kleinert
2025-05-17 [2025-05-17]
2025-05-17 [2025-05-17]
#elixir #game #ocaml #os #rust #software #web #zig - Parallel Scaling Law for Language Models - #lang - The Language That Never Was - Leaving Rust gamedev after 3 years - Mun - jank - The Little Book of Rust Macros - MonoGame - #rust/error - Using unwrap() in Rust is Okay - anyhow for applications and thiserror for libraries - On Error Handling in Rust - error_set, inspired by Zig's error set - snafu - found GNU Parallel Examples - found Lua for Elixir - found OCaml Web Development: Essential Tools and Libraries in 2025 - found Teal: a statically-typed dialect of Lua, a statically-typed dialect of Lua
2025-05-16 [2025-05-16]
2025-05-16 [2025-05-16]
#formal #game #news #os #rust #tla #zig - I don’t like NumPy - Writing a better code with pytorch and einops - Einops and Einsum Summarized - looking for Zig way to implement eiops - Interesting (mis-)use cases for comptime - zig-infix-parser - Zig Comptime is amazing - ZEIN, Zig-based implementation of general-rank tensors - Functional Programming in Zig - What is Zig's Comptime? - comath: comptime math, used by zilliam - alg, Algebra for Zig - mecha, A parser combinator library for Zig - from Zig, Parser Combinators - and Why They're Awesome - parcom, see also this blog post - einops in Rust, with only backend `tch` - Einsums and einops-cpp are in C++ - The current state of TLA⁺ development - found Spectacle and tlafmt - 10 Years of Stable Rust: An Infrastructure Story - formal methods projects built on Rust - Beyond 'Aha!': Toward Systematic Meta-Abilities Alignment in Large Reasoning Models - Declaring a friendship to self - Internet Artifacts - discovered Helicopter game
2025-05-15 [2025-05-15]
2025-05-15 [2025-05-15]
#formal #forth #os #tla #zig - Introducing oniux: Kernel-level Tor isolation for any Linux app - code - found smoltcp - The cryptography behind passkeys - How fast is CeTZ-Plot? - ZJIT has been merged into Ruby - Instead of compiling YARV bytecode directly to the low-level IR (LIR), it uses an high-level SSA-based intermediate representation (HIR) - In the bytecode, which is tersely encoded, jumps are offsets, some control-flow is implicit, and most dataflow is via the stack. - By contrast, HIR looks more like a graph. Jumps have pointers to their targets and there’s no stack: instructions that use data have pointers directly to the instructions that create the data. - found Warteschlangensimulator, a event-driven, stochastic simulator for queueing systems - found kowk, a ~100k-pod k8s cluster simulator - Data is code, about philosophy behind Forth - also What the hell is Forth? - found Insights into DeepSeek-V3: Scaling Challenges and Reflections on Hardware for AI Architectures - found Marigold: Affordable Adaptation of Diffusion-Based Image Generators for Image Analysis - Marigold Computer Vision - Zig App Release and Updates via Github ⚡
2025-05-14 [2025-05-14]
2025-05-14 [2025-05-14]
#agent #ebpf #os #physics #rust #software #tui #web #yaml - try genspark - impressive result - one deep research per day for free - Read the Code, Not the Profile - Dramatic percentages in software is just linear improvement - Writing that changed how I think about PL - Experiment on your code freely with Git worktree - Lock-Free Rust: How to Build a Rollercoaster While It’s on Fire - found - Spall: a code profiler that runs in your browser - TUI for search & replace - scooter: Interactive find and replace in the terminal - serpl: A simple terminal UI for search and replace, ala VS Code. - scooter wins as it supports filtering files, both support regex and replace preview - Avian Physics 0.3 - Makepad 1.0 : Rust UI Framework - checked out YS — YAML Done Wisely - I wish to use it as a template engine, but the scripting syntax is not delicious - Two months in Servo: CSS nesting, Shadow DOM, Clipboard API, and more - Servo is still very actively growing - Misadventures in DTrace: how to debug the macOS kernel - I need to compare more with eBPF and DTrace - found DTrace book
2025-05-12 [2025-05-12]
2025-05-12 [2025-05-12]
#apl #formal #os #proof #rust #sec #tla #web - Are We Serious About Using TLA+ For Statistical Properties? - found FizzBee for behavior correctness verification and performance modelling, based on simulation - I've wished for a tool like this for a long time - see also Modular verification of MongoDB Transactions using TLA+ - Flattening Rust's Learning Curve - The best open source project for someone might not be yours, and that's OK - A review of documentation in the Rust ecosystem - found Blessed.rs: Recommended Crate Directory - Secure by Design: Google’s Perspective on Memory Safety (2024) - Microservices Are a Tax Your Startup Probably Can’t Afford - Private Internet (2024) - A tool to verify estimates, II: a flexible proof assistant
2025-05-09 [2025-05-09]
2025-05-09 [2025-05-09]
#os #rust #zig - Memory Safety Features in Zig - very well summarized, with great examples - Reservoir Sampling - You can use C-Reduce for any language - Rust Dependencies scare Me - a comment reminds me of Build It Yourself - What's in an e-graph? - A catalog of ways to generate SSA
2025-05-08 [2025-05-08]
2025-05-08 [2025-05-08]
#agent #gpu #idea #interop #os #software #web #zig - Why transformers need adam: A hessian perspective[zhang2024transformers] - insightful, and well summarized related work - trying to figure out a way to let AI agent to read all papers citing an paper, and write a summary of the follow-up research - The magic of software; or, what makes a good engineer also makes a good engineering organization - "Engineers are most capable and most effective when abstraction layers serve as shorthand for an understanding of what it is doing on your behalf, rather than a black box" - "start with deep understanding as the basis for innovation – cultivating the curiosity to look inside the black boxes" - "The magic of both software and software organizations comes from those moments where insight into how something works sparks entirely new ideas about what it could become" - related: Reinvent the Wheel - Implement your language twice - Futhark is a statically typed, data-parallel, and purely functional array language with AoT compilation to CUDA, OpenCL, HIP, and WebGPU (WIP) - also Comparing the performance of OpenCL, CUDA, and HIP - Objective-C interop with Zig? - got zig to work inside lima with minimal setup
2025-05-07 [2025-05-07]
2025-05-07 [2025-05-07]
#os #rust #tui #web #zig - Zig’s Low-Level Safety Features Leave Rust in the Dust - Zig defer Patterns - Glossary Web Component - Recreating an iOS Animation with GLSL (interactive tutorial) - found Argo CD - Declarative Continuous Delivery for k8s - found bash/POSIX-compatible shell implemented in Rust - found nnd: A TUI alternative to gdb
2025-05-07 [2025-05-07-2]
2025-05-07 [2025-05-07-2]
#ebpf #os #rust #tui #zig - Zig’s Low-Level Safety Features Leave Rust in the Dust - found Parallel, Concurrent and Distributed Programming in Scala - found nnd: A TUI alternative to gdb - found A part of the fundamental group of an n-dimensional beanA - Building a regex engine in C++ - wondering about chaos engineering in Zig with eBPF #ebpf - learn more about zbpf - maybe it's easiest to use lima to test eBPF - found Pixie when reading Debugging Production: eBPF Chaos - Introducing Minderbinder which is in Go - Implementing fast TCP fingerprinting with eBPF - using Cilium in Go - ebpf series - Unnamed Memories - Introducing TCP-in-UDP solution (eBPF) - Go Allocation Probe (on HN) - KernelScript eBPF-centric programming language (on HN) #lang - OOMProf - Take a heap profile just before OOMkill using eBPF #chaos - found alternative open source front-ends for popular internet platforms
2025-05-06 [2025-05-06]
2025-05-06 [2025-05-06]
#agent #benchmark #blogging #context #formal #game #gpu #news #optimization #os - LM - survey papers - A Survey on Inference Engines for Large Language Models: Perspectives on Optimization and Efficiency - Low-Precision Training of Large Language Models: Methods, Challenges, and Opportunities - sadly, NormalFloat used by QLoRA is excluded from the paper, as it is "specifically designed for pretrained fixed parameters, which only participate in the forward inference stage during training." - improvements on reasoning - Think on your Feet: Adaptive Thinking via Reinforcement Learning for Social Agents - the model is trained to switch between different complexity level of thinking mode based on context for an optimal balance between correct answer and reasoning length - the thinking modes are inspired by Hierarchical Cognitive Control Theory (HCCT) - RM-R1: Reward Modeling as Reasoning - provides good insight into reward modeling and how each training stage boosts the model's performance - other - Unlearning Sensitive Information in Multimodal LLMs: Benchmark and Attack-Defense Evaluation - I'm still interested in unlearning and model editing - Benchmarking Crimes Meet Formal Verification - learn about Systems Benchmarking Crimes - #zig - Implementing a Struct of Arrays - Zig has easy-to-use support of SoA via MultiArrayList - learn about Data-Oriented Design - I can't help but feel that new features of C++ such as reflection is really becoming syntax cancer - Reflecting on a year of Gamedev in Zig - Jai, the game programming contender - bringing data to AI, not the other way around - The Data Surrender Trap: How Enterprises Are Losing Control in the AI Gold Rush—and the Simple Fix - lifestyle - Protect The Habit - skimmed blogging in isolation - skimmed modern-latex: A short guide to LaTeX that avoids legacy cruft - The Beauty Of Having A Pi-hole - own your own DNS - An appeal to Apple from Anukari regarding GPU frequency scaling - I'm amazed that the author is using GPU to simulate physics for realtime audio
2025-05-04 [2025-05-04]
2025-05-04 [2025-05-04]
#git #interop #lean #os - found pyonji, a tool to support sr.ht style e-mail patches - Git: programmatic staging - and learn about `grepdiff`, unfortunately, it's not available on Mac - `git add -p` is also acceptable for a small number of hunks - MathML with Pandoc - Starting on seamless C++ interop in jank - found Anemll: Artificial Neural Engine Machine Learning Library
2025-05-02 [2025-05-02]
2025-05-02 [2025-05-02]
#formal #os #web - DeepSeek-prover-V2: Advancing formal mathematical reasoning via reinforcement learning for subgoal decomposition[ren2025deepseekproverv2] - A survey on post-training of large language models[tie2025survey] - notes on LM could be based on this survey and the following papers related to r1 - 100 days after DeepSeek-R1: A survey on replication studies and more directions for reasoning language models[zhang2025days] - Deepseek-r1: Incentivizing reasoning capability in llms via reinforcement learning[guo2025deepseek] - should revisit - found critics of r1/GRPO - Understanding r1-zero-like training: A critical perspective[liu2025understanding] - Does reinforcement learning really incentivize reasoning capacity in LLMs beyond the base model?[yue2025does] - Kimina-prover preview: Towards large formal reasoning models with reinforcement learning[wang2025kimina] - found A Survey of Interactive Generative Video - Polishing your typography with line height units - Solving Sudoku with Algebraic Geometry and Computer Algebra : A C Programming Approach
April, 2025 [2025-04]
April, 2025 [2025-04]
2025-04-30 [2025-04-30]
2025-04-30 [2025-04-30]
#apl #formal #lean #os #prolog - found Leanabell-prover: Posttraining scaling in formal reasoning[zhang2025leanabell] - skimmed Flow matching guide and code[lipman2024flow] - APL: Comparison with Traditional Mathematics - I use Zip Bombs to Protect my Server - found Prolog Notes - found Quotes on notation design & how it affects thought
2025-04-29 [2025-04-29]
2025-04-29 [2025-04-29]
#agent #os #✍️ - found A Dependently Typed Assembly Language - Qwen3: Think Deeper, Act Faster - found Topologies and Sheaves Appeared as Syntax and Semantics of Natural Language (2012) - reveals connection between sheaf theory and linguistics - found On the expressivity role of LayerNorm in transformers’ attention[brody2023expressivity] [code] - found Grammar prompting for domain-specific language generation with large language models[wang2023grammar] - wrote My setup with 4 screens and 2 Macs
2025-04-28 [2025-04-28]
2025-04-28 [2025-04-28]
#compiler #llvm #os #zig - BitNet v2: Native 4-bit Activations with Hadamard Transformation for 1-bit LLMs - Converting a C API to Zig with the help of comptime - How a Single Line Of Code Could Brick Your iPhone - found Nouveau: The Rule Based Language Family - and easily got into an infinite loop by adding a rule trying to combine a match and a box back to a matchbox - Technical Debt as Theory Building and Practice - Using HAProxy to protect me from scrapers - What if we embraced simulation-driven development? - Notes about ETCD, there are some war stories - Notes about Raft's paper - toycalculator, an MLIR/LLVM compiler experiment.
2025-04-27 [2025-04-27]
2025-04-27 [2025-04-27]
#apl #news #os #web - found APL Cultivations - found Dive into Systems (2020) - found Smallweb – Your Internet Folder - found Cognition's DeepWiki, a free encyclopedia of all GitHub repos
2025-04-26 [2025-04-26]
2025-04-26 [2025-04-26]
#benchmark #compiler #formal - found Mitata - a beautiful benchmarking tool - Nofl: A Precise Immix - O(no) You Didn’t - found PyGraph: Robust Compiler Support for CUDA Graphs in PyTorch
2025-04-25 [2025-04-25]
2025-04-25 [2025-04-25]
#bevy #gpu #idea #news #os #render #sec #software #tla #wasm - Bevy 0.16 - learn about GPU-Driven Rendering and WESL - How I Got Hacked: A Warning about Malicious PoCs - MCP Security: Tool Poisoning Attacks - The ‘trickonometry’ of math olympiad inequalities - intriguing write-up, well collected problems, insightful perspective - found My list of challenging software projects some programmers should try - Towards Vortex 1.0 - a next-generation columnar format with self-describing layouts and WASM decoders that is 200x faster than Parquet for random access, among other goodies
2025-04-24 [2025-04-24]
2025-04-24 [2025-04-24]
#diagram #duckdb #gpu #idea #llvm #optimization #os #tla #wasm #✍️ - Abusing DuckDB-WASM by making SQL draw 3D graphics (Sort Of) - a very cool idea - I should learn more about modern databases - found Bluefish - a JS diagram library with quite some potential - some teaser examples were added by this commit - Exploiting undefined behavior in c/c++ programs for optimization: A study on the performance impact[popescu2025exploiting] - so there are actually many performance-wise well defined UBs in LLVM - GPU Compilation with MLIR - found MLIR Python Bindings - skimmed Some possible roles for AI of Grothendieck topos theory by Laurent Lafforgue (2022) - made a start on improving PDF organization in and out of MarginNote - looked for ways to manipulate iCloud files programatically - noticed that `rclone` supports iCloud too - but `~/Library/Mobile Documents/com~apple~CloudDocs` already works well for my purpose
2025-04-23 [2025-04-23]
2025-04-23 [2025-04-23]
#elixir #os #rust #zig - Nine Reasons to Use OSH - it contains a POSIX-compatible shell `osh`, and an incompatible shell `ysh` - it's written in a subset of Python, then transpiled to C++ by mycpp that is based on MyPy, an interesting approach - found codapi which supports sandboxes for Rust, Zig, Elixir etc.
2025-04-22 [2025-04-22]
2025-04-22 [2025-04-22]
- Make Your Own Internet Presence with NetBSD and a 1 euro VPS – Part 1: Your Blog - which uses BSSG, a simple static site generator written in Bash - will settle on UTM for Mac/BSD virtualization, and Lima for Linux virtualization - still haven't figure out how to virtualize/emulate NetBSD with UTM, see this issue - My Dev Workflow: 2025 - found and started using Loop
2025-04-21 [2025-04-21]
2025-04-21 [2025-04-21]
#context #elixir #idea #os #render #rust #web #z3 #zig - wish to learn more about other architectures of LMs, e.g. - BitNet b1. 58 2B4T technical report[ma2025bitnet] - d1: Scaling reasoning in diffusion large language models via reinforcement learning[zhao2025d1] - M1: Towards scalable test-time compute with mamba reasoning models[wang2025m1] - RWKV7-G1 "GooseOne" reasoning model, see Rwkv-7 "goose" with expressive dynamic state evolution[peng2025rwkv] - ModernBERT, see Smarter, better, faster, longer: A modern bidirectional encoder for fast, memory efficient, and long context finetuning and inference[warner2024smarter] - The State of Reinforcement Learning for LLM Reasoning: Understanding GRPO and New Insights from Reasoning Model Papers - Lorenz and modular flows: a visual introduction which is "deep, beautiful and with a taste of singularity and knot theory" - found Ultra Fractal 6 and POV-Ray - found less_slow.cpp: Playing Around Less Slow Coding Practices for C++, CUDA, and Assembly Code - found Common Expression Language - How I use Kate Editor - watched Implicit Surfaces (using interval arithmetic to evaluate SDFs) - PDF Slides - the ideas behind Fidget and Massively parallel rendering of complex closed-form implicit surfaces[keeter2020massively] well explained, GOAT-level inspiring - should be further explored in Notes on ray-marching implicit surfaces - there are also many interesting writeups in The Prospero Challenge - Things Zig comptime Won't Do - #gleam - Gleam that has a Rust-like syntax, runs on Erlang VM, and supports compiling to JavaScript - My First Impressions of Gleam - Gleam for Elixir users - Lustre - a web framework in Gleam - note more about Taiji and practice more
2025-04-19 [2025-04-19]
2025-04-19 [2025-04-19]
#elixir #formal #os - Common shell script mistakes - Four Years of Jai - My journey from Ruby to Elixir: lessons learned - Revisiting an early critique of formal verification
2025-04-18 [2025-04-18]
2025-04-18 [2025-04-18]
#gpu #os #zig - found Matrix Calculus for Machine Learning and Beyond - Reflections on Unikernels - found OSv - revisit Seastar, a C++ server framework that uses a shared-nothing model - Stop Writing `__init__` Methods - for potential gotchas, read also Python dataclasses, a package full of surprises - Weird / irritating build issue with raylib - so I should also start using the new hash format - Zig and GPUs
2025-04-17 [2025-04-17]
2025-04-17 [2025-04-17]
#agent #news #os #rust #sec #tui #zig #✍️ - found A practical hacker's guide to the C programming language - An Intro to DeepSeek's Distributed File System - my takeaway: DeepSeek's 3FS sacrifices small-file performance, POSIX compatibility, and fault tolerance (single-master risk) to maximize large-file throughput via CRAQ-based chain replication and RDMA-optimized chunk writes on 512B-sector SSDs - Development On Apple Silicon with UTM - cloud-init - Windows ARM64 Download | MAS #win - TLS Certificate Lifetimes Will Officially Reduce to 47 Days - found Torque – A lightweight meta-assembler for any processor - found Unsure Calculator - Zigistry about to reach 300 stars on GitHub ⭐️ - [AINews] OpenAI o3, o4-mini, and Codex CLI - and particularly codex: Lightweight coding agent that runs in your terminal - the lifecycle of a pull request and tried to login to https://tangled.sh/ - learned about `std::autodiff` in Rust via `Enzyme` - converted some of my playlist to Youtube Music and scrobble them to libre.fm - found also cmus, a TUI music player that plays from local files, and supports scrobbling - wrote some more Taiji notes
2025-04-16 [2025-04-16]
2025-04-16 [2025-04-16]
#dspy #tla #tui #web #webgl #zig - A flowing WebGL gradient, deconstructed - found An Introduction to Modern CMake - JSX Over The Wire - found ax, DSPy in TypeScript - looked for HEIC libraries in C that can be used in Zig - found WebTUI - found Terminal Trove, a collection of terminal-based applications
2025-04-15 [2025-04-15]
2025-04-15 [2025-04-15]
#compiler #optimization #os #render #rust - A 2025 Survey of Rust GUI Libraries - Algebraic Semantics for Machine Knitting - further reading: - Semantics and scheduling for machine knitting compilers[lin2023semantics] - C++20 idioms for parameter packs - skimmed Flat origami is turing complete[hull2023flat] - Pretty State Machine Patterns in Rust - Implementing GRPO - found Networking Research Resources - found TeX.social: a feed aggregator for LaTeX-related sites, especially blogs. - A 2025 Survey of Rust GUI Libraries - learn about AerynOS - Algebraic Semantics for Machine Knitting - C++20 idioms for parameter packs - Flat origami is Turing complete - Frontier AI Models Still Fail at Basic Physical Tasks: A Manufacturing Case Study - Procedural Foliage Rendering with L-systems and Geometry Instancing - What the Hell Is a Target Triple? - try converting some playlist to Spotify with TuneMyMusic - screenshot, VLM OCR, then text to playlist - Spotify doesn't always have the songs, even if manual search, e.g. some songs before 2017 - thinking about Graph RAG, and found HelixDB, a graph-vector database
2025-04-14 [2025-04-14]
2025-04-14 [2025-04-14]
#rust #visualization - A Visual Journey Through Async Rust - and it would be insteresting to see the visualization for `monoio` - Solving One Million Sudoku Puzzles per hour in Swift
2025-04-13 [2025-04-13]
2025-04-13 [2025-04-13]
#compiler #ebpf #elixir #lean #tui #zig - looking for Zig libraries for TUI, `io_uring`, eBPF, scripting, e-graph - the candidates are `libvaxis`, `libxev`, `zbpf`, `Cyber`, `zegg`, respectively - found Juniper CAS, which is exactly my original dream for lean-ga - found Beaver: MLIR Toolkit in Elixir and Zig. - one relevant application is Manx - Building a high-performance database buffer pool in Zig using io_uring's new fixed-buffer mode - How io_uring and eBPF Will Revolutionize Programming in Linux - found Performance Analysis and Tuning on Modern CPUs
2025-04-12 [2025-04-12]
2025-04-12 [2025-04-12]
#cg #compiler #elixir #gpu #rust #shader #software #tla - Bootstrapping Understanding: An Introduction to Reverse Engineering - Bug in Outlook PST Password Protection (2006) - Erlang’s not about lightweight processes and message passing… - further reading: Making reliable distributed systems in the presence of software errors[armstrong2003making] - found Rust to C compiler - 95.9% test pass rate, odd platforms - Shadertoys ported to Rust GPU - Build a Static Site in Elixir Under 5 Minutes with Phoenix Components while looking for SSG in Elixir
2025-04-09 [2025-04-09]
2025-04-09 [2025-04-09]
#elixir #os #rust - Archiving URLs - maybe I should use tools like ArchiveBox to prevent link rot - Mistakes and cool things to do with arena allocators - found shorty: a C++ library for concise lambdas - Parser Combinators Beat Regexes - found facet: Rust reflection, serialization, deserialization — know the shape of your types - thus found unsynn: a minimalist rust parser library - $handle_undefined_function in Elixir/Erlang - found Twee, an equational theorem prover again - from Automated Equational Reasoning with Twee Pt 1.
2025-04-08 [2025-04-08]
2025-04-08 [2025-04-08]
#compiler #neovim #os #render #rust - Beautiful CI for Bazel - found Real-Time Rendering Resources - The Gamma Knife model of incidents (2019) - Thinking like a compiler: places and values in Rust - Writing good comments: the why, not the how (2020) - My neovim markdown setup in 2025
2025-04-07 [2025-04-07]
2025-04-07 [2025-04-07]
#✍️ - Model error - wrote 4 bugs caught me off guard recently
2025-04-05 [2025-04-05]
2025-04-05 [2025-04-05]
#os #rust - Atproto Ethos - BPF From Scratch In Rust - Pitfalls of Safe Rust
2025-04-04 [2025-04-04]
2025-04-04 [2025-04-04]
#lean #news #os #rust #simd #web - Of manners and machines - Rewriting my site in vanilla web - TAC: A new CSS methodology - Blinded By the Light DOM - maybe I should rewrite most of my customizations to forest markup as web components - Vector Sets are part of Redis - Towards fearless SIMD, 7 years later - Introduction to Monoio: A High-Performance Rust Runtime - found Public mdBooks
2025-04-03 [2025-04-03]
2025-04-03 [2025-04-03]
#biology #lean #rust #tui #web - learn about geonum, a ridiculously fast Rust library that supports many GA operations except for geometric product - some portions of On the Biology of a Large Language Model - it's a particularly inspiring article on the interpretability of LLMs - it's authored with Distill Template, see guide - similarly, found World Models - A Year of Rust in ClickHouse - AI ambivalence - Minimal CSS-only blurry image placeholders - found chawan: TUI Web Browser
2025-04-02 [2025-04-02]
2025-04-02 [2025-04-02]
#formal #os #sec #web - Stop syncing everything, which launches Graft, an open-source transactional storage engine optimized for lazy, partial, and strongly consistent replication—perfect for edge, offline-first, and distributed applications. - The Most Amusing Security Flaws I've Discovered - Foundation Models and Unix - Goodbye Offpunk, Welcome XKCDpunk - Hello Quarto: Porting my Website from Hugo Apéro - found Interaction nets - Programming with an AI copilot: My perspective as a senior dev - found Testing Distributed Systems - found - Mathematical theory of deep learning[petersen2024mathematical] - Beyond limited data: Self-play LLM theorem provers with iterative conjecturing and proving[dong2025beyond] - Dapo: An open-source llm reinforcement learning system at scale[yu2025dapo]
March, 2025 [2025-03]
March, 2025 [2025-03]
2025-03-31 [2025-03-31]
2025-03-31 [2025-03-31]
#os #rust - There is no Vibe Engineering - found Koto Programming Language, it's not so DSL-friendly like Rhai, but a reasonably good script language embeddable in Rust - Thoughts on ECS - Expressing Japanese Grammar Through TypeScript Type System - I really wanted this for French, except for not in TypeScript, but something Rust-like
2025-03-30 [2025-03-30]
2025-03-30 [2025-03-30]
#agent #idea - work on exporting Discord chat and feeding them to RAG, the result is not quite ideal - try DeepSeek-v3-0324, but still not as good as Claude 3.5 for my use cases - re-evaluate marimo as an alternative to testing with Jupyter notebooks - but it doesn' store outputs, and the candidate testing solution is not elegant
2025-03-28 [2025-03-28]
2025-03-28 [2025-03-28]
#os #rust #✍️ - found - Learning theory from first principles[bach2024learning] - Winding numbers on discrete surfaces[feng2023winding], and read the blog post - Simulating time with square-root space[williams2025simulating] - found Xee: A Modern XPath and XSLT Engine in Rust which could be used to process Forester XMLs in the future - found The Mean-ing of Loss Functions - wrote Fragmented learning, no more
2025-03-27 [2025-03-27]
2025-03-27 [2025-03-27]
#elixir #news #os #rust #zig - learn more about Elixir - Running ML models in Elixir using Pythonx - Embedded Zig with Elixir, Mandelbrot set - Rustler Precompilation guide - learn about axon and the Numerical Elixir (Nx) ecosystem - Why MCP Won
2025-03-24 [2025-03-24]
2025-03-24 [2025-03-24]
#os - slowly picking up open-source work, after fragmented learning due to the DeepSeek hype - found PeanoScript, TypeScript but a theorem prover - attention is logarithmic, actually - The willing kingdon clifford algebra library[roelfs2025willing], the Kingdon paper
2025-03-18 [2025-03-18]
2025-03-18 [2025-03-18]
#ocaml #os #racket #tui - found Rhombus, a Racket without parenthesis - Writing a SIGGRAPH paper (for fun) (2020) - The 70% problem: Hard truths about AI-assisted coding - learn about owi: Cross-language Bugfinder - found Reinforcement learning: An overview[murphy2024reinforcement], some ML books by the same author are on Github - found Intuitive topology[prasolov1995intuitive]
2025-03-13 [2025-03-13]
2025-03-13 [2025-03-13]
- learn about Minimal algorithms for lipschitz monoids and vahlen monoids[helmstetter2013minimal], a paper about determining whether a multivector is a versor, as versors are invertible lipschitzian elements, related to galgebra#533
2025-03-11 [2025-03-11]
2025-03-11 [2025-03-11]
#agent #category #lean #os #proof #quantum #sec - found - Math - Category Theory Illustrated - Introduction to gauge theory[haydys2024introduction] - A gentle introduction to categorical logic and type theory[schmid2025gentle] - A lean and mean introduction to modern general relativity[hayman2024lean] - Knot theory[fushida2020knot] - Introduction to representation theory[etingof2024introduction] - A first course in topos quantum theory[flori2013first] - PLP - An Introduction to Mathematical Proof [source] - ML - Demystifying Diffusion Models - Deepseek-r1: Incentivizing reasoning capability in llms via reinforcement learning[guo2025deepseek] - Camel: Communicative agents for" mind" exploration of large language model society[li2023camel] for Owl
2025-03-07 [2025-03-07]
2025-03-07 [2025-03-07]
#rust #zig - found some readings for Rust and Zig, see native-land commits
February, 2025 [2025-02]
February, 2025 [2025-02]
2025-02-27 [2025-02-27]
2025-02-27 [2025-02-27]
#raymarching #rss - Raymarching The Gunk
2025-02-26 [2025-02-26]
2025-02-26 [2025-02-26]
#agent #codegen #news #proof #typst #z3 - Uncensor any LLM with abliteration - All the Transformer Math You Need to Know - [AINews] Claude 3.7 Sonnet - learn about Typst 0.13 is out now: Experimental HTML export, semantic paragraphs, and more - Where are all the Rewrite Rules?, using Knuckledragger, a down to earth, highly automated interactive proof assistant in Python, based on Z3 - My LLM codegen workflow atm - found The FFmpeg School of Assembly Language - Serving local LLMs with MLX - Enough with all the Raft
January, 2025 [2025-01]
January, 2025 [2025-01]
2025-01-23 [2025-01-23]
2025-01-23 [2025-01-23]
#news #typst #✍️
- busy with Spring Festival
- WeRead books and wrote some reviews
- casual readings are starred in NetNewsWire
- learn stuff related to DeepSeek and MLX
- set up my new Mac Mini with M4 Pro, Logi MX Keys, MX Master 3, and 4 screen working environment
- organize my Chinese ancient poetry collection (in LaTeX, wishing to port to Typst in the future)
2025-01-11 [2025-01-11]
2025-01-11 [2025-01-11]
#os #physics #quantum #render #rust #zig - articles on lobste.rs - Elementary Water Rendering - Prototyping in Rust - Go is a Well-Designed Language, Actually v.s. Why Go Should Sometimes Be a No-Go - Zig's Comptime is Bonkers Good - Not every user owns an iPhone - First Contentful Paint (FCP) - Time To Interactive (TTI) - Interaction to Next Paint - The Most Elegant Configuration Language - found Lectures on topos quantum theory[flori2012topos] - Applications of topos theory to quantum physics[bielas2023applications] can provide some motivation and applications - gutta cavat lapidem non vi, sed saepe cadendo - wish to write more serious Zig in new year, found Mach - found *Histoire de la philosophie* by Émile Bréhier
2025-01-01 [2025-01-01]
2025-01-01 [2025-01-01]
- 📦 move to new office and get used to everything - 🗓️ making plans for the new year
Year 2024 [2024]
Year 2024 [2024]
December, 2024 [2024-12]
December, 2024 [2024-12]
2024-12-30 [2024-12-30]
2024-12-30 [2024-12-30]
#gpu #lean #rust - Fish 4.0: The Fish Of Theseus, it's about Fish team porting Fish from C++ to Rust - found cargo-gpu - A letter to open-source maintainers - I hope to make a release for both GAlgebra and lean4_jupyter before or around the end of the year - Dotfile Management using Stow - previously I was reluctant to use stow as it's written in Perl - maybe I'll also try `brew bundle` too
2024-12-27 [2024-12-27]
2024-12-27 [2024-12-27]
#rust #zig - When Zig is safer and faster than Rust - and How to Actually Write C - PKMs: Less Management, More Knowledge - found capacities and hoarder - Gu Shi's *Möbius Continuum* and write a review on Weread
2024-12-13 [2024-12-13]
2024-12-13 [2024-12-13]
- recieved pygae/galgebra#529 about Shirokov inverse, read On computing the determinant, other characteristic polynomial coefficients, and inverse in clifford algebras of arbitrary dimension[shirokov2021computing]
2024-12-17 [2024-12-17]
2024-12-17 [2024-12-17]
#os - 🎿🪂 - reading Wang Guowei's philosophical works - Ghostty Is Native—So What?
2024-12-15 [2024-12-15]
2024-12-15 [2024-12-15]
#news #os #proof #rust #✍️ - My Ph.D. advisor rewrote himself in bash, and learn about how weasel words, passive voice, and lexical illusions can make technical writing less precise, clear, and convey a lack of proofreading - Playground Wisdom: Threads Beat Async/Await, and learn that in imperative programming, structured concurrency might be better than async/await, we don't always need to introduce functional programming concepts - From where I left by antirez, the author of Redis, and learn that he likes the new license, and he does more work but better work by using AI to proofread and help testing the work instead of replace what he does better - Fermat’s Last Theorem — how it’s going, and enjoy the story of finding the right work for fixing a fixable proof - Dude, where's my main? and learn that executables can be position-independent just like libraries, and wonder if I can implement chaos engineering in Rust to learn more about low-level system design - post-mortems for massive IT outage in recent years, and wish to keep a track of inspiring ones of them - learn about git-backdate, which can help me date unpushed commits better
2024-12-12 [2024-12-12]
2024-12-12 [2024-12-12]
#agent #proof #software - How wide is a proof? - found Notes on Geometric Algebra - skimmed Agents in software engineering: Survey, landscape, and vision[wang2024agents] and related papers
2024-12-09 [2024-12-09]
2024-12-09 [2024-12-09]
- 🚧 busy - reading 📘*Zen and the Art of Motorcycle Maintenance: An Inquiry into Values*
2024-12-01 [2024-12-01]
2024-12-01 [2024-12-01]
#git #os #render #rust - try Deepseek Deep Think, add deep think of Deepseek - rethinking self-hosted git repos, CI, and pages, found - Forgejo - GitHub Pages App on Cloudron - try using aider to write Rust script, not so good - based on an AoC Rust script example - try QwQ - try copilot-more, maybe settle on it - Clifford algebra or Lie algebra? - learn a bit more about Slang, V, and Lobster - watch Really amazing talk by Tomasz Stachowiak: Rendering Tiny Glades With Entirely Too Much Ray Marching - The Door ProblemA from awesome-falsehood
November, 2024 [2024-11]
November, 2024 [2024-11]
2024-11-29 [2024-11-29]
2024-11-29 [2024-11-29]
#gpu #rust - Optimizing a Rust GPU matmul kernel
2024-11-28 [2024-11-28]
2024-11-28 [2024-11-28]
#idea #quantum - found - Knots inside fractals[broden2024knots] - Mathematical ideas and notions of quantum field theory[etingof2024mathematical] - Applied Linear Algebra and Differential Equations - Lecture notes for MATH 2350 by Jeffrey R. Chasnov - Competitive Programmer's Handbook
2024-11-27 [2024-11-27]
2024-11-27 [2024-11-27]
#haskell - Haskell: A Great Procedural Language
2024-11-23 [2024-11-23]
2024-11-23 [2024-11-23]
- 🚧 busy
2024-11-22 [2024-11-22]
2024-11-22 [2024-11-22]
#os #shader - found Slang - Exploring Async Runtimes by Building our Own - found The dirac equation in general relativity, a guide for calculations[collas2018dirac]
2024-11-21 [2024-11-21]
2024-11-21 [2024-11-21]
#compiler #vulkan - found Impala - skimmed - AnyDSL: A partial evaluation framework for programming high-performance libraries[leissa2018anydsl] - RaTrace: Simple and efficient abstractions for BVH ray traversal algorithms[perard2017ratrace] - related: - shady - Vulkan Clang Compiler
2024-11-12 [2024-11-12]
2024-11-12 [2024-11-12]
#citation #lean #os #rust #✍️ - experiments on using aider for LLM assisted project-level pair programming - this PR is a most extensive one - finish citation trace for GAlgebra, see this PR for relevant readings - found Towards a categorical foundation of deep learning: A survey[riccardo2024towards], Cat for DL - found Cario, a provable Rust-like language
2024-11-11 [2024-11-11]
2024-11-11 [2024-11-11]
#os - found Bartosz Ciechanowski's blog - found Topics in differential geometry[michor2008topics] and Algebraic geometry[milne2012algebraic], helpful for Notes on Algebraic Geometry - plan to read Templex-based dynamical units for a taxonomy of chaos[mosto2024templex]
2024-11-10 [2024-11-10]
2024-11-10 [2024-11-10]
#idea #lean #rust #wasm - contemplate the idea of better file management with Rust - meet datachain, extism, revisit mage-ai, should evaluate kestra, contemplate the idea of ML orchestration with Rust where each node is a WASM plugin, BAML has some potential - wish to get back more on Lean and Math in this month
2024-11-08 [2024-11-08]
2024-11-08 [2024-11-08]
#compiler #idea #rust - 🌴 - contemplate the idea of a bot to keep me going back to work on my projects, triggered by - an update of a related project - more than a month of inactivity - on the repo - or on a recent opened issue - gccrs: An alternative compiler for Rust
2024-11-07 [2024-11-07]
2024-11-07 [2024-11-07]
#proof - Isa Proof Shell
2024-11-06 [2024-11-06]
2024-11-06 [2024-11-06]
#git #gpu #neovim #ocaml #os #render #rust #shader - Forester 5.x git log, not bumping to 5.x yet - evaluate HTMX a bit - Why not just embed Neovim?, will need to revisit Zed later - RustGPU: Pros&Cons, the author becomes a maintainer of RustGPU - found VR Schwarzschild black hole shader (works with SPS and SPS-I)
October, 2024 [2024-10]
October, 2024 [2024-10]
2024-10-30 [2024-10-30]
2024-10-30 [2024-10-30]
#✍️ - finish Notes on modern C++ programming
2024-10-25 [2024-10-25]
2024-10-25 [2024-10-25]
#benchmark #formal #rust #tui
- work on native-land
- trying to make GA and math benchmark work, also evaluating the feasibility of benchmarking C++ libraries from Rust
- pass CI on runpod
- work on formal-land, make Verso work
- debug various TUI tools
2024-10-18 [2024-10-18]
2024-10-18 [2024-10-18]
#formal #gpu #lean #neovim #rust - work on native-land, trying to make rust-gpu fully work - work on formal-land, trying to establish the infrastructure to explore multiple Lean 4 projects with independent toolchains and dependencies - switching to Neovim, make it work for Rust, Lean, and forester - write some useful key mappings in Neovim - skim The Lean Language Reference - start reading Modern C++ Programming Course (C++03/11/14/17/20/23/26)
2024-10-17 [2024-10-17]
2024-10-17 [2024-10-17]
#citation #haskell #physics #render #shader #vulkan #web #webgl - initial citation trace for Gravitational lensing by spinning black holes in astrophysics, and in the movie interstellar[james2015gravitational] and Visualizing interstellar’s wormhole[james2015visualizing] - Custom vulkan engine to render black holes in real time using ray-marching[meseguer2023custom] (Vulkan, Ray-marching, Kerr black hole) lrogerorrit/narwhalEngine - Real-time high-quality rendering of non-rotating black holes[bruneton2020real] (CPU precal, WebGL2, Schwarzschild black hole) ebruneton/black_hole_shader - skimmed Identifying black holes through space telescopes and deep learning[fang2024identifying] - learn about Haskell-style type classes with isabelle/isar[haftmann2013haskell]: the type class for Isabelle, but its expressiveness is limited, see discussions in A construction of the lie algebra of a lie group in isabelle/HOL[schmoetten2024construction]
2024-10-16 [2024-10-16]
2024-10-16 [2024-10-16]
#benchmark #gpu #os - Automatic differentiation: Inverse accumulation mode[siskind2019automatic] and A matrix-free exact newton method[naumann2024matrix], seems limited, but have some good references - skim Gafro: Geometric algebra for robotics[low2023gafro] (good library and benchmark) and Developing GA-FuL: A generic wide-purpose library for computing with geometric algebra[eid2024developing] (good refs, but in C#) - skim A comprehensive overview of GPU accelerated databases[sharma2024comprehensive], an interesting area with sparse tensors as an in-memory database in mind - skim Felix: Optimizing tensor programs with gradient descent[zhao2024felix] (uiuc-arc/felix), which uses egg
2024-10-15 [2024-10-15]
2024-10-15 [2024-10-15]
#compiler - found Functoriality in finitary vacuum einstein gravity and free yang-mills theories from an abstract differential geometric perspective[raptis2024functoriality] - found A tensor algebra compiler for sparse differentiation[shaikhha2024tensor] and Felix: Optimizing tensor programs with gradient descent[zhao2024felix] - SDQLite Optimizing tensor programs on flexible storage[schleich2023optimizing] (based on SDQL) is an intermediate language that expresses sparse tensor workloads by separating the tensoropt computations from the storage formats - reminds me of A multi-level superoptimizer for tensor programs[wu2024multi]
2024-10-11 [2024-10-11]
2024-10-11 [2024-10-11]
#gpu - work on native-land about GPU computation, see relavant README updates.
2024-10-10 [2024-10-10]
2024-10-10 [2024-10-10]
#bevy #game #idea #rust - watch Chris Biscardi - Bevy: A case study in ergonomic Rust - have a better idea about the game about fly, evade, slingshot, and shoot around black holes, 4D implicit surfaces - explore sketchfab, polyhaven, and openverse, and have a basic idea about how to use them in the early stage of the game - learn about itch.io to surveying existing games, and a open revenue sharing platform to release games - found Algebraic geometry: A problem solving approach[garrity2013algebraic]
2024-10-09 [2024-10-09]
2024-10-09 [2024-10-09]
#lean #os - C++ Package Managers: The Ultimate Roundup, and start using xrepo for C/C++ package management, it also supports a wide range of package repositories, including Conan, Conda, Vcpkg, Homebrew, Apt, and Cargo. But not BinaryBuilder.jl ecosystem (see also this FAQ). - clarify the license for GinacLean, laying the ground for potential future work around Cadabra 2, which is licensed under GPLv3 - learn about Kento Okura's forest and Glade and Nota
2024-10-08 [2024-10-08]
2024-10-08 [2024-10-08]
#formal #gpu #lean #llvm #os #vulkan #web #z3 - add more plans in formal-land - recovered Research Codebase Manifesto from Lean-MLIR - recovered quotes from CICM 2020 Slack chat - make CubeCL example work - add CI with WebGPU on Mac & Ubuntu thanks to `llvmpipe`, `lavapipe`, `Vulkan SDK`, `Mesa` setup by tracel-ai/github-actions/setup-linux@v1 - found Lorenz and modular flows: a visual introduction
2024-10-07 [2024-10-07]
2024-10-07 [2024-10-07]
#news #os #rust - learned about lobste.rs, a computing-focused community centered around link aggregation and discussion, a bit like Hacker News but less noise maybe - Rewriting Rust and Josh Triplett's comment - A multi-level superoptimizer for tensor programs[wu2024multi] and learn about mirage - port My math interests in 2024 - make the Railscasts theme for Zed
2024-10-06 [2024-10-06]
2024-10-06 [2024-10-06]
#apl #os #tla #z3 - found ipe that is used extensively in tungsteno (source) - Why I use TLA+ and not(TLA+), learn about PlusCal, Quint and Apalache (TLA+ to Z3) - trying to figure out if TLA+ can be run in browser via TeaVM or CheerpJ
2024-10-05 [2024-10-05]
2024-10-05 [2024-10-05]
#os #render #web - A simple approach to differentiable rendering of SDFs[wang2024simple] - Rose: Composable autodiff for the interactive web[estep2024rose], and learn about Getting to the point: Index sets and parallelism-preserving autodiff for pointful array programming[paszke2021getting] dex-lang - they are read on mobile app Reflow which has good PDF reflow support for math formulas in Arxiv papers, but not so good for other math book PDFs
2024-10-04 [2024-10-04]
2024-10-04 [2024-10-04]
#category #game #idea - learn about catcolab.org and double category - learn about Curved Diffusion: A Generative Model With Optical Geometry Control from ECCV 2024 - Reusing Styles from Tailwind CSS, decide to use it for CSS refactor - found vanjs, considering for using it for VDOM and SSR - learn about the game sgued/slingshot (just like a recent idea about black hole puzzle game inspired by Star Trek: Discovery)
2024-10-03 [2024-10-03]
2024-10-03 [2024-10-03]
#os #render #rust #sci #shader - Differentiable Programming - found Differentiable Programming for Image Processing and Deep Learning in Halide and gradient-halide autodiff for halide - Adelta: Automatic Differentiation for Discontinuous Programs for A𝛿: Autodiff for Discontinuous Programs – Applied to Shaders Aδ: Autodiff for discontinuous programs-applied to shaders[yang2022delta] - found Dr.Jit - found Stan Math Library - found Kokkos - should eval the Rust crates of Rose - found mistral.rs for LLM inference, which uses a HF candle fork internally - found Why is anything conscious?[bennett2024anything]
2024-10-01 [2024-10-01]
2024-10-01 [2024-10-01]
#render #rust #shader - found A simple approach to differentiable rendering of SDFs[wang2024simple] and Interval shading: Using mesh shaders to generate shading intervals for volume rendering[tricard2024interval] - work on Rust stuff, particularly read about dioxus
September, 2024 [2024-09]
September, 2024 [2024-09]
2024-09-30 [2024-09-30]
2024-09-30 [2024-09-30]
#lean - skim rubik-lean4 and be reminded of On the nxnxn rubik’s cube[bonzio2018nxnxn] and Nxnxn rubik’s cubes and god’s number[salkinder2021nxnxn] - skim read-lean
2024-09-29 [2024-09-29]
2024-09-29 [2024-09-29]
#gpu #os - watch Coding Adventure: Optimizing a Ray Tracer (by building a BVH) and learn about the importance of BVH in ray tracing, and gkjohnson/three-mesh-bvh - collect autodiff in GPU - submit a bug report to Chromium - thinking about separating devlog from reading diary - thinking about turning my playground repos to monorepos by language/stack
2024-09-27 [2024-09-27]
2024-09-27 [2024-09-27]
#lean #sci - found Teaching mathematics using lean and controlled natural language[massot2024teaching] - noticed that Scientific Computing in Lean is now written in Verso! - checked some progress in Type Checking in Lean 4 - I should put together a list of resources for learning Lean, as I have been asked and answered this question multiple times - improve the VSCode Forester extension to have Hover, Go to definition, Search by title, and user-defined patterns for triggering completion
2024-09-26 [2024-09-26]
2024-09-26 [2024-09-26]
#bevy #os #rust #wasm #web - add initial survey on headless render/testing for WebGL - Compiling C to WebAssembly without Emscripten and WebAssembly without Emscripten, a bit dead-end for me - found twr-wasm, a lightweight emscripten - I still need to learn more about wasmer and cranelift - add test Rhai scripting - learn about monorepo tools: nx seems to have most feature-complete support for most stacks, moon is the next best choice for Bun.js+Rust projects that I have in mind. Other resources: - Building a Monorepo with Rust - I need to learn more about Salva: fluids simulation in Rust that works with Rapier, but it doesn't seem to have a JS binding yet, rapier even has an r3f package, and a plugin for bevy. See FLUID SIMULATION - SIGGRAPH 2007 Course Notes to learn more about fluid simulation. - learn about WLJS for Wolfram Mathematica, recalled my early Mathematica notebooks, and wish to do SSR for them
2024-09-25 [2024-09-25]
2024-09-25 [2024-09-25]
#biome #web - use `biome` for linting web source files - add some links about Star Trek
2024-09-24 [2024-09-24]
2024-09-24 [2024-09-24]
#web #webgl - add live reload - improve various loading and WebGL animation experience - found David Tong: Lectures on Gauge Theory
2024-09-23 [2024-09-23]
2024-09-23 [2024-09-23]
#gpu #render #shader #✍️ - more progress on Notes on ray-marching implicit surfaces, particularly on Raymarching in raymarching (sphere tracing) - found shaderfrog - found three-gpu-pathtracer and related projects, particularly Physically Based Materials, and that Steve Trettel uses it to render black holes and Hopf fibrations - found Multiview neural surface reconstruction by disentangling geometry and appearance[yariv2020multiview] (lioryariv/idr)
2024-09-22 [2024-09-22]
2024-09-22 [2024-09-22]
#os #quantum - skimmed Geometric quantization[carosso2018geometric]: "Geometric quantization is an attempt at using the differential-geometric ingredients of classical phase spaces regarded as symplectic manifolds in order to define a corresponding quantum theory." - skimmed Differential geometry: From elastic curves to willmore surfaces[pinkall2024differential]: "Unlike the common approach in existing textbooks on this topic, there is a strong focus on variational problems, ranging from elastic curves to surface that minimize area or Willmore functional." - found demo-geodesic-heat and mesh-parameterize - found From rings and modules to hopf algebras: One flew over the algebraist’s nest[broue2024rings]
2024-09-19 [2024-09-19]
2024-09-19 [2024-09-19]
#diagram #✍️ Make some progress on Notes on ray-marching implicit surfaces, particularly on mixing 4 elements (formulas, diagrams, algorithms, and readable working code).
2024-09-17 [2024-09-17]
2024-09-17 [2024-09-17]
#quantum - skimmed The role of symmetry in the development of the standard model[love2024role] Cambridge lectures on the standard model[quevedo2024cambridge] Lectures on quantum mechanics for mathematics students[faddeev2009lectures] Quantum mechanics for mathematicians graduate studies in mathematics vol 95 (providence, RI: American mathematical society)[takhtajan2008quantum] Lectures on quantum mechanics for mathematicians[komech2019lectures], and The role of the rigged hilbert space in quantum mechanics[madrid2005role]
2024-09-16 [2024-09-16]
2024-09-16 [2024-09-16]
#bevy #cg #game #os #render #rust #shader #visualization - found - symbolica for Rust and Python - Rusph: SPH algorithm in Rust for astrophysical simulations - Bevy: a game engine in Rust that could also be used for simulations - looking for materials related to ray-marching with GA, found - Non-parametric realtime rendering of subspace objects in arbitrary geometric algebras[keninck2019non] - Exploring novel surface representations via an experimental ray-tracer in cga[hadfield2021exploring] - Real-time visualization of moebius transformations in space using quaternionic-bezier approach[karpavicius2013real] - Visualizing hyperbolic honeycombs[nelson2017visualizing] talk - pga3.glsl - Normals and the Inverse Transpose, Part 1: Grassmann Algebra in 2018
2024-09-15 [2024-09-15]
2024-09-15 [2024-09-15]
#apl #benchmark #compiler #gpu #os #render #rust #sci #shader #web - found Compile Julia code to WebAssembly - found SHADERed as another source of shader examples, particularly some are written in Rust, supported via one of its plugins - looking for ways to include 3D models in LaTeX, found - asymptote - that can render .obj - that works in Overleaf - MeshLab that can export models to formats supported by media9 - watched Mike Seddon - Rust GPU Compute, found - Bend - faer-rs - cudarc - tinygrad - diol: benchmarking - wgpu-mm - Implementing Matrix Multiplication with WebGPU in Safari for optimized matrix multiplication on WebGPU - Fast CUDA SGEMM from Scratch - linfa: `scikit-learn` in Rust - gpu.cpp - CubeCL from Burn team - Candle from HF team - read - WebGPU — All of the cores, none of the canvas - How to Optimize a CUDA Matmul Kernel for cuBLAS-like Performance: a Worklog - Autotune for GPU Kernels: Ensuring Consistent Peak Performance from Burn team - WebGPU Compute Shader Basics - work through WebGPU Puzzles - learned about APL and BQN - a portion of The Dao Of FP - learned about fpgatoy
2024-09-12 [2024-09-12]
2024-09-12 [2024-09-12]
#✍️ - make a start on Notes on ray-marching implicit surfaces - make Ray marching (naïve)
2024-09-11 [2024-09-11]
2024-09-11 [2024-09-11]
#os #shader - trying to figure out curvature calculation in shaders - Screen Space Curvature Shader is a trick to mimic curvature calculation in shaders,using dFdx, dFdy in GLSL, Curvature shader by iY0Yi used it but it shows certain shower door effect - glsl-autodiff properly uses forward auto differentiation to calculate curvature in shaders, but it requires rewrite every math function for bookkeeping the gradient and the Hessian
2024-09-10 [2024-09-10]
2024-09-10 [2024-09-10]
#shader - work out shader for test Keenan Crane's style for rendering edge and shade - inspired by Surface Plotter (demo), read - Marching Cubes - Polygonising a scalar field - CIS700 Procedural Graphics: Implicit surfaces - Marching cubes - Marching Cubes Part 1: Explaining marching cubes
2024-09-09 [2024-09-09]
2024-09-09 [2024-09-09]
#formal #lean #optimization #os #rust #wasm - add `egglog` and `ginac`, and streamline the build process of Rust WASM dependencies - reading source of projects using egg: `jafioti/luminal`, `marcusrossel/lean-egg`, `verified-optimization/CvxLean` etc. TODO: read more egg papers: Bridging syntax and semantics of lean expressions in e-graphs[rossel2024bridging]An equality saturation tactic for lean[rossel2024equality]Verified reductions for optimization[bentkamp2023verified]
2024-09-08 [2024-09-08]
2024-09-08 [2024-09-08]
#gpu #render #web #z3 - mark candidates for rendering PDB: some links for viewing protein or molecules - fail to run Z3 in browser (due to `SharedArrayBuffer` again) - the source of examples of uwal and the corresponding articles at webgpufundamentals.org - test compute.toys and test 3D Bifurcation Diagram
2024-09-07 [2024-09-07]
2024-09-07 [2024-09-07]
#shader - Skim through Projective geometric algebra illuminated[lengyel2024foundations] - experiments on compute shaders
2024-09-06 [2024-09-06]
2024-09-06 [2024-09-06]
#idea - Polish Notes on Clifford Algebras - Some more on Translation of Bourbaki on Clifford algebras - Re-skim Clifford and the ’square root’ ideas[trautman1997clifford] - The algebra of grand unified theories[baez2010algebra] and make 97 notes - Notes on Distributed Systems for Young Bloods (2013)
2024-09-05 [2024-09-05]
2024-09-05 [2024-09-05]
#formal #lean #sec #✍️
- Ported the rest of the prelimilary part of The blueprint for formalizing geometric algebra in lean[wieser2024blueprint] to Notes on Clifford Algebras, except \(Z_2\)-graded derivations \(i_f\), anti-derivation
- Make a start on notes on group algebras
2024-09-04 [2024-09-04]
2024-09-04 [2024-09-04]
#citation #idea #os - The supergeometric algebra[hamilton2023supergeometric] and Unification of the four forces in the spin (11, 1) geometric algebra[hamilton2023unification]: illuminating path towards a unified theory of four fundamental forces, the first theory seemingly capable of reaching the same level of elegance and simplicity as A discrete model for gell-mann matrices[wilson2024discrete], the authors are also aware of potential issues and worked out viable solutions to address them. Unfortunately, there are no citations as of now. - Clifford and the ’square root’ ideas[trautman1997clifford] has certain historical remarks and a unusual approach that spinor representations are treated first for odd-dimensional spaces spaces - Geometry of lightning self-attention: Identifiability and dimension[henry2024geometry] (found on Mar 11, 2025 again) - The tensor cookbook[ahle2024tensor] and Graphical tensor notation for interpretability - The Calculus of Variations and Geometry: a Historical Perspective - Data-driven linearization of dynamical systems - Meta Flow Matching: Integrating Vector Fields on the Wasserstein Manifold
2024-09-03 [2024-09-03]
2024-09-03 [2024-09-03]
#cg #formal #physics #sci #sec - [grassmann2000extension, ch. 1-4] - [browne2012grassmann, sec. 1.1-2.8] - The universe is not a lie, but actually an hopf, algebra[loret2024universe] - some slides of AGACSE 2024 - The Willing Kingdon Clifford Algebra Library - Look, Ma, No Matrices! - Spacetime Algebra and Octonions: Links with the groups used in particle physics and computer graphics - Construction of Exceptional Lie Algebra G2 and Non-Associative Algebras using Clifford Algebra - On Multidimensional Dirac-Hestenes Equation - On Rank of Multivectors in Geometric Algebra - From Null Monomials to Versors in Conformal Geometry - Look, Ma, No Trigonometry! - Dual Spaces are Real: Orientation Types in Geometric Algebras - On Generalized Degenerate Lipschitz and Spin Groups - Projective and Conformal Formulations of Electromagnetism - Representation and Gauge Freedom in Electromagnetism and Acoustics - Pencils and set operators in 3D CGA - Factorizations of the Conformal Villarceau Motion
January to August, 2024 [2024-01~08]
January to August, 2024 [2024-01~08]
2024-08-11 [2024-08-11]
2024-08-11 [2024-08-11]
The readings during this period are reflected in - some links for rendering implicit surfaces - some links for learning shaders Many experiments on Forester are done, as summarized in A customizable, hybrid approach to code & resource pipeline and embedding.
2024-07-27 [2024-07-27]
2024-07-27 [2024-07-27]
The readings during this period are yet to be reflected in Notes on Algebraic Geometry.
2024-05-09 [2024-05-09]
2024-05-09 [2024-05-09]
The readings during this period are reflected in Notes on Topos Theory and Type Theory. Translation of Bourbaki on Clifford algebras was ported to Forester on 07-22.
2024-04-25 [2024-04-25]
2024-04-25 [2024-04-25]
The readings during this period are reflected in Compendium on Spin groups. Some are yet to be reflected in Notes on Hopf Algebras.
2024-01-01 [2024-01-01]
2024-01-01 [2024-01-01]
#os The readings during this period are reflected in - My math interests in 2024 - Studying group algebras with GAP - Notes on Zeon Algebra
Year 2023 [2023]
Year 2023 [2023]
September to December, 2023 [2023-09~12]
September to December, 2023 [2023-09~12]
I was working on Lean related projects during this period, my readings are partially reflected in my Lean 4 Playground, but most of the time I was reading Lean's Zulip Chat messages. Maybe one day I should archive my stars on Zulip Chat.
February to August, 2023 [2023-02~08]
February to August, 2023 [2023-02~08]
The readings during this period are reflected in - my LLM Daily Picks - my blog post Transformers: from self-attention to performance optimizations
Year 2014~2023
The interests during this period are reflected in interests in early years.
Year 2014~2023
Lost notes [uts-0014]
Lost notes [uts-0014]
The following are normal leaf notes that are not transcluded by any note, and are not captured by root notes or Draft notes, thus might be lost.
Status [spin-000S]
Status [spin-000S]
Currently it's a work-in-progress.
Some tips about Forester [uts-000T]
Some tips about Forester [uts-000T]
Browsing
Browsing
To search, use the magnifying glass icon on the top right corner, or press Ctrl+K(Windows/Linux) or Cmd+K(Mac).
Some math in this forest are rendered as SVG images, to copy texts you need to open the SVG image in a new browser tab then select them.
Authoring
Authoring
See The Forester markup language for Markup references, also consult Forester changlog for updates.
To find macros used in the forest, check out Basic macros.
Technical experiments [uts-0010]
Technical experiments [uts-0010]
The following are technical experiments on what kind of rich content I can include in my forester notes. See my post on this for more background. Some of my Technical notes (draft) might have additional information.
Lean 4 code highlighting [uts-0003]
Lean 4 code highlighting [uts-0003]
The following code is taken from pygments to test Lean 4 code highlighting, with only wrapped strings removed because it confuses forester.
/-
Copyright (c) 2017 Johannes Hölzl. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Johannes Hölzl
-/
import Mathlib.Order.Chain
#align_import order.zorn from "leanprover-community/mathlib"@"46a64b5b4268c594af770c44d9e502afc6a515cb"
/-!
# Zorn's lemmas
This file proves several formulations of Zorn's Lemma.
## Variants
The primary statement of Zorn's lemma is `exists_maximal_of_chains_bounded`. Then it is specialized
to particular relations:
* `(≤)` with `zorn_partialOrder`
* `(⊆)` with `zorn_subset`
* `(⊇)` with `zorn_superset`
Lemma names carry modifiers:
* `₀`: Quantifies over a set, as opposed to over a type.
* `_nonempty`: Doesn't ask to prove that the empty chain is bounded and lets you give an element
that will be smaller than the maximal element found (the maximal element is no smaller than any
other element, but it can also be incomparable to some).
## How-to
This file comes across as confusing to those who haven't yet used it, so here is a detailed
walkthrough:
1. Know what relation on which type/set you're looking for. See Variants above. You can discharge
some conditions to Zorn's lemma directly using a `_nonempty` variant.
2. Write down the definition of your type/set, put a `suffices : ∃ m, ∀ a, m ≺ a → a ≺ m, { ... },`
(or whatever you actually need) followed by an `apply some_version_of_zorn`.
3. Fill in the details. This is where you start talking about chains.
A typical proof using Zorn could look like this (TODO: update to mathlib4)
```lean
lemma zorny_lemma : zorny_statement :=
begin
let s : Set α := {x | whatever x},
suffices : ∃ x ∈ s, ∀ y ∈ s, y ⊆ x → y = x, -- or with another operator
{ exact proof_post_zorn },
apply zorn_subset, -- or another variant
rintro c hcs hc,
obtain rfl | hcnemp := c.eq_empty_or_nonempty, -- you might need to disjunct on c empty or not
{ exact ⟨edge_case_construction,
proof_that_edge_case_construction_respects_whatever,
proof_that_edge_case_construction_contains_all_stuff_in_c⟩ },
exact ⟨construction,
proof_that_construction_respects_whatever,
proof_that_construction_contains_all_stuff_in_c⟩,
end
```
## Notes
Originally ported from Isabelle/HOL. The
[original file](https://isabelle.in.tum.de/dist/library/HOL/HOL/Zorn.html) was written by Jacques D.
Fleuriot, Tobias Nipkow, Christian Sternagel.
-/
open Classical Set
variable {α β : Type*} {r : α → α → Prop} {c : Set α}
/-- Local notation for the relation being considered. -/
local infixl:50 " ≺ " => r
/-- **Zorn's lemma**
If every chain has an upper bound, then there exists a maximal element. -/
theorem exists_maximal_of_chains_bounded (h : ∀ c, IsChain r c → ∃ ub, ∀ a ∈ c, a ≺ ub)
(trans : ∀ {a b c}, a ≺ b → b ≺ c → a ≺ c) : ∃ m, ∀ a, m ≺ a → a ≺ m :=
have : ∃ ub, ∀ a ∈ maxChain r, a ≺ ub := h _ <| maxChain_spec.left
let ⟨ub, (hub : ∀ a ∈ maxChain r, a ≺ ub)⟩ := this
⟨ub, fun a ha =>
have : IsChain r (insert a <| maxChain r) :=
maxChain_spec.1.insert fun b hb _ => Or.inr <| trans (hub b hb) ha
hub a <| by
rw [maxChain_spec.right this (subset_insert _ _)]
exact mem_insert _ _⟩
#align exists_maximal_of_chains_bounded exists_maximal_of_chains_bounded
/-- A variant of Zorn's lemma. If every nonempty chain of a nonempty type has an upper bound, then
there is a maximal element.
-/
theorem exists_maximal_of_nonempty_chains_bounded [Nonempty α]
(h : ∀ c, IsChain r c → c.Nonempty → ∃ ub, ∀ a ∈ c, a ≺ ub)
(trans : ∀ {a b c}, a ≺ b → b ≺ c → a ≺ c) : ∃ m, ∀ a, m ≺ a → a ≺ m :=
exists_maximal_of_chains_bounded
(fun c hc =>
(eq_empty_or_nonempty c).elim
(fun h => ⟨Classical.arbitrary α, fun x hx => (h ▸ hx : x ∈ (∅ : Set α)).elim⟩) (h c hc))
trans
#align exists_maximal_of_nonempty_chains_bounded exists_maximal_of_nonempty_chains_bounded
section Preorder
variable [Preorder α]
theorem zorn_preorder (h : ∀ c : Set α, IsChain (· ≤ ·) c → BddAbove c) :
∃ m : α, ∀ a, m ≤ a → a ≤ m :=
exists_maximal_of_chains_bounded h le_trans
#align zorn_preorder zorn_preorder
theorem zorn_nonempty_preorder [Nonempty α]
(h : ∀ c : Set α, IsChain (· ≤ ·) c → c.Nonempty → BddAbove c) : ∃ m : α, ∀ a, m ≤ a → a ≤ m :=
exists_maximal_of_nonempty_chains_bounded h le_trans
#align zorn_nonempty_preorder zorn_nonempty_preorder
theorem zorn_preorder₀ (s : Set α)
(ih : ∀ c ⊆ s, IsChain (· ≤ ·) c → ∃ ub ∈ s, ∀ z ∈ c, z ≤ ub) :
∃ m ∈ s, ∀ z ∈ s, m ≤ z → z ≤ m :=
let ⟨⟨m, hms⟩, h⟩ :=
@zorn_preorder s _ fun c hc =>
let ⟨ub, hubs, hub⟩ :=
ih (Subtype.val '' c) (fun _ ⟨⟨_, hx⟩, _, h⟩ => h ▸ hx)
(by
rintro _ ⟨p, hpc, rfl⟩ _ ⟨q, hqc, rfl⟩ hpq
refine' hc hpc hqc fun t => hpq (Subtype.ext_iff.1 t))
⟨⟨ub, hubs⟩, fun ⟨y, hy⟩ hc => hub _ ⟨_, hc, rfl⟩⟩
⟨m, hms, fun z hzs hmz => h ⟨z, hzs⟩ hmz⟩
#align zorn_preorder₀ zorn_preorder₀
theorem zorn_nonempty_preorder₀ (s : Set α)
(ih : ∀ c ⊆ s, IsChain (· ≤ ·) c → ∀ y ∈ c, ∃ ub ∈ s, ∀ z ∈ c, z ≤ ub) (x : α)
(hxs : x ∈ s) : ∃ m ∈ s, x ≤ m ∧ ∀ z ∈ s, m ≤ z → z ≤ m := by
-- Porting note: the first three lines replace the following two lines in mathlib3.
-- The mathlib3 `rcases` supports holes for proof obligations, this is not yet implemented in 4.
-- rcases zorn_preorder₀ ({ y ∈ s | x ≤ y }) fun c hcs hc => ?_ with ⟨m, ⟨hms, hxm⟩, hm⟩
-- · exact ⟨m, hms, hxm, fun z hzs hmz => hm _ ⟨hzs, hxm.trans hmz⟩ hmz⟩
have H := zorn_preorder₀ ({ y ∈ s | x ≤ y }) fun c hcs hc => ?_
· rcases H with ⟨m, ⟨hms, hxm⟩, hm⟩
exact ⟨m, hms, hxm, fun z hzs hmz => hm _ ⟨hzs, hxm.trans hmz⟩ hmz⟩
· rcases c.eq_empty_or_nonempty with (rfl | ⟨y, hy⟩)
· exact ⟨x, ⟨hxs, le_rfl⟩, fun z => False.elim⟩
· rcases ih c (fun z hz => (hcs hz).1) hc y hy with ⟨z, hzs, hz⟩
exact ⟨z, ⟨hzs, (hcs hy).2.trans <| hz _ hy⟩, hz⟩
#align zorn_nonempty_preorder₀ zorn_nonempty_preorder₀
theorem zorn_nonempty_Ici₀ (a : α)
(ih : ∀ c ⊆ Ici a, IsChain (· ≤ ·) c → ∀ y ∈ c, ∃ ub, ∀ z ∈ c, z ≤ ub)
(x : α) (hax : a ≤ x) : ∃ m, x ≤ m ∧ ∀ z, m ≤ z → z ≤ m := by
let ⟨m, _, hxm, hm⟩ := zorn_nonempty_preorder₀ (Ici a) (fun c hca hc y hy ↦ ?_) x hax
· exact ⟨m, hxm, fun z hmz => hm _ (hax.trans <| hxm.trans hmz) hmz⟩
· have ⟨ub, hub⟩ := ih c hca hc y hy; exact ⟨ub, (hca hy).trans (hub y hy), hub⟩
#align zorn_nonempty_Ici₀ zorn_nonempty_Ici₀
end Preorder
section PartialOrder
variable [PartialOrder α]
theorem zorn_partialOrder (h : ∀ c : Set α, IsChain (· ≤ ·) c → BddAbove c) :
∃ m : α, ∀ a, m ≤ a → a = m :=
let ⟨m, hm⟩ := zorn_preorder h
⟨m, fun a ha => le_antisymm (hm a ha) ha⟩
#align zorn_partial_order zorn_partialOrder
theorem zorn_nonempty_partialOrder [Nonempty α]
(h : ∀ c : Set α, IsChain (· ≤ ·) c → c.Nonempty → BddAbove c) : ∃ m : α, ∀ a, m ≤ a → a = m :=
let ⟨m, hm⟩ := zorn_nonempty_preorder h
⟨m, fun a ha => le_antisymm (hm a ha) ha⟩
#align zorn_nonempty_partial_order zorn_nonempty_partialOrder
theorem zorn_partialOrder₀ (s : Set α)
(ih : ∀ c ⊆ s, IsChain (· ≤ ·) c → ∃ ub ∈ s, ∀ z ∈ c, z ≤ ub) :
∃ m ∈ s, ∀ z ∈ s, m ≤ z → z = m :=
let ⟨m, hms, hm⟩ := zorn_preorder₀ s ih
⟨m, hms, fun z hzs hmz => (hm z hzs hmz).antisymm hmz⟩
#align zorn_partial_order₀ zorn_partialOrder₀
theorem zorn_nonempty_partialOrder₀ (s : Set α)
(ih : ∀ c ⊆ s, IsChain (· ≤ ·) c → ∀ y ∈ c, ∃ ub ∈ s, ∀ z ∈ c, z ≤ ub) (x : α)
(hxs : x ∈ s) : ∃ m ∈ s, x ≤ m ∧ ∀ z ∈ s, m ≤ z → z = m :=
let ⟨m, hms, hxm, hm⟩ := zorn_nonempty_preorder₀ s ih x hxs
⟨m, hms, hxm, fun z hzs hmz => (hm z hzs hmz).antisymm hmz⟩
#align zorn_nonempty_partial_order₀ zorn_nonempty_partialOrder₀
end PartialOrder
theorem zorn_subset (S : Set (Set α))
(h : ∀ c ⊆ S, IsChain (· ⊆ ·) c → ∃ ub ∈ S, ∀ s ∈ c, s ⊆ ub) :
∃ m ∈ S, ∀ a ∈ S, m ⊆ a → a = m :=
zorn_partialOrder₀ S h
#align zorn_subset zorn_subset
theorem zorn_subset_nonempty (S : Set (Set α))
(H : ∀ c ⊆ S, IsChain (· ⊆ ·) c → c.Nonempty → ∃ ub ∈ S, ∀ s ∈ c, s ⊆ ub) (x)
(hx : x ∈ S) : ∃ m ∈ S, x ⊆ m ∧ ∀ a ∈ S, m ⊆ a → a = m :=
zorn_nonempty_partialOrder₀ _ (fun _ cS hc y yc => H _ cS hc ⟨y, yc⟩) _ hx
#align zorn_subset_nonempty zorn_subset_nonempty
theorem zorn_superset (S : Set (Set α))
(h : ∀ c ⊆ S, IsChain (· ⊆ ·) c → ∃ lb ∈ S, ∀ s ∈ c, lb ⊆ s) :
∃ m ∈ S, ∀ a ∈ S, a ⊆ m → a = m :=
(@zorn_partialOrder₀ (Set α)ᵒᵈ _ S) fun c cS hc => h c cS hc.symm
#align zorn_superset zorn_superset
theorem zorn_superset_nonempty (S : Set (Set α))
(H : ∀ c ⊆ S, IsChain (· ⊆ ·) c → c.Nonempty → ∃ lb ∈ S, ∀ s ∈ c, lb ⊆ s) (x)
(hx : x ∈ S) : ∃ m ∈ S, m ⊆ x ∧ ∀ a ∈ S, a ⊆ m → a = m :=
@zorn_nonempty_partialOrder₀ (Set α)ᵒᵈ _ S (fun _ cS hc y yc => H _ cS hc.symm ⟨y, yc⟩) _ hx
#align zorn_superset_nonempty zorn_superset_nonempty
/-- Every chain is contained in a maximal chain. This generalizes Hausdorff's maximality principle.
-/
theorem IsChain.exists_maxChain (hc : IsChain r c) : ∃ M, @IsMaxChain _ r M ∧ c ⊆ M := by
-- Porting note: the first three lines replace the following two lines in mathlib3.
-- The mathlib3 `obtain` supports holes for proof obligations, this is not yet implemented in 4.
-- obtain ⟨M, ⟨_, hM₀⟩, hM₁, hM₂⟩ :=
-- zorn_subset_nonempty { s | c ⊆ s ∧ IsChain r s } _ c ⟨Subset.rfl, hc⟩
have H := zorn_subset_nonempty { s | c ⊆ s ∧ IsChain r s } ?_ c ⟨Subset.rfl, hc⟩
· obtain ⟨M, ⟨_, hM₀⟩, hM₁, hM₂⟩ := H
exact ⟨M, ⟨hM₀, fun d hd hMd => (hM₂ _ ⟨hM₁.trans hMd, hd⟩ hMd).symm⟩, hM₁⟩
rintro cs hcs₀ hcs₁ ⟨s, hs⟩
refine'
⟨⋃₀cs, ⟨fun _ ha => Set.mem_sUnion_of_mem ((hcs₀ hs).left ha) hs, _⟩, fun _ =>
Set.subset_sUnion_of_mem⟩
rintro y ⟨sy, hsy, hysy⟩ z ⟨sz, hsz, hzsz⟩ hyz
obtain rfl | hsseq := eq_or_ne sy sz
· exact (hcs₀ hsy).right hysy hzsz hyz
cases' hcs₁ hsy hsz hsseq with h h
· exact (hcs₀ hsz).right (h hysy) hzsz hyz
· exact (hcs₀ hsy).right hysy (h hzsz) hyz
#align is_chain.exists_max_chain IsChain.exists_maxChain
-- other bits of tricky syntax
variable {ι A B : Type*} (𝒜 : ι → A) (ℬ : ι → B)
#check `𝒜.a
#check ``𝒜
#check List.get!
#check 1.0 + 2. + 0.3e1
#check "\
This is\na \
wrapped string."
@[to_additive "See note [foo]"]
lemma mul_one : sorry := sorry
Test TwistySim [uts-016I]
Test TwistySim [uts-016I]
For docs, see TwistySim.
TwistySim is the work of Conrad Rider, licensed under the Creative Commons Attribution-ShareAlike 4.0 International License (CC BY-SA 4.0).
Test Twizzle [uts-016H]
R U2' R2 U' R2 U' R2 U2' R
y'
M2' U M U2 M' U M2
Test Twizzle [uts-016H]
- API: cubing.js and full API reference - available options for TwistyPlayer: twisty-player-config - demo for TwistyAlgVier: twisty-alg-viewer demo for use of alg viewer, inspired by A supplement to "Commutators in the Rubik's Cube Group"
test 3D Bifurcation Diagram [uts-001C]
test 3D Bifurcation Diagram [uts-001C]
Adapted from ⧉:
#storage atomic_storage array<atomic<i32>>
const MaxSamples = 256.0;
const FOV = 0.6;
const PI = 3.14159265;
const TWO_PI = 6.28318530718;
const STEP = 0.01;
const LARGENUM = 1e10;
const ATOMIC_SCALE = 1024.0;
struct Camera
{
pos: float3,
cam: float3x3,
fov: float,
size: float2
}
struct Ray
{
ro: float3,
rd: float3,
}
var<private> camera : Camera;
var<private> state : uint4;
fn pcg4d(a: uint4) -> uint4
{
var v = a * 1664525u + 1013904223u;
v.x += v.y*v.w; v.y += v.z*v.x; v.z += v.x*v.y; v.w += v.y*v.z;
v = v ^ ( v >> uint4(16u) );
v.x += v.y*v.w; v.y += v.z*v.x; v.z += v.x*v.y; v.w += v.y*v.z;
return v;
}
fn rand4() -> float4
{
state = pcg4d(state);
return float4(state)/float(0xffffffffu);
}
fn nrand4(sigma: float, mean: float4) -> float4
{
let Z = rand4();
return mean + sigma * sqrt(-2.0 * log(Z.xxyy)) *
float4(cos(TWO_PI * Z.z),sin(TWO_PI * Z.z),cos(TWO_PI * Z.w),sin(TWO_PI * Z.w));
}
fn udir(rng: float2) -> float3
{
let r = float2(2.*PI*rng.x, acos(2.*rng.y - 1.0));
let c = cos(r);
let s = sin(r);
return float3(c.x*s.y, s.x*s.y, c.y);
}
fn disk(rng: float2) -> float2
{
return float2(sin(TWO_PI*rng.x), cos(TWO_PI*rng.x))*sqrt(rng.y);
}
fn Rotate(t: float) -> float2x2
{
return float2x2(
cos(t), sin(t),
- sin(t), cos(t),
);
}
fn RotXY(x: float3, t: float) -> float3
{
return float3(Rotate(t)*x.xy, x.z);
}
fn GetCameraMatrix(ang: float2) -> float3x3
{
let x_dir = float3(cos(ang.x)*sin(ang.y), cos(ang.y), sin(ang.x)*sin(ang.y));
let y_dir = normalize(cross(x_dir, float3(0.0,1.0,0.0)));
let z_dir = normalize(cross(y_dir, x_dir));
return float3x3(-x_dir, y_dir, z_dir);
}
fn SetCamera()
{
let screen_size = int2(textureDimensions(screen));
let screen_size_f = float2(screen_size);
let ang = float2(mouse.pos.xy)*float2(-TWO_PI, PI)/screen_size_f + float2(0.4, 0.4);
camera.fov = FOV;
camera.cam = GetCameraMatrix(ang);
camera.pos = - (camera.cam*float3(8.0*custom.Radius+0.5,0.0,0.0));
camera.size = screen_size_f;
}
//project to clip space
fn Project(cam: Camera, p: float3) -> float3
{
let td = distance(cam.pos, p);
let dir = (p - cam.pos)/td;
let screen = dir*cam.cam;
return float3(screen.yz*cam.size.y/(cam.fov*screen.x) + 0.5*cam.size,screen.x*td);
}
const max_iterations = 256;
const color_thresholds = float4(255.0, 130.0, 80.0, 255.0);
fn AdditiveBlend(color: float3, depth: float, index: int)
{
let scaledColor = int3(floor(ATOMIC_SCALE*color/(depth*depth + 0.2) + rand4().xyz));
if(scaledColor.x>0)
{
atomicAdd(&atomic_storage[index*4+0], scaledColor.x);
}
if(scaledColor.y>0)
{
atomicAdd(&atomic_storage[index*4+1], scaledColor.y);
}
if(scaledColor.z>0)
{
atomicAdd(&atomic_storage[index*4+2], scaledColor.z);
}
}
fn RasterizePoint(pos: float3, color: float3)
{
let screen_size = int2(camera.size);
let projectedPos = Project(camera, pos);
let screenCoord = int2(projectedPos.xy+0.5*rand4().xy);
//outside of our view
if(screenCoord.x < 0 || screenCoord.x >= screen_size.x ||
screenCoord.y < 0 || screenCoord.y >= screen_size.y || projectedPos.z < 0.0)
{
return;
}
let idx = screenCoord.x + screen_size.x * screenCoord.y;
AdditiveBlend(color, projectedPos.z, idx);
}
fn saturate(x: f32) -> f32 {
return min(1.0, max(0.0, x));
}
fn saturate_vec3(x: vec3<f32>) -> vec3<f32> {
return min(vec3<f32>(1.0, 1.0, 1.0), max(vec3<f32>(0.0, 0.0, 0.0), x));
}
fn bump3y(x: vec3<f32>, yoffset: vec3<f32>) -> vec3<f32> {
var y: vec3<f32> = vec3<f32>(1.0, 1.0, 1.0) - x * x;
y = saturate_vec3(y - yoffset);
return y;
}
fn spectral_zucconi(w: f32) -> vec3<f32> {
let x: f32 = saturate((w - 400.0) / 300.0);
let cs: vec3<f32> = vec3<f32>(3.54541723, 2.86670055, 2.29421995);
let xs: vec3<f32> = vec3<f32>(0.69548916, 0.49416934, 0.28269708);
let ys: vec3<f32> = vec3<f32>(0.02320775, 0.15936245, 0.53520021);
return bump3y(cs * (x - xs), ys);
}
fn hue(v: float) -> float3 {
return .6 + .6 * cos(6.3 * v + float3(0.,23.,21.));
}
fn bifurcation(iters: i32) {
var p = rand4().xyz * float3(4.0, 4.0, 5.0) - float3(2.0, 2.0, -0.25);
let s = rand4().x;
let alpha = custom.Alpha;
let beta = custom.Beta + custom.BetaAnim*(0.5 * sin(time.elapsed) + 0.5) + custom.BetaS*s;
for (var j: i32 = 0; j <= iters; j = j + 1) {
let p0 = p;
p.x = p.z - p0.y*(beta * p0.x + (1.0 - beta) * p0.y);
p.y = p0.x + p0.y * p0.y * alpha;
if(j < iters - int(custom.Samples*MaxSamples + 1.0)) {continue;}
var color = spectral_zucconi(350 + 350.0*s);
color = pow(color, vec3(1.0));
RasterizePoint(float3(1,1,2.5)*(p - float3(0.5, 0.5, 1.5)), 32.0*color/(custom.Samples*MaxSamples + 1.0));
}
}
@compute @workgroup_size(16, 16)
fn Clear(@builtin(global_invocation_id) id: uint3) {
let screen_size = int2(textureDimensions(screen));
let idx0 = int(id.x) + int(screen_size.x * int(id.y));
atomicStore(&atomic_storage[idx0*4+0], 0);
atomicStore(&atomic_storage[idx0*4+1], 0);
atomicStore(&atomic_storage[idx0*4+2], 0);
atomicStore(&atomic_storage[idx0*4+3], 0);
}
@compute @workgroup_size(16, 16)
fn Rasterize(@builtin(global_invocation_id) id: uint3)
{
SetCamera();
//RNG state
state = uint4(id.x, id.y, id.z, uint(custom.NoiseAnimation)*time.frame);
bifurcation(int(MaxSamples*2.0));
}
fn Sample(pos: int2) -> float3
{
let screen_size = int2(textureDimensions(screen));
let idx = pos.x + screen_size.x * pos.y;
var color: float3;
let x = float(atomicLoad(&atomic_storage[idx*4+0]));
let y = float(atomicLoad(&atomic_storage[idx*4+1]));
let z = float(atomicLoad(&atomic_storage[idx*4+2]));
color = float3(x,y,z)/ATOMIC_SCALE;
return abs(color);
}
@compute @workgroup_size(16, 16)
fn FinalPass(@builtin(global_invocation_id) id: uint3)
{
let screen_size = uint2(textureDimensions(screen));
// Prevent overdraw for workgroups on the edge of the viewport
if (id.x >= screen_size.x || id.y >= screen_size.y) { return; }
// Pixel coordinates (centre of pixel, origin at bottom left)
let fragCoord = float2(float(id.x) + .5, float(id.y) + .5);
let oldColor = textureLoad(pass_in, int2(id.xy), 0, 0);
var color = float4(Sample(int2(id.xy)), 1.0);
if(mouse.click != 1)
{
color += oldColor * custom.Accumulation;
}
let exposed = 1.0 - exp(-5.0*custom.Exposure*color.xyz/color.w);
// Output to buffer
textureStore(pass_out, int2(id.xy), 0, color);
textureStore(screen, int2(id.xy), float4(exposed, 1.));
}
test GiNaC (WASM) [uts-001H]
test GiNaC (WASM) [uts-001H]
For now, open the console to see the output.
test Keenan Crane's style for rendering edge and shade [uts-001D]
test Keenan Crane's style for rendering edge and shade [uts-001D]
Adapted from ⧉:
#define EDGE_WIDTH 0.12
#define RAYMARCH_ITERATIONS 35
#define SHADOW_ITERATIONS 40
#define SHADOW_STEP 1.0
#define SHADOW_SMOOTHNESS 256.0
#define SHADOW_DARKNESS 0.75
// Distance functions from iquilezles.org
float fSubtraction(float a, float b) {return max(-a,b);}
float fIntersection(float d1, float d2) {return max(d1,d2);}
void fUnion(inout float d1, float d2) {d1 = min(d1,d2);}
float pSphere(vec3 p, float s) {return length(p)-s;}
float pRoundBox(vec3 p, vec3 b, float r) {return length(max(abs(p)-b,0.0))-r;}
float pTorus(vec3 p, vec2 t) {vec2 q = vec2(length(p.xz)-t.x,p.y); return length(q)-t.y;}
float pTorus2(vec3 p, vec2 t) {vec2 q = vec2(length(p.xy)-t.x,p.z); return length(q)-t.y;}
float pCapsule(vec3 p, vec3 a, vec3 b, float r) {vec3 pa = p - a, ba = b - a;
float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 ); return length( pa - ba*h ) - r;}
float mySDF(vec3 p) {
float x = p.x;
float y = p.y;
float z = p.z;
float x2 = pow(x, 2.);
float y2 = pow(y, 2.);
float z2 = pow(z, 2.);
float x3 = pow(x, 3.);
float y3 = pow(y, 3.);
float z3 = pow(z, 3.);
float x4 = pow(x, 4.);
float y4 = pow(y, 4.);
float z4 = pow(z, 4.);
// return (y-x2)*(z-x3);
// return 5.*(z2+y3-y4-x2*y2);
// return (y2-x2-z2);
return (x2-z2*y2+y3);
}
float distf(vec3 p)
{
float d = 100000.0;
fUnion(d, pRoundBox(vec3(0,0,10) + p, vec3(21,21,1), 1.0));
fUnion(d, pSphere(vec3(10,10,0) + p, 8.0));
fUnion(d, pSphere(vec3(16,0,4) + p, 4.0));
fUnion(d, pCapsule(p, vec3(10,10,12), vec3(15,15,-6.5), 1.5));
fUnion(d, pCapsule(p, vec3(10,10,12), vec3(5,15,-6.5), 1.5));
fUnion(d, pCapsule(p, vec3(10,10,12), vec3(10,5,-6.5), 1.5));
fUnion(d, pTorus(vec3(15,-15,0) + p, vec2(6,2)));
fUnion(d, pTorus2(vec3(10,-15,0) + p, vec2(6,2)));
fUnion(d, pRoundBox(vec3(-10,10,-2) + p, vec3(1,1,9), 1.0));
fUnion(d, pRoundBox(vec3(-10,10,-4) + p, vec3(0.5,6,0.5), 1.0));
fUnion(d, pRoundBox(vec3(-10,10,2) + p, vec3(6,0.5,0.5), 1.0));
// d = mySDF(p);
// d = fIntersection(d, pSphere(p,15.0));
return d;
}
vec3 grad(vec3 p)
{
const float eps = 0.01;
float m;
vec3 d_distf = vec3( (distf(vec3(p.x-eps,p.y,p.z)) - distf(vec3(p.x+eps,p.y,p.z))),
(distf(vec3(p.x,p.y-eps,p.z)) - distf(vec3(p.x,p.y+eps,p.z))),
(distf(vec3(p.x,p.y,p.z-eps)) - distf(vec3(p.x,p.y,p.z+eps)))
);
return d_distf / (2.*eps);
}
vec3 grad2(vec3 p)
{
const float eps = 0.01;
float m;
vec3 d_grad = vec3( (grad(vec3(p.x-eps,p.y,p.z)) - grad(vec3(p.x+eps,p.y,p.z))).x,
(grad(vec3(p.x,p.y-eps,p.z)) - grad(vec3(p.x,p.y+eps,p.z))).y,
(grad(vec3(p.x,p.y,p.z-eps)) - grad(vec3(p.x,p.y,p.z+eps)).z)
);
return d_grad / (2.*eps);
}
vec3 normal(vec3 p)
{
return normalize(grad(p));
}
vec4 raymarch(vec3 from, vec3 increment)
{
const float maxDist = 200.0;
const float minDist = 0.001;
const int maxIter = RAYMARCH_ITERATIONS;
float dist = 0.0;
float lastDistEval = 1e10;
float edge = 0.0;
for(int i = 0; i < maxIter; i++) {
vec3 pos = (from + increment * dist);
float distEval = distf(pos);
if (lastDistEval < EDGE_WIDTH && distEval > lastDistEval + 0.001) {
edge = 1.0;
}
if (distEval < minDist) {
break;
}
dist += distEval;
if (distEval < lastDistEval) lastDistEval = distEval;
}
float mat = 1.0;
if (dist >= maxDist) mat = 0.0;
return vec4(dist, mat, edge, 0);
}
float shadow(vec3 from, vec3 increment)
{
const float minDist = 1.0;
float res = 1.0;
float t = 1.0;
for(int i = 0; i < SHADOW_ITERATIONS; i++) {
float h = distf(from + increment * t);
if(h < minDist)
return 0.0;
res = min(res, SHADOW_SMOOTHNESS * h / t);
t += SHADOW_STEP;
}
return res;
}
float rand(float x)
{
return fract(sin(x) * 43758.5453);
}
float triangle(float x)
{
return abs(1.0 - mod(abs(x), 2.0)) * 2.0 - 1.0;
}
// Camera localized normal
vec3 campos, camup;
vec3 localNormal(vec3 p, vec3 rd) {
vec3 n = normal(p), ln;
vec3 side = cross(campos, camup);
return vec3(dot(n, side), dot(n, camup), dot(n, -rd));
}
float time;
vec4 getPixel(vec2 p, vec3 from, vec3 increment, vec3 light)
{
vec4 c = raymarch(from, increment);
vec3 hitPos = from + increment * c.x;
vec3 normalDir = normal(hitPos);
float diffuse = 1.0 + min(0.0, dot(normalDir, -light));
float inshadow = (1.0 - shadow(hitPos, -light)) * SHADOW_DARKNESS;
// diffuse = max(diffuse, inshadow);
// if it's not edge, and no contact
if (c.z != 1.0 && c.y == 0.0) return vec4(0.96, 0.94, 0.87,1);
float low = 0.05;
float high = 0.95;
diffuse = diffuse > high ? 1.0 : (diffuse > low ? low : diffuse);
vec4 mCol = mix(vec4(vec3(0.78, 0.76, 0.78) * 1.15,1), vec4(0.70, 0.68, 0.75,1), diffuse);
float gridStep = 1.0;
// optional chess style grid
// mCol = mix(mCol,vec4(0.,0.,0.,1.0),0.1*mod(floor(hitPos.x/gridStep)+floor(hitPos.y/gridStep)+floor(hitPos.z/gridStep),2.));
float dt = dot(vec3(0., 0., 1.), normalDir);
float eps_high = 0.02;
float eps_low = 0.00000; //1;
// vec3 n = vec4(normalDir, 0.).xyz;
vec3 n = localNormal(hitPos, increment); // grad(hitPos); // localNormal(hitPos, increment);
vec3 ez = vec3(0.,0.,0.1);
// https://www.shadertoy.com/view/fsGXzc
const float MAX_DIST = 200.0;
float depth = distance(from, hitPos); // /MAX_DIST;
// I've mostly just copied and pasted Evan's code.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Compute curvature
vec3 dx = dFdx(n);
vec3 dy = dFdy(n);
vec3 xneg = n - dx;
vec3 xpos = n + dx;
vec3 yneg = n - dy;
vec3 ypos = n + dy;
float curvature = (cross(xneg, xpos).y - cross(yneg, ypos).x) * 4.0 / (depth);
// curvature debug
// return vec4(vec3(1,0.9,0.8) * 0.7 * (abs(curvature) * 500.),1);
;
vec4 curve_color = vec4(mix(vec3(1,0.9,0.8) * 0.5, vec3(1.), 0.5), 1.); // * length(grad(hitPos).xy) // * abs(curvature) * 200.
float curvature_eps = 0.0001;
if(c.z != 1. && abs(curvature) > curvature_eps && length(grad(hitPos).z) > eps_low && ( length(grad(hitPos).z) < eps_high * abs(curvature) * 100. ) ) {
return curve_color;
}
if(c.z != 1. && abs(curvature) > curvature_eps && length(grad(hitPos).y) > eps_low && ( length(grad(hitPos).y) < eps_high * abs(curvature) * 100.) ) {
return curve_color;
}
if(c.z != 1. && abs(curvature) > curvature_eps && length(grad(hitPos).x) > eps_low && ( length(grad(hitPos).x) < eps_high * abs(curvature) * 100.) ) {
return curve_color;
}
if(c.z != 1. && length(grad(hitPos).z) > eps_low && ( length(grad(hitPos).z) < eps_high) ) {
// return vec4(mix(vec3(1,0.9,0.8) * 0.5, vec3(1.), 0.5), 1.); // * (abs(curvature) * 1000.),1);
}
// .z is edge
mCol = mix(mCol,vec4(vec3(1,0.9,0.8) * 0.5,1),c.z);
return mCol;
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
time = floor(iTime * 16.0) / 16.0;
// pixel position
vec2 q = fragCoord.xy / iResolution.xy;
vec2 p = -1.0+2.0*q;
p.x *= -iResolution.x/iResolution.y;
// mouse
vec2 mo = iMouse.xy/iResolution.xy;
vec2 m = iMouse.xy / iResolution.xy;
if (iMouse.x == 0.0 && iMouse.y == 0.0) {
m = vec2(time * 0.06 + 1.67, 0.78);
}
m = -1.0 + 2.0 * m;
m *= vec2(4.0,-0.75);
m.y += 0.75;
// camera position
float dist = 65.0;
vec3 ta = vec3(0,0,0);
vec3 ro = vec3(cos(m.x) * cos(m.y) * dist, sin(m.x) * cos(m.y) * dist, sin(m.y) * dist);
vec3 light = vec3(cos(m.x - 2.27) * 50.0, sin(m.x - 2.27) * 50.0, -20.0);
// camera direction
vec3 cw = normalize( ta-ro );
vec3 cp = vec3( 0.0, 0.0, 1.0 );
vec3 cu = normalize( cross(cw,cp) );
vec3 cv = normalize( cross(cu,cw) );
vec3 rd = normalize( p.x*cu + p.y*cv + 2.5*cw );
campos = -cw, camup = cv;
// calculate color
vec4 col = getPixel(p, ro, rd, normalize(light));
col = pow(col, vec4(1.0 / 2.2));
col = col * 1.8 - 0.8;
fragColor = col;
}
Color extracted with the help of ⧉.
See also: - toon shader - GLSL Fragment Shader: Sobel Edge Detection - Cross hatching WebGL shader - Penumbra Maps: Approximate Soft Shadows in Real-Time - stackgl/glsl-lighting-walkthrough
test Rhai scripting [uts-001P]
test Rhai scripting [uts-001P]
For now, open the console to see the output.
test Three.js and shaders [uts-0015]
test Three.js and shaders [uts-0015]
test ray-marching [uts-0016]
test ray-marching [uts-0016]
From ⧉:
float SDSphere(in vec3 worldCoordinate, in vec3 center, in float radius) {
return distance(worldCoordinate, center) - radius;
}
float SDPlane(in vec3 worldCoordinate, in float planeHeight, in vec3 rayDirection) {
return (worldCoordinate.y - planeHeight)/abs(rayDirection.y);
}
float SDOctahedron( vec3 p, float s)
{
p = abs(p);
return (p.x+p.y+p.z-s)*0.57735027;
}
float SDScene(in vec3 worldCoordinate, in vec3 rayDirection) {
float sphereOne = SDSphere(worldCoordinate, vec3(0.0, 0.0, 0.0), 0.5);
//float sphereTwo = SDSphere(worldCoordinate, vec3(cos(iTime/3.0), -0.3, sin(iTime/5.0)), 0.2);
//float sphereThree = SDSphere(worldCoordinate, vec3(sin(iTime/5.0), 0.3, cos(iTime/5.0)), 0.2);
float orbital = SDOctahedron(worldCoordinate - vec3(cos(iTime/2.0), -0.15, sin(iTime/2.0)), 0.2);
float groundPlane = SDPlane(worldCoordinate, -0.5, rayDirection);
return min(min(sphereOne, orbital), groundPlane);
}
# define EPSILON 0.001
vec3 estimateNormal(in vec3 worldCoordinate) {
if (worldCoordinate.y < -0.49) return vec3(0.0, 1.0, 0.0);
float partialX = SDScene(worldCoordinate + vec3(EPSILON, 0.0, 0.0), vec3(0.0, 0.0, 1.0)) - SDScene(worldCoordinate - vec3(EPSILON, 0.0, 0.0), vec3(0.0, 0.0, 1.0));
float partialY = SDScene(worldCoordinate + vec3(0.0, EPSILON, 0.0), vec3(0.0, 0.0, 1.0)) - SDScene(worldCoordinate - vec3(0.0, EPSILON, 0.0), vec3(0.0, 0.0, 1.0));
float partialZ = SDScene(worldCoordinate + vec3(0.0, 0.0, EPSILON), vec3(0.0, 0.0, 1.0)) - SDScene(worldCoordinate - vec3(0.0, 0.0, EPSILON), vec3(0.0, 0.0, 1.0));
return normalize(vec3(partialX, partialY, partialZ));
}
# define MAX_STEPS 105
vec3 rayMarch(in vec3 rayOrigin, in vec3 rayDirection) {
vec3 ray = rayOrigin;
for (int index = 0; index < MAX_STEPS; index++) {
float distanceToScene = SDScene(ray, rayDirection);
if (distanceToScene < EPSILON) return ray;
ray += distanceToScene * rayDirection;
}
return vec3(0.0, 0.0, 0.0);
}
void mainImage(out vec4 pixelColor, in vec2 pixelCoordinate) {
float aspect = iResolution.x/iResolution.y;
vec2 uv = pixelCoordinate/iResolution.xy;
uv -= vec2(0.5, 0.5);
uv *= 2.0 * vec2(aspect, 1.0);
vec3 observerPosition = vec3(0.0, 0.0, -5.0);
vec3 cameraBox = observerPosition + vec3(uv, 5.0);
vec3 rayDirection = normalize(cameraBox - observerPosition);
vec3 worldCoordinate = rayMarch(observerPosition, rayDirection);
float renderable = length(worldCoordinate) > 0.0 ? 1.0 : 0.0;
vec3 surfaceNormal = estimateNormal(worldCoordinate);
float fresnel = 0.9 + dot(surfaceNormal, rayDirection);
vec3 lightSource = vec3(7.0 * cos(iTime), 5.0, 7.0 * sin(iTime));
vec3 photonDirection = normalize(worldCoordinate - lightSource);
vec3 photonPosition = rayMarch(lightSource, photonDirection);
float directLight = 1.2 - step(0.01, distance(photonPosition, worldCoordinate));
float diffuseLight = 0.25 * smoothstep(0.0, 1.0, directLight * dot(surfaceNormal, -photonDirection));
float ambientLight = 0.7;
float specularLight = 0.1 * smoothstep(0.0, 1.0, dot(reflect(photonDirection, surfaceNormal), normalize(observerPosition - worldCoordinate)));
float scatterFactor = 1.0 / sqrt(distance(worldCoordinate, lightSource)/5.0);
pixelColor = vec4(renderable * (diffuseLight + ambientLight + specularLight) * scatterFactor * vec3(1.0, 1.0, 1.0), 1.0);
}
test shadertoy via react-three-fiber [uts-0017]
test shadertoy via react-three-fiber [uts-0017]
From ⧉:
#define AA 1
//------------------------------------------------------------------
float dot2( in vec2 v ) { return dot(v,v); }
float dot2( in vec3 v ) { return dot(v,v); }
float ndot( in vec2 a, in vec2 b ) { return a.x*b.x - a.y*b.y; }
float sdPlane( vec3 p )
{
return p.y;
}
float sdSphere( vec3 p, float s )
{
return length(p)-s;
}
float sdBox( vec3 p, vec3 b )
{
vec3 d = abs(p) - b;
return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0));
}
float sdBoxFrame( vec3 p, vec3 b, float e )
{
p = abs(p )-b;
vec3 q = abs(p+e)-e;
return min(min(
length(max(vec3(p.x,q.y,q.z),0.0))+min(max(p.x,max(q.y,q.z)),0.0),
length(max(vec3(q.x,p.y,q.z),0.0))+min(max(q.x,max(p.y,q.z)),0.0)),
length(max(vec3(q.x,q.y,p.z),0.0))+min(max(q.x,max(q.y,p.z)),0.0));
}
float sdEllipsoid( in vec3 p, in vec3 r ) // approximated
{
float k0 = length(p/r);
float k1 = length(p/(r*r));
return k0*(k0-1.0)/k1;
}
float sdTorus( vec3 p, vec2 t )
{
return length( vec2(length(p.xz)-t.x,p.y) )-t.y;
}
float sdCappedTorus(in vec3 p, in vec2 sc, in float ra, in float rb)
{
p.x = abs(p.x);
float k = (sc.y*p.x>sc.x*p.y) ? dot(p.xy,sc) : length(p.xy);
return sqrt( dot(p,p) + ra*ra - 2.0*ra*k ) - rb;
}
float sdHexPrism( vec3 p, vec2 h )
{
vec3 q = abs(p);
const vec3 k = vec3(-0.8660254, 0.5, 0.57735);
p = abs(p);
p.xy -= 2.0*min(dot(k.xy, p.xy), 0.0)*k.xy;
vec2 d = vec2(
length(p.xy - vec2(clamp(p.x, -k.z*h.x, k.z*h.x), h.x))*sign(p.y - h.x),
p.z-h.y );
return min(max(d.x,d.y),0.0) + length(max(d,0.0));
}
float sdOctogonPrism( in vec3 p, in float r, float h )
{
const vec3 k = vec3(-0.9238795325, // sqrt(2+sqrt(2))/2
0.3826834323, // sqrt(2-sqrt(2))/2
0.4142135623 ); // sqrt(2)-1
// reflections
p = abs(p);
p.xy -= 2.0*min(dot(vec2( k.x,k.y),p.xy),0.0)*vec2( k.x,k.y);
p.xy -= 2.0*min(dot(vec2(-k.x,k.y),p.xy),0.0)*vec2(-k.x,k.y);
// polygon side
p.xy -= vec2(clamp(p.x, -k.z*r, k.z*r), r);
vec2 d = vec2( length(p.xy)*sign(p.y), p.z-h );
return min(max(d.x,d.y),0.0) + length(max(d,0.0));
}
float sdCapsule( vec3 p, vec3 a, vec3 b, float r )
{
vec3 pa = p-a, ba = b-a;
float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
return length( pa - ba*h ) - r;
}
float sdRoundCone( in vec3 p, in float r1, float r2, float h )
{
vec2 q = vec2( length(p.xz), p.y );
float b = (r1-r2)/h;
float a = sqrt(1.0-b*b);
float k = dot(q,vec2(-b,a));
if( k < 0.0 ) return length(q) - r1;
if( k > a*h ) return length(q-vec2(0.0,h)) - r2;
return dot(q, vec2(a,b) ) - r1;
}
float sdRoundCone(vec3 p, vec3 a, vec3 b, float r1, float r2)
{
// sampling independent computations (only depend on shape)
vec3 ba = b - a;
float l2 = dot(ba,ba);
float rr = r1 - r2;
float a2 = l2 - rr*rr;
float il2 = 1.0/l2;
// sampling dependant computations
vec3 pa = p - a;
float y = dot(pa,ba);
float z = y - l2;
float x2 = dot2( pa*l2 - ba*y );
float y2 = y*y*l2;
float z2 = z*z*l2;
// single square root!
float k = sign(rr)*rr*rr*x2;
if( sign(z)*a2*z2 > k ) return sqrt(x2 + z2) *il2 - r2;
if( sign(y)*a2*y2 < k ) return sqrt(x2 + y2) *il2 - r1;
return (sqrt(x2*a2*il2)+y*rr)*il2 - r1;
}
float sdTriPrism( vec3 p, vec2 h )
{
const float k = sqrt(3.0);
h.x *= 0.5*k;
p.xy /= h.x;
p.x = abs(p.x) - 1.0;
p.y = p.y + 1.0/k;
if( p.x+k*p.y>0.0 ) p.xy=vec2(p.x-k*p.y,-k*p.x-p.y)/2.0;
p.x -= clamp( p.x, -2.0, 0.0 );
float d1 = length(p.xy)*sign(-p.y)*h.x;
float d2 = abs(p.z)-h.y;
return length(max(vec2(d1,d2),0.0)) + min(max(d1,d2), 0.);
}
// vertical
float sdCylinder( vec3 p, vec2 h )
{
vec2 d = abs(vec2(length(p.xz),p.y)) - h;
return min(max(d.x,d.y),0.0) + length(max(d,0.0));
}
// arbitrary orientation
float sdCylinder(vec3 p, vec3 a, vec3 b, float r)
{
vec3 pa = p - a;
vec3 ba = b - a;
float baba = dot(ba,ba);
float paba = dot(pa,ba);
float x = length(pa*baba-ba*paba) - r*baba;
float y = abs(paba-baba*0.5)-baba*0.5;
float x2 = x*x;
float y2 = y*y*baba;
float d = (max(x,y)<0.0)?-min(x2,y2):(((x>0.0)?x2:0.0)+((y>0.0)?y2:0.0));
return sign(d)*sqrt(abs(d))/baba;
}
// vertical
float sdCone( in vec3 p, in vec2 c, float h )
{
vec2 q = h*vec2(c.x,-c.y)/c.y;
vec2 w = vec2( length(p.xz), p.y );
vec2 a = w - q*clamp( dot(w,q)/dot(q,q), 0.0, 1.0 );
vec2 b = w - q*vec2( clamp( w.x/q.x, 0.0, 1.0 ), 1.0 );
float k = sign( q.y );
float d = min(dot( a, a ),dot(b, b));
float s = max( k*(w.x*q.y-w.y*q.x),k*(w.y-q.y) );
return sqrt(d)*sign(s);
}
float sdCappedCone( in vec3 p, in float h, in float r1, in float r2 )
{
vec2 q = vec2( length(p.xz), p.y );
vec2 k1 = vec2(r2,h);
vec2 k2 = vec2(r2-r1,2.0*h);
vec2 ca = vec2(q.x-min(q.x,(q.y < 0.0)?r1:r2), abs(q.y)-h);
vec2 cb = q - k1 + k2*clamp( dot(k1-q,k2)/dot2(k2), 0.0, 1.0 );
float s = (cb.x < 0.0 && ca.y < 0.0) ? -1.0 : 1.0;
return s*sqrt( min(dot2(ca),dot2(cb)) );
}
float sdCappedCone(vec3 p, vec3 a, vec3 b, float ra, float rb)
{
float rba = rb-ra;
float baba = dot(b-a,b-a);
float papa = dot(p-a,p-a);
float paba = dot(p-a,b-a)/baba;
float x = sqrt( papa - paba*paba*baba );
float cax = max(0.0,x-((paba<0.5)?ra:rb));
float cay = abs(paba-0.5)-0.5;
float k = rba*rba + baba;
float f = clamp( (rba*(x-ra)+paba*baba)/k, 0.0, 1.0 );
float cbx = x-ra - f*rba;
float cby = paba - f;
float s = (cbx < 0.0 && cay < 0.0) ? -1.0 : 1.0;
return s*sqrt( min(cax*cax + cay*cay*baba,
cbx*cbx + cby*cby*baba) );
}
// c is the sin/cos of the desired cone angle
float sdSolidAngle(vec3 pos, vec2 c, float ra)
{
vec2 p = vec2( length(pos.xz), pos.y );
float l = length(p) - ra;
float m = length(p - c*clamp(dot(p,c),0.0,ra) );
return max(l,m*sign(c.y*p.x-c.x*p.y));
}
float sdOctahedron(vec3 p, float s)
{
p = abs(p);
float m = p.x + p.y + p.z - s;
// exact distance
#if 0
vec3 o = min(3.0*p - m, 0.0);
o = max(6.0*p - m*2.0 - o*3.0 + (o.x+o.y+o.z), 0.0);
return length(p - s*o/(o.x+o.y+o.z));
#endif
// exact distance
#if 1
vec3 q;
if( 3.0*p.x < m ) q = p.xyz;
else if( 3.0*p.y < m ) q = p.yzx;
else if( 3.0*p.z < m ) q = p.zxy;
else return m*0.57735027;
float k = clamp(0.5*(q.z-q.y+s),0.0,s);
return length(vec3(q.x,q.y-s+k,q.z-k));
#endif
// bound, not exact
#if 0
return m*0.57735027;
#endif
}
float sdPyramid( in vec3 p, in float h )
{
float m2 = h*h + 0.25;
// symmetry
p.xz = abs(p.xz);
p.xz = (p.z>p.x) ? p.zx : p.xz;
p.xz -= 0.5;
// project into face plane (2D)
vec3 q = vec3( p.z, h*p.y - 0.5*p.x, h*p.x + 0.5*p.y);
float s = max(-q.x,0.0);
float t = clamp( (q.y-0.5*p.z)/(m2+0.25), 0.0, 1.0 );
float a = m2*(q.x+s)*(q.x+s) + q.y*q.y;
float b = m2*(q.x+0.5*t)*(q.x+0.5*t) + (q.y-m2*t)*(q.y-m2*t);
float d2 = min(q.y,-q.x*m2-q.y*0.5) > 0.0 ? 0.0 : min(a,b);
// recover 3D and scale, and add sign
return sqrt( (d2+q.z*q.z)/m2 ) * sign(max(q.z,-p.y));;
}
// la,lb=semi axis, h=height, ra=corner
float sdRhombus(vec3 p, float la, float lb, float h, float ra)
{
p = abs(p);
vec2 b = vec2(la,lb);
float f = clamp( (ndot(b,b-2.0*p.xz))/dot(b,b), -1.0, 1.0 );
vec2 q = vec2(length(p.xz-0.5*b*vec2(1.0-f,1.0+f))*sign(p.x*b.y+p.z*b.x-b.x*b.y)-ra, p.y-h);
return min(max(q.x,q.y),0.0) + length(max(q,0.0));
}
float sdHorseshoe( in vec3 p, in vec2 c, in float r, in float le, vec2 w )
{
p.x = abs(p.x);
float l = length(p.xy);
p.xy = mat2(-c.x, c.y,
c.y, c.x)*p.xy;
p.xy = vec2((p.y>0.0 || p.x>0.0)?p.x:l*sign(-c.x),
(p.x>0.0)?p.y:l );
p.xy = vec2(p.x,abs(p.y-r))-vec2(le,0.0);
vec2 q = vec2(length(max(p.xy,0.0)) + min(0.0,max(p.x,p.y)),p.z);
vec2 d = abs(q) - w;
return min(max(d.x,d.y),0.0) + length(max(d,0.0));
}
float sdU( in vec3 p, in float r, in float le, vec2 w )
{
p.x = (p.y>0.0) ? abs(p.x) : length(p.xy);
p.x = abs(p.x-r);
p.y = p.y - le;
float k = max(p.x,p.y);
vec2 q = vec2( (k<0.0) ? -k : length(max(p.xy,0.0)), abs(p.z) ) - w;
return length(max(q,0.0)) + min(max(q.x,q.y),0.0);
}
//------------------------------------------------------------------
vec2 opU( vec2 d1, vec2 d2 )
{
return (d1.x<d2.x) ? d1 : d2;
}
//------------------------------------------------------------------
#define ZERO (min(iFrame,0))
//------------------------------------------------------------------
vec2 map( in vec3 pos )
{
vec2 res = vec2( pos.y, 0.0 );
// bounding box
if( sdBox( pos-vec3(-2.0,0.3,0.25),vec3(0.3,0.3,1.0) )<res.x )
{
res = opU( res, vec2( sdSphere( pos-vec3(-2.0,0.25, 0.0), 0.25 ), 26.9 ) );
res = opU( res, vec2( sdRhombus( (pos-vec3(-2.0,0.25, 1.0)).xzy, 0.15, 0.25, 0.04, 0.08 ),17.0 ) );
}
// bounding box
if( sdBox( pos-vec3(0.0,0.3,-1.0),vec3(0.35,0.3,2.5) )<res.x )
{
res = opU( res, vec2( sdCappedTorus((pos-vec3( 0.0,0.30, 1.0))*vec3(1,-1,1), vec2(0.866025,-0.5), 0.25, 0.05), 25.0) );
res = opU( res, vec2( sdBoxFrame( pos-vec3( 0.0,0.25, 0.0), vec3(0.3,0.25,0.2), 0.025 ), 16.9 ) );
res = opU( res, vec2( sdCone( pos-vec3( 0.0,0.45,-1.0), vec2(0.6,0.8),0.45 ), 55.0 ) );
res = opU( res, vec2( sdCappedCone( pos-vec3( 0.0,0.25,-2.0), 0.25, 0.25, 0.1 ), 13.67 ) );
res = opU( res, vec2( sdSolidAngle( pos-vec3( 0.0,0.00,-3.0), vec2(3,4)/5.0, 0.4 ), 49.13 ) );
}
// bounding box
if( sdBox( pos-vec3(1.0,0.3,-1.0),vec3(0.35,0.3,2.5) )<res.x )
{
res = opU( res, vec2( sdTorus( (pos-vec3( 1.0,0.30, 1.0)).xzy, vec2(0.25,0.05) ), 7.1 ) );
res = opU( res, vec2( sdBox( pos-vec3( 1.0,0.25, 0.0), vec3(0.3,0.25,0.1) ), 3.0 ) );
res = opU( res, vec2( sdCapsule( pos-vec3( 1.0,0.00,-1.0),vec3(-0.1,0.1,-0.1), vec3(0.2,0.4,0.2), 0.1 ), 31.9 ) );
res = opU( res, vec2( sdCylinder( pos-vec3( 1.0,0.25,-2.0), vec2(0.15,0.25) ), 8.0 ) );
res = opU( res, vec2( sdHexPrism( pos-vec3( 1.0,0.2,-3.0), vec2(0.2,0.05) ), 18.4 ) );
}
// bounding box
if( sdBox( pos-vec3(-1.0,0.35,-1.0),vec3(0.35,0.35,2.5))<res.x )
{
res = opU( res, vec2( sdPyramid( pos-vec3(-1.0,-0.6,-3.0), 1.0 ), 13.56 ) );
res = opU( res, vec2( sdOctahedron( pos-vec3(-1.0,0.15,-2.0), 0.35 ), 23.56 ) );
res = opU( res, vec2( sdTriPrism( pos-vec3(-1.0,0.15,-1.0), vec2(0.3,0.05) ),43.5 ) );
res = opU( res, vec2( sdEllipsoid( pos-vec3(-1.0,0.25, 0.0), vec3(0.2, 0.25, 0.05) ), 43.17 ) );
res = opU( res, vec2( sdHorseshoe( pos-vec3(-1.0,0.25, 1.0), vec2(cos(1.3),sin(1.3)), 0.2, 0.3, vec2(0.03,0.08) ), 11.5 ) );
}
// bounding box
if( sdBox( pos-vec3(2.0,0.3,-1.0),vec3(0.35,0.3,2.5) )<res.x )
{
res = opU( res, vec2( sdOctogonPrism(pos-vec3( 2.0,0.2,-3.0), 0.2, 0.05), 51.8 ) );
res = opU( res, vec2( sdCylinder( pos-vec3( 2.0,0.14,-2.0), vec3(0.1,-0.1,0.0), vec3(-0.2,0.35,0.1), 0.08), 31.2 ) );
res = opU( res, vec2( sdCappedCone( pos-vec3( 2.0,0.09,-1.0), vec3(0.1,0.0,0.0), vec3(-0.2,0.40,0.1), 0.15, 0.05), 46.1 ) );
res = opU( res, vec2( sdRoundCone( pos-vec3( 2.0,0.15, 0.0), vec3(0.1,0.0,0.0), vec3(-0.1,0.35,0.1), 0.15, 0.05), 51.7 ) );
res = opU( res, vec2( sdRoundCone( pos-vec3( 2.0,0.20, 1.0), 0.2, 0.1, 0.3 ), 37.0 ) );
}
return res;
}
// https://iquilezles.org/articles/boxfunctions
vec2 iBox( in vec3 ro, in vec3 rd, in vec3 rad )
{
vec3 m = 1.0/rd;
vec3 n = m*ro;
vec3 k = abs(m)*rad;
vec3 t1 = -n - k;
vec3 t2 = -n + k;
return vec2( max( max( t1.x, t1.y ), t1.z ),
min( min( t2.x, t2.y ), t2.z ) );
}
vec2 raycast( in vec3 ro, in vec3 rd )
{
vec2 res = vec2(-1.0,-1.0);
float tmin = 1.0;
float tmax = 20.0;
// raytrace floor plane
float tp1 = (0.0-ro.y)/rd.y;
if( tp1>0.0 )
{
tmax = min( tmax, tp1 );
res = vec2( tp1, 1.0 );
}
//else return res;
// raymarch primitives
vec2 tb = iBox( ro-vec3(0.0,0.4,-0.5), rd, vec3(2.5,0.41,3.0) );
if( tb.x<tb.y && tb.y>0.0 && tb.x<tmax)
{
//return vec2(tb.x,2.0);
tmin = max(tb.x,tmin);
tmax = min(tb.y,tmax);
float t = tmin;
for( int i=0; i<70 && t<tmax; i++ )
{
vec2 h = map( ro+rd*t );
if( abs(h.x)<(0.0001*t) )
{
res = vec2(t,h.y);
break;
}
t += h.x;
}
}
return res;
}
// https://iquilezles.org/articles/rmshadows
float calcSoftshadow( in vec3 ro, in vec3 rd, in float mint, in float tmax )
{
// bounding volume
float tp = (0.8-ro.y)/rd.y; if( tp>0.0 ) tmax = min( tmax, tp );
float res = 1.0;
float t = mint;
for( int i=ZERO; i<24; i++ )
{
float h = map( ro + rd*t ).x;
float s = clamp(8.0*h/t,0.0,1.0);
res = min( res, s );
t += clamp( h, 0.01, 0.2 );
if( res<0.004 || t>tmax ) break;
}
res = clamp( res, 0.0, 1.0 );
return res*res*(3.0-2.0*res);
}
// https://iquilezles.org/articles/normalsSDF
vec3 calcNormal( in vec3 pos )
{
#if 0
vec2 e = vec2(1.0,-1.0)*0.5773*0.0005;
return normalize( e.xyy*map( pos + e.xyy ).x +
e.yyx*map( pos + e.yyx ).x +
e.yxy*map( pos + e.yxy ).x +
e.xxx*map( pos + e.xxx ).x );
#else
// inspired by tdhooper and klems - a way to prevent the compiler from inlining map() 4 times
vec3 n = vec3(0.0);
for( int i=ZERO; i<4; i++ )
{
vec3 e = 0.5773*(2.0*vec3((((i+3)>>1)&1),((i>>1)&1),(i&1))-1.0);
n += e*map(pos+0.0005*e).x;
//if( n.x+n.y+n.z>100.0 ) break;
}
return normalize(n);
#endif
}
// https://iquilezles.org/articles/nvscene2008/rwwtt.pdf
float calcAO( in vec3 pos, in vec3 nor )
{
float occ = 0.0;
float sca = 1.0;
for( int i=ZERO; i<5; i++ )
{
float h = 0.01 + 0.12*float(i)/4.0;
float d = map( pos + h*nor ).x;
occ += (h-d)*sca;
sca *= 0.95;
if( occ>0.35 ) break;
}
return clamp( 1.0 - 3.0*occ, 0.0, 1.0 ) * (0.5+0.5*nor.y);
}
// https://iquilezles.org/articles/checkerfiltering
float checkersGradBox( in vec2 p, in vec2 dpdx, in vec2 dpdy )
{
// filter kernel
vec2 w = abs(dpdx)+abs(dpdy) + 0.001;
// analytical integral (box filter)
vec2 i = 2.0*(abs(fract((p-0.5*w)*0.5)-0.5)-abs(fract((p+0.5*w)*0.5)-0.5))/w;
// xor pattern
return 0.5 - 0.5*i.x*i.y;
}
vec3 render( in vec3 ro, in vec3 rd, in vec3 rdx, in vec3 rdy )
{
// background
vec3 col = vec3(0.7, 0.7, 0.9) - max(rd.y,0.0)*0.3;
// raycast scene
vec2 res = raycast(ro,rd);
float t = res.x;
float m = res.y;
if( m>-0.5 )
{
vec3 pos = ro + t*rd;
vec3 nor = (m<1.5) ? vec3(0.0,1.0,0.0) : calcNormal( pos );
vec3 ref = reflect( rd, nor );
// material
col = 0.2 + 0.2*sin( m*2.0 + vec3(0.0,1.0,2.0) );
float ks = 1.0;
if( m<1.5 )
{
// project pixel footprint into the plane
vec3 dpdx = ro.y*(rd/rd.y-rdx/rdx.y);
vec3 dpdy = ro.y*(rd/rd.y-rdy/rdy.y);
float f = checkersGradBox( 3.0*pos.xz, 3.0*dpdx.xz, 3.0*dpdy.xz );
col = 0.15 + f*vec3(0.05);
ks = 0.4;
}
// lighting
float occ = calcAO( pos, nor );
vec3 lin = vec3(0.0);
// sun
{
vec3 lig = normalize( vec3(-0.5, 0.4, -0.6) );
vec3 hal = normalize( lig-rd );
float dif = clamp( dot( nor, lig ), 0.0, 1.0 );
//if( dif>0.0001 )
dif *= calcSoftshadow( pos, lig, 0.02, 2.5 );
float spe = pow( clamp( dot( nor, hal ), 0.0, 1.0 ),16.0);
spe *= dif;
spe *= 0.04+0.96*pow(clamp(1.0-dot(hal,lig),0.0,1.0),5.0);
//spe *= 0.04+0.96*pow(clamp(1.0-sqrt(0.5*(1.0-dot(rd,lig))),0.0,1.0),5.0);
lin += col*2.20*dif*vec3(1.30,1.00,0.70);
lin += 5.00*spe*vec3(1.30,1.00,0.70)*ks;
}
// sky
{
float dif = sqrt(clamp( 0.5+0.5*nor.y, 0.0, 1.0 ));
dif *= occ;
float spe = smoothstep( -0.2, 0.2, ref.y );
spe *= dif;
spe *= 0.04+0.96*pow(clamp(1.0+dot(nor,rd),0.0,1.0), 5.0 );
//if( spe>0.001 )
spe *= calcSoftshadow( pos, ref, 0.02, 2.5 );
lin += col*0.60*dif*vec3(0.40,0.60,1.15);
lin += 2.00*spe*vec3(0.40,0.60,1.30)*ks;
}
// back
{
float dif = clamp( dot( nor, normalize(vec3(0.5,0.0,0.6))), 0.0, 1.0 )*clamp( 1.0-pos.y,0.0,1.0);
dif *= occ;
lin += col*0.55*dif*vec3(0.25,0.25,0.25);
}
// sss
{
float dif = pow(clamp(1.0+dot(nor,rd),0.0,1.0),2.0);
dif *= occ;
lin += col*0.25*dif*vec3(1.00,1.00,1.00);
}
col = lin;
col = mix( col, vec3(0.7,0.7,0.9), 1.0-exp( -0.0001*t*t*t ) );
}
return vec3( clamp(col,0.0,1.0) );
}
mat3 setCamera( in vec3 ro, in vec3 ta, float cr )
{
vec3 cw = normalize(ta-ro);
vec3 cp = vec3(sin(cr), cos(cr),0.0);
vec3 cu = normalize( cross(cw,cp) );
vec3 cv = ( cross(cu,cw) );
return mat3( cu, cv, cw );
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 mo = iMouse.xy/iResolution.xy;
float time = 32.0 + iTime*1.5;
// camera
vec3 ta = vec3( 0.25, -0.75, -0.75 );
vec3 ro = ta + vec3( 4.5*cos(0.1*time + 7.0*mo.x), 2.2, 4.5*sin(0.1*time + 7.0*mo.x) );
// camera-to-world transformation
mat3 ca = setCamera( ro, ta, 0.0 );
vec3 tot = vec3(0.0);
#if AA>1
for( int m=ZERO; m<AA; m++ )
for( int n=ZERO; n<AA; n++ )
{
// pixel coordinates
vec2 o = vec2(float(m),float(n)) / float(AA) - 0.5;
vec2 p = (2.0*(fragCoord+o)-iResolution.xy)/iResolution.y;
#else
vec2 p = (2.0*fragCoord-iResolution.xy)/iResolution.y;
#endif
// focal length
const float fl = 2.5;
// ray direction
vec3 rd = ca * normalize( vec3(p,fl) );
// ray differentials
vec2 px = (2.0*(fragCoord+vec2(1.0,0.0))-iResolution.xy)/iResolution.y;
vec2 py = (2.0*(fragCoord+vec2(0.0,1.0))-iResolution.xy)/iResolution.y;
vec3 rdx = ca * normalize( vec3(px,fl) );
vec3 rdy = ca * normalize( vec3(py,fl) );
// render
vec3 col = render( ro, rd, rdx, rdy );
// gain
// col = col*3.0/(2.5+col);
// gamma
col = pow( col, vec3(0.4545) );
tot += col;
#if AA>1
}
tot /= float(AA*AA);
#endif
fragColor = vec4( tot, 1.0 );
}
test interactions between ray-marching and 3D objects [uts-000L]
test interactions between ray-marching and 3D objects [uts-000L]
The following renders texts and a ray-marching fragment shader on a plane which always faces the camera, the cubes are outside the plane.
test implicit surface shader 1
test implicit surface shader 1
Figure. Implicit surfaces [uts-000J]
Figure. Implicit surfaces [uts-000J]
#define AS_LIB 1
int get_shape() {
return int(iTime) % 52;
}
#include "/forest/shader/implicit.glsl"
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = 2.*(fragCoord-iResolution.xy/2.)/iResolution.y; // contains [-1,1]^2
vec3 col = vec3(0.);
// Camera rays
vec3 camPos = vec3(4.,0.,0.);
vec3 camDir = - normalize(camPos);
vec3 rayPos, rayDir;
float zoom = 1.3; // 1.8*cos(iTime);
// if (checkKey(KEY_E)) zoom = 0.5;
float fov = 0.4*zoom;
float fov_ortho = 1.5*zoom;
#if perspective
// perspective cam
rayPos = camPos;
rayDir = normalize(camDir + fov*vec3(0., uv.x, uv.y));
#else
// orthographic cam
rayPos = camPos + fov_ortho*vec3(0., uv.x, uv.y);
rayDir = camDir;
#endif
// for perspective background in orthographic mode
vec3 cubemapDir = normalize(camDir + fov*vec3(0., uv.x, uv.y));
// Mouse-controlled rotation
vec2 mouse = initMouse + vec2(0.015625*sin(iTime*PI), 0.0); // initMouse; // iMouse.xy == vec2(0.,0.) ? initMouse : (iMouse.xy/iResolution.xy - 0.5);
float yaw = clamp(- mouse.x * 2.*PI * 1., -PI,PI);
float pitch = clamp( mouse.y * PI * 1.2, -PI*0.5, PI*0.5);
// pitch and yaw rotations (column-wise matrices)
mat3 rot = mat3(cos(yaw), sin(yaw), 0., -sin(yaw), cos(yaw), 0., 0., 0., 1.);
rot = rot * mat3(cos(pitch), 0., -sin(pitch), 0., 1., 0., sin(pitch), 0., cos(pitch));
// apply
camPos = rot*camPos;
camDir = rot*camDir;
rayPos = rot*rayPos;
rayDir = rot*rayDir;
cubemapDir = rot*cubemapDir;
//cubemapDir = vec3(cubemapDir.x, cubemapDir.z, cubemapDir.y);
vec3 hitPoint = raycast(rayPos, rayDir);
if (hitPoint == BINGO) { fragColor = vec4(BINGO,1.0); return; }
//if (hitPoint == NOHIT) { fragColor = vec4(NOHIT,1.0); return; }
//if (hitPoint == NOBOUNDHIT) { fragColor = vec4(NOBOUNDHIT,1.0); return; }
//if (hitPoint == ESCAPEDBOUNDS) { fragColor = vec4(ESCAPEDBOUNDS,1.0); return; }
//if (hitPoint == MAXDISTREACHED) { fragColor = vec4(MAXDISTREACHED,1.0); return; }
//if (hitPoint == MAXITERREACHED) { fragColor = vec4(MAXITERREACHED,1.0); return; }
if (hitPoint == NOBOUNDHIT || hitPoint == NOHIT || hitPoint == ESCAPEDBOUNDS || hitPoint == MAXITERREACHED) {
//fragColor = vec4(vec3(0.2),1.0); return;
// make background transparent
fragColor = vec4(0.0,0.0,0.0,0.0); return;
col = with_background(cubemapDir);
#if showBoundingCube
// darken bounding cube
if (hitPoint != NOBOUNDHIT) { col *= vec3(0.7); }
#endif
fragColor = vec4(col,1.0); return;
}
vec3 grad = gradf(hitPoint+1.1*EPS*(-rayDir));
float s = -sign(dot(grad,rayDir));
col = with_color_mode(grad, s, hitPoint, camPos);
col = clamp(col, 0., 1.);
col = with_surface_pattern(col, hitPoint);
col = with_shading(col, grad, s, rayDir);
col = clamp(col, 0., 1.);
fragColor = vec4(col,1.0);
}
test implicit surface shader 2 [uts-000K]
test implicit surface shader 2 [uts-000K]
// Adapted from https://lygia.xyz/lighting/raymarch
#define LIGHT_COLOR vec3(1.000,0.794,0.066)
#define RESOLUTION iResolution.xy
#define RAYMARCH_MULTISAMPLE 4
// #define RAYMARCH_BACKGROUND (RAYMARCH_AMBIENT + rayDirection.y * 0.8)
#define RAYMARCH_BACKGROUND vec3(1.0, 1.0, 1.0)
#define RAYMARCH_AMBIENT vec3(1.0, 1.0, 1.0)
// #define RAYMARCH_AMBIENT vec3(0.7, 0.9, 1.0)
// #define RAYMARCH_AMBIENT vec3(0.374,0.481,0.535)
#define EPSILON 0.0001
#include "lygia/space/ratio.glsl"
#include "lygia/sdf.glsl"
#include "lygia/lighting/raymarch.glsl"
#include "lygia/color/space/linear2gamma.glsl"
float checkBoard(vec2 uv, vec2 _scale) {
uv = floor(fract(uv * _scale) * 2.0);
return min(1.0, uv.x + uv.y) - (uv.x * uv.y);
}
float myCubeSDF(vec3 p) {
float x = p.x;
float y = p.y;
float z = p.z;
float x6 = pow(x, 6.);
float y6 = pow(y, 6.);
float z6 = pow(z, 6.);
return x6+y6+z6-1.;
}
float mySDF2(vec3 p) {
float x = p.x;
float y = p.y;
float z = p.z;
float x2 = pow(x, 2.);
float y2 = pow(y, 2.);
float z2 = pow(z, 2.);
float x3 = pow(x, 3.);
float y3 = pow(y, 3.);
float z3 = pow(z, 3.);
float x4 = pow(x, 4.);
float y4 = pow(y, 4.);
float z4 = pow(z, 4.);
// return (y-x2)*(z-x3);
// return 5.*(z2+y3-y4-x2*y2);
// return (y2-x2-z2);
return (x2-z2*y2+y3);
}
float tapping_abs(float x) {
return max(-0.01 * x, x);
}
Material raymarchMap( in vec3 pos ) {
// float check = 0.5 + checkBoard(pos.xz, vec2(1.0, 1.0)) * 0.5;
// Material res = materialNew(vec3(check), 0.0, 0.5, planeSDF(pos - vec3(0.0, -2.0, 0.0)));
// res = opUnion( res, materialNew( vec3(1.0, 2.0, 1.0), myCubeSDF(pos - vec3(0.0, -1.0, 0.0))*0.004 ) );
// res = opUnion( res, materialNew( vec3(1.0, 2.0, 1.0),opIntersection(0.004 * myCubeSDF(pos), cubeSDF(pos, 1.0))) );
// res = opUnion(res, materialNew( vec3(1.0, 2.0, 1.0), 0.004 * abs(mySDF2(pos))));
// res = opUnion(res, materialNew( vec3(1.0, 2.0, 1.0), opIntersection(0.05 * abs(mySDF2(pos)), cubeSDF(pos, 1.0))) );
Material res = materialNew( vec3(1.0, 2.0, 1.0), opIntersection(0.05 * abs(mySDF2(pos)), sphereSDF(pos, 1.8)));
// res = opUnion( res, materialNew( vec3(1.0, 1.0, 1.0), 1.0, 0.0, sphereSDF(pos-vec3( 0.0, 2.0, 0.0), 0.5 ) ) );
// res = opUnion( res, materialNew( vec3(0.0, 1.0, 1.0), boxSDF( pos-vec3( 2.0, 0.5, 0.0), vec3(0.4, 0.4, 0.4) ) ) );
// res = opUnion( res, materialNew( vec3(0.3, 0.3, 1.0), torusSDF( pos-vec3( 0.0, 0.5, 2.0), vec2(0.4,0.1) ) ) );
// res = opUnion( res, materialNew( vec3(0.3, 0.1, 0.3), capsuleSDF( pos,vec3(-2.3, 0.4,-0.2), vec3(-1.6,0.75,0.2), 0.2 ) ) );
// res = opUnion( res, materialNew( vec3(0.5, 0.3, 0.4), triPrismSDF( pos-vec3(-2.0, 0.50,-2.0), vec2(0.5,0.1) ) ) );
// res = opUnion( res, materialNew( vec3(0.2, 0.2, 0.8), cylinderSDF( pos-vec3( 2.0, 0.50,-2.0), vec2(0.2,0.4) ) ) );
// res = opUnion( res, materialNew( vec3(0.7, 0.5, 0.2), coneSDF( pos-vec3( 0.0, 0.75,-2.0), vec3(0.8,0.6,0.6) ) ) );
// res = opUnion( res, materialNew( vec3(0.4, 0.2, 0.9), hexPrismSDF( pos-vec3(-2.0, 0.60, 2.0), vec2(0.5,0.1) ) ) );
// res = opUnion( res, materialNew( vec3(0.1, 0.3, 0.6), pyramidSDF( pos-vec3( 2.0, 0.10, 2.0), 1.0 ) ) );;
return res;
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 u_resolution = iResolution.xy;
vec2 u_mouse = iMouse.xy;
float u_time = iTime;
vec3 color = vec3(0.0);
vec2 pixel = 1.0/u_resolution;
vec2 st = fragCoord.xy * pixel;
vec2 uv = ratio(st, u_resolution);
vec2 mo = u_mouse * pixel;
float time = 32.0 + u_time * 1.5;
// vec3 cam = vec3( 12.5*cos(0.1*time), 2.2, 12.5*sin(0.1*time) );
// vec3 cam = vec3( 8.5*cos(0.1*time - 7.0*mo.x), 2.2, 8.5*sin(0.1*time - 7.0*mo.x) );
const vec2 initMouse = vec2(0.2, -0.1);
vec2 mouse = initMouse + vec2(0.035625*sin(u_time*PI), 0.0); // initMouse; // iMouse.xy == vec2(0.,0.) ? initMouse : (iMouse.xy/iResolution.xy - 0.5);
float pitch = clamp(- mouse.x * 2.*PI * 1., -PI,PI);
float yaw = clamp( mouse.y * PI * 1.2, -PI*0.5, PI*0.5);
// pitch and yaw rotations (column-wise matrices)
mat3 rot = mat3(cos(yaw), sin(yaw), 0., -sin(yaw), cos(yaw), 0., 0., 0., 1.);
rot = rot * mat3(cos(pitch), 0., -sin(pitch), 0., 1., 0., sin(pitch), 0., cos(pitch));
vec3 camPos = 0.8*vec3(-4., 2.2, -2.);
// apply
vec3 cam = rot*camPos;
color = raymarch(cam, vec3(0.0), uv).rgb;
color = linear2gamma(color);
// if color is almost white, make it transparent
// if (color.r > 0.99 && color.g > 0.99 && color.b > 0.99) {
// fragColor = vec4(0.0,0.0,0.0,0.0);
// } else {
fragColor = vec4( color, 1.0 );
// }
}
test Keenan Crane's style for rendering edge and shade [uts-001D]
test Keenan Crane's style for rendering edge and shade [uts-001D]
Adapted from ⧉:
#define EDGE_WIDTH 0.12
#define RAYMARCH_ITERATIONS 35
#define SHADOW_ITERATIONS 40
#define SHADOW_STEP 1.0
#define SHADOW_SMOOTHNESS 256.0
#define SHADOW_DARKNESS 0.75
// Distance functions from iquilezles.org
float fSubtraction(float a, float b) {return max(-a,b);}
float fIntersection(float d1, float d2) {return max(d1,d2);}
void fUnion(inout float d1, float d2) {d1 = min(d1,d2);}
float pSphere(vec3 p, float s) {return length(p)-s;}
float pRoundBox(vec3 p, vec3 b, float r) {return length(max(abs(p)-b,0.0))-r;}
float pTorus(vec3 p, vec2 t) {vec2 q = vec2(length(p.xz)-t.x,p.y); return length(q)-t.y;}
float pTorus2(vec3 p, vec2 t) {vec2 q = vec2(length(p.xy)-t.x,p.z); return length(q)-t.y;}
float pCapsule(vec3 p, vec3 a, vec3 b, float r) {vec3 pa = p - a, ba = b - a;
float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 ); return length( pa - ba*h ) - r;}
float mySDF(vec3 p) {
float x = p.x;
float y = p.y;
float z = p.z;
float x2 = pow(x, 2.);
float y2 = pow(y, 2.);
float z2 = pow(z, 2.);
float x3 = pow(x, 3.);
float y3 = pow(y, 3.);
float z3 = pow(z, 3.);
float x4 = pow(x, 4.);
float y4 = pow(y, 4.);
float z4 = pow(z, 4.);
// return (y-x2)*(z-x3);
// return 5.*(z2+y3-y4-x2*y2);
// return (y2-x2-z2);
return (x2-z2*y2+y3);
}
float distf(vec3 p)
{
float d = 100000.0;
fUnion(d, pRoundBox(vec3(0,0,10) + p, vec3(21,21,1), 1.0));
fUnion(d, pSphere(vec3(10,10,0) + p, 8.0));
fUnion(d, pSphere(vec3(16,0,4) + p, 4.0));
fUnion(d, pCapsule(p, vec3(10,10,12), vec3(15,15,-6.5), 1.5));
fUnion(d, pCapsule(p, vec3(10,10,12), vec3(5,15,-6.5), 1.5));
fUnion(d, pCapsule(p, vec3(10,10,12), vec3(10,5,-6.5), 1.5));
fUnion(d, pTorus(vec3(15,-15,0) + p, vec2(6,2)));
fUnion(d, pTorus2(vec3(10,-15,0) + p, vec2(6,2)));
fUnion(d, pRoundBox(vec3(-10,10,-2) + p, vec3(1,1,9), 1.0));
fUnion(d, pRoundBox(vec3(-10,10,-4) + p, vec3(0.5,6,0.5), 1.0));
fUnion(d, pRoundBox(vec3(-10,10,2) + p, vec3(6,0.5,0.5), 1.0));
// d = mySDF(p);
// d = fIntersection(d, pSphere(p,15.0));
return d;
}
vec3 grad(vec3 p)
{
const float eps = 0.01;
float m;
vec3 d_distf = vec3( (distf(vec3(p.x-eps,p.y,p.z)) - distf(vec3(p.x+eps,p.y,p.z))),
(distf(vec3(p.x,p.y-eps,p.z)) - distf(vec3(p.x,p.y+eps,p.z))),
(distf(vec3(p.x,p.y,p.z-eps)) - distf(vec3(p.x,p.y,p.z+eps)))
);
return d_distf / (2.*eps);
}
vec3 grad2(vec3 p)
{
const float eps = 0.01;
float m;
vec3 d_grad = vec3( (grad(vec3(p.x-eps,p.y,p.z)) - grad(vec3(p.x+eps,p.y,p.z))).x,
(grad(vec3(p.x,p.y-eps,p.z)) - grad(vec3(p.x,p.y+eps,p.z))).y,
(grad(vec3(p.x,p.y,p.z-eps)) - grad(vec3(p.x,p.y,p.z+eps)).z)
);
return d_grad / (2.*eps);
}
vec3 normal(vec3 p)
{
return normalize(grad(p));
}
vec4 raymarch(vec3 from, vec3 increment)
{
const float maxDist = 200.0;
const float minDist = 0.001;
const int maxIter = RAYMARCH_ITERATIONS;
float dist = 0.0;
float lastDistEval = 1e10;
float edge = 0.0;
for(int i = 0; i < maxIter; i++) {
vec3 pos = (from + increment * dist);
float distEval = distf(pos);
if (lastDistEval < EDGE_WIDTH && distEval > lastDistEval + 0.001) {
edge = 1.0;
}
if (distEval < minDist) {
break;
}
dist += distEval;
if (distEval < lastDistEval) lastDistEval = distEval;
}
float mat = 1.0;
if (dist >= maxDist) mat = 0.0;
return vec4(dist, mat, edge, 0);
}
float shadow(vec3 from, vec3 increment)
{
const float minDist = 1.0;
float res = 1.0;
float t = 1.0;
for(int i = 0; i < SHADOW_ITERATIONS; i++) {
float h = distf(from + increment * t);
if(h < minDist)
return 0.0;
res = min(res, SHADOW_SMOOTHNESS * h / t);
t += SHADOW_STEP;
}
return res;
}
float rand(float x)
{
return fract(sin(x) * 43758.5453);
}
float triangle(float x)
{
return abs(1.0 - mod(abs(x), 2.0)) * 2.0 - 1.0;
}
// Camera localized normal
vec3 campos, camup;
vec3 localNormal(vec3 p, vec3 rd) {
vec3 n = normal(p), ln;
vec3 side = cross(campos, camup);
return vec3(dot(n, side), dot(n, camup), dot(n, -rd));
}
float time;
vec4 getPixel(vec2 p, vec3 from, vec3 increment, vec3 light)
{
vec4 c = raymarch(from, increment);
vec3 hitPos = from + increment * c.x;
vec3 normalDir = normal(hitPos);
float diffuse = 1.0 + min(0.0, dot(normalDir, -light));
float inshadow = (1.0 - shadow(hitPos, -light)) * SHADOW_DARKNESS;
// diffuse = max(diffuse, inshadow);
// if it's not edge, and no contact
if (c.z != 1.0 && c.y == 0.0) return vec4(0.96, 0.94, 0.87,1);
float low = 0.05;
float high = 0.95;
diffuse = diffuse > high ? 1.0 : (diffuse > low ? low : diffuse);
vec4 mCol = mix(vec4(vec3(0.78, 0.76, 0.78) * 1.15,1), vec4(0.70, 0.68, 0.75,1), diffuse);
float gridStep = 1.0;
// optional chess style grid
// mCol = mix(mCol,vec4(0.,0.,0.,1.0),0.1*mod(floor(hitPos.x/gridStep)+floor(hitPos.y/gridStep)+floor(hitPos.z/gridStep),2.));
float dt = dot(vec3(0., 0., 1.), normalDir);
float eps_high = 0.02;
float eps_low = 0.00000; //1;
// vec3 n = vec4(normalDir, 0.).xyz;
vec3 n = localNormal(hitPos, increment); // grad(hitPos); // localNormal(hitPos, increment);
vec3 ez = vec3(0.,0.,0.1);
// https://www.shadertoy.com/view/fsGXzc
const float MAX_DIST = 200.0;
float depth = distance(from, hitPos); // /MAX_DIST;
// I've mostly just copied and pasted Evan's code.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Compute curvature
vec3 dx = dFdx(n);
vec3 dy = dFdy(n);
vec3 xneg = n - dx;
vec3 xpos = n + dx;
vec3 yneg = n - dy;
vec3 ypos = n + dy;
float curvature = (cross(xneg, xpos).y - cross(yneg, ypos).x) * 4.0 / (depth);
// curvature debug
// return vec4(vec3(1,0.9,0.8) * 0.7 * (abs(curvature) * 500.),1);
;
vec4 curve_color = vec4(mix(vec3(1,0.9,0.8) * 0.5, vec3(1.), 0.5), 1.); // * length(grad(hitPos).xy) // * abs(curvature) * 200.
float curvature_eps = 0.0001;
if(c.z != 1. && abs(curvature) > curvature_eps && length(grad(hitPos).z) > eps_low && ( length(grad(hitPos).z) < eps_high * abs(curvature) * 100. ) ) {
return curve_color;
}
if(c.z != 1. && abs(curvature) > curvature_eps && length(grad(hitPos).y) > eps_low && ( length(grad(hitPos).y) < eps_high * abs(curvature) * 100.) ) {
return curve_color;
}
if(c.z != 1. && abs(curvature) > curvature_eps && length(grad(hitPos).x) > eps_low && ( length(grad(hitPos).x) < eps_high * abs(curvature) * 100.) ) {
return curve_color;
}
if(c.z != 1. && length(grad(hitPos).z) > eps_low && ( length(grad(hitPos).z) < eps_high) ) {
// return vec4(mix(vec3(1,0.9,0.8) * 0.5, vec3(1.), 0.5), 1.); // * (abs(curvature) * 1000.),1);
}
// .z is edge
mCol = mix(mCol,vec4(vec3(1,0.9,0.8) * 0.5,1),c.z);
return mCol;
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
time = floor(iTime * 16.0) / 16.0;
// pixel position
vec2 q = fragCoord.xy / iResolution.xy;
vec2 p = -1.0+2.0*q;
p.x *= -iResolution.x/iResolution.y;
// mouse
vec2 mo = iMouse.xy/iResolution.xy;
vec2 m = iMouse.xy / iResolution.xy;
if (iMouse.x == 0.0 && iMouse.y == 0.0) {
m = vec2(time * 0.06 + 1.67, 0.78);
}
m = -1.0 + 2.0 * m;
m *= vec2(4.0,-0.75);
m.y += 0.75;
// camera position
float dist = 65.0;
vec3 ta = vec3(0,0,0);
vec3 ro = vec3(cos(m.x) * cos(m.y) * dist, sin(m.x) * cos(m.y) * dist, sin(m.y) * dist);
vec3 light = vec3(cos(m.x - 2.27) * 50.0, sin(m.x - 2.27) * 50.0, -20.0);
// camera direction
vec3 cw = normalize( ta-ro );
vec3 cp = vec3( 0.0, 0.0, 1.0 );
vec3 cu = normalize( cross(cw,cp) );
vec3 cv = normalize( cross(cu,cw) );
vec3 rd = normalize( p.x*cu + p.y*cv + 2.5*cw );
campos = -cw, camup = cv;
// calculate color
vec4 col = getPixel(p, ro, rd, normalize(light));
col = pow(col, vec4(1.0 / 2.2));
col = col * 1.8 - 0.8;
fragColor = col;
}
Color extracted with the help of ⧉.
See also: - toon shader - GLSL Fragment Shader: Sobel Edge Detection - Cross hatching WebGL shader - Penumbra Maps: Approximate Soft Shadows in Real-Time - stackgl/glsl-lighting-walkthrough
test compute shaders [uts-001E]
test compute shaders [uts-001E]
test Use.GPU [uts-0019]
test Use.GPU [uts-0019]
This is an initial test for Use.GPU:
test compute.toys [uts-001B]
test compute.toys [uts-001B]
Adapted from ⧉:
@compute @workgroup_size(16, 16)
fn main_image(@builtin(global_invocation_id) id: vec3u) {
// Viewport resolution (in pixels)
let screen_size = textureDimensions(screen);
// Prevent overdraw for workgroups on the edge of the viewport
if (id.x >= screen_size.x || id.y >= screen_size.y) { return; }
// Pixel coordinates (centre of pixel, origin at bottom left)
let fragCoord = vec2f(f32(id.x) + .5, f32(screen_size.y - id.y) - .5);
// Normalised pixel coordinates (from 0 to 1)
let uv = fragCoord / vec2f(screen_size);
// Time varying pixel colour
var col = .5 + .5 * cos(time.elapsed + uv.xyx + vec3f(0.,2.,4.));
// Convert from gamma-encoded to linear colour space
col = pow(col, vec3f(2.2));
// Output to screen (linear colour space)
textureStore(screen, id.xy, vec4f(col, 1.));
}
test d3-graphviz [uts-001Q]
test d3-graphviz [uts-001Q]
Same as test graphviz, but with d3-graphviz. There is no obvious difference as zooming and panning are disabled to avoid distraction.
Adapted from ⧉:
Adapted from ⧉:
Adapted from ⧉:
The same, but randomly choose a layout from one of 'circo', 'dot', 'fdp', 'sfdp', 'neato', 'osage', 'patchwork', 'twopi':
test egglog [uts-001I]
test egglog [uts-001I]
For now, open the console to see the output.
test graphviz [uts-001L]
test graphviz [uts-001L]
Adapted from ⧉:
Adapted from ⧉:
Adapted from ⧉:
The same, but randomly choose a layout from one of 'circo', 'dot', 'fdp', 'sfdp', 'neato', 'osage', 'patchwork', 'twopi':
test markdownit [uts-000M]
test markdownit [uts-000M]
We test hybrid markdown with forester markup:
We wish to use - external link: markdown-it demo - wiki link: test tikz drawing - citations: [nakahira2023diagrammatic] - cross-references: § [uts-000E]
The following tests a raw markdown-it renderer with no plugins, adapted from markdown-it demo:
# h1 Heading 8-)
## h2 Heading
### h3 Heading
#### h4 Heading
##### h5 Heading
###### h6 Heading
## Horizontal Rules
___
---
***
## Typographic replacements
Enable typographer option to see result.
(c) (C) (r) (R) (tm) (TM) (p) (P) +-
test.. test... test..... test?..... test!....
!!!!!! ???? ,, -- ---
"Smartypants, double quotes" and 'single quotes'
## Emphasis
**This is bold text**
__This is bold text__
*This is italic text*
_This is italic text_
~~Strikethrough~~
## Blockquotes
> Blockquotes can also be nested...
>> ...by using additional greater-than signs right next to each other...
> > > ...or with spaces between arrows.
## Lists
Unordered
+ Create a list by starting a line with `+`, `-`, or `*`
+ Sub-lists are made by indenting 2 spaces:
- Marker character change forces new list start:
* Ac tristique libero volutpat at
+ Facilisis in pretium nisl aliquet
- Nulla volutpat aliquam velit
+ Very easy!
Ordered
1. Lorem ipsum dolor sit amet
2. Consectetur adipiscing elit
3. Integer molestie lorem at massa
1. You can use sequential numbers...
1. ...or keep all the numbers as `1.`
Start numbering with offset:
57. foo
1. bar
## Code
Inline `code`
Indented code
// Some comments
line 1 of code
line 2 of code
line 3 of code
Block code "fences"
```
Sample text here...
```
Syntax highlighting
``` js
var foo = function (bar) {
return bar++;
};
console.log(foo(5));
```
## Tables
| Option | Description |
| ------ | ----------- |
| data | path to data files to supply the data that will be passed into templates. |
| engine | engine to be used for processing templates. Handlebars is the default. |
| ext | extension to be used for dest files. |
Right aligned columns
| Option | Description |
| ------:| -----------:|
| data | path to data files to supply the data that will be passed into templates. |
| engine | engine to be used for processing templates. Handlebars is the default. |
| ext | extension to be used for dest files. |
## Links
[link text](http://dev.nodeca.com)
[link with title](http://nodeca.github.io/pica/demo/ "title text!")
Autoconverted link https://github.com/nodeca/pica (enable linkify to see)
## Images


Like links, Images also have a footnote style syntax
![Alt text][id]
With a reference later in the document defining the URL location:
[id]: https://octodex.github.com/images/dojocat.jpg "The Dojocat"
## Plugins
The killer feature of `markdown-it` is very effective support of
[syntax plugins](https://www.npmjs.org/browse/keyword/markdown-it-plugin).
### [Emojies](https://github.com/markdown-it/markdown-it-emoji)
> Classic markup: :wink: :cry: :laughing: :yum:
>
> Shortcuts (emoticons): :-) :-( 8-) ;)
see [how to change output](https://github.com/markdown-it/markdown-it-emoji#change-output) with twemoji.
### [Subscript](https://github.com/markdown-it/markdown-it-sub) / [Superscript](https://github.com/markdown-it/markdown-it-sup)
- 19^th^
- H~2~O
### [\<ins>](https://github.com/markdown-it/markdown-it-ins)
++Inserted text++
### [\<mark>](https://github.com/markdown-it/markdown-it-mark)
==Marked text==
### [Footnotes](https://github.com/markdown-it/markdown-it-footnote)
Footnote 1 link[^first].
Footnote 2 link[^second].
Inline footnote^[Text of inline footnote] definition.
Duplicated footnote reference[^second].
[^first]: Footnote **can have markup**
and multiple paragraphs.
[^second]: Footnote text.
### [Definition lists](https://github.com/markdown-it/markdown-it-deflist)
Term 1
: Definition 1
with lazy continuation.
Term 2 with *inline markup*
: Definition 2
{ some code, part of Definition 2 }
Third paragraph of definition 2.
_Compact style:_
Term 1
~ Definition 1
Term 2
~ Definition 2a
~ Definition 2b
### [Abbreviations](https://github.com/markdown-it/markdown-it-abbr)
This is HTML abbreviation example.
It converts "HTML", but keep intact partial entries like "xxxHTMLyyy" and so on.
*[HTML]: Hyper Text Markup Language
### [Custom containers](https://github.com/markdown-it/markdown-it-container)
::: warning
*here be dragons*
:::
test markmap [uts-016G]
test markmap [uts-016G]
The following example is adapted from markmap: Try it out.
test mermaid [uts-016F]
test mermaid [uts-016F]
We test hybrid markdown with forester markup and mermaid diagrams.
They should render to a mermaid diagram or fail gracefully as the mermaid source code.
The following examples are taken from various DeepWiki generated by AI or official Mermaid examples.
graph TD
RaftNode["raftNode"] --> WAL["Write-Ahead Log (WAL)"]
RaftNode --> MemoryStorage["raft.MemoryStorage"]
MemoryStorage --> Snapshot["snap.Snapshotter"]
WAL --> DiskStorage["Storage on Disk"]
Snapshot --> DiskStorage
subgraph "Log Compaction"
Snapshot -->|"Creates"| SnapshotFile["Snapshot File"]
SnapshotFile -->|"Allows truncation of"| WAL
end
sequenceDiagram
participant App as "Your Application"
participant Config as "embed.Config"
participant Etcd as "embed.Etcd"
participant Server as "etcdserver.EtcdServer"
App->>Config: NewConfig()
Note over Config: Configure options
App->>Config: Customize configuration
App->>Etcd: StartEtcd(config)
Etcd->>Config: Validate()
Etcd->>Server: NewServer(serverConfig)
Etcd->>Server: Start()
Etcd-->>App: Return Etcd instance
App->>Etcd: Server.ReadyNotify()
Note over App,Etcd: Wait for server to be ready
App->>Etcd: Use etcd server
classDiagram
class Config {
+Name string
+Dir string
+WalDir string
+ListenPeerUrls []url.URL
+ListenClientUrls []url.URL
+AdvertisePeerUrls []url.URL
+AdvertiseClientUrls []url.URL
+ClientTLSInfo transport.TLSInfo
+PeerTLSInfo transport.TLSInfo
+ClusterState string
+InitialCluster string
+InitialClusterToken string
+LogOutput[] string
+LogLevel string
+Logger *zap.Logger
+AuthToken string
+ServerFeatureGate featuregate.FeatureGate
+...other fields
}
Config --> ServerConfig
Config --> ClientConfig
Config --> SecurityConfig
class ServerConfig {
+Name string
+DataDir string
+...other fields
}
class ClientConfig {
+ConnectionType ClientConnType
+CertAuthority bool
+AutoTLS bool
+...other fields
}
class SecurityConfig {
+CertFile string
+KeyFile string
+TrustedCAFile string
+...other fields
}
stateDiagram-v2
[*] --> Still
Still --> [*]
Still --> Moving
Moving --> Still
Moving --> Crash
Crash --> [*]
erDiagram
CUSTOMER }|..|{ DELIVERY-ADDRESS : has
CUSTOMER ||--o{ ORDER : places
CUSTOMER ||--o{ INVOICE : "liable for"
DELIVERY-ADDRESS ||--o{ ORDER : receives
INVOICE ||--|{ ORDER : covers
ORDER ||--|{ ORDER-ITEM : includes
PRODUCT-CATEGORY ||--|{ PRODUCT : contains
PRODUCT ||--o{ ORDER-ITEM : "ordered in"
%%{init: { 'logLevel': 'debug', 'timeline': {'disableMulticolor': true}}}%%
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google
2005 : YouTube
2006 : Twitter
sankey-beta %% source,target,value Electricity grid,Over generation / exports,104.453 Electricity grid,Heating and cooling - homes,113.726 Electricity grid,H2 conversion,27.14
journey
title My working day
section Go to work
Make tea: 5: Me
Go upstairs: 3: Me
Do work: 1: Me, Cat
section Go home
Go downstairs: 5: Me
Sit down: 3: Me
gantt
title A Gantt Diagram
dateFormat MM-DD
section sec 1
task1 : a1, 2014-01-01, 3d
task2 : after a1, 2d
section sec 2
task3 : 2014-01-02, 2d
task4 : 4d
test penrose [uts-000Q]
test penrose [uts-000Q]
The following combines Penrose examples walk-on-spheres/laplace-estimator and curve-examples/blobs:
test pikchr [uts-000W]
test pikchr [uts-000W]
The following example is from ⧉:
The following is from my blog post Transformers: from self-attention to performance optimizations:
test syntax highlighting [uts-000Y]
test syntax highlighting [uts-000Y]
This is an additional test to Lean 4 code highlighting, which should load language highlighting syntax from CDN on demand to avoid a huge bundle of all languages.
Python
Python
From ⧉:
# Closures in nested functions:
# We can use the nonlocal keyword to work with variables in nested scope which shouldn't be declared in the inner functions.
def create_avg():
total = 0
count = 0
def avg(n):
nonlocal total, count
total += n
count += 1
return total/count
return avg
avg = create_avg()
avg(3) # => 3.0
avg(5) # (3+5)/2 => 4.0
avg(7) # (8+7)/3 => 5.0
# There are also anonymous functions
(lambda x: x > 2)(3) # => True
(lambda x, y: x ** 2 + y ** 2)(2, 1) # => 5
# There are built-in higher order functions
list(map(add_10, [1, 2, 3])) # => [11, 12, 13]
list(map(max, [1, 2, 3], [4, 2, 1])) # => [4, 2, 3]
list(filter(lambda x: x > 5, [3, 4, 5, 6, 7])) # => [6, 7]
OCaml
OCaml
From ⧉:
(** Matching type constructors **)
type animal = Dog of string | Cat of string ;;
let say x =
match x with
| Dog x -> x ^ " says woof"
| Cat x -> x ^ " says meow"
;;
say (Cat "Fluffy") ;; (* "Fluffy says meow". *)
(* However, pattern matching must be exhaustive *)
type color = Red | Blue | Green ;;
let what_color x =
match x with
| Red -> "color is red"
| Blue -> "color is blue"
(* Won't compile! You have to add a _ case or a Green case
to ensure all possibilities are accounted for *)
;;
(* Also, the match statement checks each case in order.
So, if a _ case appears first, none of the
following cases will be reached! *)
(** Traversing data structures with pattern matching **)
(* Recursive types can be traversed with pattern matching easily.
Let's see how we can traverse a data structure of the built-in list type.
Even though the built-in cons ("::") looks like an infix operator,
it's actually a type constructor and can be matched like any other. *)
let rec sum_list l =
match l with
| [] -> 0
| head :: tail -> head + (sum_list tail)
;;
test tikz drawing [uts-000E]
test tikz drawing [uts-000E]
This is a series of experiments with TikZ drawing to ensure my `diagrams.tex` has sufficient preambles to render them. Most of them are adapted to minimize dependencies, and fix wierd render issues.
some important links
some important links
- Styling considerations: Illustrating Geometry by Keenan Crane - Workflow: Explanatory paper figures with Illustrator and Blender - TikZ drawing tools - Quiver - TikZiT - TikzMaker - awesome-latex-drawing - TikZ browser-side rendering - TikZJax - LaTeX.wasm
from sites collecting TikZ examples [uts-000P]
from sites collecting TikZ examples [uts-000P]
pgfplots.net
pgfplots.net
- Heteroskedasticity in a model of linear regression - Spiral cone with projections and annotations - Plotting several 2d functions in a 3d graph - Lorentz system (requires LuaLaTeX) - Moebius strip (requires non-DVI drivers)
TikZ.net
TikZ.net
- Izaak Neutelings has diagrams covering all areas of Physics, e.g. vector analysis on manifolds, 3D coordinate systems, diagrams on different planes - Analysis has many diagrams on analysis. - Bernouilli’s equation has diagrams with proper shading of complicated smooth geometries. - Some other interesting diagrams: Helicoid, Manifold mapping, topology, Convolution Operator, Fourier series & synthesis with projections, Tree with aligned matrixfigure out why all distance has to be 0, or all of them become too far away.
from various sources: annotating on 2D/3D diagrams
from various sources: annotating on 2D/3D diagrams
The following is adapted from exo7math/deepmath-exo7:
The following is adapted from bcharlier/HLMA410:
The following is adapted from giaan-nguyen/latex-notes:
From ⧉:
The following is adapted from 20squares/blog (rendered):
test tikz drawing for ray-tracing [uts-000N]
test tikz drawing for ray-tracing [uts-000N]
Adpated from Eric Wieser's snippet from the bivector discord (is it possible to combine this with kingdon and pylatex to render it with PGA etc.?):
From ⧉:
From ⧉:
Drawing string diagrams [uts-0008]
Drawing string diagrams [uts-0008]
The following are now used extensively in related links and backlinks of string diagram [nakahira2023diagrammatic, table 1.1].
The following is testing string diagram drawing using the example from Jon Sterling's String diagrams (extensively used in [sterling2023models] and [sterling2023monads]):
The following follows Algebraic description of natural models
The following is testing string diagram drawing using the example from Category theory using string diagrams:
some more links
some more links
- Tool: PGFPlotsEdt - Three-dimensional graphics with PGF/TikZ by Keith Wolcott - Draw a surface using Tikz on SE
test typst [uts-000R]
test typst [uts-000R]
Note: The Typst files and their imports must be placed under typst, as it's set up as the root directory for Typst imports.
rendering a Typst file with imports
rendering a Typst file with imports
rendering a Typst code block with imports
rendering a Typst code block with imports
hybrid typst with forester markup
hybrid typst with forester markup
This is native forester markup:
- external link: typst docs
- wiki link: test tikz drawing
- citations: [nakahira2023diagrammatic]
- cross-references: § [uts-000E]
This is the same markup rendered in Typst:
render a complicated Typst file
render a complicated Typst file
Adapted from ⧉, removed figures and bib for now, due to depending on external non-Typst files.
test uwal [uts-001J]
test uwal [uts-001J]
For now, open the console to see the output.
Technical notes (draft) [uts-0012]
Technical notes (draft) [uts-0012]
Try some alternative browsers [uts-016N]
Try some alternative browsers [uts-016N]
I decided to widen my horizon about browsers. After browsing a few subreddits, I have chosen these 3 browsers: - Arc - Chromium based - the team has moved on to Dia, an AI browser - but people still miss the UX of Arc, it seems to be one of a kind, so I have to know - unlikely to be open-source - Mac/iOS/Windows, no Linux - Orion - WebKit based, this engine is the best hope for degoogle - will be open-source - not mature yetA - Mac/iOS, Linux WIP, no Windows/Android - Floorp - Firefox based - open-source - Mac/Windows/Linux, no mobile
How to run perf in a colima container [uts-016L]
How to run perf in a colima container [uts-016L]
Just to note down that it's not straightforward to get perf working. Here's what worked finally: First, the container needs to be started with proper capabilities: ```bash docker run --rm -it --platform linux/amd64 --cap-add PERFMON ubuntu:jammy bash ``` Secondly, some flags need to be set from the VM: ```bash # this would start a shell in the VM, outside of containers colima ssh # don't know why, sudo doesn't work, but it works in a root shell # -1 or 2 both work sudo bash -c 'echo -1 > /proc/sys/kernel/perf_event_paranoid' ``` Lastly, install perf in the container: ```bash apt install -y linux-tools-$(uname -r) linux-cloud-tools-$(uname -r) ``` Then the following works: ```bash perf record -g echo 1 perf report -g graph,0.5,caller ``` Note also that you can't pass `"echo 1"` because perf will failed to find a file named "echo 1". Learned this while working on Trying Zig's self-hosted x86 backend on Apple Silicon and before submitting this issue about unable to run `poop` in `colima` containers. Follow-up: It's important to check whether certain perf counters actually work: ``` sleep 10 & perf stat -p $! -e "cpu-cycles,instructions,cache-references,cache-misses,branch-misses" ``` On a machine that supports corresponding counters, it should give something like: ``` Performance counter stats for process id '101011': 511488 cpu-cycles 280194 instructions # 0.55 insn per cycle 16193 cache-references 6161 cache-misses # 38.047 8730 branch-misses 10.009515156 seconds time elapsed ``` On an unsupported machine, the output would be like: ``` Performance counter stats for process id '552': <not supported> cpu-cycles <not supported> instructions <not supported> cache-references <not supported> cache-misses <not supported> branch-misses 6.491105847 seconds time elapsed ```
Resources about Rubik's Cube [uts-016J]
Resources about Rubik's Cube [uts-016J]
- speed solving
- Roux (a.k.a as bridging)
- Learning the Roux method
- Simple Roux Method of Solving Rubik's Cube
- Introduction - Roux Tutorial
- uses TwistySim
- ZZ
- Example Solves - Beginner ZZ Tutorial
- notation
- Rubik's cube notation by Sebastiano Tronto
- 3x3x3 notation
- which clarifies naming of `E`, `S`, `r` etc.
- papers
- The Generalized Rubik’s Cube: Combinatorial Insights Through Group Theory
- it cites Nxnxn rubik’s cubes and god’s number[salkinder2021nxnxn]
- has its own notation for nxnxn cubies
- works out many details about general nxnxn cubes and their corresponding group theory
- Commutators in the Rubik’s Cube Group
- uses notations like `UR`, `FUR` to denote edges and corners, which I prefered
- nice diagrams
- demo with Twizzle
- Generalising the configurations of an N×N×N Rubik’s Cube
- aimed to find an expression for the total number of possible configurations of an N×N×N Rubik’s Cube
- uses notations like `ur`, `fur`, `u_1` for 3x3x3 and 4x4x4 cubes
- generalize to N×N×N with 3x3x3-style edges and 4x4x4-style corners
- solving with linear algebra
- asked by this Reddit post
- Mathematics of the Rubik’s cube by W. D. Joyner in 1996
- Non-Commutative Gaussian Elimination and Rubik’s Cube
- Test TwistySim
- Test Twizzle
My setup with 4 screens and 2 Macs [uts-016B]
My setup with 4 screens and 2 Macs [uts-016B]
Recently, a MacBookPro and a Mac Mini, both are M4 Pro, have become my primary productivity tools. Along with them, I have 3 monitors, plus the one comes with MacBookPro, counts as 4 screens in total. On top of that, I have the logi MX Keys keyboard and MX Master 3S suite, and an Apple Magic Trackpad.
It turns out that I need to come up with a productive setup for them.
## TL;DR as an ASCII art
```
+---------+
| |
+-----------------+ +-----------------+ | Tall |
| Reference | | Primary | | |
| Display | | Display | | Display |
+-----------------+ +-----------------+ | |
| |
+------+ +------------+ +---------+
| Mini | | MBP |
+------+ +------------+
| [Keyboard] |
| [Pad] |
+------------+
[ MX Keys ] [MX 3S]
[Pad]
```
## Screen arrangement
Above the screen of MacBookPro, I have my primary display, which serves as the main workspace for coding, browsing etc. The second display is placed on its left, on the same height, hosting stuff for reference. Both are horizontal and wide.
The third display (I would like to call it the "tall display") is placed on the right, yet vertically, with its middle part aligned with the primary display, it might host IM, PDFs, AI assistants, or any stuff that are tall, including vertically stacked windows that requires less width.
## Mac-display correspondence
Mac Mini is placed under the second display, and it's connected to the first 2 displays, and all of them if desired.
MacBookPro is connected to the tall display, and optionally also to the primary display.
## Keyboard and mouse
I could just use the keyboard and trackpad of MacBookPro, and they can travel to the nearby Mac Mini.
As I have muscle memory that's already used to MacBookPro's keyboard, MX Keys would be a good fit, as the keys are flatter, the key distance is also shorter.
I'm so used to use the trackpad to scroll, zoom, switching between spaces, and move cursor during coding, so that I would either put MX Keys on top of the keyboard of MacBookPro so I can reach its trackpad effortlessly, or I would just MX Keys and the Magic Trackpad beneath it, with the same relative location like the MacBookPro's keyboard and trackpad.
When I work with diagrams, slides, or UIs that require meticulous mouse control, I would use the MX Master 3S mouse. Its side wheel is configured to send `Ctrl+Left` and `Ctrl+Right`, and side buttons are configured to send `Ctrl+Up` and `Ctrl+Down`, both serving space switching.
The logi keyboard and mouse supports switch between 3 devices, so I can switch between 2 Macs. Unfortunately, one doesn't follow the other to switch, so I would rely on Mac's native support for keyboard and mouse sharing, and it goes like `2->1->MacBookPro->Tall`, so there is minimal extra travel between 1 and tall.
One might noticed that such a setup is highly redundant, but this provides me with maximum flexibility and productivity:
- In coding mode, I could have both hands on the keyboard, with the left hand sometimes on the trackpad
- In browing mode, my left hand is on the trackpad, and the right hand is on the mouse
- In diagramming mode, both hands are also on the keyboard, with the right hand sometimes on the mouse
## Thunderbolt bridge
I also have a Thunderbolt bridge, by connecting 2 Macs with a Thunderbolt cable, and following this guide. This would create a secure and fast connection between them for file transfer, screen sharing, distributed AI inference etc.
Such a bridge could also be used in MX Flow, but it has certain delay each time the cursor moves between the 2 Macs, so I didn't use it.
Organizing files [uts-002J]
- January 3, 2025
- Utensil Song
Organizing files [uts-002J]
- January 3, 2025
- Utensil Song
I wish to note down my exploration of solutions to organize massive amount of (mostly binary media) files.
## Wishlist
- Performant
- it should be able to handle huge amount of files, with cached metadata, thumbnails, etc. so I can browse over their contents quickly
- batch operations to files on NAS should be as performant as local files, e.g. using client-server architecture, using rsync to determine the diff, etc.
- Data integrity
- it should be able to use versioning, deduplication, etc. to ensure data integrity so I can mess with the files (mostly moving around, renaming) without worrying about losing them and their metadata such as timestamp, and this should be efficient in terms of storage
- Semi-auto tagging
- I should be able to tag files manually, in batch, and set rules to tag files automatically with metadata or based on content (using ML models)
- preferably, tags could have its own hierarchy
- tags should not be using filename or metadata, but rather a separate database
- Open-source, freemium or affordable one-time purchase
- in anycase, I should not be locked in, and the data should be exportable, so I can script
## Candidate solutions
- git-annex
- Pros
- it maintains a versioned record for files, can even track offline media
- Cons
- it only have access to the file contents when they are present at the registered location
- even with the web UI, it's not realy user-friendly
- DataLad
- it builds on git-annex, but still a CLI
- kopia
- Pros
- backup, versioning, deduplication, encryption, compression, error correction etc.
- it can mount or restore any snapshot to a directory
- there is official support for syncing the repo, making it reliable to backup the backup
- Cons
- can't really check the history of a file
- relies on other tools for checking file location changes
- lost the time added, preserving only the modification time
- Commander One
- dual-pane file manager, trying out
- `dua -i`
- it can analyze disk usage recursively, interactively
- I can mark files for deletion
- jw
- Pros
- it can calculate the hashes of files in deep directories really quick
- I use it to check the integrity of files after copying files
- Cons
- it doesn't check file renaming/moving
- VeraCrypt
- Pros
- useful if you just want to encrypt files in a container
- Cons
- it's inconvenient to mount in docker
- Garage
- Pros
- it's a S3-compatible storage
- it works with git-annex and kopia
- macFUSE
- needed to mount various filesystems
- photo management
- HomeGallery
- librephotos
- digiKam
- PhotoPrism
- Immich
- Lychee
- asset management
- Eagle 4
- Pixcall
- Billfish
Notes on modern C++ programming [uts-002H]
Notes on modern C++ programming [uts-002H]
Scope
Scope
This note will cover some modern C++ features interesting to me during reading Modern C++ Programming.
Features standardized in C++23, or implemented for C++26, are in scope.
This note serves as a holistic view and a reminder.
Introduction
Introduction
Curiosity and persistence matter. -- Ben Cichy
C++ achieves uncompromised performance by living with undefined behavior, accepting a safety trade-off. -- This is C++: Uncompromised Performance, Undefined Behavior, & Move Semantics - Jon Kalb C++Now 2024
The problem with using C++...is that there’s already a strong tendency in the language to require you to know everything before you can do anything -- Larry Wall
Preparation
Preparation
- C++23 `std::print`
- Reducing C++ Compilation Times Through Good Design - Andrew Pearcy - ACCU 2024
Basic Concepts I
Basic Concepts I
- C++14 digit separators, e.g. `1'000'000`
- C++14 `auto` for function return types, e.g. `auto f() { return 1; }`
- C++20 `auto` for function input, equivalent to templates but less expensive at compile-time
- C++20 `<utility>` for safely comparing signed/unsigned types
Basic Concepts II
Basic Concepts II
- Detecting wraparound for unsigned integral types is not trivial
- C++23 `std::float128`, `std::binary16`, `std::bfloat16`
- `inf` and `nan` for floating-point types
- Floating-point Arithmetic Properties
- Catastrophic Cancellation
- Fixed epsilon “looks small” but it could be too large when the numbers being compared are very small
- `areFloatNearlyEqual`
- compensation algorithm like Kahan summation, Dekker’s FastTwoSum, Rump’s AccSum
Basic Concepts III
Basic Concepts III
- C++11/C++17/C++20 enum class, e.g. `using enum Color`
- C++17 range-based loop for structure binding: `for (auto [key, value] : map)`
- C++17/C++20 initializing statement in `if`/`switch` and range-for loop, e.g. `for (int i = 0; auto x : {'A', 'B', 'C'}) {}`
- C++17 `[[maybe_unused]]` attribute, C++26 `auto _`
Basic Concepts IV
Basic Concepts IV
- C++11 Dynamic memory 2D allocation/deallocation: `new int[3][4]` and `delete[]`
- `new (buffer)`: `delele[] buffer`, explicit `x->∼A()`
- `new (std::nothrow)`
- C++20 Designated Initializer List: `struct A { int x, y; }; A a{.x = 1, .y = 2};`
- Pointer arithmetic rule: `address(ptr + i) = address(ptr) + (sizeof(T) * i)`
- C++11 `constexpr`: _can_ be evaluated at compile-time
- variable: always evaluated at compile-time
- function
- evaluated at compile-time as long as all its arguments are evaluated at compile-time
- always evaluated at run-time if
- contain run-time functions
- contain references to run-time global variables
- C++20 `consteval`: guarantees compile-time evaluation
- A run-time value always produces a compile error
- C++20 `constinit`: guarantees initialization at compile-time
- A run-time initialization value always produces a compile error
- The value of a variable _can_ change during the execution
- C++17 `if constexpr`: compile-time branching
- C++20 `std::is_constant_evaluated()`
- C++23 `if consteval`
- C++20 `std::bit_cast`
Basic Concepts V
Basic Concepts V
- `=delete` can be used to prevent calling the wrong overload
- C++20 `[[nodiscard("reason")]]`
- This issues a warning if the return value of a function is discarded (not handled), which is good for ensuring error handling.
- C++17 for the entire class/struct
- C++20 for constructors
- C++23 for lambdas
- The compiler injects `operator()` in the code of the destination function and then compile the routine. Operator inlining is the standard behavior
- C++11 lambda expression: capture clause
- `[]` captures nothing
- `[&]` captures all variables by reference
- `[=]` captures all variables by value
- `[=, x, &y]` captures `x` by value and `y` by reference, all other variables by value
- C++17 `[this]` captures the current object by reference
- C++14 `[x=x]`, `[&x=x]` capture current object member `x` by value/reference
- C++20 deprecates `[=]` capturing `this` pointer by value
- C++14 `[](auto value)`, `[](int i = 6)`
- A function can return a lambda (dynamic dispatch is also possible)
- C++17 `constexpr` lambda, C++20 `consteval` lambda, `mutable`
- syntax: post specifier
- C++20 `template` and `requires` clause for lambda
auto lambda = []<typename T>(T value)
requires std::is_arithmetic_v<T> {
return value * 2;
};
auto v = lambda(3.4); // v: 6.8 (double)
struct A{} a;
// auto v = lambda(a); // compiler error
- When Preprocessors are Necessary
- Conditional compiling
- [Abseil Platform Check Macros](https://abseil.io/docs/cpp/platforms/macros)
- Mixing different languages
- Complex name replacing
- [Are We Macro free Yet, CppCon2019](https://github.com/CppCon/CppCon2019/blob/master/Presentations/are_we_macrofree_yet/are_we_macrofree_yet__zhihao_yuan__cppcon_2019.pdf)
- C++20 `<source location>`
- replaces `__FILE__`, `__LINE__`, C++11 `__func__`
- still: non-standard `__PRETTY_FUNCTION__`
- C++17 [`__has_include`](https://en.cppreference.com/w/cpp/preprocessor/include)
- stringizing macro operator `#`, e.g. `#string` expands to `"string"`
- token pasting macro operator `##`, e.g. `x##y` expands to `xy`
- `#error`, C++23 `#warning`
- non-portable `pragma`, C++11 `_Pragma`
- C++11 `__VA_ARGS__`
Object-Oriented Programming I
Object-Oriented Programming I
- C++11 In-class non-static data members initialization (NSDMI)
- allows initializing the data members where they are declared
- a user-defined constructor can be used to override their default values
- C++11 uniform initialization `{}`
- in function arguments and return values
- C++11 delegate constructor
- C++11 `=default`, `=delete`
- `using` for type aliasing
- e.g. partial specialization for templates
Object-Oriented Programming II
Object-Oriented Programming II
- C++11 `override`
- ensures that the function is virtual and is overriding a virtual function from a base class
- C++11 `final`
- prevents a virtual function from being overridden in a derived class
- `dynamic_cast`
- upcast: `dynamic_cast<Base*>(derived)`
- C++23 multidimensional subscript operator `[]`
- C++23 static `[]` and `()` operators
- C++11 `explicit` for conversion operators
- `std:swap`
- operators preserve precedence and short-circuit properties
- binary operators should be implemented as friend methods
- layouts
- aggregate
- initializable with `{}`
- trivial copyable
- can be copied with `memcpy`
- standard layout
- just like a struct or a union
- POD
- trivial copyable + standard layout
- C++11/C++20 `<type_traits>` to check layout
Templates and Meta-programming I
Templates and Meta-programming I
- C++17 automatic deduction of non-type template parameters, with `auto`
- non-type template parameters
- C++20 a class literal type
- `constexpr` assignable
- public, non-mutable
- for all base classes and non-static data members
- pointer, reference, and pointer to member
- function, e.g. `decltype(f)`
- C++26 assertion with text formatting
- e.g. `static_assert(sizeof(T) != 4, std::format("test1 with sizeof(T)={}", sizeof(T)));`
- `decltype((expr))` for `lvalue` reference to the type of `expr`
- C++14 `auto` for function template return types
- replaces e.g. `decltype(T{} + R{})`
- `<type_traits>`
- type query
- type manipulation
Templates and Meta-programming II
Templates and Meta-programming II
- C++17 CTAD
- automatic deduction of class template arguments in constructor calls (CTAD)
- template deduction guide
- map constructor parameter types to class template parameters
- e.g. `MyString(char const*) -> MyString<std::string>;`
- doesn’t work within the class scope
- C++20 alias template deduction
- use `std::enable_if` to make use of SFINAE
- helper alias: `_t` for `::type`, `_v` for `::value`
- using `std::enable_if_t` for the return type prevents `auto` deduction
- variadic template
- captures a parameter pack of arguments, which hold an arbitrary number of values or types
- ellipsis `...`
- prefix an identifier to introduce/capture
- suffix the identifier to expand
- `sizeof...(args)` to get the number of arguments
- C++17 fold
`(other op ... op pack)`
- C++14 for lambdas
- C++20 for concepts
- [C++20 idioms for parameter packs](https://www.scs.stanford.edu/~dm/blog/param-pack.html)
- C++20 concepts
- `concept [name] = [compile-time boolean expression];`
- `requires` clause: `requires [compile-time boolean expression or Concept]`
- `requires` expression:
#include <concept>
requires [(arguments)] {
[SFINAE contrain]; // or
requires [predicate];
} -> bool
template<typename T>
concept MyConcept = requires (T a, T b) { // First case: SFINAE constrains
a + b; // Req. 1 - support add operator
a[0]; // Req. 2 - support subscript operator
a.x; // Req. 3 - has "x" data member
a.f(); // Req. 4 - has "f" function member
typename T::type; // Req. 5 - has "type" field
{*a + 1} -> std::convertible_to<float>;// Req. 6 - can be deferred
// and the sum
// with an integer is convertible
// to float
{a * a} -> std::same_as<int>; // Req. 7 - "a * a" must be valid
// and the result type is "int"
};
Translation Units I
Translation Units I
- storage duration - static initialization order fiasco - One Definition Rule (ODR) - C++11 `extern template class A<int>;`
Translation Units II
Translation Units II
- common linker errors
- multiple definitions
- undefined reference
- C++20 modules
- a module is a set of source code files that are compiled independently of the translation units that import them
- `module module.name;`
- `import module.name;`
- `export`
- `export { ... }`
- `export module module.name;`
- `expor import module.name;`
- global module fragment: include header files in a module interface
- `module;`
- private module fragment: include header files in a module implementation
- `module :private;`
- legacy headers can be directly imported with import
- all declarations are implicitly exported and attached to the global module (fragment)
- a module can be organized in isolated module partitions
- namespace
- anonymous namespace
- visible only in the translation unit, internal linkage
- inline namespace
- can be used to version a library
- C++17 attributes on namespaces
- tools
- `c++filt`, `ldd`, `nm`, `objdump`, `readelf`
Code Conventions
Code Conventions
- “Common” Project Organization - [C++ Core Guidelines](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines) - Naming style conventions can be also enforced by using tools like `clang-tidy`'s [readability-identifier-naming](https://clang.llvm.org/extra/clang-tidy/checks/readability/identifier-naming.html#readability-identifier-naming) - Use braced direct-list-initialization or copy-initialization for setting default data member value. Avoid initialization in constructors if possible
struct A {
int x = 3; // copy-initialization
int x { 3 }; // direct-list-initialization (best option)
};
Debugging and Testing
Debugging and Testing
- Cost of Software Defects - 60 terrible tips for a C++ developer - Compiler Options Hardening Guide for C and C++ - Sanitizers - Static Analyzers - Linters
Ecosystem
Ecosystem
- xmake vs cmake - Compiler Explorer - CppInsights: see what your compiler does behind the scenes - grep.app: search git repos - Quick C++ Benchmark
Utilities
Utilities
- C++20 `std::format`
- C++23 `std::print`, `std::println`
- C++20 `std::span`: non-owning view of an underlying sequence or array
- C++20 `<numeric>`
- C++11 pseudo random number generation (PRNG)
- C++11 `<chrono>`
- overhead ~20-40ns
- C++17 `<optional>`, `<any>`
- C++23 `<stacktrace>`
Containers, Iterators, and Algorithms
Containers, Iterators, and Algorithms
- C++20 Ranges
- operate on elements of data structures uniformly
- pipe operator `|`, `|=`
- `std::views::*`, `std::actions::*`
- range factory: produces a view that contains no elements
Advanced Topics I
Advanced Topics I
- lvalue, rvalue (could be *p*ure rvalue, or e*x*piring *g*eneralized lvalue) - `std::move` indicates that an object is no longer needed and can be moved - C++11 reference collapsing rules - C++11 perfect forwarding with `std::forward`: allows preserving argument value category and const/volatile modifiers - copy elision for return value (C++17 guarantees some cases) - C++23 decay copy with `auto`
Advanced Topics II
Advanced Topics II
- C++23 `std::expected`
- return a value or an `std::unexpected`
- the user can choose how to handle the error: check return value, throw an exception, or monadic operations
- future
- `std::async(f, args)`
- launch policy: `std::launch::async`, `std::launch::deferred`
- `.get()` or `.wait()`
Performance Optimizations I
Performance Optimizations I
Mostly known conceptual introductions, good reference.
Performance Optimizations II
Performance Optimizations II
- C++11 `std:fma` - C++20 `<bit>` - C++20[[unlikely]]- C++23[[assume(boolean expression)]]
Performance Optimizations III
Performance Optimizations III
- compiler flags and optimization
- consider using optimized external libraries for critical program operations (good reference)
- profiling tools
- parallel computing
- OpenACC
- Intel OneAPI
Software Design I
Software Design I
- functions that are strongly suggested being non-member
- binary operators
- template functions within a class template
- `std::linalg` proposal
Software Design II
Software Design II
- Curiously Recurring Template Pattern (CRTP): static polymorphism - Template Virtual Function
useful tools and key mappings for TUI [uts-002G]
- October 29, 2024
- Utensil Song
useful tools and key mappings for TUI [uts-002G]
- October 29, 2024
- Utensil Song
Top bar
- October 29, 2024
- Utensil Song
Top bar
- October 29, 2024
- Utensil Song
Setup: - Use SketchyBar - Use `just prep-sbar` to setup SketchyBar - Use `just prep-skhd` to setup some extra key bindings - `Shift + Alt + space`: toggle sketchbar - Modify `~/.config/sketchybar/bar.lua` as follows: ```lua display = "all", sticky = true, ``` for better multi-monitor support, and make the bar sticky. Unfortunatly, SketchyBar actively hides itself for fullscreen spaces, see this issue for more info. So, remember to use `Cmd + Ctrl + F` to toggle fullscreen mode.
Window tiling
- October 29, 2024
- Utensil Song
Window tiling
- October 29, 2024
- Utensil Song
Setup: - Use Amethyst - sensible default - less confusing configuration than yabai it seems - Use `just prep-tile` to install Amethyst Keys: - `Option + Shift + Space` to cycle through layouts - I prefer only BSP and wide - `Option + Shift + J/K` to cycle through windows - `Option + Shift + H/L` to resize windows Alternative setup: - Use yabai - requires skhd for key bindings - Use `just prep-yabai` to install yabai - Intentionally choose not to disable SIP Keys: - Space manipulation won't work with SIP enabled - keys to switch between windows are confusing - place windows on another window to split with it, there is visual hint for the split layout when overlapping with different areas - `Shift + Alt + s`: change how windows are splitted, prefer use Kitty's own layout management - `Ctrl + Alt + g`: toggle gaps between windows, prefer some gap for normal apps but no gap for terminals
Terminal
- October 29, 2024
- Utensil Song
Terminal
- October 29, 2024
- Utensil Song
Setup:
- Use Kitty
- Use `just prep-kitty` to install Kitty
Keys:
- Font size
- `Cmd +` to increase font size
- `Cmd -` to decrease font size
- OS Windows
- `Cmd + N` to open a new OS window with the same current directory
- Tabs
- `Cmd + T` to open a new tab with the same current directory
- `Cmd + number` to switch to tab number
- particularly useful for tiled windows, as SketchyBar will hide the tab bar
- `Cmd + w` to close the current tab
- Kitty Windows
- `Cmd + Enter` to open a new window with the same current directory
- close the current Kitty window
- `Ctrl + Shift + w`
- or run `exit`
- `Ctrl + Shift + l` to switch to next layout
- `Cmd + r` to resize window, e.g. `t` to make it taller
- Kitty
- `Cmd + q` to quit kitty
- `Cmd + ,` to open kitty config file
- with `Ctrl` to reload config
Monitor
- October 29, 2024
- Utensil Song
Monitor
- October 29, 2024
- Utensil Song
- For most info, use btop - For GPU on Mac, use macmon - Install both with `just prep-monit`
some useful key mappings in Neovim [uts-002F]
some useful key mappings in Neovim [uts-002F]
Introduction
Introduction
Here are some useful keys that I like using in NeoVim, some of them require corresponding plugins. I use - LunarVim - it has some pre-installed plugins - Task `prep-lvim` in my justfile is how I have installed LunarVim. Task `lvim` will syncrhonize the configurations, change the working directory and open LunarVim for a specified project. - my LunarVim configuration - LunarVim specific keys are marked with 🌕 - AstroVim - seems to be a better starting point - see astrocommunity for configuring plugin packs - I've ported plugins to use it except for forester - AstroVim specific keys are marked with 🌌 - LazyVim - it has some pre-installed plugins - similarly, see task `prep-lazyvim` and `lazyvim` in my justfile - LazyVim specific keys are marked with 💤 - NvChad - it's ~ 900 LOC lightweight configuration - see tasks `prep-chad` and `chad` in my justfile - NvChad specific keys are marked with 📦 - For all Vim flavors, the following apply: - shared configurations - shared plugins
Vital meta keys
Vital meta keys
some useful key mappings in Neovim › Esc
some useful key mappings in Neovim › Esc
The `Esc` key is used to escape to normal mode, to use Vim's powerful motions. It's the most frequently used key in Vim.
- I have configured CapsLock to mean Esc
- on Mac, go to `System Preferences > Keyboard > Modifier Keys > Caps Lock Key`
- I have configured `jk` in insert mode to mean Esc
- this is a common practice, but I don't seem to need it much
some useful key mappings in Neovim › Leader key
some useful key mappings in Neovim › Leader key
The leader key is used to trigger many key mappings in normal mode. The default leader key is a single space, represented by `<leader>` below. 🌕 The default local leader key is not set. I've configure it to be two consecutive spaces. `,` is also a common choice. 💤 The default local leader key is set to `\\`. I didn't change it. With plugin `whichkey` installed, `<leader>` and wait to see some useful mappings. Most frequently used key mappings is `<leader>` + one character. There are also many two-character mappings, with the first character indicating a category.
First aid
First aid
> To generate a truly random string, place a new user in front of Vim and ask them to exit
Most of the time, one can use `Esc` + `:qa!` to force quit Vim, with potential loss of unsaved changes.
In most plugin UIs,
- it can be quit with a single `q`, or `Esc` + `:q`, when in despair, try also `Ctrl+c`
- it will usually enter normal mode first, even in terminals, a single `i` is required to enter insert mode, to acually type something
- it might provide visual hints on how to navigate, usually a single number or a character in brackets
- `g?` or `?` might bring up help on key mappings.
Recording is a powerful feature of Vim, but one can accidentally trigger it with an out-of-order `q`, so one simply need to remember to press `q` again to quit recording if seeing something like `recording @a` in the status bar.
Other first aid key mappings or commands available:
- `:map` to see all key mappings
- `:help key-notation`
- in case it's not immediately clear that
- `C` means `Ctrl`, `S` means `Shift`
- `M` means `Alt`/`Option`
- `D` means `Cmd` on Mac
- use `:Lazy` to check on plugins
- use `:Mason` to check on LSPs
- 🌕
- `<leader>+;` to open the dashboard for frequently used actions
- `<leader>+Lr` to reload the config
- `<leader>+li` to see LSP informations
- 📦
- `<leader>+ch` to open cheatsheet
- Theming
- dropping into an unfamiliar theme is worth a first aid
- `:colorscheme ` and tab to select a theme
- 🌕 `<leader>+sp` to search/select and preview themes
- my favorite is `railscasts`
- 💤 defaults to `tokyonight`
- 📦 defaults to `onedark`
Navigation
Navigation
- Resume session
- `<leader>+rs` to resume the last session
- `<leader>+rS` to select a session to resume
- Explore and find files
- `<leader>+e` to toggle file explorer on the left
- `x` to cut, `c` to copy, `p` to paste
- `a` to create a file, `d` to delete, `r` to rename
- `H` to toggle hidden files, `I` to toggle git ignored files
- `Y` to copy relative path, `gy` to copy absolute path
- `s` to open in system file explorer
- `g?` for help, `q` to quit, `R` to refresh
- `hjkl` to move up/down, collapse/expand
- it will automatically follow the current file
- 💤 and 📦 use NeoTree
- can't be toggled, need `q` to quit
- `?` for help
- 🌕
- `<leader>+sr` to fuzzy find recent files
- `<leader>+sf` to fuzzy find files
- `<leader>+st` to grep text in files
- `<leader>+bf` to fuzzy find buffers
- 💤
- `<leader>+fr` to fuzzy find recent files
- `<leader>+ff` to fuzzy find files, or simply double space
- `<leader>+/` to grep text in files
- Manipulate buffers and windows
- use `L` for going to next buffer, `H` for previous buffer
- use `<C-hjkl>` to move between windows
- use `-`/`=` to resizing, or with `C-` for vertical resizing
- Jump between files
- `gd`: go to definition
- `Ctrl`+click also works, note that it's not cmd+click on mac
- `gl`: show diagnostics under cursor
- `<C+o>`: go back, `<C+i>`: go forward
`:jum` to see the jump history
- `gf`: go to file
- `K` : hover, backspace to cancel hover
- `Shift`+click on URL to open in browser
- In-file outline
- `<leader>+o` to toggle the outline on the right
- I have configure it to autojump and autoexpand
- Folding
- the following needs to be run inside the fold
- otherwist it will work on the upper level
- `za` to toggle fold
- `zA` to toggle all folds
- `zO` or `zC` to open/close folds recursively
- e.g. it's useful `zCV` then `<leader>+/` to toggle comment for a fold range
Editing
Editing
some useful key mappings in Neovim › Basics
some useful key mappings in Neovim › Basics
- Open file
- `:e` to open a file, with tab completion, but it's better to use the fuzzy finder above
- `:vs` to open a file (or the current buffer) on the right
- `:sp` to open a file (or the current buffer) on the bottom
- Save & quit
- `:bd` (i.e. buffer delete) to close the current buffer/tab
- won't close if there are unsaved changes, `:bd!` to force close
- In VSCode Vim mode, should stick to `cmd+s` for saving, `cmd+w` for closing a tab
- 💤
- `:w` or `Ctrl+s` to save
- `<leader>+bd` to close a buffer with confirmation on unsaved changes
- 🌕 prefer to use
- `<leader>+w` to save
- `<leader>+c` to close a buffer with confirmation on unsaved changes
- `ZZ` to save and quit
some useful key mappings in Neovim › Motions
some useful key mappings in Neovim › Motions
- Repeatition
- prefix with a number to repeat a motion multiple times, e.g. `3j`, `3w` for the impatient
- `.` to repeat the last edit motion, but not move motions
- Move motions
- On Mac, combine with the touchpad to be even more efficient
- `gg` for beginning, `G` for end
- `zz` to center the current line, `zt` to top, `zb` to bottom
- prefixing with a number works on the corresponding line
- `w`/`b` to move forward/backward by word
- `W`/`B` to move by space-separated words
- `e` works like `w` but moves to the end of the word
- `ge` works like `b` but moves to the end of the previous word
- left `hj` are for left, down; right `kl` are for right, up
- pointer finger on `j`, then muscle memory for `jkl` but `h` is a little difficult to reach
- `0` to move to the beginning of the line
- I don't like `^` and `$` because they are difficult to reach
- but in the case of `d$`, it's worth it to reach for `$`
- `f` + character to move to the next such character on the same line
- `;` and `,` to move to next or previous
- `t` works like `f` but moves to one character before, just like `i` for `a`
- e.g.
- `ct)` is useful for change until the next `)`
- `vt)p` is useful for select until the next `)` and paste and replace
- `F` and `T` work like `f` and `t` but move backward
- `}` to the next paragraph
- Edit motions
- to enter INSERT mode
- `i` for before the cursor
- `I` to insert at non-whitespace beginning of the line
- `0i` to insert at the beginning of the line
- `a` for after the cursor
- `A` to append at the end of the line
- `c` (i.e. change) to replace by motion, e.g. `cw` to replace a word
- `R` to replace by character
- `u` to undo, surprisingly `Ctrl+r` to redo
- Text objects
- `i` for inside, `a` for around
- works after the action, before the motion
- e.g. `ciw` to *c*hange *i*nside the *w*ord
- note that `cw` only changes the part of the word after the cursor, but `ciw` changes the whole word
- `a` will affect the surrounding whitespace and punctuation
- with `mini.ai` extending the text objects, we have more general way to discribe the text objects
- `b` for brackets
- `q` for quotes
- `c` for class
- `f` for function bodies
- `a` for arguments
- `?` to specify left and right delimiters interactively
- Cut/copy/paste
- `x` to immediately delete the character under the cursor
- `d`+direction to delete a character in that direction
- prefer to use number + `dj`/`dk` to delete multiple lines
- `dw`/`dd` to delete a character/word/line
- all the above will also cut the deleted text
- `yw` to copy the current word, `yy` to copy the current line
- `p` to paste after, `P` to paste before
- for pasting into a pair of brackets/quotes etc., move to the opening one (e.g. use `Esc` + `b`), then `p` or `Cmd+v`
- `yyp` to duplicate a line
- `<leader>+s+R` to search the registers for cut/copied text
- on Mac, `Cmd`+`c`/`v`/`x` also works despite which mode Vim is in
- but it seems to be not working stably across difference instances of Vim, especially when inside various plugins
- `y` usually guarantees the text is copied to the system clipboard, then use it in other applications
some useful key mappings in Neovim › Search & replace
some useful key mappings in Neovim › Search & replace
- Search
- `/` to search forward, `n`/`p` to go to next/previous match
- `?` to search backward
- `*` to search the word under the cursor
- remember to press `Enter` after typing the search term
- remember to treat the search as a regex
- i.e. to escape `\`, `()`, `[]`, `{}`, `^`, `$`, `*`, `+`, `?`, `|`, `.` etc.
- use `<leader>+h` to clear the search highlight
- `gn` to select the next match, `gN` to select the previous match
- repeating this would select *to* the following matches
- prefix with an operator to operate on the selected text
- Replace
- use `%s/before/after/g` to replace all occurrences, remember`%`, otherwise it will only look for the pattern in the current line
- `<leader>+ss` to toggle the search and replace panel
- `<localleader>+r` to replace all occurrences
- manually: use `gf` to go to each file, do edits, then `Ctrl+o` to go back and continue for the next file
some useful key mappings in Neovim › Visual selection
some useful key mappings in Neovim › Visual selection
- Select text
- use `V` to enter line visual mode
- this is the most frequently used visual mode, to select multiple lines
- lowercase `v` can be used for character visual mode, but I find it less useful
- `Ctrl+v` to enter block visual mode, i.e. select by column
- Indentation & comment
- use `<<`/`>>` to indent/unindent the current line
- use a single `<`/`>` to unindent/indent the selected text
- 🌕
- `<leader>+/` to toggle comment
- works for both current line and selected text
- 💤
- `gc` to toggle comment for selected text
- `gcc` to comment/uncomment a line
- Multiple-cursor editing (⧉)
- use `/xyz` + enter to search for `xyz`, then `cgn` to change it to something else, `Esc`, then
- use `.` to do the same for next occurrences
- use `n` to skip, and `u` to undo
- use `Ctrl+v` and direction keys (e.g. `j` or `5j`) to vertically select
- use `c` to change
- use `I` to prepend
- use `A` to append
- use `d` to delete
- type the new text, then `Esc`, then it will be applied to all lines of selection
- use `gv` to reselect the last selection
- Visual selection with mouse/touchpad
- motion-compatible selections
- dragging works like `v`
- triple click + scroll works like `V`
- `alt/option` + drag works like `Ctrl+v`
- select and
- ✅ delete by `d`/`x`
- ✅ cut/copy/paste
- ✅ comment/uncomment
- ❌ typing
- ✅ use one of `i`, `a`, `c` etc., then start typing
- ❌ indent/unindent with `Tab`/`Shift+Tab`
- ✅ indent/unindent with `<`/`>`
- vertical select and
- ✅ delete
- ✅ paste
- ❌ typing
- ✅ use one of `I`, `A`, `c`, then start typing
- Recording
- `qa` starts recording user's inputs, `q` quits recording, `@a` replays the recording, `a` could be any other letter
- it could serve as ad hoc key mappings
Diagnostic, quickfix and code actions
Diagnostic, quickfix and code actions
- Diagnostics
- by default, diagnostics are shown as virtual text, I've disabled it for now
- `<leader>+l` with `j`/`k` to move between diagnostics
- `<leader>+ld` to show diagnostics in the current buffer
- `<leader>lw` can search for diagnostics in workspace
- `Trouble` can be used to show diagnostics in a separate panel
- `<leader>+xx` to open the trouble panel at the bottom
- use `<leader>+xX` to see only the current buffer's diagnostics
- click on diagnostics to jump to the corresponding location
- `<leader>+lq` to open the quickfix list
- `<leader>+la` to open the code action list
Terminal
Terminal
It's very important to stay in the flow and Zen mode as much as possible. Split windows for terminals breaks the flow, so I prefer to use float terminals.
- Float terminals
- 🌕 `Ctrl+\`to toggle a float terminal
- 🌕 number + `Ctrl`+backslash to toggle the n-th float terminal
- 💤 same, but with `Ctrl+/`
- it's insert mode on first launch
- but usually enter normal mode when lost focus
- Split terminals
- `:term` to open a terminal
- it's normal mode by default, `i` to start typing commands
- `:sp term://zsh` to open a terminal running `zsh` at the bottom
- 📦
- use `<leader>+h` to open a new horizontal split terminal
- `:q` to hide terminal
- `<leader>+pt` to pick hidden terminal
- Working inside the terminal
- `exit` will exit the terminal and close the window associated with it
- `Ctrl`+`c` can be used for interrupting the terminal
Git & Github
Git & Github
- git
- install and use `lazygit`
- `<leader>+gg` to open lazygit, `q` to quit
- on a file/directory
- space to stage/unstage, `i` to ignore, `d` to discard
- `c` to commit, `P` to push, `p` to pull
- `r` on a commit to reword
- in editor, `<leader>+gs` to stage the current hunk, `<leader>+gr` to revert the current hunk
- usually lazygit is good enough, one can also use `:DiffviewOpen` to inspect diff and handle merge conflicts
- Github Actions
- `<leader>+ga` to open the Github Actions split window
- deprecated: `<leader>+gh` because it conflicts with 💤
- `gj` to open the job under cursor, `gr` for the run, `gw` for the workflow file
- `<leader>+gq` to close the split window
- Octo
- `:Octo <Tab>` to operate on issues and PRs
- it's interesting but I've disabled it for now, in favor of using the web interface
Auto-completion
Auto-completion
- Auto-complete
- with Github Copilot
- `:Copilot setup` to authenticate etc.
- `Tab` to accept suggestions
- `Shift+Tab` to use the normal Tab
- with `blink.cmp`
- I've configure it to not triggered by default, in favor of Github Copilot
- toggle by `Ctrl+q`
- could also be triggerd by `down` in insert mode
- up/down to cycle through suggestions, `Enter` to accept
- the above is set up so all this key mapping are explicit, intuitive and won't interfere with `<Tab>` for Github Copilot
- with `nvim-cmp` (deprecated)
- `Tab` to cycle through suggestions from `cmp`, reverse cycle with `Shift+Tab`
- continue to type to select a suggestion, this is better then hitting `Enter`
- `Ctrl+e` to reject suggestions, and `Tab` to take suggestions from Github Copilot
- LLM Chats
- Github Copilot
- `<leader>+aa` to toggle the chat, `<leader>+al` to clear chat history
- `<leader>+a` + a character
- for selected code block, **e**xplain, **r**eview, **o**ptimize, **R**efactor, **t**est
- **d**ebug, **f**ix, co**m**mit log, **n**aming etc.
- `?` to select the model
- `C-s` to send the prompt
- `:help copilot` to learn more
- Aichat
- `aichat` with a little setup at `~/Application Support/aichat/config.yaml`
- `.` + tab to see available commands
- Aider
- it's great for multiple-file code generation
- I've created a `aider` shim to run it in a virtual environment with preferred configurations
- `/` + tab to see available commands
- mostly it's a combination of `/add`, `/web`
- use `/token` to check token usage, use `/clear`, `/drop` and check `/map` to save token usage
- Code Companion
- `<localleader>+a` to toggle the inline chat (works also for selection)
- `<localleader>+z` to toggle the chat sidebar
- Parrot
- `<leader>+pr` to rewrite the selection
- `<leader>+pp` to implement the selection
- `<leader>+pn` to start a new chat, optionally with the selection
- select and `:Prt` + `<Tab>` to select advanced prompts
- `:PrtInfo` to inspect configurations
- `:PrtModel` to select the model
- I've configured it to use a buffer to input the prompt, escape twice to send it
- it seems unable to stop generation sometimes, use `:PrtChatStop` to stop
- Avante (deprecated for now)
- `<leader>+aa` to open the chat, use `a` to accept individual suggestions, or `A` to accept all
- select code and `<leader>+ae` to modify code
- it's interesting but I've disabled it for now, in favor of Github Copilot
- Spellcheck
- to use NeoVim's built-in spellcheck
- use `:set spell`
- `]s`/`[s` to move between misspelled words
- `zg` marks a word as good, `zw` marks a word as wrong
- `zug`/`zuw` to undo
- `z=` to see suggestions
Useful plugins
Useful plugins
- Conform
- formart on save using LSP default formatter
- `<leader>+lf` to format the current file
- showkeys
- `<leader>+kk` to show keys screencaster on top-right corner
- symbols
- `<leader>+se` to fuzzy search symbols, e.g. emoji, LaTeX
- Lean
- set local leader to " " (tentative)
- `<localleader>+i` to toggle Lean Infoview
- `<localleader>+r` to restart Lean server for the current file
- Forester
- `<localleader>+c` to create a new tree and open it
- `<localleader>+b` to browse and search trees by title
- `gf` to go to the tree under the cursor
Further reading
Further reading
See the following articles for further inspirations: - useful tools and key mappings for TUI for related TUI key mappings. - Lucas on Vim bindings for discovering more key bindings - Vim cheat sheet for key mappings that apply to vanilla Vim. - VSCode Vim ROADMAP for key mappings that apply to (limited) VSCode Vim mode, but now I have switch to use the real NeoVim. - Keybinds overview for LunarVim key mappings. - zed-101-setup for configurations and key maps inspirations. - My Favorite Neovim Plugins - You don’t need more than one cursor in vim When I use VSCode, I would also use vscode-neovim which would connect to my real NeoVim instance that has some basic configurations here. Zed's Vim mode has many widely used enhancements built in, see also rationale here.
initial survey on headless render/testing for WebGL [uts-001N]
initial survey on headless render/testing for WebGL [uts-001N]
I want to be able to run headless render or visual regression tests, both locally where GPU is available, and on CI where GPU has to be emulated. The ingredients seems to be Storybook+Playwright+Xvfb. - use OrbStack as local docker engine - use act (usage) to run GitHub Actions locally - use Storybook to building pages and components in isolation - use Playwright to verify the visual appearance on different browsers - use Xvfb to emulate a display server If I'm a bit more ambitious, I would like to be able to do the same for WebGPU. At least we do know that Xvfb support OpenGL via mesa (which also supports Vulkan etc.), and there are some libraries to run WebGPU via WebGL 2 (e.g. wgpu). Some resources I found so far: - Effortless CI Integration: Running Playwright Tests with GitHub Actions uses `xvfb-run` - `playwright`'s own CI uses `xvfb-run` - Headless chrome – testing WebGL using playwright demonstrates WegGL testing when GPU is available, see also its writeup - Options to enable GPU Hardware Acceleration in headeless mode - use xquartz with PyVirtualDisplay on Mac - use libosmesa with Chrome from 2016 - use VirtualGL with Xvfb ⧉For an earlier survey on headless testing, see SSR of WebGL.
SSR of WebGL [uts-0013]
- August 31, 2024
- Utensil Song
SSR of WebGL [uts-0013]
- August 31, 2024
- Utensil Song
## Server-side rendering of WebGL Combining `xvfb-run`, headless-gl, three.js, should make it possible, e.g. see Headless rendering with THREE.js, see also: - sharp for rendering to various image formats - three.js + headless.gl rendering with texturing in CoffeeScript - How to run OpenGL based tests on Github Actions ## Plotly.js I wish to draw a style similar to Project contour profiles onto a graph by Matplotlib, which plots a 3D surface then its contour profiles projected to surrounding planes. Plotly.js has a similar example as Surface Plot With Contours. Plotly requires a `div` element to render the plot, it will initialize a WebGL-capable `canvas` to do so. It has support for using virtual WebGL context but no native way to specify a `canvas` from the outside. When running in headless mode from node, we will typically use jsdom which in turn uses node-canvas that's not WebGL-capable. There is an open issue to detect the presence of node-canvas-webgl and use it, as it integrations `node-canvas` and headless-gl. Another idea is to make NPM packages `get-canvas-context` and in turn `webgl-context` to handle this. A commercial plot libraries `LightningChart JS` has made Headless server use support for itself, which could be used as a reference. Should I Render Three.js to Video on the Client or Server? has some discussions on this topic.
initial survey on writing Rust in Forester [uts-0011]
- August 31, 2024
- Utensil Song
initial survey on writing Rust in Forester [uts-0011]
- August 31, 2024
- Utensil Song
I wish to be able to call rust libraries that are WASM compatible to use it for both BSR and SSR. Here is my initial survey: - wasm-pack and wasm-bindgen are the two main tools for building and binding rust to javascript, more info see awesome-rust-and-webassembly - I wish to write one-file Rust and specify the dependencies in the file, rust-script is similar in spirit but it's for server-side execution. - I wish to find prior art on doing this with bun, found bun-ffi-rust and hyperimport, but again, it's for server-side execution.
some links for learning shaders [uts-000H]
some links for learning shaders [uts-000H]
readings
readings
- Ray tracing weekend series [shirley2024ray1][shirley2024ray2][shirley2024ray3] is a good starting point for learning ray tracing.
- The Book of Shaders [vivo2024book] is a good starting point for learning shaders.
- [glassner1989introduction] is a classic book on ray tracing, now free to download here.
- [pharr2023physically] is a complete, illustrative, and physically based ray-tracing renderer book, free to read on line.
- Autodesk Standard Surface contains references to many concepts and formulas for surface shaders.
libraries and tools
libraries and tools
- One could use GlslEditor (which provides widgets to adjust colors, 1-3D numeric values etc.), GlslCanvas or glslViewer to play with the shaders. They are crreated by the authors of The Book of Shaders.
- ShaderMania seems to be a good tool to play with shaders. Similarly there are Shadertoy, which has a VS Code extension and a basic ThreeJS port.
- stackgl provides many packages for using in GLSL. LYGIA is a similar effort, targeting a wider range of languages: GLSL/HLSL/MSL/WGSL/CUDA, it also has great integration with many tools, including ObservableJS.
- For GA, there are miniPGA.glsl, slerp optimization, Spinor 2d, and G2 Multivector-Valued Functions.
- MPR implements [keeter2020massively] on GPU, while Fidget implements it on CPU.
- Easy steps to implementing a Shadertoy in React Three Fiber
- Workflow from Shadertoy to React Three Fiber - R3F
- The Study of Shaders with React Three Fiber
some links for rendering implicit surfaces [uts-000G]
some links for rendering implicit surfaces [uts-000G]
# readings: raymarching on implicit surfaces - [singh2009real] has reviews on related work, an algorithm and many examples. But it has no code. - Ray Marching and Signed Distance Functions is a good introduction to ray-marching and signed distance functions, and the author learns from Inigo Quilez. - Rendering Worlds with Two Triangles with raytracing on the GPU in 4096 bytes by Iñigo Quilez in 2008 - Raymarching Distance Fields in 2013 - raymarching terrains by Iñigo Quilez in 2002 - Volumetric Rendering: Raymarching in 2016 - Painting with Math: A Gentle Study of Raymarching in 2023, which has interative illustration of ray-marching algorithm, and shader examples from simple to complex - CUDA Ray Marching by Jonathan Granskog - Slides on GPU Ray Marching by Alex Benton in 2017–18, with more related materials here. - Ray Tracing Deterministic 3-D Fractals in 1989 - Ray-marching Thurston geometries in 2022 - PU-Ray: Domain-Independent Point Cloud Upsampling via Ray Marching on Neural Implicit Surface in 2024 - Ray Tracing Harmonic Functions in 2024 - Lipschitz-agnostic, efficient and accurate rendering of implicit surfaces in 2024 - What is raytracing/raymarching/raycasting - Ray Marching in JS, the source code has a link to the principle behind ray marching shadows: soft shadows in raymarched SDFs - 2010 - Raymarching Voxel Rendering in 2017 - UC Berkeley CS184/284A Lecture 9: Ray Tracing & Acceleration Structures in 2024 - Third Year and MSc Interactive Computer Graphics in 2008 - Raymarching Distance Fields in 2013 - Perfecting anti-aliasing on signed distance functions in 2025 # libraries and tools: raymarching on implicit surfaces - SURFER renders implicit surfaces using ray-tracing, the result is stunning well. It also has a Java library with many examples. - Raycasting Implicit Surfaces based on CindyJS is Web-based implicit surface renderer using ray-tracing, and the source code is best suited for reproducing and learning. It also has a rich set of examples. - Raycasting a surface of degree 4 is a relatively simpler example of ray-tracing implicit surfaces with source here. - mla has a series of shaders from simple to complicated to render the Kummer surface, see here. mla has also ported a tiny ray tracer here which could be a starting point. - A simpler but more versatile ray-tracer for implicit surfaces is Implicit surfaces created by Rogolop. - 3D Bifurcation Diagram - MA1104-implicitplot has a naive implicit surface plotter. - usegpu.live demo of ploting implicit surface - Surface Plotter makes use of Paul Bourke's Marching Cubes algorithm with edge table, to turn implicit surfaces into polygonal meshes. See Marching Cubes and its references. ## Implicit reconstruction or polygonization - A Heat Method for Generalized Signed Distance in 2024 - Robust Creation of Implicit Surfaces from Polygonal Meshes in 2002 - Curvature Dependent Polygonization of Implicit Surfaces in 2004 - Implicit Meshes for Modeling and Reconstruction in 2018 - Differential Geometry in Neural Implicits in 2022 - Differentiable Iterated Function Systems in 2024 - Adaptive grid generation for discretizing implicit complexes in 2024 - SDFGen: A simple commandline utility to generate grid-based signed distance field (level set) generator from triangle meshes, using code from Robert Bridson's website. Found from Merging Meshes with Signed Distance Fields. - sdf: Generate 3D meshes based on SDFs (signed distance functions) with a dirt simple Python API. - SDFStudio: A Unified Framework for Surface Reconstruction For learning shaders, see some links for learning shaders. Convert some of the links to citations. I would like to have a formal specification of the raymarching algorithm (in algorithm2e or algorithmicx+algpseudocode or even algpseudocodex), and find propositions worth proving.
Distributing my binaries [uts-016P]
Distributing my binaries [uts-016P]
- Repology - brew for mac & linux - personal tap repo: see - Taps (Third-Party Repositories) — Homebrew Documentation - Adding Software to Homebrew — Homebrew Documentation - `create`, `bottle` in brew(1), also `bump*` - Windows or all platforms - Aqua private registery - then supported by mise or maybe more - see Develop a Registry | aqua
Using Zig to build more [uts-016O]
Using Zig to build more [uts-016O]
- C/C++ projects
- All Your Codebase | Loris Cro's Blog
- All Your Codebase
- no GiNaC yet
- help rust to cross-compile
- rust-cross/cargo-zigbuild
- Compile Cargo project with zig as linker for easier cross compiling
- help PyPI to store less
- The Python Package Index Should Get Rid Of Its Training Wheels | Loris Cro's Blog
- zig is also available as a PyPI package
- ziglang · PyPI
- zig alternative to PyO3/maturin: Build and publish crates with pyo3, cffi and uniffi bindings as well as rust binaries as python packages
- spiraldb/ziggy-pydust: A toolkit for building Python extensions in Zig.
- the orginal template that ueses poetry
- the community template that uses uv and hatchling
- where hatchling seems to be a better build backend than setup tools post 3.12 for projects with native extensions and custom build hooks
- see also Why Hatch? - Hatch
interests in early years [uts-0166]
interests in early years [uts-0166]
Year 2023-2024
Year 2023-2024
- 2024-05-28 Export issues and keep them in the repo
- 2024-03-15 Migrate from disqus to giscus
- 2024-02-11 Investigate egg from Lean
- 2024-02-04 Investigate Knot Theory
- 2023-12-23 https://compute.toys/
- 2023-09-03 Investigate formalized philosophies
- 2023-08-23 Investigate Standard Model Lagrangian
- 2023-08-23 Investigate Osamu Tezuka's Astro Boy "Robot Spaceship"
Year 2022 [2022]
Year 2022 [2022]
- 2022-10-04 Digest Lean 4 materials
- 2022-10-04 Digest UvA DL 1&2
Year 2019 [2021]
Year 2019 [2021]
- 2019-04-09 Investigate math related to Origami
Year 2018 [2018]
Year 2018 [2018]
- 2018-10-04 Give up understanding Sir Atiyah's proof
- 2018-10-04 Understand Monad in Haskell and Rust
- 2018-10-04 Investigate queues and locks in C++ and rust
- 2018-09-29 Examine limitations of Floating Point Arithmetic
- 2018-09-26 Investigate Paxos-related with TLA+ in mind
- 2018-08-18 Compile a short list for Rust Introduction
Year 2017 [2017]
Year 2017 [2017]
- 2017-12-01 Learn by solving problems
- 2017-11-07 Try these clouds
- 2017-11-04 Investigate AlphaGo Zero
- 2017-11-04 Investigate OpenCL
- 2017-10-07 Geometric Algebra (GA)
- 2017-02-18 Investigate UX tools and workflow
- 2017-01-19 Loose ends in 2016
Year 2016 [2016]
Year 2016 [2016]
- 2016-12-17 Learn about Alexander Grothendieck
- 2016-11-29 Write a blog about docker
- 2016-11-25 Magic Numbers: Integers
- 2016-11-20 Add plan 2008
- 2016-10-02 Add handy links to site
- 2016-09-14 Add latest poems
- 2016-09-06 Investigate Netflix/SimianArmy
- 2016-09-03 Arts
- 2016-09-01 Write Chinese Ancient Poem Linter
- 2016-08-19 Investigate v8 profiling
- 2016-08-14 Investigate Customer Journey Map
- 2016-08-12 Investigate tiny-dnn
- 2016-08-12 Investigate frp
- 2016-07-18 Investigate Thai Alphabet
- 2016-07-06 Experiment with saguijs/sagui
- 2016-06-29 Investigate Forkner Shorthand
- 2016-06-23 Investigate Collation in MySQL
- 2016-06-19 Collect Chrestomathy for languages I like
- 2016-06-16 Collect good Visual Programming Languages
- 2016-06-10 Consider symbolic DL/Nupic challenges
- 2016-06-10 Investigate the neurobiology of dreaming
- 2016-06-05 Investigate secure tunnels
- 2016-06-05 Literature consumption(Continously updating...)
- 2016-06-01 Find good file syncing solutions
- 2016-05-28 Write a blog about daily Cryptography
- 2016-05-28 Collect building blocks for a bot to answer questions in a Wechat group
- 2016-05-28 Taste Computational Conformal Geometry
- 2016-05-27 Visualize sorting algorithms
- 2016-05-25 Write a blog about my thoughts on Physics
- 2016-05-24 Learn open courses from MIT
- 2016-05-21 Make a slide about Visual Group Theory
- 2016-05-20 Use Overleaf to write papers in LaTeX
- 2016-05-19 Utilize sites to find papers, articles, books and data
- 2016-05-17 Digest ML/NLP/CV/CG reading materials
- 2016-05-17 Select fonts for editors
- 2016-05-13 Select good books from ThoughtWorks Reading Radar
- 2016-05-11 Proofreading tools
- 2016-05-11 Find sites to read open papers
- 2016-05-11 Gather my frequently used git commands
- 2016-05-09 Citation tools
- 2016-05-09 Quantum Computing
- 2016-05-07 Investigate Mac tooling
- 2016-04-30 Add a standalone page to elaborate on my poems
- 2016-04-29 Phonetic algorithm
- 2016-04-28 Archive my Github contributions
- 2016-04-26 Compare SSH and File compare tools
- 2016-04-24 Utilize Julia
- 2016-04-15 Write C++ backend server guide
- 2016-04-08 Find good screen record software
- 2016-03-20 Read through links in chenshuo's book
- 2016-03-19 Look for a new static site generator in node.js instead of ruby
- 2016-03-18 MySQL Server Internal related
- 2016-03-18 Linux Kernel related
Year 2015 [2015]
Year 2015 [2015]
- 2015-12-29 Presentation about js ecosystem based on kuitos/kuitos.github.io/issues/32
- 2015-05-22 Online Judge
- 2015-04-23 Separate excerpts from writings
- 2015-04-23 Investigate Stamplay
- 2015-04-23 Add blogs for latest poems
- 2015-04-23 Add a blog for Interstellar
- 2015-04-22 A new markdown wiki
- 2015-04-22 Rep Star
- 2015-04-22 Build an app for cultivating habits
- 2015-04-22 Establish a timeline for my most valuable experiences
- 2015-04-21 Investigate socket implementation in Linux kernel
- 2015-04-15 Organize my config files
- 2015-04-14 Find good translation collaboration solutions
- 2015-04-09 _ in LaTeX rendered as em
- 2015-04-09 Fix header fonts and link color
- 2015-04-09 Fix identation in syntax highlight
- 2015-04-09 Date the blogs
- 2015-04-09 Investigate drawing tools
- 2015-04-08 Add proof-of-concept implementations
- 2015-04-06 Use Astral to organize my stars
- 2015-03-30 Review algorithms
- 2015-03-30 Write a blog to review basic CG
- 2015-03-30 Learn shader-school and webgl-workshop
- 2015-03-28 Upgrade dependencies to latest version
- 2015-03-18 Read The Book of Shaders and investigate openFrameworks
- 2015-03-13 Collect starred projects from Google Code
- 2015-03-12 Investigate Capstone Engine
- 2015-03-04 Learn Distributed Algorithms
- 2015-03-04 Collect accounts and identities that I seldom use
- 2015-02-23 Investigate Interstellar
- 2015-02-14 Investigate fonts
- 2015-02-03 Investigate open source monitor system building blocks
- 2015-01-23 Investigate stress test and performance tuning
- 2015-01-10 Investigate jsxgraph
Year 2014 [2014]
Year 2014 [2014]
- 2014-12-25 Investigate Evolving Objects (EO)
- 2014-12-21 Apply AviSynth to baby's videos
- 2014-11-12 Find a nice theme to use with IDEA
- 2014-10-29 Investigate GPGPU using WebGL
- 2014-10-27 Investigate cazala/synaptic
- 2014-10-22 Investigate Neural Darwinism and Reentry
- 2014-09-26 Investigate certik/theoretical-physics
- 2014-09-23 Learn SVG better
- 2014-09-22 Investigate FRP (functional reactive programming)
- 2014-09-16 Figure out how to simulate LEGO® MINDSTORMS® EV3
- 2014-09-16 Investigate Khan Academy
- 2014-09-16 Replace MathJax with KaTeX
- 2014-09-10 Investigate tools used by neovim
- 2014-09-04 Write a blog to digest Category Theory
- 2014-08-30 Investigate Linux performance tools
- 2014-08-29 Digest "Readings in Databases"
- 2014-08-26 Investigate Eigen, Manifold ToolKit, GTSAM and Pteros
- 2014-08-26 Investigate Audacity, Sonic Visualiser, Essentia and Gaia
- 2014-08-17 Organize Wolfram Mathematica notebooks
- 2014-08-15 Add blogs about graphing
- 2014-08-12 Setup NuPIC on CentOS
- 2014-08-12 Information Theory, Inference, and Learning Algorithms
- 2014-08-11 Higgs Boson Machine Learning Challenge
- 2014-08-10 Add blogs to consume some of John Baez's work
- 2014-07-19 Add a blog about loop quantum gravity