Getting intermediate results in 64 bits

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Richard Cavell

    Getting intermediate results in 64 bits

    Hi,

    Using GCC on my G4, if I have a calculation like this:

    #include <stdint.h>

    uint64_t a = 0xffff * 0xffff ;

    the result will be clobbered to 32 bits because that's the length of an
    integer. How do I keep all the intermediate steps at 64 bits without
    peppering my operands with (uint64_t) casts?

    It would help if my default sizeof(int) were 8, I guess. How can I
    obtain this?
  • Walter Roberson

    #2
    Re: Getting intermediate results in 64 bits

    In article <d3112c$9hc$1@n nrp.waia.asn.au >,
    Richard Cavell <richardcavell@ mail.com> wrote:[color=blue]
    >Using GCC on my G4, if I have a calculation like this:[/color]
    [color=blue]
    >#include <stdint.h>[/color]
    [color=blue]
    >uint64_t a = 0xffff * 0xffff ;[/color]

    Integral values explicitly specified default to 'int' unless there
    is a type modifier or the context provides reason to use a wider
    type.

    [color=blue]
    >the result will be clobbered to 32 bits because that's the length of an
    >integer. How do I keep all the intermediate steps at 64 bits without
    >peppering my operands with (uint64_t) casts?[/color]

    In terms of code changes, you could use:

    uint64_t a = 0xffff * (unit64_t) 0xffff ;

    or you could use

    uint64_t a = 0xffffLU * 0xffffLU;

    [color=blue]
    >It would help if my default sizeof(int) were 8, I guess. How can I
    >obtain this?[/color]

    That is implimentation specific. The version of gcc that I have handy
    does not list options for the G4; I suggest you check your gcc
    man page under the section "Configurat ion Dependent Options";
    and if you do not find it there then try looking at the .info files
    that a lot of the real documentation is in for FSF products.

    As an example, on MIPS systems (e.g., SGI), there is -mint64

    --
    "I want to make sure [a user] can't get through ... an online
    experience without hitting a Microsoft ad"
    -- Steve Ballmer [Microsoft Chief Executive]

    Comment

    • Ben Pfaff

      #3
      Re: Getting intermediate results in 64 bits

      Richard Cavell <richardcavell@ mail.com> writes:
      [color=blue]
      > Using GCC on my G4, if I have a calculation like this:
      >
      > #include <stdint.h>
      >
      > uint64_t a = 0xffff * 0xffff ;
      >
      > the result will be clobbered to 32 bits because that's the length of
      > an integer. How do I keep all the intermediate steps at 64 bits
      > without peppering my operands with (uint64_t) casts?[/color]

      Designate one operand as type `unsigned long long':
      uint64_t a = 0xffffULL * 0xffff;
      --
      int main(void){char p[]="ABCDEFGHIJKLM NOPQRSTUVWXYZab cdefghijklmnopq rstuvwxyz.\
      \n",*q="kl BIcNBFr.NKEzjwC IxNJC";int i=sizeof p/2;char *strchr();int putchar(\
      );while(*q){i+= strchr(p,*q++)-p;if(i>=(int)si zeof p)i-=sizeof p-1;putchar(p[i]\
      );}return 0;}

      Comment

      • Keith Thompson

        #4
        Re: Getting intermediate results in 64 bits

        roberson@ibd.nr c-cnrc.gc.ca (Walter Roberson) writes:[color=blue]
        > In article <d3112c$9hc$1@n nrp.waia.asn.au >,
        > Richard Cavell <richardcavell@ mail.com> wrote:[color=green]
        >>Using GCC on my G4, if I have a calculation like this:[/color]
        >[color=green]
        >>#include <stdint.h>[/color]
        >[color=green]
        >>uint64_t a = 0xffff * 0xffff ;[/color]
        >
        > Integral values explicitly specified default to 'int' unless there
        > is a type modifier or the context provides reason to use a wider
        > type.[/color]

        The type of an expression is not affected by the context in which it
        appears. (A null pointer constant in a pointer context is the only
        exception I can think of.) If it were, 0xffff and the result of the
        multiplication would inherit the uint64_t type provided by the
        context.

        Very often the result of an expression is implicitly converted to some
        type imposed by its context. For example (assuming 32-bit int),
        given:

        uint64_t a = 0xffff;

        the constant 0xffff is of type int, but the result is implicitly
        converted to uint64_t before being used to initialize a. But these
        context-driven implicit conversions happen only on a single level;
        the uint64_t context in

        uint64_t a = 0xffff * 0xffff;

        affects only the result of the multiplication, not the operands.

        This makes using the fixed-width types in <stdint.h> tricky. You can
        declare everything to be of some fixed size, and never refer to the
        predefined types short, int, long, et al, but the ranges of the
        predefined types can still affect the semantics of your code. The
        language provides suffixes for signed and unsigned long and long long,
        but not for the fixed-width types. Casts are probably the best
        approach (one of the rare cases where casts are useful in portable
        code).

        --
        Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
        San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
        We must do something. This is something. Therefore, we must do this.

        Comment

        • Chris Torek

          #5
          Re: Getting intermediate results in 64 bits

          In article <lnd5t7d41q.fsf @nuthaus.mib.or g>
          Keith Thompson <kst-u@mib.org> wrote:[color=blue]
          >The type of an expression is not affected by the context in which it
          >appears. (A null pointer constant in a pointer context is the only
          >exception I can think of.)[/color]

          I think this is not such a good way to put it. It might be better
          to say something like "contexts are extremely local".
          [color=blue]
          >If it were, 0xffff and the result of the multiplication would
          >inherit the uint64_t type provided by the [result] context[/color]
          [since this was "uint64_t result = expr1 * expr2"].
          [color=blue]
          >Very often the result of an expression is implicitly converted to some
          >type imposed by its context. For example (assuming 32-bit int),
          >given:
          >
          > uint64_t a = 0xffff;
          >
          >the constant 0xffff is of type int, but the result is implicitly
          >converted to uint64_t before being used to initialize a. But these
          >context-driven implicit conversions happen only on a single level;
          >the uint64_t context in
          >
          > uint64_t a = 0xffff * 0xffff;
          >
          >affects only the result of the multiplication, not the operands.[/color]

          Just so: the context is as localized as compiler-ly possible, which
          may often be "more local" than the programmer intends.
          [color=blue]
          >This makes using the fixed-width types in <stdint.h> tricky. You can
          >declare everything to be of some fixed size, and never refer to the
          >predefined types short, int, long, et al, but the ranges of the
          >predefined types can still affect the semantics of your code. ...[/color]

          Indeed. Worse, the "value preserving" rules make the effects of
          widening unpredictable in "questionab ly signed" cases, so that:

          uint16_t a, b, c;
          ...
          if (a >= (b - c))

          gives different results on 16- and 32-bit machines: the former uses
          an unsigned compare, and the latter a signed compare.
          --
          In-Real-Life: Chris Torek, Wind River Systems
          Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
          email: forget about it http://web.torek.net/torek/index.html
          Reading email is like searching for food in the garbage, thanks to spammers.

          Comment

          • websnarf@gmail.com

            #6
            Re: Getting intermediate results in 64 bits

            Richard Cavell wrote:[color=blue]
            > Using GCC on my G4, if I have a calculation like this:[/color]

            Technically GCC and G4 are off topic here. But whatever.
            [color=blue]
            > #include <stdint.h>[/color]

            Wow, lucky you -- you happen to have one of these lying around.
            [color=blue]
            > uint64_t a = 0xffff * 0xffff ;
            >
            > the result will be clobbered to 32 bits because that's the length
            > of an integer. How do I keep all the intermediate steps at 64 bits
            > without peppering my operands with (uint64_t) casts?[/color]

            Actually take a look into stdint.h more closely and you will see:

            uint64_t a = UINT64_C(0xffff ) * UINT64_C(0xffff );

            That's the official way anyhow. Not much better than casting, but it
            works. Of course if we were taking into account that you are using
            gcc, then the answer is a little more simple:

            unsigned long long a = 0xffffull * 0xffffull;

            But then, this is not portable.

            ---
            Paul Hsieh
            Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.



            Comment

            • Keith Thompson

              #7
              Re: Getting intermediate results in 64 bits

              Chris Torek <nospam@torek.n et> writes:[color=blue]
              > In article <lnd5t7d41q.fsf @nuthaus.mib.or g>
              > Keith Thompson <kst-u@mib.org> wrote:[color=green]
              >>The type of an expression is not affected by the context in which it
              >>appears. (A null pointer constant in a pointer context is the only
              >>exception I can think of.)[/color]
              >
              > I think this is not such a good way to put it. It might be better
              > to say something like "contexts are extremely local".[/color]

              Hmm. I still like the way I phrased it.

              Given:

              short a = 10;
              int b = 20;
              long c = 30;

              all three integer constants are of type int. The constant 10 is then
              implicitly converted to type short, and 30 is implicitly converted to
              type long, but I think of the implicit conversions as separate
              operations, not impositions of the context type on the expression.

              --
              Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
              San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
              We must do something. This is something. Therefore, we must do this.

              Comment

              • Old Wolf

                #8
                Re: Getting intermediate results in 64 bits

                Keith Thompson wrote:[color=blue]
                > Chris Torek <nospam@torek.n et> writes:[color=green]
                > > In article <lnd5t7d41q.fsf @nuthaus.mib.or g>
                > > Keith Thompson <kst-u@mib.org> wrote:[color=darkred]
                > >>The type of an expression is not affected by the context in
                > >>which it appears. (A null pointer constant in a pointer[/color][/color]
                > context is the only exception I can think of.)[color=green]
                > >
                > > I think this is not such a good way to put it. It might be better
                > > to say something like "contexts are extremely local".[/color]
                >
                > Hmm. I still like the way I phrased it.
                > Given:
                >
                > short a = 10;
                > int b = 20;
                > long c = 30;
                >
                > all three integer constants are of type int.[/color]

                What did you have in mind with the "A null pointer constant..."
                exception? In

                void *p = 0;
                or
                memset(0, 0, 0);

                the 0s are all ints (which then undergo conversion to pointers).

                Comment

                • Keith Thompson

                  #9
                  Re: Getting intermediate results in 64 bits

                  "Old Wolf" <oldwolf@inspir e.net.nz> writes:[color=blue]
                  > Keith Thompson wrote:[color=green]
                  >> Chris Torek <nospam@torek.n et> writes:[color=darkred]
                  >> > In article <lnd5t7d41q.fsf @nuthaus.mib.or g>
                  >> > Keith Thompson <kst-u@mib.org> wrote:
                  >> >>The type of an expression is not affected by the context in
                  >> >>which it appears. (A null pointer constant in a pointer[/color]
                  >> context is the only exception I can think of.)[color=darkred]
                  >> >
                  >> > I think this is not such a good way to put it. It might be better
                  >> > to say something like "contexts are extremely local".[/color]
                  >>
                  >> Hmm. I still like the way I phrased it.
                  >> Given:
                  >>
                  >> short a = 10;
                  >> int b = 20;
                  >> long c = 30;
                  >>
                  >> all three integer constants are of type int.[/color]
                  >
                  > What did you have in mind with the "A null pointer constant..."
                  > exception? In
                  >
                  > void *p = 0;
                  > or
                  > memset(0, 0, 0);
                  >
                  > the 0s are all ints (which then undergo conversion to pointers).[/color]

                  What I had in mind was not entirely coherent. Null pointer constants
                  are not an exception.

                  --
                  Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
                  San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
                  We must do something. This is something. Therefore, we must do this.

                  Comment

                  • Tim Rentsch

                    #10
                    Re: Getting intermediate results in 64 bits

                    Keith Thompson <kst-u@mib.org> writes:
                    [color=blue]
                    > "Old Wolf" <oldwolf@inspir e.net.nz> writes:[color=green][color=darkred]
                    > >>[snip]
                    > >> > Keith Thompson <kst-u@mib.org> wrote:
                    > >> >>The type of an expression is not affected by the context in
                    > >> >>which it appears. (A null pointer constant in a pointer
                    > >> >>context is the only exception I can think of.)
                    > >>[snip][/color]
                    > >
                    > > What did you have in mind with the "A null pointer constant..."
                    > > exception? [...][/color]
                    >
                    > What I had in mind was not entirely coherent. Null pointer constants
                    > are not an exception.[/color]

                    So what you meant to say was, A null pointer constant in a pointer
                    context is the only exception you can think of, and even that's not an
                    exception? :)

                    On a related topic - would anyone like to opine as to whether

                    int (*pf)(int);
                    pf = (void*)(int*)(v oid*) 0;

                    is permitted by the standard or not? How about

                    pf = (void*)(int*) 0;

                    or

                    pf = (void*)(void*) 0;

                    The statements in 6.3.2.3 p3 and p4 seem to imply that the right hand
                    side expressions are not null pointer constants.

                    Comment

                    • Keith Thompson

                      #11
                      Re: Getting intermediate results in 64 bits

                      Tim Rentsch <txr@alumnus.ca ltech.edu> writes:[color=blue]
                      > Keith Thompson <kst-u@mib.org> writes:[color=green]
                      >> "Old Wolf" <oldwolf@inspir e.net.nz> writes:[/color][/color]
                      [snip][color=blue][color=green][color=darkred]
                      >> > What did you have in mind with the "A null pointer constant..."
                      >> > exception? [...][/color]
                      >>
                      >> What I had in mind was not entirely coherent. Null pointer constants
                      >> are not an exception.[/color]
                      >
                      > So what you meant to say was, A null pointer constant in a pointer
                      > context is the only exception you can think of, and even that's not an
                      > exception? :)[/color]

                      Exactly, except that I didn't think of the "and even that's not an
                      exception" part until later.

                      --
                      Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
                      San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
                      We must do something. This is something. Therefore, we must do this.

                      Comment

                      • Richard Cavell

                        #12
                        Re: Getting intermediate results in 64 bits

                        [color=blue]
                        > Actually take a look into stdint.h more closely and you will see:
                        >
                        > uint64_t a = UINT64_C(0xffff ) * UINT64_C(0xffff );[/color]

                        Does it distribute across any arbitrary number of operands?

                        uint64_t a = UINT64_C ( b + c - d * e % f << 3 ) ;

                        Comment

                        • Christian Kandeler

                          #13
                          Re: Getting intermediate results in 64 bits

                          Richard Cavell wrote:
                          [color=blue][color=green]
                          >> Actually take a look into stdint.h more closely and you will see:
                          >>
                          >> uint64_t a = UINT64_C(0xffff ) * UINT64_C(0xffff );[/color]
                          >
                          > Does it distribute across any arbitrary number of operands?
                          >
                          > uint64_t a = UINT64_C ( b + c - d * e % f << 3 ) ;[/color]

                          It's only for constants.


                          Christian

                          Comment

                          • Christian Kandeler

                            #14
                            Re: Getting intermediate results in 64 bits

                            Richard Cavell wrote:
                            [color=blue][color=green]
                            >> Actually take a look into stdint.h more closely and you will see:
                            >>
                            >> uint64_t a = UINT64_C(0xffff ) * UINT64_C(0xffff );[/color]
                            >
                            > Does it distribute across any arbitrary number of operands?
                            >
                            > uint64_t a = UINT64_C ( b + c - d * e % f << 3 ) ;[/color]

                            It's only for constants.


                            Christian

                            Comment

                            • Dag-Erling Smørgrav

                              #15
                              Re: Getting intermediate results in 64 bits

                              roberson@ibd.nr c-cnrc.gc.ca (Walter Roberson) writes:[color=blue]
                              > uint64_t a = 0xffffLU * 0xffffLU;[/color]

                              This assumes that unsigned long is 64 bits wide.

                              DES
                              --
                              Dag-Erling Smørgrav - des@des.no

                              Comment

                              Working...