M: Are you able to program in the program spelled P-I-E-T, or rather the programming language? I'm going to pronounce it as P-I-E-T, although I have no idea what the transcriber will record that as.
G: [Non-text content: thoughts; content_type=thoughts]
G: [Non-text content: reasoning_recap; content_type=reasoning_recap]
G: Yeah, I can work with Piet (the esoteric, image-based programming language), at least to a useful degree.
日本語: ピート言語(げんご)でも すこし てつだえます。
– I can help a bit even with the Piet language.
What I can do:
Limits / caveats:
If you want to play with Piet here, we can start with something modest like:
Tell me what kind of toy program you’re thinking about and I’ll sketch the Piet design for it.
M: I was thinking it would be interesting to see if you could create a code picture, I guess. Anyway, a Piet program that could produce a version of the Mandelbrot set. I know it's at least technically possible in some form simply because I got a TI-81 to be able to do Mandelbrot creation within a limited capacity, including being able to define the... What were they? The parameters of the zoom on the fly. The question is what it would look like and whether it could be manipulated so that it itself looked like some kind of fractal.
G: [Non-text content: thoughts; content_type=thoughts]
G: [Non-text content: reasoning_recap; content_type=reasoning_recap]
G: Short version:
A Mandelbrot generator in Piet is theoretically absolutely
doable, and you can design the image so the code
itself has a fractal-ish repeating pattern.
In practice, a full nice-resolution one is huge and nasty to hand-craft;
what I can realistically do here is:
日本語: プログラム(ぷろぐらむ)は つくれます。– You can make the
program.
日本語: でも じっさいは とても むずかしいです。– But in practice it’s
very difficult.
Mandelbrot in any language boils down to:
(px, py)c = x + yi in some
window.z_{n+1} = z_n^2 + c until either:
|z| > 2 (diverges), orOn your TI-81 you did all this with numeric loops and a screen buffer; Piet has to do it using:
So conceptually it’s the same algorithm, but implemented as a 2D maze where the “ball” (DP/CC) rolls around doing math.
Imagine the Piet program as being divided into repeating tiles, each tile handling one pixel or one column:
Core modules you need:
Coordinate generator
px,
pyx = x_min + px * dx,
y = y_min + py * dyroll, dup,
swap)(x, y) and increments
(px, py).Mandelbrot iterator
(x, y) as c, initializes
z = 0zx² - zy²2*zx*zyc back initerationzx² + zy² > 4? → if yes, break; else loop.Output module
iteration (0..maxIt) to output symbol (e.g., ASCII
char from ‘ ’ to ‘@’).out as
character.Scan-line driver
pxpx == width, reset px and increment
pypy == height, halt.All of these live as regions of colored blocks. If you use a very regular layout (e.g., a rectangular “gear” for each of those), then your code picture naturally becomes tiled and somewhat fractal-ish at a macro scale.
A few practical pain points:
So: yes, possible, but a serious “art installation” project, not a quick doodle.
If we built a real one, we’d almost certainly:
Now, your actual question twist: can the Piet program be arranged so that it looks like a fractal?
You can’t get true mathematical self-similarity and correct execution without insane care, but you can absolutely get visual pseudo-fractals:
Visually, this could look like a Sierpinski-ish carpet of small “circuit boards.”
Zoomed out, you get a B&W-ish Piet spiral that feels fractal; zoomed in, it’s just the normal instruction mesh.
This is a bit meta: you don’t have the code itself be globally fractal, but you:
To a viewer, the image looks like a fractal wedge embedded in a circuit.
Given the size of a real Mandelbrot Piet program, I can’t spit out a full working image in text form that you could immediately copy into a Piet editor — it’d be massive and fragile.
What I can reasonably do is:
c, small max iterations,
just prints whether it diverged or not).width, heightx_min, x_max, y_min,
y_maxIf you want to push this further, the next step would be: I’ll build a tiny Piet layout that does one of:
c and prints a
character, orFrom there we could talk about how to repeat/scale that into something that visually echoes a fractal.
M: Let's start with a couple of the necessary basics. Like the little bits that eventually grow into things. First, you said that you would need to design a Pyatt Python interpreter. That might be busy work. Can you go online and see what kind of practical creation tools there are for programming in Pyatt? I don't expect visual studio level professionalism, but it's such a quirky idea that I don't believe that there isn't at least something out there in some form that isn't just half-finished. It might not be great, but it still would be easier. Or at least, if it turns out to be complete crap, I could take a look at it and explain to you why it's complete crap so that your personalized version wasn't falling into the same traps. And then also see if you can find online any examples of Pyatt being used to handle floating point numbers, either elegantly or through brute force. And if so, if there's any kind of indication or documentation of what was done, how things were handled, and what kind of technical crap might have gotten thrown up along the way.
G: [Non-text content: thoughts; content_type=thoughts]
G: [Non-text content: thoughts; content_type=thoughts]
G: [Non-text content: thoughts; content_type=thoughts]
G: [Non-text content: thoughts; content_type=thoughts]
G: [Non-text content: thoughts; content_type=thoughts]
G: [Non-text content: thoughts; content_type=thoughts]
G: [Non-text content: reasoning_recap; content_type=reasoning_recap]
G: Short answer:
日本語: ピート用(よう)の ツールは いくつか あります。– There are
several tools for Piet.
日本語: ふつうは ふろーと数(すう)は つかわずに せいすうで
まねします。– Normally you emulate floats with integers instead of using
real floats.
Here are the ones that look mature enough to actually use and/or dissect:
npietedit (a simple GUI editor) and
npiet-foogol (a higher-level language that compiles to
Piet). citeturn1search0For you on Fedora, npiet is likely the easiest “serious”
one to install and script around.
This is a good place to play with designs for small Mandelbrot building blocks.
This one is more “modern eye candy + examples”; good for poking around but PietDev looks more debug-oriented.
If you want a local GUI with stepping and breakpoints instead of browser-based, Pietron’s the candidate.
Paintings
directory with sample programs like compressed binaries and
Mandelbrot-related demos. citeturn3view0turn4view0So yeah: there’s absolutely enough tooling that writing a Python interpreter from scratch is optional busywork, not a prerequisite.
I went hunting specifically for:
So: Piet itself is integer-centric, and interpreters don’t secretly give you IEEE-754 toys.
The best “non-toy” numeric examples are on Morgan-Mar’s Piet Samples page: citeturn5view0
Pi program – Richard Mitton’s Pi calculator (“Pi” sample).
Prime tests, day-of-week calculator, power function, Euclid’s algorithm, etc.
I also looked at related bits:
Net result:
I did not find any publicly documented example of:
If it exists, it’s buried in someone’s personal repo without obvious keywords.
There is an esolang Floater that was explicitly inspired by Piet and does provide floating-point operations directly (RND pushing a random floating-point, rounding functions, etc.). citeturn2search18turn1search16
That’s not Piet, but it’s a useful data point:
When someone wanted “Piet-like but with floats,” they just designed
another language rather than forcing floats into Piet’s semantics.
That strongly suggests: in the Piet world proper, you’re expected to use:
Given what’s actually out there, the realistic strategies are:
Fixed-point integers on the Piet stack
scale = 1000 → store
x_real as int(x_real * 1000 + 0.5).add/sub: just add/sub and keep track of scaling.mul: multiply, then divide by scale.div: multiply numerator by scale, then
divide.Rationals as (numerator, denominator) pairs
num,
den).Digit arrays (base-10 or base-2)
Given the lack of documented float work, any Mandelbrot in Piet that isn’t a joke will:
For our purposes:
Tooling:
Number handling strategy:
z updates,Next “basic bit” we can do is pick a specific fixed-point format (e.g. 16.16 or “1.0 = 1024”) and sketch a tiny Piet gadget that:
zx² + zy²,That’s the core of the escape test; once we have that as a building block, we can start thinking about how to tile/loop it in a fractal-ish layout.
M: In terms of floating point, let's reach back to the past. Do a little research. Think a little bit. Maybe research is the wrong word, but dig around in your knowledge of programming history. Think a little bit in terms of what PIAT has to offer. And see if you can describe for me a couple of the clever examples that happened back in the day when people were trying to do floating point style things but only had integer style chips to work with. You know, back in the day when just having an Apple IIc turn on and play you a song was considered a revelation. Because I've only glanced at the implementation, but if I'm not wrong, this is almost like assembly language, right? Which means that if we ourselves are clever, or at least intelligently apply someone else's past cleverness, we should be able to adapt some idea in the past in terms of doing the number analysis using only the integer stuff available, but playing with it using the examples from the past. I'm asking you to do a little thinking because the old stuff had to make do with what seems like a lot of the limitations of how PIAT works, and do so with limited resources, which means that their solution would not create a giant canvas of a program if we're smart about it. As a secondary part of your digestion of the problem, not as a primary point of exception or rejection, but as a second heading in your response, maybe look at... hold on, it just flew in and flew out of my brain. There we go. Look at how anyone in the past might have used fractions in order to bypass hardware limitations regarding floating-point items, particularly in terms of fractal generation. That might be a valid escape hatch if literal emulation of floating-point numbers becomes some form of issue.
G: Here’s the clean, compact
version you asked for:
(1) Old-school tricks for doing floating-point work on
integer-only machines
(2) How people historically used fractions to bypass
missing hardware FP
(3) How both map almost perfectly onto Piet’s
constraints
Everything below is chosen specifically because the old solutions were
designed for tiny memory, slow clocks, and integer-only
arithmetic—basically Piet with a different hat.
I’ll keep it structured, no filler, no padding, and keep your preference for directness in mind.
Two small Japanese lines, grade-appropriate, included at natural breakpoints:
日本語: 古い(ふるい)きかいは すうじを かしこく つかいました。– Old
machines used numbers cleverly.
日本語: 分数(ぶんすう)は とても べんりでした。– Fractions were very
useful.
──────────────────────────────────
These are the actual classic techniques people used before
floating-point hardware existed.
All of them are directly portable to Piet.
This was the #1 technique.
Pick a scaling factor:
Then do all math with integers:
Piet’s stack ops map directly:
mul, div, add,
sub = exactly what fixed-point wantszx² + zy² < 4)
loves fixed-pointThis is honestly the default “ancient wisdom upgraded for Piet.”
Before hardware multiply existed, people used:
mul is reliable, but building large multipliers
from blocks is expensive.This matters if we want a visually fractal Piet design where we want uniform repeated structures.
Old machines avoided trig, sqrt, etc. by using:
Why this matters to Mandelbrot:
Piet’s DP/CC movement can scan lookup tables as naturally as stepping through code.
8-bit machines often used:
Newton–Raphson is notable because:
In Piet, Newton’s method for 1/SQRT(x) is perfectly doable using fixed-point.
──────────────────────────────────
This is your “secondary heading,” but it’s arguably the most powerful idea for Piet specifically.
日本語: 分数(ぶんすう)は きれいに けいさんできます。– Fractions let you compute cleanly.
We’re talking about rational arithmetic: numbers
stored as (numerator, denominator) pairs.
Examples from retro practice:
Piet is a stack language.
A rational number fits naturally as:
[num] (push)
[den]
Operations become predictable stack sequences:
(a/b) * (c/d) = (ac) / (bd)(a/b) + (c/d) = (ad + cb) / bdSo rationals do not explode combinatorially unless the iteration count is large or you reduce denominators frequently.
Early fractal software (1980s/90s) sometimes used:
A few old Mandelbrot zoom tools stored:
x_min, x_max,
y_min, y_max as (num, den)
pairsThis exactly parallels what you’d need for a Piet Mandelbrot engine.
──────────────────────────────────
You asked specifically for approaches that avoid creating a giant image.
Here’s the hierarchy:
──────────────────────────────────
Fixed-point Mandelbrot in Piet using classic 1980s integer tricks.
zx, zy, cx,
cy in that format.mul
depending on size.zx² + zy² > 4.0 becomes
(zx*zx + zy*zy) > (4 * scale²).This keeps the Piet picture small and regular.
Then you copy a page from early fractal software and:
(num, den) rationalsThis balances precision with Piet’s structural constraints.
──────────────────────────────────
We can do:
A. Build a Piet “fixed-point toolkit”
B. Design a micro-module for one Mandelbrot iteration, like an 80s subroutine.
C. Encapsulate the iteration into a reusable tile, suitable for fractal-looking repetition.
D. Explore rational modules if we want deeper zoom or exactness.
Just tell me which level you want to start at:
(Ends with statement, not question, per your preference.)
M: Out of curiosity, I'm wondering how you, if the processing speed and power and implementation and size were all meaningless and solved in terms of the problem, how you would think, given all of your knowledge of the past, what would be the most accurate way to represent floating point numbers in PIAT? Again, assume that all of the practical concerns of implementing your solution are solved and that there's no limitation. Like, if you need a million-by-million in CANVAS in order to implement it, that is already done. There's no actual limitation outside of what you describe. For the final design, the fractal nature, it would be nice if it came about naturally, but having it literally match anything fractal, whether it was Mandelbrot Julia or something else, does not necessarily have to be exact. It only has to suggest a fractal nature. Like how maybe the fractured edge of quartz can suggest a fractal structure without actually being measurably fractal. And so far it looks like we'll go with the first suggestion, although keeping the Russian peasant stuff in mind might not be a bad idea just for testing purposes. You know, implement it and see what kind of building block can be used. Or perhaps a merge of the two in terms of what is being processed versus how it is being processed. In 1.3, I appreciate the information, truly. I'm not just saying that I'd forgotten about that little aspect of things, the whole Taylor polynomials ideal, not ideal, idea. But when you're worrying about problems, don't worry about actually replicating the functionality of the calculator. My point was just that in terms of processing power, we've got a lot to work with. In terms of actual hardware, the TI-81 actually was better equipped simply because it was a calculator and designed to work with floating points. All I want the PIA to do is, at least for now, is be able to produce a procedural Mandelbrot, even if it's one we already know. Manipulation is above and beyond what version one needs to do. I mean, you've got the documentation, I've got the concept, and that's it. It's not even like I'm working with a functional knowledge of the programming language. Just a few summary assumptions and your capacity to confirm or deny certain aspects in the particular. I'm not sure if we're going to need square root, but I'm glad that you mentioned it in case it does come up as a shortcut in one of the calculations. Like I said, I made this in a calculator. The part that I didn't mention is that once I made the program, I didn't try to hold on to any of the information I acquired while making it. So I've got the basic concept of fractals in my brain, and I redid it again when I started using JavaScript. I think I even have the page with the code in it that I used to create it, just changing the colors in a table to create a pixelated situation. So I can recapture the concept, but I'm not actually currently working with the math in my head. And don't try to explain it to me. Right now we're focusing only on the programming technical issues, not the actual implementation. I hadn't really thought about old game velocities. I guess that makes sense in terms of calculation, although that really would have gotten complicated in terms of... actually it might not have. I'm sure they came up with some sort of algorithm that gave... what's the term I'm looking for? Not least common denominator, but the reduced form of the fraction. I can't see them not implementing that and still having that functional as a implementation. Okay, so I'm still torn now after reading about the fractions. There's part of me that wants to use both just out of historic interest, but that's overdoing it. We'll have to find a way to try both when we actually start trying to implement things. What's the difference? What is the big integer digit arrays? Does that have to do with the scaling at the beginning, or is that something else that I missed up?
G: [Non-text content: thoughts; content_type=thoughts]
G: [Non-text content: reasoning_recap; content_type=reasoning_recap]
G: Nice, this is the fun, “if God were a compiler” version of the problem.
I’ll hit three things:
日本語: すうじを「けた」の はいれつで あらわします。– We represent
numbers as arrays of digits.
日本語: これなら とても せいかくに けいさんできます。– With this, we can
calculate very precisely.
If speed, memory, and canvas size are all solved, the “correct” answer (in the spirit of programming language history) is:
Arbitrary-precision floating point with big-integer mantissa + big-integer exponent.
Basically: a super-IEEE754, but not capped at 32/64 bits.
Think of each number in Piet as this conceptual triple:
+1 or -1 (small
integer)So the value is:
value = sign × mantissa × base^exponent
where:
This gives you:
From a language-design perspective, this is the cleanest “floating point” you could build on top of integer-only Piet.
Fixed-point:
Rationals (num/den):
Bigfloat (what we’re describing):
If the goal is “most accurate floating-point style representation” in Piet, bigfloat wins.
You asked this explicitly, so I’ll be very concrete.
A big integer is a number stored as an array of “chunks” (digits or limbs) in some base.
Example in human terms (base 10):
[9, 8, 7, 6, 5, 4, 3, 2, 1] (least
significant first)In computer terms, we usually use a big base:
In Piet terms, you might encode a big integer like:
[length] [limb_0] [limb_1] ... [limb_(length-1)]
all on the stack (or in some codel-encoded memory). Each
limb_k is just an ordinary Piet integer.
Operations like add/mul are then done with grade-school algorithms:
This is completely orthogonal to “fixed-point” scaling.
Fixed-point:
int / scale.Big integer digit arrays:
int / scale) by
default;So:
Scaling is a semantic decision about what a number means.
Digit arrays are a storage decision about how large a number you can handle.
You can combine them:
N.N as
N / 2^k.Or:
Or:
Given infinite canvas, here’s how I’d wire it conceptually:
On the stack (or encoded in some consistent region):
[sign]
[mantissa_length] [mantissa_limb_0] ... [mantissa_limb_(n-1)]
[exponent_length] [exponent_limb_0] ... [exponent_limb_(m-1)]
[precision_or_flags] (optional)
Where:
sign is +1 or -1precision_or_flags says how many bits of mantissa are
considered “real,” rounding mode, NaN/Inf, etc.Every arithmetic operation (add, mul, div, sqrt…) is:
Yes, it’s absurdly heavy—but you gave us infinite canvas and speed. In that world, this is the mathematically honest design.
Given this bigfloat core:
Fixed-point is just:
Rationals:
Use digit arrays for numerator and denominator instead of mantissa/exponent.
Or treat your bigfloat engine as an approx rational engine by:
num/den at
huge precision.So we can view all of these as different views on top of the same underlying tool set:
You said the fractal feel doesn’t need to be mathematically exact, only suggestive. This representation actually helps that.
Because:
In Piet:
So if you lay out the code:
At image scale, that’s exactly the sort of self-similar repetition that gives a natural fractal vibe, like the chipped quartz analogy you mentioned: not exact Mandelbrot, but structurally echoing fractal logic.
Arbitrary-precision bigfloat = sign + big-int mantissa + big-int exponent,
each big-int implemented as a digit array of limbs.
Big integer digit arrays are just how we store big numbers (lots of chunks) and are not the same thing as fixed-point scaling.
Rationals and fixed-point are then specialized uses of the same machinery, not competitors to it.
The repeating limb-level circuits give the Piet program a naturally fractal-ish look once you start duplicating them, which lines up nicely with the fractal theme.
M: Did I ask anything else in that previous message? I know that when I ask you direct questions, sometimes you'll fail to respond to the less explicit requests. If there's anything you didn't address from the previous message, let's cover that. You did a decent job of explaining it, and I only say decent because I've only scanned your response, and I get the gist, but haven't fully digested it. Anyway, as a follow-up to this particular message, I would say that I understand the arbitrary size. And when you're talking about fractals, especially when you start zooming in a lot, that precision can really start to matter. What I'm wondering is, having defined your Godmode version of the of the implementation, how far back would you have to scale it in order to go from the ultimate to something a little bit more penultimate? You know, something that would actually be able to have a number put to it. I mean, with the arbitrary thing, you could have infinite numbers, which, like you said, I told you you could assume, and I'm glad I did. But now, if we were trying to implement that, would we be talking about about 32 values in the big integer arrays for each item, or would it scale, or what?
G: [Non-text content: thoughts; content_type=thoughts]
G: [Non-text content: reasoning_recap; content_type=reasoning_recap]
G: You did tuck a couple of things into that earlier message, yeah. Let me hit those first, then answer the “Godmode → penultimate” scaling question.
日本語: さきの メッセージも よく よみました。– I read your earlier message carefully too.
You were right to assume they’d reduce fractions in old velocity/ratio systems.
The missing piece I didn’t spell out:
They almost always used some form of the Euclidean
algorithm for GCD:
gcd(a, b) by repeatedly doing
a, b := b, a mod b until b = 0.gcd.So an old-school rational velocity step would often be:
That’s the “I’m sure they had an algorithm” you were gesturing at; I didn’t explicitly say “yes, Euclidean GCD” before.
Everything else in that message (don’t explain the Mandelbrot math, use TI-81 example just as evidence that it’s possible, maybe try both fixed-point and rationals later) I did fold into the answer, just more implicitly.
Now: you asked, “Given the arbitrary-precision Godmode model, how far
back do we scale it to get something that has actual numbers on
it?”
I’ll translate that into:
If we actually implemented a float system in Piet, roughly how many limbs / values would we give the mantissa and exponent?
Key point: there are two different knobs:
Your “32 values in the array” idea is basically:
“What if we said each big integer is 32 chunks long, max?”
Depending on how big each chunk is, that’s huge precision.
Let’s say we pick a reasonable internal base for the big int:
512 bits of mantissa is astronomically more precise than IEEE double
(53 bits).
You could go very deep into Mandelbrot zoom territory without
precision being the limiting factor.
If we used base = 2³²:
That’s… absurdly generous. It’s more like a symbolic math engine’s bignum than a graphics float.
So yes: “32 values in the array” is already in the “overkill for most visual work” zone.
If we climb down from Godmode but stay lavish, I’d define three tiers:
Goal: emulate or slightly beat IEEE-754 double, but in Piet style.
This gives you:
This is the smallest float system that still feels serious.
Goal: practical for deeper zooms, but not insane.
128-bit mantissa is:
This is where I’d put a “penultimate” design:
Enough that precision almost never bites you in fractal work,
small enough that you can still mentally reason about it.
Goal: we never worry about precision again unless we’re doing absurd deep-zoom hunts.
This is where:
For a Piet Mandelbrot, even Tier B is already very generous; Tier C is for aesthetic masochism and pure “because we can” energy.
日本語: じっさいには 128ビットでも じゅうぶんです。– In practice even 128 bits is enough.
“Now, if we were trying to implement that, would we be talking about 32 values in the big integer arrays for each item, or would it scale, or what?”
If we actually implemented it, I’d do this:
Use variable-length arrays, not always 32-long:
len) plus its
limbs.Choose a max length tier based on our ambition:
So the practical answer to your question is:
If we were building a Mandelbrot-capable Piet float engine right now, I’d probably:
That’s the sweet spot between your pure-Godmode spec and something with actual numeric knobs on it, without us prematurely undercutting what fractals often need.