conv-integer.i.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /* This code in included by numbers.c to generate integer conversion
  2. functions like scm_to_int and scm_from_int. It is only for signed
  3. types, see conv-uinteger.i.c for the unsigned variant.
  4. */
  5. /* You need to define the following macros before including this
  6. template. They are undefined at the end of this file to give a
  7. clean slate for the next inclusion.
  8. TYPE - the integral type to be converted
  9. TYPE_MIN - the smallest representable number of TYPE
  10. TYPE_MAX - the largest representable number of TYPE
  11. SIZEOF_TYPE - the size of TYPE, equal to "sizeof (TYPE)" but
  12. in a form that can be computed by the preprocessor.
  13. When this number is 0, the preprocessor is not used
  14. to select which code to compile; the most general
  15. code is always used.
  16. SCM_TO_TYPE_PROTO(arg), SCM_FROM_TYPE_PROTO(arg)
  17. - These two macros should expand into the prototype
  18. for the two defined functions, without the return
  19. type.
  20. */
  21. TYPE
  22. SCM_TO_TYPE_PROTO (SCM val)
  23. {
  24. if (SCM_I_INUMP (val))
  25. {
  26. scm_t_signed_bits n = SCM_I_INUM (val);
  27. #if SIZEOF_TYPE != 0 && SIZEOF_TYPE > SIZEOF_UINTPTR_T
  28. return n;
  29. #else
  30. if (n >= TYPE_MIN && n <= TYPE_MAX)
  31. return n;
  32. else
  33. {
  34. goto out_of_range;
  35. }
  36. #endif
  37. }
  38. else if (SCM_BIGP (val))
  39. {
  40. if (TYPE_MIN >= SCM_MOST_NEGATIVE_FIXNUM
  41. && TYPE_MAX <= SCM_MOST_POSITIVE_FIXNUM)
  42. goto out_of_range;
  43. else if (TYPE_MIN >= LONG_MIN && TYPE_MAX <= LONG_MAX)
  44. {
  45. if (mpz_fits_slong_p (SCM_I_BIG_MPZ (val)))
  46. {
  47. long n = mpz_get_si (SCM_I_BIG_MPZ (val));
  48. #if SIZEOF_TYPE != 0 && SIZEOF_TYPE > SCM_SIZEOF_LONG
  49. return n;
  50. #else
  51. if (n >= TYPE_MIN && n <= TYPE_MAX)
  52. return n;
  53. else
  54. goto out_of_range;
  55. #endif
  56. }
  57. else
  58. goto out_of_range;
  59. }
  60. else
  61. {
  62. uintmax_t abs_n;
  63. TYPE n;
  64. size_t count;
  65. if (mpz_sizeinbase (SCM_I_BIG_MPZ (val), 2)
  66. > CHAR_BIT*sizeof (uintmax_t))
  67. goto out_of_range;
  68. mpz_export (&abs_n, &count, 1, sizeof (uintmax_t), 0, 0,
  69. SCM_I_BIG_MPZ (val));
  70. if (mpz_sgn (SCM_I_BIG_MPZ (val)) >= 0)
  71. {
  72. if (abs_n <= TYPE_MAX)
  73. n = abs_n;
  74. else
  75. goto out_of_range;
  76. }
  77. else
  78. {
  79. /* Carefully avoid signed integer overflow. */
  80. if (TYPE_MIN < 0 && abs_n - 1 <= -(TYPE_MIN + 1))
  81. n = -1 - (TYPE)(abs_n - 1);
  82. else
  83. goto out_of_range;
  84. }
  85. if (n >= TYPE_MIN && n <= TYPE_MAX)
  86. return n;
  87. else
  88. {
  89. out_of_range:
  90. scm_i_range_error (val,
  91. scm_from_signed_integer (TYPE_MIN),
  92. scm_from_signed_integer (TYPE_MAX));
  93. return 0;
  94. }
  95. }
  96. }
  97. else
  98. {
  99. scm_wrong_type_arg_msg (NULL, 0, val, "exact integer");
  100. return 0;
  101. }
  102. }
  103. SCM
  104. SCM_FROM_TYPE_PROTO (TYPE val)
  105. {
  106. #if SIZEOF_TYPE != 0 && SIZEOF_TYPE < SIZEOF_UINTPTR_T
  107. return SCM_I_MAKINUM (val);
  108. #else
  109. if (SCM_FIXABLE (val))
  110. return SCM_I_MAKINUM (val);
  111. else if (val >= LONG_MIN && val <= LONG_MAX)
  112. return scm_i_long2big (val);
  113. else
  114. {
  115. SCM z = make_bignum ();
  116. mpz_init (SCM_I_BIG_MPZ (z));
  117. if (val < 0)
  118. {
  119. val = -val;
  120. mpz_import (SCM_I_BIG_MPZ (z), 1, 1, sizeof (TYPE), 0, 0,
  121. &val);
  122. mpz_neg (SCM_I_BIG_MPZ (z), SCM_I_BIG_MPZ (z));
  123. }
  124. else
  125. mpz_import (SCM_I_BIG_MPZ (z), 1, 1, sizeof (TYPE), 0, 0,
  126. &val);
  127. return z;
  128. }
  129. #endif
  130. }
  131. /* clean up */
  132. #undef TYPE
  133. #undef TYPE_MIN
  134. #undef TYPE_MAX
  135. #undef SIZEOF_TYPE
  136. #undef SCM_TO_TYPE_PROTO
  137. #undef SCM_FROM_TYPE_PROTO