groff
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Groff] Floating point arithmetic in groff


From: Werner LEMBERG
Subject: Re: [Groff] Floating point arithmetic in groff
Date: Tue, 31 Jan 2006 07:38:54 +0100 (CET)

> Is anyone aware of a means by which floating point arithmetic and
> formating can be computed either within groff or in a preprocessor
> (ala eqn, tbl, etc.)?

Not that I know of.  Why do you need it?  A longer time ago I've
written routines to handle double-precision integers, this is, doing
60bit integer arithmetic (see below), to be used in a.  Does this help?


    Werner


======================================================================


.\"
.\" 60bit.tmac
.\"
.\" This file provides macros for addition, multiplication, and division of
.\" 60bit integers.
.\"
.\" A macro for small caps which works correctly for arbitrary font sizes is
.\" given as an example how to use them.
.\"
.\" written by Werner Lemberg <address@hidden>
.\"
.\" Version 0.1: 03-Apr-2003
.\"   Initial release.
.\"
.\" Version 1.0: 31-Jan-2006
.\"   Rename package to `60bit.tmac'.
.\"   Rename register prefix to `60bit-'.
.\"   Use `SC-' register prefix within `SMALLCAPS' macro.
.\"   Fix rounding in SMALLCAPS macro.
.\"   Add more documentation.
.\"
.
.
.\" .add30to60 <x> <y> <z>
.\"
.\" Add a 30bit number to a 60bit number.  Result is a 60bit number:
.\"
.\"   <x> + (<y>h * 2^30 + <y>l) = <z>h * 2^30 + <z>l
.\"
.\"
.\" in: \n[<x>], \n[<y>h], \n[<y>l]
.\"
.\" out: \n[<z>h], \n[<z>l]
.\"
.\" Example: .add30to60 p q r
.\"
.\"          -> input registers: \n[p], \n[qh], \n[ql]
.\"             output registers: \n[rh], \n[rl]
.\"
.de1 add30to60
.  nr 60bit-i (\\n[\\$1] >? \\n[\\$2l])
.  nr \\$3l (\\n[\\$1] + \\n[\\$2l] % 1073741824)
.  nr \\$3h \\n[\\$2h]
.  if (\\n[\\$3l] < \\n[60bit-i]) \
.    nr \\$3h +1
..
.
.
.\" .mult60 <x> <y> <z>
.\"
.\" Multiply two 30bit numbers.  Result is a 60bit number:
.\"
.\"   <x> * <y> = <z>h * 2^30 + <z>l
.\"
.\"
.\" in: \n[<x>], \n[<y>]
.\"
.\" out: \n[<z>h], \n[<z>l]
.\"
.\" Example: .mult60 a b c
.\"
.\"          -> input registers: \n[a], \n[b]
.\"             output registers: \n[ch], \n[cl]
.\"
.de1 mult60
.  nr 60bit-lo1 (\\n[\\$1] % 32768)
.  nr 60bit-hi1 (\\n[\\$1] / 32768)
.  nr 60bit-lo2 (\\n[\\$2] % 32768)
.  nr 60bit-hi2 (\\n[\\$2] / 32768)
.
.  nr \\$3l (\\n[60bit-lo1] * \\n[60bit-lo2] % 1073741824)
.  nr 60bit-i1 (\\n[60bit-lo1] * \\n[60bit-hi2] % 1073741824)
.  nr 60bit-i2 (\\n[60bit-lo2] * \\n[60bit-hi1] % 1073741824)
.  nr \\$3h (\\n[60bit-hi1] * \\n[60bit-hi2] % 1073741824)
.
.  nr 60bit-i1 (\\n[60bit-i1] + \\n[60bit-i2] % 1073741824)
.  \" check carry overflow of 60bit-i1 + 60bit-i2
.  if (\\n[60bit-i1] < \\n[60bit-i2]) \
.    nr \\$3h +32768
.
.  nr \\$3h +(\\n[60bit-i1] / 32768)
.  \" multiply by 32768 in small steps to avoid overflow
.  nr 60bit-i 15
.  while (\\n[60bit-i]) \{\
.    nr 60bit-i1 (\\n[60bit-i1] * 2 % 1073741824)
.    nr 60bit-i -1
.  \}
.
.  nr \\$3l (\\n[\\$3l] + \\n[60bit-i1] % 1073741824)
.  \" check carry overflow of 60bit-i1 + lo
.  if (\\n[\\$3l] < \\n[60bit-i1]) \
.    nr \\$3h +1
..
.
.
.\" .div60by30 <x> <y> <z>
.\"
.\" Divide a 60bit number by a 30bit.  Result is a 30bit number:
.\"
.\"   (<x>h * 2^30 + <x>l) / <y> = <z>
.\"
.\"
.\" in: \n[<x>h], \n[<x>l], \n[<y>]
.\"
.\" out: \n[<z>]
.\"
.\" Example: .div60by30 foo bar baz
.\"
.\"          -> input registers: \n[fooh] \n[fool] \n[bar]
.\"             output register: \n[baz]
.\"
.de1 div60by30
.  nr \\$3 0
.  nr 60bit-i 30
.
.  while (\\n[60bit-i]) \{\
.    nr \\$1h (\\n[\\$1h] * 2 % 1073741824)
.    nr \\$3 (\\n[\\$3] * 2)
.    nr \\$1h +(\\n[\\$1l] / 536870912)
.
.    if (\\n[\\$1h] >= \\n[\\$2]) \{\
.      nr \\$1h -\\n[\\$2]
.      nr \\$3 +1
.    \}
.    nr \\$1l (\\n[\\$1l] * 2 % 1073741824)
.    nr 60bit-i -1
.  \}
..
.
.
.\" .SMALLCAPS <first> <small> <rest>
.\"
.\" This macro emulates small caps.  All three arguments are concatenated
.\" without spaces inbetween.  The first and third argument is taken
.\" unmodified, and the kerning between the last glyph of <first> and the
.\" first glyph of <small> is retained.  Similarly, kerning between the
.\" last glyph of <small> and the first glyph of <rest> is preserved.
.\"
.de1 SMALLCAPS
.  nr SC-x (0*\w'x' + \\n[rst])
.  nr SC-X (0*\w'X' + \\n[rst])
.  nr SC-X/2 (\\n[SC-X] / 2)
.  nr SC-s ((9 * \\n[.ps] + 5) / 10)
.
.  \" We scale the small caps glyphs horizontally by 90%; the vertical
.  \" size is the lowercase letter height plus a third of the difference
.  \" between lowercase and uppercase letter heights.  These are
.  \" heuristical values.
.
.  \" To do proper rounding we multiply all elements by 2:
.  \"   sX = (X - x)/3 + x = (2X + 4x)/6
.  nr SC-sX (((2 * \\n[SC-X]) + (4 * \\n[SC-x]) + 3) / 6)
.
.  \" It is not possible to specify vertical and horizontal scaling
.  \" independently: \H scales only the height, while \s scales both
.  \" height and width.  Consequently, we adjust the argument of \H for
.  \" compensation.
.
.  \" Groff register `.ps' holds the point size in scaled points.  Note
.  \" that `(sX * .ps + X/2) / X' can easily overflow if done with normal
.  \" integer arithmetic.
.  mult60 SC-sX .ps SC-temp1
.  add30to60 SC-X/2 SC-temp1 SC-temp2
.  div60by30 SC-temp2 SC-X SC-H
.
\\$1\
\h'(\w'\\$1\\$2'u - \w'\\$1'u - \w'\\$2'u)'\
\H'\\n[SC-H]u'\
\s[\\n[SC-s]u]\
\\$2\
\h'(\w'\\$2\\$3'u - \w'\\$2'u - \w'\\$3'u)'\
\s0\H'0'\
\\$3
..
.
.
.ps 72z
.vs 76p
Van Gogh,
.br
.SMALLCAPS V AN
.SMALLCAPS G OGH ,
.br
VAN GOGH,
.
.\" EOF




reply via email to

[Prev in Thread] Current Thread [Next in Thread]