2 /* { dg-require-effective-target int32plus } */
4 #define PART_PRECISION (sizeof (cpp_num_part) * 8)
6 typedef unsigned int cpp_num_part
;
7 typedef struct cpp_num cpp_num
;
12 int unsignedp
; /* True if value should be treated as unsigned. */
13 int overflow
; /* True if the most recent calculation overflowed. */
17 num_positive (cpp_num num
, unsigned int precision
)
19 if (precision
> PART_PRECISION
)
21 precision
-= PART_PRECISION
;
22 return (num
.high
& (cpp_num_part
) 1 << (precision
- 1)) == 0;
25 return (num
.low
& (cpp_num_part
) 1 << (precision
- 1)) == 0;
29 num_trim (cpp_num num
, unsigned int precision
)
31 if (precision
> PART_PRECISION
)
33 precision
-= PART_PRECISION
;
34 if (precision
< PART_PRECISION
)
35 num
.high
&= ((cpp_num_part
) 1 << precision
) - 1;
39 if (precision
< PART_PRECISION
)
40 num
.low
&= ((cpp_num_part
) 1 << precision
) - 1;
47 /* Shift NUM, of width PRECISION, right by N bits. */
49 num_rshift (cpp_num num
, unsigned int precision
, unsigned int n
)
51 cpp_num_part sign_mask
;
52 int x
= num_positive (num
, precision
);
54 if (num
.unsignedp
|| x
)
57 sign_mask
= ~(cpp_num_part
) 0;
60 num
.high
= num
.low
= sign_mask
;
64 if (precision
< PART_PRECISION
)
65 num
.high
= sign_mask
, num
.low
|= sign_mask
<< precision
;
66 else if (precision
< 2 * PART_PRECISION
)
67 num
.high
|= sign_mask
<< (precision
- PART_PRECISION
);
69 if (n
>= PART_PRECISION
)
78 num
.low
= (num
.low
>> n
) | (num
.high
<< (PART_PRECISION
- n
));
79 num
.high
= (num
.high
>> n
) | (sign_mask
<< (PART_PRECISION
- n
));
83 num
= num_trim (num
, precision
);
87 #define num_zerop(num) ((num.low | num.high) == 0)
88 #define num_eq(num1, num2) (num1.low == num2.low && num1.high == num2.high)
91 num_lshift (cpp_num num
, unsigned int precision
, unsigned int n
)
95 num
.overflow
= !num
.unsignedp
&& !num_zerop (num
);
96 num
.high
= num
.low
= 0;
104 if (m
>= PART_PRECISION
)
112 num
.high
= (num
.high
<< m
) | (num
.low
>> (PART_PRECISION
- m
));
115 num
= num_trim (num
, precision
);
121 cpp_num maybe_orig
= num_rshift (num
, precision
, n
);
122 num
.overflow
= !num_eq (orig
, maybe_orig
);
129 unsigned int precision
= 64;
132 cpp_num num
= { 0, 3, 0, 0 };
136 cpp_num res
= num_lshift (num
, 64, n
);
138 if (res
.low
!= 0x30000)
144 if (res
.overflow
!= 0)