public inbox for cygwin@cygwin.com
 help / color / mirror / Atom feed
* FW: Printing long int in C program under cygwin64
@ 2017-05-24 12:18 Carl Fredrik Forsberg
  2017-05-24 12:54 ` bug in lrint [was: FW: Printing long int in C program under cygwin64] Eric Blake
  0 siblings, 1 reply; 16+ messages in thread
From: Carl Fredrik Forsberg @ 2017-05-24 12:18 UTC (permalink / raw)
  To: cygwin

I am experiencing problems printing long int values under cygwin64 installed on a Windows 10 machine.

Below is a test program followed by its output to demonstrate the problem. The program was initially written to demonstrate the output from lrint(), and developed further to demonstrate to myself how negative integers are tackled by printf type specifiers (e.g. %li, %ld etc).

My understanding is that lrint() should return a long int. However I am unable to get printf to print the correct number. Instead its output is treated as an unsigned integer.
Any  help or hints would be much appreciated.

Regards
Carl Fredrik

#include <stdio.h>      /* printf */
#include <math.h>       /* lrint */

int main ()
{
  char text[64];
  printf ( "int -2 = %i\n", -2 );
  printf ( "int -1 = %i\n", -1 );
  printf ( "int 0 = %i\n", 0 );
  printf ( "int 1 = %i\n", 1 );
  printf ( "long int -2 = %li\n", -2 );
  printf ( "long int -1 = %li\n", -1 );
  printf ( "type cast -1 = %li\n", (long int)-1 );
  printf ( "type cast lrint(-1.0) = %li\n", (long int)lrint(-1.0) );
  printf ( "lrint(-1.0) = %li\n", lrint(-1.0) );
  printf ( "lrint(1.0) = %li\n", lrint(1.0) );
  printf ( "long int 0 = %li\n", 0 );
  printf ( "long int 1 = %li\n", 1 );
  sprintf( text,"long int -1 = %li", -1 );
  printf ( "Via sprintf: %s\n", text);
  printf ( "size of long int: %i\n", sizeof(long int));
  printf ( "size of int: %i\n", sizeof(int));
  return 0;
}


compiled by:
gcc lrint_test.c -o lrint_test.exe

Output:

int -2 = -2
int -1 = -1
int 0 = 0
int 1 = 1
long int -2 = 4294967294
long int -1 = 4294967295
type cast -1 = -1
type cast lrint(-1.0) = 4294967295
lrint(-1.0) = 4294967295
lrint(1.0) = 1
long int 0 = 0
long int 1 = 1
Via sprintf: long int -1 = 4294967295
size of long int: 8
size of int: 4



gcc version:
gcc (GCC) 5.4.0
Copyright (C) 2015 Free Software Foundation, Inc.









The confidentiality or integrity of this message can not be guaranteed following transmission on the Internet. The addressee should be aware of this before using the contents of this message.

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 16+ messages in thread
* Re: bug in lrint [was: FW: Printing long int in C program under cygwin64]
@ 2017-06-19 11:09 Carl Fredrik Forsberg
  2017-06-20 11:22 ` Corinna Vinschen
  0 siblings, 1 reply; 16+ messages in thread
From: Carl Fredrik Forsberg @ 2017-06-19 11:09 UTC (permalink / raw)
  To: cygwin

Hello again.
I have performed a few more tests with the program below.
The lrint() family of functions I tested all appear tohave problems with negative numbers. There seem to be an unsigned vs. signed integer problems.

I could not find  cygwin/math/lrint.c  on my Cygwin installation where patches were applied by Corinna Vinschen as discussed below. This probably  reflects that I am not familiar
with processes that go on "behind the scenes".

A workaround I applied to the program was to  add:

#define lrint(x) (long int)(int)lrint(x)

to the program. This seems to work, but I expect it will fail if all the long int digits are needed.

Program:
#include <stdio.h>      /* printf */
#include <math.h>       /* lrint */
// define statement put in here

