Skip to content

Instantly share code, notes, and snippets.

@Hafthor
Hafthor / SpanExtensions.Partition.cs
Last active March 28, 2026 23:33
Partition algorithm (Bentley-McIlroy three-way/fat partitioning)
using System.Diagnostics;
public static class SpanExtensions {
/// <summary>
/// Partitions a span. Useful if you want the smallest/largest k elements of a list without sorting the whole list.
/// This is a generalization of the partition step of quickselect.
/// </summary>
/// <param name="array">source array</param>
/// <param name="k">desired split point</param>
/// <param name="comparer">optional comparer to use instead of the default for the type</param>
@Hafthor
Hafthor / nosuppress.cs
Last active July 16, 2025 16:05
Why you shouldn't call GC.SuppressFinalize(this) unless you directly have a finalizer
public class MyClass : MyDerivedClass {
public override void Dispose() {
base.Dispose();
GC.SuppressFinalize(this); // here we improperly call GC.SuppressFinalize(this)
}
}
public class MyDerivedClass : MyBaseClass {
public override void Dispose() {
; // oops, we forgot to call base.Dispose();
@Hafthor
Hafthor / RSAExplainer.cs
Last active July 15, 2025 00:43
Explanation of how RSA encryption and signatures work
using System.Diagnostics;
int p = 23, q = 29; // two private primes
int pubMod = p * q; // 667, the neighbor of the beast
// In practice, the primes used are crazy big (1024-bit each), making it infeasible to factor pubMod (2048-bit).
// Even if you could try 4B factors a second, on 4B machines, each with 4B CPUs, for 4B seconds (~126 years), you
// could only explore 128-bits worth of possibilities! And that doesn't mean you're an eighth of the way there. It
// would be if the number were 131-bits in length. Each extra bit doubles the effort required.
int pubExp = 257; // third Fermat prime (2^2^n+1, where n=3)
// The real RSA uses the fourth, and believed to be the last, Fermat prime, 2^2^4+1=65537.
@Hafthor
Hafthor / DHECExplainer.cs
Created July 13, 2025 18:16
Explanation of how Diffie Hellman Elliptic Curve Key Exchange works
// Example:
// E: y^2 = x^3 + 2x + 2 (mod 17) - a=2, b=2
// G: (5, 1)
using Point = (int x, int y);
int a = 2, b = 2, mod = 17, Z = 19; // y^2 = x^3 + 2x + 2 (mod 17)
Point g = (5, 1); // G: (5,1)
Console.WriteLine($"G:{g}");
@Hafthor
Hafthor / floatradix.js
Created April 10, 2021 23:45
non-decimal non-integer stuff
// like parseFloat, but takes an optional radix
function parseFloatWithRadix(s, r) {
r = (r||10)|0;
const [b,a] = ((s||'0') + '.').split('.');
const l1 = parseInt('1'+(a||''), r).toString(r).length;
return parseInt(b, r) +
parseInt(a||'0', r) / parseInt('1' + Array(l1).join('0'), r);
}
// like Number..toFixed, but takes an optional radix
@Hafthor
Hafthor / httprelay.js
Created August 17, 2011 20:33
http relay using node.js
var http = require('http');
http.createServer(function (req, resp) {
var h = req.headers;
h.host = "stackoverflow.com";
var req2 = http.request({
host: h.host, port: 80, path: req.url, method: req.method, headers: h
}, function (resp2) {
resp.writeHead(resp2.statusCode, resp2.headers);
resp2.on('data', function (d) { resp.write(d); });
resp2.on('end', function () { resp.end(); });
@Hafthor
Hafthor / gcf.cs
Last active November 19, 2022 19:45
Greatest Common Factor using Euclid's algorithm and, gasp, gotos to be fast (about 50% faster)
static long gcf(long m, long n)
{
if (m < n) goto l2;
l1: if ((m %= n) == 0) return n;
l2: if ((n %= m) == 0) return m;
goto l1;
}
@Hafthor
Hafthor / ForwardCopy.cs
Last active August 21, 2022 00:22
Works like Array.Copy or Buffer.BlockCopy but with memcpy forward only operation vs memmove
public static void ForwardCopy(byte[] s, uint si, byte[] d, uint di, uint cx) {
unchecked {
// pre copy to qword align to destination
uint cxpre = (8 - (di & 7)) & 7;
if (cx < cxpre) {
// early out if we cannot even align to the first qword
for (int i = 0; i < cx; i++)
d[di++] = s[si++];
return;
}
@Hafthor
Hafthor / UnsafeCompare.cs
Last active August 7, 2022 05:11
Fast compare for byte arrays in .NET - uses unsafe code to compare by casting as longs
// Copyright (c) 2008-2022 Hafthor Stefansson
// Distributed under the MIT/X11 software license
// Ref: http://www.opensource.org/licenses/mit-license.php.
static unsafe bool UnsafeCompare(byte[] a1, byte[] a2) {
unchecked {
if(a1==null || a2==null || a1.Length!=a2.Length)
return false;
fixed (byte* p1=a1, p2=a2) {
byte* x1=p1, x2=p2;
int l = a1.Length;
@Hafthor
Hafthor / DisposableList.cs
Created August 7, 2022 04:53
For making a list of disposable items. Useful since you can using wrap the list create and add disposable items to it, like FileStreams.
public class DisposableList<T> : List<T>, IDisposable where T : IDisposable {
public void Dispose() {
foreach (var i in this) i.Dispose();
}
}