From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=0.2 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED autolearn=no autolearn_force=no version=3.4.4 Received: (qmail 20155 invoked from network); 30 Dec 2022 13:21:27 -0000 Received: from 9front.inri.net (168.235.81.73) by inbox.vuxu.org with ESMTPUTF8; 30 Dec 2022 13:21:27 -0000 Received: from mail.cosarara.me ([159.69.205.102]) by 9front; Fri Dec 30 08:20:06 -0500 2022 Received: from [192.168.49.141] (unknown [93.176.172.208]) by mail.cosarara.me (Postfix) with ESMTPSA id 99EF8130CC for <9front@9front.org>; Fri, 30 Dec 2022 14:20:00 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cosarara.me; s=20200226; t=1672406400; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=yNM8LQf8/R7pD7cwXeGspdBO0f/uEQb/aFfGZIkZD4U=; b=i9wK3OgjNw9D1WZDWjJ3RHJ4wnAolVodMpEjWLqqgqxEaLO80XeLzjovrVckQb194JwqAD JOlxdWlLc6AbF8vcsfyFJSVQxnjW3diEvvBEHxTpcdpW2nbZ3SzThgGFMByFERsmzGIp0Y SlruM0uyXBDkegTBdvLlkV3VapRL4XY= Message-ID: <6d3b100d-1732-efa2-f01c-728440859ba2@cosarara.me> Date: Fri, 30 Dec 2022 14:19:59 +0100 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.4.2 From: cosarara To: 9front@9front.org Content-Language: en-US Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: quoted-printable List-ID: <9front.9front.org> List-Help: X-Glyph: ➈ X-Bullshit: virtual advanced rich-client polling manager Subject: [9front] Bug converting vlong to double on 32bit architectures Reply-To: 9front@9front.org Precedence: bulk Hi, While trying to run kvik's lu9 on ARM, I found that when converting=20 LLONG_MIN to a double on 32bit systems, the result is wrong (positive=20 instead of negative). Given the following test program: #include #include #define LLONG_MAX #define LLONG_MIN (-LLONG_MAX-1) void main() { vlong min =3D LLONG_MIN; double dmin =3D min; print("minint %lld\n", min); print("minint as double %f\n", dmin); if (dmin > 0.0) { exits("int min as double turned positive"); } exits(0); } The output on x86_64 will be: minint -9223372036854775808 minint as double -9223372036854776400.000000 But on arm or 386 (and I expect also spim, 68000, mips, 68020, sparc,=20 power, since they all use the same _v2d): minint -9223372036854775808 minint as double 9223372036854776400.000000 And the value turned positive in the conversion. The function used for the cast to double is (in /sys/src/libc/arm/vlrt.c)= : #define SIGN(n) (1UL<<(n-1)) double _v2d(Vlong x) { if(x.hi & SIGN(32)) { if(x.lo) { x.lo =3D -x.lo; x.hi =3D ~x.hi; } else x.hi =3D -x.hi; return -((long)x.hi*4294967296. + x.lo); } return (long)x.hi*4294967296. + x.lo; } If I understand correctly, the issue is that where it tries to flip the=20 sign for x.hi (x.hi =3D -x.hi), 0x80000000 has no positive, thus stays th= e=20 same (it stays negative). Then when we get to the negative return, we=20 get a positive out. What came to my mind then, is that in the case that there is no x.lo, we=20 can keep the x.hi sign and cast directly, thus: double _v2d(Vlong x) { =C2=A0=C2=A0=C2=A0=C2=A0if(!x.lo) { =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return (long)x.hi*4294967296.= ; =C2=A0=C2=A0=C2=A0=C2=A0} =C2=A0=C2=A0=C2=A0=C2=A0if(x.hi & SIGN(32)) { =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 x.lo =3D -x.lo; =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 x.hi =3D ~x.hi; =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return -((long)x.hi*429496729= 6. + x.lo); =C2=A0=C2=A0=C2=A0=C2=A0} =C2=A0=C2=A0=C2=A0=C2=A0return (long)x.hi*4294967296. + x.lo; } This looks correct to me, but I don't trust myself to not make mistakes=20 in such critical code, so I would like some feedback on the change. Happy new year in advance, cosa