Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #394650 > unrolled thread

_BitInt(N)

Started byThiago Adams <thiago.adams@gmail.com>
First post2025-10-22 09:45 -0300
Last post2025-11-24 11:52 -0600
Articles 20 on this page of 248 — 14 participants

Back to article view | Back to comp.lang.c


Contents

  _BitInt(N) Thiago Adams <thiago.adams@gmail.com> - 2025-10-22 09:45 -0300
    Re: _BitInt(N) BGB <cr88192@gmail.com> - 2025-10-22 11:42 -0500
      Re: _BitInt(N) Thiago Adams <thiago.adams@gmail.com> - 2025-10-22 14:23 -0300
        Re: _BitInt(N) Thiago Adams <thiago.adams@gmail.com> - 2025-10-22 14:25 -0300
          Re: _BitInt(N) BGB <cr88192@gmail.com> - 2025-10-22 14:03 -0500
    Re: _BitInt(N) Philipp Klaus Krause <pkk@spth.de> - 2025-11-23 12:46 +0100
      Re: _BitInt(N) antispam@fricas.org (Waldek Hebisch) - 2025-11-23 13:32 +0000
        Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-23 13:59 +0000
          Re: _BitInt(N) Michael S <already5chosen@yahoo.com> - 2025-11-23 17:06 +0200
            Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-24 10:29 +0100
              Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-24 11:17 +0000
                Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-11-24 05:12 -0800
                Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-24 14:49 +0100
                  Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-11-24 17:23 -0800
                    Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-25 07:56 +0100
                  Re: _BitInt(N) antispam@fricas.org (Waldek Hebisch) - 2025-11-29 19:36 +0000
                    Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-30 11:56 +0100
                      Re: _BitInt(N) antispam@fricas.org (Waldek Hebisch) - 2025-11-30 15:50 +0000
              Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-11-24 05:06 -0800
                Re: _BitInt(N) Michael S <already5chosen@yahoo.com> - 2025-11-24 15:27 +0200
                Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-24 14:51 +0100
            Re: _BitInt(N) Philipp Klaus Krause <pkk@spth.de> - 2025-11-29 22:06 +0100
              Re: _BitInt(N) BGB <cr88192@gmail.com> - 2025-11-29 17:10 -0600
              Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-11-29 17:32 -0800
                Re: _BitInt(N) Michael S <already5chosen@yahoo.com> - 2025-11-30 11:46 +0200
                Re: _BitInt(N) Philipp Klaus Krause <pkk@spth.de> - 2025-11-30 11:12 +0100
                Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-30 12:07 +0100
          Re: _BitInt(N) antispam@fricas.org (Waldek Hebisch) - 2025-11-23 17:55 +0000
          Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-11-23 14:38 -0800
            Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-24 00:30 +0000
              Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-24 12:17 +0100
                Re: _BitInt(N) Michael S <already5chosen@yahoo.com> - 2025-11-24 13:44 +0200
                  Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-24 15:02 +0100
                Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-24 12:31 +0000
                  Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-11-24 05:33 -0800
                    Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-24 14:41 +0000
                      Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-11-24 16:46 -0800
                  Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-24 15:41 +0100
                    Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-24 18:35 +0000
                      Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-24 21:26 +0100
                        Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-24 22:27 +0000
                          Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-11-24 18:10 -0800
                          Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-25 21:25 +0100
                            Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-25 21:58 +0000
                              Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-11-25 15:20 -0800
                                Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-26 02:08 +0000
                                  Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-11-25 19:06 -0800
                                    Re: _BitInt(N) Michael S <already5chosen@yahoo.com> - 2025-11-26 11:52 +0200
                                  Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-26 13:15 +0100
                                    Re: _BitInt(N) Michael S <already5chosen@yahoo.com> - 2025-11-26 15:08 +0200
                                Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-11-25 19:21 -0800
                                  Re: _BitInt(N) Philipp Klaus Krause <pkk@spth.de> - 2025-11-29 22:40 +0100
                                    Re: _BitInt(N) James Kuyper <jameskuyper@alumni.caltech.edu> - 2025-11-29 22:04 -0500
                              Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-26 08:55 +0100
                                Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-26 12:05 +0000
                                  Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-26 15:49 +0100
                                    Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-26 15:44 +0000
                                      Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-26 17:37 +0100
                                        Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-26 18:42 +0000
                                          Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-26 21:43 +0100
                                            Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-26 22:19 +0000
                                              Re: _BitInt(N) antispam@fricas.org (Waldek Hebisch) - 2025-11-27 02:32 +0000
                                                Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-27 12:46 +0000
                                                  Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-27 14:39 +0100
                                              Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-27 11:43 +0100
                                                Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-27 12:20 +0000
                                                  Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-27 14:02 +0100
                                                    Re: _BitInt(N) Michael S <already5chosen@yahoo.com> - 2025-11-27 16:02 +0200
                                                      Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-27 21:15 +0100
                                                        Re: _BitInt(N) Michael S <already5chosen@yahoo.com> - 2025-11-28 00:15 +0200
                                                          Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-28 09:46 +0100
                                                            Re: _BitInt(N) Michael S <already5chosen@yahoo.com> - 2025-11-28 13:12 +0200
                                                              Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-28 12:45 +0100
                                                                Re: _BitInt(N) Michael S <already5chosen@yahoo.com> - 2025-11-28 15:33 +0200
                                                                  Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-28 15:47 +0100
                                                                    Re: _BitInt(N) Michael S <already5chosen@yahoo.com> - 2025-11-29 19:23 +0200
                                                              Re: _BitInt(N) antispam@fricas.org (Waldek Hebisch) - 2025-11-29 00:20 +0000
                                                                Re: _BitInt(N) Michael S <already5chosen@yahoo.com> - 2025-11-29 19:30 +0200
                                                        Re: _BitInt(N) BGB <cr88192@gmail.com> - 2025-11-28 13:09 -0600
                                                          Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-28 22:43 +0000
                                                    Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-27 17:13 +0000
                                                      Re: _BitInt(N) Ike Naar <ike@sdf.org> - 2025-11-27 17:38 +0000
                                                        Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-27 17:59 +0000
                                                          Re: _BitInt(N) Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-11-28 03:33 +0100
                                                            Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-28 11:49 +0000
                                                              Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-28 14:46 +0000
                                                              Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-11-28 15:23 -0800
                                                                Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-29 00:08 +0000
                                                                  Re: _BitInt(N) antispam@fricas.org (Waldek Hebisch) - 2025-11-29 03:12 +0000
                                                                  Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-11-28 19:38 -0800
                                                                    Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-29 11:24 +0000
                                                                      Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-29 14:45 +0100
                                                                        Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-29 14:40 +0000
                                                                          Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-29 17:15 +0100
                                                                  Re: _BitInt(N) James Kuyper <jameskuyper@alumni.caltech.edu> - 2025-11-29 10:27 -0500
                                                                    Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-11-29 16:29 -0800
                                                                      Re: _BitInt(N) James Kuyper <jameskuyper@alumni.caltech.edu> - 2025-11-29 22:08 -0500
                                                                    Re: _BitInt(N) Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-12-20 11:24 -0800
                                                                      Re: _BitInt(N) antispam@fricas.org (Waldek Hebisch) - 2025-12-21 00:18 +0000
                                                                        Re: _BitInt(N) Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-12-21 23:07 -0800
                                                                          Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-12-22 02:51 -0800
                                                                            Re: _BitInt(N) Kaz Kylheku <046-301-5902@kylheku.com> - 2025-12-22 19:23 +0000
                                                                            Re: _BitInt(N) Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-01-07 03:01 -0800
                                                                      Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-12-20 18:22 -0800
                                                                        Re: _BitInt(N) Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-01-06 21:57 -0800
                                                                      Re: _BitInt(N) James Kuyper <jameskuyper@alumni.caltech.edu> - 2025-12-20 21:27 -0500
                                                                        Re: _BitInt(N) Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-01-06 21:51 -0800
                                                                      Re: _BitInt(N) Kaz Kylheku <046-301-5902@kylheku.com> - 2025-12-21 02:27 +0000
                                                                        Re: _BitInt(N) Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-12-21 22:48 -0800
                                                              Re: _BitInt(N) Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-11-29 03:26 +0100
                                                                Re: _BitInt(N) Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-11-29 03:32 +0100
                                                                  Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-29 12:24 +0000
                                                        Re: _BitInt(N) James Kuyper <jameskuyper@alumni.caltech.edu> - 2025-11-28 09:48 -0500
                                                      Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-28 11:41 +0100
                                                        Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-28 19:46 +0000
                                                          Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-28 21:58 +0100
                                                  Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-11-27 15:59 -0800
                                                    Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-28 00:11 +0000
                                                      Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-11-27 16:39 -0800
                                                        Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-28 01:49 +0000
                                                          Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-11-27 19:36 -0800
                                                            Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-12-04 17:58 -0800
                                                        [meta] Newsreader and formatting (was Re: _BitInt(N)) Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-11-28 02:56 +0100
                                            Re: _BitInt(N) Michael S <already5chosen@yahoo.com> - 2025-12-01 14:59 +0200
                                              Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-12-01 14:18 +0100
                                          Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-12-01 12:06 -0800
                                            Re: _BitInt(N) Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-12-01 23:59 +0100
                                              Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-12-02 08:31 +0100
                                                Re: _BitInt(N) Philipp Klaus Krause <pkk@spth.de> - 2025-12-02 12:14 +0100
                                                  [OT] Keyboard layout (was Re: _BitInt(N)) Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-12-02 14:01 +0100
                                                  Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-12-02 15:33 -0800
                                                    Re: _BitInt(N) Philipp Klaus Krause <pkk@spth.de> - 2025-12-03 09:23 +0100
                                                    Re: _BitInt(N) Richard Heathfield <rjh@cpax.org.uk> - 2025-12-03 08:29 +0000
                                                      Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-12-03 02:16 -0800
                                                      Re: _BitInt(N) Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-12-15 11:01 -0800
                                                        Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-12-15 14:19 -0800
                                                          Re: _BitInt(N) Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-12-21 22:24 -0800
                                                Re: _BitInt(N) bart <bc@freeuk.com> - 2025-12-02 12:21 +0000
                                                  Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-12-02 13:45 +0100
                                                  Re: _BitInt(N) Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-12-02 14:15 +0100
                                                    Block syntax (was Re: _BitInt(N)) bart <bc@freeuk.com> - 2025-12-02 14:12 +0000
                                                Re: _BitInt(N) Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-12-02 13:53 +0100
                                                  Re: _BitInt(N) Michael S <already5chosen@yahoo.com> - 2025-12-02 19:55 +0200
                                                    Re: _BitInt(N) Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-12-02 19:37 +0100
                                                    Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-12-02 21:07 +0100
                                      Re: _BitInt(N) Ike Naar <ike@sdf.org> - 2025-11-27 08:10 +0000
                                  Re: _BitInt(N) antispam@fricas.org (Waldek Hebisch) - 2025-11-27 01:30 +0000
                                    Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-27 02:18 +0000
                                      Re: _BitInt(N) antispam@fricas.org (Waldek Hebisch) - 2025-11-27 04:12 +0000
                          Re: _BitInt(N) antispam@fricas.org (Waldek Hebisch) - 2025-11-29 20:24 +0000
                            Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-29 22:58 +0000
                              Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-11-29 16:46 -0800
                                Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-30 02:30 +0000
                                  Re: _BitInt(N) Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-11-30 05:31 +0100
                                    Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-30 12:51 +0000
                                      Re: _BitInt(N) Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-11-30 18:17 +0100
                                        Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-30 17:55 +0000
                                          Re: _BitInt(N) antispam@fricas.org (Waldek Hebisch) - 2025-12-01 00:08 +0000
                                            Re: _BitInt(N) bart <bc@freeuk.com> - 2025-12-01 01:14 +0000
                                              Re: _BitInt(N) antispam@fricas.org (Waldek Hebisch) - 2025-12-01 04:10 +0000
                                                Re: _BitInt(N) bart <bc@freeuk.com> - 2025-12-01 14:41 +0000
                                                  Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-12-01 16:24 +0100
                                                    Re: _BitInt(N) bart <bc@freeuk.com> - 2025-12-01 17:19 +0000
                                                      Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-12-01 19:33 +0100
                                                        Re: _BitInt(N) bart <bc@freeuk.com> - 2025-12-01 20:14 +0000
                                                    Re: _BitInt(N) antispam@fricas.org (Waldek Hebisch) - 2025-12-02 01:04 +0000
                                                      Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-12-01 18:21 -0800
                                                  Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-12-01 12:34 -0800
                                                    Re: _BitInt(N) bart <bc@freeuk.com> - 2025-12-01 22:01 +0000
                                                      Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-12-01 15:01 -0800
                                          Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-12-01 11:33 +0100
                                            Re: _BitInt(N) bart <bc@freeuk.com> - 2025-12-01 11:29 +0000
                                              Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-12-01 14:10 +0100
                                            Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-12-01 08:56 -0800
                                              Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-12-01 19:38 +0100
                                                Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-12-01 12:42 -0800
                                                  Re: _BitInt(N) Philipp Klaus Krause <pkk@spth.de> - 2025-12-02 22:17 +0100
                                                    Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-12-03 09:25 +0100
                                                  Re: _BitInt(N) James Kuyper <jameskuyper@alumni.caltech.edu> - 2025-12-03 06:17 -0500
                                                    Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-12-03 10:07 -0800
                                                      Re: _BitInt(N) Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-12-15 08:19 -0800
                                              Re: _BitInt(N) Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-12-15 08:21 -0800
                                      Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-11-30 18:05 -0800
                                  Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-11-29 20:32 -0800
                              Re: _BitInt(N) Michael S <already5chosen@yahoo.com> - 2025-11-30 12:22 +0200
                                Re: _BitInt(N) Philipp Klaus Krause <pkk@spth.de> - 2025-11-30 11:41 +0100
                                  Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-30 12:28 +0100
                                    Re: _BitInt(N) Philipp Klaus Krause <pkk@spth.de> - 2025-11-30 13:35 +0100
                                      Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-30 15:14 +0100
                                Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-30 12:09 +0000
                      Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-11-24 18:03 -0800
                        Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-25 11:38 +0000
                          Re: _BitInt(N) Michael S <already5chosen@yahoo.com> - 2025-11-25 14:12 +0200
                            Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-25 14:57 +0000
                              Re: _BitInt(N) Michael S <already5chosen@yahoo.com> - 2025-11-25 18:29 +0200
                                Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-25 18:33 +0000
                                  Re: _BitInt(N) Michael S <already5chosen@yahoo.com> - 2025-11-26 11:12 +0200
                                    Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-26 12:45 +0000
                                      Re: _BitInt(N) Michael S <already5chosen@yahoo.com> - 2025-11-26 15:31 +0200
                                  Re: _BitInt(N) Michael S <already5chosen@yahoo.com> - 2025-11-26 11:29 +0200
                                    Re: _BitInt(N) James Kuyper <jameskuyper@alumni.caltech.edu> - 2025-11-26 21:19 -0500
                                      Re: _BitInt(N) Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-12-15 08:29 -0800
                            Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-25 21:54 +0100
                              Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-11-25 13:42 -0800
                                Re: _BitInt(N) Michael S <already5chosen@yahoo.com> - 2025-11-26 12:01 +0200
                                  Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-26 15:08 +0100
                                Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-26 13:24 +0100
                            Re: _BitInt(N) Michael S <already5chosen@yahoo.com> - 2025-11-25 23:11 +0200
                          Re: _BitInt(N) BGB <cr88192@gmail.com> - 2025-11-26 17:04 -0600
                            Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-27 01:05 +0000
                        Re: _BitInt(N) antispam@fricas.org (Waldek Hebisch) - 2025-11-27 02:54 +0000
                  Re: _BitInt(N) Philipp Klaus Krause <pkk@spth.de> - 2025-11-29 22:17 +0100
                    Re: _BitInt(N) antispam@fricas.org (Waldek Hebisch) - 2025-11-29 22:41 +0000
                      Re: _BitInt(N) Philipp Klaus Krause <pkk@spth.de> - 2025-11-30 00:17 +0100
                        Re: _BitInt(N) antispam@fricas.org (Waldek Hebisch) - 2025-11-30 01:22 +0000
                          Re: _BitInt(N) Philipp Klaus Krause <pkk@spth.de> - 2025-11-30 11:00 +0100
                        Re: _BitInt(N) Michael S <already5chosen@yahoo.com> - 2025-11-30 11:05 +0200
                          Re: _BitInt(N) Philipp Klaus Krause <pkk@spth.de> - 2025-11-30 10:51 +0100
                            Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-30 13:10 +0000
                              Re: _BitInt(N) Philipp Klaus Krause <pkk@spth.de> - 2025-11-30 15:26 +0100
                                Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-30 15:09 +0000
                                  Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-30 17:26 +0100
                          Re: _BitInt(N) antispam@fricas.org (Waldek Hebisch) - 2025-11-30 21:53 +0000
                          Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-11-30 17:32 -0800
                            Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-12-01 08:36 +0100
                              Re: _BitInt(N) bart <bc@freeuk.com> - 2025-12-01 11:37 +0000
                                Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-12-01 14:37 +0100
                                  Re: _BitInt(N) bart <bc@freeuk.com> - 2025-12-01 14:14 +0000
                                    Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-12-01 16:28 +0100
                      Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-30 12:39 +0100
              Re: _BitInt(N) Michael S <already5chosen@yahoo.com> - 2025-11-24 14:10 +0200
              Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-11-24 04:29 -0800
          Re: _BitInt(N) BGB <cr88192@gmail.com> - 2025-11-23 21:39 -0600
            Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-24 11:45 +0000
              Re: _BitInt(N) Michael S <already5chosen@yahoo.com> - 2025-11-24 13:57 +0200
                Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-24 12:56 +0000
                  Re: _BitInt(N) Michael S <already5chosen@yahoo.com> - 2025-11-24 15:17 +0200
                    Re: _BitInt(N) David Brown <david.brown@hesbynett.no> - 2025-11-24 15:59 +0100
              Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-11-24 05:35 -0800
                Re: _BitInt(N) bart <bc@freeuk.com> - 2025-11-24 14:21 +0000
                  Re: _BitInt(N) BGB <cr88192@gmail.com> - 2025-11-24 13:12 -0600
                    Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-11-24 17:00 -0800
                      Re: _BitInt(N) BGB <cr88192@gmail.com> - 2025-11-24 20:10 -0600
                  Re: _BitInt(N) Philipp Klaus Krause <pkk@spth.de> - 2025-11-29 22:30 +0100
                    Re: _BitInt(N) antispam@fricas.org (Waldek Hebisch) - 2025-11-30 01:51 +0000
                      Re: _BitInt(N) Michael S <already5chosen@yahoo.com> - 2025-11-30 11:22 +0200
            Re: _BitInt(N) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-11-24 04:37 -0800
              Re: _BitInt(N) BGB <cr88192@gmail.com> - 2025-11-24 11:52 -0600

