From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id B3ADB3858006 for ; Tue, 1 Nov 2022 12:22:49 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org B3ADB3858006 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1667305369; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=mrbuDo4Da7FWTEUrLpUc6J7tJfxcBJki5FgrmTv+lqA=; b=fB68BhulUjd7oh1axdpP89uALLtoLtMUc13PMHWwV00qhE6TWXgnF9Zi2uKk9/ar5SAHl0 fmnFMHSF6AY99b4LV/Uwc0hIy9bx6qf8ZUTSrFT6n3I3xQCjDRiVkO6YquK0Rk677VBnAP p9qUrL/Xz+IvvykK9GptycO5ZM3kjuo= Received: from mail-ej1-f72.google.com (mail-ej1-f72.google.com [209.85.218.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-610-r2I3wUh9PnqQze6s86_oxA-1; Tue, 01 Nov 2022 08:22:48 -0400 X-MC-Unique: r2I3wUh9PnqQze6s86_oxA-1 Received: by mail-ej1-f72.google.com with SMTP id he6-20020a1709073d8600b0078e20190301so7846600ejc.22 for ; Tue, 01 Nov 2022 05:22:48 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=mrbuDo4Da7FWTEUrLpUc6J7tJfxcBJki5FgrmTv+lqA=; b=4/yS7iEVRWJxsBgaroFsIGbIOJ1d23KK/zReiC6KKJfE9zyEZ1yYprmPOo94VCq33q 2aW7iXIfjhmJOejmnMnP9qT8daTGvLsDrVywXpi2gShu3EVB9Pl85vj4cFdc19EJRJcn R3S8C4oYPCz21cCy5UGgVN7BUi7EhrGeZS5+gM82U4fdAJdhEhGDhZJYw1DvJAF2OQUz E1udHEosf5iSjy+CezgEGJ/SJ05I0zBsGEURyp+CjEitUcFKIBiOVCzd9bx81BJ0Pzk/ zLBhWYOemp+9Uq8HtUCyU+WFSvMdj58DL8dH++My/MTXYaYoaCACfMyU7IwKxan/KHkx cYzg== X-Gm-Message-State: ACrzQf2QGNVsyLXdpsQfEV2ngGzitxf33HRBPjo+ONUB3JCiUGzg7Kx7 Hl9es/TF5mVQ6zsEi3fFAQQViXCilmnFIKd7Pl2xP9JouM97HtHYTQO7NhUvGr/BIRyCZXGUJ1h cidt2aP2w85+zKKnN4KozcsJcl+FQhOM= X-Received: by 2002:a05:6402:50d4:b0:461:e349:56b2 with SMTP id h20-20020a05640250d400b00461e34956b2mr19190479edb.17.1667305367445; Tue, 01 Nov 2022 05:22:47 -0700 (PDT) X-Google-Smtp-Source: AMsMyM7mzL7wUnEPcOFaWTALZnjxNCoayXEcndCi1E7k2AG8LB0tynf02/c11+XcOv2itMPYxlt5bCAgWC9J/gwpv/E= X-Received: by 2002:a05:6402:50d4:b0:461:e349:56b2 with SMTP id h20-20020a05640250d400b00461e34956b2mr19190460edb.17.1667305367237; Tue, 01 Nov 2022 05:22:47 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Jonathan Wakely Date: Tue, 1 Nov 2022 12:22:36 +0000 Message-ID: Subject: Re: [PATCH] libstdc++: std::to_chars std::{,b}float16_t support To: Jakub Jelinek Cc: Patrick Palka , gcc-patches@gcc.gnu.org, libstdc++@gcc.gnu.org X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,KAM_SHORT,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On Thu, 27 Oct 2022 at 09:00, Jakub Jelinek wrote: > > Hi! > > The following patch on top of > https://gcc.gnu.org/pipermail/libstdc++/2022-October/054849.html > adds std::{,b}float16_t support for std::to_chars. > When precision is specified (or for std::bfloat16_t for hex mode even if not), > I believe we can just use the std::to_chars float (when float is mode > compatible with std::float32_t) overloads, both formats are proper subsets > of std::float32_t. > Unfortunately when precision is not specified and we are supposed to emit > shortest string, the std::{,b}float16_t strings are usually much shorter. > E.g. 1.e7p-14f16 shortest fixed representation is > 0.0001161 and shortest scientific representation is > 1.161e-04 while 1.e7p-14f32 (same number promoted to std::float32_t) > 0.00011610985 and > 1.1610985e-04. > Similarly for 1.38p-112bf16, > 0.000000000000000000000000000000000235 > 2.35e-34 vs. 1.38p-112f32 > 0.00000000000000000000000000000000023472271 > 2.3472271e-34 > For std::float16_t there are differences even in the shortest hex, say: > 0.01p-14 vs. 1p-22 > but only for denormal std::float16_t values (where all std::float16_t > denormals converted to std::float32_t are normal), __FLT16_MIN__ and > everything larger in absolute value than that is the same. Unless > that is a bug and we should try to discover shorter representations > even for denormals... > std::bfloat16_t has the same exponent range as std::float32_t, so all > std::bfloat16_t denormals are also std::float32_t denormals and thus > the shortest hex representations are the same. > > As documented, ryu can handle arbitrary IEEE like floating point formats > (probably not wider than IEEE quad) using the generic_128 handling, but > ryu is hidden in libstdc++.so. As only few architectures support > std::float16_t right now and some of them have special ISA requirements > for those (e.g. on i?86 one needs -msse2) and std::bfloat16_t is right > now supported only on x86 (again with -msse2), perhaps with aarch64/arm > coming next if ARM is interested, but I think it is possible that more > will be added later, instead of exporting APIs from the library to handle > directly the std::{,b}float16_t overloads this patch instead exports > functions which take a float which is a superset of those and expects > the inline overloads to promote the 16-bit formats to 32-bit, then inside > of the library it ensures they are printed right. > With the added [[gnu::cold]] attribute because I think most users > will primarily use these formats as storage formats and perform arithmetics > in the excess precision for them and print also as std::float32_t the > added support doesn't seem to be too large, on x86_64: > readelf -Ws libstdc++.so.6.0.31 | grep float16_t > 912: 00000000000ae824 950 FUNC GLOBAL DEFAULT 13 _ZSt21__to_chars_bfloat16_tPcS_fSt12chars_format@@GLIBCXX_3.4.31 > 5767: 00000000000ae4a1 899 FUNC GLOBAL DEFAULT 13 _ZSt20__to_chars_float16_tPcS_fSt12chars_format@@GLIBCXX_3.4.31 > 842: 000000000016d430 106 FUNC LOCAL DEFAULT 13 _ZN12_GLOBAL__N_113get_ieee_reprINS_23floating_type_float16_tEEENS_6ieee_tIT_EES3_ > 865: 0000000000170980 1613 FUNC LOCAL DEFAULT 13 _ZSt23__floating_to_chars_hexIN12_GLOBAL__N_123floating_type_float16_tEESt15to_chars_resultPcS3_T_St8optionalIiE.constprop.0.isra.0 > 7205: 00000000000ae824 950 FUNC GLOBAL DEFAULT 13 _ZSt21__to_chars_bfloat16_tPcS_fSt12chars_format > 7985: 00000000000ae4a1 899 FUNC GLOBAL DEFAULT 13 _ZSt20__to_chars_float16_tPcS_fSt12chars_format > so 3568 code bytes together or so. > > Tested with the attached test (which doesn't prove the shortest > representation, just prints std::{,b}float16_t and std::float32_t > shortest strings side by side, then tries to verify it can be > emitted even into the exact sized range and can't be into range > one smaller than that and tries to read what is printed > back using from_chars float32_t overload (so there could be > double rounding, but apparently there is none for the shortest strings). > The only differences printed are for NaNs, where sNaNs are canonicalized > to canonical qNaNs and as to_chars doesn't print NaN mantissa, even qNaNs > other than the canonical one are read back just as the canonical NaN. > > Also attaching what Patrick wrote to generate the pow10_adjustment_tab, > for std::float16_t only 1.0, 10.0, 100.0, 1000.0 and 10000.0 are powers > of 10 in the range because __FLT16_MAX__ is 65504.0, and all of the above > are exactly representable in std::float16_t, so we want to use 0 in > pow10_adjustment_tab. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > Unless I misunderstood something in Patrick's review, this is good and can be incrementally improved. OK for trunk, thanks.