mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
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:
99
man/rgbasm.5
99
man/rgbasm.5
@@ -369,23 +369,28 @@ equals $roman clz ( n )$.
|
||||
delim off
|
||||
.EN
|
||||
.Ss Fixed-point expressions
|
||||
Fixed-point numbers are basically normal (32-bit) integers, which count fractions instead of whole numbers.
|
||||
They offer better precision than integers but limit the range of values.
|
||||
By default, the upper 16 bits are used for the integer part and the lower 16 bits are used for the fraction (65536ths).
|
||||
The default number of fractional bits can be changed with the
|
||||
Fixed-point numbers are technically just integers, but conceptually they have a decimal point at a fixed location (hence the name).
|
||||
This gives them increased precision, at the cost of a smaller range, while remaining far cheaper to manipulate than floating-point numbers (which
|
||||
.Nm
|
||||
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
|
||||
command-line option.
|
||||
You can also specify a precise fixed-point value by appending a
|
||||
command-line option, and/or by
|
||||
.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
|
||||
to it followed by the number of fractional bits, such as
|
||||
.Ql 12.34q8 .
|
||||
followed by the number of fractional bits: for example,
|
||||
.Ql 1234.5q8
|
||||
is equal to $0004d2_80
|
||||
.EQ
|
||||
delim $$
|
||||
.EN
|
||||
($= 1234.5 * 2 sup 8$).
|
||||
.Pp
|
||||
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.
|
||||
It follows that you can convert an integer to a fixed-point number by shifting it left that same amount.
|
||||
.Pp
|
||||
@@ -393,19 +398,16 @@ Note that the current number of fractional bits can be computed as
|
||||
.Ic TZCOUNT Ns Pq 1.0 .
|
||||
.Pp
|
||||
The following functions are designed to operate with fixed-point numbers:
|
||||
.EQ
|
||||
delim $$
|
||||
.EN
|
||||
.Bl -column -offset indent "ATAN2(y, x)"
|
||||
.It Sy Name Ta Sy Operation
|
||||
.It Fn DIV x y Ta Fixed-point division $( x \[di] y ) \[mu] ( 2 ^ precision )$
|
||||
.It Fn MUL x y Ta Fixed-point multiplication $( x \[mu] y ) \[di] ( 2 ^ precision )$
|
||||
.It Fn FMOD x y Ta Fixed-point modulo $( x % y ) \[di] ( 2 ^ precision )$
|
||||
.It Fn POW x y Ta $x$ to the $y$ power
|
||||
.It Fn DIV x y Ta Fixed-point division
|
||||
.It Fn MUL x y Ta Fixed-point multiplication
|
||||
.It Fn FMOD x y Ta Fixed-point modulo
|
||||
.It Fn POW x y Ta $x sup 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 CEIL x Ta Round $x$ up to an integer
|
||||
.It Fn FLOOR x Ta Round $x$ down to an integer
|
||||
.It Fn CEIL x Ta Round $x$ up to the nearest integer
|
||||
.It Fn FLOOR x Ta Round $x$ down to the nearest integer
|
||||
.It Fn SIN x Ta Sine of $x$
|
||||
.It Fn COS x Ta Cosine of $x$
|
||||
.It Fn TAN x Ta Tangent of $x$
|
||||
@@ -418,7 +420,25 @@ delim $$
|
||||
delim off
|
||||
.EN
|
||||
.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,
|
||||
.Ql MUL(6.0q8, 7.0q8, 8)
|
||||
will evaluate to
|
||||
@@ -426,6 +446,12 @@ will evaluate to
|
||||
no matter what value is set as the current
|
||||
.Cm Q
|
||||
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
|
||||
The
|
||||
.Ic FMOD
|
||||
@@ -439,21 +465,26 @@ this is the opposite of how the integer modulo operator
|
||||
.Sq %
|
||||
works!
|
||||
.Pp
|
||||
The trigonometry functions (
|
||||
.Ic SIN ,
|
||||
.Ic COS ,
|
||||
.Ic TAN ,
|
||||
etc) are defined in terms of a circle divided into 1.0 "turns" (equal to 2pi radians or 360 degrees).
|
||||
The trigonometry functions
|
||||
.Pq Ic SIN , Ic COS , Ic TAN , No etc
|
||||
are defined in terms of a circle divided into 1.0
|
||||
.Dq turns
|
||||
.EQ
|
||||
delim $$
|
||||
.EN
|
||||
(equal to $2 pi$ radians, or 360 degrees).
|
||||
.EQ
|
||||
delim off
|
||||
.EN
|
||||
.Pp
|
||||
These functions are useful for automatic generation of various tables.
|
||||
For example:
|
||||
.Bd -literal -offset indent
|
||||
; Generate a table of sine values from sin(0.0) to sin(1.0), with
|
||||
; amplitude scaled from [-1.0, 1.0] to [0.0, 128.0]
|
||||
DEF turns = 0.0
|
||||
REPT 256
|
||||
db MUL(64.0, SIN(turns) + 1.0) >> 16
|
||||
DEF turns += 1.0 / 256
|
||||
; Generate a table of 128 sine values
|
||||
; from sin(0.0) to sin(0.5) excluded,
|
||||
; with amplitude scaled from [-1.0, 1.0] to [0.0, 128.0].
|
||||
FOR angle, 0.0, 0.5, 0.5 / 128
|
||||
db MUL(SIN(angle) + 1.0, 128.0 / 2) >> 16
|
||||
ENDR
|
||||
.Ed
|
||||
.Ss String expressions
|
||||
|
||||
Reference in New Issue
Block a user