Page 4 of 13 — ← Prev page 1 2 3 [4] 5 6 … 13  Next page →


#395507

Frombart <bc@freeuk.com>
Date2025-11-26 22:19 +0000
Message-ID<10g7ue4$r47b$1@dont-email.me>
In reply to#395506
On 26/11/2025 20:43, David Brown wrote:
> On 26/11/2025 19:42, bart wrote:
>> On 26/11/2025 16:37, David Brown wrote:
>>> On 26/11/2025 16:44, bart wrote:
>>
>>> The "other people" I referred to are the folks behind the C language, 
>>> not me.
>>
>> OK. The people who chose to make 'break' do two jobs, unfortunately in 
>> parts of the language that can overlap in use; those people! (I guess 
>> you mean the more recent lot.)
>>
>>>> In C, the solution for my example might look like this:
>>>>
>>>>      double temp = x+y;
>>>>      printf("%llu", ((*(uint64_t*)&temp)>>52) & 2047);
>>>>
>>>
>>> No, that's not how a C solution would work.  People who know C would 
>>> know that.  As a challenge for you, see if you can spot your mistake.
>>
>> This was my point. (Although I can't see the problem, making it even 
>> more pertinent.)
>>
> 
> So you can claim to have a "better" solution than C, without knowing how 
> to write it correctly in C?

> 
>>>
>>> (And of course if anyone wanted to do this stuff in real code, they'd 
>>> wrap things in a static inline "bit_range_extract" function.)
>>
>> Also my point: everyone will invent their own incompatible solutions 
>> for this fundamental stuff.
> 
> It is not remotely fundamental.  Extracting groups of bits from the 
> representation of a type, especially a floating point type, is a niche 
> operation.

A bit like that BitInt(12) example then?

This is about a lower-level systems language working with primitive 
machine types, and having access to the underlying bits of those types.

How much more fundamental can you get?

C provides only basic bitwise operators, and you have to do some 
bit-fiddling, while trying to avoid UB, in order to extract or inject 
individual bits or bitfields.

I provide direct indexing ops to get or set any bit or bitfield, which 
is actually a great core feature to have, but for some reason you want 
to downplay it.

You might just admit for once that it is quite neat.


>  (It can be an important operation - such as for software 
> floating point routines.

That particular task can be important for lots of reasons.

>  But the people who write those are few, and 
> they know what they are doing.)

And I don't? I used to write FP emulation routines...


> "Type punning" refers to using a union to access or reinterpret the 
> underlying bit representation.  Using references and a cast to do so is 
> UB,

In C maybe, using your favoured compilers. In my implementations of C, 
and in my languages, it is well defined, especially as it is 
type-punning a 64-bit quantity to another 64-bit quantity.

(This is a great thing about creating your own implementations: you get 
to say what is UB, which will be for genuine, not artificial ones 
maintained so that C compilers can be one-up on each other.

As it is, somebody using C as an intermediate language can have a 
situation where something is well-defined in their source language, 
known to be well-defined on their platforms of interest, but inbetween, 
C says otherwise.)

Note that in the original example in my language, no references are used 
(the code just copies a FP register to a GPR without conversion).

> except when using pointers to character types.  Neither involves 
> actually putting data into memory or the stack unless you are using a 
> compiler that can't optimise well - and then it is just a matter of less 
> efficient generated code.

OK, so how would you do a 'reinterpret' cast in C, of a value like 'x+y'?

>> Anything without braces isn't taken as seriously, eg. scripting 
>> languages.
>>
> 
> What a /very/ strange way to distinguish or classify languages.

It's an observation. Which languages that call themselves 'systems 
languages' these days don't use braces?

>  And 
> what a bizarre way to generalise what people think, as though all 
> programmers share the same opinions.

You're welcome to do your own survey.

[toc] | [prev] | [next] | [standalone]


#395513

Fromantispam@fricas.org (Waldek Hebisch)
Date2025-11-27 02:32 +0000
Message-ID<10g8d76$i159$1@paganini.bofh.team>
In reply to#395507
bart <bc@freeuk.com> wrote:
> 
> This is about a lower-level systems language working with primitive 
> machine types, and having access to the underlying bits of those types.
> 
> How much more fundamental can you get?
> 
> C provides only basic bitwise operators, and you have to do some 
> bit-fiddling, while trying to avoid UB, in order to extract or inject 
> individual bits or bitfields.
> 
> I provide direct indexing ops to get or set any bit or bitfield, which 
> is actually a great core feature to have, but for some reason you want 
> to downplay it.
> 
> You might just admit for once that it is quite neat.

Yes, it is neat.

>>  (It can be an important operation - such as for software 
>> floating point routines.
> 
> That particular task can be important for lots of reasons.
> 
>>  But the people who write those are few, and 
>> they know what they are doing.)
> 
> And I don't? I used to write FP emulation routines...
> 
> 
>> "Type punning" refers to using a union to access or reinterpret the 
>> underlying bit representation.  Using references and a cast to do so is 
>> UB,
> 
> In C maybe, using your favoured compilers. In my implementations of C, 
> and in my languages, it is well defined, especially as it is 
> type-punning a 64-bit quantity to another 64-bit quantity.
> 
<snip>
> 
> OK, so how would you do a 'reinterpret' cast in C, of a value like 'x+y'?
 
#include <stdint.h>
#include <string.h>

uint64_t
d_to_u(double d) {
    uint64_t tmp;
    memcpy(&tmp, &d, sizeof(tmp));
    return tmp;
}

int
f_exp(double d) {
   return (d_to_u(d)>>52)&2047;
}

Using 'gcc -O' I get the following assembly (only code, without
unimportant directives/labels):

d_to_u:
        movq    %xmm0, %rax
        ret

f_exp:
        movq    %xmm0, %rax
        shrq    $52, %rax
        andl    $2047, %eax
        ret

As you can see 'd_to_u' is single computational instruction,
you can not do better given that floating point registers
are distinct from integer registers.  And 'f_exp' looks
optimal assuming lack of "bit extract" or "extract exponent"
instructions.

Note that you can put both functions above in a header file,
so once you have written few lines above you can use them
in all your C code.  Of course, efficientcy depends on
compiler optimization.

-- 
                              Waldek Hebisch

[toc] | [prev] | [next] | [standalone]


#395524

Frombart <bc@freeuk.com>
Date2025-11-27 12:46 +0000
Message-ID<10g9h6a$1crf0$2@dont-email.me>
In reply to#395513
On 27/11/2025 02:32, Waldek Hebisch wrote:
> bart <bc@freeuk.com> wrote:
>>
>> This is about a lower-level systems language working with primitive
>> machine types, and having access to the underlying bits of those types.
>>
>> How much more fundamental can you get?
>>
>> C provides only basic bitwise operators, and you have to do some
>> bit-fiddling, while trying to avoid UB, in order to extract or inject
>> individual bits or bitfields.
>>
>> I provide direct indexing ops to get or set any bit or bitfield, which
>> is actually a great core feature to have, but for some reason you want
>> to downplay it.
>>
>> You might just admit for once that it is quite neat.
> 
> Yes, it is neat.

