393 karma · joined April 27, 2014
like this:
D ~ unif_int(1, 6); Print("P(rolled a 6 | rolled > 3) =", P(D == 6 | D > 3));
or:
loss ~ unif(0, 1000); claim = if loss > 200 { loss - 200 } else { 0 }; p = P(claim > 0); Print("P(insurer pays a claim) =", p)
notice that "claim" is also a random variable! result of a if expression
What noiselang does it parse, convert to a execution graph then carefully use the Cranelift api to describe the program, and under the hood, it will find different opetimization and generate byte code that runs directly in the host CPU.
The reason for it to be killer is that it allows NoiseLang to run as native speeds, with very little compiler/optimization work. it's a very simple repo.
For the RNG, this was a discovery myself, when profiling, i found the many benchmarks were limited by the speed of the RNG itself, ie, if i could genenrate random numbers faster, the simulation would be faster. xoshiro's next number is computed from its current state. So to get number N+1 you must have finished number N. It's a chain: A → B → C → D. Your CPU can run maybe 6 integer operations per cycle, but a chain only ever offers it one to run. Five of the six lanes sit empty.
I tried to use SIMD to speed this up, but still hit the limit, even if using SIMD, it still had to wait for the next number, a massive speed up came from realizing that i can keep four independent xoshiro256++ states and emits four samples per loop iteration, i += 4. Since the four state-update chains share no registers, the out-of-order core issues them in the same cycles instead of stalling on one serial chain.
SIMD gives you more work per instruction. But I wasn't short on work, I was waiting. A 2-wide xoshiro still needs state N before it can compute state N+1, so the chain is the same length and I wait at every link, I just get two numbers per link instead of one.
And each link costs more. xoshiro rotates a 64-bit word every round, and NEON has no 64-bit rotate, so that becomes three instructions instead of one. Twice the numbers, three times the wait.
Four streams wins because it leaves the chain alone. It just runs four of them at once, and the CPU was already idle enough to overlap them for free.
For the scope of the language it never even comes up, because Noise is a simulator, it does not evaluate densities, it draws samples.
The point is that every value goes through the same operators. Add them, compare them, pass them to a function, put one in the condition of an if. You can even use a random variable to define another random variable:
bias ~ unif(0, 1) flips ~[10] bernoulli(bias) // bernoulli just took a distribution where a number normally goes.
and in if-stataments:
DistributionC = if DistributionA < DistributionB { 0 } else { 1 }
But you right, dirac only applies to continuous functions, in Noise is only refers to the dirac measure. I found this article a fun/nerd to make my point that everything "acts" as a distribution from the DX perspective, but under the hood 5 is just 5.
And a constant collapses back to a plain integer in the graph anyway, so 5 costs nothing.
Fair! My thinking was that PM of a single tone signal (the one i use in the demo is equivalent to FM, but shifted a bit). And implementing real FM for decoding is a lot more noisy, but I will add some callout in the article.
Truth be told, you motivated me to write the exact FM with the differenciation, maybe. Could be interesting to simulate PM vs FM for non single tone signals, to see how FM does even better!
The engine is Rust, the JIT is built on Cranelift, there is also a WASM backend so everything runs in the browser too.
Full disclosure, I could only finish it now because of AI agents. In my experience they are amazing at the runtime and the numerical code, but pretty bad at language design, so I kept that part for myself.
It's a toy language. Ask me anything!
A lot good content here too: https://qwik.builder.io/media/
That's my dilemma:)
There is nothing like "window.stencil" or any stencil related API in the output of the stencil compiler. It generates vanilla JS web components without dependencies.
The documentation of stencil linked in this HN post was in fact created with stencil itself. Just open the Dev Tools!
var engine = gin.default();
engine.get("/back", CandyJS.proxy(function(ctx) {
var future = time.date(2015, 10, 21, 4, 29 ,0, 0, time.UTC);
var now = time.now();
ctx.json(200, {
future: future.string(),
now: now.string(),
nsecs: future.sub(now)
});
}));