• AVR Freaks

Hot!Division with XC8

Page: 12 > Showing page 1 of 2
Author
hakelm
Starting Member
  • Total Posts : 50
  • Reward points : 0
  • Joined: 2008/02/09 07:15:09
  • Location: 0
  • Status: offline
2019/08/30 07:27:14 (permalink)
0

Division with XC8

I am trying to get XC8 to compute a constant for me with:
#define vmax 300
const unsigned int limit=(vmax*1023)/500;
this returns limit = 0xFFD7  instead of the expected 0x265
 
If I on the other hand do: 
const unsigned int vmax=300;
const unsigned int limit=(vmax*1023)/500;
I get a limit of 0x59 
(GCC, however, returns the correct result with the two examples above.)
 
If I do:
const uint32_t vmax=300;
const uint32_t tmp=(vmax*1023)/500;
const uint16_t limit=(uint16_t) tmp;
I get the correct result.
 
What is it that I haven't grasped?
H
 
#1

20 Replies Related Threads

    mkwahler
    Junior Member
    • Total Posts : 19
    • Reward points : 0
    • Joined: 2012/10/09 12:27:33
    • Location: 0
    • Status: offline
    Re: Division with XC8 2019/08/30 07:44:49 (permalink)
    +1 (1)
    300 * 1023 == 306900
     
    2^8   - 1 == 255
    2^16 - 1 == 65535
    2^32 - 1 == 4294967296
     
    What is sizeof(unsigned int)?
    #2
    Chris A
    Super Member
    • Total Posts : 839
    • Reward points : 0
    • Joined: 2010/07/20 04:37:07
    • Location: 0
    • Status: offline
    Re: Division with XC8 2019/08/30 07:52:21 (permalink)
    +1 (1)
    Its using 16bit maths as you have told it too!
     
    #define vmax 300L

    Will be enough to fix it. But you should be doing:
    #define vmax 300L
    const unsigned int limit=(vmax*1023L)/500L;

    Maybe you should also check that the calculation result will actually fit in 16 bit!
    #3
    Gort2015
    Klaatu Barada Nikto
    • Total Posts : 3266
    • Reward points : 0
    • Joined: 2015/04/30 10:49:57
    • Location: 0
    • Status: online
    Re: Division with XC8 2019/08/30 07:54:28 (permalink)
    0
    #define vmax 300ul ;*** unsigned long ***
    #define limit (vmax * 1023ul / 500ul)  ; 613
    #define big (limit * 1000ul)    ; 613,000
     
    uint16_t L = big & -1, H = big >> 16
     
    "#define" is used for macro or insertion code, it does not return any type.
     
    No need for , "const" in this case.
     
     
     
     
     
     
    post edited by Gort2015 - 2019/08/30 07:58:08

    MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
    https://www.youtube.com/watch?v=Iu1qa8N2ID0
    + ST:Continues, "What Ships are Made for", Q's back.
    #4
    du00000001
    Just Some Member
    • Total Posts : 3050
    • Reward points : 0
    • Joined: 2016/05/03 13:52:42
    • Location: Germany
    • Status: offline
    Re: Division with XC8 2019/08/30 07:57:42 (permalink)
    +1 (1)
    hakelm
    What is it that I haven't grasped?

    What you didn't get?
    1023 * 300 = 0x4AED4 > 65536, making an uint16_t overflow (int16_t performs even worse).
    Not sure about the 0xFFD7 - equalling -41, but the 0x59 (89d) is a result from dividing AED4 by 500.
     
    I'd expect
    #define vmax 300UL
    const unsigned int limit=(uint16_t)(vmax*1023)/500;

    and some variants of this to yield the correct result as well.
     
    GCC might not be quite as picky with respect to type conversions.
    For constant expressions I personally would expect the compiler to calculate all this on the PC side with 32 or 64 Bits default types. Might not be completely according to the doctrine, but this would be what I expect. (Got this in the good old times on 32 Bit PC CPUs with 32 Bit targets. With 64 Bit PC CPUs one might expect a 64 Bit numerical range.)
     
    And for all those "followers of the doctrine" and pea counters:
    as this calculation is made on the PC, I'd expect the PC's implicit type conversions - not those of the later target !

    PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
    #5
    hakelm
    Starting Member
    • Total Posts : 50
    • Reward points : 0
    • Joined: 2008/02/09 07:15:09
    • Location: 0
    • Status: offline
    Re: Division with XC8 2019/08/30 08:08:29 (permalink)
    -1 (1)
    I understand that, but it is beside the point.
    When evaluating a constant expression the compiler shouldn't try to make any unnecessary guesses about the types of the constituent parts. GCC and most other languages has no problem with this, try for instance:
    int main() {
    #define d 23456789999
    #define n 12345678999
    const unsigned int limit=d/n;
    printf("%d", limit);
    }
    In my opinion this is limitation of or a bug in the XC8.
    H
    #6
    du00000001
    Just Some Member
    • Total Posts : 3050
    • Reward points : 0
    • Joined: 2016/05/03 13:52:42
    • Location: Germany
    • Status: offline
    Re: Division with XC8 2019/08/30 08:25:17 (permalink)
    0
    It's not a bug - it's just following the C rules for type propagation. With an "integer" defined as int16_t. Perfect for an 8-Bit controller.
     
    On the other hand, gcc is a bit reluctant about type propagation: a 32-Bit integer is not reasonable for an 8-Bitter.
     
    "Most other languages ...": which languages and which targets are you talking about ?

    PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
    #7
    NKurzman
    A Guy on the Net
    • Total Posts : 17817
    • Reward points : 0
    • Joined: 2008/01/16 19:33:48
    • Location: 0
    • Status: online
    Re: Division with XC8 2019/08/30 08:43:03 (permalink)
    +1 (1)
     GCC and most other languages???  On what CPU?  a 32or 64 bit one?  Yes your code will work on a 32 or 64 Bit CPU.
    Those are the Rules of the C Programming Language (which XC8 follows more closely than GCC does).  IF you plan to program in C you should be aware it's rules
     
    C sees:
    const unsigned int limit=(vmax*1023)/500;
    as (16 bit signed int * 16 bit signed int) / 16 bit signed int;
    and 300 * 1023 will not fit in a 16 bit signed int. 
    #8
    1and0
    Access is Denied
    • Total Posts : 9699
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Division with XC8 2019/08/30 09:03:11 (permalink)
    +1 (1)
    hakelm
    I understand that, but it is beside the point.
    When evaluating a constant expression the compiler shouldn't try to make any unnecessary guesses about the types of the constituent parts. GCC and most other languages has no problem with this, try for instance:
    ...
    In my opinion this is limitation of or a bug in the XC8.

    From the C language standard:
    ISO/IEC 9899:1999 §6.6/4
    Each constant expression shall evaluate to a constant that is in the range of representable values for its type.

     
    hakelm
    What is it that I haven't grasped?

    300 * 1023 = 306900 = 0x4AED4.  In 16-bit, it is 0xAED4.
     

    I am trying to get XC8 to compute a constant for me with:
    #define vmax 300
    const unsigned int limit=(vmax*1023)/500;
    this returns limit = 0xFFD7  instead of the expected 0x265

    300 is int16_t and 1023 is int16_t, so the result is int16_t; 0xAED4 = -20780 and -20780/500 = -41 = 0xFFD7.
     

    If I on the other hand do: 
    const unsigned int vmax=300;
    const unsigned int limit=(vmax*1023)/500;
    I get a limit of 0x59 

    300 is uint16_t and 1023 is int16_t, so the result is uint16_t; 0xAED4 = 44756 and 44756/500 = 89 = 0x59.
     

    (GCC, however, returns the correct result with the two examples above.)

    GCC is not exactly standard compliant.
     
    #9
    mkwahler
    Junior Member
    • Total Posts : 19
    • Reward points : 0
    • Joined: 2012/10/09 12:27:33
    • Location: 0
    • Status: offline
    Re: Division with XC8 2019/08/30 09:05:27 (permalink)
    +1 (1)
    hakelm
    I understand that, but it is beside the point.

    It's exactly the point.
    hakelm
    When evaluating a constant expression the compiler shouldn't try to make any unnecessary guesses about the types of the constituent parts.

    The compiler is *required* (by the ISO C standard), to evaluate literal values as certain types (determined by their value), according to the language rules. (which essentially say "the smallest type that can represent the value.", and that the 'smallest type' to be used is 'int').  There are also rules about operations between different types, e.g. signed/unsigned, int/long int, etc.

    hakelm
    GCC and most other languages has no problem with this,

    GCC is not a language, it's a collection of compilers (GCC ==GNU Compiler Collection), which includes translators for C, and at least five other programming languages.
    This misunderstanding might begin to explain your confusion about the C language, and seemingly about the difference between a language and a translator (aka 'compiler')
     
    Also, compilers for 'most other languages' would fail to compile your code at all, since most^H^H^H^H all 'other languages', by definition, are not C.
     

    hakelm
    try for instance:
    int main() {
    #define d
    #define n 12345678999
    const unsigned int limit=d/n;
    printf("%d", limit);
    }
     
    In my opinion this is limitation of or a bug in the XC8.
    H
     

    This is a (necessary) limitation of the C language (all computer languages have limitations, since computers are finite machines).
     
    On which platform did you run the GCC?  A PC?  Note that the size of a data type (e.g. 'unsigned int') depends upon the compiler and target platform (subject to minima dictated by the language standard).
     
    The value 23456789999 requires 35 bits to store.
    The value12345678999 requires 34 bits to store.
     
    How many bits in an unsigned int in XC8? Certainly not >= 35.  The C standard only requires it have a minimum range from 0 to 65535 (but allows a larger range).
     
    See the 'sizeof' operator to programmatically determine the size of a type or object (in bytes).  Note that this value will NOT necessarily be the same for the same C types on different compilers and/or platforms.  That's why we have the 'sizeof' operator, as well as the items in the standard header <limits.h>
     
    -Mike
     
     
    #10
    1and0
    Access is Denied
    • Total Posts : 9699
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Division with XC8 2019/08/30 09:20:24 (permalink)
    +1 (1)
    hakelm
    ... try for instance:
    int main() {
    #define d 23456789999
    #define n 12345678999
    const unsigned int limit=d/n;
    printf("%d", limit);
    }
    In my opinion this is limitation of or a bug in the XC8.

    For XC8 an int type is 16-bit.  The size of int is different on different platforms. The C language requires:
    • signed int -- contains at least the [-32,767, +32,767] range; thus, it is at least 16 bits in size.
    • unsigned int -- contains at least the [0, 65,535] range.
     
    #11
    Gort2015
    Klaatu Barada Nikto
    • Total Posts : 3266
    • Reward points : 0
    • Joined: 2015/04/30 10:49:57
    • Location: 0
    • Status: online
    Re: Division with XC8 2019/08/30 09:49:32 (permalink)
    -1 (1)
    Didn't want to be picky but it's
    signed int: -32768 to 32767.

    MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
    https://www.youtube.com/watch?v=Iu1qa8N2ID0
    + ST:Continues, "What Ships are Made for", Q's back.
    #12
    andersm
    Super Member
    • Total Posts : 2651
    • Reward points : 0
    • Joined: 2012/10/07 14:57:44
    • Location: 0
    • Status: offline
    Re: Division with XC8 2019/08/30 10:10:11 (permalink)
    +1 (1)
    Gort2015
    Didn't want to be picky but it's
    signed int: -32768 to 32767.

    The C standard does not assume two's complement, so if defines INT_MIN to be at least -32767.
    #13
    1and0
    Access is Denied
    • Total Posts : 9699
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Division with XC8 2019/08/30 10:13:04 (permalink)
    +1 (1)
    Gort2015
    Didn't want to be picky but it's
    signed int: -32768 to 32767.

    From the C language standard:
    ISO/IEC 9899:1999 Annex E
    #define INT_MAX     +32767
    #define INT_MIN     -32767

    The key word being at least. LoL: LoL
     
     
    #14
    NKurzman
    A Guy on the Net
    • Total Posts : 17817
    • Reward points : 0
    • Joined: 2008/01/16 19:33:48
    • Location: 0
    • Status: online
    Re: Division with XC8 2019/08/30 10:34:46 (permalink)
    +1 (1)
    To the OP get familiar with the terms “implementation defined Behavior” and “Standards Compliant” your problem is your preconceived ideas. The first is that all C compilers work the same exact way as GCC does on your computer. You should be asking what the rule are , not demanding they change to your liking.
    #15
    du00000001
    Just Some Member
    • Total Posts : 3050
    • Reward points : 0
    • Joined: 2016/05/03 13:52:42
    • Location: Germany
    • Status: offline
    Re: Division with XC8 2019/08/30 12:28:11 (permalink)
    0
    Just to demonstrate some pickiness:
    strictly spoken -32768 is less than -32767, thus not covered by at least.  grin: grin
     
    It might be a valid attempt to represent such #defines (if only used to calculate further constants) as float, casting the result to the data type required. In the past, I had the pleasure to observe repeated overflows, stemming from the ever-increasing clock rate of some system. Float calculations might have been able to prevent most of these overflows.

    PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
    #16
    1and0
    Access is Denied
    • Total Posts : 9699
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Division with XC8 2019/08/30 12:58:10 (permalink)
    +1 (1)
    du00000001
    Just to demonstrate some pickiness:
    strictly spoken -32768 is less than -32767, thus not covered by at least

    Contains at least the [-32,767, +32,767] range; so the range [-32,768, +32,767] does contain that range. grin: grin
    #17
    Gort2015
    Klaatu Barada Nikto
    • Total Posts : 3266
    • Reward points : 0
    • Joined: 2015/04/30 10:49:57
    • Location: 0
    • Status: online
    Re: Division with XC8 2019/08/30 14:41:50 (permalink)
    0
    "#define INT_MIN     -32767"
    If you were a nube though.
     
    #define MIN_BINARY_VALUE     0
    #define MAX_BINARY_VALUE     1

    MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
    https://www.youtube.com/watch?v=Iu1qa8N2ID0
    + ST:Continues, "What Ships are Made for", Q's back.
    #18
    1and0
    Access is Denied
    • Total Posts : 9699
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Division with XC8 2019/08/30 15:04:04 (permalink)
    +1 (1)
    Gort2015
    "#define INT_MIN     -32767"
    If you were a nube though.

    Actually XC8 defines it as
    #define INT_MIN  (int)-32768

    and
    #define INT_MIN  (-INT_MAX-1)

     

    #define MIN_BINARY_VALUE     0
    #define MAX_BINARY_VALUE     1

    That would be assuming unsigned binary. ;)  Anyway, standard C does not define binary constants.
     
    post edited by 1and0 - 2019/08/30 15:06:38
    #19
    Gort2015
    Klaatu Barada Nikto
    • Total Posts : 3266
    • Reward points : 0
    • Joined: 2015/04/30 10:49:57
    • Location: 0
    • Status: online
    Re: Division with XC8 2019/08/30 15:18:38 (permalink)
    0
    I made that last part up but you see worst on here.

    MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
    https://www.youtube.com/watch?v=Iu1qa8N2ID0
    + ST:Continues, "What Ships are Made for", Q's back.
    #20
    Page: 12 > Showing page 1 of 2
    Jump to:
    © 2019 APG vNext Commercial Version 4.5