-
Notifications
You must be signed in to change notification settings - Fork 0
Fingerprints
For each fingerprint, the original source is listed, followed by the original documentation, followed by any addenda or notes on ambiguities or implementation details.
From the rcFunge docs
Instruction | Args | Description |
---|---|---|
A | (a b — r) | And |
N | (a — r) | Not |
O | (a b — r) | Or |
X | (a b — r) | Xor |
Addendum: These ‘logic‘ functions are bitwise operations.
From the rcFunge docs
Instruction | Args | Description |
---|---|---|
A | (a b — a and b) | And |
B | (n — arccos(b)) | Find arccosin of tos |
C | (n — cos(b)) | Find cosin of tos |
D | (n — rnd(n)) | RanDom number |
I | (n — sin(b)) | Find sin of tos |
J | (n — arcsin(b)) | Find arcsin of tos |
N | (a — 0-a) | Negate |
O | (a b — a or b) | Or |
P | (a — a*pi) | Multiply by pi |
Q | (a — sqrt(a)) | Square root |
R | (a b — a**b) | Raise a to the power of b |
S | (n — n) | Replace tos with sign of tos |
T | (n — tan(b)) | Find tangent of tos |
U | (n — arctan(b) | Find arctangent of tos |
V | (n — n) | Absolute value of tos |
X | (a b — a xor b) | Xor |
- The functions C,I,T,B,J,U expect their arguments times 10000, for example: 45 should be passed as 450000. The results will also be multiplied by 10000, thereby giving 4 digits of decimal precision.
- Trigonometric functions work in degrees. not radians.
From the rcFunge docs
Instruction | Args | Description |
---|---|---|
A | (a b — n) | Add two double precision fp numbers |
B | (n — n) | Sin of double precision fp number |
C | (n — n) | Cosin of double precision fp number |
D | (a b — n) | Divide two double precision fp numbers |
E | (n — n) | Arcsin of double precision fp number |
F | (n — n) | Convert integer to floating point |
G | (n — n) | Arctangent of double precision fp number |
H | (n — n) | Arccosin of double precision fp number |
I | (n — n) | Convert floating point to integer |
K | (n — n) | Natural logarithm of double precision fp number |
L | (n — n) | Base 10 logarithm of double precision fp number |
M | (a b — n) | Multiply two double precision fp numbers |
N | (n — n) | Negate double precision fp number |
P | (n — ) | Print a floating point number |
Q | (n — n) | Double precision square root |
R | (0gnirts — n) | Convert ascii number to floating point |
S | (a b — n) | Subtract two double precision fp numbers |
T | (n — n) | Tangent of double precision fp number |
V | (n — n) | Absolute value of double precision fp number |
X | (n — n) | Exponential of double precision fp number (e**n) |
Y | (x y — n) | Raise x to the power of y |
Addendum: The docs do not mention whether these instructions operate on one or two stack cells per double. De facto, all interpreters use two cells per double; rfunge does so too, even in 64-bit mode (where a double could fit in a single cell)
Trig functions work in radians (like FPSP, unlike FIXP)
From the rcFunge docs
Instruction | Args | Description |
---|---|---|
D | (fmt fh fl — 0gnirts) | Format FPDP type number |
F | (fmt f — 0gnirts) | Format FPSP type number |
I | (fmt i — 0gnirts) | Format an integer |
L | (fmt h l — 0gnirts) | Format a long integer |
S | (fmt 0gnirts — 0gnirts) | Format a string |
Formats are printf style. Error in any function reflects.
Addendum: Format strings are 0gnirts. Only exactly one conversion is supported per format string, passing a format string with no valid fields or with too many is undefined behaviour. All standard C99 formats should be supported in theory, but sometimes aren't.
From the rcFunge docs
Instruction | Args | Description |
---|---|---|
A | (a b — n) | Add two single precision fp numbers |
B | (n — n) | Sin of single precision fp number |
C | (n — n) | Cosin of single precision fp number |
D | (a b — n) | Divide two single precision fp numbers |
E | (n — n) | Arcsin of single precision fp number |
F | (n — n) | Convert integer to floating point |
G | (n — n) | Arctangent of single precision fp number |
H | (n — n) | Arccosin of single precision fp number |
I | (n — n) | Convert floating point to integer |
K | (n — n) | Natural logarithm of single precision fp number |
L | (n — n) | Base 10 logarithm of single precision fp number |
M | (a b — n) | Multiply two single precision fp numbers |
N | (n — n) | Negate single precision fp number |
P | (n — ) | Print a floating point number |
Q | (n — n) | Single precision square root |
R | (0gnirts — n) | Convert ascii number to floating point |
S | (a b — n) | Subtract two single precision fp numbers |
T | (n — n) | Tangent of single precision fp number |
V | (n — n) | Absolute value of single precision fp number |
X | (n — n) | Exponential of single precision fp number (e**n) |
Y | (x y — n) | Raise x to the power of y |
Trig functions work in radians
From the rcFunge docs
Instruction | Args | Description |
---|---|---|
D | ( — n) | Push depth of stack to tos |
L | (… n — …) | Forth Roll command |
O | (a b — a b a) | Forth Over command |
P | (… n — …) | Forth Pick command |
R | (a b c — b c a) | Forth Rot command |
Stack operations are subject to the modes set by MODE
Clarification
- P should reflect on a negative argument
- P should push 0 if argument is greater than stack size
- L should act like forth -roll with a negative argument
- L with an argument larger than the stack size is allowed, enough zeroes will be created in order to fulfill the request. Example: n543210a-L will leave a stack of: 2 3 4 5 0 0 0 0 0 0 1
- L, P: the top of stack is position 0
Addendum: Note that L
with negative argument is implemented as described
in rcFunge and rfunge, but not in several other implementations of the fingerprint.
From the catseye library (‘Under development.’)
The HRTI fingerprint allows a Funge program to measure elapsed time much
more finely than the clock values returned by y
.
After successfully loading HRTI, the instructions E
, G
, M
, S
,
and T
take on new semantics.
Instruction | Args | Description |
---|---|---|
G | ( — tick) | ‘Granularity’ pushes the smallest clock tick the underlying system can reliably handle, measured in microseconds. |
M | ( — ) | ‘Mark’ designates the timer as having been read by the IP with this ID at this instance in time. |
T | ( — dt) | ‘Timer’ pushes the number of microseconds elapsed since the last time an IP with this ID marked the timer. If there is no previous mark, acts like r . |
E | ( — ) | ‘Erase mark’ erases the last timer mark by this IP (such that T above will act like r ) |
S | ( — μs) | ‘Second’ pushes the number of microseconds elapsed since the last whole second. |
The timer and mark-list are considered global and static, shared amongst all IP's, in order to retain tame behaviour.
This timer is not affected by 'time travel' contrivances.
Addendum: In rfunge, the mark is not global, but specific to an IP – but it
is inherited by child IPs. The definition is ambiguous as to what E
does: we
interpret it as erasing the mark, such that T
then acts like r
(meaning
there is no ‘mark-list’), i.e. MME
is equivalent to zzz
, not to Mzz
.
One of Jesse van Herk’s fingerprints
Instruction | Args | Description |
---|---|---|
P | (Vd Va n — ) | pop n cells off of the stack and write at Va with delta Vd. |
G | (Vd Va n — 0gnirts) | read n cells from position Va and delta Vd, push on stack as a string. |
This extension is the Right Way to handle string writing/reading in fungespace. multidimensionality, people!
Addendum: P
pops the cells off the stack after it has popped its vector arguments. These instructions respect the storage offset.
The rcFunge 2 manual has the instructions the wrong way around, but rcFunge 2 still implements them correctly.
From the rcFunge docs
Instruction | Args | Description |
---|---|---|
A | (ah al bh bl — rh rl) | Addition |
B | (ah al — rh rl) | Absolute value |
D | (ah al bh bl — rh rl) | Division |
E | (n — rh rl) | Sign extend single to long |
L | (ah al n — rh rl) | Shift left n times |
M | (ah al bh bl — rh rl) | Multiplication |
N | (ah al — rh rl) | Negate |
O | (ah al bh bl — rh rl) | Modulo |
P | (ah al — ) | |
R | (ah al n — rh rl) | Shift right n times |
S | (ah al bh bl — rh rl) | Subraction |
Z | (0gnirts — rh rl) | Ascii to long |
- long integers are 2 cell integers, if the interpreter's cell size is 32, then long integers are 64-bits.
- Division by zero results in zero, not error
Addendum: rfunge implements 128-bit integers in 64-bit mode; it may be the only interpreter to do so.
From the catseye library (‘Under development.’)
The MODU fingerprint implements some of the finer, less-well-agreed-upon points of modulo arithmetic. With positive arguments, these instructions work exactly the same as % does. However, when negative values are involved, they all work differently:
Instruction | Args | Description |
---|---|---|
M | (a b — r) | signed-result modulo |
U | (a b — r) | Sam Holden's unsigned-result modulo |
R | (a b — r) | C-language integer remainder |
Addendum: This fingerprint is poorly defined and, for the most part, equally poorly implemented. Of all the implementations I’ve seen, other than rfunge, only CCBI gets it right.
It’s easiest to define what these commands need to do by thinking about the remainder in integer division. There are different ways to defining integer division, but for all of them we get a result
n ÷ d = q rem r
which we can rearrange as
q × d + r = n
If the result of the modulo operator is supposed to be some kind of integer division remainder, then there must be a sound definition of integer division for which the above holds!. C uses truncating division (rounding q to 0) and the appropriate remainder, which is fine and all implementations get right. This is of course a ‘signed-result modulo’, but as the instructions are supposed to do different things and the result for positive arguments is supposed to be unchanged, we end up with floor division (rounding q to -∞), which most implementations also get right.
U
, the unsigned-result modulo, however, is frequently implemented as the
absolute value of C modulo result, and I do not believe there is any coherent
definition of integer division for which this is correct. We can instead define
our division to round q
in whatever direction makes r
positive (sometimes
called ‘Euclidean division’). This is what CCBI and rfunge do.
(We could also approach the problem from the point of view of modulo arithmetic, but then we’d run into invariants broken even by the C-language remainder)
From the catseye library
After successfully loading fingerprint 0x4e554c4c, all 26 instructions A to Z take on the semantics of r.
This can be loaded before loading a regular transparent fingerprint to make it act opaquely.
From the catseye library (‘Under development.’)
The REFC fingerprint allows vectors to be encoded into and decoded from single scalar cell values.
After successfully loading REFC, the instructions D
and R
take on
new semantics.
Instruction | Args | Description |
---|---|---|
R | (Va — ref) | ‘Reference’ pops a vector off the stack, and pushes a scalar value back onto the stack, unique within an internal list of references, which refers to that vector. |
D | (ref — Va) | ‘Dereference’ pops a scalar value off the stack, and pushes the vector back onto the stack which corresponds to that unique reference value. |
The internal list of references is considered shared among all IP's, so a global static can be used to store this list, so that this extension remains tame.
Addendum: In rfunge, the reference list is not global, but specific to an IP – but it is inherited by and shared with/between child IPs. The behaviour is the same as long as the fingerprint is loaded and first used before any child IPs are spawned.
From the catseye library (‘Under development.’)
After successfully loading ROMA, the instructions C
, D
, I
, L
,
M
, V
, and X
take on new semantics.
Instruction | Args | Description |
---|---|---|
C | ( — n) | pushes 100 onto the stack. |
D | ( — n) | pushes 500 onto the stack. |
I | ( — n) | pushes 1 onto the stack. |
L | ( — n) | pushes 50 onto the stack. |
M | ( — n) | pushes 1000 onto the stack. |
V | ( — n) | pushes 5 onto the stack. |
X | ( — n) | pushes 10 onto the stack. |
Note that these are just digits, you still have to do the arithmetic
yourself. Executing MCMLXXXIV
will not leave 1984 on the stack. But
executing MCM\-+LXXX+++IV\-++
should.
From the rcFunge docs
Instruction | Args | Description |
---|---|---|
A | (s — prt addr s) | Accept a connection |
B | (s ct prt addr — ) | Bind a socket |
C | (s ct prt addr — ) | Open a connection |
I | (0gnirts — addr) | Convert an ascii ip address to a 32 bit address |
K | (s — ) | Kill a connection |
L | (n s — ) | Set a socket to listening mode (n=backlog size) |
O | (n o s — ) | Set socket option |
R | (V l s — bytes) | Receive from a socket, |
S | (pf typ pro — s) | Create a socket |
W | (V l s — retcode) | Write to a socket |
note: All functions act as r on failure
- addr: 32 bit destination address
- ct:
- 1=AF_UNIX
- 2=AF_INET
- o:
- 1=SO_DEBUG
- 2=SO_REUSEADDR
- 3=SO_KEEPALIVE
- 4=SO_DONTROUTE
- 5=SO_BROADCAST
- 6=OOBINLINE
- pf:
- 1=PF_UNIX
- 2=PF_INET
- prt: Port to connect to
- s: Socket identifier
- typ:
- 1=SOCK_DGRAM
- 2=SOCK_STREAM
- pro:
- 1=tcp
- 2=udp
- V: Vector to io buffer
Clarification
The socket descriptor s used in these functions could be either an index into a table of open sockets or else use the id returned by the OS. In either case the socket identifier needs to be usable by other IPs, therefore a socket table that is global to all IPs or else use the OS descriptors.
ct=1 and pf=1 are a broken spec and should not be implemented. Usage of either of these should reflect.
Addendum: rfunge does not support SO_DEBUG, SO_DONTROUTE, or OOBINLINE. (Or UNIX sockets of course). This fingerprint is not available on the web or in sandbox mode.
From the catseye library (‘Under development.’)
Instruction | Args | Description |
---|---|---|
L | (angle — ) | Turn Left |
R | (angle — ) | Turn Right |
H | (angle — ) | Set Heading (0 = east) |
F | (dist — ) | Go Forward |
B | (dist — ) | Go Back |
P | (pos — ) | Set Pen Position (0 = up, 1 = down) |
C | (colour — ) | Set Pen Colour |
N | (colour — ) | Clear with Colour |
D | (disp — ) | Show Display (0 = off, 1 = on) |
T | (x y — ) | Teleport |
E | ( — pos) | Query Pen Position |
A | ( — angle) | Query heading |
Q | ( — x y) | Query position |
U | ( — x1 y1 x2 y2) | Query Bounds |
I | ( — ) | Print current Drawing (if possible) |
All angles are in degrees, all distances are in pixels.
To keep this fingerprint tame, a single Turtle and display is defined to be shared amongst all IP's. The turtle is not defined to wrap if it goes out of bounds (after all this interface might just as well be used to drive a real turtle robot.)
Addendum: RFunge supports this fingerprint both on the web and on the desktop; on the web, the ‘display’ is a <canvas>
embedded in the user interface and I
triggers a PNG download. The native version opens a GUI window (if possible) when the TURT display is requested, and writes an SVG file to the current directory on I
. This corresponds to the behaviour of CCBI and cfunge, which do not support direct GUI output. TURT is disabled in sandbox mode. RFunge can be compiled without GUI support.