Hmm, perhaps you're being sincere, perhaps not ...

>> OK, so how would you do a 'reinterpret' cast in C, of a value like 'x+y'?
>   
> #include <stdint.h>
> #include <string.h>
> 
> uint64_t
> d_to_u(double d) {
>      uint64_t tmp;
>      memcpy(&tmp, &d, sizeof(tmp));
>      return tmp;
> }
> 
> int
> f_exp(double d) {
>     return (d_to_u(d)>>52)&2047;
> }
> 
> Using 'gcc -O' I get the following assembly (only code, without
> unimportant directives/labels):
> 
> d_to_u:
>          movq    %xmm0, %rax
>          ret
> 
> f_exp:
>          movq    %xmm0, %rax
>          shrq    $52, %rax
>          andl    $2047, %eax
>          ret
> 
> As you can see 'd_to_u' is single computational instruction,
> you can not do better given that floating point registers
> are distinct from integer registers.  And 'f_exp' looks
> optimal assuming lack of "bit extract" or "extract exponent"
> instructions.
> 
> Note that you can put both functions above in a header file,
> so once you have written few lines above you can use them
> in all your C code.  Of course, efficientcy depends on
> compiler optimization.

Yes (that's something I can't rely on).

These examples are interesting: with a HLL you normally express yourself 
in a clear manner, and it is the compiler's job to generate the 
complicated code required to implement what you mean.

Here it seems to be other way around: it is the programmer who writes 
the convoluted code, and the compiler turns that into short, clear 
instructions! Which unfortunately no one will see.

If I use your functions like this:

     a = f_exp(x + y);

then once the x+y result is in a register, gcc-O2 generates this inline 
code for the extraction:

     movq    rax, xmm0
     shr rax, 52
     and eax, 2047


If I express it in my language:

    a := int@(x + y).[52..62]

then my non-optimising compiler generates this (D0 is rax):

     movq      D0,	XMM4
     shr       D0,	52
     and       D0,	2047

So such features have definite advantages, in being able to express 
intent directly, and to make it easier for a simple compiler to know 
that intent and help it generate reasonable code without lots of 
analysis or needing function inlining.

BTW, your example explicitly writes to memory; David Brown posted a 
version that didn't do so that I could see. Unless a compound literal is 
designed to be built in memory? However that version only seemed to work 
with one compiler.

[toc] | [prev] | [next] | [standalone]


#395526

FromDavid Brown <david.brown@hesbynett.no>
Date2025-11-27 14:39 +0100
Message-ID<10g9kb7$1dpa3$2@dont-email.me>
In reply to#395524
On 27/11/2025 13:46, bart wrote:
> On 27/11/2025 02:32, Waldek Hebisch wrote:
>> bart <bc@freeuk.com> wrote:
>>>
>>> This is about a lower-level systems language working with primitive
>>> machine types, and having access to the underlying bits of those types.
>>>
>>> How much more fundamental can you get?
>>>
>>> C provides only basic bitwise operators, and you have to do some
>>> bit-fiddling, while trying to avoid UB, in order to extract or inject
>>> individual bits or bitfields.
>>>
>>> I provide direct indexing ops to get or set any bit or bitfield, which
>>> is actually a great core feature to have, but for some reason you want
>>> to downplay it.
>>>
>>> You might just admit for once that it is quite neat.
>>
>> Yes, it is neat.
> 
> Hmm, perhaps you're being sincere, perhaps not ...
> 
>>> OK, so how would you do a 'reinterpret' cast in C, of a value like 
>>> 'x+y'?
>> #include <stdint.h>
>> #include <string.h>
>>
>> uint64_t
>> d_to_u(double d) {
>>      uint64_t tmp;
>>      memcpy(&tmp, &d, sizeof(tmp));
>>      return tmp;
>> }
>>
>> int
>> f_exp(double d) {
>>     return (d_to_u(d)>>52)&2047;
>> }
>>
>> Using 'gcc -O' I get the following assembly (only code, without
>> unimportant directives/labels):
>>
>> d_to_u:
>>          movq    %xmm0, %rax
>>          ret
>>
>> f_exp:
>>          movq    %xmm0, %rax
>>          shrq    $52, %rax
>>          andl    $2047, %eax
>>          ret
>>
>> As you can see 'd_to_u' is single computational instruction,
>> you can not do better given that floating point registers
>> are distinct from integer registers.  And 'f_exp' looks
>> optimal assuming lack of "bit extract" or "extract exponent"
>> instructions.
>>
>> Note that you can put both functions above in a header file,
>> so once you have written few lines above you can use them
>> in all your C code.  Of course, efficientcy depends on
>> compiler optimization.
> 
> Yes (that's something I can't rely on).
> 
> These examples are interesting: with a HLL you normally express yourself 
> in a clear manner, and it is the compiler's job to generate the 
> complicated code required to implement what you mean.
> 
> Here it seems to be other way around: it is the programmer who writes 
> the convoluted code, and the compiler turns that into short, clear 
> instructions! Which unfortunately no one will see.
> 

I don't think Waldek's code (or mine) is particularly convoluted.  But 
in either case, you put such things in static inline functions (or 
macros if you need to).  Then you have clear intent when implementing 
those functions - you are clearly doing low-level shifts and masking. 
And you have clear intent when /using/ the functions - you are 
extracting some bits from the underlying representation of the value. 
You split things into identified functions with specific tasks - that's 
at the heart of programming.

And then you let the automated computer system - the compiler - do what 
it does best, and generate efficient results.

> If I use your functions like this:
> 
>      a = f_exp(x + y);
> 
> then once the x+y result is in a register, gcc-O2 generates this inline 
> code for the extraction:
> 
>      movq    rax, xmm0
>      shr rax, 52
>      and eax, 2047
> 
> 
> If I express it in my language:
> 
>     a := int@(x + y).[52..62]
> 
> then my non-optimising compiler generates this (D0 is rax):
> 
>      movq      D0,    XMM4
>      shr       D0,    52
>      and       D0,    2047
> 
> So such features have definite advantages, in being able to express 
> intent directly, and to make it easier for a simple compiler to know 
> that intent and help it generate reasonable code without lots of 
> analysis or needing function inlining.
> 

You seem to be arguing that it is a good thing to write code that 
spoon-feeds the compiler so that the compiler doesn't have to do much 
work.  You get this because you are writing the application code and 
also writing the compiler - so you pick the solution that gives you the 
best results for the least effort overall.  But that is only appropriate 
for people with personal languages like yours.

It should be the other way round - the compiler should be optimising so 
that the programmer can work at higher levels of abstraction or write 
code in the way that is most convenient to them, and the compiler will 
handle the boring low-level details.  Programmers using serious 
languages /can/ rely on the compiler optimising well.


> BTW, your example explicitly writes to memory; David Brown posted a 
> version that didn't do so that I could see. Unless a compound literal is 
> designed to be built in memory? However that version only seemed to work 
> with one compiler.

The version I wrote is C99 and works fine with any C99 compiler.  No, 
compound literals are not "designed to be built in memory", whatever 
that might mean.  A compound literal is a value, and can be used like 
any other value.

Waldek's version does use "memcpy" and pointers formed from the 
addresses of a parameter and a local variable.  That means it must give 
results as if the parameter and local variable were in memory somewhere 
(the stack, in usual practice - though C does not actually require a 
stack) and a memory-to-memory copy was carried out, byte by byte. 
Critical here is the term "as if".  If the compiler can give the same 
results without using memory, it is allowed to do so - thus optimising 
compilers will just do a register transfer from a floating point 
register to a general purpose register in this case.



[toc] | [prev] | [next] | [standalone]


#395522

FromDavid Brown <david.brown@hesbynett.no>
Date2025-11-27 11:43 +0100
Message-ID<10g9a0r$1a895$1@dont-email.me>
In reply to#395507
On 26/11/2025 23:19, bart wrote:
> On 26/11/2025 20:43, David Brown wrote:
>> On 26/11/2025 19:42, bart wrote:
>>> On 26/11/2025 16:37, David Brown wrote:
>>>> On 26/11/2025 16:44, bart wrote:
>>>
>>>> The "other people" I referred to are the folks behind the C 
>>>> language, not me.
>>>
>>> OK. The people who chose to make 'break' do two jobs, unfortunately 
>>> in parts of the language that can overlap in use; those people! (I 
>>> guess you mean the more recent lot.)
>>>
>>>>> In C, the solution for my example might look like this:
>>>>>
>>>>>      double temp = x+y;
>>>>>      printf("%llu", ((*(uint64_t*)&temp)>>52) & 2047);
>>>>>
>>>>
>>>> No, that's not how a C solution would work.  People who know C would 
>>>> know that.  As a challenge for you, see if you can spot your mistake.
>>>
>>> This was my point. (Although I can't see the problem, making it even 
>>> more pertinent.)
>>>
>>
>> So you can claim to have a "better" solution than C, without knowing 
>> how to write it correctly in C?
> 
>>
>>>>
>>>> (And of course if anyone wanted to do this stuff in real code, 
>>>> they'd wrap things in a static inline "bit_range_extract" function.)
>>>
>>> Also my point: everyone will invent their own incompatible solutions 
>>> for this fundamental stuff.
>>
>> It is not remotely fundamental.  Extracting groups of bits from the 
>> representation of a type, especially a floating point type, is a niche 
>> operation.
> 
> A bit like that BitInt(12) example then?

Yes, using BitInt(12) is quite niche.

But when the people behind _BitInt() started thinking about what sizes 
people might want, it quickly became clear that it would be vastly more 
effort to try to define which sizes were useful.  It was much simpler 
and clearer just to support any size (up to an implementation-defined 
limit).  Most particular sizes, other than 8, 16, 32, 64, and perhaps 
128, are going to be niche.  But if one clear feature enables a large 
number of niche uses, that's a good thing.

No one has suggested that _BitInt(12) is in any way a /necessary/ 
feature.  And I certainly don't think a stand-alone proposal to add 
12-bit types to C would have been accepted.  But since it exists, it 
will let me write slightly neater code in some cases - thus I will use 
it when appropriate.

What I don't like about your bit extraction operations is that you have 
an operator syntax for a fairly obscure and rarely used operation.  A 
"bit_range_extract" standard library function would make more sense to 
me, though I think shifting and masking works well enough for the few 
situations where you need it.  A syntax that looks very much like array 
access is not going to be helpful to people looking at the code - for 
general-purpose languages, most programmers will never see or use bit 
ranges.

> 
> This is about a lower-level systems language working with primitive 
> machine types, and having access to the underlying bits of those types.
> 
> How much more fundamental can you get?

It is not fundamental for a low-level systems language.  And this is a C 
group - C is a language covering general application programming as well 
as systems programming.  I can agree that it can be a /useful/ operation 
at times - useful enough to make it worth having a standard library 
function (or macro - or, in your case, a keyword or built-in function). 
But not "fundamental" or useful enough to make it operator based like that.

> 
> C provides only basic bitwise operators, and you have to do some 
> bit-fiddling, while trying to avoid UB, in order to extract or inject 
> individual bits or bitfields.

You make it sound difficult.  It's not.

> 
> I provide direct indexing ops to get or set any bit or bitfield, which 
> is actually a great core feature to have, but for some reason you want 
> to downplay it.
> 
> You might just admit for once that it is quite neat.
> 

I am sure it is very nice on the few occasions when it is useful.

> 
>>   (It can be an important operation - such as for software floating 
>> point routines.
> 
> That particular task can be important for lots of reasons.
> 
>>   But the people who write those are few, and they know what they are 
>> doing.)
> 
> And I don't? I used to write FP emulation routines...
> 

The thing you always seem to forget, is that your languages are written 
for /you/ - no one else.  It doesn't make a difference whether something 
is added /to/ the language or written in code /for/ the language.  You 
think other languages are missing critical features simply because there 
is a thing that /you/ want to do that you added to your own language. 
And you think other languages are overly complex or bloated because they 
have features that you don't want to use.

That attitude is fine for your own personal specific language.  If 
that's how you like to do things, that's fine.  But that's your own 
little isolated world that does not compare to the wider world of other 
people, other programmers, other languages, other tools.

Imagine asking the regulars in this group what features or changes they 
would like C to have in order to make C "perfect" for their uses, 
regardless of everyone else, all existing code, all existing tools.  We 
could all fill pages with ideas.  And if those were all added to C, the 
result would be a language that made C++ look as easy as Logo, while 
being riddled with inconsistencies and contradictions.

> 
>> "Type punning" refers to using a union to access or reinterpret the 
>> underlying bit representation.  Using references and a cast to do so 
>> is UB,
> 
> In C maybe, using your favoured compilers. 

In C, yes.  This is comp.lang.c.

> In my implementations of C, 
> and in my languages, it is well defined, especially as it is 
> type-punning a 64-bit quantity to another 64-bit quantity.
> 

OK.  But not in C.

> (This is a great thing about creating your own implementations: you get 
> to say what is UB, which will be for genuine, not artificial ones 
> maintained so that C compilers can be one-up on each other.

Ah, so the many C compilers I have used over the decades were not 
"genuine", and the many different processors I have used were all 
"artificial".  Okay, that clears things up.

> 
> As it is, somebody using C as an intermediate language can have a 
> situation where something is well-defined in their source language, 
> known to be well-defined on their platforms of interest, but inbetween, 
> C says otherwise.)

You've never really understood how languages are defined, have you? 
With your own languages and tools, you don't have to - there is no need 
for standards, specifications, or anything like that.  You can just make 
up what suits you at the time.  The language is "defined" by what the 
implementation does.  That's been very convenient for you, but it has 
left you with serious misconceptions about how non-personal languages work.

> 
> Note that in the original example in my language, no references are used 
> (the code just copies a FP register to a GPR without conversion).
> 
>> except when using pointers to character types.  Neither involves 
>> actually putting data into memory or the stack unless you are using a 
>> compiler that can't optimise well - and then it is just a matter of 
>> less efficient generated code.
> 
> OK, so how would you do a 'reinterpret' cast in C, of a value like 'x+y'?

As you know, you use a union.  So just to please you, here is your bit 
extraction - written as a one-line function (split over two lines for 
Usenet) because you seem to think that kind of thing is important :

uint64_t get_exponent(double x) {
     return ((union { double d; uint64_t u;}) { x }.u >> 52)
			 & ((1ull << (62 - 52 + 1)) - 1);
}

That compiles (with gcc on x86-64) to :

	movq rax, xmm0
	shr rax, 52
	and eax, 2047
	ret

There's nothing in C that suggests this must be put in memory or do 
anything more than this.

> 
>>> Anything without braces isn't taken as seriously, eg. scripting 
>>> languages.
>>>
>>
>> What a /very/ strange way to distinguish or classify languages.
> 
> It's an observation. Which languages that call themselves 'systems 
> languages' these days don't use braces?
> 

Ada?  Forth?

It is certainly common for languages to use braces, simply because they 
are a simple and unambiguous way to delimit blocks.  They are widely 
used in languages that might be called "systems languages", and widely 
used in languages that might /not/ be called "systems languages" - 
though I don't think there is any remotely clear definition or 
distinction between "systems languages" and other languages.

>>   And what a bizarre way to generalise what people think, as though 
>> all programmers share the same opinions.
> 
> You're welcome to do your own survey.
> 

In what way are languages like Ada, Fortran, Python, Haskell, Erlang, 
etc., "not taken seriously" ?  /Who/ does not take them seriously?  Who 
takes "B" seriously but not Ruby, just because "B" uses braces and Ruby 
does not?

<https://en.wikipedia.org/wiki/Comparison_of_programming_languages_(syntax)#Block_delimitation>

[toc] | [prev] | [next] | [standalone]


#395523

Frombart <bc@freeuk.com>
Date2025-11-27 12:20 +0000
Message-ID<10g9fmh$1crf0$1@dont-email.me>
In reply to#395522
On 27/11/2025 10:43, David Brown wrote:
> On 26/11/2025 23:19, bart wrote:


> What I don't like about your bit extraction operations is that you have 
> an operator syntax for a fairly obscure and rarely used operation.

So shift and masking operations in C are obscure?!

   A
> "bit_range_extract" standard library function would make more sense to 
> me, though I think shifting and masking works well enough for the few 
> situations where you need it.  A syntax that looks very much like array 
> access is not going to be helpful to people looking at the code - for 
> general-purpose languages, most programmers will never see or use bit 
> ranges.

The syntax actually comes from DEC Algol60 IIRC. It was used to access 
individual characters of a string, normally an indivisible type in that 
language, and I applied the same concept to bits of an integer.

>> How much more fundamental can you get?
> 
> It is not fundamental for a low-level systems language.

So bits are not fundamental either! But then, it has taken until C23 to 
standardise binary literals, and there is still no format code for 
binary output.

>>>   But the people who write those are few, and they know what they are 
>>> doing.)
>>
>> And I don't? I used to write FP emulation routines...
>>
> 
> The thing you always seem to forget, is that your languages are written 
> for /you/ - no one else.  It doesn't make a difference whether something 
> is added /to/ the language or written in code /for/ the language.  You 
> think other languages are missing critical features simply because there 
> is a thing that /you/ want to do that you added to your own language. 
> And you think other languages are overly complex or bloated because they 
> have features that you don't want to use.

