From patchwork Thu Mar 19 08:00:05 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= X-Patchwork-Id: 26299 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 6F41EBD87C for ; Thu, 19 Mar 2026 08:00:10 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 9B1B562723; Thu, 19 Mar 2026 09:00:09 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="I/ieosb+"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 7C3AF62635 for ; Thu, 19 Mar 2026 09:00:08 +0100 (CET) Received: from pb-laptop.local (185.221.143.129.nat.pool.zt.hu [185.221.143.129]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id E80A6838; Thu, 19 Mar 2026 08:58:54 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1773907135; bh=K8r/1BVdvKghAP7XuC7OzckRtvFgwxaLpqokIiF9Hnc=; h=From:To:Subject:Date:From; b=I/ieosb+2gcEICG83jf/xTSRbDkMMuq7SwoUc7CzJH4VzEdTN9Z/jl57veDBA+fHY /UcAlrOEqCh5yy6tdUE7Q6GLeXZ5ebZVm1C60krFS9lnl62Uft6kIrYI5n2Y3/VTSC IByawOV/cR+IpgTwvTKsyoewmEKmCFrA1CcslNKo= From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= To: libcamera-devel@lists.libcamera.org, Kieran Bingham Subject: [PATCH v1] ipa: libipa: quantized: Enable `constexpr` operation Date: Thu, 19 Mar 2026 09:00:05 +0100 Message-ID: <20260319080005.162571-1-barnabas.pocze@ideasonboard.com> X-Mailer: git-send-email 2.53.0 MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" There is nothing inherently non-constexpr in the `Quantized` type. Whether it can work in `constexpr` contexts depends on the traits type. There is no reason to explicitly disallow `constexpr` operation. So mark all eligible methods `constexpr`. In addition, add some `static_assert()`s to the "quantized" test to check constexpr operation. For example, `FixedPointQTraits<...>::toFloat()` is `constexpr`, so this enables the construction of `{U,}Q<...>` from the underlying quantized value in `constexpr` contexts, which can be useful for example for storing default values in e.g. `static constexpr` variables. Signed-off-by: Barnabás Pőcze --- src/ipa/libipa/quantized.h | 32 +++++++++++++++++++------------- test/ipa/libipa/quantized.cpp | 15 +++++++++++++-- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/ipa/libipa/quantized.h b/src/ipa/libipa/quantized.h index 6bd196c7d..8d7b06a2d 100644 --- a/src/ipa/libipa/quantized.h +++ b/src/ipa/libipa/quantized.h @@ -24,34 +24,40 @@ struct Quantized { static_assert(std::is_arithmetic_v, "Quantized: QuantizedType must be arithmetic"); - Quantized() + constexpr Quantized() : Quantized(0.0f) {} - Quantized(float x) { *this = x; } - Quantized(QuantizedType x) { *this = x; } - Quantized &operator=(float x) + constexpr Quantized(float x) + : Quantized(Traits::fromFloat(x)) { - quantized_ = Traits::fromFloat(x); - value_ = Traits::toFloat(quantized_); + } + + constexpr Quantized(QuantizedType x) + : quantized_(x), value_(Traits::toFloat(x)) + { + } + + constexpr Quantized &operator=(float x) + { + *this = Quantized(x); return *this; } - Quantized &operator=(QuantizedType x) + constexpr Quantized &operator=(QuantizedType x) { - value_ = Traits::toFloat(x); - quantized_ = x; + *this = Quantized(x); return *this; } - float value() const { return value_; } - QuantizedType quantized() const { return quantized_; } + constexpr float value() const { return value_; } + constexpr QuantizedType quantized() const { return quantized_; } - bool operator==(const Quantized &other) const + constexpr bool operator==(const Quantized &other) const { return quantized_ == other.quantized_; } - bool operator!=(const Quantized &other) const + constexpr bool operator!=(const Quantized &other) const { return !(*this == other); } diff --git a/test/ipa/libipa/quantized.cpp b/test/ipa/libipa/quantized.cpp index f138597f2..18655dac5 100644 --- a/test/ipa/libipa/quantized.cpp +++ b/test/ipa/libipa/quantized.cpp @@ -25,7 +25,7 @@ struct BrightnessHueTraits { int quantized = std::lround(v * 128.0f); return std::clamp(quantized, -128, 127); } - static float toFloat(QuantizedType v) + static constexpr float toFloat(QuantizedType v) { return static_cast(v) / 128.0f; } @@ -40,7 +40,7 @@ struct ContrastSaturationTraits { int quantized = std::lround(v * 128.0f); return std::clamp(quantized, 0, 255); } - static float toFloat(QuantizedType v) + static constexpr float toFloat(QuantizedType v) { return static_cast(v) / 128.0f; } @@ -138,6 +138,17 @@ protected: return TestFail; } + /* Test constexpr operation */ + { + constexpr BrightnessQ b1(uint8_t(1)); + constexpr BrightnessQ b2(uint8_t(2)); + + static_assert(b1.quantized() == 1); + static_assert(b2.quantized() == 2); + static_assert(b1 != b2); + static_assert(!(b1 == b2)); + } + return TestPass; } };