[{"id":37753,"web_url":"https://patchwork.libcamera.org/comment/37753/","msgid":"<176889918695.508107.16263205271582334087@localhost>","date":"2026-01-20T08:53:06","subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","submitter":{"id":184,"url":"https://patchwork.libcamera.org/api/people/184/","name":"Stefan Klug","email":"stefan.klug@ideasonboard.com"},"content":"Hi Jacopo,\n\nQuoting Jacopo Mondi (2026-01-20 09:39:49)\n> Converting numbers with a signed fixed-point representation to\n> the corresponding float value requires to include the sign bit in the\n> width of the fixed-point integral part.\n> \n> Clearly specify it in documentation.\n> \n> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n> ---\n>  src/ipa/libipa/fixedpoint.cpp | 22 +++++++++++++++++++++-\n>  1 file changed, 21 insertions(+), 1 deletion(-)\n> \n> diff --git a/src/ipa/libipa/fixedpoint.cpp b/src/ipa/libipa/fixedpoint.cpp\n> index 6b698fc5d680..b37cdc43936f 100644\n> --- a/src/ipa/libipa/fixedpoint.cpp\n> +++ b/src/ipa/libipa/fixedpoint.cpp\n> @@ -29,11 +29,31 @@ namespace ipa {\n>  /**\n>   * \\fn R fixedToFloatingPoint(T number)\n>   * \\brief Convert a fixed-point number to a floating point representation\n> - * \\tparam I Bit width of the integer part of the fixed-point\n> + * \\tparam I Bit width of the integer part of the fixed-point including the\n> + * optional sign bit\n>   * \\tparam F Bit width of the fractional part of the fixed-point\n>   * \\tparam R Return type of the floating point representation\n>   * \\tparam T Input type of the fixed-point representation\n>   * \\param number The fixed point number to convert to floating point\n> + *\n> + * If the fixed-point representation is signed, the sign bit shall be included\n> + * in the \\a I template parameter that specifies the number of bits of the\n> + * integral part of the fixed-point representation.\n> + *\n> + * As an example, a value represented as signed fixed-point Q4.8 format can be\n> + * converted to its corresponding floating point representation as:\n\nI'm a bit confused here. Doesn't signed Q4.8 mean that the first bit of\nthe 4 is the sign bit? The same way a signed int32 has the signed bit on\nthe first of the 32 bits?\n\nBest regards,\nStefan\n\n> + *\n> + * \\code{.cpp}\n> + * double d = fixedToFloatingPoint<5, 8, double, uint16_t>(fixed);\n> + * \\endcode\n> + *\n> + * While a value represented as unsigned fixed-point Q4.8 format can be\n> + * converted as:\n> + *\n> + * \\code{.cpp}\n> + * double d = fixedToFloatingPoint<4, 8, double, uint16_t>(fixed);\n> + * \\endcode\n> + *\n>   * \\return The converted value\n>   */\n> \n> --\n> 2.52.0\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 8C79BC3220\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 20 Jan 2026 08:53:13 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id BD03E61FC8;\n\tTue, 20 Jan 2026 09:53:12 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 720B961F84\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 20 Jan 2026 09:53:10 +0100 (CET)","from ideasonboard.com (unknown\n\t[IPv6:2a00:6020:448c:6c00:7f76:a386:d798:7544])\n\tby perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id 50E121733; \n\tTue, 20 Jan 2026 09:52:39 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"Fu4imPuD\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1768899159;\n\tbh=iLWpaITAu37BqZp7KIVcNyHk0ek9Q/4HBDO7JU3z8lM=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=Fu4imPuD40+Bu4nX6f64b3PtIoqXooF94/jbAjknLEAcFQfsMvVhe1nfJHW+ksXNf\n\t67pvPyM6pjP77ShP3mf4NRd1kEZ79sV7v3MsFE3Z1aX1ELmie7cAfWoXtg6ug62nma\n\tPV37gdrR2JmHnY+Rwb8LClaKiA4Zfv1hV+Lh8tj0=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20260120083952.15338-1-jacopo.mondi@ideasonboard.com>","References":"<20260120083952.15338-1-jacopo.mondi@ideasonboard.com>","Subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","From":"Stefan Klug <stefan.klug@ideasonboard.com>","Cc":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>,\n\tPaul Elder <paul.elder@ideasonboard.com>","To":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","Date":"Tue, 20 Jan 2026 09:53:06 +0100","Message-ID":"<176889918695.508107.16263205271582334087@localhost>","User-Agent":"alot/0.12.dev8+g2c003385c862.d20250602","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":37754,"web_url":"https://patchwork.libcamera.org/comment/37754/","msgid":"<aW9DuVQauFNYVvBm@zed>","date":"2026-01-20T09:00:14","subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","submitter":{"id":143,"url":"https://patchwork.libcamera.org/api/people/143/","name":"Jacopo Mondi","email":"jacopo.mondi@ideasonboard.com"},"content":"Hi Stefan\n\nOn Tue, Jan 20, 2026 at 09:53:06AM +0100, Stefan Klug wrote:\n> Hi Jacopo,\n>\n> Quoting Jacopo Mondi (2026-01-20 09:39:49)\n> > Converting numbers with a signed fixed-point representation to\n> > the corresponding float value requires to include the sign bit in the\n> > width of the fixed-point integral part.\n> >\n> > Clearly specify it in documentation.\n> >\n> > Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n> > ---\n> >  src/ipa/libipa/fixedpoint.cpp | 22 +++++++++++++++++++++-\n> >  1 file changed, 21 insertions(+), 1 deletion(-)\n> >\n> > diff --git a/src/ipa/libipa/fixedpoint.cpp b/src/ipa/libipa/fixedpoint.cpp\n> > index 6b698fc5d680..b37cdc43936f 100644\n> > --- a/src/ipa/libipa/fixedpoint.cpp\n> > +++ b/src/ipa/libipa/fixedpoint.cpp\n> > @@ -29,11 +29,31 @@ namespace ipa {\n> >  /**\n> >   * \\fn R fixedToFloatingPoint(T number)\n> >   * \\brief Convert a fixed-point number to a floating point representation\n> > - * \\tparam I Bit width of the integer part of the fixed-point\n> > + * \\tparam I Bit width of the integer part of the fixed-point including the\n> > + * optional sign bit\n> >   * \\tparam F Bit width of the fractional part of the fixed-point\n> >   * \\tparam R Return type of the floating point representation\n> >   * \\tparam T Input type of the fixed-point representation\n> >   * \\param number The fixed point number to convert to floating point\n> > + *\n> > + * If the fixed-point representation is signed, the sign bit shall be included\n> > + * in the \\a I template parameter that specifies the number of bits of the\n> > + * integral part of the fixed-point representation.\n> > + *\n> > + * As an example, a value represented as signed fixed-point Q4.8 format can be\n> > + * converted to its corresponding floating point representation as:\n>\n> I'm a bit confused here. Doesn't signed Q4.8 mean that the first bit of\n> the 4 is the sign bit? The same way a signed int32 has the signed bit on\n> the first of the 32 bits?\n\nI'm right now looking at the datasheet documentation of a value said\nto be in \"signed Q4.8\" format whose register size is 13 bits\n\nCoefft R-G [12:0] : sign/magnitude 4.8-bit fixed-point\n\n>\n> Best regards,\n> Stefan\n>\n> > + *\n> > + * \\code{.cpp}\n> > + * double d = fixedToFloatingPoint<5, 8, double, uint16_t>(fixed);\n> > + * \\endcode\n> > + *\n> > + * While a value represented as unsigned fixed-point Q4.8 format can be\n> > + * converted as:\n> > + *\n> > + * \\code{.cpp}\n> > + * double d = fixedToFloatingPoint<4, 8, double, uint16_t>(fixed);\n> > + * \\endcode\n> > + *\n> >   * \\return The converted value\n> >   */\n> >\n> > --\n> > 2.52.0\n> >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 349C3BDCBF\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 20 Jan 2026 09:00:21 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 4B6CE61FC6;\n\tTue, 20 Jan 2026 10:00:20 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 161CB61F84\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 20 Jan 2026 10:00:18 +0100 (CET)","from ideasonboard.com (unknown\n\t[IPv6:2001:b07:6462:5de2:520d:d7a3:63ca:99e8])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id C582E1733;\n\tTue, 20 Jan 2026 09:59:46 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"XrHhFXTE\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1768899586;\n\tbh=jwz8lvUoRk4MG7r6iYjH/aYXSjaHUgeh+4fatkvt72o=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=XrHhFXTEMRa4FGtw5EXD8H/zfYxEIFoT91QiRJN7yksfHnqFMRbLgEzfT0Q2wtEnp\n\tCr/uWfy58SUabH6TJMShPpZSZubnNJiBX30lAa1Ku0gygbJeKfQ1gm4CPO/u96MMsD\n\tQNfeiSw0fpcoxPazvrNn/efzw8ze9HNsrj03XfYU=","Date":"Tue, 20 Jan 2026 10:00:14 +0100","From":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","To":"Stefan Klug <stefan.klug@ideasonboard.com>","Cc":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>, \n\tlibcamera-devel@lists.libcamera.org,\n\tPaul Elder <paul.elder@ideasonboard.com>","Subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","Message-ID":"<aW9DuVQauFNYVvBm@zed>","References":"<20260120083952.15338-1-jacopo.mondi@ideasonboard.com>\n\t<176889918695.508107.16263205271582334087@localhost>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<176889918695.508107.16263205271582334087@localhost>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":37755,"web_url":"https://patchwork.libcamera.org/comment/37755/","msgid":"<176890024147.508107.10383913212138532634@localhost>","date":"2026-01-20T09:10:41","subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","submitter":{"id":184,"url":"https://patchwork.libcamera.org/api/people/184/","name":"Stefan Klug","email":"stefan.klug@ideasonboard.com"},"content":"Hi Jacopo,\n\nQuoting Jacopo Mondi (2026-01-20 10:00:14)\n> Hi Stefan\n> \n> On Tue, Jan 20, 2026 at 09:53:06AM +0100, Stefan Klug wrote:\n> > Hi Jacopo,\n> >\n> > Quoting Jacopo Mondi (2026-01-20 09:39:49)\n> > > Converting numbers with a signed fixed-point representation to\n> > > the corresponding float value requires to include the sign bit in the\n> > > width of the fixed-point integral part.\n> > >\n> > > Clearly specify it in documentation.\n> > >\n> > > Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n> > > ---\n> > >  src/ipa/libipa/fixedpoint.cpp | 22 +++++++++++++++++++++-\n> > >  1 file changed, 21 insertions(+), 1 deletion(-)\n> > >\n> > > diff --git a/src/ipa/libipa/fixedpoint.cpp b/src/ipa/libipa/fixedpoint.cpp\n> > > index 6b698fc5d680..b37cdc43936f 100644\n> > > --- a/src/ipa/libipa/fixedpoint.cpp\n> > > +++ b/src/ipa/libipa/fixedpoint.cpp\n> > > @@ -29,11 +29,31 @@ namespace ipa {\n> > >  /**\n> > >   * \\fn R fixedToFloatingPoint(T number)\n> > >   * \\brief Convert a fixed-point number to a floating point representation\n> > > - * \\tparam I Bit width of the integer part of the fixed-point\n> > > + * \\tparam I Bit width of the integer part of the fixed-point including the\n> > > + * optional sign bit\n> > >   * \\tparam F Bit width of the fractional part of the fixed-point\n> > >   * \\tparam R Return type of the floating point representation\n> > >   * \\tparam T Input type of the fixed-point representation\n> > >   * \\param number The fixed point number to convert to floating point\n> > > + *\n> > > + * If the fixed-point representation is signed, the sign bit shall be included\n> > > + * in the \\a I template parameter that specifies the number of bits of the\n> > > + * integral part of the fixed-point representation.\n> > > + *\n> > > + * As an example, a value represented as signed fixed-point Q4.8 format can be\n> > > + * converted to its corresponding floating point representation as:\n> >\n> > I'm a bit confused here. Doesn't signed Q4.8 mean that the first bit of\n> > the 4 is the sign bit? The same way a signed int32 has the signed bit on\n> > the first of the 32 bits?\n> \n> I'm right now looking at the datasheet documentation of a value said\n> to be in \"signed Q4.8\" format whose register size is 13 bits\n> \n> Coefft R-G [12:0] : sign/magnitude 4.8-bit fixed-point\n\nI should have consulted wikipedia first. https://en.wikipedia.org/wiki/Q_(number_format)\nclearly states that the sign bit is implicitely added.\n\nBest regards,\nStefan\n\n> \n> >\n> > Best regards,\n> > Stefan\n> >\n> > > + *\n> > > + * \\code{.cpp}\n> > > + * double d = fixedToFloatingPoint<5, 8, double, uint16_t>(fixed);\n> > > + * \\endcode\n> > > + *\n> > > + * While a value represented as unsigned fixed-point Q4.8 format can be\n> > > + * converted as:\n> > > + *\n> > > + * \\code{.cpp}\n> > > + * double d = fixedToFloatingPoint<4, 8, double, uint16_t>(fixed);\n> > > + * \\endcode\n> > > + *\n> > >   * \\return The converted value\n> > >   */\n> > >\n> > > --\n> > > 2.52.0\n> > >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id A91B7C3220\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 20 Jan 2026 09:10:46 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id C869161F84;\n\tTue, 20 Jan 2026 10:10:45 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id A9D6661F84\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 20 Jan 2026 10:10:44 +0100 (CET)","from ideasonboard.com (unknown\n\t[IPv6:2a00:6020:448c:6c00:7f76:a386:d798:7544])\n\tby perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id 92AF111DE; \n\tTue, 20 Jan 2026 10:10:13 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"co3qzrQA\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1768900213;\n\tbh=U6LGm4Y4+M/vxNHDtcScjU6/TmKT+y2+NRabmYY5Sqc=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=co3qzrQAlm9xUepJBqOhHhAFOQLZfzf59ndirIdjQ66T0p3V0Hi98U67HqnZoy18j\n\tM6Sk36tBPQkyxiKUVuxcsf7Mw6zGsfdnIjpneuilM9sFkdMbAURrKEGf6seqoFWUyM\n\tK8tafzjnNGES8lGao7AkxPg5wpmmCplQj6Sa7jQw=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<aW9DuVQauFNYVvBm@zed>","References":"<20260120083952.15338-1-jacopo.mondi@ideasonboard.com>\n\t<176889918695.508107.16263205271582334087@localhost>\n\t<aW9DuVQauFNYVvBm@zed>","Subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","From":"Stefan Klug <stefan.klug@ideasonboard.com>","Cc":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org,\n\tPaul Elder <paul.elder@ideasonboard.com>","To":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","Date":"Tue, 20 Jan 2026 10:10:41 +0100","Message-ID":"<176890024147.508107.10383913212138532634@localhost>","User-Agent":"alot/0.12.dev8+g2c003385c862.d20250602","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":37756,"web_url":"https://patchwork.libcamera.org/comment/37756/","msgid":"<6d89de31-511a-4932-9c58-05b94effc6dd@ideasonboard.com>","date":"2026-01-20T09:11:10","subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","submitter":{"id":216,"url":"https://patchwork.libcamera.org/api/people/216/","name":"Barnabás Pőcze","email":"barnabas.pocze@ideasonboard.com"},"content":"2026. 01. 20. 10:00 keltezéssel, Jacopo Mondi írta:\n> Hi Stefan\n> \n> On Tue, Jan 20, 2026 at 09:53:06AM +0100, Stefan Klug wrote:\n>> Hi Jacopo,\n>>\n>> Quoting Jacopo Mondi (2026-01-20 09:39:49)\n>>> Converting numbers with a signed fixed-point representation to\n>>> the corresponding float value requires to include the sign bit in the\n>>> width of the fixed-point integral part.\n>>>\n>>> Clearly specify it in documentation.\n>>>\n>>> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n>>> ---\n>>>   src/ipa/libipa/fixedpoint.cpp | 22 +++++++++++++++++++++-\n>>>   1 file changed, 21 insertions(+), 1 deletion(-)\n>>>\n>>> diff --git a/src/ipa/libipa/fixedpoint.cpp b/src/ipa/libipa/fixedpoint.cpp\n>>> index 6b698fc5d680..b37cdc43936f 100644\n>>> --- a/src/ipa/libipa/fixedpoint.cpp\n>>> +++ b/src/ipa/libipa/fixedpoint.cpp\n>>> @@ -29,11 +29,31 @@ namespace ipa {\n>>>   /**\n>>>    * \\fn R fixedToFloatingPoint(T number)\n>>>    * \\brief Convert a fixed-point number to a floating point representation\n>>> - * \\tparam I Bit width of the integer part of the fixed-point\n>>> + * \\tparam I Bit width of the integer part of the fixed-point including the\n>>> + * optional sign bit\n>>>    * \\tparam F Bit width of the fractional part of the fixed-point\n>>>    * \\tparam R Return type of the floating point representation\n>>>    * \\tparam T Input type of the fixed-point representation\n>>>    * \\param number The fixed point number to convert to floating point\n>>> + *\n>>> + * If the fixed-point representation is signed, the sign bit shall be included\n>>> + * in the \\a I template parameter that specifies the number of bits of the\n>>> + * integral part of the fixed-point representation.\n>>> + *\n>>> + * As an example, a value represented as signed fixed-point Q4.8 format can be\n>>> + * converted to its corresponding floating point representation as:\n>>\n>> I'm a bit confused here. Doesn't signed Q4.8 mean that the first bit of\n>> the 4 is the sign bit? The same way a signed int32 has the signed bit on\n>> the first of the 32 bits?\n\nIt would appear there are two interpretations: https://en.wikipedia.org/wiki/Q_(number_format)\n\n\"Texas Instruments version\": \"Thus, the total number w of bits used is 1 + m + n.\"\n\"ARM version\": \"A variant of the Q notation has been in use by ARM in which the m number also counts the sign bit.\"\n\n\n> \n> I'm right now looking at the datasheet documentation of a value said\n> to be in \"signed Q4.8\" format whose register size is 13 bits\n> \n> Coefft R-G [12:0] : sign/magnitude 4.8-bit fixed-point\n\nDoes that mean \"sign/magnitude\" as in https://en.wikipedia.org/wiki/Signed_number_representations#Sign–magnitude ?\nIf so, then I'm not sure these functions will work.\n\n\n> \n>>\n>> Best regards,\n>> Stefan\n>>\n>>> + *\n>>> + * \\code{.cpp}\n>>> + * double d = fixedToFloatingPoint<5, 8, double, uint16_t>(fixed);\n>>> + * \\endcode\n>>> + *\n>>> + * While a value represented as unsigned fixed-point Q4.8 format can be\n>>> + * converted as:\n>>> + *\n>>> + * \\code{.cpp}\n>>> + * double d = fixedToFloatingPoint<4, 8, double, uint16_t>(fixed);\n>>> + * \\endcode\n>>> + *\n>>>    * \\return The converted value\n>>>    */\n>>>\n>>> --\n>>> 2.52.0\n>>>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id CFFF4C3220\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 20 Jan 2026 09:11:14 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 7588161FC3;\n\tTue, 20 Jan 2026 10:11:14 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 3464561F84\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 20 Jan 2026 10:11:13 +0100 (CET)","from [192.168.33.23] (185.221.143.114.nat.pool.zt.hu\n\t[185.221.143.114])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 3153D11DE;\n\tTue, 20 Jan 2026 10:10:42 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"STEGzEsF\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1768900242;\n\tbh=/xWCNHj3FudtAi80dqaqtg2ttrdMvsii4PYXf1ZEoq4=;\n\th=Date:Subject:To:Cc:References:From:In-Reply-To:From;\n\tb=STEGzEsFLVlxKzYVQUfnFWvp30XQOtDiGQtoxvkGKSGYj+eF8BjLJ//wjc8hd8GDU\n\t3z8byp8HtrO4h5zU9qBC5hgCskdevGJUGygt1Pgm+CK59/Jal7YeznxbJBryxQcudH\n\tw3ENgrik/MzjgJ5EXZ+3xcKolx3UZuByfLHeHQYs=","Message-ID":"<6d89de31-511a-4932-9c58-05b94effc6dd@ideasonboard.com>","Date":"Tue, 20 Jan 2026 10:11:10 +0100","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","To":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>,\n\tStefan Klug <stefan.klug@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org,\n\tPaul Elder <paul.elder@ideasonboard.com>","References":"<20260120083952.15338-1-jacopo.mondi@ideasonboard.com>\n\t<176889918695.508107.16263205271582334087@localhost>\n\t<aW9DuVQauFNYVvBm@zed>","From":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>","Content-Language":"en-US, hu-HU","In-Reply-To":"<aW9DuVQauFNYVvBm@zed>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"8bit","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":37774,"web_url":"https://patchwork.libcamera.org/comment/37774/","msgid":"<aW-633il2AbfjBEJ@zed>","date":"2026-01-20T19:26:29","subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","submitter":{"id":143,"url":"https://patchwork.libcamera.org/api/people/143/","name":"Jacopo Mondi","email":"jacopo.mondi@ideasonboard.com"},"content":"Hi Barnabás\n\nOn Tue, Jan 20, 2026 at 10:11:10AM +0100, Barnabás Pőcze wrote:\n> 2026. 01. 20. 10:00 keltezéssel, Jacopo Mondi írta:\n> > Hi Stefan\n> >\n> > On Tue, Jan 20, 2026 at 09:53:06AM +0100, Stefan Klug wrote:\n> > > Hi Jacopo,\n> > >\n> > > Quoting Jacopo Mondi (2026-01-20 09:39:49)\n> > > > Converting numbers with a signed fixed-point representation to\n> > > > the corresponding float value requires to include the sign bit in the\n> > > > width of the fixed-point integral part.\n> > > >\n> > > > Clearly specify it in documentation.\n> > > >\n> > > > Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n> > > > ---\n> > > >   src/ipa/libipa/fixedpoint.cpp | 22 +++++++++++++++++++++-\n> > > >   1 file changed, 21 insertions(+), 1 deletion(-)\n> > > >\n> > > > diff --git a/src/ipa/libipa/fixedpoint.cpp b/src/ipa/libipa/fixedpoint.cpp\n> > > > index 6b698fc5d680..b37cdc43936f 100644\n> > > > --- a/src/ipa/libipa/fixedpoint.cpp\n> > > > +++ b/src/ipa/libipa/fixedpoint.cpp\n> > > > @@ -29,11 +29,31 @@ namespace ipa {\n> > > >   /**\n> > > >    * \\fn R fixedToFloatingPoint(T number)\n> > > >    * \\brief Convert a fixed-point number to a floating point representation\n> > > > - * \\tparam I Bit width of the integer part of the fixed-point\n> > > > + * \\tparam I Bit width of the integer part of the fixed-point including the\n> > > > + * optional sign bit\n> > > >    * \\tparam F Bit width of the fractional part of the fixed-point\n> > > >    * \\tparam R Return type of the floating point representation\n> > > >    * \\tparam T Input type of the fixed-point representation\n> > > >    * \\param number The fixed point number to convert to floating point\n> > > > + *\n> > > > + * If the fixed-point representation is signed, the sign bit shall be included\n> > > > + * in the \\a I template parameter that specifies the number of bits of the\n> > > > + * integral part of the fixed-point representation.\n> > > > + *\n> > > > + * As an example, a value represented as signed fixed-point Q4.8 format can be\n> > > > + * converted to its corresponding floating point representation as:\n> > >\n> > > I'm a bit confused here. Doesn't signed Q4.8 mean that the first bit of\n> > > the 4 is the sign bit? The same way a signed int32 has the signed bit on\n> > > the first of the 32 bits?\n>\n> It would appear there are two interpretations: https://en.wikipedia.org/wiki/Q_(number_format)\n>\n> \"Texas Instruments version\": \"Thus, the total number w of bits used is 1 + m + n.\"\n> \"ARM version\": \"A variant of the Q notation has been in use by ARM in which the m number also counts the sign bit.\"\n>\n>\n> >\n> > I'm right now looking at the datasheet documentation of a value said\n> > to be in \"signed Q4.8\" format whose register size is 13 bits\n> >\n> > Coefft R-G [12:0] : sign/magnitude 4.8-bit fixed-point\n>\n> Does that mean \"sign/magnitude\" as in https://en.wikipedia.org/wiki/Signed_number_representations#Sign–magnitude ?\n> If so, then I'm not sure these functions will work.\n\nI had just told Stefan \"I'm not sure I acutally know what 'magnitude'\nimplies there\", and I didn't :)\n\nSo, I had a bit of read around, including Kieran's Quantized type\nseries and I fell into a too familiarly deep rabbit hole.\n\n--------------------- TL;DR -----------------------------------------------\nFeel free to skip, these are mostly notes to clarify my understanding\n---------------------------------------------------------------------------\n\nLet's look at floatingToFixedPoint() remembering that\n\nf = float value\nq = value in Q<m,n>\n\n        f = q / 2^n\n        q = f * 2^n\n\nAnd that's what floatingToFixedPoint() does\n\ntemplate<unsigned int I, unsigned int F, typename R, typename T>\nconstexpr R floatingToFixedPoint(T number)\n{\n\tstatic_assert(sizeof(int) >= sizeof(R));\n\tstatic_assert(I + F <= sizeof(R) * 8);\n\n\tR mask = (1 << (F + I)) - 1;\n\tR frac = static_cast<R>(static_cast<int>(std::round(number * (1 << F)))) & mask;\n\n\treturn frac;\n}\n\nwich can be summarized as (n * 2^n & mask)\n\nAll good, but how is this handled if floatingToFixedPoint<>() is\ncalled as:\n        block->gain01 = floatingToFixedPoint<4, 8, uint16_t, double>(1.0);\n\n        uint16_t frac = static_cast<uint16_t>(\n                        static_cast<int>(std::round(1.0 * 2^8)) & mask;\n\n1.0 * 1^8 is a double\ncalling std::round(double) picks the right overload and returns a\ndouble\n\nthe double is cast to int. The C standard doesn't impose a\nrepresentation for signed integers and allows it to be either\nsign/magnitude, 1-complement or 2-complement. It's fair to assume\n2-complement is the standard and the C23 standard makes it so.\n\nSo, on a 64 bits platform we have the result of (1.0 * 2^8)\nrepresented as a signed 64-bit integers in 2-complement.\n\nAccording to the C standard, to cast a signed int to an unsigned int\n\n\"When a value with integer type is converted to another integer type\nother than _Bool, if the value can be represented by the new type, it\nis unchanged.\n\nOtherwise, if the new type is unsigned, the value is converted by\nrepeatedly adding or subtracting one more than the maximum value that\ncan be represented in the new type until the value is in the range of\nthe new type.\"\n\nAs vague as it might sound to me\n\n-43 + 2^16 = 65493 = 1111 1111 1101 0101\nwhich in 2-complement is ... -43\n\nAmazing, let's start from the beginning.\n\nI want to write to a 13 bits register the number -1.45 in signed Q<4.8>\nformat:\n\n        uint16_t q = floatingToFixedPoint<4, 8, uint16_t, double>(-1.45);\n\n        std::round(-1.45 * 2^8) = -371\n\n        static_cast<int>(-371) is stored as 2-complement in 64 bits\n        static_cast<int16_t>(-371) = -371 + 2^16 = 65165\n\n        65165 = 1111 1110 1000 1101\n\n        if we interpret this as a register value in Q<4,8> signed\n        format\n\n        xx11 1110 1000 1101\n\n        1 is the sign bit so let's calculate the 2 complement of\n        0  1110 1000 1101 = ~(1110 1000 1101) + 1 =\n                       =   0001 0111 0010 + 1 = 370 + 1 = 371\n\nAmazing!\n\n--------------------- End TL;DR -------------------------------------------\n\nNow, I want this in sign/magnitude. I bet there are smarter ways of\ndoing this but if I simply take the result of floatingToFixedPoint()\nand check the sign bit, I can simply add it back to absolute value of\nthe result ?\n\nAs a bit of pseudo code\n\n        int reg = static_cast<int>(std::round(number * (1 << F)))) & mask;\n        uint16_t res += std::abs(reg);\n        if (reg < 0)\n                res |= BIT(13);\n\nI think this could be surely optimized and nicely made a Traits that\ncan be added to the Quantized series Kieran is working on.\n\n>\n>\n> >\n> > >\n> > > Best regards,\n> > > Stefan\n> > >\n> > > > + *\n> > > > + * \\code{.cpp}\n> > > > + * double d = fixedToFloatingPoint<5, 8, double, uint16_t>(fixed);\n> > > > + * \\endcode\n> > > > + *\n> > > > + * While a value represented as unsigned fixed-point Q4.8 format can be\n> > > > + * converted as:\n> > > > + *\n> > > > + * \\code{.cpp}\n> > > > + * double d = fixedToFloatingPoint<4, 8, double, uint16_t>(fixed);\n> > > > + * \\endcode\n> > > > + *\n> > > >    * \\return The converted value\n> > > >    */\n> > > >\n> > > > --\n> > > > 2.52.0\n> > > >\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 87A6CBDCBF\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 20 Jan 2026 19:26:35 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id A1A8B61FC9;\n\tTue, 20 Jan 2026 20:26:34 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 8B67C61A35\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 20 Jan 2026 20:26:32 +0100 (CET)","from ideasonboard.com (net-93-65-100-155.cust.vodafonedsl.it\n\t[93.65.100.155])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 059AD2169;\n\tTue, 20 Jan 2026 20:26:00 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"h7q41qGg\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1768937161;\n\tbh=KUYhdzZDHwLffba8Y7cA76sfi6VoaWtaiKoLuUGWhuA=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=h7q41qGg+sCwCQf+FlnmW5Ed9k3GbLuyDkqc8KjN+edvegidEtp9tY3ci5GjSY9Yp\n\tyqyP6o2k3CM0Eh8t1Nc6RUyGuFYSU7VPds/KwuE5ZhFhLdHEEYBX7eWYQ5mdtlo+nF\n\tSxnjgmTPyLgtl6+WB1Qsh5PAox9YyXhoq/8KF2XE=","Date":"Tue, 20 Jan 2026 20:26:29 +0100","From":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","To":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>","Cc":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>, \n\tStefan Klug <stefan.klug@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org, \n\tPaul Elder <paul.elder@ideasonboard.com>","Subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","Message-ID":"<aW-633il2AbfjBEJ@zed>","References":"<20260120083952.15338-1-jacopo.mondi@ideasonboard.com>\n\t<176889918695.508107.16263205271582334087@localhost>\n\t<aW9DuVQauFNYVvBm@zed>\n\t<6d89de31-511a-4932-9c58-05b94effc6dd@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<6d89de31-511a-4932-9c58-05b94effc6dd@ideasonboard.com>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":37775,"web_url":"https://patchwork.libcamera.org/comment/37775/","msgid":"<20260120212342.GA173080@killaraus>","date":"2026-01-20T21:23:42","subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"On Tue, Jan 20, 2026 at 08:26:29PM +0100, Jacopo Mondi wrote:\n> On Tue, Jan 20, 2026 at 10:11:10AM +0100, Barnabás Pőcze wrote:\n> > 2026. 01. 20. 10:00 keltezéssel, Jacopo Mondi írta:\n> > > On Tue, Jan 20, 2026 at 09:53:06AM +0100, Stefan Klug wrote:\n> > > > Quoting Jacopo Mondi (2026-01-20 09:39:49)\n> > > > > Converting numbers with a signed fixed-point representation to\n> > > > > the corresponding float value requires to include the sign bit in the\n> > > > > width of the fixed-point integral part.\n> > > > >\n> > > > > Clearly specify it in documentation.\n> > > > >\n> > > > > Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n> > > > > ---\n> > > > >   src/ipa/libipa/fixedpoint.cpp | 22 +++++++++++++++++++++-\n> > > > >   1 file changed, 21 insertions(+), 1 deletion(-)\n> > > > >\n> > > > > diff --git a/src/ipa/libipa/fixedpoint.cpp b/src/ipa/libipa/fixedpoint.cpp\n> > > > > index 6b698fc5d680..b37cdc43936f 100644\n> > > > > --- a/src/ipa/libipa/fixedpoint.cpp\n> > > > > +++ b/src/ipa/libipa/fixedpoint.cpp\n> > > > > @@ -29,11 +29,31 @@ namespace ipa {\n> > > > >   /**\n> > > > >    * \\fn R fixedToFloatingPoint(T number)\n> > > > >    * \\brief Convert a fixed-point number to a floating point representation\n> > > > > - * \\tparam I Bit width of the integer part of the fixed-point\n> > > > > + * \\tparam I Bit width of the integer part of the fixed-point including the\n> > > > > + * optional sign bit\n> > > > >    * \\tparam F Bit width of the fractional part of the fixed-point\n> > > > >    * \\tparam R Return type of the floating point representation\n> > > > >    * \\tparam T Input type of the fixed-point representation\n> > > > >    * \\param number The fixed point number to convert to floating point\n> > > > > + *\n> > > > > + * If the fixed-point representation is signed, the sign bit shall be included\n> > > > > + * in the \\a I template parameter that specifies the number of bits of the\n> > > > > + * integral part of the fixed-point representation.\n> > > > > + *\n> > > > > + * As an example, a value represented as signed fixed-point Q4.8 format can be\n> > > > > + * converted to its corresponding floating point representation as:\n> > > >\n> > > > I'm a bit confused here. Doesn't signed Q4.8 mean that the first bit of\n> > > > the 4 is the sign bit? The same way a signed int32 has the signed bit on\n> > > > the first of the 32 bits?\n> >\n> > It would appear there are two interpretations: https://en.wikipedia.org/wiki/Q_(number_format)\n> >\n> > \"Texas Instruments version\": \"Thus, the total number w of bits used is 1 + m + n.\"\n> > \"ARM version\": \"A variant of the Q notation has been in use by ARM in which the m number also counts the sign bit.\"\n> >\n> > > I'm right now looking at the datasheet documentation of a value said\n> > > to be in \"signed Q4.8\" format whose register size is 13 bits\n> > >\n> > > Coefft R-G [12:0] : sign/magnitude 4.8-bit fixed-point\n> >\n> > Does that mean \"sign/magnitude\" as in https://en.wikipedia.org/wiki/Signed_number_representations#Sign–magnitude ?\n> > If so, then I'm not sure these functions will work.\n> \n> I had just told Stefan \"I'm not sure I acutally know what 'magnitude'\n> implies there\", and I didn't :)\n> \n> So, I had a bit of read around, including Kieran's Quantized type\n> series and I fell into a too familiarly deep rabbit hole.\n> \n> --------------------- TL;DR -----------------------------------------------\n> Feel free to skip, these are mostly notes to clarify my understanding\n> ---------------------------------------------------------------------------\n> \n> Let's look at floatingToFixedPoint() remembering that\n> \n> f = float value\n> q = value in Q<m,n>\n> \n>         f = q / 2^n\n>         q = f * 2^n\n> \n> And that's what floatingToFixedPoint() does\n> \n> template<unsigned int I, unsigned int F, typename R, typename T>\n> constexpr R floatingToFixedPoint(T number)\n> {\n> \tstatic_assert(sizeof(int) >= sizeof(R));\n> \tstatic_assert(I + F <= sizeof(R) * 8);\n> \n> \tR mask = (1 << (F + I)) - 1;\n> \tR frac = static_cast<R>(static_cast<int>(std::round(number * (1 << F)))) & mask;\n> \n> \treturn frac;\n> }\n> \n> wich can be summarized as (n * 2^n & mask)\n> \n> All good, but how is this handled if floatingToFixedPoint<>() is\n> called as:\n>         block->gain01 = floatingToFixedPoint<4, 8, uint16_t, double>(1.0);\n> \n>         uint16_t frac = static_cast<uint16_t>(\n>                         static_cast<int>(std::round(1.0 * 2^8)) & mask;\n> \n> 1.0 * 1^8 is a double\n> calling std::round(double) picks the right overload and returns a\n> double\n> \n> the double is cast to int. The C standard doesn't impose a\n> representation for signed integers and allows it to be either\n> sign/magnitude, 1-complement or 2-complement. It's fair to assume\n> 2-complement is the standard and the C23 standard makes it so.\n> \n> So, on a 64 bits platform we have the result of (1.0 * 2^8)\n> represented as a signed 64-bit integers in 2-complement.\n> \n> According to the C standard, to cast a signed int to an unsigned int\n> \n> \"When a value with integer type is converted to another integer type\n> other than _Bool, if the value can be represented by the new type, it\n> is unchanged.\n> \n> Otherwise, if the new type is unsigned, the value is converted by\n> repeatedly adding or subtracting one more than the maximum value that\n> can be represented in the new type until the value is in the range of\n> the new type.\"\n> \n> As vague as it might sound to me\n> \n> -43 + 2^16 = 65493 = 1111 1111 1101 0101\n> which in 2-complement is ... -43\n> \n> Amazing, let's start from the beginning.\n> \n> I want to write to a 13 bits register the number -1.45 in signed Q<4.8>\n> format:\n> \n>         uint16_t q = floatingToFixedPoint<4, 8, uint16_t, double>(-1.45);\n> \n>         std::round(-1.45 * 2^8) = -371\n> \n>         static_cast<int>(-371) is stored as 2-complement in 64 bits\n>         static_cast<int16_t>(-371) = -371 + 2^16 = 65165\n> \n>         65165 = 1111 1110 1000 1101\n> \n>         if we interpret this as a register value in Q<4,8> signed\n>         format\n> \n>         xx11 1110 1000 1101\n> \n>         1 is the sign bit so let's calculate the 2 complement of\n>         0  1110 1000 1101 = ~(1110 1000 1101) + 1 =\n>                        =   0001 0111 0010 + 1 = 370 + 1 = 371\n> \n> Amazing!\n> \n> --------------------- End TL;DR -------------------------------------------\n> \n> Now, I want this in sign/magnitude. I bet there are smarter ways of\n> doing this but if I simply take the result of floatingToFixedPoint()\n> and check the sign bit, I can simply add it back to absolute value of\n> the result ?\n> \n> As a bit of pseudo code\n> \n>         int reg = static_cast<int>(std::round(number * (1 << F)))) & mask;\n>         uint16_t res += std::abs(reg);\n>         if (reg < 0)\n>                 res |= BIT(13);\n> \n> I think this could be surely optimized and nicely made a Traits that\n> can be added to the Quantized series Kieran is working on.\n\nI think you should first test to see if \"sign-magnitude\" mentioned in\nthe datasheet actually means that, or if it's a signed fixed-point\nvalue. If it's the former we'll see how to support it.\n\n> > > > > + *\n> > > > > + * \\code{.cpp}\n> > > > > + * double d = fixedToFloatingPoint<5, 8, double, uint16_t>(fixed);\n> > > > > + * \\endcode\n> > > > > + *\n> > > > > + * While a value represented as unsigned fixed-point Q4.8 format can be\n> > > > > + * converted as:\n> > > > > + *\n> > > > > + * \\code{.cpp}\n> > > > > + * double d = fixedToFloatingPoint<4, 8, double, uint16_t>(fixed);\n> > > > > + * \\endcode\n> > > > > + *\n> > > > >    * \\return The converted value\n> > > > >    */","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 578F0C3220\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 20 Jan 2026 21:23:46 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id A6CA961FCA;\n\tTue, 20 Jan 2026 22:23:45 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 227E361A35\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 20 Jan 2026 22:23:44 +0100 (CET)","from pendragon.ideasonboard.com\n\t(2001-14ba-703d-e500--2a1.rev.dnainternet.fi\n\t[IPv6:2001:14ba:703d:e500::2a1])\n\tby perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id 8852CC6C;\n\tTue, 20 Jan 2026 22:23:12 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"jaBBBUe7\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1768944192;\n\tbh=qJ8pGTWPdIi4PuDgXTPrWqC8pAQ655fK7kAIGEJr1AM=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=jaBBBUe72nwFJgoOOY4ylflDbvL1Y24AfAIUknq/8MwDw4W4/mBxA1YooojUly8fA\n\tr6hXLT4azH/2RmX5NHV/RG4hTSYPthQoFVxTjrCqUldNrLa/vO28yGMFleO8Mfs1Ni\n\tBgC1+X4BzBfuMkBcKy9IJNKHg9lcQ/BWIO1oScvI=","Date":"Tue, 20 Jan 2026 23:23:42 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","Cc":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>,\n\tStefan Klug <stefan.klug@ideasonboard.com>, \n\tlibcamera-devel@lists.libcamera.org, Paul Elder\n\t<paul.elder@ideasonboard.com>","Subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","Message-ID":"<20260120212342.GA173080@killaraus>","References":"<20260120083952.15338-1-jacopo.mondi@ideasonboard.com>\n\t<176889918695.508107.16263205271582334087@localhost>\n\t<aW9DuVQauFNYVvBm@zed>\n\t<6d89de31-511a-4932-9c58-05b94effc6dd@ideasonboard.com>\n\t<aW-633il2AbfjBEJ@zed>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<aW-633il2AbfjBEJ@zed>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":37788,"web_url":"https://patchwork.libcamera.org/comment/37788/","msgid":"<176899822075.3544004.689251715744219495@ping.linuxembedded.co.uk>","date":"2026-01-21T12:23:40","subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Hi Jacopo,\n\nQuoting Stefan Klug (2026-01-20 08:53:06)\n> Hi Jacopo,\n> \n> Quoting Jacopo Mondi (2026-01-20 09:39:49)\n> > Converting numbers with a signed fixed-point representation to\n> > the corresponding float value requires to include the sign bit in the\n> > width of the fixed-point integral part.\n> > \n> > Clearly specify it in documentation.\n> > \n> > Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n> > ---\n> >  src/ipa/libipa/fixedpoint.cpp | 22 +++++++++++++++++++++-\n> >  1 file changed, 21 insertions(+), 1 deletion(-)\n> > \n> > diff --git a/src/ipa/libipa/fixedpoint.cpp b/src/ipa/libipa/fixedpoint.cpp\n> > index 6b698fc5d680..b37cdc43936f 100644\n> > --- a/src/ipa/libipa/fixedpoint.cpp\n> > +++ b/src/ipa/libipa/fixedpoint.cpp\n> > @@ -29,11 +29,31 @@ namespace ipa {\n> >  /**\n> >   * \\fn R fixedToFloatingPoint(T number)\n> >   * \\brief Convert a fixed-point number to a floating point representation\n> > - * \\tparam I Bit width of the integer part of the fixed-point\n> > + * \\tparam I Bit width of the integer part of the fixed-point including the\n> > + * optional sign bit\n> >   * \\tparam F Bit width of the fractional part of the fixed-point\n> >   * \\tparam R Return type of the floating point representation\n> >   * \\tparam T Input type of the fixed-point representation\n> >   * \\param number The fixed point number to convert to floating point\n> > + *\n> > + * If the fixed-point representation is signed, the sign bit shall be included\n> > + * in the \\a I template parameter that specifies the number of bits of the\n> > + * integral part of the fixed-point representation.\n> > + *\n> > + * As an example, a value represented as signed fixed-point Q4.8 format can be\n> > + * converted to its corresponding floating point representation as:\n\nJust to be sure - you know I've got patches to remove all of the above\nthat I want to get merged 'soon' right?\n\nQuantized brings in explicit signed/unsigned types through Q<4,8> and\nUQ<4, 8> types.\n\nIn the new types Q<I, F> has the sign bit included in 'I'.\nI can add that explicitly to the documentation in my new series for v6.\n\n\n\"\"\"\n * The sign of the value is determined by the sign of \\a T. For signed types,\n * the number of integer bits includes the sign bit.\n\"\"\"\n\n--\nKieran\n\n> I'm a bit confused here. Doesn't signed Q4.8 mean that the first bit of\n> the 4 is the sign bit? The same way a signed int32 has the signed bit on\n> the first of the 32 bits?\n> \n> Best regards,\n> Stefan\n> \n> > + *\n> > + * \\code{.cpp}\n> > + * double d = fixedToFloatingPoint<5, 8, double, uint16_t>(fixed);\n> > + * \\endcode\n> > + *\n> > + * While a value represented as unsigned fixed-point Q4.8 format can be\n> > + * converted as:\n> > + *\n> > + * \\code{.cpp}\n> > + * double d = fixedToFloatingPoint<4, 8, double, uint16_t>(fixed);\n> > + * \\endcode\n> > + *\n> >   * \\return The converted value\n> >   */\n> > \n> > --\n> > 2.52.0\n> >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id D7C8AC3220\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 21 Jan 2026 12:23:46 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id E10D561FCA;\n\tWed, 21 Jan 2026 13:23:45 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 9831861F9F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 21 Jan 2026 13:23:43 +0100 (CET)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust6594.18-1.cable.virginm.net [86.31.185.195])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id BFAC3741;\n\tWed, 21 Jan 2026 13:23:11 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"H97MOl7M\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1768998191;\n\tbh=B9pKzfJ1zSBfYlBSRYC9UzWzkontKCMAGjYfJCR9MjU=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=H97MOl7Mnm7jAfg3HoB7mADRpW88XuktiPuaANRbCax1P+m5vWDEgYJSPtoGNF43+\n\tUQ0DXgysofWTjBQD/lDzTTO3yitbuCbciKzc/OQW8ftL/IFHhV2sEWYap2+lI+U9iq\n\tKBgpIaoeMTC6aLWNuRZZKn0wZ0D0vmn+ldoy7cF4=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<176889918695.508107.16263205271582334087@localhost>","References":"<20260120083952.15338-1-jacopo.mondi@ideasonboard.com>\n\t<176889918695.508107.16263205271582334087@localhost>","Subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>,\n\tPaul Elder <paul.elder@ideasonboard.com>","To":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>,\n\tStefan Klug <stefan.klug@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","Date":"Wed, 21 Jan 2026 12:23:40 +0000","Message-ID":"<176899822075.3544004.689251715744219495@ping.linuxembedded.co.uk>","User-Agent":"alot/0.9.1","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":37789,"web_url":"https://patchwork.libcamera.org/comment/37789/","msgid":"<aXDI56yl6xve-_UK@zed>","date":"2026-01-21T12:42:00","subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","submitter":{"id":143,"url":"https://patchwork.libcamera.org/api/people/143/","name":"Jacopo Mondi","email":"jacopo.mondi@ideasonboard.com"},"content":"Hi Laurent\n\nOn Tue, Jan 20, 2026 at 11:23:42PM +0200, Laurent Pinchart wrote:\n> On Tue, Jan 20, 2026 at 08:26:29PM +0100, Jacopo Mondi wrote:\n> > On Tue, Jan 20, 2026 at 10:11:10AM +0100, Barnabás Pőcze wrote:\n> > > 2026. 01. 20. 10:00 keltezéssel, Jacopo Mondi írta:\n> > > > On Tue, Jan 20, 2026 at 09:53:06AM +0100, Stefan Klug wrote:\n> > > > > Quoting Jacopo Mondi (2026-01-20 09:39:49)\n> > > > > > Converting numbers with a signed fixed-point representation to\n> > > > > > the corresponding float value requires to include the sign bit in the\n> > > > > > width of the fixed-point integral part.\n> > > > > >\n> > > > > > Clearly specify it in documentation.\n> > > > > >\n> > > > > > Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n> > > > > > ---\n> > > > > >   src/ipa/libipa/fixedpoint.cpp | 22 +++++++++++++++++++++-\n> > > > > >   1 file changed, 21 insertions(+), 1 deletion(-)\n> > > > > >\n> > > > > > diff --git a/src/ipa/libipa/fixedpoint.cpp b/src/ipa/libipa/fixedpoint.cpp\n> > > > > > index 6b698fc5d680..b37cdc43936f 100644\n> > > > > > --- a/src/ipa/libipa/fixedpoint.cpp\n> > > > > > +++ b/src/ipa/libipa/fixedpoint.cpp\n> > > > > > @@ -29,11 +29,31 @@ namespace ipa {\n> > > > > >   /**\n> > > > > >    * \\fn R fixedToFloatingPoint(T number)\n> > > > > >    * \\brief Convert a fixed-point number to a floating point representation\n> > > > > > - * \\tparam I Bit width of the integer part of the fixed-point\n> > > > > > + * \\tparam I Bit width of the integer part of the fixed-point including the\n> > > > > > + * optional sign bit\n> > > > > >    * \\tparam F Bit width of the fractional part of the fixed-point\n> > > > > >    * \\tparam R Return type of the floating point representation\n> > > > > >    * \\tparam T Input type of the fixed-point representation\n> > > > > >    * \\param number The fixed point number to convert to floating point\n> > > > > > + *\n> > > > > > + * If the fixed-point representation is signed, the sign bit shall be included\n> > > > > > + * in the \\a I template parameter that specifies the number of bits of the\n> > > > > > + * integral part of the fixed-point representation.\n> > > > > > + *\n> > > > > > + * As an example, a value represented as signed fixed-point Q4.8 format can be\n> > > > > > + * converted to its corresponding floating point representation as:\n> > > > >\n> > > > > I'm a bit confused here. Doesn't signed Q4.8 mean that the first bit of\n> > > > > the 4 is the sign bit? The same way a signed int32 has the signed bit on\n> > > > > the first of the 32 bits?\n> > >\n> > > It would appear there are two interpretations: https://en.wikipedia.org/wiki/Q_(number_format)\n> > >\n> > > \"Texas Instruments version\": \"Thus, the total number w of bits used is 1 + m + n.\"\n> > > \"ARM version\": \"A variant of the Q notation has been in use by ARM in which the m number also counts the sign bit.\"\n> > >\n> > > > I'm right now looking at the datasheet documentation of a value said\n> > > > to be in \"signed Q4.8\" format whose register size is 13 bits\n> > > >\n> > > > Coefft R-G [12:0] : sign/magnitude 4.8-bit fixed-point\n> > >\n> > > Does that mean \"sign/magnitude\" as in https://en.wikipedia.org/wiki/Signed_number_representations#Sign–magnitude ?\n> > > If so, then I'm not sure these functions will work.\n> >\n> > I had just told Stefan \"I'm not sure I acutally know what 'magnitude'\n> > implies there\", and I didn't :)\n> >\n> > So, I had a bit of read around, including Kieran's Quantized type\n> > series and I fell into a too familiarly deep rabbit hole.\n> >\n> > --------------------- TL;DR -----------------------------------------------\n> > Feel free to skip, these are mostly notes to clarify my understanding\n> > ---------------------------------------------------------------------------\n> >\n> > Let's look at floatingToFixedPoint() remembering that\n> >\n> > f = float value\n> > q = value in Q<m,n>\n> >\n> >         f = q / 2^n\n> >         q = f * 2^n\n> >\n> > And that's what floatingToFixedPoint() does\n> >\n> > template<unsigned int I, unsigned int F, typename R, typename T>\n> > constexpr R floatingToFixedPoint(T number)\n> > {\n> > \tstatic_assert(sizeof(int) >= sizeof(R));\n> > \tstatic_assert(I + F <= sizeof(R) * 8);\n> >\n> > \tR mask = (1 << (F + I)) - 1;\n> > \tR frac = static_cast<R>(static_cast<int>(std::round(number * (1 << F)))) & mask;\n> >\n> > \treturn frac;\n> > }\n> >\n> > wich can be summarized as (n * 2^n & mask)\n> >\n> > All good, but how is this handled if floatingToFixedPoint<>() is\n> > called as:\n> >         block->gain01 = floatingToFixedPoint<4, 8, uint16_t, double>(1.0);\n> >\n> >         uint16_t frac = static_cast<uint16_t>(\n> >                         static_cast<int>(std::round(1.0 * 2^8)) & mask;\n> >\n> > 1.0 * 1^8 is a double\n> > calling std::round(double) picks the right overload and returns a\n> > double\n> >\n> > the double is cast to int. The C standard doesn't impose a\n> > representation for signed integers and allows it to be either\n> > sign/magnitude, 1-complement or 2-complement. It's fair to assume\n> > 2-complement is the standard and the C23 standard makes it so.\n> >\n> > So, on a 64 bits platform we have the result of (1.0 * 2^8)\n> > represented as a signed 64-bit integers in 2-complement.\n> >\n> > According to the C standard, to cast a signed int to an unsigned int\n> >\n> > \"When a value with integer type is converted to another integer type\n> > other than _Bool, if the value can be represented by the new type, it\n> > is unchanged.\n> >\n> > Otherwise, if the new type is unsigned, the value is converted by\n> > repeatedly adding or subtracting one more than the maximum value that\n> > can be represented in the new type until the value is in the range of\n> > the new type.\"\n> >\n> > As vague as it might sound to me\n> >\n> > -43 + 2^16 = 65493 = 1111 1111 1101 0101\n> > which in 2-complement is ... -43\n> >\n> > Amazing, let's start from the beginning.\n> >\n> > I want to write to a 13 bits register the number -1.45 in signed Q<4.8>\n> > format:\n> >\n> >         uint16_t q = floatingToFixedPoint<4, 8, uint16_t, double>(-1.45);\n> >\n> >         std::round(-1.45 * 2^8) = -371\n> >\n> >         static_cast<int>(-371) is stored as 2-complement in 64 bits\n> >         static_cast<int16_t>(-371) = -371 + 2^16 = 65165\n> >\n> >         65165 = 1111 1110 1000 1101\n> >\n> >         if we interpret this as a register value in Q<4,8> signed\n> >         format\n> >\n> >         xx11 1110 1000 1101\n> >\n> >         1 is the sign bit so let's calculate the 2 complement of\n> >         0  1110 1000 1101 = ~(1110 1000 1101) + 1 =\n> >                        =   0001 0111 0010 + 1 = 370 + 1 = 371\n> >\n> > Amazing!\n> >\n> > --------------------- End TL;DR -------------------------------------------\n> >\n> > Now, I want this in sign/magnitude. I bet there are smarter ways of\n> > doing this but if I simply take the result of floatingToFixedPoint()\n> > and check the sign bit, I can simply add it back to absolute value of\n> > the result ?\n> >\n> > As a bit of pseudo code\n> >\n> >         int reg = static_cast<int>(std::round(number * (1 << F)))) & mask;\n> >         uint16_t res += std::abs(reg);\n> >         if (reg < 0)\n> >                 res |= BIT(13);\n> >\n> > I think this could be surely optimized and nicely made a Traits that\n> > can be added to the Quantized series Kieran is working on.\n>\n> I think you should first test to see if \"sign-magnitude\" mentioned in\n> the datasheet actually means that, or if it's a signed fixed-point\n> value. If it's the former we'll see how to support it.\n\nConsider that other registers are said to be:\n- unsigned 4.8-bit fixed-poin\nor\n- signed (2's complement) 11-bit integer\n\nWhile these are specifically described as:\n- sign/magnitude 4.8-bit fixed-point\n\nI would tend to believe it actually is correct, but I can check with\nthe vendor maybe\n\n>\n> > > > > > + *\n> > > > > > + * \\code{.cpp}\n> > > > > > + * double d = fixedToFloatingPoint<5, 8, double, uint16_t>(fixed);\n> > > > > > + * \\endcode\n> > > > > > + *\n> > > > > > + * While a value represented as unsigned fixed-point Q4.8 format can be\n> > > > > > + * converted as:\n> > > > > > + *\n> > > > > > + * \\code{.cpp}\n> > > > > > + * double d = fixedToFloatingPoint<4, 8, double, uint16_t>(fixed);\n> > > > > > + * \\endcode\n> > > > > > + *\n> > > > > >    * \\return The converted value\n> > > > > >    */\n>\n> --\n> Regards,\n>\n> Laurent Pinchart","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 6243FBDCBF\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 21 Jan 2026 12:42:06 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 6EEDB61FC4;\n\tWed, 21 Jan 2026 13:42:05 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 3B37361F9F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 21 Jan 2026 13:42:04 +0100 (CET)","from ideasonboard.com (static.170.20.224.46.clients.your-server.de\n\t[46.224.20.170])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 22D16741;\n\tWed, 21 Jan 2026 13:41:32 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"AaOQmMdF\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1768999292;\n\tbh=ToZePwaHXFWSfYAy9e9cT9ATTmKWXhktp4P8a4JQyLw=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=AaOQmMdFU+ZChkgDVBBM6VYM4KdXETOnbI55tiFfzsRJNpDrTMG0ReNt2stVEe4S5\n\tOf0g/Yt1UREspNO/9sT8E1JJhwXthnFgF/JGUP4O/NHEH4EQYpFKNFGBgmfJHjqwT5\n\tKaiN3qM9o4SPqA/tzJeO6gcZLVt+RhW1WXO8Qptk=","Date":"Wed, 21 Jan 2026 13:42:00 +0100","From":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>, =?utf-8?b?QmFybmFiw6Fz?=\n\t=?utf-8?q?_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>, Stefan Klug\n\t<stefan.klug@ideasonboard.com>, libcamera-devel@lists.libcamera.org,\n\tPaul Elder <paul.elder@ideasonboard.com>","Subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","Message-ID":"<aXDI56yl6xve-_UK@zed>","References":"<20260120083952.15338-1-jacopo.mondi@ideasonboard.com>\n\t<176889918695.508107.16263205271582334087@localhost>\n\t<aW9DuVQauFNYVvBm@zed>\n\t<6d89de31-511a-4932-9c58-05b94effc6dd@ideasonboard.com>\n\t<aW-633il2AbfjBEJ@zed> <20260120212342.GA173080@killaraus>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20260120212342.GA173080@killaraus>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":37791,"web_url":"https://patchwork.libcamera.org/comment/37791/","msgid":"<aXDJol4kIvRx6_49@zed>","date":"2026-01-21T12:53:49","subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","submitter":{"id":143,"url":"https://patchwork.libcamera.org/api/people/143/","name":"Jacopo Mondi","email":"jacopo.mondi@ideasonboard.com"},"content":"Hi Kieran\n\nOn Wed, Jan 21, 2026 at 12:23:40PM +0000, Kieran Bingham wrote:\n> Hi Jacopo,\n>\n> Quoting Stefan Klug (2026-01-20 08:53:06)\n> > Hi Jacopo,\n> >\n> > Quoting Jacopo Mondi (2026-01-20 09:39:49)\n> > > Converting numbers with a signed fixed-point representation to\n> > > the corresponding float value requires to include the sign bit in the\n> > > width of the fixed-point integral part.\n> > >\n> > > Clearly specify it in documentation.\n> > >\n> > > Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n> > > ---\n> > >  src/ipa/libipa/fixedpoint.cpp | 22 +++++++++++++++++++++-\n> > >  1 file changed, 21 insertions(+), 1 deletion(-)\n> > >\n> > > diff --git a/src/ipa/libipa/fixedpoint.cpp b/src/ipa/libipa/fixedpoint.cpp\n> > > index 6b698fc5d680..b37cdc43936f 100644\n> > > --- a/src/ipa/libipa/fixedpoint.cpp\n> > > +++ b/src/ipa/libipa/fixedpoint.cpp\n> > > @@ -29,11 +29,31 @@ namespace ipa {\n> > >  /**\n> > >   * \\fn R fixedToFloatingPoint(T number)\n> > >   * \\brief Convert a fixed-point number to a floating point representation\n> > > - * \\tparam I Bit width of the integer part of the fixed-point\n> > > + * \\tparam I Bit width of the integer part of the fixed-point including the\n> > > + * optional sign bit\n> > >   * \\tparam F Bit width of the fractional part of the fixed-point\n> > >   * \\tparam R Return type of the floating point representation\n> > >   * \\tparam T Input type of the fixed-point representation\n> > >   * \\param number The fixed point number to convert to floating point\n> > > + *\n> > > + * If the fixed-point representation is signed, the sign bit shall be included\n> > > + * in the \\a I template parameter that specifies the number of bits of the\n> > > + * integral part of the fixed-point representation.\n> > > + *\n> > > + * As an example, a value represented as signed fixed-point Q4.8 format can be\n> > > + * converted to its corresponding floating point representation as:\n>\n> Just to be sure - you know I've got patches to remove all of the above\n> that I want to get merged 'soon' right?\n\nRead the last bit of my reply from yesterday :)\n\n>\n> Quantized brings in explicit signed/unsigned types through Q<4,8> and\n> UQ<4, 8> types.\n\nWhat is the difference between signed and unsigned ? Is it only the\nsign bit ? I guess then that the Q<4,8>[12:0] = UQ<4,8>[11:0]\n\n>\n> In the new types Q<I, F> has the sign bit included in 'I'.\n> I can add that explicitly to the documentation in my new series for v6.\n\n\nWell, maybe we need two traits ?\nhttps://en.wikipedia.org/wiki/Q_(number_format)\n\nTexas Instruments version:\nThe first bit always gives the sign of the value (1 = negative, 0 =\nnon-negative), and it is not counted in the m parameter. Thus, the\ntotal number w of bits used is 1 + m + n.\n\nARM Version:\nA variant of the Q notation has been in use by ARM in which the m\nnumber also counts the sign bit\n\nI guess the only way to know which one is meant to be used is to\nactually look at the register sizes. If a Q<4,8> number is stored as\na 13 bit fields, then the TI version is used. I wonder how common the\nARM version is.\n\n>\n>\n> \"\"\"\n>  * The sign of the value is determined by the sign of \\a T. For signed types,\n>  * the number of integer bits includes the sign bit.\n> \"\"\"\n>\n> --\n> Kieran\n>\n> > I'm a bit confused here. Doesn't signed Q4.8 mean that the first bit of\n> > the 4 is the sign bit? The same way a signed int32 has the signed bit on\n> > the first of the 32 bits?\n> >\n> > Best regards,\n> > Stefan\n> >\n> > > + *\n> > > + * \\code{.cpp}\n> > > + * double d = fixedToFloatingPoint<5, 8, double, uint16_t>(fixed);\n> > > + * \\endcode\n> > > + *\n> > > + * While a value represented as unsigned fixed-point Q4.8 format can be\n> > > + * converted as:\n> > > + *\n> > > + * \\code{.cpp}\n> > > + * double d = fixedToFloatingPoint<4, 8, double, uint16_t>(fixed);\n> > > + * \\endcode\n> > > + *\n> > >   * \\return The converted value\n> > >   */\n> > >\n> > > --\n> > > 2.52.0\n> > >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 1DE4CC3220\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 21 Jan 2026 12:53:55 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id ADB0961FC9;\n\tWed, 21 Jan 2026 13:53:54 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 8354C61F9F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 21 Jan 2026 13:53:53 +0100 (CET)","from ideasonboard.com (static.170.20.224.46.clients.your-server.de\n\t[46.224.20.170])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 9D2CC741;\n\tWed, 21 Jan 2026 13:53:20 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"NKgsEkXz\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1769000000;\n\tbh=MP3ihv+yqTlL9c7hn2DEkDPnoxv9kOGtleKB42Mkh8A=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=NKgsEkXzGNaydKk6nTvkTbFkWmklSCZwtWp74H9tP+DrSLioCXR0dJWdvj6hckNBD\n\th85Zv0k8sytIbQJaGaFWykS8pLTVlZlwYXgKxbqT8yOnRoSWhr5z9nABrq8ugU2R6F\n\tjuw6QCfKERBLKXKdyoDN106B3ghnkauXaQGD+FkY=","Date":"Wed, 21 Jan 2026 13:53:49 +0100","From":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>, \n\tStefan Klug <stefan.klug@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org, \n\tPaul Elder <paul.elder@ideasonboard.com>","Subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","Message-ID":"<aXDJol4kIvRx6_49@zed>","References":"<20260120083952.15338-1-jacopo.mondi@ideasonboard.com>\n\t<176889918695.508107.16263205271582334087@localhost>\n\t<176899822075.3544004.689251715744219495@ping.linuxembedded.co.uk>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<176899822075.3544004.689251715744219495@ping.linuxembedded.co.uk>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":37796,"web_url":"https://patchwork.libcamera.org/comment/37796/","msgid":"<176900670418.1693075.17512355310821360852@ping.linuxembedded.co.uk>","date":"2026-01-21T14:45:04","subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Jacopo Mondi (2026-01-21 12:53:49)\n> Hi Kieran\n> \n> On Wed, Jan 21, 2026 at 12:23:40PM +0000, Kieran Bingham wrote:\n> > Hi Jacopo,\n> >\n> > Quoting Stefan Klug (2026-01-20 08:53:06)\n> > > Hi Jacopo,\n> > >\n> > > Quoting Jacopo Mondi (2026-01-20 09:39:49)\n> > > > Converting numbers with a signed fixed-point representation to\n> > > > the corresponding float value requires to include the sign bit in the\n> > > > width of the fixed-point integral part.\n> > > >\n> > > > Clearly specify it in documentation.\n> > > >\n> > > > Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n> > > > ---\n> > > >  src/ipa/libipa/fixedpoint.cpp | 22 +++++++++++++++++++++-\n> > > >  1 file changed, 21 insertions(+), 1 deletion(-)\n> > > >\n> > > > diff --git a/src/ipa/libipa/fixedpoint.cpp b/src/ipa/libipa/fixedpoint.cpp\n> > > > index 6b698fc5d680..b37cdc43936f 100644\n> > > > --- a/src/ipa/libipa/fixedpoint.cpp\n> > > > +++ b/src/ipa/libipa/fixedpoint.cpp\n> > > > @@ -29,11 +29,31 @@ namespace ipa {\n> > > >  /**\n> > > >   * \\fn R fixedToFloatingPoint(T number)\n> > > >   * \\brief Convert a fixed-point number to a floating point representation\n> > > > - * \\tparam I Bit width of the integer part of the fixed-point\n> > > > + * \\tparam I Bit width of the integer part of the fixed-point including the\n> > > > + * optional sign bit\n> > > >   * \\tparam F Bit width of the fractional part of the fixed-point\n> > > >   * \\tparam R Return type of the floating point representation\n> > > >   * \\tparam T Input type of the fixed-point representation\n> > > >   * \\param number The fixed point number to convert to floating point\n> > > > + *\n> > > > + * If the fixed-point representation is signed, the sign bit shall be included\n> > > > + * in the \\a I template parameter that specifies the number of bits of the\n> > > > + * integral part of the fixed-point representation.\n> > > > + *\n> > > > + * As an example, a value represented as signed fixed-point Q4.8 format can be\n> > > > + * converted to its corresponding floating point representation as:\n> >\n> > Just to be sure - you know I've got patches to remove all of the above\n> > that I want to get merged 'soon' right?\n> \n> Read the last bit of my reply from yesterday :)\n> \n> >\n> > Quantized brings in explicit signed/unsigned types through Q<4,8> and\n> > UQ<4, 8> types.\n> \n> What is the difference between signed and unsigned ? Is it only the\n> sign bit ? I guess then that the Q<4,8>[12:0] = UQ<4,8>[11:0]\n\nPlease take a look through the tests I've added:\n\nhttps://patchwork.libcamera.org/patch/25801/\n\n/* Q1.7(-1 .. 0.992188)  Min: [0x80:-1] -- Max: [0x7f:0.992188] Step:0.0078125*/\n/* UQ1.7(0 .. 1.99219)  Min: [0x00:0] -- Max: [0xff:1.99219] Step:0.0078125 */\n\n/* Q12.4(-2048 .. 2047.94)  Min: [0x8000:-2048] -- Max: [0x7fff:2047.94] Step:0.0625 */\n/* UQ12.4(0 .. 4095.94)  Min: [0x0000:0] -- Max: [0xffff:4095.94] Step:0.0625 */\n\nIt's easy to extend that if you have specific Q types you want to\nuse/test.\n\n \n> >\n> > In the new types Q<I, F> has the sign bit included in 'I'.\n> > I can add that explicitly to the documentation in my new series for v6.\n> \n> \n> Well, maybe we need two traits ?\n> https://en.wikipedia.org/wiki/Q_(number_format)\n> \n> Texas Instruments version:\n> The first bit always gives the sign of the value (1 = negative, 0 =\n> non-negative), and it is not counted in the m parameter. Thus, the\n> total number w of bits used is 1 + m + n.\n> \n> ARM Version:\n> A variant of the Q notation has been in use by ARM in which the m\n> number also counts the sign bit\n\nYes, you've definitely got to know which one the hardware is using and\nexpecting. I wouldn't make a new trait for this - if we have to specify\nwe can wrap one in the other if it really helps.\n\n--\nKieran\n\n\n> \n> I guess the only way to know which one is meant to be used is to\n> actually look at the register sizes. If a Q<4,8> number is stored as\n> a 13 bit fields, then the TI version is used. I wonder how common the\n> ARM version is.\n> \n> >\n> >\n> > \"\"\"\n> >  * The sign of the value is determined by the sign of \\a T. For signed types,\n> >  * the number of integer bits includes the sign bit.\n> > \"\"\"\n> >\n> > --\n> > Kieran\n> >\n> > > I'm a bit confused here. Doesn't signed Q4.8 mean that the first bit of\n> > > the 4 is the sign bit? The same way a signed int32 has the signed bit on\n> > > the first of the 32 bits?\n> > >\n> > > Best regards,\n> > > Stefan\n> > >\n> > > > + *\n> > > > + * \\code{.cpp}\n> > > > + * double d = fixedToFloatingPoint<5, 8, double, uint16_t>(fixed);\n> > > > + * \\endcode\n> > > > + *\n> > > > + * While a value represented as unsigned fixed-point Q4.8 format can be\n> > > > + * converted as:\n> > > > + *\n> > > > + * \\code{.cpp}\n> > > > + * double d = fixedToFloatingPoint<4, 8, double, uint16_t>(fixed);\n> > > > + * \\endcode\n> > > > + *\n> > > >   * \\return The converted value\n> > > >   */\n> > > >\n> > > > --\n> > > > 2.52.0\n> > > >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 24982BDCBF\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 21 Jan 2026 14:45:10 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 1CA4861FC4;\n\tWed, 21 Jan 2026 15:45:09 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id E413D61F9F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 21 Jan 2026 15:45:07 +0100 (CET)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust6594.18-1.cable.virginm.net [86.31.185.195])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 8E6CB741;\n\tWed, 21 Jan 2026 15:44:35 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"kywdpJe+\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1769006675;\n\tbh=1+kkEOEjwZyjGhq78TODVaoQcFL2s5QXc2qW8/VXZOU=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=kywdpJe+vriTCv0bvXueSUjpGI83EKBop67TtSjuVxylAg6zZQHQUAvGUUlHrNqiy\n\tbldsiIlam2z6YxctlENYogBxPnqXxqPzKqb4zzBasSkSzoCsqtkAsFZxUqVc+CzV4+\n\tJIotEDymY7DpMB65Tdxlypo4jWeKBQdxsoIS27dY=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<aXDJol4kIvRx6_49@zed>","References":"<20260120083952.15338-1-jacopo.mondi@ideasonboard.com>\n\t<176889918695.508107.16263205271582334087@localhost>\n\t<176899822075.3544004.689251715744219495@ping.linuxembedded.co.uk>\n\t<aXDJol4kIvRx6_49@zed>","Subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>,\n\tStefan Klug <stefan.klug@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org,\n\tPaul Elder <paul.elder@ideasonboard.com>","To":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","Date":"Wed, 21 Jan 2026 14:45:04 +0000","Message-ID":"<176900670418.1693075.17512355310821360852@ping.linuxembedded.co.uk>","User-Agent":"alot/0.9.1","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":37798,"web_url":"https://patchwork.libcamera.org/comment/37798/","msgid":"<aXDsQiDhhbWWuKV1@zed>","date":"2026-01-21T15:12:24","subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","submitter":{"id":143,"url":"https://patchwork.libcamera.org/api/people/143/","name":"Jacopo Mondi","email":"jacopo.mondi@ideasonboard.com"},"content":"Hi Kieran\n\nOn Wed, Jan 21, 2026 at 02:45:04PM +0000, Kieran Bingham wrote:\n> Quoting Jacopo Mondi (2026-01-21 12:53:49)\n> > Hi Kieran\n> >\n> > On Wed, Jan 21, 2026 at 12:23:40PM +0000, Kieran Bingham wrote:\n> > > Hi Jacopo,\n> > >\n> > > Quoting Stefan Klug (2026-01-20 08:53:06)\n> > > > Hi Jacopo,\n> > > >\n> > > > Quoting Jacopo Mondi (2026-01-20 09:39:49)\n> > > > > Converting numbers with a signed fixed-point representation to\n> > > > > the corresponding float value requires to include the sign bit in the\n> > > > > width of the fixed-point integral part.\n> > > > >\n> > > > > Clearly specify it in documentation.\n> > > > >\n> > > > > Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n> > > > > ---\n> > > > >  src/ipa/libipa/fixedpoint.cpp | 22 +++++++++++++++++++++-\n> > > > >  1 file changed, 21 insertions(+), 1 deletion(-)\n> > > > >\n> > > > > diff --git a/src/ipa/libipa/fixedpoint.cpp b/src/ipa/libipa/fixedpoint.cpp\n> > > > > index 6b698fc5d680..b37cdc43936f 100644\n> > > > > --- a/src/ipa/libipa/fixedpoint.cpp\n> > > > > +++ b/src/ipa/libipa/fixedpoint.cpp\n> > > > > @@ -29,11 +29,31 @@ namespace ipa {\n> > > > >  /**\n> > > > >   * \\fn R fixedToFloatingPoint(T number)\n> > > > >   * \\brief Convert a fixed-point number to a floating point representation\n> > > > > - * \\tparam I Bit width of the integer part of the fixed-point\n> > > > > + * \\tparam I Bit width of the integer part of the fixed-point including the\n> > > > > + * optional sign bit\n> > > > >   * \\tparam F Bit width of the fractional part of the fixed-point\n> > > > >   * \\tparam R Return type of the floating point representation\n> > > > >   * \\tparam T Input type of the fixed-point representation\n> > > > >   * \\param number The fixed point number to convert to floating point\n> > > > > + *\n> > > > > + * If the fixed-point representation is signed, the sign bit shall be included\n> > > > > + * in the \\a I template parameter that specifies the number of bits of the\n> > > > > + * integral part of the fixed-point representation.\n> > > > > + *\n> > > > > + * As an example, a value represented as signed fixed-point Q4.8 format can be\n> > > > > + * converted to its corresponding floating point representation as:\n> > >\n> > > Just to be sure - you know I've got patches to remove all of the above\n> > > that I want to get merged 'soon' right?\n> >\n> > Read the last bit of my reply from yesterday :)\n> >\n> > >\n> > > Quantized brings in explicit signed/unsigned types through Q<4,8> and\n> > > UQ<4, 8> types.\n> >\n> > What is the difference between signed and unsigned ? Is it only the\n> > sign bit ? I guess then that the Q<4,8>[12:0] = UQ<4,8>[11:0]\n>\n> Please take a look through the tests I've added:\n>\n> https://patchwork.libcamera.org/patch/25801/\n>\n> /* Q1.7(-1 .. 0.992188)  Min: [0x80:-1] -- Max: [0x7f:0.992188] Step:0.0078125*/\n> /* UQ1.7(0 .. 1.99219)  Min: [0x00:0] -- Max: [0xff:1.99219] Step:0.0078125 */\n>\n> /* Q12.4(-2048 .. 2047.94)  Min: [0x8000:-2048] -- Max: [0x7fff:2047.94] Step:0.0625 */\n> /* UQ12.4(0 .. 4095.94)  Min: [0x0000:0] -- Max: [0xffff:4095.94] Step:0.0625 */\n>\n> It's easy to extend that if you have specific Q types you want to\n> use/test.\n\nAh yes, for min/max it's defintely useful to have signed/unsigned\ntypes\n\n>\n>\n> > >\n> > > In the new types Q<I, F> has the sign bit included in 'I'.\n> > > I can add that explicitly to the documentation in my new series for v6.\n> >\n> >\n> > Well, maybe we need two traits ?\n> > https://en.wikipedia.org/wiki/Q_(number_format)\n> >\n> > Texas Instruments version:\n> > The first bit always gives the sign of the value (1 = negative, 0 =\n> > non-negative), and it is not counted in the m parameter. Thus, the\n> > total number w of bits used is 1 + m + n.\n> >\n> > ARM Version:\n> > A variant of the Q notation has been in use by ARM in which the m\n> > number also counts the sign bit\n>\n> Yes, you've definitely got to know which one the hardware is using and\n> expecting. I wouldn't make a new trait for this - if we have to specify\n> we can wrap one in the other if it really helps.\n\nI'm not sure, if I'm working with the TI format (which as far as I\nunderstand is the most common?) then to have a signed value correctly\nrepresented as a Q<4,8> I would have to use Q<5,8> (which is\ncounter-intuitive).\n\nI would rather modify the Trait to put the sign in the [m + n + 1]\nbit.\n\nOr are the registers you're working with in ARM format ? (sign in\n[m + n] position)\n\nThanks\n  j\n\n>\n> --\n> Kieran\n>\n>\n> >\n> > I guess the only way to know which one is meant to be used is to\n> > actually look at the register sizes. If a Q<4,8> number is stored as\n> > a 13 bit fields, then the TI version is used. I wonder how common the\n> > ARM version is.\n> >\n> > >\n> > >\n> > > \"\"\"\n> > >  * The sign of the value is determined by the sign of \\a T. For signed types,\n> > >  * the number of integer bits includes the sign bit.\n> > > \"\"\"\n> > >\n> > > --\n> > > Kieran\n> > >\n> > > > I'm a bit confused here. Doesn't signed Q4.8 mean that the first bit of\n> > > > the 4 is the sign bit? The same way a signed int32 has the signed bit on\n> > > > the first of the 32 bits?\n> > > >\n> > > > Best regards,\n> > > > Stefan\n> > > >\n> > > > > + *\n> > > > > + * \\code{.cpp}\n> > > > > + * double d = fixedToFloatingPoint<5, 8, double, uint16_t>(fixed);\n> > > > > + * \\endcode\n> > > > > + *\n> > > > > + * While a value represented as unsigned fixed-point Q4.8 format can be\n> > > > > + * converted as:\n> > > > > + *\n> > > > > + * \\code{.cpp}\n> > > > > + * double d = fixedToFloatingPoint<4, 8, double, uint16_t>(fixed);\n> > > > > + * \\endcode\n> > > > > + *\n> > > > >   * \\return The converted value\n> > > > >   */\n> > > > >\n> > > > > --\n> > > > > 2.52.0\n> > > > >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 9A64CBDCBF\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 21 Jan 2026 15:12:29 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id D5E6761FC4;\n\tWed, 21 Jan 2026 16:12:28 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id A002E61F9F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 21 Jan 2026 16:12:27 +0100 (CET)","from ideasonboard.com (static.170.20.224.46.clients.your-server.de\n\t[46.224.20.170])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 546F61C6;\n\tWed, 21 Jan 2026 16:11:55 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"qolxtNcD\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1769008315;\n\tbh=3kuoa7ZL+NuHgOo02dqpuwLe6dd49T0ppBQgrwlFlqc=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=qolxtNcDN/LDQ5ZgoxmO3IChpTUVP9quNIYF2fQ/HJ+7yU/T9xatG3hLDur0QYwnV\n\tD/FrrRZfJZgoRPqgsc0RPTwoe02ETpVkVAMpJ9nFirz7vVn4FxoEykiqpvgGNtIy+7\n\tdc73fuSNwSPOF8YPhTE1C+sU3LT91SM1Gdo4gTZc=","Date":"Wed, 21 Jan 2026 16:12:24 +0100","From":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>, \n\tStefan Klug <stefan.klug@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org, \n\tPaul Elder <paul.elder@ideasonboard.com>","Subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","Message-ID":"<aXDsQiDhhbWWuKV1@zed>","References":"<20260120083952.15338-1-jacopo.mondi@ideasonboard.com>\n\t<176889918695.508107.16263205271582334087@localhost>\n\t<176899822075.3544004.689251715744219495@ping.linuxembedded.co.uk>\n\t<aXDJol4kIvRx6_49@zed>\n\t<176900670418.1693075.17512355310821360852@ping.linuxembedded.co.uk>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<176900670418.1693075.17512355310821360852@ping.linuxembedded.co.uk>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":37803,"web_url":"https://patchwork.libcamera.org/comment/37803/","msgid":"<176901024127.1693075.2963823420483106366@ping.linuxembedded.co.uk>","date":"2026-01-21T15:44:01","subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Jacopo Mondi (2026-01-21 15:12:24)\n> Hi Kieran\n> \n> On Wed, Jan 21, 2026 at 02:45:04PM +0000, Kieran Bingham wrote:\n> > Quoting Jacopo Mondi (2026-01-21 12:53:49)\n> > > Hi Kieran\n> > >\n> > > On Wed, Jan 21, 2026 at 12:23:40PM +0000, Kieran Bingham wrote:\n> > > > Hi Jacopo,\n> > > >\n> > > > Quoting Stefan Klug (2026-01-20 08:53:06)\n> > > > > Hi Jacopo,\n> > > > >\n> > > > > Quoting Jacopo Mondi (2026-01-20 09:39:49)\n> > > > > > Converting numbers with a signed fixed-point representation to\n> > > > > > the corresponding float value requires to include the sign bit in the\n> > > > > > width of the fixed-point integral part.\n> > > > > >\n> > > > > > Clearly specify it in documentation.\n> > > > > >\n> > > > > > Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n> > > > > > ---\n> > > > > >  src/ipa/libipa/fixedpoint.cpp | 22 +++++++++++++++++++++-\n> > > > > >  1 file changed, 21 insertions(+), 1 deletion(-)\n> > > > > >\n> > > > > > diff --git a/src/ipa/libipa/fixedpoint.cpp b/src/ipa/libipa/fixedpoint.cpp\n> > > > > > index 6b698fc5d680..b37cdc43936f 100644\n> > > > > > --- a/src/ipa/libipa/fixedpoint.cpp\n> > > > > > +++ b/src/ipa/libipa/fixedpoint.cpp\n> > > > > > @@ -29,11 +29,31 @@ namespace ipa {\n> > > > > >  /**\n> > > > > >   * \\fn R fixedToFloatingPoint(T number)\n> > > > > >   * \\brief Convert a fixed-point number to a floating point representation\n> > > > > > - * \\tparam I Bit width of the integer part of the fixed-point\n> > > > > > + * \\tparam I Bit width of the integer part of the fixed-point including the\n> > > > > > + * optional sign bit\n> > > > > >   * \\tparam F Bit width of the fractional part of the fixed-point\n> > > > > >   * \\tparam R Return type of the floating point representation\n> > > > > >   * \\tparam T Input type of the fixed-point representation\n> > > > > >   * \\param number The fixed point number to convert to floating point\n> > > > > > + *\n> > > > > > + * If the fixed-point representation is signed, the sign bit shall be included\n> > > > > > + * in the \\a I template parameter that specifies the number of bits of the\n> > > > > > + * integral part of the fixed-point representation.\n> > > > > > + *\n> > > > > > + * As an example, a value represented as signed fixed-point Q4.8 format can be\n> > > > > > + * converted to its corresponding floating point representation as:\n> > > >\n> > > > Just to be sure - you know I've got patches to remove all of the above\n> > > > that I want to get merged 'soon' right?\n> > >\n> > > Read the last bit of my reply from yesterday :)\n\nI still don't get this?\n\n\n> > >\n> > > >\n> > > > Quantized brings in explicit signed/unsigned types through Q<4,8> and\n> > > > UQ<4, 8> types.\n> > >\n> > > What is the difference between signed and unsigned ? Is it only the\n> > > sign bit ? I guess then that the Q<4,8>[12:0] = UQ<4,8>[11:0]\n> >\n> > Please take a look through the tests I've added:\n> >\n> > https://patchwork.libcamera.org/patch/25801/\n> >\n> > /* Q1.7(-1 .. 0.992188)  Min: [0x80:-1] -- Max: [0x7f:0.992188] Step:0.0078125*/\n> > /* UQ1.7(0 .. 1.99219)  Min: [0x00:0] -- Max: [0xff:1.99219] Step:0.0078125 */\n> >\n> > /* Q12.4(-2048 .. 2047.94)  Min: [0x8000:-2048] -- Max: [0x7fff:2047.94] Step:0.0625 */\n> > /* UQ12.4(0 .. 4095.94)  Min: [0x0000:0] -- Max: [0xffff:4095.94] Step:0.0625 */\n> >\n> > It's easy to extend that if you have specific Q types you want to\n> > use/test.\n> \n> Ah yes, for min/max it's defintely useful to have signed/unsigned\n> types\n\nIt's not about min/max is useful - it's the very fact that Q and UQ have\na distinct range. Q types can go less than zero but still span the same\ndistance, so the top/max is halved, but the step size is the same.\n\n\n> > > > In the new types Q<I, F> has the sign bit included in 'I'.\n> > > > I can add that explicitly to the documentation in my new series for v6.\n> > >\n> > >\n> > > Well, maybe we need two traits ?\n> > > https://en.wikipedia.org/wiki/Q_(number_format)\n> > >\n> > > Texas Instruments version:\n> > > The first bit always gives the sign of the value (1 = negative, 0 =\n> > > non-negative), and it is not counted in the m parameter. Thus, the\n> > > total number w of bits used is 1 + m + n.\n> > >\n> > > ARM Version:\n> > > A variant of the Q notation has been in use by ARM in which the m\n> > > number also counts the sign bit\n> >\n> > Yes, you've definitely got to know which one the hardware is using and\n> > expecting. I wouldn't make a new trait for this - if we have to specify\n> > we can wrap one in the other if it really helps.\n> \n> I'm not sure, if I'm working with the TI format (which as far as I\n> understand is the most common?) then to have a signed value correctly\n> represented as a Q<4,8> I would have to use Q<5,8> (which is\n> counter-intuitive).\n> \n> I would rather modify the Trait to put the sign in the [m + n + 1]\n> bit.\n> \n> Or are the registers you're working with in ARM format ? (sign in\n> [m + n] position)\n\n\nThat's (include the bit) what the original fixedToFloatingPoint()\nimplementations used, so that's what I've continued with.\n\nIf you want to distinguish these? How should we represent them?\n\n\n/* All 8 bit storage */\nUQ<1, 7> Q<1, 7> Q_TI<0, 7> ?\n\n--\nKieran\n\n> \n> Thanks\n>   j\n> \n> >\n> > --\n> > Kieran\n> >\n> >\n> > >\n> > > I guess the only way to know which one is meant to be used is to\n> > > actually look at the register sizes. If a Q<4,8> number is stored as\n> > > a 13 bit fields, then the TI version is used. I wonder how common the\n> > > ARM version is.\n> > >\n> > > >\n> > > >\n> > > > \"\"\"\n> > > >  * The sign of the value is determined by the sign of \\a T. For signed types,\n> > > >  * the number of integer bits includes the sign bit.\n> > > > \"\"\"\n> > > >\n> > > > --\n> > > > Kieran\n> > > >\n> > > > > I'm a bit confused here. Doesn't signed Q4.8 mean that the first bit of\n> > > > > the 4 is the sign bit? The same way a signed int32 has the signed bit on\n> > > > > the first of the 32 bits?\n> > > > >\n> > > > > Best regards,\n> > > > > Stefan\n> > > > >\n> > > > > > + *\n> > > > > > + * \\code{.cpp}\n> > > > > > + * double d = fixedToFloatingPoint<5, 8, double, uint16_t>(fixed);\n> > > > > > + * \\endcode\n> > > > > > + *\n> > > > > > + * While a value represented as unsigned fixed-point Q4.8 format can be\n> > > > > > + * converted as:\n> > > > > > + *\n> > > > > > + * \\code{.cpp}\n> > > > > > + * double d = fixedToFloatingPoint<4, 8, double, uint16_t>(fixed);\n> > > > > > + * \\endcode\n> > > > > > + *\n> > > > > >   * \\return The converted value\n> > > > > >   */\n> > > > > >\n> > > > > > --\n> > > > > > 2.52.0\n> > > > > >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id E0294C3220\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 21 Jan 2026 15:44:05 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 994CA61FCA;\n\tWed, 21 Jan 2026 16:44:05 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 51DE461F9F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 21 Jan 2026 16:44:04 +0100 (CET)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust6594.18-1.cable.virginm.net [86.31.185.195])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 679AA1C6;\n\tWed, 21 Jan 2026 16:43:32 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"faBRbxT4\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1769010212;\n\tbh=mSl/cWroA7R/VYAzXplem+XDPNfCXh58D1jfs1TyU0M=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=faBRbxT4WASjBRlACQP+V2pBE9x70/5CA7dyZ6d+WtL9j9qgbXsNNsfb+/m+ySHS5\n\tY583fiya/xBRkGSUjUKjIKU7XuD8ut+UmyMOpqryo6Enf7xA+QdrxH3FaGbkd9Imyd\n\tTOEO/0FeSOjwsrVx1EwnpQvHWGh7mw/0VX0l1lBE=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<aXDsQiDhhbWWuKV1@zed>","References":"<20260120083952.15338-1-jacopo.mondi@ideasonboard.com>\n\t<176889918695.508107.16263205271582334087@localhost>\n\t<176899822075.3544004.689251715744219495@ping.linuxembedded.co.uk>\n\t<aXDJol4kIvRx6_49@zed>\n\t<176900670418.1693075.17512355310821360852@ping.linuxembedded.co.uk>\n\t<aXDsQiDhhbWWuKV1@zed>","Subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>,\n\tStefan Klug <stefan.klug@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org,\n\tPaul Elder <paul.elder@ideasonboard.com>","To":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","Date":"Wed, 21 Jan 2026 15:44:01 +0000","Message-ID":"<176901024127.1693075.2963823420483106366@ping.linuxembedded.co.uk>","User-Agent":"alot/0.9.1","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":37808,"web_url":"https://patchwork.libcamera.org/comment/37808/","msgid":"<aXD1saAAJ248-U0S@zed>","date":"2026-01-21T16:13:02","subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","submitter":{"id":143,"url":"https://patchwork.libcamera.org/api/people/143/","name":"Jacopo Mondi","email":"jacopo.mondi@ideasonboard.com"},"content":"On Wed, Jan 21, 2026 at 03:44:01PM +0000, Kieran Bingham wrote:\n> Quoting Jacopo Mondi (2026-01-21 15:12:24)\n> > Hi Kieran\n> >\n> > On Wed, Jan 21, 2026 at 02:45:04PM +0000, Kieran Bingham wrote:\n> > > Quoting Jacopo Mondi (2026-01-21 12:53:49)\n> > > > Hi Kieran\n> > > >\n> > > > On Wed, Jan 21, 2026 at 12:23:40PM +0000, Kieran Bingham wrote:\n> > > > > Hi Jacopo,\n> > > > >\n> > > > > Quoting Stefan Klug (2026-01-20 08:53:06)\n> > > > > > Hi Jacopo,\n> > > > > >\n> > > > > > Quoting Jacopo Mondi (2026-01-20 09:39:49)\n> > > > > > > Converting numbers with a signed fixed-point representation to\n> > > > > > > the corresponding float value requires to include the sign bit in the\n> > > > > > > width of the fixed-point integral part.\n> > > > > > >\n> > > > > > > Clearly specify it in documentation.\n> > > > > > >\n> > > > > > > Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n> > > > > > > ---\n> > > > > > >  src/ipa/libipa/fixedpoint.cpp | 22 +++++++++++++++++++++-\n> > > > > > >  1 file changed, 21 insertions(+), 1 deletion(-)\n> > > > > > >\n> > > > > > > diff --git a/src/ipa/libipa/fixedpoint.cpp b/src/ipa/libipa/fixedpoint.cpp\n> > > > > > > index 6b698fc5d680..b37cdc43936f 100644\n> > > > > > > --- a/src/ipa/libipa/fixedpoint.cpp\n> > > > > > > +++ b/src/ipa/libipa/fixedpoint.cpp\n> > > > > > > @@ -29,11 +29,31 @@ namespace ipa {\n> > > > > > >  /**\n> > > > > > >   * \\fn R fixedToFloatingPoint(T number)\n> > > > > > >   * \\brief Convert a fixed-point number to a floating point representation\n> > > > > > > - * \\tparam I Bit width of the integer part of the fixed-point\n> > > > > > > + * \\tparam I Bit width of the integer part of the fixed-point including the\n> > > > > > > + * optional sign bit\n> > > > > > >   * \\tparam F Bit width of the fractional part of the fixed-point\n> > > > > > >   * \\tparam R Return type of the floating point representation\n> > > > > > >   * \\tparam T Input type of the fixed-point representation\n> > > > > > >   * \\param number The fixed point number to convert to floating point\n> > > > > > > + *\n> > > > > > > + * If the fixed-point representation is signed, the sign bit shall be included\n> > > > > > > + * in the \\a I template parameter that specifies the number of bits of the\n> > > > > > > + * integral part of the fixed-point representation.\n> > > > > > > + *\n> > > > > > > + * As an example, a value represented as signed fixed-point Q4.8 format can be\n> > > > > > > + * converted to its corresponding floating point representation as:\n> > > > >\n> > > > > Just to be sure - you know I've got patches to remove all of the above\n> > > > > that I want to get merged 'soon' right?\n> > > >\n> > > > Read the last bit of my reply from yesterday :)\n>\n> I still don't get this?\n>\n\nI meant the discussion on sign/magnitude representation\n\nsign/magnitude is a different representation of signed integers\ncompared to the de-facto standard 2's complement. It requires to\nmanipulate the result of the float-to-fixed conversion so that we take\nthe absolute value and the sign bit is set in the [m + n + 1] bit\n\n\n------------------------------------------------------------------------------\nAs a bit of pseudo code\n\n        int reg = static_cast<int>(std::round(number * (1 << F)))) & mask;\n        uint16_t res += std::abs(reg);\n        if (reg < 0)\n                res |= BIT(13);\n\n\nI think this could be surely optimized and nicely made a Traits that\ncan be added to the Quantized series Kieran is working on.\n------------------------------------------------------------------------------\n\nThe above is the pharse I thought it could make you happy:\nsign/magnitude fixed-point formats can be easily be represented with a\nTrait on top of your series\n\n\n>\n> > > >\n> > > > >\n> > > > > Quantized brings in explicit signed/unsigned types through Q<4,8> and\n> > > > > UQ<4, 8> types.\n> > > >\n> > > > What is the difference between signed and unsigned ? Is it only the\n> > > > sign bit ? I guess then that the Q<4,8>[12:0] = UQ<4,8>[11:0]\n> > >\n> > > Please take a look through the tests I've added:\n> > >\n> > > https://patchwork.libcamera.org/patch/25801/\n> > >\n> > > /* Q1.7(-1 .. 0.992188)  Min: [0x80:-1] -- Max: [0x7f:0.992188] Step:0.0078125*/\n> > > /* UQ1.7(0 .. 1.99219)  Min: [0x00:0] -- Max: [0xff:1.99219] Step:0.0078125 */\n> > >\n> > > /* Q12.4(-2048 .. 2047.94)  Min: [0x8000:-2048] -- Max: [0x7fff:2047.94] Step:0.0625 */\n> > > /* UQ12.4(0 .. 4095.94)  Min: [0x0000:0] -- Max: [0xffff:4095.94] Step:0.0625 */\n> > >\n> > > It's easy to extend that if you have specific Q types you want to\n> > > use/test.\n> >\n> > Ah yes, for min/max it's defintely useful to have signed/unsigned\n> > types\n>\n> It's not about min/max is useful - it's the very fact that Q and UQ have\n> a distinct range. Q types can go less than zero but still span the same\n> distance, so the top/max is halved, but the step size is the same.\n\nYes, min/max and range indeed.\n\n>\n>\n> > > > > In the new types Q<I, F> has the sign bit included in 'I'.\n> > > > > I can add that explicitly to the documentation in my new series for v6.\n> > > >\n> > > >\n> > > > Well, maybe we need two traits ?\n> > > > https://en.wikipedia.org/wiki/Q_(number_format)\n> > > >\n> > > > Texas Instruments version:\n> > > > The first bit always gives the sign of the value (1 = negative, 0 =\n> > > > non-negative), and it is not counted in the m parameter. Thus, the\n> > > > total number w of bits used is 1 + m + n.\n> > > >\n> > > > ARM Version:\n> > > > A variant of the Q notation has been in use by ARM in which the m\n> > > > number also counts the sign bit\n> > >\n> > > Yes, you've definitely got to know which one the hardware is using and\n> > > expecting. I wouldn't make a new trait for this - if we have to specify\n> > > we can wrap one in the other if it really helps.\n> >\n> > I'm not sure, if I'm working with the TI format (which as far as I\n> > understand is the most common?) then to have a signed value correctly\n> > represented as a Q<4,8> I would have to use Q<5,8> (which is\n> > counter-intuitive).\n> >\n> > I would rather modify the Trait to put the sign in the [m + n + 1]\n> > bit.\n> >\n> > Or are the registers you're working with in ARM format ? (sign in\n> > [m + n] position)\n>\n>\n> That's (include the bit) what the original fixedToFloatingPoint()\n> implementations used, so that's what I've continued with.\n\nI see but that doesn't mean it's correct.\n\nI read one platform manual the description of a coefficient as\n\n\"8:0 cc_coeff_0 Coefficient 0 for color space conversion\"\ncolor conversion coefficients are signed integer values with a 7 bit\nfractional part; range: [-2…1.992]\n\nso if there are 7 fractional bit and the max achievable value is 1.992\nit means that the value is in Q<1,7> format as:\n\n        (1 << (1 + 7)) - 1 / (1 << 7) = 1.999\n\nthe register size is 9 bits (see the [8:0] in the register\ndescription) so I the sign bit is at location [8].\n\nAm I wrong that I want to obtain this with your model I would have to\ndescribe the fixed point representation as Q<2,7> (which doesn't match\nthe datasheet) ?\n\nAnd I guess this really is the difference between UQ<m, n> and Q<m, n>\n\nusigned Q has no sign bit and the destination register is of size [m+n]\nsigned Q has a sign bit in position [m+n+1] with the value in 2's\ncomplement format and destination register of size [m+n+1]\n\n>\n> If you want to distinguish these? How should we represent them?\n>\n>\n> /* All 8 bit storage */\n> UQ<1, 7> Q<1, 7> Q_TI<0, 7> ?\n>\n\nLet's start by deciding what behaviour we want by default maybe..\n\n> --\n> Kieran\n>\n> >\n> > Thanks\n> >   j\n> >\n> > >\n> > > --\n> > > Kieran\n> > >\n> > >\n> > > >\n> > > > I guess the only way to know which one is meant to be used is to\n> > > > actually look at the register sizes. If a Q<4,8> number is stored as\n> > > > a 13 bit fields, then the TI version is used. I wonder how common the\n> > > > ARM version is.\n> > > >\n> > > > >\n> > > > >\n> > > > > \"\"\"\n> > > > >  * The sign of the value is determined by the sign of \\a T. For signed types,\n> > > > >  * the number of integer bits includes the sign bit.\n> > > > > \"\"\"\n> > > > >\n> > > > > --\n> > > > > Kieran\n> > > > >\n> > > > > > I'm a bit confused here. Doesn't signed Q4.8 mean that the first bit of\n> > > > > > the 4 is the sign bit? The same way a signed int32 has the signed bit on\n> > > > > > the first of the 32 bits?\n> > > > > >\n> > > > > > Best regards,\n> > > > > > Stefan\n> > > > > >\n> > > > > > > + *\n> > > > > > > + * \\code{.cpp}\n> > > > > > > + * double d = fixedToFloatingPoint<5, 8, double, uint16_t>(fixed);\n> > > > > > > + * \\endcode\n> > > > > > > + *\n> > > > > > > + * While a value represented as unsigned fixed-point Q4.8 format can be\n> > > > > > > + * converted as:\n> > > > > > > + *\n> > > > > > > + * \\code{.cpp}\n> > > > > > > + * double d = fixedToFloatingPoint<4, 8, double, uint16_t>(fixed);\n> > > > > > > + * \\endcode\n> > > > > > > + *\n> > > > > > >   * \\return The converted value\n> > > > > > >   */\n> > > > > > >\n> > > > > > > --\n> > > > > > > 2.52.0\n> > > > > > >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 04373C3220\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 21 Jan 2026 16:13:08 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 1EAE761FC5;\n\tWed, 21 Jan 2026 17:13:07 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id F037A61FBB\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 21 Jan 2026 17:13:05 +0100 (CET)","from ideasonboard.com (static.170.20.224.46.clients.your-server.de\n\t[46.224.20.170])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id A88DC593;\n\tWed, 21 Jan 2026 17:12:33 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"ilHZRDYb\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1769011953;\n\tbh=gtGlxk8XBepH37lP9FSBx7LNb0blt0SN5N99OxxLixI=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=ilHZRDYbmfldRBcP/eA+8xdB6HlZsPuxbxPYCqqAgyN9S7Rt373kCF4LT+6r7zEFl\n\tDRWRdl8vm//CQr0FSJAIRCpZ4KlCw61kvnFInIXUFKvzKfIDaXmX2I+eQmjkuaFYA3\n\tgZL+N7c0POnDkp0RpmSj/xY5CrTsYK4KLjhK5gbc=","Date":"Wed, 21 Jan 2026 17:13:02 +0100","From":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>, \n\tStefan Klug <stefan.klug@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org, \n\tPaul Elder <paul.elder@ideasonboard.com>","Subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","Message-ID":"<aXD1saAAJ248-U0S@zed>","References":"<20260120083952.15338-1-jacopo.mondi@ideasonboard.com>\n\t<176889918695.508107.16263205271582334087@localhost>\n\t<176899822075.3544004.689251715744219495@ping.linuxembedded.co.uk>\n\t<aXDJol4kIvRx6_49@zed>\n\t<176900670418.1693075.17512355310821360852@ping.linuxembedded.co.uk>\n\t<aXDsQiDhhbWWuKV1@zed>\n\t<176901024127.1693075.2963823420483106366@ping.linuxembedded.co.uk>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<176901024127.1693075.2963823420483106366@ping.linuxembedded.co.uk>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":37816,"web_url":"https://patchwork.libcamera.org/comment/37816/","msgid":"<20260121163755.GG382676@killaraus>","date":"2026-01-21T16:37:55","subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"On Wed, Jan 21, 2026 at 05:13:02PM +0100, Jacopo Mondi wrote:\n> On Wed, Jan 21, 2026 at 03:44:01PM +0000, Kieran Bingham wrote:\n> > Quoting Jacopo Mondi (2026-01-21 15:12:24)\n> > > On Wed, Jan 21, 2026 at 02:45:04PM +0000, Kieran Bingham wrote:\n> > > > Quoting Jacopo Mondi (2026-01-21 12:53:49)\n> > > > > On Wed, Jan 21, 2026 at 12:23:40PM +0000, Kieran Bingham wrote:\n> > > > > > Quoting Stefan Klug (2026-01-20 08:53:06)\n> > > > > > > Quoting Jacopo Mondi (2026-01-20 09:39:49)\n> > > > > > > > Converting numbers with a signed fixed-point representation to\n> > > > > > > > the corresponding float value requires to include the sign bit in the\n> > > > > > > > width of the fixed-point integral part.\n> > > > > > > >\n> > > > > > > > Clearly specify it in documentation.\n> > > > > > > >\n> > > > > > > > Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n> > > > > > > > ---\n> > > > > > > >  src/ipa/libipa/fixedpoint.cpp | 22 +++++++++++++++++++++-\n> > > > > > > >  1 file changed, 21 insertions(+), 1 deletion(-)\n> > > > > > > >\n> > > > > > > > diff --git a/src/ipa/libipa/fixedpoint.cpp b/src/ipa/libipa/fixedpoint.cpp\n> > > > > > > > index 6b698fc5d680..b37cdc43936f 100644\n> > > > > > > > --- a/src/ipa/libipa/fixedpoint.cpp\n> > > > > > > > +++ b/src/ipa/libipa/fixedpoint.cpp\n> > > > > > > > @@ -29,11 +29,31 @@ namespace ipa {\n> > > > > > > >  /**\n> > > > > > > >   * \\fn R fixedToFloatingPoint(T number)\n> > > > > > > >   * \\brief Convert a fixed-point number to a floating point representation\n> > > > > > > > - * \\tparam I Bit width of the integer part of the fixed-point\n> > > > > > > > + * \\tparam I Bit width of the integer part of the fixed-point including the\n> > > > > > > > + * optional sign bit\n> > > > > > > >   * \\tparam F Bit width of the fractional part of the fixed-point\n> > > > > > > >   * \\tparam R Return type of the floating point representation\n> > > > > > > >   * \\tparam T Input type of the fixed-point representation\n> > > > > > > >   * \\param number The fixed point number to convert to floating point\n> > > > > > > > + *\n> > > > > > > > + * If the fixed-point representation is signed, the sign bit shall be included\n> > > > > > > > + * in the \\a I template parameter that specifies the number of bits of the\n> > > > > > > > + * integral part of the fixed-point representation.\n> > > > > > > > + *\n> > > > > > > > + * As an example, a value represented as signed fixed-point Q4.8 format can be\n> > > > > > > > + * converted to its corresponding floating point representation as:\n> > > > > >\n> > > > > > Just to be sure - you know I've got patches to remove all of the above\n> > > > > > that I want to get merged 'soon' right?\n> > > > >\n> > > > > Read the last bit of my reply from yesterday :)\n> >\n> > I still don't get this?\n> \n> I meant the discussion on sign/magnitude representation\n> \n> sign/magnitude is a different representation of signed integers\n> compared to the de-facto standard 2's complement. It requires to\n> manipulate the result of the float-to-fixed conversion so that we take\n> the absolute value and the sign bit is set in the [m + n + 1] bit\n> \n> ------------------------------------------------------------------------------\n> As a bit of pseudo code\n> \n>         int reg = static_cast<int>(std::round(number * (1 << F)))) & mask;\n>         uint16_t res += std::abs(reg);\n>         if (reg < 0)\n>                 res |= BIT(13);\n> \n> \n> I think this could be surely optimized and nicely made a Traits that\n> can be added to the Quantized series Kieran is working on.\n> ------------------------------------------------------------------------------\n> \n> The above is the pharse I thought it could make you happy:\n> sign/magnitude fixed-point formats can be easily be represented with a\n> Trait on top of your series\n> \n> > > > > > Quantized brings in explicit signed/unsigned types through Q<4,8> and\n> > > > > > UQ<4, 8> types.\n> > > > >\n> > > > > What is the difference between signed and unsigned ? Is it only the\n> > > > > sign bit ? I guess then that the Q<4,8>[12:0] = UQ<4,8>[11:0]\n> > > >\n> > > > Please take a look through the tests I've added:\n> > > >\n> > > > https://patchwork.libcamera.org/patch/25801/\n> > > >\n> > > > /* Q1.7(-1 .. 0.992188)  Min: [0x80:-1] -- Max: [0x7f:0.992188] Step:0.0078125*/\n> > > > /* UQ1.7(0 .. 1.99219)  Min: [0x00:0] -- Max: [0xff:1.99219] Step:0.0078125 */\n> > > >\n> > > > /* Q12.4(-2048 .. 2047.94)  Min: [0x8000:-2048] -- Max: [0x7fff:2047.94] Step:0.0625 */\n> > > > /* UQ12.4(0 .. 4095.94)  Min: [0x0000:0] -- Max: [0xffff:4095.94] Step:0.0625 */\n> > > >\n> > > > It's easy to extend that if you have specific Q types you want to\n> > > > use/test.\n> > >\n> > > Ah yes, for min/max it's defintely useful to have signed/unsigned\n> > > types\n> >\n> > It's not about min/max is useful - it's the very fact that Q and UQ have\n> > a distinct range. Q types can go less than zero but still span the same\n> > distance, so the top/max is halved, but the step size is the same.\n> \n> Yes, min/max and range indeed.\n> \n> >\n> >\n> > > > > > In the new types Q<I, F> has the sign bit included in 'I'.\n> > > > > > I can add that explicitly to the documentation in my new series for v6.\n> > > > >\n> > > > >\n> > > > > Well, maybe we need two traits ?\n> > > > > https://en.wikipedia.org/wiki/Q_(number_format)\n> > > > >\n> > > > > Texas Instruments version:\n> > > > > The first bit always gives the sign of the value (1 = negative, 0 =\n> > > > > non-negative), and it is not counted in the m parameter. Thus, the\n> > > > > total number w of bits used is 1 + m + n.\n> > > > >\n> > > > > ARM Version:\n> > > > > A variant of the Q notation has been in use by ARM in which the m\n> > > > > number also counts the sign bit\n> > > >\n> > > > Yes, you've definitely got to know which one the hardware is using and\n> > > > expecting. I wouldn't make a new trait for this - if we have to specify\n> > > > we can wrap one in the other if it really helps.\n> > >\n> > > I'm not sure, if I'm working with the TI format (which as far as I\n> > > understand is the most common?) then to have a signed value correctly\n> > > represented as a Q<4,8> I would have to use Q<5,8> (which is\n> > > counter-intuitive).\n> > >\n> > > I would rather modify the Trait to put the sign in the [m + n + 1]\n> > > bit.\n> > >\n> > > Or are the registers you're working with in ARM format ? (sign in\n> > > [m + n] position)\n> >\n> > That's (include the bit) what the original fixedToFloatingPoint()\n> > implementations used, so that's what I've continued with.\n> \n> I see but that doesn't mean it's correct.\n> \n> I read one platform manual the description of a coefficient as\n> \n> \"8:0 cc_coeff_0 Coefficient 0 for color space conversion\"\n> color conversion coefficients are signed integer values with a 7 bit\n> fractional part; range: [-2…1.992]\n> \n> so if there are 7 fractional bit and the max achievable value is 1.992\n> it means that the value is in Q<1,7> format as:\n> \n>         (1 << (1 + 7)) - 1 / (1 << 7) = 1.999\n> \n> the register size is 9 bits (see the [8:0] in the register\n> description) so I the sign bit is at location [8].\n> \n> Am I wrong that I want to obtain this with your model I would have to\n> describe the fixed point representation as Q<2,7> (which doesn't match\n> the datasheet) ?\n\nWhy doesn't this match the datasheet ? The text you quoted says 7 bits of\nfractional value (match), 9 bits register field (8:0, matching 2+7), and\nthe range of Q<2,7> is -2 to +1.992 (1.9921875 to be precise).\n\n> And I guess this really is the difference between UQ<m, n> and Q<m, n>\n> \n> usigned Q has no sign bit and the destination register is of size [m+n]\n> signed Q has a sign bit in position [m+n+1] with the value in 2's\n> complement format and destination register of size [m+n+1]\n\nIn Kieran's implementation, Q<m, n> is stored in m+n bits, not m+n+1.\n\n> > If you want to distinguish these? How should we represent them?\n> >\n> > /* All 8 bit storage */\n> > UQ<1, 7> Q<1, 7> Q_TI<0, 7> ?\n> \n> Let's start by deciding what behaviour we want by default maybe..\n\nLet's pick one option and stick to it please. Yes, writing Q<4, 12> when\na TI datasheet says \"Q3.12 value\" may be a bit confusing, but it's\nencoding in the type in one place and the rest of the code doesn't have\nto think about it.\n\nWe *could* define device-specific aliases in specific IPA modules if we\nreally wanted, but I wouldn't define multiple types in libipa.\n\n> > > > > I guess the only way to know which one is meant to be used is to\n> > > > > actually look at the register sizes. If a Q<4,8> number is stored as\n> > > > > a 13 bit fields, then the TI version is used. I wonder how common the\n> > > > > ARM version is.\n> > > > >\n> > > > > > \"\"\"\n> > > > > >  * The sign of the value is determined by the sign of \\a T. For signed types,\n> > > > > >  * the number of integer bits includes the sign bit.\n> > > > > > \"\"\"\n> > > > > >\n> > > > > > > I'm a bit confused here. Doesn't signed Q4.8 mean that the first bit of\n> > > > > > > the 4 is the sign bit? The same way a signed int32 has the signed bit on\n> > > > > > > the first of the 32 bits?\n> > > > > > >\n> > > > > > > > + *\n> > > > > > > > + * \\code{.cpp}\n> > > > > > > > + * double d = fixedToFloatingPoint<5, 8, double, uint16_t>(fixed);\n> > > > > > > > + * \\endcode\n> > > > > > > > + *\n> > > > > > > > + * While a value represented as unsigned fixed-point Q4.8 format can be\n> > > > > > > > + * converted as:\n> > > > > > > > + *\n> > > > > > > > + * \\code{.cpp}\n> > > > > > > > + * double d = fixedToFloatingPoint<4, 8, double, uint16_t>(fixed);\n> > > > > > > > + * \\endcode\n> > > > > > > > + *\n> > > > > > > >   * \\return The converted value\n> > > > > > > >   */\n> > > > > > > >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 0D07EC3220\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 21 Jan 2026 16:37:58 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id B9B7261FCC;\n\tWed, 21 Jan 2026 17:37:57 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 77FE561F9F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 21 Jan 2026 17:37:56 +0100 (CET)","from pendragon.ideasonboard.com\n\t(2001-14ba-703d-e500--2a1.rev.dnainternet.fi\n\t[IPv6:2001:14ba:703d:e500::2a1])\n\tby perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id 77940833;\n\tWed, 21 Jan 2026 17:37:24 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"C1Hj7kIe\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1769013444;\n\tbh=J5jgO3/nO8u09EwkNwSPs9WP6AtMX1n6JLDEAkXhgeo=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=C1Hj7kIe7kXzqdztXJKLwyLLVIoflpwVhcGjHnZAkxPn94+A4eo/e1Wxm1PyIO+YH\n\t03257UvDjMPUoX7CUSsqdGHOwL3TDohsC5Lrh8CKj5lxKRl+lhUBfwxWWjVhEqZfhr\n\tNXysNJI4JGMPqpzbvo96wIFDU+n8rRptQk4IdsKE=","Date":"Wed, 21 Jan 2026 18:37:55 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","Cc":"Kieran Bingham <kieran.bingham@ideasonboard.com>,\n\tStefan Klug <stefan.klug@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org,\n\tPaul Elder <paul.elder@ideasonboard.com>","Subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","Message-ID":"<20260121163755.GG382676@killaraus>","References":"<20260120083952.15338-1-jacopo.mondi@ideasonboard.com>\n\t<176889918695.508107.16263205271582334087@localhost>\n\t<176899822075.3544004.689251715744219495@ping.linuxembedded.co.uk>\n\t<aXDJol4kIvRx6_49@zed>\n\t<176900670418.1693075.17512355310821360852@ping.linuxembedded.co.uk>\n\t<aXDsQiDhhbWWuKV1@zed>\n\t<176901024127.1693075.2963823420483106366@ping.linuxembedded.co.uk>\n\t<aXD1saAAJ248-U0S@zed>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<aXD1saAAJ248-U0S@zed>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":37818,"web_url":"https://patchwork.libcamera.org/comment/37818/","msgid":"<aXECEOf5wie2EZvI@zed>","date":"2026-01-21T16:54:35","subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","submitter":{"id":143,"url":"https://patchwork.libcamera.org/api/people/143/","name":"Jacopo Mondi","email":"jacopo.mondi@ideasonboard.com"},"content":"Hi Laurent\n\nOn Wed, Jan 21, 2026 at 06:37:55PM +0200, Laurent Pinchart wrote:\n> On Wed, Jan 21, 2026 at 05:13:02PM +0100, Jacopo Mondi wrote:\n> > On Wed, Jan 21, 2026 at 03:44:01PM +0000, Kieran Bingham wrote:\n> > > Quoting Jacopo Mondi (2026-01-21 15:12:24)\n> > > > On Wed, Jan 21, 2026 at 02:45:04PM +0000, Kieran Bingham wrote:\n> > > > > Quoting Jacopo Mondi (2026-01-21 12:53:49)\n> > > > > > On Wed, Jan 21, 2026 at 12:23:40PM +0000, Kieran Bingham wrote:\n> > > > > > > Quoting Stefan Klug (2026-01-20 08:53:06)\n> > > > > > > > Quoting Jacopo Mondi (2026-01-20 09:39:49)\n> > > > > > > > > Converting numbers with a signed fixed-point representation to\n> > > > > > > > > the corresponding float value requires to include the sign bit in the\n> > > > > > > > > width of the fixed-point integral part.\n> > > > > > > > >\n> > > > > > > > > Clearly specify it in documentation.\n> > > > > > > > >\n> > > > > > > > > Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n> > > > > > > > > ---\n> > > > > > > > >  src/ipa/libipa/fixedpoint.cpp | 22 +++++++++++++++++++++-\n> > > > > > > > >  1 file changed, 21 insertions(+), 1 deletion(-)\n> > > > > > > > >\n> > > > > > > > > diff --git a/src/ipa/libipa/fixedpoint.cpp b/src/ipa/libipa/fixedpoint.cpp\n> > > > > > > > > index 6b698fc5d680..b37cdc43936f 100644\n> > > > > > > > > --- a/src/ipa/libipa/fixedpoint.cpp\n> > > > > > > > > +++ b/src/ipa/libipa/fixedpoint.cpp\n> > > > > > > > > @@ -29,11 +29,31 @@ namespace ipa {\n> > > > > > > > >  /**\n> > > > > > > > >   * \\fn R fixedToFloatingPoint(T number)\n> > > > > > > > >   * \\brief Convert a fixed-point number to a floating point representation\n> > > > > > > > > - * \\tparam I Bit width of the integer part of the fixed-point\n> > > > > > > > > + * \\tparam I Bit width of the integer part of the fixed-point including the\n> > > > > > > > > + * optional sign bit\n> > > > > > > > >   * \\tparam F Bit width of the fractional part of the fixed-point\n> > > > > > > > >   * \\tparam R Return type of the floating point representation\n> > > > > > > > >   * \\tparam T Input type of the fixed-point representation\n> > > > > > > > >   * \\param number The fixed point number to convert to floating point\n> > > > > > > > > + *\n> > > > > > > > > + * If the fixed-point representation is signed, the sign bit shall be included\n> > > > > > > > > + * in the \\a I template parameter that specifies the number of bits of the\n> > > > > > > > > + * integral part of the fixed-point representation.\n> > > > > > > > > + *\n> > > > > > > > > + * As an example, a value represented as signed fixed-point Q4.8 format can be\n> > > > > > > > > + * converted to its corresponding floating point representation as:\n> > > > > > >\n> > > > > > > Just to be sure - you know I've got patches to remove all of the above\n> > > > > > > that I want to get merged 'soon' right?\n> > > > > >\n> > > > > > Read the last bit of my reply from yesterday :)\n> > >\n> > > I still don't get this?\n> >\n> > I meant the discussion on sign/magnitude representation\n> >\n> > sign/magnitude is a different representation of signed integers\n> > compared to the de-facto standard 2's complement. It requires to\n> > manipulate the result of the float-to-fixed conversion so that we take\n> > the absolute value and the sign bit is set in the [m + n + 1] bit\n> >\n> > ------------------------------------------------------------------------------\n> > As a bit of pseudo code\n> >\n> >         int reg = static_cast<int>(std::round(number * (1 << F)))) & mask;\n> >         uint16_t res += std::abs(reg);\n> >         if (reg < 0)\n> >                 res |= BIT(13);\n> >\n> >\n> > I think this could be surely optimized and nicely made a Traits that\n> > can be added to the Quantized series Kieran is working on.\n> > ------------------------------------------------------------------------------\n> >\n> > The above is the pharse I thought it could make you happy:\n> > sign/magnitude fixed-point formats can be easily be represented with a\n> > Trait on top of your series\n> >\n> > > > > > > Quantized brings in explicit signed/unsigned types through Q<4,8> and\n> > > > > > > UQ<4, 8> types.\n> > > > > >\n> > > > > > What is the difference between signed and unsigned ? Is it only the\n> > > > > > sign bit ? I guess then that the Q<4,8>[12:0] = UQ<4,8>[11:0]\n> > > > >\n> > > > > Please take a look through the tests I've added:\n> > > > >\n> > > > > https://patchwork.libcamera.org/patch/25801/\n> > > > >\n> > > > > /* Q1.7(-1 .. 0.992188)  Min: [0x80:-1] -- Max: [0x7f:0.992188] Step:0.0078125*/\n> > > > > /* UQ1.7(0 .. 1.99219)  Min: [0x00:0] -- Max: [0xff:1.99219] Step:0.0078125 */\n> > > > >\n> > > > > /* Q12.4(-2048 .. 2047.94)  Min: [0x8000:-2048] -- Max: [0x7fff:2047.94] Step:0.0625 */\n> > > > > /* UQ12.4(0 .. 4095.94)  Min: [0x0000:0] -- Max: [0xffff:4095.94] Step:0.0625 */\n> > > > >\n> > > > > It's easy to extend that if you have specific Q types you want to\n> > > > > use/test.\n> > > >\n> > > > Ah yes, for min/max it's defintely useful to have signed/unsigned\n> > > > types\n> > >\n> > > It's not about min/max is useful - it's the very fact that Q and UQ have\n> > > a distinct range. Q types can go less than zero but still span the same\n> > > distance, so the top/max is halved, but the step size is the same.\n> >\n> > Yes, min/max and range indeed.\n> >\n> > >\n> > >\n> > > > > > > In the new types Q<I, F> has the sign bit included in 'I'.\n> > > > > > > I can add that explicitly to the documentation in my new series for v6.\n> > > > > >\n> > > > > >\n> > > > > > Well, maybe we need two traits ?\n> > > > > > https://en.wikipedia.org/wiki/Q_(number_format)\n> > > > > >\n> > > > > > Texas Instruments version:\n> > > > > > The first bit always gives the sign of the value (1 = negative, 0 =\n> > > > > > non-negative), and it is not counted in the m parameter. Thus, the\n> > > > > > total number w of bits used is 1 + m + n.\n> > > > > >\n> > > > > > ARM Version:\n> > > > > > A variant of the Q notation has been in use by ARM in which the m\n> > > > > > number also counts the sign bit\n> > > > >\n> > > > > Yes, you've definitely got to know which one the hardware is using and\n> > > > > expecting. I wouldn't make a new trait for this - if we have to specify\n> > > > > we can wrap one in the other if it really helps.\n> > > >\n> > > > I'm not sure, if I'm working with the TI format (which as far as I\n> > > > understand is the most common?) then to have a signed value correctly\n> > > > represented as a Q<4,8> I would have to use Q<5,8> (which is\n> > > > counter-intuitive).\n> > > >\n> > > > I would rather modify the Trait to put the sign in the [m + n + 1]\n> > > > bit.\n> > > >\n> > > > Or are the registers you're working with in ARM format ? (sign in\n> > > > [m + n] position)\n> > >\n> > > That's (include the bit) what the original fixedToFloatingPoint()\n> > > implementations used, so that's what I've continued with.\n> >\n> > I see but that doesn't mean it's correct.\n> >\n> > I read one platform manual the description of a coefficient as\n> >\n> > \"8:0 cc_coeff_0 Coefficient 0 for color space conversion\"\n> > color conversion coefficients are signed integer values with a 7 bit\n> > fractional part; range: [-2…1.992]\n> >\n> > so if there are 7 fractional bit and the max achievable value is 1.992\n> > it means that the value is in Q<1,7> format as:\n> >\n> >         (1 << (1 + 7)) - 1 / (1 << 7) = 1.999\n> >\n> > the register size is 9 bits (see the [8:0] in the register\n> > description) so I the sign bit is at location [8].\n> >\n> > Am I wrong that I want to obtain this with your model I would have to\n> > describe the fixed point representation as Q<2,7> (which doesn't match\n> > the datasheet) ?\n>\n> Why doesn't this match the datasheet ? The text you quoted says 7 bits of\n> fractional value (match), 9 bits register field (8:0, matching 2+7), and\n> the range of Q<2,7> is -2 to +1.992 (1.9921875 to be precise).\n\nOk, this datasheet doesn't specify the value for 'm' but do we agree\nthat if m has to indicate the \"integer\" part, then it should be 1 and\nnot 2 ?\n\nIn the same datasheet we also have:\n\n  10:0 ct_coeff\n  Values are 11-bit signed fixed-point numbers with 4 bit integer and 7\n  bit fractional part, ranging from -8 (0x400) to +7.992 (0x3FF).\"\n\nIn this case the value is suggested as Q<4,7> and the register is of\n11 bits, so bit[11] is the sign.\n\nDatasheets for other platforms clearly say that a signed Q<4,8> format\nis stored in 13 bits, so I should have to use Q<5,8> to have the sign\nbit in position [13] I guess\n\nI feel like, give the wide variety of option, we should be able to\ncontrol where the sign bit goes to accommodate different vendors, or\neven different register formats from the same vendor.\n\n>\n> > And I guess this really is the difference between UQ<m, n> and Q<m, n>\n> >\n> > usigned Q has no sign bit and the destination register is of size [m+n]\n> > signed Q has a sign bit in position [m+n+1] with the value in 2's\n> > complement format and destination register of size [m+n+1]\n>\n> In Kieran's implementation, Q<m, n> is stored in m+n bits, not m+n+1.\n>\n> > > If you want to distinguish these? How should we represent them?\n> > >\n> > > /* All 8 bit storage */\n> > > UQ<1, 7> Q<1, 7> Q_TI<0, 7> ?\n> >\n> > Let's start by deciding what behaviour we want by default maybe..\n>\n> Let's pick one option and stick to it please. Yes, writing Q<4, 12> when\n> a TI datasheet says \"Q3.12 value\" may be a bit confusing, but it's\n\nI'm not sure this is limited by TI, I actually see datasheet from the\nauthor of the variant Q format complying with the TI version of the Q\nformat.. So don't assume the \"ARM format\" is used on ARM platforms and\nTI format on TI ones..\n\n\n> encoding in the type in one place and the rest of the code doesn't have\n> to think about it.\n>\n> We *could* define device-specific aliases in specific IPA modules if we\n> really wanted, but I wouldn't define multiple types in libipa.\n>\n> > > > > > I guess the only way to know which one is meant to be used is to\n> > > > > > actually look at the register sizes. If a Q<4,8> number is stored as\n> > > > > > a 13 bit fields, then the TI version is used. I wonder how common the\n> > > > > > ARM version is.\n> > > > > >\n> > > > > > > \"\"\"\n> > > > > > >  * The sign of the value is determined by the sign of \\a T. For signed types,\n> > > > > > >  * the number of integer bits includes the sign bit.\n> > > > > > > \"\"\"\n> > > > > > >\n> > > > > > > > I'm a bit confused here. Doesn't signed Q4.8 mean that the first bit of\n> > > > > > > > the 4 is the sign bit? The same way a signed int32 has the signed bit on\n> > > > > > > > the first of the 32 bits?\n> > > > > > > >\n> > > > > > > > > + *\n> > > > > > > > > + * \\code{.cpp}\n> > > > > > > > > + * double d = fixedToFloatingPoint<5, 8, double, uint16_t>(fixed);\n> > > > > > > > > + * \\endcode\n> > > > > > > > > + *\n> > > > > > > > > + * While a value represented as unsigned fixed-point Q4.8 format can be\n> > > > > > > > > + * converted as:\n> > > > > > > > > + *\n> > > > > > > > > + * \\code{.cpp}\n> > > > > > > > > + * double d = fixedToFloatingPoint<4, 8, double, uint16_t>(fixed);\n> > > > > > > > > + * \\endcode\n> > > > > > > > > + *\n> > > > > > > > >   * \\return The converted value\n> > > > > > > > >   */\n> > > > > > > > >\n>\n> --\n> Regards,\n>\n> Laurent Pinchart","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id AD552C3220\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 21 Jan 2026 16:54:41 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id CF79B61FC9;\n\tWed, 21 Jan 2026 17:54:40 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 3FED761F9F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 21 Jan 2026 17:54:39 +0100 (CET)","from ideasonboard.com (static.170.20.224.46.clients.your-server.de\n\t[46.224.20.170])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id E44FD833;\n\tWed, 21 Jan 2026 17:54:06 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"I7NnUTmS\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1769014447;\n\tbh=jbGk7abLKRUc2bZ+1t28DmaucUeY2LPMH1sYHHZ2yW4=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=I7NnUTmSh0T40t9vWCn9rR4cZOE109QUm7M/FSUtOyWE10rtwU/46eXSP3XMqmb1f\n\t4VAG7oWFPne4iRTI9hvOKY+vNDVnMezrqdob+7325b1z98TPhjGs/1N2xERJNHJdSv\n\toMUlUAF7UjVmSP3Vzh5OOnOK243jWxbjtF/v7x2U=","Date":"Wed, 21 Jan 2026 17:54:35 +0100","From":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>, \n\tKieran Bingham <kieran.bingham@ideasonboard.com>,\n\tStefan Klug <stefan.klug@ideasonboard.com>, \n\tlibcamera-devel@lists.libcamera.org,\n\tPaul Elder <paul.elder@ideasonboard.com>","Subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","Message-ID":"<aXECEOf5wie2EZvI@zed>","References":"<20260120083952.15338-1-jacopo.mondi@ideasonboard.com>\n\t<176889918695.508107.16263205271582334087@localhost>\n\t<176899822075.3544004.689251715744219495@ping.linuxembedded.co.uk>\n\t<aXDJol4kIvRx6_49@zed>\n\t<176900670418.1693075.17512355310821360852@ping.linuxembedded.co.uk>\n\t<aXDsQiDhhbWWuKV1@zed>\n\t<176901024127.1693075.2963823420483106366@ping.linuxembedded.co.uk>\n\t<aXD1saAAJ248-U0S@zed> <20260121163755.GG382676@killaraus>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20260121163755.GG382676@killaraus>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":37824,"web_url":"https://patchwork.libcamera.org/comment/37824/","msgid":"<20260121180008.GH382676@killaraus>","date":"2026-01-21T18:00:08","subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"On Wed, Jan 21, 2026 at 05:54:35PM +0100, Jacopo Mondi wrote:\n> On Wed, Jan 21, 2026 at 06:37:55PM +0200, Laurent Pinchart wrote:\n> > On Wed, Jan 21, 2026 at 05:13:02PM +0100, Jacopo Mondi wrote:\n> > > On Wed, Jan 21, 2026 at 03:44:01PM +0000, Kieran Bingham wrote:\n> > > > Quoting Jacopo Mondi (2026-01-21 15:12:24)\n> > > > > On Wed, Jan 21, 2026 at 02:45:04PM +0000, Kieran Bingham wrote:\n> > > > > > Quoting Jacopo Mondi (2026-01-21 12:53:49)\n> > > > > > > On Wed, Jan 21, 2026 at 12:23:40PM +0000, Kieran Bingham wrote:\n> > > > > > > > Quoting Stefan Klug (2026-01-20 08:53:06)\n> > > > > > > > > Quoting Jacopo Mondi (2026-01-20 09:39:49)\n> > > > > > > > > > Converting numbers with a signed fixed-point representation to\n> > > > > > > > > > the corresponding float value requires to include the sign bit in the\n> > > > > > > > > > width of the fixed-point integral part.\n> > > > > > > > > >\n> > > > > > > > > > Clearly specify it in documentation.\n> > > > > > > > > >\n> > > > > > > > > > Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n> > > > > > > > > > ---\n> > > > > > > > > >  src/ipa/libipa/fixedpoint.cpp | 22 +++++++++++++++++++++-\n> > > > > > > > > >  1 file changed, 21 insertions(+), 1 deletion(-)\n> > > > > > > > > >\n> > > > > > > > > > diff --git a/src/ipa/libipa/fixedpoint.cpp b/src/ipa/libipa/fixedpoint.cpp\n> > > > > > > > > > index 6b698fc5d680..b37cdc43936f 100644\n> > > > > > > > > > --- a/src/ipa/libipa/fixedpoint.cpp\n> > > > > > > > > > +++ b/src/ipa/libipa/fixedpoint.cpp\n> > > > > > > > > > @@ -29,11 +29,31 @@ namespace ipa {\n> > > > > > > > > >  /**\n> > > > > > > > > >   * \\fn R fixedToFloatingPoint(T number)\n> > > > > > > > > >   * \\brief Convert a fixed-point number to a floating point representation\n> > > > > > > > > > - * \\tparam I Bit width of the integer part of the fixed-point\n> > > > > > > > > > + * \\tparam I Bit width of the integer part of the fixed-point including the\n> > > > > > > > > > + * optional sign bit\n> > > > > > > > > >   * \\tparam F Bit width of the fractional part of the fixed-point\n> > > > > > > > > >   * \\tparam R Return type of the floating point representation\n> > > > > > > > > >   * \\tparam T Input type of the fixed-point representation\n> > > > > > > > > >   * \\param number The fixed point number to convert to floating point\n> > > > > > > > > > + *\n> > > > > > > > > > + * If the fixed-point representation is signed, the sign bit shall be included\n> > > > > > > > > > + * in the \\a I template parameter that specifies the number of bits of the\n> > > > > > > > > > + * integral part of the fixed-point representation.\n> > > > > > > > > > + *\n> > > > > > > > > > + * As an example, a value represented as signed fixed-point Q4.8 format can be\n> > > > > > > > > > + * converted to its corresponding floating point representation as:\n> > > > > > > >\n> > > > > > > > Just to be sure - you know I've got patches to remove all of the above\n> > > > > > > > that I want to get merged 'soon' right?\n> > > > > > >\n> > > > > > > Read the last bit of my reply from yesterday :)\n> > > >\n> > > > I still don't get this?\n> > >\n> > > I meant the discussion on sign/magnitude representation\n> > >\n> > > sign/magnitude is a different representation of signed integers\n> > > compared to the de-facto standard 2's complement. It requires to\n> > > manipulate the result of the float-to-fixed conversion so that we take\n> > > the absolute value and the sign bit is set in the [m + n + 1] bit\n> > >\n> > > ------------------------------------------------------------------------------\n> > > As a bit of pseudo code\n> > >\n> > >         int reg = static_cast<int>(std::round(number * (1 << F)))) & mask;\n> > >         uint16_t res += std::abs(reg);\n> > >         if (reg < 0)\n> > >                 res |= BIT(13);\n> > >\n> > >\n> > > I think this could be surely optimized and nicely made a Traits that\n> > > can be added to the Quantized series Kieran is working on.\n> > > ------------------------------------------------------------------------------\n> > >\n> > > The above is the pharse I thought it could make you happy:\n> > > sign/magnitude fixed-point formats can be easily be represented with a\n> > > Trait on top of your series\n> > >\n> > > > > > > > Quantized brings in explicit signed/unsigned types through Q<4,8> and\n> > > > > > > > UQ<4, 8> types.\n> > > > > > >\n> > > > > > > What is the difference between signed and unsigned ? Is it only the\n> > > > > > > sign bit ? I guess then that the Q<4,8>[12:0] = UQ<4,8>[11:0]\n> > > > > >\n> > > > > > Please take a look through the tests I've added:\n> > > > > >\n> > > > > > https://patchwork.libcamera.org/patch/25801/\n> > > > > >\n> > > > > > /* Q1.7(-1 .. 0.992188)  Min: [0x80:-1] -- Max: [0x7f:0.992188] Step:0.0078125*/\n> > > > > > /* UQ1.7(0 .. 1.99219)  Min: [0x00:0] -- Max: [0xff:1.99219] Step:0.0078125 */\n> > > > > >\n> > > > > > /* Q12.4(-2048 .. 2047.94)  Min: [0x8000:-2048] -- Max: [0x7fff:2047.94] Step:0.0625 */\n> > > > > > /* UQ12.4(0 .. 4095.94)  Min: [0x0000:0] -- Max: [0xffff:4095.94] Step:0.0625 */\n> > > > > >\n> > > > > > It's easy to extend that if you have specific Q types you want to\n> > > > > > use/test.\n> > > > >\n> > > > > Ah yes, for min/max it's defintely useful to have signed/unsigned\n> > > > > types\n> > > >\n> > > > It's not about min/max is useful - it's the very fact that Q and UQ have\n> > > > a distinct range. Q types can go less than zero but still span the same\n> > > > distance, so the top/max is halved, but the step size is the same.\n> > >\n> > > Yes, min/max and range indeed.\n> > >\n> > > > > > > > In the new types Q<I, F> has the sign bit included in 'I'.\n> > > > > > > > I can add that explicitly to the documentation in my new series for v6.\n> > > > > > >\n> > > > > > >\n> > > > > > > Well, maybe we need two traits ?\n> > > > > > > https://en.wikipedia.org/wiki/Q_(number_format)\n> > > > > > >\n> > > > > > > Texas Instruments version:\n> > > > > > > The first bit always gives the sign of the value (1 = negative, 0 =\n> > > > > > > non-negative), and it is not counted in the m parameter. Thus, the\n> > > > > > > total number w of bits used is 1 + m + n.\n> > > > > > >\n> > > > > > > ARM Version:\n> > > > > > > A variant of the Q notation has been in use by ARM in which the m\n> > > > > > > number also counts the sign bit\n> > > > > >\n> > > > > > Yes, you've definitely got to know which one the hardware is using and\n> > > > > > expecting. I wouldn't make a new trait for this - if we have to specify\n> > > > > > we can wrap one in the other if it really helps.\n> > > > >\n> > > > > I'm not sure, if I'm working with the TI format (which as far as I\n> > > > > understand is the most common?) then to have a signed value correctly\n> > > > > represented as a Q<4,8> I would have to use Q<5,8> (which is\n> > > > > counter-intuitive).\n> > > > >\n> > > > > I would rather modify the Trait to put the sign in the [m + n + 1]\n> > > > > bit.\n> > > > >\n> > > > > Or are the registers you're working with in ARM format ? (sign in\n> > > > > [m + n] position)\n> > > >\n> > > > That's (include the bit) what the original fixedToFloatingPoint()\n> > > > implementations used, so that's what I've continued with.\n> > >\n> > > I see but that doesn't mean it's correct.\n> > >\n> > > I read one platform manual the description of a coefficient as\n> > >\n> > > \"8:0 cc_coeff_0 Coefficient 0 for color space conversion\"\n> > > color conversion coefficients are signed integer values with a 7 bit\n> > > fractional part; range: [-2…1.992]\n> > >\n> > > so if there are 7 fractional bit and the max achievable value is 1.992\n> > > it means that the value is in Q<1,7> format as:\n> > >\n> > >         (1 << (1 + 7)) - 1 / (1 << 7) = 1.999\n> > >\n> > > the register size is 9 bits (see the [8:0] in the register\n> > > description) so I the sign bit is at location [8].\n> > >\n> > > Am I wrong that I want to obtain this with your model I would have to\n> > > describe the fixed point representation as Q<2,7> (which doesn't match\n> > > the datasheet) ?\n> >\n> > Why doesn't this match the datasheet ? The text you quoted says 7 bits of\n> > fractional value (match), 9 bits register field (8:0, matching 2+7), and\n> > the range of Q<2,7> is -2 to +1.992 (1.9921875 to be precise).\n> \n> Ok, this datasheet doesn't specify the value for 'm' but do we agree\n> that if m has to indicate the \"integer\" part, then it should be 1 and\n> not 2 ?\n\nNo :-) If you want a range from -2 to 1.992, the 'm' value given the\nconvention in this series is 2.\n\n> In the same datasheet we also have:\n> \n>   10:0 ct_coeff\n>   Values are 11-bit signed fixed-point numbers with 4 bit integer and 7\n>   bit fractional part, ranging from -8 (0x400) to +7.992 (0x3FF).\"\n> \n> In this case the value is suggested as Q<4,7> and the register is of\n> 11 bits, so bit[11] is the sign.\n> \n> Datasheets for other platforms clearly say that a signed Q<4,8> format\n> is stored in 13 bits, so I should have to use Q<5,8> to have the sign\n> bit in position [13] I guess\n\nAs discussed in this thread, there are multiple conventions. The\nconvention taken in this series is that Q<4, 8> is stored in 12 bits.\nThere's no single convention that will match all documentation ever\nwritten, so we should pick one an live with it. I vote for the\nconvention in this series (a.k.a. the ARM convention).\n\n> I feel like, give the wide variety of option, we should be able to\n> control where the sign bit goes to accommodate different vendors, or\n> even different register formats from the same vendor.\n> \n> > > And I guess this really is the difference between UQ<m, n> and Q<m, n>\n> > >\n> > > usigned Q has no sign bit and the destination register is of size [m+n]\n> > > signed Q has a sign bit in position [m+n+1] with the value in 2's\n> > > complement format and destination register of size [m+n+1]\n> >\n> > In Kieran's implementation, Q<m, n> is stored in m+n bits, not m+n+1.\n> >\n> > > > If you want to distinguish these? How should we represent them?\n> > > >\n> > > > /* All 8 bit storage */\n> > > > UQ<1, 7> Q<1, 7> Q_TI<0, 7> ?\n> > >\n> > > Let's start by deciding what behaviour we want by default maybe..\n> >\n> > Let's pick one option and stick to it please. Yes, writing Q<4, 12> when\n> > a TI datasheet says \"Q3.12 value\" may be a bit confusing, but it's\n> \n> I'm not sure this is limited by TI, I actually see datasheet from the\n> author of the variant Q format complying with the TI version of the Q\n> format.. So don't assume the \"ARM format\" is used on ARM platforms and\n> TI format on TI ones..\n> \n> > encoding in the type in one place and the rest of the code doesn't have\n> > to think about it.\n> >\n> > We *could* define device-specific aliases in specific IPA modules if we\n> > really wanted, but I wouldn't define multiple types in libipa.\n> >\n> > > > > > > I guess the only way to know which one is meant to be used is to\n> > > > > > > actually look at the register sizes. If a Q<4,8> number is stored as\n> > > > > > > a 13 bit fields, then the TI version is used. I wonder how common the\n> > > > > > > ARM version is.\n> > > > > > >\n> > > > > > > > \"\"\"\n> > > > > > > >  * The sign of the value is determined by the sign of \\a T. For signed types,\n> > > > > > > >  * the number of integer bits includes the sign bit.\n> > > > > > > > \"\"\"\n> > > > > > > >\n> > > > > > > > > I'm a bit confused here. Doesn't signed Q4.8 mean that the first bit of\n> > > > > > > > > the 4 is the sign bit? The same way a signed int32 has the signed bit on\n> > > > > > > > > the first of the 32 bits?\n> > > > > > > > >\n> > > > > > > > > > + *\n> > > > > > > > > > + * \\code{.cpp}\n> > > > > > > > > > + * double d = fixedToFloatingPoint<5, 8, double, uint16_t>(fixed);\n> > > > > > > > > > + * \\endcode\n> > > > > > > > > > + *\n> > > > > > > > > > + * While a value represented as unsigned fixed-point Q4.8 format can be\n> > > > > > > > > > + * converted as:\n> > > > > > > > > > + *\n> > > > > > > > > > + * \\code{.cpp}\n> > > > > > > > > > + * double d = fixedToFloatingPoint<4, 8, double, uint16_t>(fixed);\n> > > > > > > > > > + * \\endcode\n> > > > > > > > > > + *\n> > > > > > > > > >   * \\return The converted value\n> > > > > > > > > >   */\n> > > > > > > > > >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 07FC5C3220\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 21 Jan 2026 18:00:13 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id C684561FC4;\n\tWed, 21 Jan 2026 19:00:11 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id ED19461F9F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 21 Jan 2026 19:00:09 +0100 (CET)","from pendragon.ideasonboard.com\n\t(2001-14ba-703d-e500--2a1.rev.dnainternet.fi\n\t[IPv6:2001:14ba:703d:e500::2a1])\n\tby perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id 7F169741;\n\tWed, 21 Jan 2026 18:59:37 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"DwQqQKsn\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1769018377;\n\tbh=ONpc7UorwMLZlr3beCVF67oZyFMucGxTYwHNK88Ctrk=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=DwQqQKsnLd3rYv6HrgjC+O6Ln33103f09xVFuJ3kAZony1m10/OQMxO6WVOPdmvT7\n\tBMOaxa/jpmWlaJsufpfv//2vJyvpoBoC2R0v4ws21CvIUuRXJiMPGMMYFg7ws4pf3U\n\tBmhIeqM6qrakXReE+Ihk7U/GbTQ+WkE1MhoIfvCQ=","Date":"Wed, 21 Jan 2026 20:00:08 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","Cc":"Kieran Bingham <kieran.bingham@ideasonboard.com>,\n\tStefan Klug <stefan.klug@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org,\n\tPaul Elder <paul.elder@ideasonboard.com>","Subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","Message-ID":"<20260121180008.GH382676@killaraus>","References":"<20260120083952.15338-1-jacopo.mondi@ideasonboard.com>\n\t<176889918695.508107.16263205271582334087@localhost>\n\t<176899822075.3544004.689251715744219495@ping.linuxembedded.co.uk>\n\t<aXDJol4kIvRx6_49@zed>\n\t<176900670418.1693075.17512355310821360852@ping.linuxembedded.co.uk>\n\t<aXDsQiDhhbWWuKV1@zed>\n\t<176901024127.1693075.2963823420483106366@ping.linuxembedded.co.uk>\n\t<aXD1saAAJ248-U0S@zed> <20260121163755.GG382676@killaraus>\n\t<aXECEOf5wie2EZvI@zed>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<aXECEOf5wie2EZvI@zed>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":37825,"web_url":"https://patchwork.libcamera.org/comment/37825/","msgid":"<aXEXs1ROzMLHuamT@zed>","date":"2026-01-21T18:17:51","subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","submitter":{"id":143,"url":"https://patchwork.libcamera.org/api/people/143/","name":"Jacopo Mondi","email":"jacopo.mondi@ideasonboard.com"},"content":"Hi Laurent\n\nOn Wed, Jan 21, 2026 at 08:00:08PM +0200, Laurent Pinchart wrote:\n> On Wed, Jan 21, 2026 at 05:54:35PM +0100, Jacopo Mondi wrote:\n> > On Wed, Jan 21, 2026 at 06:37:55PM +0200, Laurent Pinchart wrote:\n> > > On Wed, Jan 21, 2026 at 05:13:02PM +0100, Jacopo Mondi wrote:\n> > > > On Wed, Jan 21, 2026 at 03:44:01PM +0000, Kieran Bingham wrote:\n> > > > > Quoting Jacopo Mondi (2026-01-21 15:12:24)\n> > > > > > On Wed, Jan 21, 2026 at 02:45:04PM +0000, Kieran Bingham wrote:\n> > > > > > > Quoting Jacopo Mondi (2026-01-21 12:53:49)\n> > > > > > > > On Wed, Jan 21, 2026 at 12:23:40PM +0000, Kieran Bingham wrote:\n> > > > > > > > > Quoting Stefan Klug (2026-01-20 08:53:06)\n> > > > > > > > > > Quoting Jacopo Mondi (2026-01-20 09:39:49)\n> > > > > > > > > > > Converting numbers with a signed fixed-point representation to\n> > > > > > > > > > > the corresponding float value requires to include the sign bit in the\n> > > > > > > > > > > width of the fixed-point integral part.\n> > > > > > > > > > >\n> > > > > > > > > > > Clearly specify it in documentation.\n> > > > > > > > > > >\n> > > > > > > > > > > Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n> > > > > > > > > > > ---\n> > > > > > > > > > >  src/ipa/libipa/fixedpoint.cpp | 22 +++++++++++++++++++++-\n> > > > > > > > > > >  1 file changed, 21 insertions(+), 1 deletion(-)\n> > > > > > > > > > >\n> > > > > > > > > > > diff --git a/src/ipa/libipa/fixedpoint.cpp b/src/ipa/libipa/fixedpoint.cpp\n> > > > > > > > > > > index 6b698fc5d680..b37cdc43936f 100644\n> > > > > > > > > > > --- a/src/ipa/libipa/fixedpoint.cpp\n> > > > > > > > > > > +++ b/src/ipa/libipa/fixedpoint.cpp\n> > > > > > > > > > > @@ -29,11 +29,31 @@ namespace ipa {\n> > > > > > > > > > >  /**\n> > > > > > > > > > >   * \\fn R fixedToFloatingPoint(T number)\n> > > > > > > > > > >   * \\brief Convert a fixed-point number to a floating point representation\n> > > > > > > > > > > - * \\tparam I Bit width of the integer part of the fixed-point\n> > > > > > > > > > > + * \\tparam I Bit width of the integer part of the fixed-point including the\n> > > > > > > > > > > + * optional sign bit\n> > > > > > > > > > >   * \\tparam F Bit width of the fractional part of the fixed-point\n> > > > > > > > > > >   * \\tparam R Return type of the floating point representation\n> > > > > > > > > > >   * \\tparam T Input type of the fixed-point representation\n> > > > > > > > > > >   * \\param number The fixed point number to convert to floating point\n> > > > > > > > > > > + *\n> > > > > > > > > > > + * If the fixed-point representation is signed, the sign bit shall be included\n> > > > > > > > > > > + * in the \\a I template parameter that specifies the number of bits of the\n> > > > > > > > > > > + * integral part of the fixed-point representation.\n> > > > > > > > > > > + *\n> > > > > > > > > > > + * As an example, a value represented as signed fixed-point Q4.8 format can be\n> > > > > > > > > > > + * converted to its corresponding floating point representation as:\n> > > > > > > > >\n> > > > > > > > > Just to be sure - you know I've got patches to remove all of the above\n> > > > > > > > > that I want to get merged 'soon' right?\n> > > > > > > >\n> > > > > > > > Read the last bit of my reply from yesterday :)\n> > > > >\n> > > > > I still don't get this?\n> > > >\n> > > > I meant the discussion on sign/magnitude representation\n> > > >\n> > > > sign/magnitude is a different representation of signed integers\n> > > > compared to the de-facto standard 2's complement. It requires to\n> > > > manipulate the result of the float-to-fixed conversion so that we take\n> > > > the absolute value and the sign bit is set in the [m + n + 1] bit\n> > > >\n> > > > ------------------------------------------------------------------------------\n> > > > As a bit of pseudo code\n> > > >\n> > > >         int reg = static_cast<int>(std::round(number * (1 << F)))) & mask;\n> > > >         uint16_t res += std::abs(reg);\n> > > >         if (reg < 0)\n> > > >                 res |= BIT(13);\n> > > >\n> > > >\n> > > > I think this could be surely optimized and nicely made a Traits that\n> > > > can be added to the Quantized series Kieran is working on.\n> > > > ------------------------------------------------------------------------------\n> > > >\n> > > > The above is the pharse I thought it could make you happy:\n> > > > sign/magnitude fixed-point formats can be easily be represented with a\n> > > > Trait on top of your series\n> > > >\n> > > > > > > > > Quantized brings in explicit signed/unsigned types through Q<4,8> and\n> > > > > > > > > UQ<4, 8> types.\n> > > > > > > >\n> > > > > > > > What is the difference between signed and unsigned ? Is it only the\n> > > > > > > > sign bit ? I guess then that the Q<4,8>[12:0] = UQ<4,8>[11:0]\n> > > > > > >\n> > > > > > > Please take a look through the tests I've added:\n> > > > > > >\n> > > > > > > https://patchwork.libcamera.org/patch/25801/\n> > > > > > >\n> > > > > > > /* Q1.7(-1 .. 0.992188)  Min: [0x80:-1] -- Max: [0x7f:0.992188] Step:0.0078125*/\n> > > > > > > /* UQ1.7(0 .. 1.99219)  Min: [0x00:0] -- Max: [0xff:1.99219] Step:0.0078125 */\n> > > > > > >\n> > > > > > > /* Q12.4(-2048 .. 2047.94)  Min: [0x8000:-2048] -- Max: [0x7fff:2047.94] Step:0.0625 */\n> > > > > > > /* UQ12.4(0 .. 4095.94)  Min: [0x0000:0] -- Max: [0xffff:4095.94] Step:0.0625 */\n> > > > > > >\n> > > > > > > It's easy to extend that if you have specific Q types you want to\n> > > > > > > use/test.\n> > > > > >\n> > > > > > Ah yes, for min/max it's defintely useful to have signed/unsigned\n> > > > > > types\n> > > > >\n> > > > > It's not about min/max is useful - it's the very fact that Q and UQ have\n> > > > > a distinct range. Q types can go less than zero but still span the same\n> > > > > distance, so the top/max is halved, but the step size is the same.\n> > > >\n> > > > Yes, min/max and range indeed.\n> > > >\n> > > > > > > > > In the new types Q<I, F> has the sign bit included in 'I'.\n> > > > > > > > > I can add that explicitly to the documentation in my new series for v6.\n> > > > > > > >\n> > > > > > > >\n> > > > > > > > Well, maybe we need two traits ?\n> > > > > > > > https://en.wikipedia.org/wiki/Q_(number_format)\n> > > > > > > >\n> > > > > > > > Texas Instruments version:\n> > > > > > > > The first bit always gives the sign of the value (1 = negative, 0 =\n> > > > > > > > non-negative), and it is not counted in the m parameter. Thus, the\n> > > > > > > > total number w of bits used is 1 + m + n.\n> > > > > > > >\n> > > > > > > > ARM Version:\n> > > > > > > > A variant of the Q notation has been in use by ARM in which the m\n> > > > > > > > number also counts the sign bit\n> > > > > > >\n> > > > > > > Yes, you've definitely got to know which one the hardware is using and\n> > > > > > > expecting. I wouldn't make a new trait for this - if we have to specify\n> > > > > > > we can wrap one in the other if it really helps.\n> > > > > >\n> > > > > > I'm not sure, if I'm working with the TI format (which as far as I\n> > > > > > understand is the most common?) then to have a signed value correctly\n> > > > > > represented as a Q<4,8> I would have to use Q<5,8> (which is\n> > > > > > counter-intuitive).\n> > > > > >\n> > > > > > I would rather modify the Trait to put the sign in the [m + n + 1]\n> > > > > > bit.\n> > > > > >\n> > > > > > Or are the registers you're working with in ARM format ? (sign in\n> > > > > > [m + n] position)\n> > > > >\n> > > > > That's (include the bit) what the original fixedToFloatingPoint()\n> > > > > implementations used, so that's what I've continued with.\n> > > >\n> > > > I see but that doesn't mean it's correct.\n> > > >\n> > > > I read one platform manual the description of a coefficient as\n> > > >\n> > > > \"8:0 cc_coeff_0 Coefficient 0 for color space conversion\"\n> > > > color conversion coefficients are signed integer values with a 7 bit\n> > > > fractional part; range: [-2…1.992]\n> > > >\n> > > > so if there are 7 fractional bit and the max achievable value is 1.992\n> > > > it means that the value is in Q<1,7> format as:\n> > > >\n> > > >         (1 << (1 + 7)) - 1 / (1 << 7) = 1.999\n> > > >\n> > > > the register size is 9 bits (see the [8:0] in the register\n> > > > description) so I the sign bit is at location [8].\n> > > >\n> > > > Am I wrong that I want to obtain this with your model I would have to\n> > > > describe the fixed point representation as Q<2,7> (which doesn't match\n> > > > the datasheet) ?\n> > >\n> > > Why doesn't this match the datasheet ? The text you quoted says 7 bits of\n> > > fractional value (match), 9 bits register field (8:0, matching 2+7), and\n> > > the range of Q<2,7> is -2 to +1.992 (1.9921875 to be precise).\n> >\n> > Ok, this datasheet doesn't specify the value for 'm' but do we agree\n> > that if m has to indicate the \"integer\" part, then it should be 1 and\n> > not 2 ?\n>\n> No :-) If you want a range from -2 to 1.992, the 'm' value given the\n> convention in this series is 2.\n\nIf you count the sign bit, yes\n\n\n>\n> > In the same datasheet we also have:\n> >\n> >   10:0 ct_coeff\n> >   Values are 11-bit signed fixed-point numbers with 4 bit integer and 7\n> >   bit fractional part, ranging from -8 (0x400) to +7.992 (0x3FF).\"\n> >\n> > In this case the value is suggested as Q<4,7> and the register is of\n> > 11 bits, so bit[11] is the sign.\n> >\n> > Datasheets for other platforms clearly say that a signed Q<4,8> format\n> > is stored in 13 bits, so I should have to use Q<5,8> to have the sign\n> > bit in position [13] I guess\n>\n> As discussed in this thread, there are multiple conventions. The\n> convention taken in this series is that Q<4, 8> is stored in 12 bits.\n> There's no single convention that will match all documentation ever\n> written, so we should pick one an live with it. I vote for the\n> convention in this series (a.k.a. the ARM convention).\n>\n\nOk, I would have found the TI one more intuitive though\n\nAs long as it is documented clearly, I'll live with that\n\nThanks\n  j\n\n> > I feel like, give the wide variety of option, we should be able to\n> > control where the sign bit goes to accommodate different vendors, or\n> > even different register formats from the same vendor.\n> >\n> > > > And I guess this really is the difference between UQ<m, n> and Q<m, n>\n> > > >\n> > > > usigned Q has no sign bit and the destination register is of size [m+n]\n> > > > signed Q has a sign bit in position [m+n+1] with the value in 2's\n> > > > complement format and destination register of size [m+n+1]\n> > >\n> > > In Kieran's implementation, Q<m, n> is stored in m+n bits, not m+n+1.\n> > >\n> > > > > If you want to distinguish these? How should we represent them?\n> > > > >\n> > > > > /* All 8 bit storage */\n> > > > > UQ<1, 7> Q<1, 7> Q_TI<0, 7> ?\n> > > >\n> > > > Let's start by deciding what behaviour we want by default maybe..\n> > >\n> > > Let's pick one option and stick to it please. Yes, writing Q<4, 12> when\n> > > a TI datasheet says \"Q3.12 value\" may be a bit confusing, but it's\n> >\n> > I'm not sure this is limited by TI, I actually see datasheet from the\n> > author of the variant Q format complying with the TI version of the Q\n> > format.. So don't assume the \"ARM format\" is used on ARM platforms and\n> > TI format on TI ones..\n> >\n> > > encoding in the type in one place and the rest of the code doesn't have\n> > > to think about it.\n> > >\n> > > We *could* define device-specific aliases in specific IPA modules if we\n> > > really wanted, but I wouldn't define multiple types in libipa.\n> > >\n> > > > > > > > I guess the only way to know which one is meant to be used is to\n> > > > > > > > actually look at the register sizes. If a Q<4,8> number is stored as\n> > > > > > > > a 13 bit fields, then the TI version is used. I wonder how common the\n> > > > > > > > ARM version is.\n> > > > > > > >\n> > > > > > > > > \"\"\"\n> > > > > > > > >  * The sign of the value is determined by the sign of \\a T. For signed types,\n> > > > > > > > >  * the number of integer bits includes the sign bit.\n> > > > > > > > > \"\"\"\n> > > > > > > > >\n> > > > > > > > > > I'm a bit confused here. Doesn't signed Q4.8 mean that the first bit of\n> > > > > > > > > > the 4 is the sign bit? The same way a signed int32 has the signed bit on\n> > > > > > > > > > the first of the 32 bits?\n> > > > > > > > > >\n> > > > > > > > > > > + *\n> > > > > > > > > > > + * \\code{.cpp}\n> > > > > > > > > > > + * double d = fixedToFloatingPoint<5, 8, double, uint16_t>(fixed);\n> > > > > > > > > > > + * \\endcode\n> > > > > > > > > > > + *\n> > > > > > > > > > > + * While a value represented as unsigned fixed-point Q4.8 format can be\n> > > > > > > > > > > + * converted as:\n> > > > > > > > > > > + *\n> > > > > > > > > > > + * \\code{.cpp}\n> > > > > > > > > > > + * double d = fixedToFloatingPoint<4, 8, double, uint16_t>(fixed);\n> > > > > > > > > > > + * \\endcode\n> > > > > > > > > > > + *\n> > > > > > > > > > >   * \\return The converted value\n> > > > > > > > > > >   */\n> > > > > > > > > > >\n>\n> --\n> Regards,\n>\n> Laurent Pinchart","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id AE591BDCBF\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 21 Jan 2026 18:17:57 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id E10F261FCA;\n\tWed, 21 Jan 2026 19:17:56 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id AEB6561F9F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 21 Jan 2026 19:17:55 +0100 (CET)","from ideasonboard.com (static.170.20.224.46.clients.your-server.de\n\t[46.224.20.170])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 3981E741;\n\tWed, 21 Jan 2026 19:17:23 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"Ib9+ZyRd\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1769019443;\n\tbh=9ymp6/pWjtFoQ35sOrEqM7Vhbu8XgpWF23lowOZcXmE=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=Ib9+ZyRdbu3o06uffI8cB4vbPCjGlR5h0T5yqOuf8LtrbHZr3nKHOdhTmSJONAfWh\n\tDHhazrCC3iepbwi4gYIhUkOgffrLBL8Jmbw+NSG0gMCsnrLOVQLDaMOenvbGWZdyos\n\t4NwpKTGEl1V8Wdfe2z5trR65wV24LmnpgynXKknU=","Date":"Wed, 21 Jan 2026 19:17:51 +0100","From":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>, \n\tKieran Bingham <kieran.bingham@ideasonboard.com>,\n\tStefan Klug <stefan.klug@ideasonboard.com>, \n\tlibcamera-devel@lists.libcamera.org,\n\tPaul Elder <paul.elder@ideasonboard.com>","Subject":"Re: [PATCH] ipa: libipa: fixedpoint: Expand documentation on sign\n\tbit","Message-ID":"<aXEXs1ROzMLHuamT@zed>","References":"<176889918695.508107.16263205271582334087@localhost>\n\t<176899822075.3544004.689251715744219495@ping.linuxembedded.co.uk>\n\t<aXDJol4kIvRx6_49@zed>\n\t<176900670418.1693075.17512355310821360852@ping.linuxembedded.co.uk>\n\t<aXDsQiDhhbWWuKV1@zed>\n\t<176901024127.1693075.2963823420483106366@ping.linuxembedded.co.uk>\n\t<aXD1saAAJ248-U0S@zed> <20260121163755.GG382676@killaraus>\n\t<aXECEOf5wie2EZvI@zed> <20260121180008.GH382676@killaraus>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20260121180008.GH382676@killaraus>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]