Skip to content

Instantly share code, notes, and snippets.

@vurtun
vurtun / anim_blend.c
Last active March 26, 2025 08:19
animation sampling
#include <immintrin.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#define MAX_MDLS 2048
#define MAX_ANIMS 256
#define MAX_JOINTS 256
#define ALIGN32 __attribute__((aligned(32)))
@vurtun
vurtun / bit_set.c
Last active February 5, 2025 09:50
#include <immintrin.h> // For AVX2
#define MAX_SIZE (64*1024)
#define BITS_PER_WORD 64
#define WORD_CNT ((MAX_SIZE + BITS_PER_WORD - 1) / BITS_PER_WORD) // 1024 words
#define BIT_MAP_CNT ((WORD_CNT + BITS_PER_WORD - 1) / BITS_PER_WORD) // 16 words
#define WORD_SHIFT 6 // log2(BITS_PER_WORD)
#define WORD_MSK (BITS_PER_WORD - 1) // 63
#define CHUNK_CNT (BIT_MAP_CNT/4)
#define CACHE_LINE_SIZE 64
@vurtun
vurtun / math.c
Last active November 21, 2024 10:37
pure C vector math
/* ---------------------------------------------------------------------------
* Vector
* ---------------------------------------------------------------------------
*/
/* vector */
#define opI(r,e,a,p,b,i,s,I)((r)[I]e(a)[I]p((b)[I]i(s)))
#define opsI(r,e,a,p,s,I) ((r)[I]e(a)[I]p(s))
#define setI(d,x,I) (d)[I]=(x)
#define dotI(a,b,I) (a)[I]*(b)[I]
#define lerpI(r,a,b,t,I) lerp((r)[I],(a)[I],(b)[I],t)
@vurtun
vurtun / rdp.c
Last active October 15, 2024 07:03
Ramer-Douglas-Peucker line simplification
#include <assert.h>
#include <math.h>
#include <stdio.h>
/* Alternative design: Iterate over path and at each point i check distance to line with points
i + 1 and i + 2 and skip i + 1 when distance is small than epsilon. */
static float
line_dist(const float *p, const float *p1, const float *p2) {
float dx = p2[0] - p1[0];
float dy = p2[1] - p1[1];
@vurtun
vurtun / kth.c
Last active May 23, 2024 18:34
print K largest(or smallest) elements in an array
/* Problem: Directory file view ui. Files can be sorted by different properties (name, size, ...). Ui itself only needs elements
that are currently in the visible section of the list view from x and count k. So I want to use a fixed size buffer with up to k elements
and walk through all files in the directory and only have the final elements in the end in the fixed size buffer.
Temp buffers are fine for me as long as they have a fixed at compile time size. For those familiar with SQL basically this is
a SORT BY LIMIT begin, count.
Idea: Use FloydRivest algorithm with average O(n) to find the element at index x. Walk over list again and skip all elements smaller than x
then use heap to sort for the k smallest elements afterwards. So we have for FloydRivest and heap combined O(n*log(k))
Problem: Find x is not directly possible since not all elements are in memory because we have only fixed size buffer.
@vurtun
vurtun / fold.c
Last active October 13, 2024 16:57
unicode case folding
// Selection algorithm
// Partial sorting
// http://www.unicode.org/Public/UCD/latest/ucd/CaseFolding.txt
switch(rune) {
case 0x0041: return 0x0061; // LATIN CAPITAL LETTER A
case 0x0042: return 0x0062; // LATIN CAPITAL LETTER B
case 0x0043: return 0x0063; // LATIN CAPITAL LETTER C
case 0x0044: return 0x0064; // LATIN CAPITAL LETTER D
case 0x0045: return 0x0065; // LATIN CAPITAL LETTER E
@vurtun
vurtun / burg.c
Last active March 13, 2024 08:22
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#define szof(a) ((int)sizeof(a))
#define cntof(a) ((int)(sizeof(a) / sizeof((a)[0])))
static void
@vurtun
vurtun / aoc.c
Last active December 8, 2023 09:34
AoC 2023
#include <stdio.h>
#include <limits.h>
#define byte4_dup(c) (((c)<<24u)|((c)<<16u)|((c)<<8u)|(c))
#define byte4_cmp_lt(x,n) (((x)-~0UL/255u*(n))&~(x)&~0UL/255u*128u) // x>=0; 0<=n<=128
#define byte4_cmp_gt(x,n) (((x)+~0UL/255*(127-(n))|(x))&~0UL/255*128) // x>=0; 0<=n<=127
#ifdef _MSC_VER
static int bit_ffs32(unsigned int u) {_BitScanForward(&u, u); return (int)(u);}
static int bit_fls32(unsigned int u) {_BitScanBackward(&u, u); return 31-(int)(u);}
@vurtun
vurtun / obj_filter.c
Last active March 3, 2025 08:53
object string filter using sse2, avx2, neon
/* This algorithm uses as a predicate equality of the first and the last characters from the substring. These two characters are populated in two registers
* F and L respectively. Then in each iteration two chunks of strings are loaded. The first chunk (A) is read from offset i (where i is the current offset)
* and the second chunk (B) is read from offset i + k - 1, where k is sub string's length. Then we compute a vector expression F == A and B == L.
* This step yields a byte vector (or a bit mask), where "true" values denote position of potential substring occurrences.
* Finally, just at these positions an exact comparisons of sub strings are performed.
*
* Example: Let's assume 8-byte registers. We're searching for word "cat", thus:
*
* F = [ c | c | c | c | c | c | c | c ]
* L = [ t | t | t | t | t | t | t | t ]
@vurtun
vurtun / perm.c
Last active October 13, 2023 08:58
Array shuffle
#define xglue(x, y) x##y
#define glue(x, y) xglue(x, y)
#define uniqid(name) glue(name, __LINE__)
#ifdef _MSC_VER
#define swap(a,b) do { decltype((a) + 0) _t = (a); (a) = (b); (b) = _t; } while(0)
#else
#define swap(a,b) do {__typeof__((a) + 0) _t = (a); (a) = (b); (b) = _t; } while(0)
#endif