int main ()
{

  printf ( "long int -1 = %i\n", -1 );
  printf ( "type cast -1 = %li\n", (long int)-1 );
  printf ( "type cast lrint(-1.0) = %li\n", (long int)(int)lrint(-1.0) );
  printf ( "rint(-1.0) = %f\n", rint(-1.0) );
  printf ( "int of rint(-1.4)-0.5 = %i\n", (int)(rint(-1.4) - 0.5) );
  printf ( "lrint(-1.0) = %li\n", lrint(-1.0) );
  printf ( "lrintf(-1.0) = %li\n", lrintf(-1.0) );
  printf ( "lrintl(-1.0) = %li\n", lrintl(-1.0) );
  printf ( "llrintl(-1.0) = %lli\n", llrintl(-1.0) );

  printf ( "(int)lrint(-1.0) = %i\n", (int)lrint(-1.0) );
  printf ( "Typecasting llrint(-1.0) = %lli\n", (long long)(int)llrint(-1.0) );
  printf ( "lrint(1.0) = %li\n", lrint(1.0) );
  printf ( "llrint(1.0) = %lli\n", llrint(1.0) );
  printf ( "Type cast long long unsigned -1.0 = %llu\n", (unsigned long long)-1 );
  return 0;
}

/*compiled by:
gcc -Wall lrint_test.c -o lrint_test.exe

Result:

long int -1 = -1
type cast -1 = -1
type cast lrint(-1.0) = -1
rint(-1.0) = -1.000000
int of rint(-1.4)-0.5 = -1
lrint(-1.0) = 4294967295
lrintf(-1.0) = 4294967295
lrintl(-1.0) = 4294967295
(int)lrint(-1.0) = -1
Typecasting llrint(-1.0) = -1
lrint(1.0) = 1
llrint(1.0) = 1
Type cast long long unsigned -1.0 = 18446744073709551615

Result with #define statement above.
long int -1 = -1
type cast -1 = -1
type cast lrint(-1.0) = -1
rint(-1.0) = -1.000000
int of rint(-1.4)-0.5 = -1
lrint(-1.0) = -1
lrintf(-1.0) = 4294967295
lrintl(-1.0) = 4294967295
llrintl(-1.0) = 4294967295
(int)lrint(-1.0) = -1
Typecasting llrint(-1.0) = -1
lrint(1.0) = 1
llrint(1.0) = 1
Type cast long long unsigned -1.0 = 18446744073709551615

gcc version:
gcc (GCC) 5.4.0
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.*/

On May 24 07:33, Eric Blake wrote:
> On 05/24/2017 07:00 AM, Carl Fredrik Forsberg wrote:
> > type cast lrint(-1.0) = 4294967295
>
> Now that's an interesting one - it may be that cygwin1.dll actually has
> buggy behavior in lrint().  In the source code, cygwin/math/lrint.c is
> dropping down to assembly; it could very well be that the assembly code
> is incorrectly truncating things at 32 bits (where it is just fine for
> 32-bit Cygwin, but wrong for 64-bit):
>
> long lrint (double x)
> {
>   long retval = 0L;
> #if defined(_AMD64_) || defined(__x86_64__) || defined(_X86_) ||
> defined(__i386__)
>   __asm__ __volatile__ ("fistpl %0"  : "=m" (retval) : "t" (x) : "st");
> #elif defined(__arm__) || defined(_ARM_)
>     retval = __lrint_internal(x);
> #endif
>   return retval;
> }
>
> But I'm not an assembly coding expert, so perhaps someone else will spot
> the fix faster.

I just applied a patch to fix this.  Using fistpl is fine and dandy for
Mingw because sizeof(long) == 4, but on 64 bit Cygwin this function
has to use fistpll to account for sizeof(long) == 8.


Thanks,
Corinna

--
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Maintainer                 cygwin AT cygwin DOT com
Red Hat
The confidentiality or integrity of this message can not be guaranteed following transmission on the Internet. The addressee should be aware of this before using the contents of this message.

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2017-06-20 11:22 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-24 12:18 FW: Printing long int in C program under cygwin64 Carl Fredrik Forsberg
2017-05-24 12:54 ` bug in lrint [was: FW: Printing long int in C program under cygwin64] Eric Blake
2017-05-24 16:53   ` Erik Bray
2017-05-24 16:57     ` Erik Bray
2017-05-24 17:40       ` Eric Blake
2017-05-24 21:19         ` Carl Fredrik Forsberg
2017-05-26 12:05         ` Erik Bray
2017-05-25  1:31   ` Steven Penny
2017-05-25  7:50     ` Steven Penny
2017-05-25 17:34       ` Brian Inglis
2017-05-25 19:25     ` Eric Blake
2017-05-26  1:53       ` Steven Penny
2017-05-26  5:01         ` Steven Penny
2017-06-07  9:10   ` Corinna Vinschen
2017-06-19 11:09 Carl Fredrik Forsberg
2017-06-20 11:22 ` Corinna Vinschen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).