Page MenuHomeFreeBSD

D20116.diff
No OneTemporary

D20116.diff

Index: head/lib/msun/man/math.3
===================================================================
--- head/lib/msun/man/math.3
+++ head/lib/msun/man/math.3
@@ -217,6 +217,7 @@
.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
Index: head/share/man/man3/Makefile
===================================================================
--- head/share/man/man3/Makefile
+++ head/share/man/man3/Makefile
@@ -13,6 +13,16 @@
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+= 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 \
Index: head/share/man/man3/Q_FRAWMASK.3
===================================================================
--- head/share/man/man3/Q_FRAWMASK.3
+++ head/share/man/man3/Q_FRAWMASK.3
@@ -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.
Index: head/share/man/man3/Q_IFRAWMASK.3
===================================================================
--- head/share/man/man3/Q_IFRAWMASK.3
+++ head/share/man/man3/Q_IFRAWMASK.3
@@ -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.
Index: head/share/man/man3/Q_INI.3
===================================================================
--- head/share/man/man3/Q_INI.3
+++ head/share/man/man3/Q_INI.3
@@ -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.
Index: head/share/man/man3/Q_IRAWMASK.3
===================================================================
--- head/share/man/man3/Q_IRAWMASK.3
+++ head/share/man/man3/Q_IRAWMASK.3
@@ -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.
Index: head/share/man/man3/Q_QABS.3
===================================================================
--- head/share/man/man3/Q_QABS.3
+++ head/share/man/man3/Q_QABS.3
@@ -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.
Index: head/share/man/man3/Q_QADDI.3
===================================================================
--- head/share/man/man3/Q_QADDI.3
+++ head/share/man/man3/Q_QADDI.3
@@ -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.
Index: head/share/man/man3/Q_QADDQ.3
===================================================================
--- head/share/man/man3/Q_QADDQ.3
+++ head/share/man/man3/Q_QADDQ.3
@@ -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.
Index: head/share/man/man3/Q_SIGNED.3
===================================================================
--- head/share/man/man3/Q_SIGNED.3
+++ head/share/man/man3/Q_SIGNED.3
@@ -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.
Index: head/share/man/man3/Q_SIGNSHFT.3
===================================================================
--- head/share/man/man3/Q_SIGNSHFT.3
+++ head/share/man/man3/Q_SIGNSHFT.3
@@ -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.
Index: head/share/man/man3/qmath.3
===================================================================
--- head/share/man/man3/qmath.3
+++ head/share/man/man3/qmath.3
@@ -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.
Index: head/sys/sys/qmath.h
===================================================================
--- head/sys/sys/qmath.h
+++ head/sys/sys/qmath.h
@@ -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_ */
Index: head/tests/sys/sys/Makefile
===================================================================
--- head/tests/sys/sys/Makefile
+++ head/tests/sys/sys/Makefile
@@ -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
Index: head/tests/sys/sys/qmath_test.c
===================================================================
--- head/tests/sys/sys/qmath_test.c
+++ head/tests/sys/sys/qmath_test.c
@@ -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());
+}

File Metadata

Mime Type
text/plain
Expires
Fri, Feb 14, 11:24 AM (21 h, 23 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16641797
Default Alt Text
D20116.diff (91 KB)

Event Timeline