They frequently have advanced features while ignoring the basics.

> Imagine asking the regulars in this group what features or changes they 
> would like C to have in order to make C "perfect" for their uses, 
> regardless of everyone else, all existing code, all existing tools.  We 
> could all fill pages with ideas.  And if those were all added to C, the 
> result would be a language that made C++ look as easy as Logo, while 
> being riddled with inconsistencies and contradictions.

Yes, that's the trick. That's why a lot of features I've played with 
have disappeared, while some have proved indispensable.

>> As it is, somebody using C as an intermediate language can have a 
>> situation where something is well-defined in their source language, 
>> known to be well-defined on their platforms of interest, but 
>> inbetween, C says otherwise.)
> 
> You've never really understood how languages are defined, have you? With 
> your own languages and tools, you don't have to - there is no need for 
> standards, specifications, or anything like that.  You can just make up 
> what suits you at the time.  The language is "defined" by what the 
> implementation does.  That's been very convenient for you, but it has 
> left you with serious misconceptions about how non-personal languages work.

Here's a  program in a very simple language, where all variables have 
i64 type:

   c = a + b

Here, the author has decreed that any overflow in this addition will 
wrap (any overflow bits above 64 are lost). If directly compiled to x64 
code it might use this (here 'a b c' are aliases for the registers where 
they reside):

     mov c, a
     add c, b

Or on ARM64:

     add c, a, b

Now, the author decides to use intermediate C (for portability, for 
optimisations etc), and will generate perhaps:

     int64_t a, b, c;
     ...
     c = a + b;

But here, if a + b happens to overflow, it is UB, and for no good 
reason. You have to fix it. This is where it can be harder to generate 
HLL code than assembly!

*Now* do you understand? This is nothing to do with me or my personal 
languages, it is a problem for every language that transpiles to C, 
where there is a mismatch between the sets of behaviour considered UB in 
each.

>> OK, so how would you do a 'reinterpret' cast in C, of a value like 'x+y'?
> 
> As you know, you use a union.  So just to please you, here is your bit 
> extraction - written as a one-line function (split over two lines for 
> Usenet) because you seem to think that kind of thing is important :
> 
> uint64_t get_exponent(double x) {
>      return ((union { double d; uint64_t u;}) { x }.u >> 52)
>               & ((1ull << (62 - 52 + 1)) - 1);
> }
> 
> That compiles (with gcc on x86-64) to :
> 
>      movq rax, xmm0
>      shr rax, 52
>      and eax, 2047
>      ret
> 
> There's nothing in C that suggests this must be put in memory or do 
> anything more than this.

(This only seems to work with gcc. Clang and MSVS don't like it.)

[toc] | [prev] | [next] | [standalone]


#395525

FromDavid Brown <david.brown@hesbynett.no>
Date2025-11-27 14:02 +0100
Message-ID<10g9i5e$1dpa3$1@dont-email.me>
In reply to#395523
On 27/11/2025 13:20, bart wrote:
> On 27/11/2025 10:43, David Brown wrote:
>> On 26/11/2025 23:19, bart wrote:
> 
> 
>> What I don't like about your bit extraction operations is that you 
>> have an operator syntax for a fairly obscure and rarely used operation.
> 
> So shift and masking operations in C are obscure?!

Both shift operators and bitwise operators have lots of other uses.

When you are designing a programming language, you first provide general 
features that can be used for multiple purposes.  You only implement 
specialised features if the need arises - it is too cumbersome, or 
error-prone, or inefficient, or laborious to use the general features.

In some areas of C usage, shifts and masks - and bitfield extraction - 
turn up quite a bit.  But it seems the C operators work fine for the 
task.  It would not exactly be difficult to add a standard 
"bit_range_extract" function to the C standard library, yet no one has 
felt it to be worth the effort over the last 50 years.  Perhaps it is 
not as essential or fundamental as you think?  Or perhaps C's current 
features do the job well enough that there's no need for anything else?

> 
>    A
>> "bit_range_extract" standard library function would make more sense to 
>> me, though I think shifting and masking works well enough for the few 
>> situations where you need it.  A syntax that looks very much like 
>> array access is not going to be helpful to people looking at the code 
>> - for general-purpose languages, most programmers will never see or 
>> use bit ranges.
> 
> The syntax actually comes from DEC Algol60 IIRC. It was used to access 
> individual characters of a string, normally an indivisible type in that 
> language, and I applied the same concept to bits of an integer.

I don't care if you found the syntax on the back of a cornflakes packet. 
  The origin is not relevant.

> 
>>> How much more fundamental can you get?
>>
>> It is not fundamental for a low-level systems language.
> 
> So bits are not fundamental either! But then, it has taken until C23 to 
> standardise binary literals, and there is still no format code for 
> binary output.
> 

Very few programmers are at all interested in bits.  A "double" holds a 
floating point value, not a pattern of bits.  You are thinking on a 
level of abstraction that is not realistic for most programming tasks.

>>>>   But the people who write those are few, and they know what they 
>>>> are doing.)
>>>
>>> And I don't? I used to write FP emulation routines...
>>>
>>
>> The thing you always seem to forget, is that your languages are 
>> written for /you/ - no one else.  It doesn't make a difference whether 
>> something is added /to/ the language or written in code /for/ the 
>> language.  You think other languages are missing critical features 
>> simply because there is a thing that /you/ want to do that you added 
>> to your own language. And you think other languages are overly complex 
>> or bloated because they have features that you don't want to use.
> 
> They frequently have advanced features while ignoring the basics.

No - they frequently have features that /you/ call "advanced" because 
you don't need or want them, and they ignore things that /you/ call 
"basics" because you /do/ need or want them.  It's all about /you/.

> 
>> Imagine asking the regulars in this group what features or changes 
>> they would like C to have in order to make C "perfect" for their uses, 
>> regardless of everyone else, all existing code, all existing tools.  
>> We could all fill pages with ideas.  And if those were all added to C, 
>> the result would be a language that made C++ look as easy as Logo, 
>> while being riddled with inconsistencies and contradictions.
> 
> Yes, that's the trick. That's why a lot of features I've played with 
> have disappeared, while some have proved indispensable.
> 
>>> As it is, somebody using C as an intermediate language can have a 
>>> situation where something is well-defined in their source language, 
>>> known to be well-defined on their platforms of interest, but 
>>> inbetween, C says otherwise.)
>>
>> You've never really understood how languages are defined, have you? 
>> With your own languages and tools, you don't have to - there is no 
>> need for standards, specifications, or anything like that.  You can 
>> just make up what suits you at the time.  The language is "defined" by 
>> what the implementation does.  That's been very convenient for you, 
>> but it has left you with serious misconceptions about how non-personal 
>> languages work.
> 
> Here's a  program in a very simple language, where all variables have 
> i64 type:
> 
>    c = a + b
> 
> Here, the author has decreed that any overflow in this addition will 
> wrap (any overflow bits above 64 are lost). If directly compiled to x64 
> code it might use this (here 'a b c' are aliases for the registers where 
> they reside):
> 
>      mov c, a
>      add c, b
> 
> Or on ARM64:
> 
>      add c, a, b
> 
> Now, the author decides to use intermediate C (for portability, for 
> optimisations etc), and will generate perhaps:
> 
>      int64_t a, b, c;
>      ...
>      c = a + b;
> 
> But here, if a + b happens to overflow, it is UB, and for no good 
> reason. You have to fix it. This is where it can be harder to generate 
> HLL code than assembly!
> 

You are talking nonsense.

Either a + b results in the correct answer, or it does not.  Any sane 
person reads that as "a plus b" - mathematically adding two integers to 
get their sum.  That's what the programmer wants, and that's what they 
ask for.  And any sane programmer expects the language to give the 
correct result within its limitations, but doe not expect it to do 
magic.  Expecting to form a sum that is greater than 2 ^ 63 and somehow 
produce the "correct" result is a total misunderstanding of mathematics 
and programming - any primary school kid will tell you that using the 
fingers of one hand, you can't add 3 and 4.  They will /not/ tell you 
that it's fine to add them on one hand because 3 + 4 is actually equal to 2.

> *Now* do you understand? This is nothing to do with me or my personal 
> languages, it is a problem for every language that transpiles to C, 
> where there is a mismatch between the sets of behaviour considered UB in 
> each.

