1 /* s_copysignl.c -- long double version of s_copysign.c.
2  * Conversion to long double by Ulrich Drepper,
3  * Cygnus Support, drepper@cygnus.com.
4  */
5 
6 /*
7  * ====================================================
8  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
9  *
10  * Developed at SunPro, a Sun Microsystems, Inc. business.
11  * Permission to use, copy, modify, and distribute this
12  * software is freely granted, provided that this notice
13  * is preserved.
14  * ====================================================
15  */
16 
17 /*
18  * copysignl(long double x, long double y)
19  * copysignl(x,y) returns a value with the magnitude of x and
20  * with the sign bit of y.
21  */
22 
23 #include <endian.h>
24 #include <stdint.h>
25 
26 #if __FLOAT_WORD_ORDER == BIG_ENDIAN
27 
28 typedef union
29 {
30   long double value;
31   struct
32   {
33     int sign_exponent:16;
34     unsigned int empty:16;
35     uint32_t msw;
36     uint32_t lsw;
37   } parts;
38 } ieee_long_double_shape_type;
39 
40 #endif
41 
42 #if __FLOAT_WORD_ORDER == LITTLE_ENDIAN
43 
44 typedef union
45 {
46   long double value;
47   struct
48   {
49     uint32_t lsw;
50     uint32_t msw;
51     int sign_exponent:16;
52     unsigned int empty:16;
53   } parts;
54 } ieee_long_double_shape_type;
55 
56 #endif
57 
58 /* Get int from the exponent of a long double.  */
59 
60 #define GET_LDOUBLE_EXP(exp,d)					\
61 do {								\
62   ieee_long_double_shape_type ge_u;				\
63   ge_u.value = (d);						\
64   (exp) = ge_u.parts.sign_exponent;				\
65 } while (0)
66 
67 /* Set exponent of a long double from an int.  */
68 
69 #define SET_LDOUBLE_EXP(d,exp)					\
70 do {								\
71   ieee_long_double_shape_type se_u;				\
72   se_u.value = (d);						\
73   se_u.parts.sign_exponent = (exp);				\
74   (d) = se_u.value;						\
75 } while (0)
76 
77 long double copysignl(long double x, long double y);
78 libc_hidden_proto(copysignl);
79 
copysignl(long double x,long double y)80 long double copysignl(long double x, long double y)
81 {
82 	uint32_t es1,es2;
83 	GET_LDOUBLE_EXP(es1,x);
84 	GET_LDOUBLE_EXP(es2,y);
85 	SET_LDOUBLE_EXP(x,(es1&0x7fff)|(es2&0x8000));
86         return x;
87 }
88 
89 libc_hidden_def(copysignl);
90