dfp-bit.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  1. /* This is a software decimal floating point library.
  2. Copyright (C) 2005-2022 Free Software Foundation, Inc.
  3. This file is part of GCC.
  4. GCC is free software; you can redistribute it and/or modify it under
  5. the terms of the GNU General Public License as published by the Free
  6. Software Foundation; either version 3, or (at your option) any later
  7. version.
  8. GCC is distributed in the hope that it will be useful, but WITHOUT ANY
  9. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10. FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  11. for more details.
  12. Under Section 7 of GPL version 3, you are granted additional
  13. permissions described in the GCC Runtime Library Exception, version
  14. 3.1, as published by the Free Software Foundation.
  15. You should have received a copy of the GNU General Public License and
  16. a copy of the GCC Runtime Library Exception along with this program;
  17. see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  18. <http://www.gnu.org/licenses/>. */
  19. /* This implements IEEE 754 decimal floating point arithmetic, but
  20. does not provide a mechanism for setting the rounding mode, or for
  21. generating or handling exceptions. Conversions between decimal
  22. floating point types and other types depend on C library functions.
  23. Contributed by Ben Elliston <bje@au.ibm.com>. */
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. /* FIXME: compile with -std=gnu99 to get these from stdlib.h */
  27. extern float strtof (const char *, char **);
  28. extern long double strtold (const char *, char **);
  29. #include <string.h>
  30. #include <limits.h>
  31. #include "dfp-bit.h"
  32. /* Forward declarations. */
  33. #if WIDTH == 32 || WIDTH_TO == 32
  34. void __host_to_ieee_32 (_Decimal32 in, decimal32 *out);
  35. void __ieee_to_host_32 (decimal32 in, _Decimal32 *out);
  36. #endif
  37. #if WIDTH == 64 || WIDTH_TO == 64
  38. void __host_to_ieee_64 (_Decimal64 in, decimal64 *out);
  39. void __ieee_to_host_64 (decimal64 in, _Decimal64 *out);
  40. #endif
  41. #if WIDTH == 128 || WIDTH_TO == 128
  42. void __host_to_ieee_128 (_Decimal128 in, decimal128 *out);
  43. void __ieee_to_host_128 (decimal128 in, _Decimal128 *out);
  44. #endif
  45. /* A pointer to a binary decFloat operation. */
  46. typedef decFloat* (*dfp_binary_func)
  47. (decFloat *, const decFloat *, const decFloat *, decContext *);
  48. /* Binary operations. */
  49. /* Use a decFloat (decDouble or decQuad) function to perform a DFP
  50. binary operation. */
  51. static inline decFloat
  52. dfp_binary_op (dfp_binary_func op, decFloat arg_a, decFloat arg_b)
  53. {
  54. decFloat result;
  55. decContext context;
  56. decContextDefault (&context, CONTEXT_INIT);
  57. DFP_INIT_ROUNDMODE (context.round);
  58. /* Perform the operation. */
  59. op (&result, &arg_a, &arg_b, &context);
  60. if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
  61. {
  62. /* decNumber exception flags we care about here. */
  63. int ieee_flags;
  64. int dec_flags = DEC_IEEE_854_Division_by_zero | DEC_IEEE_854_Inexact
  65. | DEC_IEEE_854_Invalid_operation | DEC_IEEE_854_Overflow
  66. | DEC_IEEE_854_Underflow;
  67. dec_flags &= context.status;
  68. ieee_flags = DFP_IEEE_FLAGS (dec_flags);
  69. if (ieee_flags != 0)
  70. DFP_HANDLE_EXCEPTIONS (ieee_flags);
  71. }
  72. return result;
  73. }
  74. #if WIDTH == 32
  75. /* The decNumber package doesn't provide arithmetic for decSingle (32 bits);
  76. convert to decDouble, use the operation for that, and convert back. */
  77. static inline _Decimal32
  78. d32_binary_op (dfp_binary_func op, _Decimal32 arg_a, _Decimal32 arg_b)
  79. {
  80. union { _Decimal32 c; decSingle f; } a32, b32, res32;
  81. decDouble a, b, res;
  82. decContext context;
  83. /* Widen the operands and perform the operation. */
  84. a32.c = arg_a;
  85. b32.c = arg_b;
  86. decSingleToWider (&a32.f, &a);
  87. decSingleToWider (&b32.f, &b);
  88. res = dfp_binary_op (op, a, b);
  89. /* Narrow the result, which might result in an underflow or overflow. */
  90. decContextDefault (&context, CONTEXT_INIT);
  91. DFP_INIT_ROUNDMODE (context.round);
  92. decSingleFromWider (&res32.f, &res, &context);
  93. if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
  94. {
  95. /* decNumber exception flags we care about here. */
  96. int ieee_flags;
  97. int dec_flags = DEC_IEEE_854_Inexact | DEC_IEEE_854_Overflow
  98. | DEC_IEEE_854_Underflow;
  99. dec_flags &= context.status;
  100. ieee_flags = DFP_IEEE_FLAGS (dec_flags);
  101. if (ieee_flags != 0)
  102. DFP_HANDLE_EXCEPTIONS (ieee_flags);
  103. }
  104. return res32.c;
  105. }
  106. #else
  107. /* decFloat operations are supported for decDouble (64 bits) and
  108. decQuad (128 bits). The bit patterns for the types are the same. */
  109. static inline DFP_C_TYPE
  110. dnn_binary_op (dfp_binary_func op, DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
  111. {
  112. union { DFP_C_TYPE c; decFloat f; } a, b, result;
  113. a.c = arg_a;
  114. b.c = arg_b;
  115. result.f = dfp_binary_op (op, a.f, b.f);
  116. return result.c;
  117. }
  118. #endif
  119. /* Comparison operations. */
  120. /* Use a decFloat (decDouble or decQuad) function to perform a DFP
  121. comparison. */
  122. static inline CMPtype
  123. dfp_compare_op (dfp_binary_func op, decFloat arg_a, decFloat arg_b)
  124. {
  125. decContext context;
  126. decFloat res;
  127. int result;
  128. decContextDefault (&context, CONTEXT_INIT);
  129. DFP_INIT_ROUNDMODE (context.round);
  130. /* Perform the comparison. */
  131. op (&res, &arg_a, &arg_b, &context);
  132. if (DEC_FLOAT_IS_SIGNED (&res))
  133. result = -1;
  134. else if (DEC_FLOAT_IS_ZERO (&res))
  135. result = 0;
  136. else if (DEC_FLOAT_IS_NAN (&res))
  137. result = -2;
  138. else
  139. result = 1;
  140. return (CMPtype) result;
  141. }
  142. #if WIDTH == 32
  143. /* The decNumber package doesn't provide comparisons for decSingle (32 bits);
  144. convert to decDouble, use the operation for that, and convert back. */
  145. static inline CMPtype
  146. d32_compare_op (dfp_binary_func op, _Decimal32 arg_a, _Decimal32 arg_b)
  147. {
  148. union { _Decimal32 c; decSingle f; } a32, b32;
  149. decDouble a, b;
  150. a32.c = arg_a;
  151. b32.c = arg_b;
  152. decSingleToWider (&a32.f, &a);
  153. decSingleToWider (&b32.f, &b);
  154. return dfp_compare_op (op, a, b);
  155. }
  156. #else
  157. /* decFloat comparisons are supported for decDouble (64 bits) and
  158. decQuad (128 bits). The bit patterns for the types are the same. */
  159. static inline CMPtype
  160. dnn_compare_op (dfp_binary_func op, DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
  161. {
  162. union { DFP_C_TYPE c; decFloat f; } a, b;
  163. a.c = arg_a;
  164. b.c = arg_b;
  165. return dfp_compare_op (op, a.f, b.f);
  166. }
  167. #endif
  168. #if defined(L_conv_sd)
  169. void
  170. __host_to_ieee_32 (_Decimal32 in, decimal32 *out)
  171. {
  172. memcpy (out, &in, 4);
  173. }
  174. void
  175. __ieee_to_host_32 (decimal32 in, _Decimal32 *out)
  176. {
  177. memcpy (out, &in, 4);
  178. }
  179. #endif /* L_conv_sd */
  180. #if defined(L_conv_dd)
  181. void
  182. __host_to_ieee_64 (_Decimal64 in, decimal64 *out)
  183. {
  184. memcpy (out, &in, 8);
  185. }
  186. void
  187. __ieee_to_host_64 (decimal64 in, _Decimal64 *out)
  188. {
  189. memcpy (out, &in, 8);
  190. }
  191. #endif /* L_conv_dd */
  192. #if defined(L_conv_td)
  193. void
  194. __host_to_ieee_128 (_Decimal128 in, decimal128 *out)
  195. {
  196. memcpy (out, &in, 16);
  197. }
  198. void
  199. __ieee_to_host_128 (decimal128 in, _Decimal128 *out)
  200. {
  201. memcpy (out, &in, 16);
  202. }
  203. #endif /* L_conv_td */
  204. #if defined(L_addsub_sd) || defined(L_addsub_dd) || defined(L_addsub_td)
  205. DFP_C_TYPE
  206. DFP_ADD (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
  207. {
  208. return DFP_BINARY_OP (DEC_FLOAT_ADD, arg_a, arg_b);
  209. }
  210. DFP_C_TYPE
  211. DFP_SUB (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
  212. {
  213. return DFP_BINARY_OP (DEC_FLOAT_SUBTRACT, arg_a, arg_b);
  214. }
  215. #endif /* L_addsub */
  216. #if defined(L_mul_sd) || defined(L_mul_dd) || defined(L_mul_td)
  217. DFP_C_TYPE
  218. DFP_MULTIPLY (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
  219. {
  220. return DFP_BINARY_OP (DEC_FLOAT_MULTIPLY, arg_a, arg_b);
  221. }
  222. #endif /* L_mul */
  223. #if defined(L_div_sd) || defined(L_div_dd) || defined(L_div_td)
  224. DFP_C_TYPE
  225. DFP_DIVIDE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
  226. {
  227. return DFP_BINARY_OP (DEC_FLOAT_DIVIDE, arg_a, arg_b);
  228. }
  229. #endif /* L_div */
  230. #if defined (L_eq_sd) || defined (L_eq_dd) || defined (L_eq_td)
  231. CMPtype
  232. DFP_EQ (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
  233. {
  234. CMPtype stat;
  235. stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
  236. /* For EQ return zero for true, nonzero for false. */
  237. return stat != 0;
  238. }
  239. #endif /* L_eq */
  240. #if defined (L_ne_sd) || defined (L_ne_dd) || defined (L_ne_td)
  241. CMPtype
  242. DFP_NE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
  243. {
  244. int stat;
  245. stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
  246. /* For NE return zero for true, nonzero for false. */
  247. if (__builtin_expect (stat == -2, 0)) /* An operand is NaN. */
  248. return 1;
  249. return stat != 0;
  250. }
  251. #endif /* L_ne */
  252. #if defined (L_lt_sd) || defined (L_lt_dd) || defined (L_lt_td)
  253. CMPtype
  254. DFP_LT (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
  255. {
  256. int stat;
  257. stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
  258. /* For LT return -1 (<0) for true, 1 for false. */
  259. return (stat == -1) ? -1 : 1;
  260. }
  261. #endif /* L_lt */
  262. #if defined (L_gt_sd) || defined (L_gt_dd) || defined (L_gt_td)
  263. CMPtype
  264. DFP_GT (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
  265. {
  266. int stat;
  267. stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
  268. /* For GT return 1 (>0) for true, -1 for false. */
  269. return (stat == 1) ? 1 : -1;
  270. }
  271. #endif
  272. #if defined (L_le_sd) || defined (L_le_dd) || defined (L_le_td)
  273. CMPtype
  274. DFP_LE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
  275. {
  276. int stat;
  277. stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
  278. /* For LE return 0 (<= 0) for true, 1 for false. */
  279. if (__builtin_expect (stat == -2, 0)) /* An operand is NaN. */
  280. return 1;
  281. return stat == 1;
  282. }
  283. #endif /* L_le */
  284. #if defined (L_ge_sd) || defined (L_ge_dd) || defined (L_ge_td)
  285. CMPtype
  286. DFP_GE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
  287. {
  288. int stat;
  289. stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
  290. /* For GE return 1 (>=0) for true, -1 for false. */
  291. if (__builtin_expect (stat == -2, 0)) /* An operand is NaN. */
  292. return -1;
  293. return (stat != -1) ? 1 : -1;
  294. }
  295. #endif /* L_ge */
  296. #define BUFMAX 128
  297. /* Check for floating point exceptions that are relevant for conversions
  298. between decimal float values and handle them. */
  299. static inline void
  300. dfp_conversion_exceptions (const int status)
  301. {
  302. /* decNumber exception flags we care about here. */
  303. int ieee_flags;
  304. int dec_flags = DEC_IEEE_854_Inexact | DEC_IEEE_854_Invalid_operation
  305. | DEC_IEEE_854_Overflow;
  306. dec_flags &= status;
  307. ieee_flags = DFP_IEEE_FLAGS (dec_flags);
  308. if (ieee_flags != 0)
  309. DFP_HANDLE_EXCEPTIONS (ieee_flags);
  310. }
  311. #if defined (L_sd_to_dd)
  312. /* Use decNumber to convert directly from _Decimal32 to _Decimal64. */
  313. _Decimal64
  314. DFP_TO_DFP (_Decimal32 f_from)
  315. {
  316. union { _Decimal32 c; decSingle f; } from;
  317. union { _Decimal64 c; decDouble f; } to;
  318. from.c = f_from;
  319. to.f = *decSingleToWider (&from.f, &to.f);
  320. return to.c;
  321. }
  322. #endif
  323. #if defined (L_sd_to_td)
  324. /* Use decNumber to convert directly from _Decimal32 to _Decimal128. */
  325. _Decimal128
  326. DFP_TO_DFP (_Decimal32 f_from)
  327. {
  328. union { _Decimal32 c; decSingle f; } from;
  329. union { _Decimal128 c; decQuad f; } to;
  330. decDouble temp;
  331. from.c = f_from;
  332. temp = *decSingleToWider (&from.f, &temp);
  333. to.f = *decDoubleToWider (&temp, &to.f);
  334. return to.c;
  335. }
  336. #endif
  337. #if defined (L_dd_to_td)
  338. /* Use decNumber to convert directly from _Decimal64 to _Decimal128. */
  339. _Decimal128
  340. DFP_TO_DFP (_Decimal64 f_from)
  341. {
  342. union { _Decimal64 c; decDouble f; } from;
  343. union { _Decimal128 c; decQuad f; } to;
  344. from.c = f_from;
  345. to.f = *decDoubleToWider (&from.f, &to.f);
  346. return to.c;
  347. }
  348. #endif
  349. #if defined (L_dd_to_sd)
  350. /* Use decNumber to convert directly from _Decimal64 to _Decimal32. */
  351. _Decimal32
  352. DFP_TO_DFP (_Decimal64 f_from)
  353. {
  354. union { _Decimal32 c; decSingle f; } to;
  355. union { _Decimal64 c; decDouble f; } from;
  356. decContext context;
  357. decContextDefault (&context, CONTEXT_INIT);
  358. DFP_INIT_ROUNDMODE (context.round);
  359. from.c = f_from;
  360. to.f = *decSingleFromWider (&to.f, &from.f, &context);
  361. if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
  362. dfp_conversion_exceptions (context.status);
  363. return to.c;
  364. }
  365. #endif
  366. #if defined (L_td_to_sd)
  367. /* Use decNumber to convert directly from _Decimal128 to _Decimal32. */
  368. _Decimal32
  369. DFP_TO_DFP (_Decimal128 f_from)
  370. {
  371. union { _Decimal32 c; decSingle f; } to;
  372. union { _Decimal128 c; decQuad f; } from;
  373. decDouble temp;
  374. decContext context;
  375. decContextDefault (&context, CONTEXT_INIT);
  376. DFP_INIT_ROUNDMODE (context.round);
  377. from.c = f_from;
  378. temp = *decDoubleFromWider (&temp, &from.f, &context);
  379. to.f = *decSingleFromWider (&to.f, &temp, &context);
  380. if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
  381. dfp_conversion_exceptions (context.status);
  382. return to.c;
  383. }
  384. #endif
  385. #if defined (L_td_to_dd)
  386. /* Use decNumber to convert directly from _Decimal128 to _Decimal64. */
  387. _Decimal64
  388. DFP_TO_DFP (_Decimal128 f_from)
  389. {
  390. union { _Decimal64 c; decDouble f; } to;
  391. union { _Decimal128 c; decQuad f; } from;
  392. decContext context;
  393. decContextDefault (&context, CONTEXT_INIT);
  394. DFP_INIT_ROUNDMODE (context.round);
  395. from.c = f_from;
  396. to.f = *decDoubleFromWider (&to.f, &from.f, &context);
  397. if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
  398. dfp_conversion_exceptions (context.status);
  399. return to.c;
  400. }
  401. #endif
  402. #if defined (L_dd_to_si) || defined (L_td_to_si) \
  403. || defined (L_dd_to_usi) || defined (L_td_to_usi)
  404. /* Use decNumber to convert directly from decimal float to integer types. */
  405. INT_TYPE
  406. DFP_TO_INT (DFP_C_TYPE x)
  407. {
  408. union { DFP_C_TYPE c; decFloat f; } u;
  409. decContext context;
  410. INT_TYPE i;
  411. decContextDefault (&context, DEC_INIT_DECIMAL128);
  412. context.round = DEC_ROUND_DOWN;
  413. u.c = x;
  414. i = DEC_FLOAT_TO_INT (&u.f, &context, context.round);
  415. if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
  416. dfp_conversion_exceptions (context.status);
  417. return i;
  418. }
  419. #endif
  420. #if defined (L_sd_to_si) || (L_sd_to_usi)
  421. /* Use decNumber to convert directly from decimal float to integer types. */
  422. INT_TYPE
  423. DFP_TO_INT (_Decimal32 x)
  424. {
  425. union { _Decimal32 c; decSingle f; } u32;
  426. decDouble f64;
  427. decContext context;
  428. INT_TYPE i;
  429. decContextDefault (&context, DEC_INIT_DECIMAL128);
  430. context.round = DEC_ROUND_DOWN;
  431. u32.c = x;
  432. f64 = *decSingleToWider (&u32.f, &f64);
  433. i = DEC_FLOAT_TO_INT (&f64, &context, context.round);
  434. if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
  435. dfp_conversion_exceptions (context.status);
  436. return i;
  437. }
  438. #endif
  439. #if defined (L_sd_to_di) || defined (L_dd_to_di) || defined (L_td_to_di) \
  440. || defined (L_sd_to_udi) || defined (L_dd_to_udi) || defined (L_td_to_udi)
  441. /* decNumber doesn't provide support for conversions to 64-bit integer
  442. types, so do it the hard way. */
  443. INT_TYPE
  444. DFP_TO_INT (DFP_C_TYPE x)
  445. {
  446. /* decNumber's decimal* types have the same format as C's _Decimal*
  447. types, but they have different calling conventions. */
  448. /* TODO: Decimal float to integer conversions should raise FE_INVALID
  449. if the result value does not fit into the result type. */
  450. IEEE_TYPE s;
  451. char buf[BUFMAX];
  452. char *pos;
  453. decNumber qval, n1, n2;
  454. decContext context;
  455. /* Use a large context to avoid losing precision. */
  456. decContextDefault (&context, DEC_INIT_DECIMAL128);
  457. /* Need non-default rounding mode here. */
  458. context.round = DEC_ROUND_DOWN;
  459. HOST_TO_IEEE (x, &s);
  460. TO_INTERNAL (&s, &n1);
  461. /* Rescale if the exponent is less than zero. */
  462. decNumberToIntegralValue (&n2, &n1, &context);
  463. /* Get a value to use for the quantize call. */
  464. decNumberFromString (&qval, "1.", &context);
  465. /* Force the exponent to zero. */
  466. decNumberQuantize (&n1, &n2, &qval, &context);
  467. /* Get a string, which at this point will not include an exponent. */
  468. decNumberToString (&n1, buf);
  469. /* Ignore the fractional part. */
  470. pos = strchr (buf, '.');
  471. if (pos)
  472. *pos = 0;
  473. /* Use a C library function to convert to the integral type. */
  474. return STR_TO_INT (buf, NULL, 10);
  475. }
  476. #endif
  477. #if defined (L_si_to_dd) || defined (L_si_to_td) \
  478. || defined (L_usi_to_dd) || defined (L_usi_to_td)
  479. /* Use decNumber to convert directly from integer to decimal float types. */
  480. DFP_C_TYPE
  481. INT_TO_DFP (INT_TYPE i)
  482. {
  483. union { DFP_C_TYPE c; decFloat f; } u;
  484. u.f = *DEC_FLOAT_FROM_INT (&u.f, i);
  485. return u.c;
  486. }
  487. #endif
  488. #if defined (L_si_to_sd) || defined (L_usi_to_sd)
  489. _Decimal32
  490. /* Use decNumber to convert directly from integer to decimal float types. */
  491. INT_TO_DFP (INT_TYPE i)
  492. {
  493. union { _Decimal32 c; decSingle f; } u32;
  494. decDouble f64;
  495. decContext context;
  496. decContextDefault (&context, DEC_INIT_DECIMAL128);
  497. f64 = *DEC_FLOAT_FROM_INT (&f64, i);
  498. u32.f = *decSingleFromWider (&u32.f, &f64, &context);
  499. if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
  500. dfp_conversion_exceptions (context.status);
  501. return u32.c;
  502. }
  503. #endif
  504. #if defined (L_di_to_sd) || defined (L_di_to_dd) || defined (L_di_to_td) \
  505. || defined (L_udi_to_sd) || defined (L_udi_to_dd) || defined (L_udi_to_td)
  506. /* decNumber doesn't provide support for conversions from 64-bit integer
  507. types, so do it the hard way. */
  508. DFP_C_TYPE
  509. INT_TO_DFP (INT_TYPE i)
  510. {
  511. DFP_C_TYPE f;
  512. IEEE_TYPE s;
  513. char buf[BUFMAX];
  514. decContext context;
  515. decContextDefault (&context, CONTEXT_INIT);
  516. DFP_INIT_ROUNDMODE (context.round);
  517. /* Use a C library function to get a floating point string. */
  518. sprintf (buf, INT_FMT ".", CAST_FOR_FMT(i));
  519. /* Convert from the floating point string to a decimal* type. */
  520. FROM_STRING (&s, buf, &context);
  521. IEEE_TO_HOST (s, &f);
  522. if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
  523. dfp_conversion_exceptions (context.status);
  524. return f;
  525. }
  526. #endif
  527. #if defined (L_sd_to_sf) || defined (L_dd_to_sf) || defined (L_td_to_sf) \
  528. || defined (L_sd_to_df) || defined (L_dd_to_df) || defined (L_td_to_df) \
  529. || defined (L_sd_to_kf) || defined (L_dd_to_kf) || defined (L_td_to_kf) \
  530. || ((defined (L_sd_to_xf) || defined (L_dd_to_xf) || defined (L_td_to_xf)) \
  531. && LONG_DOUBLE_HAS_XF_MODE) \
  532. || ((defined (L_sd_to_tf) || defined (L_dd_to_tf) || defined (L_td_to_tf)) \
  533. && LONG_DOUBLE_HAS_TF_MODE)
  534. BFP_TYPE
  535. DFP_TO_BFP (DFP_C_TYPE f)
  536. {
  537. IEEE_TYPE s;
  538. char buf[BUFMAX];
  539. HOST_TO_IEEE (f, &s);
  540. /* Write the value to a string. */
  541. TO_STRING (&s, buf);
  542. /* Read it as the binary floating point type and return that. */
  543. return STR_TO_BFP (buf, NULL);
  544. }
  545. #endif
  546. #if defined (L_sf_to_sd) || defined (L_sf_to_dd) || defined (L_sf_to_td) \
  547. || defined (L_df_to_sd) || defined (L_df_to_dd) || defined (L_df_to_td) \
  548. || defined (L_kf_to_sd) || defined (L_kf_to_dd) || defined (L_kf_to_td) \
  549. || ((defined (L_xf_to_sd) || defined (L_xf_to_dd) || defined (L_xf_to_td)) \
  550. && LONG_DOUBLE_HAS_XF_MODE) \
  551. || ((defined (L_tf_to_sd) || defined (L_tf_to_dd) || defined (L_tf_to_td)) \
  552. && LONG_DOUBLE_HAS_TF_MODE)
  553. DFP_C_TYPE
  554. BFP_TO_DFP (BFP_TYPE x)
  555. {
  556. DFP_C_TYPE f;
  557. IEEE_TYPE s;
  558. char buf[BUFMAX];
  559. decContext context;
  560. decContextDefault (&context, CONTEXT_INIT);
  561. DFP_INIT_ROUNDMODE (context.round);
  562. /* Use the sprintf library function to write the floating point value to a
  563. string.
  564. If we are handling the IEEE 128-bit floating point on PowerPC, use the
  565. special function __sprintfkf instead of sprintf. This function allows us
  566. to use __sprintfieee128 if we have a new enough GLIBC, and it can fall back
  567. to using the traditional sprintf via conversion to IBM 128-bit if the glibc
  568. is older. */
  569. BFP_SPRINTF (buf, BFP_FMT, (BFP_VIA_TYPE) x);
  570. /* Convert from the floating point string to a decimal* type. */
  571. FROM_STRING (&s, buf, &context);
  572. IEEE_TO_HOST (s, &f);
  573. if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
  574. {
  575. /* decNumber exception flags we care about here. */
  576. int ieee_flags;
  577. int dec_flags = DEC_IEEE_854_Inexact | DEC_IEEE_854_Invalid_operation
  578. | DEC_IEEE_854_Overflow | DEC_IEEE_854_Underflow;
  579. dec_flags &= context.status;
  580. ieee_flags = DFP_IEEE_FLAGS (dec_flags);
  581. if (ieee_flags != 0)
  582. DFP_HANDLE_EXCEPTIONS (ieee_flags);
  583. }
  584. return f;
  585. }
  586. #endif
  587. #if defined (L_unord_sd) || defined (L_unord_dd) || defined (L_unord_td)
  588. CMPtype
  589. DFP_UNORD (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
  590. {
  591. decNumber arg1, arg2;
  592. IEEE_TYPE a, b;
  593. HOST_TO_IEEE (arg_a, &a);
  594. HOST_TO_IEEE (arg_b, &b);
  595. TO_INTERNAL (&a, &arg1);
  596. TO_INTERNAL (&b, &arg2);
  597. return (decNumberIsNaN (&arg1) || decNumberIsNaN (&arg2));
  598. }
  599. #endif /* L_unord_sd || L_unord_dd || L_unord_td */