Hot!snprintf with format specifier "%.4g" seems not to work (xc1.42 + legacy lib)

Author
moser
Super Member
  • Total Posts : 262
  • Reward points : 0
  • Joined: 2015/06/16 02:53:47
  • Location: 0
  • Status: offline
2017/10/10 10:54:17 (permalink)
0

snprintf with format specifier "%.4g" seems not to work (xc1.42 + legacy lib)

I'm using xc1.42 with legacy lib and a PIC32EFM. I intended to use the "%.4g" format specifier with snprintf. However, this doesn't seem to work. 
 
Usually %g provides a mechanism that the value switches over from decimal representation (with %f) to scientific representation (with %e). For the snprintf documentation found in the Internet you can often read something like "the shorter representation is used" and sometimes even a certain mechanism is described, how it decides between %e and %f. For the xc32 the documentation is extremely vague:
32-Bit Language Tools Libraries (pdf Documentation)
g, G             double (takes the form of e, E or f as appropriate)

 
 
I used some test code which is mostly like the following with x ranging from 0 to 15:

double value_double = (2.0 / 3000000.0) * pow(10.0, (double)x);
snprintf(str_buffer, size, "%.4g", value_double);

I got these results:
0.0000006667
0.000006667
0.00006667
0.0006667
0.006667
0.06667
0.6667
6.667
66.67
666.7
6667
66666.6640625
666666.6875
6666666.5
66666660
666666600

 
As you can see, it never switches to the scientific representation. So this is another bug with the snprintf function?
 
Does anyone know whether x32 v1.44 behaves different? 
post edited by moser - 2017/10/11 00:40:42
#1

