Double to 64-bit integer conversion.
[kopensolaris-gnu/glibc.git] / sysdeps / wordsize-32 / fixdfdi.c
1 /* Convert double to 64-bit int.
2    Copyright (C) 1989, 1992-2001, 2002 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <endian.h>
21 #include <stdlib.h>
22 #include <bits/wordsize.h>
23 #include <shlib-compat.h>
24
25 #if __WORDSIZE != 32
26 # error This is for 32-bit targets only
27 #endif
28
29 #if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2_6)
30
31 typedef unsigned int UQItype    __attribute__ ((mode (QI)));
32 typedef          int SItype     __attribute__ ((mode (SI)));
33 typedef unsigned int USItype    __attribute__ ((mode (SI)));
34 typedef          int DItype     __attribute__ ((mode (DI)));
35 typedef unsigned int UDItype    __attribute__ ((mode (DI)));
36 typedef         float SFtype    __attribute__ ((mode (SF)));
37 typedef         float DFtype    __attribute__ ((mode (DF)));
38 #define Wtype SItype
39 #define HWtype SItype
40 #define DWtype DItype
41 #define UWtype USItype
42 #define UHWtype USItype
43 #define UDWtype UDItype
44 #define W_TYPE_SIZE 32
45
46 #include <stdlib/longlong.h>
47
48 #if __BYTE_ORDER == __BIG_ENDIAN
49 struct DWstruct { Wtype high, low;};
50 #elif __BYTE_ORDER == __LITTLE_ENDIAN
51 struct DWstruct { Wtype low, high;};
52 #else
53 #error Unhandled endianity
54 #endif
55 typedef union { struct DWstruct s; DWtype ll; } DWunion;
56
57 #define WORD_SIZE __WORDSIZE
58 #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
59
60 DWtype
61 ___fixunsdfdi (DFtype a)
62 {
63   DFtype b;
64   UDWtype v;
65
66   if (a < 0)
67     return 0;
68
69   /* Compute high word of result, as a flonum.  */
70   b = (a / HIGH_WORD_COEFF);
71   /* Convert that to fixed (but not to DWtype!),
72      and shift it into the high word.  */
73   v = (UWtype) b;
74   v <<= WORD_SIZE;
75   /* Remove high part from the DFtype, leaving the low part as flonum.  */
76   a -= (DFtype)v;
77   /* Convert that to fixed (but not to DWtype!) and add it in.
78      Sometimes A comes out negative.  This is significant, since
79      A has more bits than a long int does.  */
80   if (a < 0)
81     v -= (UWtype) (- a);
82   else
83     v += (UWtype) a;
84   return v;
85 }
86 symbol_version (___fixunsdfdi, __fixunsdfdi, GLIBC_2.0);
87
88
89 DWtype
90 ___fixdfdi (DFtype a)
91 {
92   if (a < 0)
93     return - __fixunsdfdi (-a);
94   return __fixunsdfdi (a);
95 }
96 symbol_version (___fixdfdi, __fixdfdi, GLIBC_2.0);
97
98 #endif