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
773a8248cc
commit
8914da68f6
@ -217,6 +217,7 @@ rarely, and then only in very-close-to-halfway cases.
|
||||
.Xr complex 3 ,
|
||||
.Xr fenv 3 ,
|
||||
.Xr ieee 3 ,
|
||||
.Xr qmath 3 ,
|
||||
.Xr tgmath 3
|
||||
.Sh HISTORY
|
||||
A math library with many of the present functions appeared in
|
||||
|
@ -13,6 +13,16 @@ MAN= assert.3 \
|
||||
makedev.3 \
|
||||
offsetof.3 \
|
||||
${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 \
|
||||
sigevent.3 \
|
||||
siginfo.3 \
|
||||
@ -72,6 +82,68 @@ MLINKS+= fpgetround.3 fpgetmask.3 \
|
||||
MLINKS+= makedev.3 major.3 \
|
||||
makedev.3 minor.3
|
||||
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 \
|
||||
queue.3 LIST_CLASS_HEAD.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
|
||||
|
||||
ATF_TESTS_C= bitstring_test rb_test splay_test
|
||||
ATF_TESTS_C= bitstring_test qmath_test rb_test splay_test
|
||||
|
||||
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