if(CMAKE_VERSION VERSION_LESS "3.6")
message(ERROR "clang-tidy support requires cmake 3.6.")
endif()
- set_target_properties(libgromacs PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_EXE};--checks=\
- -clang-analyzer-security.insecureAPI.strcpy,\
- bugprone-*,misc-*,readability-*,performance-*,mpi-*,\
- -misc-misplaced-widening-cast,-readability-named-parameter,\
- -misc-misplaced-const,\
- -misc-incorrect-roundings,-misc-macro-parentheses,-readability-function-size,-readability-else-after-return,\
- -readability-inconsistent-declaration-parameter-name,-misc-throw-by-value-catch-by-reference,\
- -readability-implicit-bool-conversion,\
- modernize-use-nullptr,modernize-use-emplace;-warnings-as-errors=*;-fix")
+ set(CLANG_TIDY_CHECKS
+ "-clang-analyzer-security.insecureAPI.strcpy"
+ "bugprone-*" "misc-*" "readability-*" "performance-*" "mpi-*"
+ "-misc-misplaced-widening-cast"
+ "-misc-misplaced-const"
+ "-misc-incorrect-roundings" #TODO: #2562
+ "-readability-else-after-return"
+ "-readability-inconsistent-declaration-parameter-name"
+ "-readability-implicit-bool-conversion" #TODO: Remove gmx_bool
+ "modernize-use-nullptr" "modernize-use-emplace"
+ )
+ string(REPLACE ";" "," CLANG_TIDY_CHECKS "${CLANG_TIDY_CHECKS}")
+ set_target_properties(libgromacs PROPERTIES CXX_CLANG_TIDY
+ "${CLANG_TIDY_EXE};--checks=${CLANG_TIDY_CHECKS};-warnings-as-errors=*;-fix")
endif()
gmx_write_installed_header_list()
/*! \brief Returns the MPI rank of the domain decomposition master rank */
-#define DDMASTERRANK(dd) (dd->masterrank)
+#define DDMASTERRANK(dd) ((dd)->masterrank)
/*! \brief Move data of type \p T in the communication region one cell along
* This code does not assume any memory alignment for the grid.
*/
RVec
- operator()(std::integral_constant<int, 4>) const
+ operator()(std::integral_constant<int, 4> /*unused*/) const
{
const int norder = nn*4;
/* Pointer arithmetic alert, next six statements */
#ifdef PME_SIMD4_SPREAD_GATHER
/* Load order elements from unaligned memory into two 4-wide SIMD */
template<int order>
- static inline void loadOrderU(const real* data, std::integral_constant<int, order>,
+ static inline void loadOrderU(const real* data, std::integral_constant<int, order> /*unused*/,
int offset, Simd4Real* S0, Simd4Real* S1)
{
#ifdef PME_SIMD4_UNALIGNED
#include "pme-gpu-program-impl.h"
-PmeGpuProgramImpl::PmeGpuProgramImpl(const gmx_device_info_t *) {};
+PmeGpuProgramImpl::PmeGpuProgramImpl(const gmx_device_info_t * /*unused*/) {};
PmeGpuProgramImpl::~PmeGpuProgramImpl() = default;
#if defined PME_SIMD_SOLVE
/* Calculate exponentials through SIMD */
-inline static void calc_exponentials_q(int, int, real f, ArrayRef<const SimdReal> d_aligned, ArrayRef<const SimdReal> r_aligned, ArrayRef<SimdReal> e_aligned)
+inline static void calc_exponentials_q(int /*unused*/, int /*unused*/, real f, ArrayRef<const SimdReal> d_aligned, ArrayRef<const SimdReal> r_aligned, ArrayRef<SimdReal> e_aligned)
{
{
SimdReal f_simd(f);
#if defined PME_SIMD_SOLVE
/* Calculate exponentials through SIMD */
-inline static void calc_exponentials_lj(int, int, ArrayRef<SimdReal> r_aligned, ArrayRef<SimdReal> factor_aligned, ArrayRef<SimdReal> d_aligned)
+inline static void calc_exponentials_lj(int /*unused*/, int /*unused*/, ArrayRef<SimdReal> r_aligned, ArrayRef<SimdReal> factor_aligned, ArrayRef<SimdReal> d_aligned)
{
SimdReal tmp_r, tmp_d, tmp_fac, d_inv, tmp_mk;
const SimdReal sqr_PI = sqrt(SimdReal(M_PI));
dr = xptr[j]; \
\
/* dr is relative offset from lower cell limit */ \
- data[order-1] = 0; \
- data[1] = dr; \
- data[0] = 1 - dr; \
+ data[(order)-1] = 0; \
+ data[1] = dr; \
+ data[0] = 1 - dr; \
\
- for (int k = 3; (k < order); k++) \
+ for (int k = 3; (k < (order)); k++) \
{ \
div = 1.0/(k - 1.0); \
data[k-1] = div*dr*data[k-2]; \
data[0] = div*(1-dr)*data[0]; \
} \
/* differentiate */ \
- dtheta[j][i*order+0] = -data[0]; \
- for (int k = 1; (k < order); k++) \
+ dtheta[j][i*(order)+0] = -data[0]; \
+ for (int k = 1; (k < (order)); k++) \
{ \
- dtheta[j][i*order+k] = data[k-1] - data[k]; \
+ dtheta[j][i*(order)+k] = data[k-1] - data[k]; \
} \
\
- div = 1.0/(order - 1); \
- data[order-1] = div*dr*data[order-2]; \
- for (int l = 1; (l < (order-1)); l++) \
+ div = 1.0/((order) - 1); \
+ data[(order)-1] = div*dr*data[(order)-2]; \
+ for (int l = 1; (l < ((order)-1)); l++) \
{ \
- data[order-l-1] = div*((dr+l)*data[order-l-2]+ \
- (order-l-dr)*data[order-l-1]); \
+ data[(order)-l-1] = div*((dr+l)*data[(order)-l-2]+ \
+ ((order)-l-dr)*data[(order)-l-1]); \
} \
data[0] = div*(1 - dr)*data[0]; \
\
- for (int k = 0; k < order; k++) \
+ for (int k = 0; k < (order); k++) \
{ \
- theta[j][i*order+k] = data[k]; \
+ theta[j][i*(order)+k] = data[k]; \
} \
} \
}
/* This has to be a macro to enable full compiler optimization with xlC (and probably others too) */
#define DO_BSPLINE(order) \
- for (ithx = 0; (ithx < order); ithx++) \
+ for (ithx = 0; (ithx < (order)); ithx++) \
{ \
index_x = (i0+ithx)*pny*pnz; \
valx = coefficient*thx[ithx]; \
\
- for (ithy = 0; (ithy < order); ithy++) \
+ for (ithy = 0; (ithy < (order)); ithy++) \
{ \
valxy = valx*thy[ithy]; \
index_xy = index_x+(j0+ithy)*pnz; \
\
- for (ithz = 0; (ithz < order); ithz++) \
+ for (ithz = 0; (ithz < (order)); ithz++) \
{ \
index_xyz = index_xy+(k0+ithz); \
grid[index_xyz] += valxy*thz[ithz]; \
| with some routines to assist in this task (those are marked
| static and cannot be called from user programs)
*/
-#define MAXABS INT_MAX-2
+#define MAXABS (INT_MAX-2)
#ifndef SQR
#define SQR(x) ((x)*(x))
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2014,2015,2018, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
#define SET(a, b, c, d, k, s, Ti) \
- t = a + F(b, c, d) + X[k] + Ti; \
- a = ROTATE_LEFT(t, s) + b
+ t = (a) + F(b, c, d) + X[k] + (Ti); \
+ (a) = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 0, 7, T1);
SET(d, a, b, c, 1, 12, T2);
a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
#define SET(a, b, c, d, k, s, Ti) \
- t = a + G(b, c, d) + X[k] + Ti; \
- a = ROTATE_LEFT(t, s) + b
+ t = (a) + G(b, c, d) + X[k] + (Ti); \
+ (a) = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 1, 5, T17);
SET(d, a, b, c, 6, 9, T18);
a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define SET(a, b, c, d, k, s, Ti) \
- t = a + H(b, c, d) + X[k] + Ti; \
- a = ROTATE_LEFT(t, s) + b
+ t = (a) + H(b, c, d) + X[k] + (Ti); \
+ (a) = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 5, 4, T33);
SET(d, a, b, c, 8, 11, T34);
a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
#define SET(a, b, c, d, k, s, Ti) \
- t = a + I(b, c, d) + X[k] + Ti; \
- a = ROTATE_LEFT(t, s) + b
+ t = (a) + I(b, c, d) + X[k] + (Ti); \
+ (a) = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 0, 6, T49);
SET(d, a, b, c, 7, 10, T50);
v = as_rvec_array(state->v.data());
}
-#define do_test(fio, b, p) if (bRead && (p != NULL) && !b) gmx_fatal(FARGS, "No %s in %s",#p, gmx_fio_getname(fio))
+#define do_test(fio, b, p) if (bRead && ((p) != NULL) && !(b)) gmx_fatal(FARGS, "No %s in %s",#p, gmx_fio_getname(fio))
do_test(fio, tpx.bBox, state->box);
if (tpx.bBox)
#define NPP asize(map)
int x, y;
-#define INDEX(ppp) (((static_cast<int> (360+ppp*RAD2DEG)) % 360)/6)
+#define INDEX(ppp) (((static_cast<int> (360+(ppp)*RAD2DEG)) % 360)/6)
x = INDEX(phi);
y = INDEX(psi);
#undef INDEX
#include "gromacs/utility/smalloc.h"
#define e2d(x) ENM2DEBYE*(x)
-#define EANG2CM E_CHARGE*1.0e-10 /* e Angstrom to Coulomb meter */
-#define CM2D SPEED_OF_LIGHT*1.0e+24 /* Coulomb meter to Debye */
+#define EANG2CM (E_CHARGE*1.0e-10) /* e Angstrom to Coulomb meter */
+#define CM2D (SPEED_OF_LIGHT*1.0e+24) /* Coulomb meter to Debye */
typedef struct {
int nelem;
* the individual components on the diagonal.
*/
-#define delta(a, b) (( a == b ) ? 1.0 : 0.0)
+#define delta(a, b) (( (a) == (b) ) ? 1.0 : 0.0)
for (m = 0; (m < DIM); m++)
{
*/
#define SWAP(i) \
- if (dd[i+1] > dd[i]) { \
- tmp = dd[i]; \
- dd[i] = dd[i+1]; \
- dd[i+1] = tmp; \
+ if (dd[(i)+1] > dd[i]) { \
+ tmp = dd[i]; \
+ dd[i] = dd[(i)+1]; \
+ dd[(i)+1] = tmp; \
}
SWAP(0);
SWAP(1);
if (timecheck == 0)
{
-#define DONTSKIP(cnt) (skip) ? ((cnt % skip) == 0) : TRUE
+#define DONTSKIP(cnt) (skip) ? (((cnt) % skip) == 0) : TRUE
if (bCont)
{
#define HB_NO 0
#define HB_YES 1<<0
#define HB_INS 1<<1
-#define HB_YESINS HB_YES|HB_INS
+#define HB_YESINS (HB_YES|HB_INS)
#define HB_NR (1<<2)
#define MAXHYDRO 4
hb->nframes = nframes;
}
-#define OFFSET(frame) (frame / 32)
-#define MASK(frame) (1 << (frame % 32))
+#define OFFSET(frame) ((frame) / 32)
+#define MASK(frame) (1 << ((frame) % 32))
static void _set_hb(unsigned int hbexist[], unsigned int frame, gmx_bool bValue)
{
char **legnames;
char buf[STRLEN];
-#define USE_THIS_GROUP(j) ( (j == gr0) || (bTwo && (j == gr1)) )
+#define USE_THIS_GROUP(j) ( ((j) == gr0) || (bTwo && ((j) == gr1)) )
fp = xvgropen(opt2fn("-dan", NFILE, fnm),
"Donors and Acceptors", output_env_get_xvgr_tlabel(oenv), "Count", oenv);
/* Sort eigenvalues in ascending order */
#define SWAPPER(i) \
- if (std::abs(dd[i+1]) < std::abs(dd[i])) { \
+ if (std::abs(dd[(i)+1]) < std::abs(dd[i])) { \
temp = dd[i]; \
for (j = 0; (j < NDIM); j++) { tvec[j] = ev[j][i]; } \
- dd[i] = dd[i+1]; \
- for (j = 0; (j < NDIM); j++) { ev[j][i] = ev[j][i+1]; } \
- dd[i+1] = temp; \
- for (j = 0; (j < NDIM); j++) { ev[j][i+1] = tvec[j]; } \
+ dd[i] = dd[(i)+1]; \
+ for (j = 0; (j < NDIM); j++) { ev[j][i] = ev[j][(i)+1]; } \
+ dd[(i)+1] = temp; \
+ for (j = 0; (j < NDIM); j++) { ev[j][(i)+1] = tvec[j]; } \
}
SWAPPER(0)
SWAPPER(1)
#define PVEC(str, v) fprintf(log, \
"%s[X]: %10.5e %s[Y]: %10.5e %s[Z]: %10.5e\n", \
- str, v[0], str, v[1], str, v[2])
+ str, (v)[0], str, (v)[1], str, (v)[2])
#ifdef DEBUG
PVEC("xcm", xcm);
PVEC("acm", acm);
/* cosine rule: a^2 = b^2 + c^2 - 2 b c cos(alpha) */
/* get a^2 when a, b and alpha are given: */
-#define cosrule(b, c, alpha) ( gmx::square(b) + gmx::square(c) - 2*b*c*std::cos(alpha) )
+#define cosrule(b, c, alpha) ( gmx::square(b) + gmx::square(c) - 2*(b)*(c)*std::cos(alpha) )
/* get cos(alpha) when a, b and c are given: */
-#define acosrule(a, b, c) ( (gmx::square(b)+gmx::square(c)-gmx::square(a))/(2*b*c) )
+#define acosrule(a, b, c) ( (gmx::square(b)+gmx::square(c)-gmx::square(a))/(2*(b)*(c)) )
static int gen_vsites_6ring(t_atoms *at, int *vsite_type[], t_params plist[],
int nrfound, int *ats, real bond_cc, real bond_ch,
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2011,2014,2015,2017, by the GROMACS development team, led by
+ * Copyright (c) 2011,2014,2015,2017,2018, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
}
}
-#define safe_strdup(str) ((str != NULL) ? gmx_strdup(str) : NULL)
+#define safe_strdup(str) (((str) != NULL) ? gmx_strdup(str) : NULL)
static void copy_t_rbonded(t_rbonded *s, t_rbonded *d)
{
#include "gromacs/utility/strdb.h"
/* use bonded types definitions in hackblock.h */
-#define ekwRepl ebtsNR+1
-#define ekwAdd ebtsNR+2
-#define ekwDel ebtsNR+3
+#define ekwRepl (ebtsNR+1)
+#define ekwAdd (ebtsNR+2)
+#define ekwDel (ebtsNR+3)
#define ekwNR 3
const char *kw_names[ekwNR] = {
"replace", "add", "delete"
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2017, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2017,2018, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Since GPU support is not configured, there is no host memory to
* allocate. */
-void gpu_set_host_malloc_and_free(bool,
+void gpu_set_host_malloc_and_free(bool /*unused*/,
gmx_host_alloc_t **nb_alloc,
gmx_host_free_t **nb_free)
{
--- /dev/null
+CheckOptions:
+ - key: readability-function-size.StatementThreshold
+ value: 2000
Simd4Float d2x, d2y, d2z; \
Simd4Float d2s, d2t; \
\
- shi = si*NNBSBB_D*DIM; \
+ shi = (si)*NNBSBB_D*DIM; \
\
- xi_l = load4(bb_i+shi+0*STRIDE_PBB); \
- yi_l = load4(bb_i+shi+1*STRIDE_PBB); \
- zi_l = load4(bb_i+shi+2*STRIDE_PBB); \
- xi_h = load4(bb_i+shi+3*STRIDE_PBB); \
- yi_h = load4(bb_i+shi+4*STRIDE_PBB); \
- zi_h = load4(bb_i+shi+5*STRIDE_PBB); \
+ xi_l = load4((bb_i)+shi+0*STRIDE_PBB); \
+ yi_l = load4((bb_i)+shi+1*STRIDE_PBB); \
+ zi_l = load4((bb_i)+shi+2*STRIDE_PBB); \
+ xi_h = load4((bb_i)+shi+3*STRIDE_PBB); \
+ yi_h = load4((bb_i)+shi+4*STRIDE_PBB); \
+ zi_h = load4((bb_i)+shi+5*STRIDE_PBB); \
\
dx_0 = xi_l - xj_h; \
dy_0 = yi_l - yj_h; \
d2s = d2x + d2y; \
d2t = d2s + d2z; \
\
- store4(d2+si, d2t); \
+ store4((d2)+(si), d2t); \
}
/* 4-wide SIMD code for nsi bb distances for bb format xxxxyyyyzzzz */
//! The values to try when switching
const int nstlist_try[] = { 20, 25, 40, 50, 80, 100 };
//! Number of elements in the neighborsearch list trials.
-#define NNSTL sizeof(nstlist_try)/sizeof(nstlist_try[0])
+#define NNSTL (sizeof(nstlist_try)/sizeof(nstlist_try[0]))
/* Increase nstlist until the size of the pair-list increased by
* \p c_nbnxnListSizeFactor??? or more, but never more than
* \p c_nbnxnListSizeFactor??? + \p c_nbnxnListSizeFactorMargin.
}
-#define calc_dx2(XI, YI, ZI, y) (gmx::square(XI-y[XX]) + gmx::square(YI-y[YY]) + gmx::square(ZI-y[ZZ]))
-#define calc_cyl_dx2(XI, YI, y) (gmx::square(XI-y[XX]) + gmx::square(YI-y[YY]))
+#define calc_dx2(XI, YI, ZI, y) (gmx::square((XI)-(y)[XX]) + gmx::square((YI)-(y)[YY]) + gmx::square((ZI)-(y)[ZZ]))
+#define calc_cyl_dx2(XI, YI, y) (gmx::square((XI)-(y)[XX]) + gmx::square((YI)-(y)[YY]))
/****************************************************
*
* F A S T N E I G H B O R S E A R C H I N G
gmx_fatal(FARGS, "Trying to print nonexistent graph (file %s, line %d)",
file, line);
}
-#define GCHECK(g) if (g == NULL) g_error(__LINE__, __FILE__)
+#define GCHECK(g) if ((g) == NULL) g_error(__LINE__, __FILE__)
void p_graph(FILE *log, const char *title, t_graph *g)
{
#endif
/* Shortcuts for often used queries */
-#define ISFLEX(rg) ( (rg->eType == erotgFLEX) || (rg->eType == erotgFLEXT) || (rg->eType == erotgFLEX2) || (rg->eType == erotgFLEX2T) )
-#define ISCOLL(rg) ( (rg->eType == erotgFLEX) || (rg->eType == erotgFLEXT) || (rg->eType == erotgFLEX2) || (rg->eType == erotgFLEX2T) || (rg->eType == erotgRMPF) || (rg->eType == erotgRM2PF) )
+#define ISFLEX(rg) ( ((rg)->eType == erotgFLEX) || ((rg)->eType == erotgFLEXT) || ((rg)->eType == erotgFLEX2) || ((rg)->eType == erotgFLEX2T) )
+#define ISCOLL(rg) ( ((rg)->eType == erotgFLEX) || ((rg)->eType == erotgFLEXT) || ((rg)->eType == erotgFLEX2) || ((rg)->eType == erotgFLEX2T) || ((rg)->eType == erotgRMPF) || ((rg)->eType == erotgRM2PF) )
/* Does any of the rotation groups use slab decomposition? */
/* Determine the 'home' slab of this atom which is the
* slab with the highest Gaussian weight of all */
-#define round(a) (int)(a+0.5)
+#define round(a) (int)((a)+0.5)
static inline int get_homeslab(
rvec curr_x, /* The position for which the home slab shall be determined */
rvec rotvec, /* The rotation vector */
old_t1 = fr.time;
j++;
new_natoms = fr.natoms;
-#define INC(s, n, f, l, item) if (s.item != 0) { if (n.item == 0) { first.item = fr.time; } last.item = fr.time; n.item++; \
+#define INC(s, n, f, l, item) if ((s).item != 0) { if ((n).item == 0) { first.item = fr.time; } last.item = fr.time; (n).item++; \
}
INC(fr, count, first, last, bStep);
INC(fr, count, first, last, bTime);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2011,2012,2013,2014,2015,2016, by the GROMACS development team, led by
+ * Copyright (c) 2011,2012,2013,2014,2015,2016,2018, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* form to make the simple syntax of GMX_THROW() possible. To support this,
* this operation needs to:
* - Allow setting information in a temporary to support
- * `GMX_THROW(InvalidInputError(ex))`. This is the reason for taking a
- * const reference and the `const_cast`.
- * - Return the same reference it takes in, instead of a base class.
- * The compiler needs this information to throw the correct type of
- * exception. This would be tedious to achieve with a member function
- * (without a lot of code duplication).
+ * `GMX_THROW(InvalidInputError(ex))`.
+ * - Return a copy of the same class it takes in. The compiler needs
+ * this information to throw the correct type of exception. This
+ * would be tedious to achieve with a member function (without a
+ * lot of code duplication). Generally, \c ex will be a temporary,
+ * copied twice and returned by value, which the compiler will
+ * typically elide away (and anyway performance is not important
+ * when throwing). We are not using the typical
+ * return-by-const-reference idiom for this operator so that
+ * tooling can reliably see that we are throwing by value.
* - Provide convenient syntax for adding multiple items. A non-member
* function that would require nested calls would look ugly for such cases.
*
*/
template <class Exception, class Tag, class T>
inline
-typename std::enable_if<std::is_base_of<GromacsException, Exception>::value, const Exception &>::type
-operator<<(const Exception &ex, const ExceptionInfo<Tag, T> &item)
+typename std::enable_if<std::is_base_of<GromacsException, Exception>::value, Exception>::type
+operator<<(Exception ex, const ExceptionInfo<Tag, T> &item)
{
- const_cast<Exception &>(ex).setInfo(item);
+ ex.setInfo(item);
return ex;
}
size_t size,
int (*compar)(const void *, const void *))
{
-#define QSORT_EXCH(a, b, t) (t = a, a = b, b = t)
+#define QSORT_EXCH(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
#define QSORT_SWAP(a, b) swaptype != 0 ? qsort_swapfunc(a, b, size, swaptype) : \
(void)QSORT_EXCH(*(int *)(a), *(int *)(b), t)