conv-uinteger.i.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /* This code in included by number.s.c to generate integer conversion
  2. functions like scm_to_int and scm_from_int. It is only for
  3. unsigned types, see conv-integer.i.c for the signed 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 giove 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, typically 0.
  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 (n >= 0
  28. && ((scm_t_uintmax)n) >= TYPE_MIN && ((scm_t_uintmax)n) <= TYPE_MAX)
  29. return n;
  30. else
  31. {
  32. out_of_range:
  33. scm_i_range_error (val,
  34. scm_from_unsigned_integer (TYPE_MIN),
  35. scm_from_unsigned_integer (TYPE_MAX));
  36. return 0;
  37. }
  38. }
  39. else if (SCM_BIGP (val))
  40. {
  41. if (TYPE_MAX <= SCM_MOST_POSITIVE_FIXNUM)
  42. goto out_of_range;
  43. else if (TYPE_MAX <= ULONG_MAX)
  44. {
  45. if (mpz_fits_ulong_p (SCM_I_BIG_MPZ (val)))
  46. {
  47. unsigned long n = mpz_get_ui (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_uintmax n;
  63. size_t count;
  64. if (mpz_sgn (SCM_I_BIG_MPZ (val)) < 0)
  65. goto out_of_range;
  66. if (mpz_sizeinbase (SCM_I_BIG_MPZ (val), 2)
  67. > CHAR_BIT*sizeof (TYPE))
  68. goto out_of_range;
  69. mpz_export (&n, &count, 1, sizeof (TYPE), 0, 0, SCM_I_BIG_MPZ (val));
  70. if (n >= TYPE_MIN && n <= TYPE_MAX)
  71. return n;
  72. else
  73. goto out_of_range;
  74. }
  75. }
  76. else
  77. {
  78. scm_wrong_type_arg_msg (NULL, 0, val, "exact integer");
  79. return 0;
  80. }
  81. }
  82. SCM
  83. SCM_FROM_TYPE_PROTO (TYPE val)
  84. {
  85. #if SIZEOF_TYPE != 0 && SIZEOF_TYPE < SIZEOF_SCM_T_BITS
  86. return SCM_I_MAKINUM (val);
  87. #else
  88. if (SCM_POSFIXABLE (val))
  89. return SCM_I_MAKINUM (val);
  90. else if (val <= ULONG_MAX)
  91. return scm_i_ulong2big (val);
  92. else
  93. {
  94. SCM z = scm_double_cell (scm_tc16_big, 0, 0, 0);
  95. mpz_init (SCM_I_BIG_MPZ (z));
  96. mpz_import (SCM_I_BIG_MPZ (z), 1, 1, sizeof (TYPE), 0, 0, &val);
  97. return z;
  98. }
  99. #endif
  100. }
  101. #undef TYPE
  102. #undef TYPE_MIN
  103. #undef TYPE_MAX
  104. #undef SIZEOF_TYPE
  105. #undef SCM_TO_TYPE_PROTO
  106. #undef SCM_FROM_TYPE_PROTO