I understand that simple maths and common sense is beyond you.  I 
understand that you think mathematics should be defined in terms of 
accidental byproducts of the way hardware logic designs happen to be 
implemented.

> 
>>> OK, so how would you do a 'reinterpret' cast in C, of a value like 
>>> 'x+y'?
>>
>> As you know, you use a union.  So just to please you, here is your bit 
>> extraction - written as a one-line function (split over two lines for 
>> Usenet) because you seem to think that kind of thing is important :
>>
>> uint64_t get_exponent(double x) {
>>      return ((union { double d; uint64_t u;}) { x }.u >> 52)
>>               & ((1ull << (62 - 52 + 1)) - 1);
>> }
>>
>> That compiles (with gcc on x86-64) to :
>>
>>      movq rax, xmm0
>>      shr rax, 52
>>      and eax, 2047
>>      ret
>>
>> There's nothing in C that suggests this must be put in memory or do 
>> anything more than this.
> 
> (This only seems to work with gcc. Clang and MSVS don't like it.)
> 

I think you are mistaken.  clang is fine with it.  It is standard C99, 
so any decent C compiler from the last 25 years will handle it fine.  MS 
gave up on bothering to make C compilers before the turn of the century 
(they make a reasonable enough C++ compiler).  Even your hero tcc is 
fine with it (though on my attempts, it produces rubbish code - maybe it 
needs different flags for optimisation).  The C code is not made invalid 
by the existence of C90-only compilers.



[toc] | [prev] | [next] | [standalone]


#395527

FromMichael S <already5chosen@yahoo.com>
Date2025-11-27 16:02 +0200
Message-ID<20251127160223.0000141e@yahoo.com>
In reply to#395525
On Thu, 27 Nov 2025 14:02:38 +0100
David Brown <david.brown@hesbynett.no> wrote:

> On 27/11/2025 13:20, bart wrote:
> > On 27/11/2025 10:43, David Brown wrote:  
> >> On 26/11/2025 23:19, bart wrote:  
> > 
> >   
> >> What I don't like about your bit extraction operations is that you 
> >> have an operator syntax for a fairly obscure and rarely used
> >> operation.  
> > 
> > So shift and masking operations in C are obscure?!  
> 
> Both shift operators and bitwise operators have lots of other uses.
> 
> When you are designing a programming language, you first provide
> general features that can be used for multiple purposes.  You only
> implement specialised features if the need arises - it is too
> cumbersome, or error-prone, or inefficient, or laborious to use the
> general features.
> 
> In some areas of C usage, shifts and masks - and bitfield extraction
> - turn up quite a bit.  But it seems the C operators work fine for
> the task.  It would not exactly be difficult to add a standard 
> "bit_range_extract" function to the C standard library, yet no one
> has felt it to be worth the effort over the last 50 years.  Perhaps
> it is not as essential or fundamental as you think?  Or perhaps C's
> current features do the job well enough that there's no need for
> anything else?
> 
> > 
> >    A  
> >> "bit_range_extract" standard library function would make more
> >> sense to me, though I think shifting and masking works well enough
> >> for the few situations where you need it.  A syntax that looks
> >> very much like array access is not going to be helpful to people
> >> looking at the code 
> >> - for general-purpose languages, most programmers will never see
> >> or use bit ranges.  
> > 
> > The syntax actually comes from DEC Algol60 IIRC. It was used to
> > access individual characters of a string, normally an indivisible
> > type in that language, and I applied the same concept to bits of an
> > integer.  
> 
> I don't care if you found the syntax on the back of a cornflakes
> packet. The origin is not relevant.
> 
> >   
> >>> How much more fundamental can you get?  
> >>
> >> It is not fundamental for a low-level systems language.  
> > 
> > So bits are not fundamental either! But then, it has taken until
> > C23 to standardise binary literals, and there is still no format
> > code for binary output.
> >   
> 
> Very few programmers are at all interested in bits.  A "double" holds
> a floating point value, not a pattern of bits.  You are thinking on a 
> level of abstraction that is not realistic for most programming tasks.
> 
> >>>>   But the people who write those are few, and they know what
> >>>> they are doing.)  
> >>>
> >>> And I don't? I used to write FP emulation routines...
> >>>  
> >>
> >> The thing you always seem to forget, is that your languages are 
> >> written for /you/ - no one else.  It doesn't make a difference
> >> whether something is added /to/ the language or written in code
> >> /for/ the language.  You think other languages are missing
> >> critical features simply because there is a thing that /you/ want
> >> to do that you added to your own language. And you think other
> >> languages are overly complex or bloated because they have features
> >> that you don't want to use.  
> > 
> > They frequently have advanced features while ignoring the basics.  
> 
> No - they frequently have features that /you/ call "advanced" because 
> you don't need or want them, and they ignore things that /you/ call 
> "basics" because you /do/ need or want them.  It's all about /you/.
> 
> >   
> >> Imagine asking the regulars in this group what features or changes 
> >> they would like C to have in order to make C "perfect" for their
> >> uses, regardless of everyone else, all existing code, all existing
> >> tools. We could all fill pages with ideas.  And if those were all
> >> added to C, the result would be a language that made C++ look as
> >> easy as Logo, while being riddled with inconsistencies and
> >> contradictions.  
> > 
> > Yes, that's the trick. That's why a lot of features I've played
> > with have disappeared, while some have proved indispensable.
> >   
> >>> As it is, somebody using C as an intermediate language can have a 
> >>> situation where something is well-defined in their source
> >>> language, known to be well-defined on their platforms of
> >>> interest, but inbetween, C says otherwise.)  
> >>
> >> You've never really understood how languages are defined, have
> >> you? With your own languages and tools, you don't have to - there
> >> is no need for standards, specifications, or anything like that.
> >> You can just make up what suits you at the time.  The language is
> >> "defined" by what the implementation does.  That's been very
> >> convenient for you, but it has left you with serious
> >> misconceptions about how non-personal languages work.  
> > 
> > Here's a  program in a very simple language, where all variables
> > have i64 type:
> > 
> >    c = a + b
> > 
> > Here, the author has decreed that any overflow in this addition
> > will wrap (any overflow bits above 64 are lost). If directly
> > compiled to x64 code it might use this (here 'a b c' are aliases
> > for the registers where they reside):
> > 
> >      mov c, a
> >      add c, b
> > 
> > Or on ARM64:
> > 
> >      add c, a, b
> > 
> > Now, the author decides to use intermediate C (for portability, for 
> > optimisations etc), and will generate perhaps:
> > 
> >      int64_t a, b, c;
> >      ...
> >      c = a + b;
> > 
> > But here, if a + b happens to overflow, it is UB, and for no good 
> > reason. You have to fix it. This is where it can be harder to
> > generate HLL code than assembly!
> >   
> 
> You are talking nonsense.
> 
> Either a + b results in the correct answer, or it does not.  Any sane 
> person reads that as "a plus b" - mathematically adding two integers
> to get their sum.  That's what the programmer wants, and that's what
> they ask for.  And any sane programmer expects the language to give
> the correct result within its limitations, but doe not expect it to
> do magic.  Expecting to form a sum that is greater than 2 ^ 63 and
> somehow produce the "correct" result is a total misunderstanding of
> mathematics and programming - any primary school kid will tell you
> that using the fingers of one hand, you can't add 3 and 4.  They will
> /not/ tell you that it's fine to add them on one hand because 3 + 4
> is actually equal to 2.
> 
> > *Now* do you understand? This is nothing to do with me or my
> > personal languages, it is a problem for every language that
> > transpiles to C, where there is a mismatch between the sets of
> > behaviour considered UB in each.  
> 
> I understand that simple maths and common sense is beyond you.  I 
> understand that you think mathematics should be defined in terms of 
> accidental byproducts of the way hardware logic designs happen to be 
> implemented.
> 
> >   
> >>> OK, so how would you do a 'reinterpret' cast in C, of a value
> >>> like 'x+y'?  
> >>
> >> As you know, you use a union.  So just to please you, here is your
> >> bit extraction - written as a one-line function (split over two
> >> lines for Usenet) because you seem to think that kind of thing is
> >> important :
> >>
> >> uint64_t get_exponent(double x) {
> >>      return ((union { double d; uint64_t u;}) { x }.u >> 52)
> >>               & ((1ull << (62 - 52 + 1)) - 1);
> >> }
> >>
> >> That compiles (with gcc on x86-64) to :
> >>
> >>      movq rax, xmm0
> >>      shr rax, 52
> >>      and eax, 2047
> >>      ret
> >>
> >> There's nothing in C that suggests this must be put in memory or
> >> do anything more than this.  
> > 
> > (This only seems to work with gcc. Clang and MSVS don't like it.)
> >   
> 
> I think you are mistaken.  clang is fine with it.  It is standard
> C99, so any decent C compiler from the last 25 years will handle it
> fine.  MS gave up on bothering to make C compilers before the turn of
> the century (they make a reasonable enough C++ compiler).  Even your
> hero tcc is fine with it (though on my attempts, it produces rubbish
> code - maybe it needs different flags for optimisation).  The C code
> is not made invalid by the existence of C90-only compilers.
> 

MSVC compilers compile your code and produce correct result, but the
code 
looks less nice:
0000000000000000 <get_exponent>:
   0:   f2 0f 11 44 24 08       movsd  %xmm0,0x8(%rsp)
   6:   48 8b 44 24 08          mov    0x8(%rsp),%rax
   b:   48 c1 e8 34             shr    $0x34,%rax
   f:   25 ff 07 00 00          and    $0x7ff,%eax
  14:   c3                      ret

Although on old AMD processors it is likely faster than nicer code
generated by gcc and clang. On newer processor gcc code is likely a bit
better, but the difference is unlikely to be detected by simple
measurements.

Also MSVC compiler does not like your style and produces following
warning:
dave_b.c(5): warning C4116: unnamed type definition in parentheses

BTW, I don't like your style either. My preferred code will look
very similar to the code of Waldek Hebisch except that I'd declare
d_to_u() static.
I don't like union trick. Not just in this particular context, but
generally. memcpy() much cleaner in expressing programmer's intentions.






[toc] | [prev] | [next] | [standalone]


#395534

FromDavid Brown <david.brown@hesbynett.no>
Date2025-11-27 21:15 +0100
Message-ID<10gabhp$1o6rk$1@dont-email.me>
In reply to#395527
On 27/11/2025 15:02, Michael S wrote:
> On Thu, 27 Nov 2025 14:02:38 +0100
> David Brown <david.brown@hesbynett.no> wrote:
> 

> 
> MSVC compilers compile your code and produce correct result, but the
> code
> looks less nice:
> 0000000000000000 <get_exponent>:
>     0:   f2 0f 11 44 24 08       movsd  %xmm0,0x8(%rsp)
>     6:   48 8b 44 24 08          mov    0x8(%rsp),%rax
>     b:   48 c1 e8 34             shr    $0x34,%rax
>     f:   25 ff 07 00 00          and    $0x7ff,%eax
>    14:   c3                      ret
> 
> Although on old AMD processors it is likely faster than nicer code
> generated by gcc and clang. On newer processor gcc code is likely a bit
> better, but the difference is unlikely to be detected by simple
> measurements.

I think it is unlikely that this version - moving from xmm0 to rax via 
memory instead of directly - is faster on any processor.  But I fully 
agree that it is unlikely to be a measurable difference in practice.

> 
> Also MSVC compiler does not like your style and produces following
> warning:
> dave_b.c(5): warning C4116: unnamed type definition in parentheses

Warnings are a matter of taste.  There's nothing wrong with my code, but 
it may be against some code styles.

> 
> BTW, I don't like your style either. My preferred code will look
> very similar to the code of Waldek Hebisch except that I'd declare
> d_to_u() static.
> I don't like union trick. Not just in this particular context, but
> generally. memcpy() much cleaner in expressing programmer's intentions.
> 

I particularly don't like using unions in compound literals like this 
either - it was just to make a compact demonstration.  I'd write real 
code in more re-usable bits with static inline functions.

I disagree, however, that memcpy() shows intent better.  The intention 
is not to copy it to memory - the intention is to access the underlying 
bit representation as a different type.  A type-punning union is at 
least, if not more, clear for that purpose (IMHO - and judgements of 
style and clarity are very much a matter of opinion).

[toc] | [prev] | [next] | [standalone]


#395535

FromMichael S <already5chosen@yahoo.com>
Date2025-11-28 00:15 +0200
Message-ID<20251128001507.000064e1@yahoo.com>
In reply to#395534
On Thu, 27 Nov 2025 21:15:53 +0100
David Brown <david.brown@hesbynett.no> wrote:

> On 27/11/2025 15:02, Michael S wrote:
> > On Thu, 27 Nov 2025 14:02:38 +0100
> > David Brown <david.brown@hesbynett.no> wrote:
> >   
> 
> > 
> > MSVC compilers compile your code and produce correct result, but the
> > code
> > looks less nice:
> > 0000000000000000 <get_exponent>:
> >     0:   f2 0f 11 44 24 08       movsd  %xmm0,0x8(%rsp)
> >     6:   48 8b 44 24 08          mov    0x8(%rsp),%rax
> >     b:   48 c1 e8 34             shr    $0x34,%rax
> >     f:   25 ff 07 00 00          and    $0x7ff,%eax
> >    14:   c3                      ret
> > 
> > Although on old AMD processors it is likely faster than nicer code
> > generated by gcc and clang. On newer processor gcc code is likely a
> > bit better, but the difference is unlikely to be detected by simple
> > measurements.  
> 
> I think it is unlikely that this version - moving from xmm0 to rax
> via memory instead of directly - is faster on any processor.  But I
> fully agree that it is unlikely to be a measurable difference in
> practice.

I wonder, how do you have a nerve "to think" about things that you have
absolutely no idea about?

Instead of "thinking" you could just as well open Optimization
Reference manuals of AMD Bulldozer family or of Bobcat. Or to read
Agner Fog's instruction tables. Move from XMM to GPR on these
processors is very slow: 8 clocks on BD, 7 on BbC.

BTW, AMD K8 has the opposite problem. Move from XMM to GPR is reasonably
fast, but move from GPR to XMM is painfully slow.

On the other hand, moves "via memory" are reasonably fast on these
CPUs (except, may be, Bobcat? I am not sure about it), because data
does not really travels through memory or through cache. Load-store
forwarding picks the data directly from the store queue.


[toc] | [prev] | [next] | [standalone]


#395544

FromDavid Brown <david.brown@hesbynett.no>
Date2025-11-28 09:46 +0100
Message-ID<10gbni0$27ugi$1@dont-email.me>
In reply to#395535
On 27/11/2025 23:15, Michael S wrote:
> On Thu, 27 Nov 2025 21:15:53 +0100
> David Brown <david.brown@hesbynett.no> wrote:
> 
>> On 27/11/2025 15:02, Michael S wrote:
>>> On Thu, 27 Nov 2025 14:02:38 +0100
>>> David Brown <david.brown@hesbynett.no> wrote:
>>>    
>>
>>>
>>> MSVC compilers compile your code and produce correct result, but the
>>> code
>>> looks less nice:
>>> 0000000000000000 <get_exponent>:
>>>      0:   f2 0f 11 44 24 08       movsd  %xmm0,0x8(%rsp)
>>>      6:   48 8b 44 24 08          mov    0x8(%rsp),%rax
>>>      b:   48 c1 e8 34             shr    $0x34,%rax
>>>      f:   25 ff 07 00 00          and    $0x7ff,%eax
>>>     14:   c3                      ret
>>>
>>> Although on old AMD processors it is likely faster than nicer code
>>> generated by gcc and clang. On newer processor gcc code is likely a
>>> bit better, but the difference is unlikely to be detected by simple
>>> measurements.
>>
>> I think it is unlikely that this version - moving from xmm0 to rax
>> via memory instead of directly - is faster on any processor.  But I
>> fully agree that it is unlikely to be a measurable difference in
>> practice.
> 
> I wonder, how do you have a nerve "to think" about things that you have
> absolutely no idea about?

I think about many things - and these are things I /do/ know about.  But 
I don't know all the details, and am happy to be corrected and learn more.

> 
> Instead of "thinking" you could just as well open Optimization
> Reference manuals of AMD Bulldozer family or of Bobcat. Or to read
> Agner Fog's instruction tables. Move from XMM to GPR on these
> processors is very slow: 8 clocks on BD, 7 on BbC.
> 

Okay.  But storing data to memory from xmm0 is also going to be slow, 
and loading it to rax from memory is going to be slow.  I am not an 
expert at the x86 world or reading Fog's tables, but it looks to me that 
on a Bulldozer, storing from xmm0 to memory has a latency of 6 cycles 
and reading the memory into rax has a latency of 4 cycles.  That adds up 
to more than the 8 cycles for the direct register transfer, and I expect 
(but do not claim to know for sure!) that the dependency limits the 
scope for pipeline overlap - decode and address calculations can be 
done, but the data can't be fetched until the previous store is complete.

So all in all, my estimate was, I think, quite reasonable.  There may be 
unusual circumstances on particular cores if the instruction scheduling 
and pipelining, combined with the stack engine, make that sequence 
faster than the single register move.

I've now had a short look at the relevant table from Fog's site.  My 
conclusion from that is that the register move - though surprisingly 
slow - is probably marginally faster than passing it through memory. 
Perhaps if I spend enough time studying the details, I might find out 
more and discover that I was wrong.  But that would be an extraordinary 
effort to learn about a meaningless little detail of a long-gone processor.

I am also fairly confident that the function as a whole will be faster 
with the register move since you will get better overlap and 
superscaling with the call and return sequence when the instructions in 
the middle don't access the stack.

Of curiosity, I compiled the code with gcc and "-march=bdver1", which I 
believe is the correct flag for that processor.  It generated the 
register move version, but with a "vmovq" instruction instead of "movq". 
  I don't know if there is any difference there - x86 instruction naming 
seems to have a certain degree of variance.  (gcc's models of 
scheduling, pipelining and timing for processors is far from perfect, 
but the gcc folks do study Agner Fog's publications as well as having 
contributors from AMD and Intel.)

More interesting, however, was that with "-march=bdver2" (up to bdver4) 
gcc changed the "shr / and" sequence to a single "bextr" instruction.  I 
didn't see that on other -march choices.  It seems the two instruction 
shift-and-mask is faster than a single bit extract instruction on most 
x86 processors.

All in all, it is a lesson on how small details of architectures can 
make a difference.

> BTW, AMD K8 has the opposite problem. Move from XMM to GPR is reasonably
> fast, but move from GPR to XMM is painfully slow.
> 
> On the other hand, moves "via memory" are reasonably fast on these
> CPUs (except, may be, Bobcat? I am not sure about it), because data
> does not really travels through memory or through cache. Load-store
> forwarding picks the data directly from the store queue.
> 

Yes, and there can be even more specialised short-cuts for stack data.


[toc] | [prev] | [next] | [standalone]


#395546

FromMichael S <already5chosen@yahoo.com>
Date2025-11-28 13:12 +0200
Message-ID<20251128131217.00002a69@yahoo.com>
In reply to#395544
On Fri, 28 Nov 2025 09:46:56 +0100
David Brown <david.brown@hesbynett.no> wrote:

> On 27/11/2025 23:15, Michael S wrote:
> > On Thu, 27 Nov 2025 21:15:53 +0100
> > David Brown <david.brown@hesbynett.no> wrote:
> >   
> >> On 27/11/2025 15:02, Michael S wrote:  
> >>> On Thu, 27 Nov 2025 14:02:38 +0100
> >>> David Brown <david.brown@hesbynett.no> wrote:
> >>>      
> >>  
> >>>
> >>> MSVC compilers compile your code and produce correct result, but
> >>> the code
> >>> looks less nice:
> >>> 0000000000000000 <get_exponent>:
> >>>      0:   f2 0f 11 44 24 08       movsd  %xmm0,0x8(%rsp)
> >>>      6:   48 8b 44 24 08          mov    0x8(%rsp),%rax
> >>>      b:   48 c1 e8 34             shr    $0x34,%rax
> >>>      f:   25 ff 07 00 00          and    $0x7ff,%eax
> >>>     14:   c3                      ret
> >>>
> >>> Although on old AMD processors it is likely faster than nicer code
> >>> generated by gcc and clang. On newer processor gcc code is likely
> >>> a bit better, but the difference is unlikely to be detected by
> >>> simple measurements.  
> >>
> >> I think it is unlikely that this version - moving from xmm0 to rax
> >> via memory instead of directly - is faster on any processor.  But I
> >> fully agree that it is unlikely to be a measurable difference in
> >> practice.  
> > 
> > I wonder, how do you have a nerve "to think" about things that you
> > have absolutely no idea about?  
> 
> I think about many things - and these are things I /do/ know about.
> But I don't know all the details, and am happy to be corrected and
> learn more.
> 
> > 
> > Instead of "thinking" you could just as well open Optimization
> > Reference manuals of AMD Bulldozer family or of Bobcat. Or to read
> > Agner Fog's instruction tables. Move from XMM to GPR on these
> > processors is very slow: 8 clocks on BD, 7 on BbC.
> >   
> 
> Okay.  But storing data to memory from xmm0 is also going to be slow, 
> and loading it to rax from memory is going to be slow.  I am not an 
> expert at the x86 world or reading Fog's tables, but it looks to me
> that on a Bulldozer, storing from xmm0 to memory has a latency of 6
> cycles and reading the memory into rax has a latency of 4 cycles.
> That adds up to more than the 8 cycles for the direct register
> transfer, and I expect (but do not claim to know for sure!) that the
> dependency limits the scope for pipeline overlap - decode and address
> calculations can be done, but the data can't be fetched until the
> previous store is complete.
> 
> So all in all, my estimate was, I think, quite reasonable.  There may
> be unusual circumstances on particular cores if the instruction
> scheduling and pipelining, combined with the stack engine, make that
> sequence faster than the single register move.
> 

It seems, you are correct in this particular case.
Latency tables, esp. those that are measured by software rather
than supplied by designer, are problematic in case of moves between
registers of different types, memory stores of all types and even
memory loads, with exception of memory load into GPR. Agner explains why
they are problematic in te preface to his tables. In short, there is no
direct way to measure this things in isolation, so one has to measure
latency of the sequence of instructions and then to apply either
guesswork or manufacturer's docs to somehow divide the combined
latency into individual parts.

So, the best way is to go by recommendations of the vendor in Opt.
Reference Manual.
There are no relevant recommendations for K8, unfortunately. I suspect
that all methods are slow here.
For Bobcat, there should be recommendations, but I don't have them and
too lazy to look for.

For Family 10h (Barcelona and derivatives):
"When moving data from a GPR to an MMX or XMM register, use separate
store and load instructions to move the data first from the source
register to a temporary location in memory and then from memory into
the destination register, taking the memory latency into account when
scheduling both stages of the load-store sequence.

When moving data from an MMX or XMM register to a general-purpose
register, use the MOVD instruction.

Whenever possible, use loads and stores of the same data length. (See
5.3, ‘Store-to-Load Forwarding Restrictions” on page 74 for more
information.)"

For Family 15h (Bullozer and derivatives):
"When moving data from a GPR to an XMM register, use separate store and
load instructions to move the data first from the source register to a
temporary location in memory and then from memory into the destination
register, taking the memory latency into account when scheduling both
stages of the load-store sequence. 

When moving data from an XMM register to a general-purpose register,
use the VMOVD instruction. 

Whenever possible, use loads and stores of the same data length. (See
6.3, ‘Store-to-Load Forwarding Restrictions” on page 98 for more
information.)"

So, for both families, vendor recommends register move in direction from
SIMD to GPR and Store/Load sequence in direction from GPR to SIMD.
The suspect point here is specific mentioning of EVEX-encoded form
(VMOVD) in case of BD. It can mean that "legacy" (SSE-encoded) form is
slower or it can mean nothing. I suspect the latter.

> I've now had a short look at the relevant table from Fog's site.  My 
> conclusion from that is that the register move - though surprisingly 
> slow - is probably marginally faster than passing it through memory. 
> Perhaps if I spend enough time studying the details, I might find out 
> more and discover that I was wrong.  But that would be an
> extraordinary effort to learn about a meaningless little detail of a
> long-gone processor.
> 
> I am also fairly confident that the function as a whole will be
> faster with the register move since you will get better overlap and 
> superscaling with the call and return sequence when the instructions
> in the middle don't access the stack.
> 
> Of curiosity, I compiled the code with gcc and "-march=bdver1", which
> I believe is the correct flag for that processor.  It generated the 
> register move version, but with a "vmovq" instruction instead of
> "movq". I don't know if there is any difference there - x86
> instruction naming seems to have a certain degree of variance.
> (gcc's models of scheduling, pipelining and timing for processors is
> far from perfect, but the gcc folks do study Agner Fog's publications
> as well as having contributors from AMD and Intel.)
> 
> More interesting, however, was that with "-march=bdver2" (up to
> bdver4) gcc changed the "shr / and" sequence to a single "bextr"
> instruction.  I didn't see that on other -march choices.  It seems
> the two instruction shift-and-mask is faster than a single bit
> extract instruction on most x86 processors.
> 
> All in all, it is a lesson on how small details of architectures can 
> make a difference.
>

Zen3 has its own can of worms in the area of moving data between
GPR and SIMD. The issues here are more subtle than those mentioned
above. And unfortunately almost completely non-documented in the
manuals. And despite that issues are subtle, performance impact can be
very significant.

I encountered these things when implementing alternative
(to those currently in use by gcc) IEEE binary128 arithmetic routines.
My conclusion was that designers of binary128 ABI in general and of ABI
of support routines in particular made a serious mistake by treating
binary128 (a.k.a. __float128, a.k.a _Float128, a.k.a. 'long double' on
ARM64) as "floating-point" type that is passed around in XMM registers
(or Neon registers on ARM64). Both passing it in pair of GPRs and via
memory would be significantly faster on AMD processors and detectably
faster on Intel processors.


> > BTW, AMD K8 has the opposite problem. Move from XMM to GPR is
> > reasonably fast, but move from GPR to XMM is painfully slow.
> > 
> > On the other hand, moves "via memory" are reasonably fast on these
> > CPUs (except, may be, Bobcat? I am not sure about it), because data
> > does not really travels through memory or through cache. Load-store
> > forwarding picks the data directly from the store queue.
> >   
> 
> Yes, and there can be even more specialised short-cuts for stack data.
> 
> 
> 

[toc] | [prev] | [next] | [standalone]


#395547

FromDavid Brown <david.brown@hesbynett.no>
Date2025-11-28 12:45 +0100
Message-ID<10gc21m$2bsou$1@dont-email.me>
In reply to#395546
On 28/11/2025 12:12, Michael S wrote:
> On Fri, 28 Nov 2025 09:46:56 +0100
> David Brown <david.brown@hesbynett.no> wrote:
> 
>> On 27/11/2025 23:15, Michael S wrote:
>>> On Thu, 27 Nov 2025 21:15:53 +0100
>>> David Brown <david.brown@hesbynett.no> wrote:
>>>    
>>>> On 27/11/2025 15:02, Michael S wrote:
>>>>> On Thu, 27 Nov 2025 14:02:38 +0100
>>>>> David Brown <david.brown@hesbynett.no> wrote:
>>>>>       
>>>>   
>>>>>
>>>>> MSVC compilers compile your code and produce correct result, but
>>>>> the code
>>>>> looks less nice:
>>>>> 0000000000000000 <get_exponent>:
>>>>>       0:   f2 0f 11 44 24 08       movsd  %xmm0,0x8(%rsp)
>>>>>       6:   48 8b 44 24 08          mov    0x8(%rsp),%rax
>>>>>       b:   48 c1 e8 34             shr    $0x34,%rax
>>>>>       f:   25 ff 07 00 00          and    $0x7ff,%eax
>>>>>      14:   c3                      ret
>>>>>
>>>>> Although on old AMD processors it is likely faster than nicer code
>>>>> generated by gcc and clang. On newer processor gcc code is likely
>>>>> a bit better, but the difference is unlikely to be detected by
>>>>> simple measurements.
>>>>
>>>> I think it is unlikely that this version - moving from xmm0 to rax
>>>> via memory instead of directly - is faster on any processor.  But I
>>>> fully agree that it is unlikely to be a measurable difference in
>>>> practice.
>>>
>>> I wonder, how do you have a nerve "to think" about things that you
>>> have absolutely no idea about?
>>
>> I think about many things - and these are things I /do/ know about.
>> But I don't know all the details, and am happy to be corrected and
>> learn more.
>>
>>>
>>> Instead of "thinking" you could just as well open Optimization
>>> Reference manuals of AMD Bulldozer family or of Bobcat. Or to read
>>> Agner Fog's instruction tables. Move from XMM to GPR on these
>>> processors is very slow: 8 clocks on BD, 7 on BbC.
>>>    
>>
>> Okay.  But storing data to memory from xmm0 is also going to be slow,
>> and loading it to rax from memory is going to be slow.  I am not an
>> expert at the x86 world or reading Fog's tables, but it looks to me
>> that on a Bulldozer, storing from xmm0 to memory has a latency of 6
>> cycles and reading the memory into rax has a latency of 4 cycles.
>> That adds up to more than the 8 cycles for the direct register
>> transfer, and I expect (but do not claim to know for sure!) that the
>> dependency limits the scope for pipeline overlap - decode and address
>> calculations can be done, but the data can't be fetched until the
>> previous store is complete.
>>
>> So all in all, my estimate was, I think, quite reasonable.  There may
>> be unusual circumstances on particular cores if the instruction
>> scheduling and pipelining, combined with the stack engine, make that
>> sequence faster than the single register move.
>>
> 
> It seems, you are correct in this particular case.
> Latency tables, esp. those that are measured by software rather
> than supplied by designer, are problematic in case of moves between
> registers of different types, memory stores of all types and even
> memory loads, with exception of memory load into GPR. Agner explains why
> they are problematic in te preface to his tables. In short, there is no
> direct way to measure this things in isolation, so one has to measure
> latency of the sequence of instructions and then to apply either
> guesswork or manufacturer's docs to somehow divide the combined
> latency into individual parts.
> 

Well, if even Agner thinks it is difficult, then I don't feel bad for 
having trouble!

> So, the best way is to go by recommendations of the vendor in Opt.
> Reference Manual.
> There are no relevant recommendations for K8, unfortunately. I suspect
> that all methods are slow here.
> For Bobcat, there should be recommendations, but I don't have them and
> too lazy to look for.
> 

Fair enough.  It is not information that is likely to be useful to 
anyone here, so it's all for fun and interest.  I certainly wouldn't 
want you to spend effort finding out the details just for me.

> For Family 10h (Barcelona and derivatives):
> "When moving data from a GPR to an MMX or XMM register, use separate
> store and load instructions to move the data first from the source
> register to a temporary location in memory and then from memory into
> the destination register, taking the memory latency into account when
> scheduling both stages of the load-store sequence.
> 
> When moving data from an MMX or XMM register to a general-purpose
> register, use the MOVD instruction.
> 
> Whenever possible, use loads and stores of the same data length. (See
> 5.3, ‘Store-to-Load Forwarding Restrictions” on page 74 for more
> information.)"

How much does advice like this take into account surrounding code? 
That's what makes generating optimal code /really/ hard.  And it means 
micro-optimising a short instruction sequence can be ineffective for 
real-world code.  After all, no one is actually interested in minimising 
the number of nanoseconds it takes to extract the exponent of a floating 
point number - the speed only matters if you are doing lots of these, 
probably in a big loop with data moving into and out of memory all the time.

This stuff was all /so/ much easier when we used PIC's and AVR's...

> 
> For Family 15h (Bullozer and derivatives):
> "When moving data from a GPR to an XMM register, use separate store and
> load instructions to move the data first from the source register to a
> temporary location in memory and then from memory into the destination
> register, taking the memory latency into account when scheduling both
> stages of the load-store sequence.
> 
> When moving data from an XMM register to a general-purpose register,
> use the VMOVD instruction.
> 
> Whenever possible, use loads and stores of the same data length. (See
> 6.3, ‘Store-to-Load Forwarding Restrictions” on page 98 for more
> information.)"
> 
> So, for both families, vendor recommends register move in direction from
> SIMD to GPR and Store/Load sequence in direction from GPR to SIMD.
> The suspect point here is specific mentioning of EVEX-encoded form
> (VMOVD) in case of BD. It can mean that "legacy" (SSE-encoded) form is
> slower or it can mean nothing. I suspect the latter.
> 
>> I've now had a short look at the relevant table from Fog's site.  My
>> conclusion from that is that the register move - though surprisingly
>> slow - is probably marginally faster than passing it through memory.
>> Perhaps if I spend enough time studying the details, I might find out
>> more and discover that I was wrong.  But that would be an
>> extraordinary effort to learn about a meaningless little detail of a
>> long-gone processor.
>>
>> I am also fairly confident that the function as a whole will be
>> faster with the register move since you will get better overlap and
>> superscaling with the call and return sequence when the instructions
>> in the middle don't access the stack.
>>
>> Of curiosity, I compiled the code with gcc and "-march=bdver1", which
>> I believe is the correct flag for that processor.  It generated the
>> register move version, but with a "vmovq" instruction instead of
>> "movq". I don't know if there is any difference there - x86
>> instruction naming seems to have a certain degree of variance.
>> (gcc's models of scheduling, pipelining and timing for processors is
>> far from perfect, but the gcc folks do study Agner Fog's publications
>> as well as having contributors from AMD and Intel.)
>>
>> More interesting, however, was that with "-march=bdver2" (up to
>> bdver4) gcc changed the "shr / and" sequence to a single "bextr"
>> instruction.  I didn't see that on other -march choices.  It seems
>> the two instruction shift-and-mask is faster than a single bit
>> extract instruction on most x86 processors.
>>
>> All in all, it is a lesson on how small details of architectures can
>> make a difference.
>>
> 
> Zen3 has its own can of worms in the area of moving data between
> GPR and SIMD. The issues here are more subtle than those mentioned
> above. And unfortunately almost completely non-documented in the
> manuals. And despite that issues are subtle, performance impact can be
> very significant.
> 
> I encountered these things when implementing alternative
> (to those currently in use by gcc) IEEE binary128 arithmetic routines.
> My conclusion was that designers of binary128 ABI in general and of ABI
> of support routines in particular made a serious mistake by treating
> binary128 (a.k.a. __float128, a.k.a _Float128, a.k.a. 'long double' on
> ARM64) as "floating-point" type that is passed around in XMM registers
> (or Neon registers on ARM64). Both passing it in pair of GPRs and via
> memory would be significantly faster on AMD processors and detectably
> faster on Intel processors.

I can believe that.  If you have to implement floating point routines in 
general integer hardware (and I expect that is the case for most of your 
implementation here) then I would think it is better to start and end 
with the data in GPR's.  On some targets, moving data into and out of 
floating point or vector registers is efficient enough that those 
registers can effectively be used as caches, but it sounds like that is 
not the case here.

> 
> 
>>> BTW, AMD K8 has the opposite problem. Move from XMM to GPR is
>>> reasonably fast, but move from GPR to XMM is painfully slow.
>>>
>>> On the other hand, moves "via memory" are reasonably fast on these
>>> CPUs (except, may be, Bobcat? I am not sure about it), because data
>>> does not really travels through memory or through cache. Load-store
>>> forwarding picks the data directly from the store queue.
>>>    
>>
>> Yes, and there can be even more specialised short-cuts for stack data.
>>
>>
>>
> 
> 

[toc] | [prev] | [next] | [standalone]


#395549

FromMichael S <already5chosen@yahoo.com>
Date2025-11-28 15:33 +0200
Message-ID<20251128153355.00002711@yahoo.com>
In reply to#395547
On Fri, 28 Nov 2025 12:45:58 +0100
David Brown <david.brown@hesbynett.no> wrote:

> 
> I can believe that.  If you have to implement floating point routines
> in general integer hardware (and I expect that is the case for most
> of your implementation here) then I would think it is better to start
> and end with the data in GPR's.  On some targets, moving data into
> and out of floating point or vector registers is efficient enough
> that those registers can effectively be used as caches, but it sounds
> like that is not the case here.
>

On Windows the problem is only of moving data between various types of
registers. 
On SysV things are worse: there is also a problem of absence of
caller-saved FP/SIMD registers. In theory, the problem could have been
solved by defining specialized ABI for support routines (__addtf3,
__subtf3, __multf3, etc...), but that was not done either.

I think, that it all comes from the old mental model of soft floating
point routines being very slow; so slow that ABI impedance mismatches
lost in noise. But in specific case of binary128 on modern CPUs, it's
simply not true - arithmetic itself is quite fast so ABI mismatches are
significant.

[toc] | [prev] | [next] | [standalone]


#395551

FromDavid Brown <david.brown@hesbynett.no>
Date2025-11-28 15:47 +0100
Message-ID<10gccmd$2frk7$1@dont-email.me>
In reply to#395549
On 28/11/2025 14:33, Michael S wrote:
> On Fri, 28 Nov 2025 12:45:58 +0100
> David Brown <david.brown@hesbynett.no> wrote:
> 
>>
>> I can believe that.  If you have to implement floating point routines
>> in general integer hardware (and I expect that is the case for most
>> of your implementation here) then I would think it is better to start
>> and end with the data in GPR's.  On some targets, moving data into
>> and out of floating point or vector registers is efficient enough
>> that those registers can effectively be used as caches, but it sounds
>> like that is not the case here.
>>
> 
> On Windows the problem is only of moving data between various types of
> registers.
> On SysV things are worse: there is also a problem of absence of
> caller-saved FP/SIMD registers. In theory, the problem could have been
> solved by defining specialized ABI for support routines (__addtf3,
> __subtf3, __multf3, etc...), but that was not done either.
> 
> I think, that it all comes from the old mental model of soft floating
> point routines being very slow; so slow that ABI impedance mismatches
> lost in noise. But in specific case of binary128 on modern CPUs, it's
> simply not true - arithmetic itself is quite fast so ABI mismatches are
> significant.
> 

My only real experience with software floating point (using it, not 
writing it) is on systems where they are either slow (like 32-bit 
Cortex-M ARMs), or /very/ slow (like an 8-bit AVR).  A little 
inefficiency in the main ABI's is, as you say, just noise in these cases.

But in those systems, the floating point arithmetic routines were part 
of the compiler support library.  Functions there don't have to abide by 
the platform ABI - they can use different registers according to what 
suits best.  Were you working on a library that integrates into the 
compiler, or was it more "user level" (like a C++ "binary128" class with 
operator overrides) ?

ABI's are obviously useful for standardisation and intermixing of code 
from different tools.  But they can also be a pain, especially when they 
are old and outdated or designed to be efficient on different processors 
or with different kinds of code.  I am finding the EABI for 32-bit ARM 
to be a serious performance drain for some kinds of work.  It doesn't 
support passing anything bigger than 32-bit in registers, except for 
"long long int" and "unsigned long long int".  It has the same 
restriction on return values.  That means if you have something like a 
C++ optional<uint32_t> type, or equivalent struct in C, it's all passed 
back and forth on the stack.  And unlike the AMD processors you mention, 
on a Cortex-M core that is a lot slower!

[toc] | [prev] | [next] | [standalone]


#395571

FromMichael S <already5chosen@yahoo.com>
Date2025-11-29 19:23 +0200
Message-ID<20251129192359.00002cfe@yahoo.com>
In reply to#395551
On Fri, 28 Nov 2025 15:47:41 +0100
David Brown <david.brown@hesbynett.no> wrote:

> On 28/11/2025 14:33, Michael S wrote:
> > On Fri, 28 Nov 2025 12:45:58 +0100
> > David Brown <david.brown@hesbynett.no> wrote:
> >   
> >>
> >> I can believe that.  If you have to implement floating point
> >> routines in general integer hardware (and I expect that is the
> >> case for most of your implementation here) then I would think it
> >> is better to start and end with the data in GPR's.  On some
> >> targets, moving data into and out of floating point or vector
> >> registers is efficient enough that those registers can effectively
> >> be used as caches, but it sounds like that is not the case here.
> >>  
> > 
> > On Windows the problem is only of moving data between various types
> > of registers.
> > On SysV things are worse: there is also a problem of absence of
> > caller-saved FP/SIMD registers. In theory, the problem could have
> > been solved by defining specialized ABI for support routines
> > (__addtf3, __subtf3, __multf3, etc...), but that was not done
> > either.
> > 
> > I think, that it all comes from the old mental model of soft
> > floating point routines being very slow; so slow that ABI impedance
> > mismatches lost in noise. But in specific case of binary128 on
> > modern CPUs, it's simply not true - arithmetic itself is quite fast
> > so ABI mismatches are significant.
> >   
> 
> My only real experience with software floating point (using it, not 
> writing it) is on systems where they are either slow (like 32-bit 
> Cortex-M ARMs), or /very/ slow (like an 8-bit AVR).  A little 
> inefficiency in the main ABI's is, as you say, just noise in these
> cases.
> 
> But in those systems, the floating point arithmetic routines were
> part of the compiler support library.  Functions there don't have to
> abide by the platform ABI - they can use different registers
> according to what suits best.  Were you working on a library that
> integrates into the compiler, or was it more "user level" (like a C++
> "binary128" class with operator overrides) ?
> 

The former. Plug-in replacement for libgcc routines.
It's absolutely true that gcc people were not obliged to follow SysV
ABI, which is rather bad in general, but especially harmful in this
particular case. But they decided to follow it.


> ABI's are obviously useful for standardisation and intermixing of
> code from different tools.  But they can also be a pain, especially
> when they are old and outdated or designed to be efficient on
> different processors or with different kinds of code.  I am finding
> the EABI for 32-bit ARM to be a serious performance drain for some
> kinds of work.  It doesn't support passing anything bigger than
> 32-bit in registers, except for "long long int" and "unsigned long
> long int".  It has the same restriction on return values.  That means
> if you have something like a C++ optional<uint32_t> type, or
> equivalent struct in C, it's all passed back and forth on the stack.
> And unlike the AMD processors you mention, on a Cortex-M core that is
> a lot slower!
> 

You know my opinion about use of C++ on MCUs. I don't have to repeat
myself.




[toc] | [prev] | [next] | [standalone]


#395560

Fromantispam@fricas.org (Waldek Hebisch)
Date2025-11-29 00:20 +0000
Message-ID<10gde8b$10fda$1@paganini.bofh.team>
In reply to#395546
Michael S <already5chosen@yahoo.com> wrote:
> 
> Zen3 has its own can of worms in the area of moving data between
> GPR and SIMD. The issues here are more subtle than those mentioned
> above. And unfortunately almost completely non-documented in the
> manuals. And despite that issues are subtle, performance impact can be
> very significant.
> 
> I encountered these things when implementing alternative
> (to those currently in use by gcc) IEEE binary128 arithmetic routines.
> My conclusion was that designers of binary128 ABI in general and of ABI
> of support routines in particular made a serious mistake by treating
> binary128 (a.k.a. __float128, a.k.a _Float128, a.k.a. 'long double' on
> ARM64) as "floating-point" type that is passed around in XMM registers
> (or Neon registers on ARM64). Both passing it in pair of GPRs and via
> memory would be significantly faster on AMD processors and detectably
> faster on Intel processors.

If they want to handle that type in hardware on some future model,
then ABI must use floating point (that is XMM) register.

-- 
                              Waldek Hebisch

[toc] | [prev] | [next] | [standalone]


#395572

FromMichael S <already5chosen@yahoo.com>
Date2025-11-29 19:30 +0200
Message-ID<20251129193007.00005efa@yahoo.com>
In reply to#395560
On Sat, 29 Nov 2025 00:20:29 -0000 (UTC)
antispam@fricas.org (Waldek Hebisch) wrote:

> Michael S <already5chosen@yahoo.com> wrote:
> > 
> > Zen3 has its own can of worms in the area of moving data between
> > GPR and SIMD. The issues here are more subtle than those mentioned
> > above. And unfortunately almost completely non-documented in the
> > manuals. And despite that issues are subtle, performance impact can
> > be very significant.
> > 
> > I encountered these things when implementing alternative
> > (to those currently in use by gcc) IEEE binary128 arithmetic
> > routines. My conclusion was that designers of binary128 ABI in
> > general and of ABI of support routines in particular made a serious
> > mistake by treating binary128 (a.k.a. __float128, a.k.a _Float128,
> > a.k.a. 'long double' on ARM64) as "floating-point" type that is
> > passed around in XMM registers (or Neon registers on ARM64). Both
> > passing it in pair of GPRs and via memory would be significantly
> > faster on AMD processors and detectably faster on Intel processors.
> >  
> 
> If they want to handle that type in hardware on some future model,
> then ABI must use floating point (that is XMM) register.
> 


Neither Intel nor AMD nor Arm ever said that they have plans of that
sort.
Thinking too much about future is bad engineering. In specific case of
computer engineering, I am pretty sure that it caused significantly
more harm than not thinking enough about future.

[toc] | [prev] | [next] | [standalone]


#395554

FromBGB <cr88192@gmail.com>
Date2025-11-28 13:09 -0600
Message-ID<10gcs5g$2mrrt$1@dont-email.me>
In reply to#395534
On 11/27/2025 2:15 PM, David Brown wrote:
> On 27/11/2025 15:02, Michael S wrote:
>> On Thu, 27 Nov 2025 14:02:38 +0100
>> David Brown <david.brown@hesbynett.no> wrote:
>>
> 
>>
>> MSVC compilers compile your code and produce correct result, but the
>> code
>> looks less nice:
>> 0000000000000000 <get_exponent>:
>>     0:   f2 0f 11 44 24 08       movsd  %xmm0,0x8(%rsp)
>>     6:   48 8b 44 24 08          mov    0x8(%rsp),%rax
>>     b:   48 c1 e8 34             shr    $0x34,%rax
>>     f:   25 ff 07 00 00          and    $0x7ff,%eax
>>    14:   c3                      ret
>>
>> Although on old AMD processors it is likely faster than nicer code
>> generated by gcc and clang. On newer processor gcc code is likely a bit
>> better, but the difference is unlikely to be detected by simple
>> measurements.
> 
> I think it is unlikely that this version - moving from xmm0 to rax via 
> memory instead of directly - is faster on any processor.  But I fully 
> agree that it is unlikely to be a measurable difference in practice.
> 
>>
>> Also MSVC compiler does not like your style and produces following
>> warning:
>> dave_b.c(5): warning C4116: unnamed type definition in parentheses
> 
> Warnings are a matter of taste.  There's nothing wrong with my code, but 
> it may be against some code styles.
> 
>>
>> BTW, I don't like your style either. My preferred code will look
>> very similar to the code of Waldek Hebisch except that I'd declare
>> d_to_u() static.
>> I don't like union trick. Not just in this particular context, but
>> generally. memcpy() much cleaner in expressing programmer's intentions.
>>
> 
> I particularly don't like using unions in compound literals like this 
> either - it was just to make a compact demonstration.  I'd write real 
> code in more re-usable bits with static inline functions.
> 
> I disagree, however, that memcpy() shows intent better.  The intention 
> is not to copy it to memory - the intention is to access the underlying 
> bit representation as a different type.  A type-punning union is at 
> least, if not more, clear for that purpose (IMHO - and judgements of 
> style and clarity are very much a matter of opinion).
> 

FWIW, BGBCC allows:
   double f;
   u64 uli;
   uli=(u64)((__m64)f);
And, you can extract an exponent as:
   uli[62:52]
But, this is pretty nonstandard...


Here, "val[hi:lo]" works on pretty much any integer type, with the behavior:
If it is a normal integer type, will return a zero-extended value of the 
same type as the input (so, similar to what shift and mask would do).

If the input type is a _BitInt or _UBitInt, the result will also be 
_BitInt or _UBitInt with the same width as the bitfield selector.

It is possible to select a single bit:
   uli[63]
But, this is only valid for _BitInt and _UBitInt, where if a normal 
integer type it used here, it makes more sense to assume the user had 
mistyped something, so "uli[63:63]" would be needed for a single bit 
extract in this case.

It is also possible to compose values of _UBitInt and similar, say:
   _UBitInt(24) rgb24;
   _UBitInt(16) rgb5;
   rgb5=(_UBitInt(16)) { 0b0u1, rgb24[23:19], rgb24[15:11], rgb24[7:3] };

Etc...

Some of this was partly inspired by Verilog in my case.

Partial merit in this case is that, beyond just being slightly more 
concise and readable than a more traditional shifts-and-masks approach, 
also makes it easier for the compiler to generate more efficient code...

Though, for this particular scenario, my ISA has a specialized CPU 
instruction for RGB24 to RGB555 that is faster than manually repacking 
the bits, so alas...


But, also there are special optional instructions for bitfield moves 
that would allow the above to be expressed in 3 CPU instructions (vs the 
11 or so instructions that would be needed with a more traditional 
approach, or 8 if one gets clever with how they use shifts).

However, with the syntax, without the special CPU instruction, it can 
infer the 8-instruction construct, and other similar constructs, it 
cases where it might have otherwise been too much mental effort for a 
human programmer (and where inferring this from shifts and masks is also 
asking too much from the compiler...).

...

[toc] | [prev] | [next] | [standalone]


#395557

Frombart <bc@freeuk.com>
Date2025-11-28 22:43 +0000
Message-ID<10gd8in$2qefr$1@dont-email.me>
In reply to#395554
On 28/11/2025 19:09, BGB wrote:

> It is also possible to compose values of _UBitInt and similar, say:
>    _UBitInt(24) rgb24;
>    _UBitInt(16) rgb5;
>    rgb5=(_UBitInt(16)) { 0b0u1, rgb24[23:19], rgb24[15:11], rgb24[7:3] };

This has given me an idea for an extended feature. Here, I would use 
rgb.[x] syntax, where x is maybe 23, or 23..19, and rgb.[x, y] just 
means rgb.[x].[y].

The latter is not that useful however; suppose that rgb.[x, y] actually 
combines rgb.[x] and rgb.[y]. That could then be used to express your 
example like this:

    rgb24.[23..19, 15..11, 7..3]

So the 3 distinct 5-bit bitfields are concatenated into one 15-bit field.

However the exact meaning and ordering would still need pinning down, 
and there are various questions to be answered. I also think that such 
extaction can be a separate feature from packing multiple sub-word 
values into one result.

I think this might be worth looking at. But I'm still not keen on 
relying on the type system to give you the lengths of those fields. (In 
my language, rgb.[23..19] is extracted into an i64 value so its bitfield 
info is lost.)

[toc] | [prev] | [next] | [standalone]


Page 4 of 13 — ← Prev page 1 2 3 [4] 5 6 … 13  Next page →

Back to top | Article view | comp.lang.c


csiph-web