libm_ceil.c 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /*
  2. * Copyright (c) 2019 Actions Semi Co., Inc.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /* poriting from newlib */
  7. #ifndef __UVISION_VERSION
  8. #include <stdint.h>
  9. typedef union {
  10. double value;
  11. struct {
  12. uint32_t lsw;
  13. uint32_t msw;
  14. } parts;
  15. } ieee_double_shape_type;
  16. /* Get two 32 bit ints from a double. */
  17. #define EXTRACT_WORDS(ix0,ix1,d) \
  18. do { \
  19. ieee_double_shape_type ew_u; \
  20. ew_u.value = (d); \
  21. (ix0) = ew_u.parts.msw; \
  22. (ix1) = ew_u.parts.lsw; \
  23. } while (0)
  24. /* Set a double from two 32 bit ints. */
  25. #define INSERT_WORDS(d,ix0,ix1) \
  26. do { \
  27. ieee_double_shape_type iw_u; \
  28. iw_u.parts.msw = (ix0); \
  29. iw_u.parts.lsw = (ix1); \
  30. (d) = iw_u.value; \
  31. } while (0)
  32. static const double huge = 1.0e300;
  33. /*
  34. * ceil(x)
  35. * Return x rounded toward -inf to integral value
  36. * Method:
  37. * Bit twiddling.
  38. * Exception:
  39. * Inexact flag raised if x not equal to ceil(x).
  40. */
  41. double ceil(double x)
  42. {
  43. int32_t i0,i1,j0;
  44. uint32_t i,j;
  45. EXTRACT_WORDS(i0,i1,x);
  46. j0 = ((i0>>20)&0x7ff)-0x3ff;
  47. if(j0<20) {
  48. if(j0<0) { /* raise inexact if x != 0 */
  49. if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
  50. if(i0<0) {i0=0x80000000;i1=0;}
  51. else if((i0|i1)!=0) { i0=0x3ff00000;i1=0;}
  52. }
  53. } else {
  54. i = (0x000fffff)>>j0;
  55. if(((i0&i)|i1)==0) return x; /* x is integral */
  56. if(huge+x>0.0) { /* raise inexact flag */
  57. if(i0>0) i0 += (0x00100000)>>j0;
  58. i0 &= (~i); i1=0;
  59. }
  60. }
  61. } else if (j0>51) {
  62. if(j0==0x400) return x+x; /* inf or NaN */
  63. else return x; /* x is integral */
  64. } else {
  65. i = ((uint32_t)(0xffffffff))>>(j0-20);
  66. if((i1&i)==0) return x; /* x is integral */
  67. if(huge+x>0.0) { /* raise inexact flag */
  68. if(i0>0) {
  69. if(j0==20) i0+=1;
  70. else {
  71. j = i1 + (1<<(52-j0));
  72. if(j<i1) i0+=1; /* got a carry */
  73. i1 = j;
  74. }
  75. }
  76. i1 &= (~i);
  77. }
  78. }
  79. INSERT_WORDS(x,i0,i1);
  80. return x;
  81. }
  82. #endif