Index: lib/msun/man/math.3 =================================================================== --- lib/msun/man/math.3 +++ 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: share/man/man3/Makefile =================================================================== --- share/man/man3/Makefile +++ share/man/man3/Makefile @@ -15,6 +15,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 \ @@ -74,6 +84,67 @@ 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 +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: share/man/man3/Q_FRAWMASK.3 =================================================================== --- /dev/null +++ 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: share/man/man3/Q_IFRAWMASK.3 =================================================================== --- /dev/null +++ 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: share/man/man3/Q_INI.3 =================================================================== --- /dev/null +++ share/man/man3/Q_INI.3 @@ -0,0 +1,236 @@ +.\" +.\" 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" "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" +.Sh DESCRIPTION +.Fn Q_INI +initialises a Q number with the supplied integral value +.Fa iv +and with appropriate control bits based on the requested radix shift point +.Fa rpshft . +.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 +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. +.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: share/man/man3/Q_IRAWMASK.3 =================================================================== --- /dev/null +++ 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: share/man/man3/Q_QABS.3 =================================================================== --- /dev/null +++ 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: share/man/man3/Q_QADDI.3 =================================================================== --- /dev/null +++ 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: share/man/man3/Q_QADDQ.3 =================================================================== --- /dev/null +++ share/man/man3/Q_QADDQ.3 @@ -0,0 +1,172 @@ +.\" +.\" 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 . +.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. +.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: share/man/man3/Q_SIGNED.3 =================================================================== --- /dev/null +++ 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: share/man/man3/Q_SIGNSHFT.3 =================================================================== --- /dev/null +++ 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: share/man/man3/qmath.3 =================================================================== --- /dev/null +++ share/man/man3/qmath.3 @@ -0,0 +1,382 @@ +.\" +.\" 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 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 +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 +.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; + +a = pi = Q_INI(&r, 0, 16); + +Q_SIFVALS(pi, 3, 14159); +Q_SIFVALS(r, 4, 2); + +Q_QCLONEQ(&a, r); +Q_QMULQ(&a, r); +Q_QMULQ(&a, pi); + +printf("%lu.%lu\\n", Q_GIVAL(a), Q_GFVAL(a)); +.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, 8); +Q_QFRACI(&s32, 5, 3); +char buf[Q_MAXSTRLEN(s32)]; +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: sys/sys/qmath.h =================================================================== --- /dev/null +++ sys/sys/qmath.h @@ -0,0 +1,603 @@ +/*- + * 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 + * + * 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 + +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 _bpb = Q_BITSPERBASEUP(base); \ + int _nfbits = Q_NFBITS(q); \ + /* \ + * Normalise enough MSBs to yield the next digit, multiply by the \ + * base, and truncate residual fractional bits post multiplication. \ + */ \ + int _idx = (((bits) >> (_bpb >= _nfbits ? 0 : _nfbits - _bpb)) * \ + (base)) >> (_nfbits > _bpb ? _bpb : _nfbits); \ + (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) && ((long)(slen)) > 0) \ + *_s++ = '-'; \ + Q_BT(q) _part = Q_GIABSVAL(q); \ + _r = _s; \ + do { \ + /* Render integer chars in reverse order. */ \ + if ((_s - (s)) < ((long)(slen))) \ + *_s++ = Q_IBITS2CH(q, _part, base); \ + else \ + _r = NULL; \ + } while (_part > 0 && _r); \ + if (!((_s - (s)) < ((long)(slen)))) \ + _r = NULL; \ + _i = (_s - _r) >> 1; /* N digits requires int(N/2) swaps. */ \ + while (_i-- > 0 && _r) { \ + /* 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) { \ + if ((_s - (s)) < ((long)(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) { \ + /* Render fraction chars in correct order. */ \ + if ((_s - (s)) < ((long)(slen))) \ + *_s++ = Q_FBITS2CH(q, _part, base); \ + else \ + _r = NULL; \ + } \ + } \ + if ((_s - (s)) < ((long)(slen)) && _r) \ + *_s = '\0'; \ + else { \ + _r = NULL; \ + if (((long)(slen)) > 0) \ + *(s) = '\0'; \ + } \ + /* Return a pointer to the '\0' or NULL on overflow. */ \ + (_r ? _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))) + +/* + * Initialise 'q' with raw integer value 'iv' 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, rpshft) \ +({ \ + (*(q)) = Q_CTRLINI(rpshft); \ + Q_SIFVALS(*(q), iv, 0); \ +}) + +/* 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: tests/sys/sys/Makefile =================================================================== --- tests/sys/sys/Makefile +++ 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: tests/sys/sys/qmath_test.c =================================================================== --- /dev/null +++ tests/sys/sys/qmath_test.c @@ -0,0 +1,615 @@ +/*- + * 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 + */ + +#include +#include + +#include +#include +#include +#include + +#include + +#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_NEG(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); \ +}) + +ATF_TC_WITHOUT_HEAD(basic_s8q); +ATF_TC_BODY(basic_s8q, tc) +{ + char buf[128]; + s8q_t s8; + + Q_INI(&s8, QTEST_IV, 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, 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, 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, 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, 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, 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, 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, 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)); +} + +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); + + /* QQ 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); + } +} + +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); + + /* QQ 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); + } +} + +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); + + /* QQ 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); + } +} + +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); + + /* QQ 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); + } +} + +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); + + /* QI testing. */ + a_dbl = a_int; + b_dbl = b_int; + + Q_INI(&r_s64q, 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); + } +} + +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); + + /* QI testing. */ + a_dbl = a_int; + b_dbl = b_int; + + Q_INI(&r_s64q, a_int, 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); + } +} + +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); + + /* QI testing. */ + a_dbl = a_int; + b_dbl = b_int; + + Q_INI(&r_s64q, a_int, 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); + } +} + +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); + + /* QI testing. */ + a_dbl = a_int; + b_dbl = b_int; + + Q_INI(&r_s64q, a_int, 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); + } +} + +ATF_TC_WITHOUT_HEAD(circle_u64q); +ATF_TC_BODY(circle_u64q, tc) +{ + char buf[128]; + u64q_t a, pi, r; + int error; + + a = pi = Q_INI(&r, 0, 16); + + Q_SIFVALS(pi, 3, 14159); + Q_SIFVALS(r, 4, 2); + + 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("51.4575652075161875", 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()); +}