aboutsummaryrefslogtreecommitdiff
path: root/STYLE.md
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-09-18 12:25:32 +0200
committerhachem <im@hachem.wtf>2026-09-18 12:25:32 +0200
commit17598056a69a14e0390a07251d383f413ded9eea (patch)
tree79cf23ea99072f065407da3e0b92ee03f8972695 /STYLE.md
parentee14ad272e68d9363202d7f668e0b20302827209 (diff)
feat: add matrix, vector, and circuit display + fmt
Diffstat (limited to 'STYLE.md')
-rw-r--r--STYLE.md274
1 files changed, 0 insertions, 274 deletions
diff --git a/STYLE.md b/STYLE.md
deleted file mode 100644
index 856287f..0000000
--- a/STYLE.md
+++ /dev/null
@@ -1,274 +0,0 @@
-# psi C style guide
-
-This document describes the conventions for the C implementation of `psi`. Formatting
-is enforced by [`.clang-format`](.clang-format) and naming by [`.clang-tidy`](.clang-tidy);
-everything a tool cannot check is described here and is expected in review.
-
-The guiding idea: **idiomatic, data-driven C that reads like the Rust original in naming**,
-with Allman bracing as the one deliberate departure from typical C style.
-
----
-
-## 1. Language & build
-
-- **C17**, compiled with `-Wall -Wextra -Werror -pedantic`. Warnings are errors; keep every
- build clean.
-- Build system is **premake5** (`premake5 gmake && make config=release`). Public headers live
- in `include/`, implementation in `src/`, the test runner in `tester/`.
-- Portable across x86_64 and ARM64 (the only supported architectures). Platform-specific code
- (SIMD intrinsics) is `#ifdef`-gated with a scalar fallback.
-
----
-
-## 2. Formatting (enforced by clang-format)
-
-Run before committing:
-
-```bash
-find include src tester -name '*.c' -o -name '*.h' | xargs clang-format -i
-```
-
-CI check (no diffs allowed):
-
-```bash
-find include src tester -name '*.c' -o -name '*.h' | xargs clang-format --dry-run -Werror
-```
-
-### Braces — Allman, everywhere
-
-Opening brace on its own line for functions, structs, enums, unions, and control blocks.
-
-```c
-struct PsiComplex
-{
- double real;
- double imaginary;
-};
-
-double psi_abs_complex(struct PsiComplex z)
-{
- return sqrt(psi_norm2_complex(z));
-}
-```
-
-**Exception (tool limitation):** compound literals keep the brace on the same line as the
-type, because clang-format cannot break it:
-
-```c
-return (struct PsiComplex){
- a.real + b.real,
- a.imaginary + b.imaginary,
-};
-```
-
-### Single statements omit braces
-
-An `if`/`for`/`while` with a single-statement body has no braces; the statement goes on the
-next line.
-
-```c
-if (index >= row->width)
- return;
-
-for (size_t i = 0; i < count; i++)
- sum = psi_add_complex(sum, values[i]);
-```
-
-Use braces once a body has more than one statement.
-
-### Indentation — tabs
-
-Tabs for indentation (width 4). Alignment (e.g. wrapped arguments under an open paren) uses
-spaces, so alignment survives any tab width.
-
-### Pointers bind to the type
-
-```c
-struct PsiComplex* data;
-void psi_free_vector(struct PsiVector* v);
-const size_t* targets;
-```
-
-Not `struct PsiComplex *data`.
-
-### Line length & wrapping
-
-- 100-column limit. Long lines wrap; continuation indents two tabs, wrapped call/parameter
- lists align under the opening paren.
-
-```c
-static void execute_kernels(struct PsiVector* state, const struct PsiKernel* kernels,
- size_t count, size_t num_qubits, struct PsiRuntimeConfig config)
-{
- ...
-}
-```
-
-### Includes
-
-Not sorted by the tool — order them yourself. Convention: system headers (`<...>`) first, a
-blank line, then project headers (`"..."`). `include/psi.h` orders its headers by dependency
-layer, not alphabetically.
-
----
-
-## 3. Naming (enforced by clang-tidy)
-
-| Kind | Convention | Example |
-|------|-----------|---------|
-| Structs | `Psi` + PascalCase | `struct PsiQuantumRegister` |
-| Enums | `Psi` + PascalCase | `enum PsiGateType` |
-| Enum constants | `UPPER_CASE` | `PSI_GATE_H`, `PSI_SIMD_NEON` |
-| Functions | `snake_case` | `psi_add_complex`, `apply_kernel` |
-| Parameters / variables | `snake_case` | `num_qubits`, `target_bit` |
-| Macros / compile-time consts | `THIS_CASE` | `PSI_VERSION_MAJOR`, `INV_SQRT_2` |
-| Function-like macros | `psi_` + `snake_case` | `psi_matrix`, `psi_column_vector` |
-
-### Library prefix
-
-Every **public** symbol is namespaced:
-
-- functions → `psi_...`
-- structs → `Psi...`
-- macros / constants → `PSI_...`
-
-File-local `static` helpers are **not** prefixed (`apply_pair`, `build_pairs`, `op_to_kernel`).
-
-### Data-driven, action-first (not OOP)
-
-The operation leads and the data is an argument — think free functions over data, not methods
-bound to a type. `psi_<operation>_<type>(...)`:
-
-```c
-psi_add_complex(a, b) /* not psi_complex_add */
-psi_new_quantum_gate(...) /* not gate_new(...) */
-psi_apply_gate(&reg, ...) /* verb first */
-```
-
-*Not enforceable by tooling — maintained in review.*
-
----
-
-## 4. Types
-
-- **`double` only** for floating point. No `float`, no fixed-width float aliases (their sizes
- are not guaranteed across platforms).
-- **Fixed-width `<stdint.h>`** types (`uint32_t`, `int64_t`, …) over `int`/`unsigned`/`long`.
-- **`size_t`** for sizes, counts, and indices (the Rust `usize`).
-- **No `typedef` on structs, enums, or unions** — always spell `struct PsiComplex`,
- `enum PsiGateType`.
-
----
-
-## 5. Memory & ownership
-
-There is no garbage collector; ownership is explicit and follows a few rules.
-
-- Every type that owns a heap allocation has a matching `psi_new_*` / `psi_free_*` pair, and
- `psi_free_*` takes a pointer and nulls the freed fields.
-
-```c
-struct PsiVector v = psi_new_vector(4, PSI_COLUMN_VECTOR);
-...
-psi_free_vector(&v);
-```
-
-- **The caller frees.** Functions that allocate and return a value (`psi_add_vector`,
- `psi_clone_matrix`, the gate factories, the renderers' returned strings) transfer ownership
- to the caller.
-- **Read-only args are passed by value**, which shares the underlying buffer and never frees
- it. Mutators and destructors take a pointer.
-- **Constructors that take ownership** consume what they are handed (e.g. a gate takes
- ownership of its matrix; `psi_apply_custom` takes ownership of the custom gate). Builders
- that take an existing value they should not consume make a copy (`psi_new_vector_from`,
- `psi_new_quantum_register_from`).
-- **Allocation idiom:** `sizeof *ptr`, not the repeated type.
-
-```c
-struct PsiKernel* out = malloc(count * sizeof *out);
-```
-
-- Verify with sanitizers during development:
-
-```bash
-clang -std=c17 -Iinclude -Isrc -Itester -fsanitize=address,undefined -g \
- src/psi.c src/**/*.c tester/*.c -o /tmp/psi -lm && /tmp/psi
-```
-
----
-
-## 6. Error handling
-
-- Preconditions and programmer errors (dimension mismatches, out-of-range indices) use
- `assert`. The Rust original returned `Option`/panicked; in C these are `assert`s, since they
- indicate caller bugs rather than recoverable conditions.
-- `malloc`/`calloc`/`realloc` results are `assert`ed non-NULL (with `|| size == 0` where a
- zero-size allocation is legal).
-
----
-
-## 7. Comments
-
-- **Avoid narration.** Code should read on its own; do not annotate ported steps or restate
- what a line does.
-- **Short math-formula comments are welcome** where they clarify an expression:
-
-```c
-struct PsiComplex psi_mul_complex(struct PsiComplex a, struct PsiComplex b)
-{
- // (a + bi)(c + di) = (ac - bd) + (ad + bc)i
- return (struct PsiComplex){
- a.real * b.real - a.imaginary * b.imaginary,
- a.real * b.imaginary + a.imaginary * b.real,
- };
-}
-```
-
-*Not enforceable by tooling — maintained in review.*
-
----
-
-## 8. Project layout
-
-```
-include/ public API (mirrors src/ subtree)
- psi.h umbrella header — includes the whole public API
- maths/ complex, vector, matrix, format, simd
- core/ quantum_components, gates, custom_gate, classical_components,
- circuit, kernel, runtime, noise
- visualizer/ renderer
-src/ implementation, same subtree; may also hold private headers
-tester/ assertion-based test suite
-```
-
-- Headers are `#pragma once` and included **root-relative**: `#include "maths/complex.h"`.
-- `include/psi.h` is the umbrella: `#include <psi.h>` pulls in the entire public API. Add each
- new module's public header to it.
-- Private, implementation-only headers live under `src/` (e.g. `src/visualizer/grid.h`).
-
----
-
-## 9. Testing
-
-- `tester/` is an assertion suite with subcommands
- (`clifford`, `non-clifford`, `custom`, `kernels`, `simd`, `noise`, `all`, `help`).
-- Tests assert against known states (Bell, GHZ, rotations, fusion, noise purity, …) and check
- that all runtimes agree. The process exit code reflects pass/fail (CI-friendly).
-
-```bash
-premake5 gmake && make config=release
-./bin/release-<system>/tester # all suites
-./bin/release-<system>/tester noise # one suite
-```
-
----
-
-## Tooling summary
-
-| Concern | Tool | Command |
-|---------|------|---------|
-| Formatting | clang-format | `... | xargs clang-format --dry-run -Werror` |
-| Naming | clang-tidy | `clang-tidy <file> -- -std=c17 -Iinclude -Isrc` |
-| Build | premake5 + make | `premake5 gmake && make config=release` |
-| Tests | tester | `./bin/release-<system>/tester` |
-| Leaks / UB | sanitizers | build with `-fsanitize=address,undefined` |