Message ID | 20230614074904.29085-8-herve.codina@bootlin.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp1067241vqr; Wed, 14 Jun 2023 00:52:58 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ6/u71JhRMRAxjEWQ9CRR+zlLyGnzRTXIMEbUtB0b5fBgxbvl8yGQ1OyzUbfeS8VljpmALJ X-Received: by 2002:a17:906:fe0a:b0:973:fe5d:ef71 with SMTP id wy10-20020a170906fe0a00b00973fe5def71mr15246294ejb.14.1686729178698; Wed, 14 Jun 2023 00:52:58 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1686729178; cv=none; d=google.com; s=arc-20160816; b=LVLY/G+SowkVqisOe1hJmCrnTfZZavBGnHxASjg7HPSPRA55GghgF7d3V7/DIPmu3B +eiX5CrOmB+jCEQw5ly+nTDqISYgpeXfjTq9NFUqq0zNOKQqQ5UuN+tfNiulP4vcYzMD ezNXUOA6sBIruoHQ3Slw2h2gtUJak8ZwQ8XOBOjc8O3hr8LsoSClzWkhKj/yLfp/6EIJ UhHN8lFhPqC9ZIXNNbyjnitZ251emAIeh1+1C2rsTSGgZ1c7XF2yJxU8Cp27J2aFiLpE 0MFExfshjL24dX0Q6BXMUdRGkDjQhYtTye9u7GQGzhgXjUAkbObbs13sRzLiClEJ1dbU 5Hyg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=+zfO40ZB12GKQyPAf5k5MdzEzUKB2vFqguLETpbhayQ=; b=rSs7q72vDLzBR3y9WLh2CeQnd1SebaSGqcWW4xsnQCkTYTBVBDQ/geFgOEaLfebQ8N BdPT+X7swEsdeeZzHPCXt/PvOhBL7+JaGfymvunB/VcVR6cq2Xqf5cGzQqfzb1EiHO0r pks+ujkLfW2t3Wkp3lgzN3gaZW1qjSyTTe2Ntmf3v1IHL/TOO59oB0B/rRUGCg/5I6Pu 7LKG1fVosyxCm1Ad64ELVJsien5QzDRIZd2yW1Mw4pKe+XUElE73oBXe45UgNFTG91W1 e8ZJH6pNF/CsViFKLOYnFy/qXfr7avxgU4+Km25ikJ+F+HFrbDSLv1pBDmLbQiZw6SCs 9eew== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@bootlin.com header.s=gm1 header.b=fwD9kZ9F; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=bootlin.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id q21-20020a170906541500b00974d5805d22si8190333ejo.727.2023.06.14.00.52.33; Wed, 14 Jun 2023 00:52:58 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@bootlin.com header.s=gm1 header.b=fwD9kZ9F; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=bootlin.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243537AbjFNHuu (ORCPT <rfc822;jesperjuhl76@gmail.com> + 99 others); Wed, 14 Jun 2023 03:50:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57260 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243398AbjFNHtm (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Wed, 14 Jun 2023 03:49:42 -0400 Received: from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::225]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 228C1E62; Wed, 14 Jun 2023 00:49:39 -0700 (PDT) X-GND-Sasl: herve.codina@bootlin.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1686728978; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=+zfO40ZB12GKQyPAf5k5MdzEzUKB2vFqguLETpbhayQ=; b=fwD9kZ9FkVy9sF1xJtD5WfPxZjQi+LrBv8wjipQlt79coHq445SdLV974h3wcWoFLfwB8O sKkrF28/MJfobtc/bsbMy4lZpqg/0pq+aYk9rNaalKyYg+MUFtJhySFXlLhlN2s1BkRvXV 8jKghyBLSrHAxdROg3mcL2rVTJrKOlTtNtqjX3lHTFqwehm5JItrcZKYStpfFP3pNQ53eH 4qtoRB1vCqMFUj6F4B9VZp5HfhAnRlHMj85nYsjaSoMBCNTSdIknzNPYYoZ3Qwdr7ZiNM7 yt86VgfWii+dDquJCJYPIYuvK3YozyEdZUmrHkEZ1oLb1hbiK40E3JKxd3Fivw== X-GND-Sasl: herve.codina@bootlin.com X-GND-Sasl: herve.codina@bootlin.com X-GND-Sasl: herve.codina@bootlin.com X-GND-Sasl: herve.codina@bootlin.com X-GND-Sasl: herve.codina@bootlin.com X-GND-Sasl: herve.codina@bootlin.com X-GND-Sasl: herve.codina@bootlin.com X-GND-Sasl: herve.codina@bootlin.com X-GND-Sasl: herve.codina@bootlin.com X-GND-Sasl: herve.codina@bootlin.com X-GND-Sasl: herve.codina@bootlin.com X-GND-Sasl: herve.codina@bootlin.com X-GND-Sasl: herve.codina@bootlin.com X-GND-Sasl: herve.codina@bootlin.com X-GND-Sasl: herve.codina@bootlin.com X-GND-Sasl: herve.codina@bootlin.com X-GND-Sasl: herve.codina@bootlin.com Received: by mail.gandi.net (Postfix) with ESMTPA id 6C4B01C0003; Wed, 14 Jun 2023 07:49:37 +0000 (UTC) From: Herve Codina <herve.codina@bootlin.com> To: Herve Codina <herve.codina@bootlin.com>, Liam Girdwood <lgirdwood@gmail.com>, Mark Brown <broonie@kernel.org>, Rob Herring <robh+dt@kernel.org>, Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>, Conor Dooley <conor+dt@kernel.org>, Jonathan Cameron <jic23@kernel.org>, Lars-Peter Clausen <lars@metafoo.de>, Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.com>, Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>, Andy Shevchenko <andy.shevchenko@gmail.com> Cc: alsa-devel@alsa-project.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org, Christophe Leroy <christophe.leroy@csgroup.eu>, Thomas Petazzoni <thomas.petazzoni@bootlin.com> Subject: [PATCH v4 07/13] minmax: Introduce {min,max}_array() Date: Wed, 14 Jun 2023 09:48:58 +0200 Message-Id: <20230614074904.29085-8-herve.codina@bootlin.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230614074904.29085-1-herve.codina@bootlin.com> References: <20230614074904.29085-1-herve.codina@bootlin.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1768663735488901699?= X-GMAIL-MSGID: =?utf-8?q?1768663735488901699?= |
Series |
Add support for IIO devices in ASoC
|
|
Commit Message
Herve Codina
June 14, 2023, 7:48 a.m. UTC
Introduce min_array() (resp max_array()) in order to get the
minimal (resp maximum) of values present in an array.
Signed-off-by: Herve Codina <herve.codina@bootlin.com>
---
include/linux/minmax.h | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
Comments
On Wed, Jun 14, 2023 at 10:49 AM Herve Codina <herve.codina@bootlin.com> wrote: > > Introduce min_array() (resp max_array()) in order to get the > minimal (resp maximum) of values present in an array. Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com> See a remark below. > Signed-off-by: Herve Codina <herve.codina@bootlin.com> > --- > include/linux/minmax.h | 36 ++++++++++++++++++++++++++++++++++++ > 1 file changed, 36 insertions(+) > > diff --git a/include/linux/minmax.h b/include/linux/minmax.h > index 396df1121bff..2cd0d34ce921 100644 > --- a/include/linux/minmax.h > +++ b/include/linux/minmax.h > @@ -133,6 +133,42 @@ > */ > #define max_t(type, x, y) __careful_cmp((type)(x), (type)(y), >) > > +/* > + * Do not check the array parameter using __must_be_array(). > + * In the following legit use-case where the "array" passed is a simple pointer, > + * __must_be_array() will return a failure. > + * --- 8< --- > + * int *buff > + * ... > + * min = min_array(buff, nb_items); > + * --- 8< --- > + */ > +#define __minmax_array(op, array, len) ({ \ > + typeof(array) __array = (array); \ > + typeof(len) __len = (len); \ > + typeof(__array[0] + 0) __element = __array[--__len]; \ Do we need the ' + 0' part? > + while (__len--) \ > + __element = op(__element, __array[__len]); \ > + __element; }) > + > +/** > + * min_array - return minimum of values present in an array > + * @array: array > + * @len: array length > + * > + * Note that @len must not be zero (empty array). > + */ > +#define min_array(array, len) __minmax_array(min, array, len) > + > +/** > + * max_array - return maximum of values present in an array > + * @array: array > + * @len: array length > + * > + * Note that @len must not be zero (empty array). > + */ > +#define max_array(array, len) __minmax_array(max, array, len) > + > /** > * clamp_t - return a value clamped to a given range using a given type > * @type: the type of variable to use > -- > 2.40.1 >
Hi Andy, On Wed, 14 Jun 2023 12:02:57 +0300 Andy Shevchenko <andy.shevchenko@gmail.com> wrote: > On Wed, Jun 14, 2023 at 10:49 AM Herve Codina <herve.codina@bootlin.com> wrote: > > > > Introduce min_array() (resp max_array()) in order to get the > > minimal (resp maximum) of values present in an array. > > Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com> > See a remark below. > > > Signed-off-by: Herve Codina <herve.codina@bootlin.com> > > --- > > include/linux/minmax.h | 36 ++++++++++++++++++++++++++++++++++++ > > 1 file changed, 36 insertions(+) > > > > diff --git a/include/linux/minmax.h b/include/linux/minmax.h > > index 396df1121bff..2cd0d34ce921 100644 > > --- a/include/linux/minmax.h > > +++ b/include/linux/minmax.h > > @@ -133,6 +133,42 @@ > > */ > > #define max_t(type, x, y) __careful_cmp((type)(x), (type)(y), >) > > > > +/* > > + * Do not check the array parameter using __must_be_array(). > > + * In the following legit use-case where the "array" passed is a simple pointer, > > + * __must_be_array() will return a failure. > > + * --- 8< --- > > + * int *buff > > + * ... > > + * min = min_array(buff, nb_items); > > + * --- 8< --- > > + */ > > +#define __minmax_array(op, array, len) ({ \ > > + typeof(array) __array = (array); \ > > + typeof(len) __len = (len); \ > > + typeof(__array[0] + 0) __element = __array[--__len]; \ > > Do we need the ' + 0' part? Yes. __array can be an array of const items and it is legitimate to get the minimum value from const items. typeof(__array[0]) keeps the const qualifier but we need to assign __element in the loop. One way to drop the const qualifier is to get the type from a rvalue computed from __array[0]. This rvalue has to have the exact same type with only the const dropped. '__array[0] + 0' was a perfect canditate. Regards, Hervé > > > + while (__len--) \ > > + __element = op(__element, __array[__len]); \ > > + __element; }) > > + > > +/** > > + * min_array - return minimum of values present in an array > > + * @array: array > > + * @len: array length > > + * > > + * Note that @len must not be zero (empty array). > > + */ > > +#define min_array(array, len) __minmax_array(min, array, len) > > + > > +/** > > + * max_array - return maximum of values present in an array > > + * @array: array > > + * @len: array length > > + * > > + * Note that @len must not be zero (empty array). > > + */ > > +#define max_array(array, len) __minmax_array(max, array, len) > > + > > /** > > * clamp_t - return a value clamped to a given range using a given type > > * @type: the type of variable to use > > -- > > 2.40.1 > > > >
On Wed, Jun 14, 2023 at 12:42 PM Herve Codina <herve.codina@bootlin.com> wrote: > On Wed, 14 Jun 2023 12:02:57 +0300 > Andy Shevchenko <andy.shevchenko@gmail.com> wrote: > > On Wed, Jun 14, 2023 at 10:49 AM Herve Codina <herve.codina@bootlin.com> wrote: ... > > > + typeof(__array[0] + 0) __element = __array[--__len]; \ > > > > Do we need the ' + 0' part? > > Yes. > > __array can be an array of const items and it is legitimate to get the > minimum value from const items. > > typeof(__array[0]) keeps the const qualifier but we need to assign __element > in the loop. > One way to drop the const qualifier is to get the type from a rvalue computed > from __array[0]. This rvalue has to have the exact same type with only the const > dropped. > '__array[0] + 0' was a perfect canditate. Seems like this also deserves a comment. But if the series is accepted as is, it may be done as a follow up.
Hi Andy, On Wed, 14 Jun 2023 14:51:43 +0300 Andy Shevchenko <andy.shevchenko@gmail.com> wrote: > On Wed, Jun 14, 2023 at 12:42 PM Herve Codina <herve.codina@bootlin.com> wrote: > > On Wed, 14 Jun 2023 12:02:57 +0300 > > Andy Shevchenko <andy.shevchenko@gmail.com> wrote: > > > On Wed, Jun 14, 2023 at 10:49 AM Herve Codina <herve.codina@bootlin.com> wrote: > > ... > > > > > + typeof(__array[0] + 0) __element = __array[--__len]; \ > > > > > > Do we need the ' + 0' part? > > > > Yes. > > > > __array can be an array of const items and it is legitimate to get the > > minimum value from const items. > > > > typeof(__array[0]) keeps the const qualifier but we need to assign __element > > in the loop. > > One way to drop the const qualifier is to get the type from a rvalue computed > > from __array[0]. This rvalue has to have the exact same type with only the const > > dropped. > > '__array[0] + 0' was a perfect canditate. > > Seems like this also deserves a comment. But if the series is accepted > as is, it may be done as a follow up. > Finally not so simple ... I did some deeper tests and the macros need to be fixed. I hope this one (with comments added) is correct: --- 8 --- /* * Do not check the array parameter using __must_be_array(). * In the following legit use-case where the "array" passed is a simple pointer, * __must_be_array() will return a failure. * --- 8< --- * int *buff * ... * min = min_array(buff, nb_items); * --- 8< --- * * The first typeof(&(array)[0]) is needed in order to support arrays of both * 'int *buff' and 'int buf[N]' types. * * typeof(__array[0] + 0) used for __element is needed as the array can be an * array of const items. * In order to discard the const qualifier use an arithmetic operation (rvalue). * This arithmetic operation discard the const but also can lead to an integer * promotion. For instance, a const s8 __array[0] lead to an int __element due * to the promotion. * In this case, simple min() or max() operation fails (type mismatch). * Use min_t() or max_t() (op_t parameter) enforcing the type in order to avoid * the min() or max() failure. */ #define __minmax_array(op_t, array, len) ({ \ typeof(&(array)[0]) __array = (array); \ typeof(len) __len = (len); \ typeof(__array[0] + 0) __element = __array[--__len]; \ while (__len--) \ __element = op_t(typeof(__array[0]), __element, __array[__len]); \ __element; }) /** * min_array - return minimum of values present in an array * @array: array * @len: array length * * Note that @len must not be zero (empty array). */ #define min_array(array, len) __minmax_array(min_t, array, len) /** * max_array - return maximum of values present in an array * @array: array * @len: array length * * Note that @len must not be zero (empty array). */ #define max_array(array, len) __minmax_array(max_t, array, len) --- 8< --- Tested ok from user-space on my x86_64 using the following types for *buff and buff[N]: - signed/unsigned char - signed/unsigned short - signed/unsigned int - signed/unsigned long - signed/unsigned long long - float, double, long double (even if not used in the kernel) Can you give me your feedback on this last version ? If you are ok, it will be present in the next iteration of the series. Otherwise, as a last ressort, I will drop the {min,max}_array() and switch back to the specific min/max computation in IIO inkern.c Sorry for this back and forth and this last minute detected bug. Best regards, Hervé
On Wed, Jun 14, 2023 at 11:34 PM Herve Codina <herve.codina@bootlin.com> wrote: > On Wed, 14 Jun 2023 14:51:43 +0300 > Andy Shevchenko <andy.shevchenko@gmail.com> wrote: > > On Wed, Jun 14, 2023 at 12:42 PM Herve Codina <herve.codina@bootlin.com> wrote: > > > On Wed, 14 Jun 2023 12:02:57 +0300 > > > Andy Shevchenko <andy.shevchenko@gmail.com> wrote: > > > > On Wed, Jun 14, 2023 at 10:49 AM Herve Codina <herve.codina@bootlin.com> wrote: ... > > > > > + typeof(__array[0] + 0) __element = __array[--__len]; \ > > > > > > > > Do we need the ' + 0' part? > > > > > > Yes. > > > > > > __array can be an array of const items and it is legitimate to get the > > > minimum value from const items. > > > > > > typeof(__array[0]) keeps the const qualifier but we need to assign __element > > > in the loop. > > > One way to drop the const qualifier is to get the type from a rvalue computed > > > from __array[0]. This rvalue has to have the exact same type with only the const > > > dropped. > > > '__array[0] + 0' was a perfect canditate. > > > > Seems like this also deserves a comment. But if the series is accepted > > as is, it may be done as a follow up. > > > > Finally not so simple ... > I did some deeper tests and the macros need to be fixed. > > I hope this one (with comments added) is correct: > --- 8 --- > /* > * Do not check the array parameter using __must_be_array(). > * In the following legit use-case where the "array" passed is a simple pointer, > * __must_be_array() will return a failure. > * --- 8< --- > * int *buff > * ... > * min = min_array(buff, nb_items); > * --- 8< --- > * > * The first typeof(&(array)[0]) is needed in order to support arrays of both > * 'int *buff' and 'int buf[N]' types. > * > * typeof(__array[0] + 0) used for __element is needed as the array can be an > * array of const items. > * In order to discard the const qualifier use an arithmetic operation (rvalue). > * This arithmetic operation discard the const but also can lead to an integer discards > * promotion. For instance, a const s8 __array[0] lead to an int __element due leads > * to the promotion. > * In this case, simple min() or max() operation fails (type mismatch). > * Use min_t() or max_t() (op_t parameter) enforcing the type in order to avoid > * the min() or max() failure. This part perhaps can be avoided. See below. > */ > #define __minmax_array(op_t, array, len) ({ \ > typeof(&(array)[0]) __array = (array); \ > typeof(len) __len = (len); \ > typeof(__array[0] + 0) __element = __array[--__len]; \ > while (__len--) \ > __element = op_t(typeof(__array[0]), __element, __array[__len]); \ But can't we instead have typeof(+(array[0])) in the definition of __element? There are also other possible solutions: a) _Generic() with listed const types to move them to non-const, and b) __auto_type (which is supported by GCC 4.9 and clang, but not in the C11 standard). > __element; }) ... > Can you give me your feedback on this last version ? Sure! > If you are ok, it will be present in the next iteration of the series. > Otherwise, as a last ressort, I will drop the {min,max}_array() and switch > back to the specific min/max computation in IIO inkern.c > > Sorry for this back and forth and this last minute detected bug. It's good that we have some tests (perhaps you can add something to unit test these)? Perhaps move your code to lib/test_minmax.c as KUnit module?
Hi Andy, On Thu, 15 Jun 2023 01:05:40 +0300 Andy Shevchenko <andy.shevchenko@gmail.com> wrote: > On Wed, Jun 14, 2023 at 11:34 PM Herve Codina <herve.codina@bootlin.com> wrote: > > On Wed, 14 Jun 2023 14:51:43 +0300 > > Andy Shevchenko <andy.shevchenko@gmail.com> wrote: > > > On Wed, Jun 14, 2023 at 12:42 PM Herve Codina <herve.codina@bootlin.com> wrote: > > > > On Wed, 14 Jun 2023 12:02:57 +0300 > > > > Andy Shevchenko <andy.shevchenko@gmail.com> wrote: > > > > > On Wed, Jun 14, 2023 at 10:49 AM Herve Codina <herve.codina@bootlin.com> wrote: > > ... > > > > > > > + typeof(__array[0] + 0) __element = __array[--__len]; \ > > > > > > > > > > Do we need the ' + 0' part? > > > > > > > > Yes. > > > > > > > > __array can be an array of const items and it is legitimate to get the > > > > minimum value from const items. > > > > > > > > typeof(__array[0]) keeps the const qualifier but we need to assign __element > > > > in the loop. > > > > One way to drop the const qualifier is to get the type from a rvalue computed > > > > from __array[0]. This rvalue has to have the exact same type with only the const > > > > dropped. > > > > '__array[0] + 0' was a perfect canditate. > > > > > > Seems like this also deserves a comment. But if the series is accepted > > > as is, it may be done as a follow up. > > > > > > > Finally not so simple ... > > I did some deeper tests and the macros need to be fixed. > > > > I hope this one (with comments added) is correct: > > --- 8 --- > > /* > > * Do not check the array parameter using __must_be_array(). > > * In the following legit use-case where the "array" passed is a simple pointer, > > * __must_be_array() will return a failure. > > * --- 8< --- > > * int *buff > > * ... > > * min = min_array(buff, nb_items); > > * --- 8< --- > > * > > * The first typeof(&(array)[0]) is needed in order to support arrays of both > > * 'int *buff' and 'int buf[N]' types. > > * > > * typeof(__array[0] + 0) used for __element is needed as the array can be an > > * array of const items. > > * In order to discard the const qualifier use an arithmetic operation (rvalue). > > > > * This arithmetic operation discard the const but also can lead to an integer > > discards > > > * promotion. For instance, a const s8 __array[0] lead to an int __element due > > leads > > > * to the promotion. > > * In this case, simple min() or max() operation fails (type mismatch). > > * Use min_t() or max_t() (op_t parameter) enforcing the type in order to avoid > > * the min() or max() failure. > > This part perhaps can be avoided. See below. > > > */ > > #define __minmax_array(op_t, array, len) ({ \ > > typeof(&(array)[0]) __array = (array); \ > > typeof(len) __len = (len); \ > > typeof(__array[0] + 0) __element = __array[--__len]; \ > > while (__len--) \ > > __element = op_t(typeof(__array[0]), __element, __array[__len]); \ > > But can't we instead have typeof(+(array[0])) in the definition of __element? > There are also other possible solutions: a) _Generic() with listed > const types to move them to non-const, and b) __auto_type (which is > supported by GCC 4.9 and clang, but not in the C11 standard). typeof(+(array[0])) keeps the promotion. __auto_type works with my gcc-12 but not with a gcc-5.5. Depending on the compiler version, it discards or keeps the const qualifier. For this reason I would prefer to not use it. Did the job using _Generic(). This lead to: --- 8< --- /* * Remove a const qualifier * _Generic(foo, type-name: association, ..., default: association) performs a * comparison against the foo type (not the qualified type). * Do not use the const keyword in the type-name as it will not match the * unqualified type of foo. */ #define __unconst_type_cases(type) \ unsigned type: (unsigned type)0, \ signed type: (signed type)0 #define __unconst_typeof(x) typeof( \ _Generic((x), \ char: (char)0, \ __unconst_type_cases(char), \ __unconst_type_cases(short), \ __unconst_type_cases(int), \ __unconst_type_cases(long), \ __unconst_type_cases(long long), \ default: (x))) /* * Do not check the array parameter using __must_be_array(). * In the following legit use-case where the "array" passed is a simple pointer, * __must_be_array() will return a failure. * --- 8< --- * int *buff * ... * min = min_array(buff, nb_items); * --- 8< --- * * The first typeof(&(array)[0]) is needed in order to support arrays of both * 'int *buff' and 'int buf[N]' types. * * The array can be an array of const items. * typeof() keeps the const qualifier. Use __unconst_typeof() in order to * discard the const qualifier for the __element variable. */ #define __minmax_array(op, array, len) ({ \ typeof(&(array)[0]) __array = (array); \ typeof(len) __len = (len); \ __unconst_typeof(__array[0]) __element = __array[--__len]; \ while (__len--) \ __element = op(__element, __array[__len]); \ __element; }) /** * min_array - return minimum of values present in an array * @array: array * @len: array length * * Note that @len must not be zero (empty array). */ #define min_array(array, len) __minmax_array(min, array, len) /** * max_array - return maximum of values present in an array * @array: array * @len: array length * * Note that @len must not be zero (empty array). */ #define max_array(array, len) __minmax_array(max, array, len) --- 8< --- Do you think it looks good ? For, the KUnit tests, I agree, it would be nice to have something. I need some more substantial work to implement and run the test in KUnit and the first task will be learning the KUnit test system. I will do that but out of this series. Thanks for your feedback and pointers, Hervé
On Thu, Jun 15, 2023 at 12:35 PM Herve Codina <herve.codina@bootlin.com> wrote: > On Thu, 15 Jun 2023 01:05:40 +0300 > Andy Shevchenko <andy.shevchenko@gmail.com> wrote: ... > Did the job using _Generic(). Cool! Keep my tag for that version and thank you for pursuing the implementation that works for everybody. > This lead to: > --- 8< --- > /* > * Remove a const qualifier ...from integer types > * _Generic(foo, type-name: association, ..., default: association) performs a > * comparison against the foo type (not the qualified type). > * Do not use the const keyword in the type-name as it will not match the > * unqualified type of foo. > */ > #define __unconst_type_cases(type) \ __unconst_integer_type_cases() ? > unsigned type: (unsigned type)0, \ > signed type: (signed type)0 > > Single blank line is enough. > #define __unconst_typeof(x) typeof( \ __unconst_integer_typeof() ? > _Generic((x), \ > char: (char)0, \ > __unconst_type_cases(char), \ > __unconst_type_cases(short), \ > __unconst_type_cases(int), \ > __unconst_type_cases(long), \ > __unconst_type_cases(long long), \ > default: (x))) > > /* > * Do not check the array parameter using __must_be_array(). > * In the following legit use-case where the "array" passed is a simple pointer, > * __must_be_array() will return a failure. > * --- 8< --- > * int *buff > * ... > * min = min_array(buff, nb_items); > * --- 8< --- > * > * The first typeof(&(array)[0]) is needed in order to support arrays of both > * 'int *buff' and 'int buf[N]' types. > * > * The array can be an array of const items. > * typeof() keeps the const qualifier. Use __unconst_typeof() in order to > * discard the const qualifier for the __element variable. > */ > #define __minmax_array(op, array, len) ({ \ > typeof(&(array)[0]) __array = (array); \ > typeof(len) __len = (len); \ > __unconst_typeof(__array[0]) __element = __array[--__len]; \ > while (__len--) \ > __element = op(__element, __array[__len]); \ > __element; }) > > /** > * min_array - return minimum of values present in an array > * @array: array > * @len: array length > * > * Note that @len must not be zero (empty array). > */ > #define min_array(array, len) __minmax_array(min, array, len) > > /** > * max_array - return maximum of values present in an array > * @array: array > * @len: array length > * > * Note that @len must not be zero (empty array). > */ > #define max_array(array, len) __minmax_array(max, array, len) > --- 8< --- > > Do you think it looks good ? Yes! > For, the KUnit tests, I agree, it would be nice to have something. > I need some more substantial work to implement and run the test in KUnit > and the first task will be learning the KUnit test system. > I will do that but out of this series. Thank you, it's fine with me.
From: Herve Codina > Sent: 15 June 2023 10:35 > > ... > > > > > > > > > + typeof(__array[0] + 0) __element = __array[--__len]; \ > > > > > > > > > > > > Do we need the ' + 0' part? > > > > > > > > > > Yes. > > > > > > > > > > __array can be an array of const items and it is legitimate to get the > > > > > minimum value from const items. > > > > > > > > > > typeof(__array[0]) keeps the const qualifier but we need to assign __element > > > > > in the loop. > > > > > One way to drop the const qualifier is to get the type from a rvalue computed > > > > > from __array[0]. This rvalue has to have the exact same type with only the const > > > > > dropped. > > > > > '__array[0] + 0' was a perfect canditate. > > > > > > > > Seems like this also deserves a comment. But if the series is accepted > > > > as is, it may be done as a follow up. > > > > > > > > > > Finally not so simple ... > > > I did some deeper tests and the macros need to be fixed. > > > > > > I hope this one (with comments added) is correct: > > > --- 8 --- > > > /* > > > * Do not check the array parameter using __must_be_array(). > > > * In the following legit use-case where the "array" passed is a simple pointer, > > > * __must_be_array() will return a failure. > > > * --- 8< --- > > > * int *buff > > > * ... > > > * min = min_array(buff, nb_items); > > > * --- 8< --- > > > * > > > * The first typeof(&(array)[0]) is needed in order to support arrays of both > > > * 'int *buff' and 'int buf[N]' types. > > > * > > > * typeof(__array[0] + 0) used for __element is needed as the array can be an > > > * array of const items. > > > * In order to discard the const qualifier use an arithmetic operation (rvalue). > > > > > > > * This arithmetic operation discard the const but also can lead to an integer > > > > discards > > > > > * promotion. For instance, a const s8 __array[0] lead to an int __element due > > > > leads > > > > > * to the promotion. > > > * In this case, simple min() or max() operation fails (type mismatch). > > > * Use min_t() or max_t() (op_t parameter) enforcing the type in order to avoid > > > * the min() or max() failure. > > > > This part perhaps can be avoided. See below. > > > > > */ > > > #define __minmax_array(op_t, array, len) ({ \ > > > typeof(&(array)[0]) __array = (array); \ > > > typeof(len) __len = (len); \ > > > typeof(__array[0] + 0) __element = __array[--__len]; \ > > > while (__len--) \ > > > __element = op_t(typeof(__array[0]), __element, __array[__len]); \ > > > > But can't we instead have typeof(+(array[0])) in the definition of __element? > > There are also other possible solutions: a) _Generic() with listed > > const types to move them to non-const, and b) __auto_type (which is > > supported by GCC 4.9 and clang, but not in the C11 standard). > > typeof(+(array[0])) keeps the promotion. > > __auto_type works with my gcc-12 but not with a gcc-5.5. Depending on the > compiler version, it discards or keeps the const qualifier. For this reason > I would prefer to not use it. Just define two variables typeof(__array[0] + 0) one for an element and one for the limit. The just test (eg): if (limit > item) limit = item; finally cast the limit back to the original type. The promotions of char/short to signed int won't matter. There is no need for all the type-checking in min/max. Indeed, if min_t(type, a, b) is in anyway sane it should expand to: type _a = a, _b = b; _a < _b ? _a : _b without any of the checks that min() does. David - Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)
Hi David, On Fri, 16 Jun 2023 09:08:22 +0000 David Laight <David.Laight@ACULAB.COM> wrote: ... > > Just define two variables typeof(__array[0] + 0) one for an element > and one for the limit. > The just test (eg): > if (limit > item) limit = item; > finally cast the limit back to the original type. > The promotions of char/short to signed int won't matter. > There is no need for all the type-checking in min/max. > > Indeed, if min_t(type, a, b) is in anyway sane it should > expand to: > type _a = a, _b = b; > _a < _b ? _a : _b > without any of the checks that min() does. I finally move to use _Generic() in order to "unconstify" and avoid the integer promotion. With this done, no extra cast is needed and min()/max() are usable. The patch is available in the v5 series. https://lore.kernel.org/linux-kernel/20230615152631.224529-8-herve.codina@bootlin.com/ Do you think the code present in the v5 series should be changed ? If so, can you give me your feedback on the v5 series ? Thanks for your review, Hervé
From: Herve Codina <herve.codina@bootlin.com> > Sent: 16 June 2023 12:49 > > Hi David, > > On Fri, 16 Jun 2023 09:08:22 +0000 > David Laight <David.Laight@ACULAB.COM> wrote: > > ... > > > > > Just define two variables typeof(__array[0] + 0) one for an element > > and one for the limit. > > The just test (eg): > > if (limit > item) limit = item; > > finally cast the limit back to the original type. > > The promotions of char/short to signed int won't matter. > > There is no need for all the type-checking in min/max. > > > > Indeed, if min_t(type, a, b) is in anyway sane it should > > expand to: > > type _a = a, _b = b; > > _a < _b ? _a : _b > > without any of the checks that min() does. > > I finally move to use _Generic() in order to "unconstify" and avoid the > integer promotion. With this done, no extra cast is needed and min()/max() > are usable. > > The patch is available in the v5 series. > https://lore.kernel.org/linux-kernel/20230615152631.224529-8-herve.codina@bootlin.com/ > > Do you think the code present in the v5 series should be changed ? > If so, can you give me your feedback on the v5 series ? It seems horribly over-complicated just to get around the perverse over-strong type checking that min/max do just to avoid sign extension issues. Maybe I ought to try getting a patch accepted that just checks is_signed_type(typeof(x)) == is_signed_type(typeof(y)) instead of typeof(x) == typeof(y) Then worry about the valid signed v unsigned cases. Indeed, since the array index can be assumed not to have side effects you could use __cmp(x, y, op) directly. No one has pointed out that __element should be __bound. David - Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)
diff --git a/include/linux/minmax.h b/include/linux/minmax.h index 396df1121bff..2cd0d34ce921 100644 --- a/include/linux/minmax.h +++ b/include/linux/minmax.h @@ -133,6 +133,42 @@ */ #define max_t(type, x, y) __careful_cmp((type)(x), (type)(y), >) +/* + * Do not check the array parameter using __must_be_array(). + * In the following legit use-case where the "array" passed is a simple pointer, + * __must_be_array() will return a failure. + * --- 8< --- + * int *buff + * ... + * min = min_array(buff, nb_items); + * --- 8< --- + */ +#define __minmax_array(op, array, len) ({ \ + typeof(array) __array = (array); \ + typeof(len) __len = (len); \ + typeof(__array[0] + 0) __element = __array[--__len]; \ + while (__len--) \ + __element = op(__element, __array[__len]); \ + __element; }) + +/** + * min_array - return minimum of values present in an array + * @array: array + * @len: array length + * + * Note that @len must not be zero (empty array). + */ +#define min_array(array, len) __minmax_array(min, array, len) + +/** + * max_array - return maximum of values present in an array + * @array: array + * @len: array length + * + * Note that @len must not be zero (empty array). + */ +#define max_array(array, len) __minmax_array(max, array, len) + /** * clamp_t - return a value clamped to a given range using a given type * @type: the type of variable to use