Introduce <sys/qmath.h>, a fixed-point math library from Netflix.
This makes it possible to perform mathematical operations on fractional values without using floating point. It operates on Q numbers, which are integer-sized, opaque structures initialized to hold a chosen number of integer and fractional bits. For a general description of the Q number system, see the "Fixed Point Representation & Fractional Math" whitepaper[1]; for the actual API see the qmath(3) man page. This is one of dependencies for the upcoming stats(3) framework[2] that will be applied to the TCP stack in a later commit. 1. https://www.superkits.net/whitepapers/Fixed%20Point%20Representation%20&%20Fractional%20Math.pdf 2. https://reviews.freebsd.org/D20477 Reviewed by: bcr (man pages, earlier version), sef (earlier version) Discussed with: cem, dteske, imp, lstewart Sponsored By: Klara Inc, Netflix Obtained from: Netflix Differential Revision: https://reviews.freebsd.org/D20116
This commit is contained in:
parent
f69c06c303
commit
5a38af1fb8
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=351544
@ -217,6 +217,7 @@ rarely, and then only in very-close-to-halfway cases.
|
|||||||
.Xr complex 3 ,
|
.Xr complex 3 ,
|
||||||
.Xr fenv 3 ,
|
.Xr fenv 3 ,
|
||||||
.Xr ieee 3 ,
|
.Xr ieee 3 ,
|
||||||
|
.Xr qmath 3 ,
|
||||||
.Xr tgmath 3
|
.Xr tgmath 3
|
||||||
.Sh HISTORY
|
.Sh HISTORY
|
||||||
A math library with many of the present functions appeared in
|
A math library with many of the present functions appeared in
|
||||||
|
@ -13,6 +13,16 @@ MAN= assert.3 \
|
|||||||
makedev.3 \
|
makedev.3 \
|
||||||
offsetof.3 \
|
offsetof.3 \
|
||||||
${PTHREAD_MAN} \
|
${PTHREAD_MAN} \
|
||||||
|
Q_FRAWMASK.3 \
|
||||||
|
Q_IFRAWMASK.3 \
|
||||||
|
Q_INI.3 \
|
||||||
|
Q_IRAWMASK.3 \
|
||||||
|
Q_QABS.3 \
|
||||||
|
Q_QADDI.3 \
|
||||||
|
Q_QADDQ.3 \
|
||||||
|
Q_SIGNED.3 \
|
||||||
|
Q_SIGNSHFT.3 \
|
||||||
|
qmath.3 \
|
||||||
queue.3 \
|
queue.3 \
|
||||||
sigevent.3 \
|
sigevent.3 \
|
||||||
siginfo.3 \
|
siginfo.3 \
|
||||||
@ -72,6 +82,68 @@ MLINKS+= fpgetround.3 fpgetmask.3 \
|
|||||||
MLINKS+= makedev.3 major.3 \
|
MLINKS+= makedev.3 major.3 \
|
||||||
makedev.3 minor.3
|
makedev.3 minor.3
|
||||||
MLINKS+= ${PTHREAD_MLINKS}
|
MLINKS+= ${PTHREAD_MLINKS}
|
||||||
|
MLINKS+= Q_FRAWMASK.3 Q_GFRAW.3 \
|
||||||
|
Q_FRAWMASK.3 Q_GFABSVAL.3 \
|
||||||
|
Q_FRAWMASK.3 Q_GFVAL.3 \
|
||||||
|
Q_FRAWMASK.3 Q_SFVAL.3
|
||||||
|
MLINKS+= Q_IFRAWMASK.3 Q_IFVALIMASK.3 \
|
||||||
|
Q_IFRAWMASK.3 Q_IFVALFMASK.3 \
|
||||||
|
Q_IFRAWMASK.3 Q_GIFRAW.3 \
|
||||||
|
Q_IFRAWMASK.3 Q_GIFABSVAL.3 \
|
||||||
|
Q_IFRAWMASK.3 Q_GIFVAL.3 \
|
||||||
|
Q_IFRAWMASK.3 Q_SIFVAL.3 \
|
||||||
|
Q_IFRAWMASK.3 Q_SIFVALS.3
|
||||||
|
MLINKS+= Q_INI.3 Q_NCBITS.3 \
|
||||||
|
Q_INI.3 Q_BT.3 \
|
||||||
|
Q_INI.3 Q_TC.3 \
|
||||||
|
Q_INI.3 Q_NTBITS.3 \
|
||||||
|
Q_INI.3 Q_NFCBITS.3 \
|
||||||
|
Q_INI.3 Q_MAXNFBITS.3 \
|
||||||
|
Q_INI.3 Q_NFBITS.3 \
|
||||||
|
Q_INI.3 Q_NIBITS.3 \
|
||||||
|
Q_INI.3 Q_RPSHFT.3 \
|
||||||
|
Q_INI.3 Q_ABS.3 \
|
||||||
|
Q_INI.3 Q_MAXSTRLEN.3 \
|
||||||
|
Q_INI.3 Q_TOSTR.3 \
|
||||||
|
Q_INI.3 Q_SHL.3 \
|
||||||
|
Q_INI.3 Q_SHR.3 \
|
||||||
|
Q_INI.3 Q_DEBUG.3 \
|
||||||
|
Q_INI.3 Q_DFV2BFV.3
|
||||||
|
MLINKS+= Q_IRAWMASK.3 Q_GIRAW.3 \
|
||||||
|
Q_IRAWMASK.3 Q_GIABSVAL.3 \
|
||||||
|
Q_IRAWMASK.3 Q_GIVAL.3 \
|
||||||
|
Q_IRAWMASK.3 Q_SIVAL.3
|
||||||
|
MLINKS+= Q_QABS.3 Q_Q2D.3 \
|
||||||
|
Q_QABS.3 Q_Q2F.3
|
||||||
|
MLINKS+= Q_QADDI.3 Q_QDIVI.3 \
|
||||||
|
Q_QADDI.3 Q_QMULI.3 \
|
||||||
|
Q_QADDI.3 Q_QSUBI.3 \
|
||||||
|
Q_QADDI.3 Q_QFRACI.3 \
|
||||||
|
Q_QADDI.3 Q_QCPYVALI.3
|
||||||
|
MLINKS+= Q_QADDQ.3 Q_QDIVQ.3 \
|
||||||
|
Q_QADDQ.3 Q_QMULQ.3 \
|
||||||
|
Q_QADDQ.3 Q_QSUBQ.3 \
|
||||||
|
Q_QADDQ.3 Q_NORMPREC.3 \
|
||||||
|
Q_QADDQ.3 Q_QMAXQ.3 \
|
||||||
|
Q_QADDQ.3 Q_QMINQ.3 \
|
||||||
|
Q_QADDQ.3 Q_QCLONEQ.3 \
|
||||||
|
Q_QADDQ.3 Q_QCPYVALQ.3
|
||||||
|
MLINKS+= Q_SIGNED.3 Q_LTZ.3 \
|
||||||
|
Q_SIGNED.3 Q_PRECEQ.3 \
|
||||||
|
Q_SIGNED.3 Q_QLTQ.3 \
|
||||||
|
Q_SIGNED.3 Q_QLEQ.3 \
|
||||||
|
Q_SIGNED.3 Q_QGTQ.3 \
|
||||||
|
Q_SIGNED.3 Q_QGEQ.3 \
|
||||||
|
Q_SIGNED.3 Q_QEQ.3 \
|
||||||
|
Q_SIGNED.3 Q_QNEQ.3 \
|
||||||
|
Q_SIGNED.3 Q_OFLOW.3 \
|
||||||
|
Q_SIGNED.3 Q_RELPREC.3
|
||||||
|
MLINKS+= Q_SIGNSHFT.3 Q_SSIGN.3 \
|
||||||
|
Q_SIGNSHFT.3 Q_CRAWMASK.3 \
|
||||||
|
Q_SIGNSHFT.3 Q_SRAWMASK.3 \
|
||||||
|
Q_SIGNSHFT.3 Q_GCRAW.3 \
|
||||||
|
Q_SIGNSHFT.3 Q_GCVAL.3 \
|
||||||
|
Q_SIGNSHFT.3 Q_SCVAL.3
|
||||||
MLINKS+= queue.3 LIST_CLASS_ENTRY.3 \
|
MLINKS+= queue.3 LIST_CLASS_ENTRY.3 \
|
||||||
queue.3 LIST_CLASS_HEAD.3 \
|
queue.3 LIST_CLASS_HEAD.3 \
|
||||||
queue.3 LIST_EMPTY.3 \
|
queue.3 LIST_EMPTY.3 \
|
||||||
|
125
share/man/man3/Q_FRAWMASK.3
Normal file
125
share/man/man3/Q_FRAWMASK.3
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2018 Netflix, Inc.
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions, and the following disclaimer,
|
||||||
|
.\" without modification, immediately at the beginning of the file.
|
||||||
|
.\" 2. The name of the author may not be used to endorse or promote products
|
||||||
|
.\" derived from this software without specific prior written permission.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
.\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
.\" SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.\" $FreeBSD$
|
||||||
|
.\"
|
||||||
|
.Dd July 8, 2018
|
||||||
|
.Dt Q_FRAWMASK 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm Q_FRAWMASK ,
|
||||||
|
.Nm Q_GFRAW ,
|
||||||
|
.Nm Q_GFABSVAL ,
|
||||||
|
.Nm Q_GFVAL ,
|
||||||
|
.Nm Q_SFVAL
|
||||||
|
.Nd fixed-point math functions which manipulate the fractional data bits
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In sys/qmath.h
|
||||||
|
.Ft ITYPE
|
||||||
|
.Fn Q_FRAWMASK "QTYPE q"
|
||||||
|
.Ft ITYPE
|
||||||
|
.Fn Q_GFRAW "QTYPE q"
|
||||||
|
.Ft ITYPE
|
||||||
|
.Fn Q_GFABSVAL "QTYPE q"
|
||||||
|
.Ft ITYPE
|
||||||
|
.Fn Q_GFVAL "QTYPE q"
|
||||||
|
.Ft QTYPE
|
||||||
|
.Fn Q_SFVAL "QTYPE q" "ITYPE fv"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Fn Q_FRAWMASK
|
||||||
|
returns a
|
||||||
|
.Fa q Ns -specific
|
||||||
|
bit mask for
|
||||||
|
.Fa q Ap s
|
||||||
|
fractional data bits.
|
||||||
|
.Pp
|
||||||
|
.Fn Q_GFRAW
|
||||||
|
returns
|
||||||
|
.Fa q Ap s
|
||||||
|
raw masked fractional data bits.
|
||||||
|
.Pp
|
||||||
|
.Fn Q_GFABSVAL
|
||||||
|
and
|
||||||
|
.Fn Q_GFVAL
|
||||||
|
return the absolute and real values of
|
||||||
|
.Fa q Ap s
|
||||||
|
fractional data bits respectively.
|
||||||
|
.Pp
|
||||||
|
.Fn Q_SFVAL
|
||||||
|
sets
|
||||||
|
.Fa q Ap s
|
||||||
|
fractional data bits to the value
|
||||||
|
.Fa fv .
|
||||||
|
.Pp
|
||||||
|
All of those functions operate on
|
||||||
|
the following data types:
|
||||||
|
.Vt s8q_t ,
|
||||||
|
.Vt u8q_t ,
|
||||||
|
.Vt s16q_t ,
|
||||||
|
.Vt u16q_t ,
|
||||||
|
.Vt s32q_t ,
|
||||||
|
.Vt u32q_t ,
|
||||||
|
.Vt s64q_t ,
|
||||||
|
and
|
||||||
|
.Vt u64q_t ,
|
||||||
|
which are referred to generically as
|
||||||
|
.Fa QTYPE .
|
||||||
|
The
|
||||||
|
.Fa ITYPE
|
||||||
|
refers to the
|
||||||
|
.Xr stdint 7
|
||||||
|
integer types.
|
||||||
|
.Pp
|
||||||
|
For more details, see
|
||||||
|
.Xr qmath 3 .
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
.Fn Q_FRAWMASK ,
|
||||||
|
.Fn Q_GFRAW ,
|
||||||
|
.Fn Q_GFABSVAL
|
||||||
|
and
|
||||||
|
.Fn Q_GFVAL
|
||||||
|
return their respective values as integers of the same underlying ITYPE as
|
||||||
|
.Fa q .
|
||||||
|
.Pp
|
||||||
|
.Fn Q_SFVAL
|
||||||
|
returns the value of
|
||||||
|
.Fa q
|
||||||
|
post set.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr errno 2 ,
|
||||||
|
.Xr qmath 3 ,
|
||||||
|
.Xr stdint 7
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Xr qmath 3
|
||||||
|
functions first appeared in
|
||||||
|
.Fx 13.0 .
|
||||||
|
.Sh AUTHORS
|
||||||
|
.An -nosplit
|
||||||
|
The
|
||||||
|
.Xr qmath 3
|
||||||
|
functions and this manual page were written by
|
||||||
|
.An Lawrence Stewart Aq Mt lstewart@FreeBSD.org
|
||||||
|
and sponsored by Netflix, Inc.
|
162
share/man/man3/Q_IFRAWMASK.3
Normal file
162
share/man/man3/Q_IFRAWMASK.3
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2018 Netflix, Inc.
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions, and the following disclaimer,
|
||||||
|
.\" without modification, immediately at the beginning of the file.
|
||||||
|
.\" 2. The name of the author may not be used to endorse or promote products
|
||||||
|
.\" derived from this software without specific prior written permission.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
.\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
.\" SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.\" $FreeBSD$
|
||||||
|
.\"
|
||||||
|
.Dd July 8, 2018
|
||||||
|
.Dt Q_IFRAWMASK 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm Q_IFRAWMASK ,
|
||||||
|
.Nm Q_IFVALIMASK ,
|
||||||
|
.Nm Q_IFVALFMASK ,
|
||||||
|
.Nm Q_GIFRAW ,
|
||||||
|
.Nm Q_GIFABSVAL ,
|
||||||
|
.Nm Q_GIFVAL ,
|
||||||
|
.Nm Q_SIFVAL ,
|
||||||
|
.Nm Q_SIFVALS
|
||||||
|
.Nd fixed-point math functions which manipulate the combined integer/fractional
|
||||||
|
data bits
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In sys/qmath.h
|
||||||
|
.Ft ITYPE
|
||||||
|
.Fn Q_IFRAWMASK "QTYPE q"
|
||||||
|
.Ft ITYPE
|
||||||
|
.Fn Q_IFVALIMASK "QTYPE q"
|
||||||
|
.Ft ITYPE
|
||||||
|
.Fn Q_IFVALFMASK "QTYPE q"
|
||||||
|
.Ft ITYPE
|
||||||
|
.Fn Q_GIFRAW "QTYPE q"
|
||||||
|
.Ft ITYPE
|
||||||
|
.Fn Q_GIFABSVAL "QTYPE q"
|
||||||
|
.Ft ITYPE
|
||||||
|
.Fn Q_GIFVAL "QTYPE q"
|
||||||
|
.Ft QTYPE
|
||||||
|
.Fn Q_SIFVAL "QTYPE q" "ITYPE ifv"
|
||||||
|
.Ft QTYPE
|
||||||
|
.Fn Q_SIFVALS "QTYPE q" "ITYPE iv" "ITYPE fv"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Fn Q_IFRAWMASK
|
||||||
|
returns a
|
||||||
|
.Fa q Ns -specific
|
||||||
|
bit mask for
|
||||||
|
.Fa q Ap s
|
||||||
|
combined integer and fractional data bits.
|
||||||
|
.Pp
|
||||||
|
.Fn Q_IFVALIMASK
|
||||||
|
and
|
||||||
|
.Fn Q_IFVALFMASK
|
||||||
|
return
|
||||||
|
.Fa q Ns -specific
|
||||||
|
bit masks for the integer and fractional bits of
|
||||||
|
.Fa q Ap s
|
||||||
|
combined integer and fractional data bits value, i.e., are applicable to the
|
||||||
|
values returned by
|
||||||
|
.Fn Q_GIFABSVAL
|
||||||
|
and
|
||||||
|
.Fn Q_GIFVAL .
|
||||||
|
.Pp
|
||||||
|
.Fn Q_GIFRAW
|
||||||
|
returns
|
||||||
|
.Fa q Ap s
|
||||||
|
raw masked integer/fractional data bits.
|
||||||
|
.Pp
|
||||||
|
.Fn Q_GIFABSVAL
|
||||||
|
and
|
||||||
|
.Fn Q_GIFVAL
|
||||||
|
return the absolute and real values of
|
||||||
|
.Fa q Ap s
|
||||||
|
integer/fractional data bits respectively.
|
||||||
|
.Pp
|
||||||
|
.Fn Q_SIFVAL
|
||||||
|
sets
|
||||||
|
.Fa q Ap s
|
||||||
|
combined integer/fractional data bits to the value
|
||||||
|
.Fa ifv ,
|
||||||
|
whereas
|
||||||
|
.Fn Q_SIFVALS
|
||||||
|
independently sets
|
||||||
|
.Fa q Ap s
|
||||||
|
integer and fractional data bits to the separate values
|
||||||
|
.Fa iv
|
||||||
|
and
|
||||||
|
.Fa fv .
|
||||||
|
.Pp
|
||||||
|
All of those functions operate on
|
||||||
|
the following data types:
|
||||||
|
.Vt s8q_t ,
|
||||||
|
.Vt u8q_t ,
|
||||||
|
.Vt s16q_t ,
|
||||||
|
.Vt u16q_t ,
|
||||||
|
.Vt s32q_t ,
|
||||||
|
.Vt u32q_t ,
|
||||||
|
.Vt s64q_t ,
|
||||||
|
and
|
||||||
|
.Vt u64q_t ,
|
||||||
|
which are referred to generically as
|
||||||
|
.Fa QTYPE .
|
||||||
|
The
|
||||||
|
.Fa ITYPE
|
||||||
|
refers to the
|
||||||
|
.Xr stdint 7
|
||||||
|
integer types.
|
||||||
|
.Pp
|
||||||
|
For more details, see
|
||||||
|
.Xr qmath 3 .
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
.Fn Q_IFRAWMASK ,
|
||||||
|
.Fn Q_IFVALIMASK ,
|
||||||
|
.Fn Q_IFVALFMASK ,
|
||||||
|
.Fn Q_GIFABSVAL ,
|
||||||
|
.Fn Q_GIFVAL ,
|
||||||
|
.Fn Q_GIFRAW ,
|
||||||
|
.Fn Q_GIFABSVAL
|
||||||
|
and
|
||||||
|
.Fn Q_GIFVAL
|
||||||
|
return their respective values as integers of the same underlying ITYPE as
|
||||||
|
.Fa q .
|
||||||
|
.Pp
|
||||||
|
.Fn Q_SIFVAL
|
||||||
|
and
|
||||||
|
.Fn Q_SIFVALS
|
||||||
|
return the value of
|
||||||
|
.Fa q
|
||||||
|
post change.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr errno 2 ,
|
||||||
|
.Xr qmath 3 ,
|
||||||
|
.Xr stdint 7
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Xr qmath 3
|
||||||
|
functions first appeared in
|
||||||
|
.Fx 13.0 .
|
||||||
|
.Sh AUTHORS
|
||||||
|
.An -nosplit
|
||||||
|
The
|
||||||
|
.Xr qmath 3
|
||||||
|
functions and this manual page were written by
|
||||||
|
.An Lawrence Stewart Aq Mt lstewart@FreeBSD.org
|
||||||
|
and sponsored by Netflix, Inc.
|
261
share/man/man3/Q_INI.3
Normal file
261
share/man/man3/Q_INI.3
Normal file
@ -0,0 +1,261 @@
|
|||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2018 Netflix, Inc.
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions, and the following disclaimer,
|
||||||
|
.\" without modification, immediately at the beginning of the file.
|
||||||
|
.\" 2. The name of the author may not be used to endorse or promote products
|
||||||
|
.\" derived from this software without specific prior written permission.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
.\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
.\" SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.\" $FreeBSD$
|
||||||
|
.\"
|
||||||
|
.Dd July 8, 2018
|
||||||
|
.Dt Q_INI 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm Q_INI ,
|
||||||
|
.Nm Q_NCBITS ,
|
||||||
|
.Nm Q_BT ,
|
||||||
|
.Nm Q_TC ,
|
||||||
|
.Nm Q_NTBITS ,
|
||||||
|
.Nm Q_NFCBITS ,
|
||||||
|
.Nm Q_MAXNFBITS ,
|
||||||
|
.Nm Q_NFBITS ,
|
||||||
|
.Nm Q_NIBITS ,
|
||||||
|
.Nm Q_RPSHFT ,
|
||||||
|
.Nm Q_ABS ,
|
||||||
|
.Nm Q_MAXSTRLEN ,
|
||||||
|
.Nm Q_TOSTR ,
|
||||||
|
.Nm Q_SHL ,
|
||||||
|
.Nm Q_SHR ,
|
||||||
|
.Nm Q_DEBUG
|
||||||
|
.Nd fixed-point math miscellaneous functions/variables
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In sys/qmath.h
|
||||||
|
.Ft QTYPE
|
||||||
|
.Fn Q_INI "QTYPE *q" "ITYPE iv" "ITYPE dfv" "int rpshft"
|
||||||
|
.Fd Q_NCBITS
|
||||||
|
.Ft __typeof(q)
|
||||||
|
.Fn Q_BT "QTYPE q"
|
||||||
|
.Ft ITYPE
|
||||||
|
.Fn Q_TC "QTYPE q" "ITYPE v"
|
||||||
|
.Ft uint32_t
|
||||||
|
.Fn Q_NTBITS "QTYPE q"
|
||||||
|
.Ft uint32_t
|
||||||
|
.Fn Q_NFCBITS "QTYPE q"
|
||||||
|
.Ft uint32_t
|
||||||
|
.Fn Q_MAXNFBITS "QTYPE q"
|
||||||
|
.Ft uint32_t
|
||||||
|
.Fn Q_NFBITS "QTYPE q"
|
||||||
|
.Ft uint32_t
|
||||||
|
.Fn Q_NIBITS "QTYPE q"
|
||||||
|
.Ft uint32_t
|
||||||
|
.Fn Q_RPSHFT "QTYPE q"
|
||||||
|
.Ft NTYPE
|
||||||
|
.Fn Q_ABS "NTYPE n"
|
||||||
|
.Ft uint32_t
|
||||||
|
.Fn Q_MAXSTRLEN "QTYPE q" "int base"
|
||||||
|
.Ft char *
|
||||||
|
.Fn Q_TOSTR "QTYPE q" "int prec" "int base" "char *s" "int slen"
|
||||||
|
.Ft ITYPE
|
||||||
|
.Fn Q_SHL "QTYPE q" "ITYPE iv"
|
||||||
|
.Ft ITYPE
|
||||||
|
.Fn Q_SHR "QTYPE q" "ITYPE iv"
|
||||||
|
.Ft char *, ...
|
||||||
|
.Fn Q_DEBUG "QTYPE q" "char *prefmt" "char *postfmt" "incfmt"
|
||||||
|
.Ft ITYPE
|
||||||
|
.Fn Q_DFV2BFV "ITYPE dfv" "int nfbits"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Fn Q_INI
|
||||||
|
initialises a Q number with the supplied integral value
|
||||||
|
.Fa iv
|
||||||
|
and decimal fractional value
|
||||||
|
.Fa dfv ,
|
||||||
|
with appropriate control bits based on the requested radix shift point
|
||||||
|
.Fa rpshft .
|
||||||
|
.Fa dfv
|
||||||
|
must be passed as a preprocessor literal to preserve leading zeroes.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Dv Q_NCBITS
|
||||||
|
defined constant specifies the number of reserved control bits, currently 3.
|
||||||
|
.Pp
|
||||||
|
.Fn Q_NTBITS ,
|
||||||
|
.Fn Q_NFCBITS ,
|
||||||
|
.Fn Q_MAXNFBITS ,
|
||||||
|
.Fn Q_NFBITS
|
||||||
|
and
|
||||||
|
.Fn Q_NIBITS
|
||||||
|
return the
|
||||||
|
.Fa q Ns -specific
|
||||||
|
count of total, control-encoded fractional, maximum fractional, effective
|
||||||
|
fractional, and integer bits applicable to
|
||||||
|
.Fa q
|
||||||
|
respectively.
|
||||||
|
.Pp
|
||||||
|
.Fn Q_BT
|
||||||
|
returns the C data type of
|
||||||
|
.Fa q ,
|
||||||
|
while
|
||||||
|
.Fn Q_TC
|
||||||
|
returns
|
||||||
|
.Fa v
|
||||||
|
type casted to the C data type of
|
||||||
|
.Fa q .
|
||||||
|
.Pp
|
||||||
|
.Fn Q_RPSHFT
|
||||||
|
returns the bit position of
|
||||||
|
.Fa q Ap s
|
||||||
|
binary radix point relative to bit zero.
|
||||||
|
.Pp
|
||||||
|
.Fn Q_ABS
|
||||||
|
returns the absolute value of any standard numeric type
|
||||||
|
.Pq that uses the MSB as a sign bit, but not Q numbers
|
||||||
|
passed in as
|
||||||
|
.Fa n .
|
||||||
|
The function is signed/unsigned type safe.
|
||||||
|
.Pp
|
||||||
|
.Fn Q_SHL
|
||||||
|
and
|
||||||
|
.Fn Q_SHR
|
||||||
|
return the integral value
|
||||||
|
.Fa v
|
||||||
|
left or right shifted by the appropriate amount for
|
||||||
|
.Fa q .
|
||||||
|
.Pp
|
||||||
|
.Fn Q_MAXSTRLEN
|
||||||
|
calculates the maximum number of characters that may be required to render the
|
||||||
|
C-string representation of
|
||||||
|
.Fa q
|
||||||
|
with numeric base
|
||||||
|
.Fa base .
|
||||||
|
.Pp
|
||||||
|
.Fn Q_TOSTR
|
||||||
|
renders the C-string representation of
|
||||||
|
.Fa q
|
||||||
|
with numeric base
|
||||||
|
.Fa base
|
||||||
|
and fractional precision
|
||||||
|
.Fa prec
|
||||||
|
into
|
||||||
|
.Fa s
|
||||||
|
which has an available capacity of
|
||||||
|
.Fa slen
|
||||||
|
characters.
|
||||||
|
.Fa base
|
||||||
|
must be in range
|
||||||
|
.Bq 2,16 .
|
||||||
|
Specifying
|
||||||
|
.Fa prec
|
||||||
|
as -1 renders the number's fractional component with maximum precision.
|
||||||
|
If
|
||||||
|
.Fa slen
|
||||||
|
is greater than zero but insufficient to hold the complete C-string, the '\\0'
|
||||||
|
C-string terminator will be written to
|
||||||
|
.Fa *s ,
|
||||||
|
thereby returning a zero length C-string.
|
||||||
|
.Pp
|
||||||
|
.Fn Q_DEBUG
|
||||||
|
returns a format string and associated data suitable for printf-like rendering
|
||||||
|
of debugging information pertaining to
|
||||||
|
.Fa q .
|
||||||
|
If either
|
||||||
|
.Fa prefmt
|
||||||
|
and/or
|
||||||
|
.Fa postfmt
|
||||||
|
are specified, they are prepended and appended to the resulting format string
|
||||||
|
respectively.
|
||||||
|
The
|
||||||
|
.Fa incfmt
|
||||||
|
boolean specifies whether to include
|
||||||
|
.Pq Vt true
|
||||||
|
or exclude
|
||||||
|
.Pq Vt false
|
||||||
|
the raw format string itself in the debugging output.
|
||||||
|
.Pp
|
||||||
|
.Fn Q_DFV2BFV
|
||||||
|
converts decimal fractional value
|
||||||
|
.Fa dfv
|
||||||
|
to its binary-encoded representation with
|
||||||
|
.Fa nfbits
|
||||||
|
of binary precision.
|
||||||
|
.Fa dfv
|
||||||
|
must be passed as a preprocessor literal to preserve leading zeroes.
|
||||||
|
The returned value can be used to set a Q number's fractional bits, for example
|
||||||
|
using
|
||||||
|
.Fn Q_SFVAL .
|
||||||
|
.Pp
|
||||||
|
All of those functions operate on
|
||||||
|
the following data types:
|
||||||
|
.Vt s8q_t ,
|
||||||
|
.Vt u8q_t ,
|
||||||
|
.Vt s16q_t ,
|
||||||
|
.Vt u16q_t ,
|
||||||
|
.Vt s32q_t ,
|
||||||
|
.Vt u32q_t ,
|
||||||
|
.Vt s64q_t ,
|
||||||
|
and
|
||||||
|
.Vt u64q_t ,
|
||||||
|
which are referred to generically as
|
||||||
|
.Fa QTYPE .
|
||||||
|
The
|
||||||
|
.Fa ITYPE
|
||||||
|
refers to the
|
||||||
|
.Xr stdint 7
|
||||||
|
integer types.
|
||||||
|
.Fa NTYPE
|
||||||
|
is used to refer to any numeric type and is therefore a superset of
|
||||||
|
.Fa QTYPE
|
||||||
|
and
|
||||||
|
.Fa ITYPE .
|
||||||
|
.Pp
|
||||||
|
For more details, see
|
||||||
|
.Xr qmath 3 .
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
.Fn Q_INI
|
||||||
|
returns the initialised Q number which can be used to chain initialise
|
||||||
|
additional Q numbers.
|
||||||
|
.Pp
|
||||||
|
.Fn Q_TOSTR
|
||||||
|
returns a pointer to the '\\0' C-string terminator appended to
|
||||||
|
.Fa s
|
||||||
|
after the rendered numeric data, or NULL on buffer overflow.
|
||||||
|
.Pp
|
||||||
|
.Fn Q_DFV2BFV
|
||||||
|
returns the binary-encoded representation of decimal fractional value
|
||||||
|
.Fa dfv
|
||||||
|
with
|
||||||
|
.Fa nfbits
|
||||||
|
of binary precision.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr errno 2 ,
|
||||||
|
.Xr qmath 3 ,
|
||||||
|
.Xr stdint 7
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Xr qmath 3
|
||||||
|
functions first appeared in
|
||||||
|
.Fx 13.0 .
|
||||||
|
.Sh AUTHORS
|
||||||
|
.An -nosplit
|
||||||
|
The
|
||||||
|
.Xr qmath 3
|
||||||
|
functions and this manual page were written by
|
||||||
|
.An Lawrence Stewart Aq Mt lstewart@FreeBSD.org
|
||||||
|
and sponsored by Netflix, Inc.
|
125
share/man/man3/Q_IRAWMASK.3
Normal file
125
share/man/man3/Q_IRAWMASK.3
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2018 Netflix, Inc.
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions, and the following disclaimer,
|
||||||
|
.\" without modification, immediately at the beginning of the file.
|
||||||
|
.\" 2. The name of the author may not be used to endorse or promote products
|
||||||
|
.\" derived from this software without specific prior written permission.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
.\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
.\" SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.\" $FreeBSD$
|
||||||
|
.\"
|
||||||
|
.Dd July 8, 2018
|
||||||
|
.Dt Q_IRAWMASK 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm Q_IRAWMASK ,
|
||||||
|
.Nm Q_GIRAW ,
|
||||||
|
.Nm Q_GIABSVAL ,
|
||||||
|
.Nm Q_GIVAL ,
|
||||||
|
.Nm Q_SIVAL
|
||||||
|
.Nd fixed-point math functions which manipulate the integer data bits
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In sys/qmath.h
|
||||||
|
.Ft ITYPE
|
||||||
|
.Fn Q_IRAWMASK "QTYPE q"
|
||||||
|
.Ft ITYPE
|
||||||
|
.Fn Q_GIRAW "QTYPE q"
|
||||||
|
.Ft ITYPE
|
||||||
|
.Fn Q_GIABSVAL "QTYPE q"
|
||||||
|
.Ft ITYPE
|
||||||
|
.Fn Q_GIVAL "QTYPE q"
|
||||||
|
.Ft QTYPE
|
||||||
|
.Fn Q_SIVAL "QTYPE q" "ITYPE iv"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Fn Q_IRAWMASK
|
||||||
|
returns a
|
||||||
|
.Fa q Ns -specific
|
||||||
|
bit mask for
|
||||||
|
.Fa q Ap s
|
||||||
|
integer data bits.
|
||||||
|
.Pp
|
||||||
|
.Fn Q_GIRAW
|
||||||
|
returns
|
||||||
|
.Fa q Ap s
|
||||||
|
raw masked integer data bits.
|
||||||
|
.Pp
|
||||||
|
.Fn Q_GIABSVAL
|
||||||
|
and
|
||||||
|
.Fn Q_GIVAL
|
||||||
|
return the absolute and real values of
|
||||||
|
.Fa q Ap s
|
||||||
|
integer data bits respectively.
|
||||||
|
.Pp
|
||||||
|
.Fn Q_SIVAL
|
||||||
|
sets
|
||||||
|
.Fa q Ap s
|
||||||
|
integer data bits to the value
|
||||||
|
.Fa iv .
|
||||||
|
.Pp
|
||||||
|
All of those functions operate on
|
||||||
|
the following data types:
|
||||||
|
.Vt s8q_t ,
|
||||||
|
.Vt u8q_t ,
|
||||||
|
.Vt s16q_t ,
|
||||||
|
.Vt u16q_t ,
|
||||||
|
.Vt s32q_t ,
|
||||||
|
.Vt u32q_t ,
|
||||||
|
.Vt s64q_t ,
|
||||||
|
and
|
||||||
|
.Vt u64q_t ,
|
||||||
|
which are referred to generically as
|
||||||
|
.Fa QTYPE .
|
||||||
|
The
|
||||||
|
.Fa ITYPE
|
||||||
|
refers to the
|
||||||
|
.Xr stdint 7
|
||||||
|
integer types.
|
||||||
|
.Pp
|
||||||
|
For more details, see
|
||||||
|
.Xr qmath 3 .
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
.Fn Q_IRAWMASK ,
|
||||||
|
.Fn Q_GIRAW ,
|
||||||
|
.Fn Q_GIABSVAL
|
||||||
|
and
|
||||||
|
.Fn Q_GIVAL
|
||||||
|
return their respective values as integers of the same underlying ITYPE as
|
||||||
|
.Fa q .
|
||||||
|
.Pp
|
||||||
|
.Fn Q_SIVAL
|
||||||
|
returns the value of
|
||||||
|
.Fa q
|
||||||
|
post change.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr errno 2 ,
|
||||||
|
.Xr qmath 3 ,
|
||||||
|
.Xr stdint 7
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Xr qmath 3
|
||||||
|
functions first appeared in
|
||||||
|
.Fx 13.0 .
|
||||||
|
.Sh AUTHORS
|
||||||
|
.An -nosplit
|
||||||
|
The
|
||||||
|
.Xr qmath 3
|
||||||
|
functions and this manual page were written by
|
||||||
|
.An Lawrence Stewart Aq Mt lstewart@FreeBSD.org
|
||||||
|
and sponsored by Netflix, Inc.
|
101
share/man/man3/Q_QABS.3
Normal file
101
share/man/man3/Q_QABS.3
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2018 Netflix, Inc.
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions, and the following disclaimer,
|
||||||
|
.\" without modification, immediately at the beginning of the file.
|
||||||
|
.\" 2. The name of the author may not be used to endorse or promote products
|
||||||
|
.\" derived from this software without specific prior written permission.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
.\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
.\" SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.\" $FreeBSD$
|
||||||
|
.\"
|
||||||
|
.Dd July 8, 2018
|
||||||
|
.Dt Q_QABS 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm Q_QABS ,
|
||||||
|
.Nm Q_Q2S ,
|
||||||
|
.Nm Q_Q2F
|
||||||
|
.Nd fixed-point math functions which operate on a single Q number
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In sys/qmath.h
|
||||||
|
.Ft QTYPE
|
||||||
|
.Fn Q_QABS "QTYPE q"
|
||||||
|
.Ft double
|
||||||
|
.Fn Q_Q2D "QTYPE q"
|
||||||
|
.Ft float
|
||||||
|
.Fn Q_Q2F "QTYPE q"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Fn Q_QABS
|
||||||
|
function returns an absolute value representation of
|
||||||
|
.Fa q .
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn Q_Q2D
|
||||||
|
and
|
||||||
|
.Fn Q_Q2F
|
||||||
|
functions return the double and float representations of
|
||||||
|
.Fa q
|
||||||
|
respectively.
|
||||||
|
.Pp
|
||||||
|
All of those functions operate on
|
||||||
|
the following data types:
|
||||||
|
.Vt s8q_t ,
|
||||||
|
.Vt u8q_t ,
|
||||||
|
.Vt s16q_t ,
|
||||||
|
.Vt u16q_t ,
|
||||||
|
.Vt s32q_t ,
|
||||||
|
.Vt u32q_t ,
|
||||||
|
.Vt s64q_t ,
|
||||||
|
and
|
||||||
|
.Vt u64q_t ,
|
||||||
|
which are referred to generically as
|
||||||
|
.Fa QTYPE .
|
||||||
|
.Pp
|
||||||
|
For more details, see
|
||||||
|
.Xr qmath 3 .
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
.Fn Q_QABS
|
||||||
|
function returns a QTYPE that is identical to that of
|
||||||
|
.Fa q .
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn Q_Q2D
|
||||||
|
and
|
||||||
|
.Fn Q_Q2F
|
||||||
|
functions return the double and float representations of
|
||||||
|
.Fa q
|
||||||
|
respectively.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr errno 2 ,
|
||||||
|
.Xr qmath 3 ,
|
||||||
|
.Xr stdint 7
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Xr qmath 3
|
||||||
|
functions first appeared in
|
||||||
|
.Fx 13.0 .
|
||||||
|
.Sh AUTHORS
|
||||||
|
.An -nosplit
|
||||||
|
The
|
||||||
|
.Xr qmath 3
|
||||||
|
functions and this manual page were written by
|
||||||
|
.An Lawrence Stewart Aq Mt lstewart@FreeBSD.org
|
||||||
|
and sponsored by Netflix, Inc.
|
134
share/man/man3/Q_QADDI.3
Normal file
134
share/man/man3/Q_QADDI.3
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2018 Netflix, Inc.
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions, and the following disclaimer,
|
||||||
|
.\" without modification, immediately at the beginning of the file.
|
||||||
|
.\" 2. The name of the author may not be used to endorse or promote products
|
||||||
|
.\" derived from this software without specific prior written permission.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
.\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
.\" SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.\" $FreeBSD$
|
||||||
|
.\"
|
||||||
|
.Dd July 8, 2018
|
||||||
|
.Dt Q_QADDI 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm Q_QADDI ,
|
||||||
|
.Nm Q_QDIVI ,
|
||||||
|
.Nm Q_QMULI ,
|
||||||
|
.Nm Q_QSUBI ,
|
||||||
|
.Nm Q_QFRACI ,
|
||||||
|
.Nm Q_QCPYVALI
|
||||||
|
.Nd fixed-point math functions which apply integers to a Q number
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In sys/qmath.h
|
||||||
|
.Ft int
|
||||||
|
.Fn Q_QADDI "QTYPE *a" "ITYPE b"
|
||||||
|
.Ft int
|
||||||
|
.Fn Q_QDIVI "QTYPE *a" "ITYPE b"
|
||||||
|
.Ft int
|
||||||
|
.Fn Q_QMULI "QTYPE *a" "ITYPE b"
|
||||||
|
.Ft int
|
||||||
|
.Fn Q_QSUBI "QTYPE *a" "ITYPE b"
|
||||||
|
.Ft int
|
||||||
|
.Fn Q_QFRACI "QTYPE *q" "ITYPE n" "ITYPE d"
|
||||||
|
.Ft int
|
||||||
|
.Fn Q_QCPYVALI "QTYPE *q" "ITYPE i"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Fn Q_QADDI ,
|
||||||
|
.Fn Q_QDIVI ,
|
||||||
|
.Fn Q_QMULI
|
||||||
|
and
|
||||||
|
.Fn Q_QSUBI
|
||||||
|
functions add, divide, multiply or subtract
|
||||||
|
.Fa b
|
||||||
|
to/by/from
|
||||||
|
.Fa a
|
||||||
|
respectively, storing the result in
|
||||||
|
.Fa a .
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn Q_QFRACI
|
||||||
|
function computes the fraction
|
||||||
|
.Fa n
|
||||||
|
divided by
|
||||||
|
.Fa d
|
||||||
|
and stores the fixed-point result in
|
||||||
|
.Fa q .
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn Q_QCPYVALI
|
||||||
|
function overwrites
|
||||||
|
.Fa q Ap s
|
||||||
|
integer and fractional bits with the Q representation of integer value
|
||||||
|
.Fa i .
|
||||||
|
.Pp
|
||||||
|
All of those functions operate on
|
||||||
|
the following data types:
|
||||||
|
.Vt s8q_t ,
|
||||||
|
.Vt u8q_t ,
|
||||||
|
.Vt s16q_t ,
|
||||||
|
.Vt u16q_t ,
|
||||||
|
.Vt s32q_t ,
|
||||||
|
.Vt u32q_t ,
|
||||||
|
.Vt s64q_t ,
|
||||||
|
and
|
||||||
|
.Vt u64q_t ,
|
||||||
|
which are referred to generically as
|
||||||
|
.Fa QTYPE .
|
||||||
|
The
|
||||||
|
.Fa ITYPE
|
||||||
|
refers to the
|
||||||
|
.Xr stdint 7
|
||||||
|
integer types.
|
||||||
|
.Pp
|
||||||
|
For more details, see
|
||||||
|
.Xr qmath 3 .
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
.Fn Q_QADDI ,
|
||||||
|
.Fn Q_QDIVI ,
|
||||||
|
.Fn Q_QMULI ,
|
||||||
|
.Fn Q_QSUBI ,
|
||||||
|
.Fn Q_QFRACI
|
||||||
|
and
|
||||||
|
.Fn Q_QCPYVALI
|
||||||
|
functions return 0 on success, or an errno on failure.
|
||||||
|
.Er EINVAL
|
||||||
|
is returned for divide-by-zero.
|
||||||
|
.Er EOVERFLOW
|
||||||
|
and
|
||||||
|
.Er ERANGE
|
||||||
|
are returned for overflow and underflow respectively.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr errno 2 ,
|
||||||
|
.Xr qmath 3 ,
|
||||||
|
.Xr stdint 7
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Xr qmath 3
|
||||||
|
functions first appeared in
|
||||||
|
.Fx 13.0 .
|
||||||
|
.Sh AUTHORS
|
||||||
|
.An -nosplit
|
||||||
|
The
|
||||||
|
.Xr qmath 3
|
||||||
|
functions and this manual page were written by
|
||||||
|
.An Lawrence Stewart Aq Mt lstewart@FreeBSD.org
|
||||||
|
and sponsored by Netflix, Inc.
|
175
share/man/man3/Q_QADDQ.3
Normal file
175
share/man/man3/Q_QADDQ.3
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2018 Netflix, Inc.
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions, and the following disclaimer,
|
||||||
|
.\" without modification, immediately at the beginning of the file.
|
||||||
|
.\" 2. The name of the author may not be used to endorse or promote products
|
||||||
|
.\" derived from this software without specific prior written permission.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
.\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
.\" SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.\" $FreeBSD$
|
||||||
|
.\"
|
||||||
|
.Dd July 8, 2018
|
||||||
|
.Dt Q_QADDQ 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm Q_QADDQ ,
|
||||||
|
.Nm Q_QDIVQ ,
|
||||||
|
.Nm Q_QMULQ ,
|
||||||
|
.Nm Q_QSUBQ ,
|
||||||
|
.Nm Q_NORMPREC ,
|
||||||
|
.Nm Q_QMAXQ ,
|
||||||
|
.Nm Q_QMINQ ,
|
||||||
|
.Nm Q_QCLONEQ ,
|
||||||
|
.Nm Q_CPYVALQ
|
||||||
|
.Nd fixed-point math functions which operate on two Q numbers
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In sys/qmath.h
|
||||||
|
.Ft int
|
||||||
|
.Fn Q_QADDQ "QTYPE *a" "QTYPE b"
|
||||||
|
.Ft int
|
||||||
|
.Fn Q_QDIVQ "QTYPE *a" "QTYPE b"
|
||||||
|
.Ft int
|
||||||
|
.Fn Q_QMULQ "QTYPE *a" "QTYPE b"
|
||||||
|
.Ft int
|
||||||
|
.Fn Q_QSUBQ "QTYPE *a" "QTYPE b"
|
||||||
|
.Ft int
|
||||||
|
.Fn Q_NORMPREC "QTYPE *a" "QTYPE *b"
|
||||||
|
.Ft QTYPE
|
||||||
|
.Fn Q_QMAXQ "QTYPE a" "QTYPE b"
|
||||||
|
.Ft QTYPE
|
||||||
|
.Fn Q_QMINQ "QTYPE a" "QTYPE b"
|
||||||
|
.Ft int
|
||||||
|
.Fn Q_QCLONEQ "QTYPE *l" "QTYPE r"
|
||||||
|
.Ft int
|
||||||
|
.Fn Q_QCPYVALQ "QTYPE *l" "QTYPE r"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Fn Q_QADDQ ,
|
||||||
|
.Fn Q_QDIVQ ,
|
||||||
|
.Fn Q_QMULQ ,
|
||||||
|
and
|
||||||
|
.Fn Q_QSUBQ
|
||||||
|
functions add, divide, multiply or subtract
|
||||||
|
.Fa b
|
||||||
|
to/by/from
|
||||||
|
.Fa a
|
||||||
|
respectively, storing the result in
|
||||||
|
.Fa a .
|
||||||
|
Both arguments must be initialized with the same fractional radix point.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn Q_NORMPREC
|
||||||
|
function attempts to normalise the precision of
|
||||||
|
.Fa a
|
||||||
|
and
|
||||||
|
.Fa b
|
||||||
|
if they differ.
|
||||||
|
The greater of the two precisions is preferred if possible, unless that would
|
||||||
|
truncate integer component data for the other operand, in which case the highest
|
||||||
|
precision that preserves the integer component of both
|
||||||
|
.Fa a
|
||||||
|
and
|
||||||
|
.Fa b
|
||||||
|
is selected.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn Q_QMAXQ
|
||||||
|
and
|
||||||
|
.Fn Q_QMINQ
|
||||||
|
functions return the larger or smaller of
|
||||||
|
.Fa a
|
||||||
|
and
|
||||||
|
.Fa b
|
||||||
|
respectively.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn Q_QCLONEQ
|
||||||
|
and
|
||||||
|
.Fn Q_QCPYVALQ
|
||||||
|
functions attempt to store identical or representational copies of
|
||||||
|
.Fa r ,
|
||||||
|
in
|
||||||
|
.Fa l
|
||||||
|
respectively.
|
||||||
|
An identical Q number produced by cloning copies the control bits as well as the
|
||||||
|
verbatim integer/fractional bits.
|
||||||
|
A representational copy only copies the values of
|
||||||
|
.Fa r Ap s
|
||||||
|
integer and fractional bits, representing them in the bits available per
|
||||||
|
.Fa l Ap s
|
||||||
|
Q format.
|
||||||
|
.Pp
|
||||||
|
All of those functions operate on the following data types:
|
||||||
|
.Vt s8q_t ,
|
||||||
|
.Vt u8q_t ,
|
||||||
|
.Vt s16q_t ,
|
||||||
|
.Vt u16q_t ,
|
||||||
|
.Vt s32q_t ,
|
||||||
|
.Vt u32q_t ,
|
||||||
|
.Vt s64q_t ,
|
||||||
|
and
|
||||||
|
.Vt u64q_t ,
|
||||||
|
which are referred to generically as
|
||||||
|
.Fa QTYPE .
|
||||||
|
.Pp
|
||||||
|
For more details, see
|
||||||
|
.Xr qmath 3 .
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
The
|
||||||
|
.Fn Q_QADDQ ,
|
||||||
|
.Fn Q_QDIVQ ,
|
||||||
|
.Fn Q_QMULQ ,
|
||||||
|
.Fn Q_QSUBQ
|
||||||
|
.Fn Q_NORMPREC ,
|
||||||
|
.Fn Q_QCLONEQ
|
||||||
|
and
|
||||||
|
.Fn Q_QCPYVALQ
|
||||||
|
functions return 0 on success, or an errno on failure.
|
||||||
|
.Er EINVAL
|
||||||
|
is returned for divide-by-zero.
|
||||||
|
.Er EOVERFLOW
|
||||||
|
and
|
||||||
|
.Er ERANGE
|
||||||
|
are returned for overflow and underflow respectively.
|
||||||
|
.Er ERANGE is also returned when the precision of arguments
|
||||||
|
does not match.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn Q_QMAXQ
|
||||||
|
and
|
||||||
|
.Fn Q_QMINQ
|
||||||
|
functions return the numerically larger or smaller of their two inputs
|
||||||
|
respectively.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr errno 2 ,
|
||||||
|
.Xr qmath 3 ,
|
||||||
|
.Xr stdint 7
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Xr qmath 3
|
||||||
|
functions first appeared in
|
||||||
|
.Fx 13.0 .
|
||||||
|
.Sh AUTHORS
|
||||||
|
.An -nosplit
|
||||||
|
The
|
||||||
|
.Xr qmath 3
|
||||||
|
functions and this manual page were written by
|
||||||
|
.An Lawrence Stewart Aq Mt lstewart@FreeBSD.org
|
||||||
|
and sponsored by Netflix, Inc.
|
210
share/man/man3/Q_SIGNED.3
Normal file
210
share/man/man3/Q_SIGNED.3
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2018 Netflix, Inc.
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions, and the following disclaimer,
|
||||||
|
.\" without modification, immediately at the beginning of the file.
|
||||||
|
.\" 2. The name of the author may not be used to endorse or promote products
|
||||||
|
.\" derived from this software without specific prior written permission.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
.\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
.\" SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.\" $FreeBSD$
|
||||||
|
.\"
|
||||||
|
.Dd July 8, 2018
|
||||||
|
.Dt Q_SIGNED 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm Q_SIGNED ,
|
||||||
|
.Nm Q_LTZ ,
|
||||||
|
.Nm Q_PRECEQ ,
|
||||||
|
.Nm Q_QLTQ ,
|
||||||
|
.Nm Q_QLEQ ,
|
||||||
|
.Nm Q_QGTQ ,
|
||||||
|
.Nm Q_QGEQ ,
|
||||||
|
.Nm Q_QEQ ,
|
||||||
|
.Nm Q_QNEQ ,
|
||||||
|
.Nm Q_OFLOW ,
|
||||||
|
.Nm Q_RELPREC
|
||||||
|
.Nd fixed-point math comparison and logic functions
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In sys/qmath.h
|
||||||
|
.Ft bool
|
||||||
|
.Fn Q_SIGNED "NTYPE n"
|
||||||
|
.Ft bool
|
||||||
|
.Fn Q_LTZ "NTYPE n"
|
||||||
|
.Ft bool
|
||||||
|
.Fn Q_PRECEQ "QTYPE a" "QTYPE b"
|
||||||
|
.Ft bool
|
||||||
|
.Fn Q_QLTQ "QTYPE a" "QTYPE b"
|
||||||
|
.Ft bool
|
||||||
|
.Fn Q_QLEQ "QTYPE a" "QTYPE b"
|
||||||
|
.Ft bool
|
||||||
|
.Fn Q_QGTQ "QTYPE a" "QTYPE b"
|
||||||
|
.Ft bool
|
||||||
|
.Fn Q_QGEQ "QTYPE a" "QTYPE b"
|
||||||
|
.Ft bool
|
||||||
|
.Fn Q_QEQ "QTYPE a" "QTYPE b"
|
||||||
|
.Ft bool
|
||||||
|
.Fn Q_QNEQ "QTYPE a" "QTYPE b"
|
||||||
|
.Ft bool
|
||||||
|
.Fn Q_OFLOW "QTYPE q" "ITYPE iv"
|
||||||
|
.Ft int
|
||||||
|
.Fn Q_RELPREC "QTYPE a" "QTYPE b"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Fn Q_SIGNED
|
||||||
|
returns
|
||||||
|
.Ft true
|
||||||
|
if the numeric data type passed in as
|
||||||
|
.Fa n
|
||||||
|
is signed, or
|
||||||
|
.Ft false
|
||||||
|
otherwise.
|
||||||
|
.Pp
|
||||||
|
.Fn Q_LTZ
|
||||||
|
returns
|
||||||
|
.Ft true
|
||||||
|
if the numeric value
|
||||||
|
passed in as
|
||||||
|
.Fa n
|
||||||
|
is negative
|
||||||
|
.Pq requires types which use the MSB as the sign bit ,
|
||||||
|
or
|
||||||
|
.Ft false
|
||||||
|
otherwise.
|
||||||
|
.Pp
|
||||||
|
.Fn Q_PRECEQ
|
||||||
|
returns
|
||||||
|
.Ft true
|
||||||
|
if the number of
|
||||||
|
.Fa a
|
||||||
|
and
|
||||||
|
.Fa b
|
||||||
|
fractional bits is the same,
|
||||||
|
.Ft false
|
||||||
|
otherwise.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn Q_QLTQ ,
|
||||||
|
.Fn Q_QLEQ ,
|
||||||
|
.Fn Q_QGTQ ,
|
||||||
|
.Fn Q_QGEQ ,
|
||||||
|
.Fn Q_QEQ
|
||||||
|
and
|
||||||
|
.Fn Q_QNEQ
|
||||||
|
functions compare two Q numbers, returning
|
||||||
|
.Ft true
|
||||||
|
if
|
||||||
|
.Fa a
|
||||||
|
is less than, less than or equal to, greater than, greater than or equal to,
|
||||||
|
equal to, or not equal to
|
||||||
|
.Fa b
|
||||||
|
respectively, or
|
||||||
|
.Ft false
|
||||||
|
otherwise.
|
||||||
|
The integral and fractional values are used to perform the comparison, without
|
||||||
|
explicit concern for the underlying number of integer versus fractional bits.
|
||||||
|
.Pp
|
||||||
|
.Fn Q_OFLOW
|
||||||
|
returns
|
||||||
|
.Ft true
|
||||||
|
if integer value
|
||||||
|
.Fa iv
|
||||||
|
cannot be stored in
|
||||||
|
.Fa q
|
||||||
|
without truncation, or false otherwise.
|
||||||
|
.Pp
|
||||||
|
.Fn Q_RELPREC
|
||||||
|
returns the relative precision of
|
||||||
|
.Fa a
|
||||||
|
versus
|
||||||
|
.Fa b .
|
||||||
|
In terms of
|
||||||
|
.Em Qm.n
|
||||||
|
notation, this function returns the difference between the
|
||||||
|
.Em n
|
||||||
|
values of
|
||||||
|
.Fa a
|
||||||
|
and
|
||||||
|
.Fa b .
|
||||||
|
For example, a return value of +4 means that
|
||||||
|
.Fa a
|
||||||
|
has an additional 4 bits of fractional precision compared to
|
||||||
|
.Fa b .
|
||||||
|
.Pp
|
||||||
|
All of those functions operate on
|
||||||
|
the following data types:
|
||||||
|
.Vt s8q_t ,
|
||||||
|
.Vt u8q_t ,
|
||||||
|
.Vt s16q_t ,
|
||||||
|
.Vt u16q_t ,
|
||||||
|
.Vt s32q_t ,
|
||||||
|
.Vt u32q_t ,
|
||||||
|
.Vt s64q_t ,
|
||||||
|
and
|
||||||
|
.Vt u64q_t ,
|
||||||
|
which are referred to generically as
|
||||||
|
.Fa QTYPE .
|
||||||
|
The
|
||||||
|
.Fa ITYPE
|
||||||
|
refers to the
|
||||||
|
.Xr stdint 7
|
||||||
|
integer types.
|
||||||
|
.Fa NTYPE
|
||||||
|
is used to refer to any numeric type and is therefore a superset of
|
||||||
|
.Fa QTYPE
|
||||||
|
and
|
||||||
|
.Fa ITYPE .
|
||||||
|
.Pp
|
||||||
|
For more details, see
|
||||||
|
.Xr qmath 3 .
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
The
|
||||||
|
.Fn Q_SIGNED ,
|
||||||
|
.Fn Q_LTZ ,
|
||||||
|
.Fn Q_PRECEQ ,
|
||||||
|
.Fn Q_QLTQ ,
|
||||||
|
.Fn Q_QLEQ ,
|
||||||
|
.Fn Q_QGTQ ,
|
||||||
|
.Fn Q_QGEQ ,
|
||||||
|
.Fn Q_QEQ ,
|
||||||
|
.Fn Q_QNEQ
|
||||||
|
and
|
||||||
|
.Fn Q_OFLOW
|
||||||
|
functions return expressions that evaluate to boolean
|
||||||
|
.Vt true
|
||||||
|
or
|
||||||
|
.Vt false .
|
||||||
|
.Pp
|
||||||
|
.Fn Q_RELPREC
|
||||||
|
returns the relative precision difference as a signed integer.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr errno 2 ,
|
||||||
|
.Xr qmath 3 ,
|
||||||
|
.Xr stdint 7
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Xr qmath 3
|
||||||
|
functions first appeared in
|
||||||
|
.Fx 13.0 .
|
||||||
|
.Sh AUTHORS
|
||||||
|
.An -nosplit
|
||||||
|
The
|
||||||
|
.Xr qmath 3
|
||||||
|
functions and this manual page were written by
|
||||||
|
.An Lawrence Stewart Aq Mt lstewart@FreeBSD.org
|
||||||
|
and sponsored by Netflix, Inc.
|
147
share/man/man3/Q_SIGNSHFT.3
Normal file
147
share/man/man3/Q_SIGNSHFT.3
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2018 Netflix, Inc.
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions, and the following disclaimer,
|
||||||
|
.\" without modification, immediately at the beginning of the file.
|
||||||
|
.\" 2. The name of the author may not be used to endorse or promote products
|
||||||
|
.\" derived from this software without specific prior written permission.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
.\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
.\" SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.\" $FreeBSD$
|
||||||
|
.\"
|
||||||
|
.Dd July 8, 2018
|
||||||
|
.Dt Q_SIGNSHFT 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm Q_SIGNSHFT ,
|
||||||
|
.Nm Q_SSIGN ,
|
||||||
|
.Nm Q_CRAWMASK ,
|
||||||
|
.Nm Q_SRAWMASK ,
|
||||||
|
.Nm Q_GCRAW ,
|
||||||
|
.Nm Q_GCVAL ,
|
||||||
|
.Nm Q_SCVAL
|
||||||
|
.Nd fixed-point math functions which manipulate the control/sign data bits
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In sys/qmath.h
|
||||||
|
.Ft uint32_t
|
||||||
|
.Fn Q_SIGNSHFT "QTYPE q"
|
||||||
|
.Ft QTYPE
|
||||||
|
.Fn Q_SSIGN "QTYPE q" "bool isneg"
|
||||||
|
.Ft ITYPE
|
||||||
|
.Fn Q_CRAWMASK "QTYPE q"
|
||||||
|
.Ft ITYPE
|
||||||
|
.Fn Q_SRAWMASK "QTYPE q"
|
||||||
|
.Ft ITYPE
|
||||||
|
.Fn Q_GCRAW "QTYPE q"
|
||||||
|
.Ft ITYPE
|
||||||
|
.Fn Q_GCVAL "QTYPE q"
|
||||||
|
.Ft QTYPE
|
||||||
|
.Fn Q_SCVAL "QTYPE q" "ITYPE cv"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Fn Q_SIGNSHFT
|
||||||
|
gets the bit position of
|
||||||
|
.Fa q Ap s
|
||||||
|
sign bit relative to bit zero.
|
||||||
|
.Pp
|
||||||
|
.Fn Q_SSIGN
|
||||||
|
sets the sign bit of
|
||||||
|
.Fa q
|
||||||
|
based on the boolean
|
||||||
|
.Fa isneg .
|
||||||
|
.Pp
|
||||||
|
.Fn Q_CRAWMASK
|
||||||
|
and
|
||||||
|
.Fn Q_SRAWMASK
|
||||||
|
return
|
||||||
|
.Fa q Ns -specific
|
||||||
|
bit masks for
|
||||||
|
.Fa q Ap s
|
||||||
|
control bits and sign bit respectively.
|
||||||
|
.Pp
|
||||||
|
.Fn Q_GCRAW
|
||||||
|
and
|
||||||
|
.Fn Q_GCVAL
|
||||||
|
get the raw masked control bits and value of
|
||||||
|
.Fa q Ap s
|
||||||
|
control bits respectively.
|
||||||
|
.Pp
|
||||||
|
.Fn Q_SCVAL
|
||||||
|
sets
|
||||||
|
.Fa q Ap s
|
||||||
|
control bits to the value
|
||||||
|
.Fa cv .
|
||||||
|
.Pp
|
||||||
|
All of those functions operate on
|
||||||
|
the following data types:
|
||||||
|
.Vt s8q_t ,
|
||||||
|
.Vt u8q_t ,
|
||||||
|
.Vt s16q_t ,
|
||||||
|
.Vt u16q_t ,
|
||||||
|
.Vt s32q_t ,
|
||||||
|
.Vt u32q_t ,
|
||||||
|
.Vt s64q_t ,
|
||||||
|
and
|
||||||
|
.Vt u64q_t ,
|
||||||
|
which are referred to generically as
|
||||||
|
.Fa QTYPE .
|
||||||
|
The
|
||||||
|
.Fa ITYPE
|
||||||
|
refers to the
|
||||||
|
.Xr stdint 7
|
||||||
|
integer types.
|
||||||
|
.Pp
|
||||||
|
For more details, see
|
||||||
|
.Xr qmath 3 .
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
.Fn Q_SIGNSHFT
|
||||||
|
returns the sign bit's position as an integer.
|
||||||
|
.Pp
|
||||||
|
.Fn Q_SSIGN
|
||||||
|
returns the value of
|
||||||
|
.Fa q
|
||||||
|
post change.
|
||||||
|
.Pp
|
||||||
|
.Fn Q_CRAWMASK ,
|
||||||
|
.Fn Q_SRAWMASK ,
|
||||||
|
.Fn Q_GCRAW
|
||||||
|
and
|
||||||
|
.Fn Q_GCVAL
|
||||||
|
return their respective values as integers of the same underlying ITYPE as
|
||||||
|
.Fa q .
|
||||||
|
.Pp
|
||||||
|
.Fn Q_SCVAL
|
||||||
|
returns the value of
|
||||||
|
.Fa q
|
||||||
|
post change.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr errno 2 ,
|
||||||
|
.Xr qmath 3 ,
|
||||||
|
.Xr stdint 7
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Xr qmath 3
|
||||||
|
functions first appeared in
|
||||||
|
.Fx 13.0 .
|
||||||
|
.Sh AUTHORS
|
||||||
|
.An -nosplit
|
||||||
|
The
|
||||||
|
.Xr qmath 3
|
||||||
|
functions and this manual page were written by
|
||||||
|
.An Lawrence Stewart Aq Mt lstewart@FreeBSD.org
|
||||||
|
and sponsored by Netflix, Inc.
|
389
share/man/man3/qmath.3
Normal file
389
share/man/man3/qmath.3
Normal file
@ -0,0 +1,389 @@
|
|||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2018 Netflix, Inc.
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions, and the following disclaimer,
|
||||||
|
.\" without modification, immediately at the beginning of the file.
|
||||||
|
.\" 2. The name of the author may not be used to endorse or promote products
|
||||||
|
.\" derived from this software without specific prior written permission.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
.\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
.\" SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.\" $FreeBSD$
|
||||||
|
.\"
|
||||||
|
.Dd July 4, 2019
|
||||||
|
.Dt QMATH 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm qmath
|
||||||
|
.Nd fixed-point math library based on the
|
||||||
|
.Dq Q
|
||||||
|
number format
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In sys/qmath.h
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Nm
|
||||||
|
data types and APIs support fixed-point math based on the
|
||||||
|
.Dq Q
|
||||||
|
number format.
|
||||||
|
The APIs have been built around the following data types:
|
||||||
|
.Vt s8q_t ,
|
||||||
|
.Vt u8q_t ,
|
||||||
|
.Vt s16q_t ,
|
||||||
|
.Vt u16q_t ,
|
||||||
|
.Vt s32q_t ,
|
||||||
|
.Vt u32q_t ,
|
||||||
|
.Vt s64q_t ,
|
||||||
|
and
|
||||||
|
.Vt u64q_t ,
|
||||||
|
which are referred to generically in the earlier API definitions as
|
||||||
|
.Fa QTYPE .
|
||||||
|
The
|
||||||
|
.Fa ITYPE
|
||||||
|
refers to the
|
||||||
|
.Xr stdint 7
|
||||||
|
integer types.
|
||||||
|
.Fa NTYPE
|
||||||
|
is used to refer to any numeric type and is therefore a superset of
|
||||||
|
.Fa QTYPE
|
||||||
|
and
|
||||||
|
.Fa ITYPE .
|
||||||
|
.Pp
|
||||||
|
This scheme can represent Q numbers with
|
||||||
|
.Bq 2, 4, 6, 8, 16, 32, 48
|
||||||
|
bits of precision after the binary radix point,
|
||||||
|
depending on the
|
||||||
|
.Fa rpshft
|
||||||
|
argument to
|
||||||
|
.Fn Q_INI .
|
||||||
|
The number of bits available for the integral component is not explicitly
|
||||||
|
specified, and implicitly consumes the remaining available bits of the chosen Q
|
||||||
|
data type.
|
||||||
|
.Pp
|
||||||
|
Operations on Q numbers maintain the precision of their arguments.
|
||||||
|
The fractional component is truncated to fit into the destination,
|
||||||
|
with no rounding.
|
||||||
|
None of the operations is affected by the floating-point environment.
|
||||||
|
.Pp
|
||||||
|
For more details, see the
|
||||||
|
.Sx IMPLEMENTATION DETAILS
|
||||||
|
below.
|
||||||
|
.Sh LIST OF FUNCTIONS
|
||||||
|
.de Cl
|
||||||
|
.Bl -column "isgreaterequal" "bessel function of the second kind of the order 0"
|
||||||
|
.Em "Name Description"
|
||||||
|
..
|
||||||
|
.Ss Functions which create/initialise a Q number
|
||||||
|
.Cl
|
||||||
|
.Xr Q_INI 3 initialise a Q number
|
||||||
|
.El
|
||||||
|
.Ss Numeric functions which operate on two Q numbers
|
||||||
|
.Cl
|
||||||
|
.Xr Q_QADDQ 3 addition
|
||||||
|
.Xr Q_QDIVQ 3 division
|
||||||
|
.Xr Q_QMULQ 3 multiplication
|
||||||
|
.Xr Q_QSUBQ 3 subtraction
|
||||||
|
.Xr Q_NORMPREC 3 normalisation
|
||||||
|
.Xr Q_QMAXQ 3 maximum function
|
||||||
|
.Xr Q_QMINQ 3 minimum function
|
||||||
|
.Xr Q_QCLONEQ 3 identical copy
|
||||||
|
.Xr Q_QCPYVALQ 3 representational copy
|
||||||
|
.El
|
||||||
|
.Ss Numeric functions which apply integers to a Q number
|
||||||
|
.Cl
|
||||||
|
.Xr Q_QADDI 3 addition
|
||||||
|
.Xr Q_QDIVI 3 division
|
||||||
|
.Xr Q_QMULI 3 multiplication
|
||||||
|
.Xr Q_QSUBI 3 subtraction
|
||||||
|
.Xr Q_QFRACI 3 fraction
|
||||||
|
.Xr Q_QCPYVALI 3 overwrite
|
||||||
|
.El
|
||||||
|
.Ss Numeric functions which operate on a single Q number
|
||||||
|
.Cl
|
||||||
|
.Xr Q_QABS 3 absolute value
|
||||||
|
.Xr Q_Q2D 3 double representation
|
||||||
|
.Xr Q_Q2F 3 float representation
|
||||||
|
.El
|
||||||
|
.Ss Comparison and logic functions
|
||||||
|
.Cl
|
||||||
|
.Xr Q_SIGNED 3 determine sign
|
||||||
|
.Xr Q_LTZ 3 less than zero
|
||||||
|
.Xr Q_PRECEQ 3 compare bits
|
||||||
|
.Xr Q_QLTQ 3 less than
|
||||||
|
.Xr Q_QLEQ 3 less or equal
|
||||||
|
.Xr Q_QGTQ 3 greater than
|
||||||
|
.Xr Q_QGEQ 3 greater or equal
|
||||||
|
.Xr Q_QEQ 3 equal
|
||||||
|
.Xr Q_QNEQ 3 not equal
|
||||||
|
.Xr Q_OFLOW 3 would overflow
|
||||||
|
.Xr Q_RELPREC 3 relative precision
|
||||||
|
.El
|
||||||
|
.Ss Functions which manipulate the control/sign data bits
|
||||||
|
.Cl
|
||||||
|
.Xr Q_SIGNSHFT 3 sign bit position
|
||||||
|
.Xr Q_SSIGN 3 sign bit
|
||||||
|
.Xr Q_CRAWMASK 3 control bitmask
|
||||||
|
.Xr Q_SRAWMASK 3 sign bitmask
|
||||||
|
.Xr Q_GCRAW 3 raw control bits
|
||||||
|
.Xr Q_GCVAL 3 value of control bits
|
||||||
|
.Xr Q_SCVAL 3 set control bits
|
||||||
|
.El
|
||||||
|
.Ss Functions which manipulate the combined integer/fractional data bits
|
||||||
|
.Cl
|
||||||
|
.Xr Q_IFRAWMASK 3 integer/fractional bitmask
|
||||||
|
.Xr Q_IFVALIMASK 3 value of integer bits
|
||||||
|
.Xr Q_IFVALFMASK 3 value of fractional bits
|
||||||
|
.Xr Q_GIFRAW 3 raw integer/fractional bits
|
||||||
|
.Xr Q_GIFABSVAL 3 absolute value of fractional bits
|
||||||
|
.Xr Q_GIFVAL 3 real value of fractional bits
|
||||||
|
.Xr Q_SIFVAL 3 set integer/fractional bits
|
||||||
|
.Xr Q_SIFVALS 3 set separate integer/fractional values
|
||||||
|
.El
|
||||||
|
.Ss Functions which manipulate the integer data bits
|
||||||
|
.Cl
|
||||||
|
.Xr Q_IRAWMASK 3 integer bitmask
|
||||||
|
.Xr Q_GIRAW 3 raw integer bits
|
||||||
|
.Xr Q_GIABSVAL 3 absolute value of integer bits
|
||||||
|
.Xr Q_GIVAL 3 real value of integer bits
|
||||||
|
.Xr Q_SIVAL 3 set integer bits
|
||||||
|
.El
|
||||||
|
.Ss Functions which manipulate the fractional data bits
|
||||||
|
.Cl
|
||||||
|
.Xr Q_FRAWMASK 3 fractional bitmask
|
||||||
|
.Xr Q_GFRAW 3 raw fractional bits
|
||||||
|
.Xr Q_GFABSVAL 3 absolute value of fractional bits
|
||||||
|
.Xr Q_GFVAL 3 real value of fractional bits
|
||||||
|
.Xr Q_SFVAL 3 set fractional bits
|
||||||
|
.El
|
||||||
|
.Ss Miscellaneous functions/variables
|
||||||
|
.Cl
|
||||||
|
.Xr Q_NCBITS 3 number of reserved control bits
|
||||||
|
.Xr Q_BT 3 C data type
|
||||||
|
.Xr Q_TC 3 casted data type
|
||||||
|
.Xr Q_NTBITS 3 number of total bits
|
||||||
|
.Xr Q_NFCBITS 3 number of control-encoded fractional bits
|
||||||
|
.Xr Q_MAXNFBITS 3 number of maximum fractional bits
|
||||||
|
.Xr Q_NFBITS 3 number of effective fractional bits
|
||||||
|
.Xr Q_NIBITS 3 number of integer bits
|
||||||
|
.Xr Q_RPSHFT 3 bit position of radix point
|
||||||
|
.Xr Q_ABS 3 absolute value
|
||||||
|
.Xr Q_MAXSTRLEN 3 number of characters to render string
|
||||||
|
.Xr Q_TOSTR 3 render string
|
||||||
|
.Xr Q_SHL 3 left-shifted value
|
||||||
|
.Xr Q_SHR 3 right-shifted value
|
||||||
|
.Xr Q_DEBUG 3 render debugging information
|
||||||
|
.Xr Q_DFV2BFV 3 convert decimal fractional value
|
||||||
|
.El
|
||||||
|
.Sh IMPLEMENTATION DETAILS
|
||||||
|
The
|
||||||
|
.Nm
|
||||||
|
data types and APIs support fixed-point math based on the
|
||||||
|
.Dq Q
|
||||||
|
number format.
|
||||||
|
This implementation uses the Q notation
|
||||||
|
.Em Qm.n ,
|
||||||
|
where
|
||||||
|
.Em m
|
||||||
|
specifies the number of bits for integral data
|
||||||
|
.Pq excluding the sign bit for signed types ,
|
||||||
|
and
|
||||||
|
.Em n
|
||||||
|
specifies the number of bits for fractional data.
|
||||||
|
.Pp
|
||||||
|
The APIs have been built around the following q_t derived data types:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
typedef int8_t s8q_t;
|
||||||
|
typedef uint8_t u8q_t;
|
||||||
|
typedef int16_t s16q_t;
|
||||||
|
typedef uint16_t u16q_t;
|
||||||
|
typedef int32_t s32q_t;
|
||||||
|
typedef uint32_t u32q_t;
|
||||||
|
typedef int64_t s64q_t;
|
||||||
|
typedef uint64_t u64q_t;
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
These types are referred to generically in the earlier API definitions as
|
||||||
|
.Fa QTYPE ,
|
||||||
|
while
|
||||||
|
.Fa ITYPE
|
||||||
|
refers to the
|
||||||
|
.Xr stdint 7
|
||||||
|
integer types the Q data types are derived from.
|
||||||
|
.Fa NTYPE
|
||||||
|
is used to refer to any numeric type and is therefore a superset of
|
||||||
|
.Fa QTYPE
|
||||||
|
and
|
||||||
|
.Fa ITYPE .
|
||||||
|
.Pp
|
||||||
|
The 3 least significant bits
|
||||||
|
.Pq LSBs
|
||||||
|
of all q_t data types are reserved for embedded control data:
|
||||||
|
.Bl -dash
|
||||||
|
.It
|
||||||
|
bits 1-2 specify the binary radix point shift index operand, with 00,01,10,11 ==
|
||||||
|
1,2,3,4.
|
||||||
|
.It
|
||||||
|
bit 3 specifies the radix point shift index operand multiplier as 2
|
||||||
|
.Pq 0
|
||||||
|
or 16
|
||||||
|
.Pq 1 .
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
This scheme can therefore represent Q numbers with
|
||||||
|
.Bq 2,4,6,8,16,32,48,64
|
||||||
|
bits of precision after the binary radix point.
|
||||||
|
The number of bits available for the integral component is not explicitly
|
||||||
|
specified, and implicitly consumes the remaining available bits of the chosen Q
|
||||||
|
data type.
|
||||||
|
.Pp
|
||||||
|
Additionally, the most significant bit
|
||||||
|
.Pq MSB
|
||||||
|
of signed Q types stores the sign bit, with bit value 0 representing a positive
|
||||||
|
number and bit value 1 representing a negative number.
|
||||||
|
Negative numbers are stored as absolute values with the sign bit set, rather
|
||||||
|
than the more typical two's complement representation.
|
||||||
|
This avoids having to bit shift negative numbers, which can result in undefined
|
||||||
|
behaviour from some compilers.
|
||||||
|
.Pp
|
||||||
|
This binary representation used for Q numbers therefore comprises a set of
|
||||||
|
distinct data bit types and associated bit counts.
|
||||||
|
Data bit types/labels, listed in LSB to MSB order, are: control
|
||||||
|
.Sq C ,
|
||||||
|
fractional
|
||||||
|
.Sq F ,
|
||||||
|
integer
|
||||||
|
.Sq I
|
||||||
|
and sign
|
||||||
|
.Sq S .
|
||||||
|
The following example illustrates the binary representation of a Q20.8 number
|
||||||
|
represented using a s32q_t variable:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
M L
|
||||||
|
S S
|
||||||
|
B B
|
||||||
|
|
||||||
|
3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
|
||||||
|
1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||||||
|
|
||||||
|
S I I I I I I I I I I I I I I I I I I I I F F F F F F F F C C C
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
Important bit counts are: total, control, control-encoded fractional, maximum
|
||||||
|
fractional, effective fractional and integer bits.
|
||||||
|
.Pp
|
||||||
|
The count of total bits is derived from the size of the q_t data type.
|
||||||
|
For example, a s32q_t has 32 total bits.
|
||||||
|
.Pp
|
||||||
|
The count of control-encoded fractional bits is derived from calculating the
|
||||||
|
number of fractional bits per the control bit encoding scheme.
|
||||||
|
For example, the control bits binary value of 101 encodes a fractional bit
|
||||||
|
count of 2 x 16 = 32 fractional bits.
|
||||||
|
.Pp
|
||||||
|
The count of maximum fractional bits is derived from the difference between the
|
||||||
|
counts of total bits and control/sign bits.
|
||||||
|
For example, a s32q_t has a maximum of 32 - 3 - 1 = 28 fractional bits.
|
||||||
|
.Pp
|
||||||
|
The count of effective fractional bits is derived from the minimum of the
|
||||||
|
control-encoded fractional bits and the maximum fractional bits.
|
||||||
|
For example, a s32q_t with 32 control-encoded fractional bits is effectively
|
||||||
|
limited to 28 fractional bits.
|
||||||
|
.Pp
|
||||||
|
The count of integer bits is derived from the difference between the counts of
|
||||||
|
total bits and all other non-integer data bits
|
||||||
|
.Pq the sum of control, fractional and sign bits.
|
||||||
|
For example, a s32q_t with 8 effective fractional bits has 32 - 3 - 8 - 1 = 20 integer
|
||||||
|
bits.
|
||||||
|
The count of integer bits can be zero if all available numeric data bits have
|
||||||
|
been reserved for fractional data, e.g., when the number of control-encoded
|
||||||
|
fractional bits is greater than or equal to the underlying Q data type's maximum
|
||||||
|
fractional bits.
|
||||||
|
.Sh EXAMPLES
|
||||||
|
.Ss Calculating area of a circle with r=4.2 and rpshft=16
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
u64q_t a, pi, r;
|
||||||
|
char buf[32]
|
||||||
|
|
||||||
|
Q_INI(&a, 0, 0, 16);
|
||||||
|
Q_INI(&pi, 3, 14159, 16);
|
||||||
|
Q_INI(&r, 4, 2, 16);
|
||||||
|
|
||||||
|
Q_QCLONEQ(&a, r);
|
||||||
|
Q_QMULQ(&a, r);
|
||||||
|
Q_QMULQ(&a, pi);
|
||||||
|
|
||||||
|
Q_TOSTR(a, -1, 10, buf, sizeof(buf));
|
||||||
|
printf("%s\\n", buf);
|
||||||
|
.Ed
|
||||||
|
.Ss Debugging
|
||||||
|
Declare a Q20.8 s32q_t number
|
||||||
|
.Fa s32 ,
|
||||||
|
initialise it with the fixed-point value for 5/3, and render a debugging
|
||||||
|
representation of the variable
|
||||||
|
.Pq including its full precision decimal C-string representation ,
|
||||||
|
to the console:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
s32q_t s32;
|
||||||
|
Q_INI(&s32, 0, 0, 8);
|
||||||
|
Q_QFRACI(&s32, 5, 3);
|
||||||
|
char buf[Q_MAXSTRLEN(s32, 10)];
|
||||||
|
Q_TOSTR(s32, -1, 10, buf, sizeof(buf));
|
||||||
|
printf(Q_DEBUG(s32, "", "\\n\\ttostr=%s\\n\\n", 0), buf);
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
The above code outputs the following to the console:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
"s32"@0x7fffffffe7d4
|
||||||
|
type=s32q_t, Qm.n=Q20.8, rpshft=11, imin=0xfff00001, \\
|
||||||
|
imax=0xfffff
|
||||||
|
qraw=0x00000d53
|
||||||
|
imask=0x7ffff800, fmask=0x000007f8, cmask=0x00000007, \\
|
||||||
|
ifmask=0x7ffffff8
|
||||||
|
iraw=0x00000800, iabsval=0x1, ival=0x1
|
||||||
|
fraw=0x00000550, fabsval=0xaa, fval=0xaa
|
||||||
|
tostr=1.664
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
Note: The
|
||||||
|
.Qq \e
|
||||||
|
present in the rendered output above indicates a manual line break inserted to
|
||||||
|
keep the man page within 80 columns and is not part of the actual output.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr errno 2 ,
|
||||||
|
.Xr math 3 ,
|
||||||
|
.Xr Q_FRAWMASK 3 ,
|
||||||
|
.Xr Q_IFRAWMASK 3 ,
|
||||||
|
.Xr Q_INI 3 ,
|
||||||
|
.Xr Q_IRAWMASK 3 ,
|
||||||
|
.Xr Q_QABS 3 ,
|
||||||
|
.Xr Q_QADDI 3 ,
|
||||||
|
.Xr Q_QADDQ 3 ,
|
||||||
|
.Xr Q_SIGNED 3 ,
|
||||||
|
.Xr Q_SIGNSHFT 3 ,
|
||||||
|
.Xr stdint 7
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Nm
|
||||||
|
functions first appeared in
|
||||||
|
.Fx 13.0 .
|
||||||
|
.Sh AUTHORS
|
||||||
|
.An -nosplit
|
||||||
|
The
|
||||||
|
.Nm
|
||||||
|
functions and this manual page were written by
|
||||||
|
.An Lawrence Stewart Aq Mt lstewart@FreeBSD.org
|
||||||
|
and sponsored by Netflix, Inc.
|
632
sys/sys/qmath.h
Normal file
632
sys/sys/qmath.h
Normal file
@ -0,0 +1,632 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2018 Netflix, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* $FreeBSD$
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Data types and APIs for fixed-point math based on the "Q" number format.
|
||||||
|
*
|
||||||
|
* Author: Lawrence Stewart <lstewart@netflix.com>
|
||||||
|
*
|
||||||
|
* The 3 LSBs of all base data types are reserved for embedded control data:
|
||||||
|
* bits 1-2 specify the radix point shift index i.e. 00,01,10,11 == 1,2,3,4
|
||||||
|
* bit 3 specifies the radix point shift index multiplier as 2 (0) or 16 (1)
|
||||||
|
*
|
||||||
|
* This scheme can therefore represent Q numbers with [2,4,6,8,16,32,48,64] bits
|
||||||
|
* of precision after the binary radix point. The number of bits available for
|
||||||
|
* the integral component depends on the underlying storage type chosen.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SYS_QMATH_H_
|
||||||
|
#define _SYS_QMATH_H_
|
||||||
|
|
||||||
|
#include <machine/_stdint.h>
|
||||||
|
|
||||||
|
typedef int8_t s8q_t;
|
||||||
|
typedef uint8_t u8q_t;
|
||||||
|
typedef int16_t s16q_t;
|
||||||
|
typedef uint16_t u16q_t;
|
||||||
|
typedef int32_t s32q_t;
|
||||||
|
typedef uint32_t u32q_t;
|
||||||
|
typedef int64_t s64q_t;
|
||||||
|
typedef uint64_t u64q_t;
|
||||||
|
/* typedef int128_t s128q_t; Not yet */
|
||||||
|
/* typedef uint128_t u128q_t; Not yet */
|
||||||
|
typedef s64q_t smaxq_t;
|
||||||
|
typedef u64q_t umaxq_t;
|
||||||
|
|
||||||
|
/* The underlying base type of 'q'. */
|
||||||
|
#define Q_BT(q) __typeof(q)
|
||||||
|
|
||||||
|
/* Type-cast variable 'v' to the same underlying type as 'q'. */
|
||||||
|
#define Q_TC(q, v) ((Q_BT(q))(v))
|
||||||
|
|
||||||
|
/* Number of total bits associated with the data type underlying 'q'. */
|
||||||
|
#define Q_NTBITS(q) ((uint32_t)(sizeof(q) << 3))
|
||||||
|
|
||||||
|
/* Number of LSBs reserved for control data. */
|
||||||
|
#define Q_NCBITS ((uint32_t)3)
|
||||||
|
|
||||||
|
/* Number of control-encoded bits reserved for fractional component data. */
|
||||||
|
#define Q_NFCBITS(q) \
|
||||||
|
((uint32_t)(((Q_GCRAW(q) & 0x3) + 1) << ((Q_GCRAW(q) & 0x4) ? 4 : 1)))
|
||||||
|
|
||||||
|
/* Min/max number of bits that can be reserved for fractional component data. */
|
||||||
|
#define Q_MINNFBITS(q) ((uint32_t)(2))
|
||||||
|
#define Q_MAXNFBITS(q) ((uint32_t)(Q_NTBITS(q) - Q_SIGNED(q) - Q_NCBITS))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Number of bits actually reserved for fractional component data. This can be
|
||||||
|
* less than the value returned by Q_NFCBITS() as we treat any excess
|
||||||
|
* control-encoded number of bits for the underlying data type as meaning all
|
||||||
|
* available bits are reserved for fractional component data i.e. zero int bits.
|
||||||
|
*/
|
||||||
|
#define Q_NFBITS(q) \
|
||||||
|
(Q_NFCBITS(q) > Q_MAXNFBITS(q) ? Q_MAXNFBITS(q) : Q_NFCBITS(q))
|
||||||
|
|
||||||
|
/* Number of bits available for integer component data. */
|
||||||
|
#define Q_NIBITS(q) ((uint32_t)(Q_NTBITS(q) - Q_RPSHFT(q) - Q_SIGNED(q)))
|
||||||
|
|
||||||
|
/* The radix point offset relative to the LSB. */
|
||||||
|
#define Q_RPSHFT(q) (Q_NCBITS + Q_NFBITS(q))
|
||||||
|
|
||||||
|
/* The sign bit offset relative to the LSB. */
|
||||||
|
#define Q_SIGNSHFT(q) (Q_NTBITS(q) - 1)
|
||||||
|
|
||||||
|
/* Set the sign bit to 0 ('isneg' is F) or 1 ('isneg' is T). */
|
||||||
|
#define Q_SSIGN(q, isneg) \
|
||||||
|
((q) = ((Q_SIGNED(q) && (isneg)) ? (q) | (1ULL << Q_SIGNSHFT(q)) : \
|
||||||
|
(q) & ~(1ULL << Q_SIGNSHFT(q))))
|
||||||
|
|
||||||
|
/* Manipulate the 'q' bits holding control/sign data. */
|
||||||
|
#define Q_CRAWMASK(q) 0x7ULL
|
||||||
|
#define Q_SRAWMASK(q) (1ULL << Q_SIGNSHFT(q))
|
||||||
|
#define Q_GCRAW(q) ((q) & Q_CRAWMASK(q))
|
||||||
|
#define Q_GCVAL(q) Q_GCRAW(q)
|
||||||
|
#define Q_SCVAL(q, cv) ((q) = ((q) & ~Q_CRAWMASK(q)) | (cv))
|
||||||
|
|
||||||
|
/* Manipulate the 'q' bits holding combined integer/fractional data. */
|
||||||
|
#define Q_IFRAWMASK(q) \
|
||||||
|
Q_TC(q, Q_SIGNED(q) ? ~(Q_SRAWMASK(q) | Q_CRAWMASK(q)) : ~Q_CRAWMASK(q))
|
||||||
|
#define Q_IFMAXVAL(q) Q_TC(q, Q_IFRAWMASK(q) >> Q_NCBITS)
|
||||||
|
#define Q_IFMINVAL(q) Q_TC(q, Q_SIGNED(q) ? -Q_IFMAXVAL(q) : 0)
|
||||||
|
#define Q_IFVALIMASK(q) Q_TC(q, ~Q_IFVALFMASK(q))
|
||||||
|
#define Q_IFVALFMASK(q) Q_TC(q, (1ULL << Q_NFBITS(q)) - 1)
|
||||||
|
#define Q_GIFRAW(q) Q_TC(q, (q) & Q_IFRAWMASK(q))
|
||||||
|
#define Q_GIFABSVAL(q) Q_TC(q, Q_GIFRAW(q) >> Q_NCBITS)
|
||||||
|
#define Q_GIFVAL(q) Q_TC(q, Q_LTZ(q) ? -Q_GIFABSVAL(q) : Q_GIFABSVAL(q))
|
||||||
|
#define Q_SIFVAL(q, ifv) \
|
||||||
|
((q) = ((q) & (~(Q_SRAWMASK(q) | Q_IFRAWMASK(q)))) | \
|
||||||
|
(Q_TC(q, Q_ABS(ifv)) << Q_NCBITS) | \
|
||||||
|
(Q_LTZ(ifv) ? 1ULL << Q_SIGNSHFT(q) : 0))
|
||||||
|
#define Q_SIFVALS(q, iv, fv) \
|
||||||
|
((q) = ((q) & (~(Q_SRAWMASK(q) | Q_IFRAWMASK(q)))) | \
|
||||||
|
(Q_TC(q, Q_ABS(iv)) << Q_RPSHFT(q)) | \
|
||||||
|
(Q_TC(q, Q_ABS(fv)) << Q_NCBITS) | \
|
||||||
|
(Q_LTZ(iv) || Q_LTZ(fv) ? 1ULL << Q_SIGNSHFT(q) : 0))
|
||||||
|
|
||||||
|
/* Manipulate the 'q' bits holding integer data. */
|
||||||
|
#define Q_IRAWMASK(q) Q_TC(q, Q_IFRAWMASK(q) & ~Q_FRAWMASK(q))
|
||||||
|
#define Q_IMAXVAL(q) Q_TC(q, Q_IRAWMASK(q) >> Q_RPSHFT(q))
|
||||||
|
#define Q_IMINVAL(q) Q_TC(q, Q_SIGNED(q) ? -Q_IMAXVAL(q) : 0)
|
||||||
|
#define Q_GIRAW(q) Q_TC(q, (q) & Q_IRAWMASK(q))
|
||||||
|
#define Q_GIABSVAL(q) Q_TC(q, Q_GIRAW(q) >> Q_RPSHFT(q))
|
||||||
|
#define Q_GIVAL(q) Q_TC(q, Q_LTZ(q) ? -Q_GIABSVAL(q) : Q_GIABSVAL(q))
|
||||||
|
#define Q_SIVAL(q, iv) \
|
||||||
|
((q) = ((q) & ~(Q_SRAWMASK(q) | Q_IRAWMASK(q))) | \
|
||||||
|
(Q_TC(q, Q_ABS(iv)) << Q_RPSHFT(q)) | \
|
||||||
|
(Q_LTZ(iv) ? 1ULL << Q_SIGNSHFT(q) : 0))
|
||||||
|
|
||||||
|
/* Manipulate the 'q' bits holding fractional data. */
|
||||||
|
#define Q_FRAWMASK(q) Q_TC(q, ((1ULL << Q_NFBITS(q)) - 1) << Q_NCBITS)
|
||||||
|
#define Q_FMAXVAL(q) Q_TC(q, Q_FRAWMASK(q) >> Q_NCBITS)
|
||||||
|
#define Q_GFRAW(q) Q_TC(q, (q) & Q_FRAWMASK(q))
|
||||||
|
#define Q_GFABSVAL(q) Q_TC(q, Q_GFRAW(q) >> Q_NCBITS)
|
||||||
|
#define Q_GFVAL(q) Q_TC(q, Q_LTZ(q) ? -Q_GFABSVAL(q) : Q_GFABSVAL(q))
|
||||||
|
#define Q_SFVAL(q, fv) \
|
||||||
|
((q) = ((q) & ~(Q_SRAWMASK(q) | Q_FRAWMASK(q))) | \
|
||||||
|
(Q_TC(q, Q_ABS(fv)) << Q_NCBITS) | \
|
||||||
|
(Q_LTZ(fv) ? 1ULL << Q_SIGNSHFT(q) : 0))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate the number of bits required per 'base' digit, rounding up or down
|
||||||
|
* for non power-of-two bases.
|
||||||
|
*/
|
||||||
|
#define Q_BITSPERBASEDOWN(base) (flsll(base) - 1)
|
||||||
|
#define Q_BITSPERBASEUP(base) (flsll(base) - (__builtin_popcountll(base) == 1))
|
||||||
|
#define Q_BITSPERBASE(base, rnd) Q_BITSPERBASE##rnd(base)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Upper bound number of digits required to render 'nbits' worth of integer
|
||||||
|
* component bits with numeric base 'base'. Overestimates for power-of-two
|
||||||
|
* bases.
|
||||||
|
*/
|
||||||
|
#define Q_NIBITS2NCHARS(nbits, base) \
|
||||||
|
({ \
|
||||||
|
int _bitsperbase = Q_BITSPERBASE(base, DOWN); \
|
||||||
|
(((nbits) + _bitsperbase - 1) / _bitsperbase); \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define Q_NFBITS2NCHARS(nbits, base) (nbits)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Maximum number of chars required to render 'q' as a C-string of base 'base'.
|
||||||
|
* Includes space for sign, radix point and NUL-terminator.
|
||||||
|
*/
|
||||||
|
#define Q_MAXSTRLEN(q, base) \
|
||||||
|
(2 + Q_NIBITS2NCHARS(Q_NIBITS(q), base) + \
|
||||||
|
Q_NFBITS2NCHARS(Q_NFBITS(q), base) + Q_SIGNED(q))
|
||||||
|
|
||||||
|
/* Yield the next char from integer bits. */
|
||||||
|
#define Q_IBITS2CH(q, bits, base) \
|
||||||
|
({ \
|
||||||
|
__typeof(bits) _tmp = (bits) / (base); \
|
||||||
|
int _idx = (bits) - (_tmp * (base)); \
|
||||||
|
(bits) = _tmp; \
|
||||||
|
"0123456789abcdef"[_idx]; \
|
||||||
|
})
|
||||||
|
|
||||||
|
/* Yield the next char from fractional bits. */
|
||||||
|
#define Q_FBITS2CH(q, bits, base) \
|
||||||
|
({ \
|
||||||
|
int _carry = 0, _idx, _nfbits = Q_NFBITS(q), _shift = 0; \
|
||||||
|
/* \
|
||||||
|
* Normalise enough MSBs to yield the next digit, multiply by the \
|
||||||
|
* base, and truncate residual fractional bits post multiplication. \
|
||||||
|
*/ \
|
||||||
|
if (_nfbits > Q_BITSPERBASEUP(base)) { \
|
||||||
|
/* Break multiplication into two steps to ensure no overflow. */\
|
||||||
|
_shift = _nfbits >> 1; \
|
||||||
|
_carry = (((bits) & ((1ULL << _shift) - 1)) * (base)) >> _shift;\
|
||||||
|
} \
|
||||||
|
_idx = ((((bits) >> _shift) * (base)) + _carry) >> (_nfbits - _shift);\
|
||||||
|
(bits) *= (base); /* With _idx computed, no overflow concern. */ \
|
||||||
|
(bits) &= (1ULL << _nfbits) - 1; /* Exclude residual int bits. */ \
|
||||||
|
"0123456789abcdef"[_idx]; \
|
||||||
|
})
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Render the C-string representation of 'q' into 's'. Returns a pointer to the
|
||||||
|
* final '\0' to allow for easy calculation of the rendered length and easy
|
||||||
|
* appending to the C-string.
|
||||||
|
*/
|
||||||
|
#define Q_TOSTR(q, prec, base, s, slen) \
|
||||||
|
({ \
|
||||||
|
char *_r, *_s = s; \
|
||||||
|
int _i; \
|
||||||
|
if (Q_LTZ(q) && ((ptrdiff_t)(slen)) > 0) \
|
||||||
|
*_s++ = '-'; \
|
||||||
|
Q_BT(q) _part = Q_GIABSVAL(q); \
|
||||||
|
_r = _s; \
|
||||||
|
do { \
|
||||||
|
/* Render integer chars in reverse order. */ \
|
||||||
|
if ((_s - (s)) < ((ptrdiff_t)(slen))) \
|
||||||
|
*_s++ = Q_IBITS2CH(q, _part, base); \
|
||||||
|
else \
|
||||||
|
_r = NULL; \
|
||||||
|
} while (_part > 0 && _r != NULL); \
|
||||||
|
if (!((_s - (s)) < ((ptrdiff_t)(slen)))) \
|
||||||
|
_r = NULL; \
|
||||||
|
_i = (_s - _r) >> 1; /* N digits requires int(N/2) swaps. */ \
|
||||||
|
while (_i-- > 0 && _r != NULL) { \
|
||||||
|
/* Work from middle out to reverse integer chars. */ \
|
||||||
|
*_s = *(_r + _i); /* Stash LHS char temporarily. */ \
|
||||||
|
*(_r + _i) = *(_s - _i - 1); /* Copy RHS char to LHS. */\
|
||||||
|
*(_s - _i - 1) = *_s; /* Copy LHS char to RHS. */ \
|
||||||
|
} \
|
||||||
|
_i = (prec); \
|
||||||
|
if (_i != 0 && _r != NULL) { \
|
||||||
|
if ((_s - (s)) < ((ptrdiff_t)(slen))) \
|
||||||
|
*_s++ = '.'; \
|
||||||
|
else \
|
||||||
|
_r = NULL; \
|
||||||
|
_part = Q_GFABSVAL(q); \
|
||||||
|
if (_i < 0 || _i > (int)Q_NFBITS(q)) \
|
||||||
|
_i = Q_NFBITS(q); \
|
||||||
|
while (_i-- > 0 && _r != NULL) { \
|
||||||
|
/* Render fraction chars in correct order. */ \
|
||||||
|
if ((_s - (s)) < ((ptrdiff_t)(slen))) \
|
||||||
|
*_s++ = Q_FBITS2CH(q, _part, base); \
|
||||||
|
else \
|
||||||
|
_r = NULL; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
if ((_s - (s)) < ((ptrdiff_t)(slen)) && _r != NULL) \
|
||||||
|
*_s = '\0'; \
|
||||||
|
else { \
|
||||||
|
_r = NULL; \
|
||||||
|
if (((ptrdiff_t)(slen)) > 0) \
|
||||||
|
*(s) = '\0'; \
|
||||||
|
} \
|
||||||
|
/* Return a pointer to the '\0' or NULL on overflow. */ \
|
||||||
|
(_r != NULL ? _s : _r); \
|
||||||
|
})
|
||||||
|
|
||||||
|
/* Left shift an integral value to align with the int bits of 'q'. */
|
||||||
|
#define Q_SHL(q, iv) \
|
||||||
|
(Q_LTZ(iv) ? -(Q_ABS(iv) << Q_NFBITS(q)) : \
|
||||||
|
Q_TC(q, iv) << Q_NFBITS(q))
|
||||||
|
|
||||||
|
/* Calculate the relative fractional precision between 'a' and 'b' in bits. */
|
||||||
|
#define Q_RELPREC(a, b) ((int)Q_NFBITS(a) - (int)Q_NFBITS(b))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine control bits for the desired 'rpshft' radix point shift. Rounds up
|
||||||
|
* to the nearest valid shift supported by the encoding scheme.
|
||||||
|
*/
|
||||||
|
#define Q_CTRLINI(rpshft) \
|
||||||
|
(((rpshft) <= 8) ? (((rpshft) - 1) >> 1) : (0x4 | (((rpshft) - 1) >> 4)))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert decimal fractional value 'dfv' to its binary-encoded representation
|
||||||
|
* with 'nfbits' of binary precision. 'dfv' must be passed as a preprocessor
|
||||||
|
* literal to preserve leading zeroes. The returned result can be used to set a
|
||||||
|
* Q number's fractional bits e.g. using Q_SFVAL().
|
||||||
|
*/
|
||||||
|
#define Q_DFV2BFV(dfv, nfbits) \
|
||||||
|
({ \
|
||||||
|
uint64_t _bfv = 0, _thresh = 5, _tmp = dfv; \
|
||||||
|
int _i = sizeof(""#dfv) - 1; \
|
||||||
|
/* \
|
||||||
|
* Compute decimal threshold to determine which \
|
||||||
|
* conversion rounds will yield a binary 1. \
|
||||||
|
*/ \
|
||||||
|
while (--_i > 0) {_thresh *= 10;} \
|
||||||
|
_i = (nfbits) - 1; \
|
||||||
|
while (_i >= 0) { \
|
||||||
|
if (_thresh <= _tmp) { \
|
||||||
|
_bfv |= 1ULL << _i; \
|
||||||
|
_tmp = _tmp - _thresh; \
|
||||||
|
} \
|
||||||
|
_i--; _tmp <<= 1; \
|
||||||
|
} \
|
||||||
|
_bfv; \
|
||||||
|
})
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialise 'q' with raw integer value 'iv', decimal fractional value 'dfv',
|
||||||
|
* and radix point shift 'rpshft'. Must be done in two steps in case 'iv'
|
||||||
|
* depends on control bits being set e.g. when passing Q_INTMAX(q) as 'iv'.
|
||||||
|
*/
|
||||||
|
#define Q_INI(q, iv, dfv, rpshft) \
|
||||||
|
({ \
|
||||||
|
(*(q)) = Q_CTRLINI(rpshft); \
|
||||||
|
Q_SIFVALS(*(q), iv, Q_DFV2BFV(dfv, Q_NFBITS(*(q)))); \
|
||||||
|
})
|
||||||
|
|
||||||
|
/* Test if 'a' and 'b' fractional precision is the same (T) or not (F). */
|
||||||
|
#define Q_PRECEQ(a, b) (Q_NFBITS(a) == Q_NFBITS(b))
|
||||||
|
|
||||||
|
/* Test if 'n' is a signed type (T) or not (F). Works with any numeric type. */
|
||||||
|
#define Q_SIGNED(n) (Q_TC(n, -1) < 0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test if 'n' is negative. Works with any numeric type that uses the MSB as the
|
||||||
|
* sign bit, and also works with Q numbers.
|
||||||
|
*/
|
||||||
|
#define Q_LTZ(n) (Q_SIGNED(n) && ((n) & Q_SRAWMASK(n)))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return absolute value of 'n'. Works with any standard numeric type that uses
|
||||||
|
* the MSB as the sign bit, and is signed/unsigned type safe.
|
||||||
|
* Does not work with Q numbers; use Q_QABS() instead.
|
||||||
|
*/
|
||||||
|
#define Q_ABS(n) (Q_LTZ(n) ? -(n) : (n))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return an absolute value interpretation of 'q'.
|
||||||
|
*/
|
||||||
|
#define Q_QABS(q) (Q_SIGNED(q) ? (q) & ~Q_SRAWMASK(q) : (q))
|
||||||
|
|
||||||
|
/* Convert 'q' to float or double representation. */
|
||||||
|
#define Q_Q2F(q) ((float)Q_GIFVAL(q) / (float)(1ULL << Q_NFBITS(q)))
|
||||||
|
#define Q_Q2D(q) ((double)Q_GIFVAL(q) / (double)(1ULL << Q_NFBITS(q)))
|
||||||
|
|
||||||
|
/* Numerically compare 'a' and 'b' as whole numbers using provided operators. */
|
||||||
|
#define Q_QCMPQ(a, b, intcmp, fraccmp) \
|
||||||
|
((Q_GIVAL(a) intcmp Q_GIVAL(b)) || \
|
||||||
|
((Q_GIVAL(a) == Q_GIVAL(b)) && (Q_GFVAL(a) fraccmp Q_GFVAL(b))))
|
||||||
|
|
||||||
|
/* Test if 'a' is numerically less than 'b' (T) or not (F). */
|
||||||
|
#define Q_QLTQ(a, b) Q_QCMPQ(a, b, <, <)
|
||||||
|
|
||||||
|
/* Test if 'a' is numerically less than or equal to 'b' (T) or not (F). */
|
||||||
|
#define Q_QLEQ(a, b) Q_QCMPQ(a, b, <, <=)
|
||||||
|
|
||||||
|
/* Test if 'a' is numerically greater than 'b' (T) or not (F). */
|
||||||
|
#define Q_QGTQ(a, b) Q_QCMPQ(a, b, >, >)
|
||||||
|
|
||||||
|
/* Test if 'a' is numerically greater than or equal to 'b' (T) or not (F). */
|
||||||
|
#define Q_QGEQ(a, b) Q_QCMPQ(a, b, >, >=)
|
||||||
|
|
||||||
|
/* Test if 'a' is numerically equal to 'b' (T) or not (F). */
|
||||||
|
#define Q_QEQ(a, b) Q_QCMPQ(a, b, ==, ==)
|
||||||
|
|
||||||
|
/* Test if 'a' is numerically not equal to 'b' (T) or not (F). */
|
||||||
|
#define Q_QNEQ(a, b) Q_QCMPQ(a, b, !=, !=)
|
||||||
|
|
||||||
|
/* Returns the numerically larger of 'a' and 'b'. */
|
||||||
|
#define Q_QMAXQ(a, b) (Q_GT(a, b) ? (a) : (b))
|
||||||
|
|
||||||
|
/* Returns the numerically smaller of 'a' and 'b'. */
|
||||||
|
#define Q_QMINQ(a, b) (Q_LT(a, b) ? (a) : (b))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test if 'a' can be represented by 'b' with full accuracy (T) or not (F).
|
||||||
|
* The type casting has to be done to a's type so that any truncation caused by
|
||||||
|
* the casts will not affect the logic.
|
||||||
|
*/
|
||||||
|
#define Q_QCANREPQ(a, b) \
|
||||||
|
((((Q_LTZ(a) && Q_SIGNED(b)) || !Q_LTZ(a)) && \
|
||||||
|
Q_GIABSVAL(a) <= Q_TC(a, Q_IMAXVAL(b)) && \
|
||||||
|
Q_GFABSVAL(a) <= Q_TC(a, Q_FMAXVAL(b))) ? \
|
||||||
|
0 : EOVERFLOW)
|
||||||
|
|
||||||
|
/* Test if raw integer value 'i' can be represented by 'q' (T) or not (F). */
|
||||||
|
#define Q_QCANREPI(q, i) \
|
||||||
|
((((Q_LTZ(i) && Q_SIGNED(q)) || !Q_LTZ(i)) && \
|
||||||
|
Q_ABS(i) <= Q_TC(i, Q_IMAXVAL(q))) ? 0 : EOVERFLOW)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns a Q variable debug format string with appropriate modifiers and
|
||||||
|
* padding relevant to the underlying Q data type.
|
||||||
|
*/
|
||||||
|
#define Q_DEBUGFMT_(prefmt, postfmt, mod, hexpad) \
|
||||||
|
prefmt \
|
||||||
|
/* Var name + address. */ \
|
||||||
|
"\"%s\"@%p" \
|
||||||
|
/* Data type. */ \
|
||||||
|
"\n\ttype=%c%dq_t, " \
|
||||||
|
/* Qm.n notation; 'm' = # int bits, 'n' = # frac bits. */ \
|
||||||
|
"Qm.n=Q%d.%d, " \
|
||||||
|
/* Radix point shift relative to the underlying data type's LSB. */ \
|
||||||
|
"rpshft=%d, " \
|
||||||
|
/* Min/max integer values which can be represented. */ \
|
||||||
|
"imin=0x%0" #mod "x, " \
|
||||||
|
"imax=0x%0" #mod "x" \
|
||||||
|
/* Raw hex dump of all bits. */ \
|
||||||
|
"\n\tqraw=0x%0" #hexpad #mod "x" \
|
||||||
|
/* Bit masks for int/frac/ctrl bits. */ \
|
||||||
|
"\n\timask=0x%0" #hexpad #mod "x, " \
|
||||||
|
"fmask=0x%0" #hexpad #mod "x, " \
|
||||||
|
"cmask=0x%0" #hexpad #mod "x, " \
|
||||||
|
"ifmask=0x%0" #hexpad #mod "x" \
|
||||||
|
/* Hex dump of masked int bits; 'iraw' includes shift */ \
|
||||||
|
"\n\tiraw=0x%0" #hexpad #mod "x, " \
|
||||||
|
"iabsval=0x%" #mod "x, " \
|
||||||
|
"ival=0x%" #mod "x" \
|
||||||
|
/* Hex dump of masked frac bits; 'fraw' includes shift */ \
|
||||||
|
"\n\tfraw=0x%0" #hexpad #mod "x, " \
|
||||||
|
"fabsval=0x%" #mod "x, " \
|
||||||
|
"fval=0x%" #mod "x" \
|
||||||
|
"%s" \
|
||||||
|
postfmt
|
||||||
|
|
||||||
|
#define Q_DEBUGFMT(q, prefmt, postfmt) \
|
||||||
|
sizeof(q) == 8 ? Q_DEBUGFMT_(prefmt, postfmt, j, 16) : \
|
||||||
|
sizeof(q) == 4 ? Q_DEBUGFMT_(prefmt, postfmt, , 8) : \
|
||||||
|
sizeof(q) == 2 ? Q_DEBUGFMT_(prefmt, postfmt, h, 4) : \
|
||||||
|
sizeof(q) == 1 ? Q_DEBUGFMT_(prefmt, postfmt, hh, 2) : \
|
||||||
|
prefmt "\"%s\"@%p: invalid" postfmt \
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns a format string and data suitable for printf-like rendering
|
||||||
|
* e.g. Print to console with a trailing newline: printf(Q_DEBUG(q, "", "\n"));
|
||||||
|
*/
|
||||||
|
#define Q_DEBUG(q, prefmt, postfmt, incfmt) \
|
||||||
|
Q_DEBUGFMT(q, prefmt, postfmt) \
|
||||||
|
, #q \
|
||||||
|
, &(q) \
|
||||||
|
, Q_SIGNED(q) ? 's' : 'u' \
|
||||||
|
, Q_NTBITS(q) \
|
||||||
|
, Q_NIBITS(q) \
|
||||||
|
, Q_NFBITS(q) \
|
||||||
|
, Q_RPSHFT(q) \
|
||||||
|
, Q_IMINVAL(q) \
|
||||||
|
, Q_IMAXVAL(q) \
|
||||||
|
, (q) \
|
||||||
|
, Q_IRAWMASK(q) \
|
||||||
|
, Q_FRAWMASK(q) \
|
||||||
|
, Q_TC(q, Q_CRAWMASK(q)) \
|
||||||
|
, Q_IFRAWMASK(q) \
|
||||||
|
, Q_GIRAW(q) \
|
||||||
|
, Q_GIABSVAL(q) \
|
||||||
|
, Q_GIVAL(q) \
|
||||||
|
, Q_GFRAW(q) \
|
||||||
|
, Q_GFABSVAL(q) \
|
||||||
|
, Q_GFVAL(q) \
|
||||||
|
, (incfmt) ? Q_DEBUGFMT(q, "\nfmt:", "") : "" \
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If precision differs, attempt to normalise to the greater precision that
|
||||||
|
* preserves the integer component of both 'a' and 'b'.
|
||||||
|
*/
|
||||||
|
#define Q_NORMPREC(a, b) \
|
||||||
|
({ \
|
||||||
|
int _perr = 0, _relprec = Q_RELPREC(*(a), b); \
|
||||||
|
if (_relprec != 0) \
|
||||||
|
_perr = ERANGE; /* XXXLAS: Do precision normalisation! */\
|
||||||
|
_perr; \
|
||||||
|
})
|
||||||
|
|
||||||
|
/* Clone r's control bits and int/frac value into 'l'. */
|
||||||
|
#define Q_QCLONEQ(l, r) \
|
||||||
|
({ \
|
||||||
|
Q_BT(*(l)) _l = Q_GCVAL(r); \
|
||||||
|
int _err = Q_QCANREPQ(r, _l); \
|
||||||
|
if (!_err) { \
|
||||||
|
*(l) = _l; \
|
||||||
|
Q_SIFVAL(*(l), Q_GIFVAL(r)); \
|
||||||
|
} \
|
||||||
|
_err; \
|
||||||
|
})
|
||||||
|
|
||||||
|
/* Copy r's int/frac vals into 'l', retaining 'l's precision and signedness. */
|
||||||
|
#define Q_QCPYVALQ(l, r) \
|
||||||
|
({ \
|
||||||
|
int _err = Q_QCANREPQ(r, *(l)); \
|
||||||
|
if (!_err) \
|
||||||
|
Q_SIFVALS(*(l), Q_GIVAL(r), Q_GFVAL(r)); \
|
||||||
|
_err; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define Q_QADDSUBQ(a, b, eop) \
|
||||||
|
({ \
|
||||||
|
int _aserr; \
|
||||||
|
if ((_aserr = Q_NORMPREC(a, b))) while(0); /* NOP */ \
|
||||||
|
else if ((eop) == '+') { \
|
||||||
|
if (Q_IFMAXVAL(*(a)) - Q_GIFABSVAL(b) < Q_GIFVAL(*(a))) \
|
||||||
|
_aserr = EOVERFLOW; /* [+/-a + +b] > max(a) */ \
|
||||||
|
else \
|
||||||
|
Q_SIFVAL(*(a), Q_GIFVAL(*(a)) + Q_TC(*(a), \
|
||||||
|
Q_GIFABSVAL(b))); \
|
||||||
|
} else { /* eop == '-' */ \
|
||||||
|
if (Q_IFMINVAL(*(a)) + Q_GIFABSVAL(b) > Q_GIFVAL(*(a))) \
|
||||||
|
_aserr = EOVERFLOW; /* [+/-a - +b] < min(a) */ \
|
||||||
|
else \
|
||||||
|
Q_SIFVAL(*(a), Q_GIFVAL(*(a)) - Q_TC(*(a), \
|
||||||
|
Q_GIFABSVAL(b))); \
|
||||||
|
} \
|
||||||
|
_aserr; \
|
||||||
|
})
|
||||||
|
#define Q_QADDQ(a, b) Q_QADDSUBQ(a, b, (Q_LTZ(b) ? '-' : '+'))
|
||||||
|
#define Q_QSUBQ(a, b) Q_QADDSUBQ(a, b, (Q_LTZ(b) ? '+' : '-'))
|
||||||
|
|
||||||
|
#define Q_QDIVQ(a, b) \
|
||||||
|
({ \
|
||||||
|
int _err; \
|
||||||
|
if ((_err = Q_NORMPREC(a, b))) while(0); /* NOP */ \
|
||||||
|
else if (Q_GIFABSVAL(b) == 0 || (!Q_SIGNED(*(a)) && Q_LTZ(b))) \
|
||||||
|
_err = EINVAL; /* Divide by zero or cannot represent. */\
|
||||||
|
/* XXXLAS: Handle overflow. */ \
|
||||||
|
else if (Q_GIFABSVAL(*(a)) != 0) { /* Result expected. */ \
|
||||||
|
Q_SIFVAL(*(a), \
|
||||||
|
((Q_GIVAL(*(a)) << Q_NFBITS(*(a))) / Q_GIFVAL(b)) + \
|
||||||
|
(Q_GFVAL(b) == 0 ? 0 : \
|
||||||
|
((Q_GFVAL(*(a)) << Q_NFBITS(*(a))) / Q_GFVAL(b)))); \
|
||||||
|
} \
|
||||||
|
_err; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define Q_QMULQ(a, b) \
|
||||||
|
({ \
|
||||||
|
int _mulerr; \
|
||||||
|
if ((_mulerr = Q_NORMPREC(a, b))) while(0); /* NOP */ \
|
||||||
|
else if (!Q_SIGNED(*(a)) && Q_LTZ(b)) \
|
||||||
|
_mulerr = EINVAL; \
|
||||||
|
else if (Q_GIFABSVAL(b) != 0 && \
|
||||||
|
Q_IFMAXVAL(*(a)) / Q_GIFABSVAL(b) < Q_GIFABSVAL(*(a))) \
|
||||||
|
_mulerr = EOVERFLOW; \
|
||||||
|
else \
|
||||||
|
Q_SIFVAL(*(a), (Q_GIFVAL(*(a)) * Q_GIFVAL(b)) >> \
|
||||||
|
Q_NFBITS(*(a))); \
|
||||||
|
_mulerr; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define Q_QCPYVALI(q, i) \
|
||||||
|
({ \
|
||||||
|
int _err = Q_QCANREPI(*(q), i); \
|
||||||
|
if (!_err) \
|
||||||
|
Q_SIFVAL(*(q), Q_SHL(*(q), i)); \
|
||||||
|
_err; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define Q_QADDSUBI(q, i, eop) \
|
||||||
|
({ \
|
||||||
|
int _aserr = 0; \
|
||||||
|
if (Q_NTBITS(*(q)) < (uint32_t)flsll(Q_ABS(i))) \
|
||||||
|
_aserr = EOVERFLOW; /* i cannot fit in q's type. */ \
|
||||||
|
else if ((eop) == '+') { \
|
||||||
|
if (Q_IMAXVAL(*(q)) - Q_TC(*(q), Q_ABS(i)) < \
|
||||||
|
Q_GIVAL(*(q))) \
|
||||||
|
_aserr = EOVERFLOW; /* [+/-q + +i] > max(q) */ \
|
||||||
|
else \
|
||||||
|
Q_SIFVAL(*(q), Q_GIFVAL(*(q)) + \
|
||||||
|
Q_SHL(*(q), Q_ABS(i))); \
|
||||||
|
} else { /* eop == '-' */ \
|
||||||
|
if (Q_IMINVAL(*(q)) + Q_ABS(i) > Q_GIVAL(*(q))) \
|
||||||
|
_aserr = EOVERFLOW; /* [+/-q - +i] < min(q) */ \
|
||||||
|
else \
|
||||||
|
Q_SIFVAL(*(q), Q_GIFVAL(*(q)) - \
|
||||||
|
Q_SHL(*(q), Q_ABS(i))); \
|
||||||
|
} \
|
||||||
|
_aserr; \
|
||||||
|
})
|
||||||
|
#define Q_QADDI(q, i) Q_QADDSUBI(q, i, (Q_LTZ(i) ? '-' : '+'))
|
||||||
|
#define Q_QSUBI(q, i) Q_QADDSUBI(q, i, (Q_LTZ(i) ? '+' : '-'))
|
||||||
|
|
||||||
|
#define Q_QDIVI(q, i) \
|
||||||
|
({ \
|
||||||
|
int _diverr = 0; \
|
||||||
|
if ((i) == 0 || (!Q_SIGNED(*(q)) && Q_LTZ(i))) \
|
||||||
|
_diverr = EINVAL; /* Divide by zero or cannot represent. */\
|
||||||
|
else if (Q_GIFABSVAL(*(q)) != 0) { /* Result expected. */ \
|
||||||
|
Q_SIFVAL(*(q), Q_GIFVAL(*(q)) / Q_TC(*(q), i)); \
|
||||||
|
if (Q_GIFABSVAL(*(q)) == 0) \
|
||||||
|
_diverr = ERANGE; /* q underflow. */ \
|
||||||
|
} \
|
||||||
|
_diverr; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define Q_QMULI(q, i) \
|
||||||
|
({ \
|
||||||
|
int _mulerr = 0; \
|
||||||
|
if (!Q_SIGNED(*(q)) && Q_LTZ(i)) \
|
||||||
|
_mulerr = EINVAL; /* Cannot represent. */ \
|
||||||
|
else if ((i) != 0 && Q_IFMAXVAL(*(q)) / Q_TC(*(q), Q_ABS(i)) < \
|
||||||
|
Q_GIFABSVAL(*(q))) \
|
||||||
|
_mulerr = EOVERFLOW; \
|
||||||
|
else \
|
||||||
|
Q_SIFVAL(*(q), Q_GIFVAL(*(q)) * Q_TC(*(q), i)); \
|
||||||
|
_mulerr; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define Q_QFRACI(q, in, id) \
|
||||||
|
({ \
|
||||||
|
uint64_t _tmp; \
|
||||||
|
int _err = 0; \
|
||||||
|
if ((id) == 0) \
|
||||||
|
_err = EINVAL; /* Divide by zero. */ \
|
||||||
|
else if ((in) == 0) \
|
||||||
|
Q_SIFVAL(*(q), in); \
|
||||||
|
else if ((_tmp = Q_ABS(in)) > (UINT64_MAX >> Q_RPSHFT(*(q)))) \
|
||||||
|
_err = EOVERFLOW; /* _tmp overflow. */ \
|
||||||
|
else { \
|
||||||
|
_tmp = Q_SHL(*(q), _tmp) / Q_ABS(id); \
|
||||||
|
if (Q_QCANREPI(*(q), _tmp & Q_IFVALIMASK(*(q)))) \
|
||||||
|
_err = EOVERFLOW; /* q overflow. */ \
|
||||||
|
else { \
|
||||||
|
Q_SIFVAL(*(q), _tmp); \
|
||||||
|
Q_SSIGN(*(q), (Q_LTZ(in) && !Q_LTZ(id)) || \
|
||||||
|
(!Q_LTZ(in) && Q_LTZ(id))); \
|
||||||
|
if (_tmp == 0) \
|
||||||
|
_err = ERANGE; /* q underflow. */ \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
_err; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#endif /* _SYS_QMATH_H_ */
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
TESTSDIR= ${TESTSBASE}/sys/sys
|
TESTSDIR= ${TESTSBASE}/sys/sys
|
||||||
|
|
||||||
ATF_TESTS_C= bitstring_test rb_test splay_test
|
ATF_TESTS_C= bitstring_test qmath_test rb_test splay_test
|
||||||
|
|
||||||
WARNS?= 5
|
WARNS?= 5
|
||||||
|
|
||||||
|
653
tests/sys/sys/qmath_test.c
Normal file
653
tests/sys/sys/qmath_test.c
Normal file
@ -0,0 +1,653 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2018 Netflix, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* $FreeBSD$
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Author: Lawrence Stewart <lstewart@netflix.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/qmath.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <atf-c.h>
|
||||||
|
|
||||||
|
#define QTEST_IV 3
|
||||||
|
#define QTEST_IVSTR "3.00"
|
||||||
|
#define QTEST_RPSHFT 2
|
||||||
|
#define QTEST_INTBITS(q) (Q_NTBITS(q) - Q_SIGNED(q) - Q_NFBITS(q) - Q_NCBITS)
|
||||||
|
#define QTEST_QITRUNC(q, iv) ((iv) >> Q_RPSHFT(q))
|
||||||
|
#define QTEST_FFACTOR 32.0
|
||||||
|
|
||||||
|
#define bitsperrand 31
|
||||||
|
#define GENRAND(a, lb, ub) \
|
||||||
|
({ \
|
||||||
|
int _rembits; \
|
||||||
|
do { \
|
||||||
|
_rembits = Q_BITSPERBASEUP(ub) + Q_LTZ(lb); \
|
||||||
|
*(a) = (__typeof(*(a)))0; \
|
||||||
|
while (_rembits > 0) { \
|
||||||
|
*(a) |= (((uint64_t)random()) & \
|
||||||
|
((1ULL << (_rembits > bitsperrand ? \
|
||||||
|
bitsperrand : _rembits)) - 1)); \
|
||||||
|
*(a) <<= (_rembits - (_rembits > bitsperrand ? \
|
||||||
|
bitsperrand : _rembits)); \
|
||||||
|
_rembits -= bitsperrand; \
|
||||||
|
} \
|
||||||
|
*(a) += lb; \
|
||||||
|
} while (*(a) < (lb) || (uint64_t)*(a) > (ub)); \
|
||||||
|
*(a); \
|
||||||
|
})
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Smoke tests for basic qmath operations, such as initialization
|
||||||
|
* or string formatting.
|
||||||
|
*/
|
||||||
|
ATF_TC_WITHOUT_HEAD(basic_s8q);
|
||||||
|
ATF_TC_BODY(basic_s8q, tc)
|
||||||
|
{
|
||||||
|
char buf[128];
|
||||||
|
s8q_t s8;
|
||||||
|
|
||||||
|
Q_INI(&s8, QTEST_IV, 0, QTEST_RPSHFT);
|
||||||
|
Q_TOSTR(s8, -1, 10, buf, sizeof(buf));
|
||||||
|
ATF_CHECK_STREQ(QTEST_IVSTR, buf);
|
||||||
|
ATF_CHECK_EQ(sizeof(s8) << 3, Q_NTBITS(s8));
|
||||||
|
ATF_CHECK_EQ(QTEST_RPSHFT, Q_NFBITS(s8));
|
||||||
|
ATF_CHECK_EQ(QTEST_INTBITS(s8), Q_NIBITS(s8));
|
||||||
|
ATF_CHECK_EQ(QTEST_QITRUNC(s8, INT8_MAX), Q_IMAXVAL(s8));
|
||||||
|
ATF_CHECK_EQ(-Q_IMAXVAL(s8), Q_IMINVAL(s8));
|
||||||
|
}
|
||||||
|
|
||||||
|
ATF_TC_WITHOUT_HEAD(basic_s16q);
|
||||||
|
ATF_TC_BODY(basic_s16q, tc)
|
||||||
|
{
|
||||||
|
char buf[128];
|
||||||
|
s16q_t s16;
|
||||||
|
|
||||||
|
Q_INI(&s16, QTEST_IV, 0, QTEST_RPSHFT);
|
||||||
|
Q_TOSTR(s16, -1, 10, buf, sizeof(buf));
|
||||||
|
ATF_CHECK_STREQ(QTEST_IVSTR, buf);
|
||||||
|
ATF_CHECK_EQ(sizeof(s16) << 3, Q_NTBITS(s16));
|
||||||
|
ATF_CHECK_EQ(QTEST_RPSHFT, Q_NFBITS(s16));
|
||||||
|
ATF_CHECK_EQ(QTEST_INTBITS(s16), Q_NIBITS(s16));
|
||||||
|
ATF_CHECK_EQ(QTEST_QITRUNC(s16, INT16_MAX), Q_IMAXVAL(s16));
|
||||||
|
ATF_CHECK_EQ(-Q_IMAXVAL(s16), Q_IMINVAL(s16));
|
||||||
|
}
|
||||||
|
|
||||||
|
ATF_TC_WITHOUT_HEAD(basic_s32q);
|
||||||
|
ATF_TC_BODY(basic_s32q, tc)
|
||||||
|
{
|
||||||
|
char buf[128];
|
||||||
|
s32q_t s32;
|
||||||
|
|
||||||
|
Q_INI(&s32, QTEST_IV, 0, QTEST_RPSHFT);
|
||||||
|
Q_TOSTR(s32, -1, 10, buf, sizeof(buf));
|
||||||
|
ATF_CHECK_STREQ(QTEST_IVSTR, buf);
|
||||||
|
ATF_CHECK_EQ(sizeof(s32) << 3, Q_NTBITS(s32));
|
||||||
|
ATF_CHECK_EQ(QTEST_RPSHFT, Q_NFBITS(s32));
|
||||||
|
ATF_CHECK_EQ(QTEST_INTBITS(s32), Q_NIBITS(s32));
|
||||||
|
ATF_CHECK_EQ(QTEST_QITRUNC(s32, INT32_MAX), Q_IMAXVAL(s32));
|
||||||
|
ATF_CHECK_EQ(-Q_IMAXVAL(s32), Q_IMINVAL(s32));
|
||||||
|
}
|
||||||
|
|
||||||
|
ATF_TC_WITHOUT_HEAD(basic_s64q);
|
||||||
|
ATF_TC_BODY(basic_s64q, tc)
|
||||||
|
{
|
||||||
|
char buf[128];
|
||||||
|
s64q_t s64;
|
||||||
|
|
||||||
|
Q_INI(&s64, QTEST_IV, 0, QTEST_RPSHFT);
|
||||||
|
Q_TOSTR(s64, -1, 10, buf, sizeof(buf));
|
||||||
|
ATF_CHECK_STREQ(QTEST_IVSTR, buf);
|
||||||
|
ATF_CHECK_EQ(sizeof(s64) << 3, Q_NTBITS(s64));
|
||||||
|
ATF_CHECK_EQ(QTEST_RPSHFT, Q_NFBITS(s64));
|
||||||
|
ATF_CHECK_EQ(QTEST_INTBITS(s64), Q_NIBITS(s64));
|
||||||
|
ATF_CHECK_EQ(QTEST_QITRUNC(s64, INT64_MAX), Q_IMAXVAL(s64));
|
||||||
|
ATF_CHECK_EQ(-Q_IMAXVAL(s64), Q_IMINVAL(s64));
|
||||||
|
}
|
||||||
|
|
||||||
|
ATF_TC_WITHOUT_HEAD(basic_u8q);
|
||||||
|
ATF_TC_BODY(basic_u8q, tc)
|
||||||
|
{
|
||||||
|
char buf[128];
|
||||||
|
u8q_t u8;
|
||||||
|
|
||||||
|
Q_INI(&u8, QTEST_IV, 0, QTEST_RPSHFT);
|
||||||
|
Q_TOSTR(u8, -1, 10, buf, sizeof(buf));
|
||||||
|
ATF_CHECK_STREQ(QTEST_IVSTR, buf);
|
||||||
|
ATF_CHECK_EQ(sizeof(u8) << 3, Q_NTBITS(u8));
|
||||||
|
ATF_CHECK_EQ(QTEST_RPSHFT, Q_NFBITS(u8));
|
||||||
|
ATF_CHECK_EQ(QTEST_INTBITS(u8), Q_NIBITS(u8));
|
||||||
|
ATF_CHECK_EQ(QTEST_QITRUNC(u8, UINT8_MAX), Q_IMAXVAL(u8));
|
||||||
|
ATF_CHECK_EQ(0, Q_IMINVAL(u8));
|
||||||
|
}
|
||||||
|
|
||||||
|
ATF_TC_WITHOUT_HEAD(basic_u16q);
|
||||||
|
ATF_TC_BODY(basic_u16q, tc)
|
||||||
|
{
|
||||||
|
char buf[128];
|
||||||
|
u16q_t u16;
|
||||||
|
|
||||||
|
Q_INI(&u16, QTEST_IV, 0, QTEST_RPSHFT);
|
||||||
|
Q_TOSTR(u16, -1, 10, buf, sizeof(buf));
|
||||||
|
ATF_CHECK_STREQ(QTEST_IVSTR, buf);
|
||||||
|
ATF_CHECK_EQ(sizeof(u16) << 3, Q_NTBITS(u16));
|
||||||
|
ATF_CHECK_EQ(QTEST_RPSHFT, Q_NFBITS(u16));
|
||||||
|
ATF_CHECK_EQ(QTEST_INTBITS(u16), Q_NIBITS(u16));
|
||||||
|
ATF_CHECK_EQ(QTEST_QITRUNC(u16, UINT16_MAX), Q_IMAXVAL(u16));
|
||||||
|
ATF_CHECK_EQ(0, Q_IMINVAL(u16));
|
||||||
|
}
|
||||||
|
|
||||||
|
ATF_TC_WITHOUT_HEAD(basic_u32q);
|
||||||
|
ATF_TC_BODY(basic_u32q, tc)
|
||||||
|
{
|
||||||
|
char buf[128];
|
||||||
|
u32q_t u32;
|
||||||
|
|
||||||
|
Q_INI(&u32, QTEST_IV, 0, QTEST_RPSHFT);
|
||||||
|
Q_TOSTR(u32, -1, 10, buf, sizeof(buf));
|
||||||
|
ATF_CHECK_STREQ(QTEST_IVSTR, buf);
|
||||||
|
ATF_CHECK_EQ(sizeof(u32) << 3, Q_NTBITS(u32));
|
||||||
|
ATF_CHECK_EQ(QTEST_RPSHFT, Q_NFBITS(u32));
|
||||||
|
ATF_CHECK_EQ(QTEST_INTBITS(u32), Q_NIBITS(u32));
|
||||||
|
ATF_CHECK_EQ(QTEST_QITRUNC(u32, UINT32_MAX), Q_IMAXVAL(u32));
|
||||||
|
ATF_CHECK_EQ(0, Q_IMINVAL(u32));
|
||||||
|
}
|
||||||
|
|
||||||
|
ATF_TC_WITHOUT_HEAD(basic_u64q);
|
||||||
|
ATF_TC_BODY(basic_u64q, tc)
|
||||||
|
{
|
||||||
|
char buf[128];
|
||||||
|
u64q_t u64;
|
||||||
|
|
||||||
|
Q_INI(&u64, QTEST_IV, 0, QTEST_RPSHFT);
|
||||||
|
Q_TOSTR(u64, -1, 10, buf, sizeof(buf));
|
||||||
|
ATF_CHECK_STREQ(QTEST_IVSTR, buf);
|
||||||
|
ATF_CHECK_EQ(sizeof(u64) << 3, Q_NTBITS(u64));
|
||||||
|
ATF_CHECK_EQ(QTEST_RPSHFT, Q_NFBITS(u64));
|
||||||
|
ATF_CHECK_EQ(QTEST_INTBITS(u64), Q_NIBITS(u64));
|
||||||
|
ATF_CHECK_EQ(QTEST_QITRUNC(u64, UINT64_MAX), Q_IMAXVAL(u64));
|
||||||
|
ATF_CHECK_EQ(0, Q_IMINVAL(u64));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test Q_QMULQ(3) by applying it to two random Q numbers and comparing
|
||||||
|
* the result with its floating-point counterpart.
|
||||||
|
*/
|
||||||
|
ATF_TC_WITHOUT_HEAD(qmulq_s64q);
|
||||||
|
ATF_TC_BODY(qmulq_s64q, tc)
|
||||||
|
{
|
||||||
|
s64q_t a_s64q, b_s64q, r_s64q;
|
||||||
|
double a_dbl, b_dbl, r_dbl, maxe_dbl, delta_dbl;
|
||||||
|
int64_t a_int, b_int;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
srandomdev();
|
||||||
|
|
||||||
|
for (int i = 0; i < 10;) {
|
||||||
|
GENRAND(&a_s64q, INT64_MIN, UINT64_MAX);
|
||||||
|
GENRAND(&b_s64q, INT64_MIN, UINT64_MAX);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX: We cheat a bit, to stand any chance of multiplying
|
||||||
|
* without overflow.
|
||||||
|
*/
|
||||||
|
error = Q_QDIVQ(&a_s64q, b_s64q);
|
||||||
|
if (error == EOVERFLOW || error == ERANGE)
|
||||||
|
continue;
|
||||||
|
ATF_CHECK_EQ(0, error);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXXLAS: Until Qmath handles precision normalisation, only
|
||||||
|
* test with equal precision.
|
||||||
|
*/
|
||||||
|
Q_SCVAL(b_s64q, Q_GCVAL(a_s64q));
|
||||||
|
a_int = Q_GIVAL(a_s64q);
|
||||||
|
b_int = Q_GIVAL(b_s64q);
|
||||||
|
|
||||||
|
/* Q<op>Q testing. */
|
||||||
|
a_dbl = Q_Q2D(a_s64q);
|
||||||
|
b_dbl = Q_Q2D(b_s64q);
|
||||||
|
|
||||||
|
r_s64q = a_s64q;
|
||||||
|
error = Q_QMULQ(&r_s64q, b_s64q);
|
||||||
|
if (error == EOVERFLOW || error == ERANGE)
|
||||||
|
continue;
|
||||||
|
i++;
|
||||||
|
ATF_CHECK_EQ(0, error);
|
||||||
|
|
||||||
|
r_dbl = a_dbl * b_dbl;
|
||||||
|
#ifdef notyet
|
||||||
|
maxe_dbl = fabs(((1.0 / Q_NFBITS(a_s64q)) * (double)b_int) +
|
||||||
|
((1.0 / Q_NFBITS(b_s64q)) * (double)a_int));
|
||||||
|
#else
|
||||||
|
maxe_dbl = QTEST_FFACTOR;
|
||||||
|
#endif
|
||||||
|
delta_dbl = fabs(r_dbl - Q_Q2D(r_s64q));
|
||||||
|
ATF_CHECK_MSG(delta_dbl <= maxe_dbl,
|
||||||
|
"\tQMULQ(%10f * %10f): |%10f - %10f| = %10f "
|
||||||
|
"(max err %f)\n",
|
||||||
|
Q_Q2D(a_s64q), Q_Q2D(b_s64q), Q_Q2D(r_s64q), r_dbl,
|
||||||
|
delta_dbl, maxe_dbl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test Q_QDIVQ(3) by applying it to two random Q numbers and comparing
|
||||||
|
* the result with its floating-point counterpart.
|
||||||
|
*/
|
||||||
|
ATF_TC_WITHOUT_HEAD(qdivq_s64q);
|
||||||
|
ATF_TC_BODY(qdivq_s64q, tc)
|
||||||
|
{
|
||||||
|
s64q_t a_s64q, b_s64q, r_s64q;
|
||||||
|
double a_dbl, b_dbl, r_dbl, maxe_dbl, delta_dbl;
|
||||||
|
int64_t a_int, b_int;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
srandomdev();
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
GENRAND(&a_s64q, INT64_MIN, UINT64_MAX);
|
||||||
|
GENRAND(&b_s64q, INT64_MIN, UINT64_MAX);
|
||||||
|
/*
|
||||||
|
* XXXLAS: Until Qmath handles precision normalisation, only
|
||||||
|
* test with equal precision.
|
||||||
|
*/
|
||||||
|
Q_SCVAL(b_s64q, Q_GCVAL(a_s64q));
|
||||||
|
a_int = Q_GIVAL(a_s64q);
|
||||||
|
b_int = Q_GIVAL(b_s64q);
|
||||||
|
|
||||||
|
/* Q<op>Q testing. */
|
||||||
|
a_dbl = Q_Q2D(a_s64q);
|
||||||
|
b_dbl = Q_Q2D(b_s64q);
|
||||||
|
|
||||||
|
r_s64q = a_s64q;
|
||||||
|
error = Q_QDIVQ(&r_s64q, b_s64q);
|
||||||
|
ATF_CHECK_EQ(0, error);
|
||||||
|
|
||||||
|
r_dbl = a_dbl / b_dbl;
|
||||||
|
#ifdef notyet
|
||||||
|
maxe_dbl = fabs(1.0 / (1ULL << Q_NFBITS(a_s64q)));
|
||||||
|
#else
|
||||||
|
maxe_dbl = QTEST_FFACTOR * 2;
|
||||||
|
#endif
|
||||||
|
delta_dbl = fabs(r_dbl - Q_Q2D(r_s64q));
|
||||||
|
ATF_CHECK_MSG(delta_dbl <= maxe_dbl,
|
||||||
|
"\tQDIVQ(%10f / %10f): |%10f - %10f| = %10f "
|
||||||
|
"(max err %f)\n",
|
||||||
|
Q_Q2D(a_s64q), Q_Q2D(b_s64q), Q_Q2D(r_s64q), r_dbl,
|
||||||
|
delta_dbl, maxe_dbl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test Q_QADDQ(3) by applying it to two random Q numbers and comparing
|
||||||
|
* the result with its floating-point counterpart.
|
||||||
|
*/
|
||||||
|
ATF_TC_WITHOUT_HEAD(qaddq_s64q);
|
||||||
|
ATF_TC_BODY(qaddq_s64q, tc)
|
||||||
|
{
|
||||||
|
s64q_t a_s64q, b_s64q, r_s64q;
|
||||||
|
double a_dbl, b_dbl, r_dbl, maxe_dbl, delta_dbl;
|
||||||
|
int64_t a_int, b_int;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
srandomdev();
|
||||||
|
|
||||||
|
for (int i = 0; i < 10;) {
|
||||||
|
GENRAND(&a_s64q, INT64_MIN, UINT64_MAX);
|
||||||
|
GENRAND(&b_s64q, INT64_MIN, UINT64_MAX);
|
||||||
|
/*
|
||||||
|
* XXXLAS: Until Qmath handles precision normalisation, only
|
||||||
|
* test with equal precision.
|
||||||
|
*/
|
||||||
|
Q_SCVAL(b_s64q, Q_GCVAL(a_s64q));
|
||||||
|
a_int = Q_GIVAL(a_s64q);
|
||||||
|
b_int = Q_GIVAL(b_s64q);
|
||||||
|
|
||||||
|
/* Q<op>Q testing. */
|
||||||
|
a_dbl = Q_Q2D(a_s64q);
|
||||||
|
b_dbl = Q_Q2D(b_s64q);
|
||||||
|
|
||||||
|
r_s64q = a_s64q;
|
||||||
|
error = Q_QADDQ(&r_s64q, b_s64q);
|
||||||
|
if (error == EOVERFLOW || error == ERANGE)
|
||||||
|
continue;
|
||||||
|
i++;
|
||||||
|
ATF_CHECK_EQ(0, error);
|
||||||
|
|
||||||
|
r_dbl = a_dbl + b_dbl;
|
||||||
|
#ifdef notyet
|
||||||
|
maxe_dbl = 0.5;
|
||||||
|
#else
|
||||||
|
maxe_dbl = QTEST_FFACTOR;
|
||||||
|
#endif
|
||||||
|
delta_dbl = fabs(r_dbl - Q_Q2D(r_s64q));
|
||||||
|
ATF_CHECK_MSG(delta_dbl <= maxe_dbl,
|
||||||
|
"\tQADDQ(%10f + %10f): |%10f - %10f| = %10f "
|
||||||
|
"(max err %f)\n",
|
||||||
|
Q_Q2D(a_s64q), Q_Q2D(b_s64q), Q_Q2D(r_s64q), r_dbl,
|
||||||
|
delta_dbl, maxe_dbl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test Q_QSUBQ(3) by applying it to two random Q numbers and comparing
|
||||||
|
* the result with its floating-point counterpart.
|
||||||
|
*/
|
||||||
|
ATF_TC_WITHOUT_HEAD(qsubq_s64q);
|
||||||
|
ATF_TC_BODY(qsubq_s64q, tc)
|
||||||
|
{
|
||||||
|
s64q_t a_s64q, b_s64q, r_s64q;
|
||||||
|
double a_dbl, b_dbl, r_dbl, maxe_dbl, delta_dbl;
|
||||||
|
int64_t a_int, b_int;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
srandomdev();
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
GENRAND(&a_s64q, INT64_MIN, UINT64_MAX);
|
||||||
|
GENRAND(&b_s64q, INT64_MIN, UINT64_MAX);
|
||||||
|
/*
|
||||||
|
* XXXLAS: Until Qmath handles precision normalisation, only
|
||||||
|
* test with equal precision.
|
||||||
|
*/
|
||||||
|
Q_SCVAL(b_s64q, Q_GCVAL(a_s64q));
|
||||||
|
a_int = Q_GIVAL(a_s64q);
|
||||||
|
b_int = Q_GIVAL(b_s64q);
|
||||||
|
|
||||||
|
/* Q<op>Q testing. */
|
||||||
|
a_dbl = Q_Q2D(a_s64q);
|
||||||
|
b_dbl = Q_Q2D(b_s64q);
|
||||||
|
|
||||||
|
r_s64q = a_s64q;
|
||||||
|
error = Q_QSUBQ(&r_s64q, b_s64q);
|
||||||
|
ATF_CHECK_EQ(0, error);
|
||||||
|
|
||||||
|
r_dbl = a_dbl - b_dbl;
|
||||||
|
#ifdef notyet
|
||||||
|
maxe_dbl = 0.5;
|
||||||
|
#else
|
||||||
|
maxe_dbl = QTEST_FFACTOR;
|
||||||
|
#endif
|
||||||
|
delta_dbl = fabs(r_dbl - Q_Q2D(r_s64q));
|
||||||
|
ATF_CHECK_MSG(delta_dbl <= maxe_dbl,
|
||||||
|
"\tQSUBQ(%10f - %10f): |%10f - %10f| = %10f "
|
||||||
|
"(max err %f)\n",
|
||||||
|
Q_Q2D(a_s64q), Q_Q2D(b_s64q), Q_Q2D(r_s64q), r_dbl,
|
||||||
|
delta_dbl, maxe_dbl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test Q_QFRACI(3) by applying it to two random integers and comparing
|
||||||
|
* the result with its floating-point counterpart.
|
||||||
|
*/
|
||||||
|
ATF_TC_WITHOUT_HEAD(qfraci_s64q);
|
||||||
|
ATF_TC_BODY(qfraci_s64q, tc)
|
||||||
|
{
|
||||||
|
s64q_t a_s64q, b_s64q, r_s64q;
|
||||||
|
double a_dbl, b_dbl, r_dbl, maxe_dbl, delta_dbl;
|
||||||
|
int64_t a_int, b_int;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
srandomdev();
|
||||||
|
|
||||||
|
for (int i = 0; i < 10;) {
|
||||||
|
GENRAND(&a_s64q, INT64_MIN, UINT64_MAX);
|
||||||
|
GENRAND(&b_s64q, INT64_MIN, UINT64_MAX);
|
||||||
|
/*
|
||||||
|
* XXXLAS: Until Qmath handles precision normalisation, only
|
||||||
|
* test with equal precision.
|
||||||
|
*/
|
||||||
|
Q_SCVAL(b_s64q, Q_GCVAL(a_s64q));
|
||||||
|
a_int = Q_GIVAL(a_s64q);
|
||||||
|
b_int = Q_GIVAL(b_s64q);
|
||||||
|
|
||||||
|
/* Q<op>I testing. */
|
||||||
|
a_dbl = a_int;
|
||||||
|
b_dbl = b_int;
|
||||||
|
|
||||||
|
Q_INI(&r_s64q, 0, 0, Q_NFBITS(a_s64q));
|
||||||
|
error = Q_QFRACI(&r_s64q, a_int, b_int);
|
||||||
|
if (error == EOVERFLOW || error == ERANGE || error == EINVAL)
|
||||||
|
continue;
|
||||||
|
i++;
|
||||||
|
ATF_CHECK_EQ(0, error);
|
||||||
|
|
||||||
|
r_dbl = a_dbl / b_dbl;
|
||||||
|
maxe_dbl = fabs(1.0 / Q_NFBITS(a_s64q));
|
||||||
|
delta_dbl = fabs(r_dbl - Q_Q2D(r_s64q));
|
||||||
|
ATF_CHECK_MSG(delta_dbl <= maxe_dbl,
|
||||||
|
"\tQFRACI(%ld / %ld): |%10f - %10f| = %10f "
|
||||||
|
"(max err %f)\n",
|
||||||
|
a_int, b_int, Q_Q2D(r_s64q), r_dbl, delta_dbl,
|
||||||
|
maxe_dbl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test Q_QMULI(3) by applying it to a random Q number and a random integer
|
||||||
|
* and comparing the result with its floating-point counterpart.
|
||||||
|
*/
|
||||||
|
ATF_TC_WITHOUT_HEAD(qmuli_s64q);
|
||||||
|
ATF_TC_BODY(qmuli_s64q, tc)
|
||||||
|
{
|
||||||
|
s64q_t a_s64q, b_s64q, r_s64q;
|
||||||
|
double a_dbl, b_dbl, r_dbl, maxe_dbl, delta_dbl;
|
||||||
|
int64_t a_int, b_int;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
srandomdev();
|
||||||
|
|
||||||
|
for (int i = 0; i < 10;) {
|
||||||
|
GENRAND(&a_s64q, INT64_MIN, UINT64_MAX);
|
||||||
|
GENRAND(&b_s64q, INT64_MIN, UINT64_MAX);
|
||||||
|
/*
|
||||||
|
* XXXLAS: Until Qmath handles precision normalisation, only
|
||||||
|
* test with equal precision.
|
||||||
|
*/
|
||||||
|
Q_SCVAL(b_s64q, Q_GCVAL(a_s64q));
|
||||||
|
a_int = Q_GIVAL(a_s64q);
|
||||||
|
b_int = Q_GIVAL(b_s64q);
|
||||||
|
|
||||||
|
/* Q<op>I testing. */
|
||||||
|
a_dbl = a_int;
|
||||||
|
b_dbl = b_int;
|
||||||
|
|
||||||
|
Q_INI(&r_s64q, a_int, 0, Q_NFBITS(a_s64q));
|
||||||
|
error = Q_QMULI(&r_s64q, b_int);
|
||||||
|
if (error == EOVERFLOW || error == ERANGE)
|
||||||
|
continue;
|
||||||
|
i++;
|
||||||
|
ATF_CHECK_EQ(0, error);
|
||||||
|
|
||||||
|
r_dbl = a_dbl * b_dbl;
|
||||||
|
maxe_dbl = fabs((1.0 / Q_NFBITS(a_s64q)) * (double)b_int);
|
||||||
|
delta_dbl = fabs(r_dbl - Q_Q2D(r_s64q));
|
||||||
|
ATF_CHECK_MSG(delta_dbl <= maxe_dbl,
|
||||||
|
"\tQMULI(%ld * %ld): |%10f - %10f| = %10f "
|
||||||
|
"(max err %f)\n",
|
||||||
|
a_int, b_int, Q_Q2D(r_s64q), r_dbl, delta_dbl,
|
||||||
|
maxe_dbl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test Q_QADDI(3) by applying it to a random Q number and a random integer
|
||||||
|
* and comparing the result with its floating-point counterpart.
|
||||||
|
*/
|
||||||
|
ATF_TC_WITHOUT_HEAD(qaddi_s64q);
|
||||||
|
ATF_TC_BODY(qaddi_s64q, tc)
|
||||||
|
{
|
||||||
|
s64q_t a_s64q, b_s64q, r_s64q;
|
||||||
|
double a_dbl, b_dbl, r_dbl, maxe_dbl, delta_dbl;
|
||||||
|
int64_t a_int, b_int;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
srandomdev();
|
||||||
|
|
||||||
|
for (int i = 0; i < 10;) {
|
||||||
|
GENRAND(&a_s64q, INT64_MIN, UINT64_MAX);
|
||||||
|
GENRAND(&b_s64q, INT64_MIN, UINT64_MAX);
|
||||||
|
/*
|
||||||
|
* XXXLAS: Until Qmath handles precision normalisation, only
|
||||||
|
* test with equal precision.
|
||||||
|
*/
|
||||||
|
Q_SCVAL(b_s64q, Q_GCVAL(a_s64q));
|
||||||
|
a_int = Q_GIVAL(a_s64q);
|
||||||
|
b_int = Q_GIVAL(b_s64q);
|
||||||
|
|
||||||
|
/* Q<op>I testing. */
|
||||||
|
a_dbl = a_int;
|
||||||
|
b_dbl = b_int;
|
||||||
|
|
||||||
|
Q_INI(&r_s64q, a_int, 0, Q_NFBITS(a_s64q));
|
||||||
|
error = Q_QADDI(&r_s64q, b_int);
|
||||||
|
if (error == EOVERFLOW || error == ERANGE)
|
||||||
|
continue;
|
||||||
|
i++;
|
||||||
|
ATF_CHECK_EQ(0, error);
|
||||||
|
|
||||||
|
r_dbl = a_dbl + b_dbl;
|
||||||
|
#ifdef notyet
|
||||||
|
maxe_dbl = 0.5;
|
||||||
|
#else
|
||||||
|
maxe_dbl = QTEST_FFACTOR;
|
||||||
|
#endif
|
||||||
|
delta_dbl = fabs(r_dbl - Q_Q2D(r_s64q));
|
||||||
|
ATF_CHECK_MSG(delta_dbl <= maxe_dbl,
|
||||||
|
"\tQADDI(%ld + %ld): |%10f - %10f| = %10f "
|
||||||
|
"(max err %f)\n",
|
||||||
|
a_int, b_int, Q_Q2D(r_s64q), r_dbl, delta_dbl,
|
||||||
|
maxe_dbl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test Q_QSUBI(3) by applying it to a random Q number and a random integer
|
||||||
|
* and comparing the result with its floating-point counterpart.
|
||||||
|
*/
|
||||||
|
ATF_TC_WITHOUT_HEAD(qsubi_s64q);
|
||||||
|
ATF_TC_BODY(qsubi_s64q, tc)
|
||||||
|
{
|
||||||
|
s64q_t a_s64q, b_s64q, r_s64q;
|
||||||
|
double a_dbl, b_dbl, r_dbl, maxe_dbl, delta_dbl;
|
||||||
|
int64_t a_int, b_int;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
srandomdev();
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
GENRAND(&a_s64q, INT64_MIN, UINT64_MAX);
|
||||||
|
GENRAND(&b_s64q, INT64_MIN, UINT64_MAX);
|
||||||
|
/*
|
||||||
|
* XXXLAS: Until Qmath handles precision normalisation, only
|
||||||
|
* test with equal precision.
|
||||||
|
*/
|
||||||
|
Q_SCVAL(b_s64q, Q_GCVAL(a_s64q));
|
||||||
|
a_int = Q_GIVAL(a_s64q);
|
||||||
|
b_int = Q_GIVAL(b_s64q);
|
||||||
|
|
||||||
|
/* Q<op>I testing. */
|
||||||
|
a_dbl = a_int;
|
||||||
|
b_dbl = b_int;
|
||||||
|
|
||||||
|
Q_INI(&r_s64q, a_int, 0, Q_NFBITS(a_s64q));
|
||||||
|
error = Q_QSUBI(&r_s64q, b_int);
|
||||||
|
ATF_CHECK_EQ(0, error);
|
||||||
|
|
||||||
|
r_dbl = a_dbl - b_dbl;
|
||||||
|
#ifdef notyet
|
||||||
|
maxe_dbl = 0.5;
|
||||||
|
#else
|
||||||
|
maxe_dbl = QTEST_FFACTOR;
|
||||||
|
#endif
|
||||||
|
delta_dbl = fabs(r_dbl - Q_Q2D(r_s64q));
|
||||||
|
ATF_CHECK_MSG(delta_dbl <= maxe_dbl,
|
||||||
|
"\tQSUBI(%ld - %ld): |%10f - %10f| = %10f "
|
||||||
|
"(max err %f)\n",
|
||||||
|
a_int, b_int, Q_Q2D(r_s64q), r_dbl, delta_dbl,
|
||||||
|
maxe_dbl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate area of a circle with r=42.
|
||||||
|
*/
|
||||||
|
ATF_TC_WITHOUT_HEAD(circle_u64q);
|
||||||
|
ATF_TC_BODY(circle_u64q, tc)
|
||||||
|
{
|
||||||
|
char buf[128];
|
||||||
|
u64q_t a, pi, r;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
Q_INI(&a, 0, 0, 16);
|
||||||
|
Q_INI(&pi, 3, 14159, 16);
|
||||||
|
Q_INI(&r, 4, 2, 16);
|
||||||
|
|
||||||
|
error = Q_QCLONEQ(&a, r);
|
||||||
|
ATF_CHECK_EQ(0, error);
|
||||||
|
error = Q_QMULQ(&a, r);
|
||||||
|
ATF_CHECK_EQ(0, error);
|
||||||
|
error = Q_QMULQ(&a, pi);
|
||||||
|
ATF_CHECK_EQ(0, error);
|
||||||
|
|
||||||
|
Q_TOSTR(a, -1, 10, buf, sizeof(buf));
|
||||||
|
ATF_CHECK_STREQ("55.4174804687500000", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
ATF_TP_ADD_TCS(tp)
|
||||||
|
{
|
||||||
|
|
||||||
|
ATF_TP_ADD_TC(tp, basic_s8q);
|
||||||
|
ATF_TP_ADD_TC(tp, basic_s16q);
|
||||||
|
ATF_TP_ADD_TC(tp, basic_s32q);
|
||||||
|
ATF_TP_ADD_TC(tp, basic_s64q);
|
||||||
|
ATF_TP_ADD_TC(tp, basic_u8q);
|
||||||
|
ATF_TP_ADD_TC(tp, basic_u16q);
|
||||||
|
ATF_TP_ADD_TC(tp, basic_u32q);
|
||||||
|
ATF_TP_ADD_TC(tp, basic_u64q);
|
||||||
|
|
||||||
|
ATF_TP_ADD_TC(tp, qmulq_s64q);
|
||||||
|
ATF_TP_ADD_TC(tp, qdivq_s64q);
|
||||||
|
ATF_TP_ADD_TC(tp, qaddq_s64q);
|
||||||
|
ATF_TP_ADD_TC(tp, qsubq_s64q);
|
||||||
|
ATF_TP_ADD_TC(tp, qfraci_s64q);
|
||||||
|
ATF_TP_ADD_TC(tp, qmuli_s64q);
|
||||||
|
ATF_TP_ADD_TC(tp, qaddi_s64q);
|
||||||
|
ATF_TP_ADD_TC(tp, qsubi_s64q);
|
||||||
|
|
||||||
|
ATF_TP_ADD_TC(tp, circle_u64q);
|
||||||
|
|
||||||
|
return (atf_no_error());
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user