conv-integer.i.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  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_SCM_T_BITS
  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. scm_t_intmax n;
  63. size_t count;
  64. if (mpz_sizeinbase (SCM_I_BIG_MPZ (val), 2)
  65. > CHAR_BIT*sizeof (scm_t_uintmax))
  66. goto out_of_range;
  67. mpz_export (&n, &count, 1, sizeof (scm_t_uintmax), 0, 0,
  68. SCM_I_BIG_MPZ (val));
  69. if (mpz_sgn (SCM_I_BIG_MPZ (val)) >= 0)
  70. {
  71. if (n < 0)
  72. goto out_of_range;
  73. }
  74. else
  75. {
  76. n = -n;
  77. if (n >= 0)
  78. goto out_of_range;
  79. }
  80. if (n >= TYPE_MIN && n <= TYPE_MAX)
  81. return n;
  82. else
  83. {
  84. out_of_range:
  85. scm_i_range_error (val,
  86. scm_from_signed_integer (TYPE_MIN),
  87. scm_from_signed_integer (TYPE_MAX));
  88. return 0;
  89. }
  90. }
  91. }
  92. else
  93. {
  94. scm_wrong_type_arg_msg (NULL, 0, val, "exact integer");
  95. return 0;
  96. }
  97. }
  98. SCM
  99. SCM_FROM_TYPE_PROTO (TYPE val)
  100. {
  101. #if SIZEOF_TYPE != 0 && SIZEOF_TYPE < SIZEOF_SCM_T_BITS
  102. return SCM_I_MAKINUM (val);
  103. #else
  104. if (SCM_FIXABLE (val))
  105. return SCM_I_MAKINUM (val);
  106. else if (val >= LONG_MIN && val <= LONG_MAX)
  107. return scm_i_long2big (val);
  108. else
  109. {
  110. SCM z = scm_double_cell (scm_tc16_big, 0, 0, 0);
  111. mpz_init (SCM_I_BIG_MPZ (z));
  112. if (val < 0)
  113. {
  114. val = -val;
  115. mpz_import (SCM_I_BIG_MPZ (z), 1, 1, sizeof (TYPE), 0, 0,
  116. &val);
  117. mpz_neg (SCM_I_BIG_MPZ (z), SCM_I_BIG_MPZ (z));
  118. }
  119. else
  120. mpz_import (SCM_I_BIG_MPZ (z), 1, 1, sizeof (TYPE), 0, 0,
  121. &val);
  122. return z;
  123. }
  124. #endif
  125. }
  126. /* clean up */
  127. #undef TYPE
  128. #undef TYPE_MIN
  129. #undef TYPE_MAX
  130. #undef SIZEOF_TYPE
  131. #undef SCM_TO_TYPE_PROTO
  132. #undef SCM_FROM_TYPE_PROTO
  133. /*
  134. Local Variables:
  135. c-file-style: "gnu"
  136. End:
  137. */