5 Replies Related Threads

    davekw7x
    Entropy++
    • Total Posts : 1205
    • Reward points : 0
    • Joined: 2012/01/16 12:01:07
    • Location: Left Coast, USA
    • Status: offline
    Re: snprintf with format specifier "%.4g" seems not to work (xc1.42 + legacy lib) 2017/10/10 13:24:47 (permalink)
    +2 (2)
    Sigh...
     
    I have lost count of the number of XC32 revisions for which they "fixed" (at most) one of the print functions for 64-bit ints, floats, doubles, or long doubles and "unfixed" (at least) one of the others.  (Kind of like playing Whack-A-Mole blindfolded, I'm thinking.)
     
    With XC32 version 1.44, with the "Use legacy libc" XC32 global option I get the same output that you posted: "%g" not working as specified.
     
    On the other hand, when I uncheck the Use legacy libc box, I get expected outputs.
     
    I pasted the following into main() in my PIC32MM0064GPL028 project:
        // Initialize clocks, I/O, timers, uart, etc...
        //
        printf("\nCompiled on %s at %s by XC32 version %d\r\n",
                __DATE__, __TIME__, __XC32_VERSION);
        int x;
        char str_buffer[80];
        size_t size = sizeof(str_buffer);
        for (x = 0; x < 16; x++) {
            double value_double = (2.0 / 3000000.0) * pow(10.0, (double)x);
            snprintf(str_buffer, size, "%.4g", value_double);
            //printf("%2d: %.4g\r\n", x, value_double);
            printf("%2d: str_buffer: <%s>\r\n", x, str_buffer);
        }

    With "Use legacy libc" unchecked the output is OK:
     
    Compiled on Oct 10 2017 at 13:18:53 PDT by XC32 version 1440
     0: str_buffer: <6.667e-07>
     1: str_buffer: <6.667e-06>
     2: str_buffer: <6.667e-05>
     3: str_buffer: <0.0006667>
     4: str_buffer: <0.006667>
     5: str_buffer: <0.06667>
     6: str_buffer: <0.6667>
     7: str_buffer: <6.667>
     8: str_buffer: <66.67>
     9: str_buffer: <666.7>
    10: str_buffer: <6667>
    11: str_buffer: <6.667e+04>
    12: str_buffer: <6.667e+05>
    13: str_buffer: <6.667e+06>
    14: str_buffer: <6.667e+07>
    15: str_buffer: <6.667e+08>
     
    Sigh...
    (But I said that already)
     
    Note that when I used printf directly instead of going through sprintf, results in both cases were exactly the same, so it isn't just sprintf; it's the whole family.
     

    Regards,

    Dave
    post edited by davekw7x - 2017/10/10 13:30:49

    Sometimes I just can't help myself...
          #SonomaStrong
    #2
    andersm
    Super Member
    • Total Posts : 2213
    • Reward points : 0
    • Joined: 2012/10/07 14:57:44
    • Location: 0
    • Status: online
    Re: snprintf with format specifier "%.4g" seems not to work (xc1.42 + legacy lib) 2017/10/10 15:19:52 (permalink)
    +1 (1)
    XC32 1.44 added Newlib as an option, though it doesn't seem to be exposed as an option in MPLAB X (yet). I haven't tried using it yet to see if it works, and how it affects the resulting program, but I would assume that Newlib is both slower and larger than either of the other options. On the flipside, it should provide full C99 support.
    #3
    davekw7x
    Entropy++
    • Total Posts : 1205
    • Reward points : 0
    • Joined: 2012/01/16 12:01:07
    • Location: Left Coast, USA
    • Status: offline
    Re: snprintf with format specifier "%.4g" seems not to work (xc1.42 + legacy lib) 2017/10/10 17:28:58 (permalink)
    +1 (1)
    andersm
    XC32 1.44 added Newlib as an option

     
    Yeah, I saw that in the release notes.  I also saw

    This option is primarily intended for applications being ported to XC32 from other compilers that use the Newlib Standard C Library.

     
    So I didn't bother.  Heck,  unless there is a real advantage (a really, really real advantage) to any kind of new stuff, I would happily (or, at least less unhappily) settle for an update that didn't break stuff that I was already using.
     
    Anyhow, just for kicks, after seeing your post, since the project was still fresh in my mind, I started it up again and added -mnewlib-libc to the XC32 global options for my little test program.  This test does a little more, but not much more, than the floating point stuff I reported.  Using newlib resulted in the same (acceptable) "%g" output as the non-legacy-libc.
     
    For this test I am using XC32 version 1.44 in "Free" mode with optimization level 1.
     
    Result: Without legacy-libc and without newlib:
        Program size = 19548 bytes (30% of my MM0064GPL028)
     
    With newlib
        Program size = 55424 bytes (85% of my MM0064GPL028)
     
    This isn't necessarily a show stopper (my "real" project with this chip doesn't use floating point calculations or printing, and I didn't test it without the floating point stuff), but it gives me pause (and makes me fraught).
     
    Bottom line regarding the "%g" format specifier:
    The non-legacy-libc, non-newlib library acts the same as gcc version 4.4.7 on my workstation.  As reported by the OP, the legacy-libc does not.  The newlib might have some advantages that I haven't observed, but then I haven't looked very hard. 
     
    (Ars longa, vita brevis.)
     
     
    Regards,

    Dave
     
    post edited by davekw7x - 2017/10/10 17:37:22

    Sometimes I just can't help myself...
          #SonomaStrong
    #4
    moser
    Super Member
    • Total Posts : 262
    • Reward points : 0
    • Joined: 2015/06/16 02:53:47
    • Location: 0
    • Status: offline
    Re: snprintf with format specifier "%.4g" seems not to work (xc1.42 + legacy lib) 2017/10/13 02:23:08 (permalink)
    +1 (1)
    Thanks to all of you for your responses. The output displayed by Dave is what I wanted and expected to see. And something similar would also have been acceptable in my case.
     
    I have reported the bug to the support now. (Case Number 00255688)
     
     
    The library situation is really sad. I switched to legacy library because some other conversion functions did not work with the normal library, and also because it is now the recommended library. It's getting more and more difficult to keep at least a vague overview which features work with which compiler, and which library, and which compiler settings.  It's not the first time that I think: "An overview table about which features are buggy would be helpful."
     
    The size of Newlib is not really nice, but I think this wouldn't stop me from using it, if it would provide less bugs. And if it is only a bit slower, this would also be still acceptable in my case. But mainly the already quoted sentence about the library doesn't give me a good feeling: "This option is primarily intended for applications being ported to XC32 from other compilers that use the Newlib Standard C Library." Somehow this sounds a bit like there might be other issues or bugs with Newlib, or like this library is really quite inefficient.
    #5
    andersm
    Super Member
    • Total Posts : 2213
    • Reward points : 0
    • Joined: 2012/10/07 14:57:44
    • Location: 0
    • Status: online
    Re: snprintf with format specifier "%.4g" seems not to work (xc1.42 + legacy lib) 2017/10/13 04:33:07 (permalink)
    +1 (1)
    Newlib is by itself a high-quality product, and is deployed in millions of products worldwide. However, the project focuses more on standards compliance and portability, which is why it's not as optimized as some proprietary alternatives. There are forks (like newlib-nano, used by ARM in their GCC toolchain distribution) that provide different tradeoffs.
    #6
    Jump to:
    © 2017 APG vNext Commercial Version 4.5