Improve fixed-point documentation (#1455)

* Clarify the operator relationship of ordinary and fixed-point numbers
* Attempt to clarify description of fixed-point numbers
* Note that RGBASM does not check fixed-point precisions
* Simplify sine table example a bit
* Remove misleading equations describing `DIV`, `MUL`, and `FMOD`
* Various minor style and formatting fixups
This commit is contained in:
Eldred Habert
2024-08-08 19:56:08 +02:00
committed by GitHub
parent a3f9952b9e
commit 817dcfdc70

View File

@@ -369,23 +369,28 @@ equals $roman clz ( n )$.
delim off delim off
.EN .EN
.Ss Fixed-point expressions .Ss Fixed-point expressions
Fixed-point numbers are basically normal (32-bit) integers, which count fractions instead of whole numbers. Fixed-point numbers are technically just integers, but conceptually they have a decimal point at a fixed location (hence the name).
They offer better precision than integers but limit the range of values. This gives them increased precision, at the cost of a smaller range, while remaining far cheaper to manipulate than floating-point numbers (which
By default, the upper 16 bits are used for the integer part and the lower 16 bits are used for the fraction (65536ths). .Nm
The default number of fractional bits can be changed with the does not support).
.Pp
The default precision of all fixed-point numbers is 16 bits, meaning the lower 16 bits are used for the fractional part; so they count in 65536ths of 1.0.
This precision can be changed with the
.Fl Q .Fl Q
command-line option. command-line option, and/or by
You can also specify a precise fixed-point value by appending a .Ic OPT Q
.Pq see Sx Changing options while assembling .
An individual fixed-point literal can specify its own precision, overriding the current default, by appending a
.Dq q .Dq q
to it followed by the number of fractional bits, such as followed by the number of fractional bits: for example,
.Ql 12.34q8 . .Ql 1234.5q8
is equal to $0004d2_80
.EQ
delim $$
.EN
($= 1234.5 * 2 sup 8$).
.Pp .Pp
Since fixed-point values are still just integers, you can use them in normal integer expressions. Since fixed-point values are still just integers, you can use them in normal integer expressions.
Some integer operators like
.Sq +
and
.Sq -
don't care whether the operands are integers or fixed-point.
You can easily truncate a fixed-point number into an integer by shifting it right by the number of fractional bits. You can easily truncate a fixed-point number into an integer by shifting it right by the number of fractional bits.
It follows that you can convert an integer to a fixed-point number by shifting it left that same amount. It follows that you can convert an integer to a fixed-point number by shifting it left that same amount.
.Pp .Pp
@@ -393,19 +398,16 @@ Note that the current number of fractional bits can be computed as
.Ic TZCOUNT Ns Pq 1.0 . .Ic TZCOUNT Ns Pq 1.0 .
.Pp .Pp
The following functions are designed to operate with fixed-point numbers: The following functions are designed to operate with fixed-point numbers:
.EQ
delim $$
.EN
.Bl -column -offset indent "ATAN2(y, x)" .Bl -column -offset indent "ATAN2(y, x)"
.It Sy Name Ta Sy Operation .It Sy Name Ta Sy Operation
.It Fn DIV x y Ta Fixed-point division $( x \[di] y ) \[mu] ( 2 ^ precision )$ .It Fn DIV x y Ta Fixed-point division
.It Fn MUL x y Ta Fixed-point multiplication $( x \[mu] y ) \[di] ( 2 ^ precision )$ .It Fn MUL x y Ta Fixed-point multiplication
.It Fn FMOD x y Ta Fixed-point modulo $( x % y ) \[di] ( 2 ^ precision )$ .It Fn FMOD x y Ta Fixed-point modulo
.It Fn POW x y Ta $x$ to the $y$ power .It Fn POW x y Ta $x sup y$
.It Fn LOG x y Ta Logarithm of $x$ to the base $y$ .It Fn LOG x y Ta Logarithm of $x$ to the base $y$
.It Fn ROUND x Ta Round $x$ to the nearest integer .It Fn ROUND x Ta Round $x$ to the nearest integer
.It Fn CEIL x Ta Round $x$ up to an integer .It Fn CEIL x Ta Round $x$ up to the nearest integer
.It Fn FLOOR x Ta Round $x$ down to an integer .It Fn FLOOR x Ta Round $x$ down to the nearest integer
.It Fn SIN x Ta Sine of $x$ .It Fn SIN x Ta Sine of $x$
.It Fn COS x Ta Cosine of $x$ .It Fn COS x Ta Cosine of $x$
.It Fn TAN x Ta Tangent of $x$ .It Fn TAN x Ta Tangent of $x$
@@ -418,7 +420,25 @@ delim $$
delim off delim off
.EN .EN
.Pp .Pp
All of these fixed-point functions can take an optional final argument, which is the precision to use. There are no functions for fixed-point addition and subtraction, because the
.Sq +
and
.Sq -
operators can add and subtract pairs of fixed-point operands.
.Bd -ragged -offset indent
Note that some operators or functions are meaningful when combining integers and fixed-point values.
For example,
.Ql 2.0 * 3
is equivalent to
.Ql MUL(2.0, 3.0) ,
and
.Ql 6.0 / 2
is equivalent to
.Ql DIV(6.0, 2.0) .
Be careful and think about what the operations mean when doing this sort of thing.
.Ed
.Pp
All of these fixed-point functions can take an optional final argument, which is the precision to use for that one operation.
For example, For example,
.Ql MUL(6.0q8, 7.0q8, 8) .Ql MUL(6.0q8, 7.0q8, 8)
will evaluate to will evaluate to
@@ -426,6 +446,12 @@ will evaluate to
no matter what value is set as the current no matter what value is set as the current
.Cm Q .Cm Q
option. option.
.Nm
.Em does not check precisions for consistency ,
so nonsensical input like
.Ql MUL(4.2q8, 6.9q12, 16)
will produce a nonsensical (but technically correct) result:
.Dq garbage in, garbage out .
.Pp .Pp
The The
.Ic FMOD .Ic FMOD
@@ -439,21 +465,26 @@ this is the opposite of how the integer modulo operator
.Sq % .Sq %
works! works!
.Pp .Pp
The trigonometry functions ( The trigonometry functions
.Ic SIN , .Pq Ic SIN , Ic COS , Ic TAN , No etc
.Ic COS , are defined in terms of a circle divided into 1.0
.Ic TAN , .Dq turns
etc) are defined in terms of a circle divided into 1.0 "turns" (equal to 2pi radians or 360 degrees). .EQ
delim $$
.EN
(equal to $2 pi$ radians, or 360 degrees).
.EQ
delim off
.EN
.Pp .Pp
These functions are useful for automatic generation of various tables. These functions are useful for automatic generation of various tables.
For example: For example:
.Bd -literal -offset indent .Bd -literal -offset indent
; Generate a table of sine values from sin(0.0) to sin(1.0), with ; Generate a table of 128 sine values
; amplitude scaled from [-1.0, 1.0] to [0.0, 128.0] ; from sin(0.0) to sin(0.5) excluded,
DEF turns = 0.0 ; with amplitude scaled from [-1.0, 1.0] to [0.0, 128.0].
REPT 256 FOR angle, 0.0, 0.5, 0.5 / 128
db MUL(64.0, SIN(turns) + 1.0) >> 16 db MUL(SIN(angle) + 1.0, 128.0 / 2) >> 16
DEF turns += 1.0 / 256
ENDR ENDR
.Ed .Ed
.Ss String expressions .Ss String expressions