Latent math
Blend, distort and edit latents without ever decoding
- V
- F
- Expression
- stack
- LATENT
- STACK
Latents are where diffusion actually happens, and most people never touch them - they decode to pixels, edit pixels, re-encode, and eat a quality hit and a bunch of VRAM doing it. Latent math from More Math lets you do the edits where the model lives. It's the same expression engine as the image node, but running on the latent tensor itself.
Why you'd bother
The classic move: blend two latents instead of two images. Interpolating in latent space is how a lot of "morph between two generations" workflows work, and doing it before decode is cheaper and smoother than decoding both, blending, and re-encoding. The default expression is the familiar I0*(1-F0)+I1*F0 - a lerp between latent V0 and V1 by float F0. Bump F0 through a schedule and you've got a latent-space animation. You can also add noise directly in latent space (I0 + perlin(...)), or apply blur and fft to the latent tensor if you're experimenting with frequency-domain edits.
Since latent tensors are just 4D float tensors, everything in the shared function library applies: smoothstep, remap, tmin/tmax, where, shape, flatten, even dilate/erode (which are less meaningful on latents, but they run). The image-style variables work too - X, Y, W, H, C, B, T - so you can write spatial edits over the latent grid.
Inputs and outputs
V is the autogrow list of latents (V0, V1, ...), F the floats, Expression the formula. length_mismatch (error/tile/pad) covers differing batch sizes, and batching controls how many latent samples evaluate per pass - leave it at 0 unless you're running out of VRAM, since latent tensors are small relative to images.
Outputs are LATENT (a list) and STACK. Feed the latent straight back into a KSampler or a second sampling pass - that's the whole trick, staying in latent space end to end.
Installing it
Identical to the rest of the pack:
cd ComfyUI/custom_nodes
git clone https://github.com/mcDandy/more_math
cd more_math
pip install -r requirements.txt
Restart, or grab "More math" from ComfyUI Manager. One real dependency (antlr4-python3-runtime) beyond torch. No models.
The sharp edges
Latent values don't have a friendly 0–1 range like masks - they're roughly centered near zero with an unbounded spread, so formulas written for images (say, clamp(I0, 0, 1)) will wreck a latent. Keep expressions in "blend and nudge" territory and you'll be fine; go wild and you'll get noise, sometimes interesting noise, sometimes garbage. Also watch the channel count: latents are 4 channels, not 3, so channel-conditional expressions should treat C as going 0–3. And as with the whole pack - it's new, solo-maintained, and still settling, so pin a version you like before building a production workflow on it.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| V | COMFY_AUTOGROW_V3 | — | |
| F | COMFY_AUTOGROW_V3 | — | |
| Expression | STRING,SYNTAX_TREE | V0 | Expression to apply on input latents |
| length_mismatch | COMBO | error | How to handle mismatched latent batch sizes. tile: repeat shorter inputs; error: raise error on mismatch; pad: treat missing frames as zero. |
| batching | INT | — | |
| remember_stack | BOOLEAN | false | If enabled, stack is copied at output leading to changes being remembered during batch operations (node runs multiple times in sucession). If disabled each batch gets it's own copy of the stack. |
| use_compute_device | BOOLEAN | true | Temporarily copies latent tensors to the compute device for math and moves the result back afterwards. |
| stackopt | STACK | Access stack between nodes |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| LATENT | LATENT | — |
| STACK | STACK | — |