0
- VODs are on my YouTube channel: @l-mdotdev.
- Streams are on Twitch: lmdotdev.
- Come meet me on Discord: Zy7P3pfQxR.
2025-12-16. Stream schedule now is every Wednesday and Friday (AEST).
▄▄▌ • ▌ ▄ ·. ██• ·██ ▐███▪ ██ ▪ ▐█ ▌▐▌▐█· ▐█▌ ▄ ██ ██▌▐█▌ .▀▀▀ ▀▀ █▪▀▀▀
https://l-m.dev - © l-m.dev 2023
Welcome! - 13 total posts. [LATEST]
0
2025-12-16. Stream schedule now is every Wednesday and Friday (AEST).
1769551200
[ stream-lean | stream-math ]https://github.com/l1mey112/methlib4
Probably going through a lot of elementary finite group theory notions.
Euler’s Theorem, Fermat’s Little Theorem, existence of right inverses for a surjective function, existence of left inverses for an injective function.

commit f303cb765cb7364abc29ff67be02f73dbecd6313
Author: l1mey112 <[email protected]>
Date: Wed Jan 28 11:50:54 2026 +1100
functions(#1769551200): left and right inverses for injective and surjective
commit 18195633cced356a78f56652ba83d605b2c76363
Author: l1mey112 <[email protected]>
Date: Wed Jan 28 10:09:18 2026 +1100
GT(#1769551200): proof of euler's and fermat's theorem
1769119200
[ stream-lean | stream-math ]https://github.com/l1mey112/methlib4
Proven! This took me a very long time but the result is stronger than
what they have in Mathlib, they don’t depend on
[Finite G].

1768514400
[ stream-randomxjs ]VOD: https://www.youtube.com/watch?v=mhvT87FZlIo
https://github.com/l1mey112/randomx.js
Agenda. FMA does work, and it’s a lot faster now. There are only two main things to do with the project:
Improvements to the code generator (improving JIT code patterns):
Implementation of a proof of concept webminer:
Attempted implementation, just continue on from here.
1768255200
[ stream-randomxjs ]VOD: https://www.youtube.com/watch?v=15CYHO-vHf0
More of the same today, except stream is a day early.
https://github.com/l1mey112/randomx.js
Agenda. I need to look into the FMA issues so I can decide whether or not to gut it from the VM/build, or make it a requirement if I’m able to re-enable it on the JIT side.
tests(#1768255200): make tests use vitest instead of bun test (testing on node + bun)
jit+semifloat(#1768255200): enable and fix the FMA semifloat (JIT_FMA)
FMA works!! See: https://github.com/l1mey112/randomx.js/issues/1#issuecomment-3741184392
It was entirely due to my own stupidity. Hopefully I can be redeemed later.

I am seeing +0.5 to 1.0 H/s already, so this seems quite
good.
This is more like a +5 H/s. Much better!

1767909600
[ stream-randomxjs ]VOD: https://www.youtube.com/watch?v=-EyorAXC8S8
RandomX.js is a library that I worked on while I was finishing highschool, it basically implements calculating RandomX hashes in the web (previously, web mining wasn’t possible for 5+ years or so).
https://github.com/l1mey112/randomx.js
Zero to RandomX.js: Bringing Webmining Back From The Grave - Linux Society UNSW 2025
I’m going to take the time to modernise it, make it nicer, fix the build system maybe. Then, I’ll see if I can port tevador/equix to the web as well.

Agenda (forever).
1767736800
[ stream-lean ]VOD: https://www.youtube.com/watch?v=-jTTxv9WvNw
Agenda. From last time to now has been entirely
cleanup. I’ve moved a lot of the modules around and fleshed out the
lemmas for the most basic optimisations (like x + 0 ~> 0
for example).
The opt_rw lemma tactic is now orw [lemma]
to be in line with rw.

There are a decent amount of issues when encoding annoying to use
hypotheses around the instructions that need it. For example a
(h : (b : iN n) < n) is quite unwieldy for the user and
proving side.
For example Pow2 over iN could be
proven if you’re plugging in the value of a shift into
Pow2.
Focus on not exposing a Lean specific encoding of the hypotheses,
for example, instead of n ≥ 2 write WGt 2 or
WidthGt 2.
Each hypothesis can become a decidable instance as well.
1767304800
[ stream-lean ]VOD: https://www.youtube.com/watch?v=0uuknejR_No
Agenda. Last stream only denoting and reification have been implemented, and the beginning of proof chaining was being done. Between this stream and now I actually got proof chaining done though.
An example is this, so given an optimisation function
impl and a proof that the function implements a correct
optimisation in wf together they make a Rule
which describes an optimisation.
You can apply that rule using the ⟦ opt : func ⟧ syntax
(which is for debugging really), and end up with a new function + a
proof that the old function (before optimisation) is equivalent (up to
UB) to the new one.

To deal with the walker + rewrite issue (proof of termination), need to show confluent rewriting rules (that is, the repeat rewriting terminates). So another framework needs to be implemented.
Other than that, the implementation of reassoc' was a
pretty good benchmark.

The proof of the optimisation’s validity is a simple induction argument.
1767132000
[ stream-lean ]VOD: https://www.youtube.com/watch?v=Ag0aRR65YgM
Agenda. The blocker with reifying variables has been solved, so I can just go and do the rest of reification and probably get done with denoting today as well.
experiments: restructure modules
experiments: reify reduced size of proof term
experiments: reifying `+nsw`
experiments: got over `IR.eval .var` hurdle
1766700000
[ stream-lean ]VOD: https://www.youtube.com/watch?v=9EN1jA2Q57c
Agenda. After the previous stream I realised that
optimisations should work as functions over an AST (not a Lean
Expr!). Doing optimisations functions over an AST allows
you to prove things a lot easier, but requires a lot more work in the
form of denotational semantics.
I promised myself I would never go anywhere near those things, but it absolutely makes sense if you want to transpile these verified optimisations to other programs (for example, export optimisations to C for someone’s optimiser).
reassociate.
1766527200
[ stream-lean ]VOD: https://www.youtube.com/watch?v=2rChq0gwhxo
Agenda. Blog post has been released: https://l-m.dev/cs/formally-verifying-peephole-optimisations-in-lean/.
Between last stream and this stream, the theorem

was proved. This wasn’t what I expected, but it makes sense. I always
thought of x <~> y meaning that the “definedness” of
x is the same as y. But, apparently they’re
equal.
So now the RewriteIff := x ~> y ∧ y ~> x relation
has been removed from the codebase and replaced with equality. Theorems
that rewrite back and forth are replaced with equality like here:

ideal directory contains the canonicalisations (the
“ideal” forms). At the moment, canon will just be a simple
simplifier but might become an SoN-esque worklist optimiser later.opt/the framework is just to be a low level wrapper
over actual optimisation functions. Eventually you would want to prove
these correct as well, but the initial implementation should be amenable
to rewrite proofs (proof of confluence, etc).1766095200
[ stream-lean ]VOD: https://www.youtube.com/watch?v=lY1GF-8sdsA
Agenda. Getting stuff done in /stream/1765922400 served to be quite
annoying. The most important part is encoding the theorem below in a
nice way that is amenable to automatic and manual proofs (of any
bitwidth n).

That’s the goal of this stream.
simp with restriction to certain
theorems/definitions first.After this stream today I’m going to upload both stream VODs and create a blog post about the project itself as a better introduction, before next week.
Formalised a proof of addNsw_assoc_all_pos, which is
actually very close to what I wanted to get done.

1765922400
[ stream-lean ]VOD: https://www.youtube.com/watch?v=IcyFhrWyzdg
Work on https://github.com/l1mey112/bitbasher.
Agenda.
theorem congrApp {n} (f : iN n → iN n)
{wf : f poison = poison := by opt_poison_input}
{a a' : iN n} (h : a ~> a') : f a ~> f a'
noUb, wF, ubEquiv',
ubEquiv, whatever works.)Proving.
1. Prove by rewriting based on what you already know (human).
2. Prove by the semantics of the actual program (human).
3. Automatically prove (machine).
At the moment, (1), (3). I guess we need (2).
/-
(h :
(x ≥ₛ 0) &&& (y ≥ₛ 0) &&& (z ≥ₛ 0) ~> 1 ∨
(x <ₛ 0) &&& (y <ₛ 0) &&& (z <ₛ 0) ~> 1)
-/
def hyp {n} (a b c : BitVec n) :=
!(a.sle 0) && !(b.sle 0) && !(c.sle 0) ∨
(a.slt 0) && (b.slt 0) && (c.slt 0)iN_convert_goal_bitvec there should be
another SimpSet to further reduce to the definition but don’t go further
than BitVec.@[opt ideal]
theorem add_zero {n} (x : iN n) : x + 0 ~> x := by
iN_convert_goal_bitvec
/-
case bitvec
n : Nat
a✝ : BitVec n
⊢ bitvec a✝ + 0 ~> bitvec a✝
-/simp only [iN_simp] you end up with the
below which isn’t really useful because you’re not going to the
definition. I would want to convert ~> bitvec to
something.⊢ (bitvec a✝).pBind₂ (bitvec 0#n) iN.add? ~> bitvec a✝