@deftypefn Function intmax_t extract_integer (emacs_env *@var{env}, emacs_value @var{arg})
This function returns the value of a Lisp integer specified by
@var{arg}. The C data type of the return value, @code{intmax_t}, is
-the widest integral data type supported by the C compiler, typically
+the widest integer data type supported by the C compiler, typically
@w{@code{long long}}. If the value of @var{arg} doesn't fit into an
@code{intmax_t}, the function signals an error using the error symbol
@code{overflow-error}.
@deftypefn Function bool extract_big_integer (emacs_env *@var{env}, emacs_value @var{arg}, int *@var{sign}, ptrdiff_t *@var{count}, emacs_limb_t *@var{magnitude})
This function, which is available since Emacs 27, extracts the
-integral value of @var{arg}. The value of @var{arg} must be an
+integer value of @var{arg}. The value of @var{arg} must be an
integer (fixnum or bignum). If @var{sign} is not @code{NULL}, it
stores the sign of @var{arg} (-1, 0, or +1) into @code{*sign}. The
magnitude is stored into @var{magnitude} as follows. If @var{count}
-and @var{magnitude} are bot non-@code{NULL}, then @var{magnitude} must
+and @var{magnitude} are both non-@code{NULL}, then @var{magnitude} must
point to an array of at least @code{*count} @code{unsigned long}
elements. If @var{magnitude} is large enough to hold the magnitude of
@var{arg}, then this function writes the magnitude into the
Emacs guarantees that the maximum required value of @code{*count}
never exceeds @code{min (PTRDIFF_MAX, SIZE_MAX) / sizeof
-(emacs_limb_t)}. This implies that you can use e.g. @code{malloc
-((size_t) (*count * sizeof (emacs_limb_t)))} to allocate the
-@code{magnitude} array without integer overflow.
+(emacs_limb_t)}, so you can use @code{malloc (*count * sizeof *magnitude)}
+to allocate the @code{magnitude} array without worrying about integer
+overflow in the size calculation.
@end deftypefn
@deftp {Type alias} emacs_limb_t
-This type is an alias to an otherwise unspecified unsigned integral
-type. It is used as element type for the magnitude arrays for the big
+This is an unsigned integer type,
+used as the element type for the magnitude arrays for the big
integer conversion functions.
@end deftp
@defvr Macro EMACS_LIMB_MAX
-This macro expands to an integer literal specifying the maximum
+This macro expands to a constant expression specifying the maximum
possible value for an @code{emacs_limb_t} object.
+The expression is suitable for use in @code{#if}.
@end defvr
@deftypefn Function double extract_float (emacs_env *@var{env}, emacs_value @var{arg})
function truncates it to nanosecond precision towards negative
infinity. This function signals an error if @var{time} (truncated to
nanoseconds) cannot be represented by @code{struct timespec}. For
-example, if @code{time_t} is a 32-bit integral type, then a @var{time}
+example, if @code{time_t} is a 32-bit integer type, then a @var{time}
value of ten billion seconds would signal an error, but a @var{time}
value of 600 picoseconds would get truncated to zero.
to and from GMP @code{mpz_t} values.
@example
+#include <emacs-module.h>
+int plugin_is_GPL_compatible;
+
#include <assert.h>
#include <limits.h>
#include <stdint.h>
#include <gmp.h>
-#include <emacs-module.h>
-
static void
memory_full (emacs_env *env)
@{
- const char *message = "Memory exhausted";
- emacs_value data = env->make_string (env, message, strlen (message));
- env->non_local_exit_signal (env, env->intern (env, "error"),
- env->funcall (env, env->intern (env, "list"), 1,
- &data));
+ static const char message[] = "Memory exhausted";
+ emacs_value data = env->make_string (env, message,
+ strlen (message));
+ env->non_local_exit_signal
+ (env, env->intern (env, "error"),
+ env->funcall (env, env->intern (env, "list"), 1, &data));
@}
enum
@{
- max_count = ((SIZE_MAX < PTRDIFF_MAX ? SIZE_MAX : PTRDIFF_MAX)
- / sizeof (emacs_limb_t))
+ order = -1, endian = 0, nails = 0,
+ limb_size = sizeof (emacs_limb_t),
+ max_nlimbs = ((SIZE_MAX < PTRDIFF_MAX ? SIZE_MAX : PTRDIFF_MAX)
+ / limb_size)
@};
static bool
extract_big_integer (emacs_env *env, emacs_value arg, mpz_t result)
@{
- int sign;
- ptrdiff_t count;
- bool success = env->extract_big_integer (env, arg, &sign, &count, NULL);
- if (!success)
+ ptrdiff_t nlimbs;
+ bool ok = env->extract_big_integer (env, arg, NULL, &nlimbs, NULL);
+ if (!ok)
return false;
- if (sign == 0)
- @{
- mpz_set_ui (result, 0);
- return true;
- @}
- enum @{ order = -1, size = sizeof (emacs_limb_t), endian = 0, nails = 0 @};
- assert (0 < count && count <= max_count);
- emacs_limb_t *magnitude = malloc ((size_t) (count * size));
+ assert (0 < nlimbs && nlimbs <= max_nlimbs);
+ emacs_limb_t *magnitude = malloc (nlimbs * limb_size);
if (magnitude == NULL)
@{
memory_full (env);
return false;
@}
- success = env->extract_big_integer (env, arg, NULL, &count, magnitude);
- assert (success);
- mpz_import (result, count, order, size, endian, nails, magnitude);
+ int sign;
+ ok = env->extract_big_integer (env, arg, &sign, &nlimbs, magnitude);
+ assert (ok);
+ mpz_import (result, nlimbs, order, limb_size, endian, nails, magnitude);
free (magnitude);
if (sign < 0)
mpz_neg (result, result);
static emacs_value
make_big_integer (emacs_env *env, const mpz_t value)
@{
- if (mpz_sgn (value) == 0)
- return env->make_integer (env, 0);
- enum
- @{
- order = -1,
- size = sizeof (emacs_limb_t),
- endian = 0,
- nails = 0,
- numb = 8 * size - nails
- @};
- size_t count = (mpz_sizeinbase (value, 2) + numb - 1) / numb;
- if (max_count < count)
- @{
- memory_full (env);
- return NULL;
- @}
- emacs_limb_t *magnitude = malloc (count * size);
+ size_t nbits = mpz_sizeinbase (value, 2);
+ int bitsperlimb = CHAR_BIT * limb_size - nails;
+ size_t nlimbs = nbits / bitsperlimb + (nbits % bitsperlimb != 0);
+ emacs_limb_t *magnitude
+ = nlimbs <= max_nlimbs ? malloc (nlimbs * limb_size) : NULL;
if (magnitude == NULL)
@{
memory_full (env);
return NULL;
@}
size_t written;
- mpz_export (magnitude, &written, order, size, endian, nails, value);
- assert (written == count);
- assert (count <= PTRDIFF_MAX);
+ mpz_export (magnitude, &written, order, limb_size, endian, nails, value);
+ assert (written == nlimbs);
+ assert (nlimbs <= PTRDIFF_MAX);
emacs_value result = env->make_big_integer (env, mpz_sgn (value),
- (ptrdiff_t) count, magnitude);
+ nlimbs, magnitude);
free (magnitude);
return result;
@}
void *data)
@{
assert (nargs == 1);
- emacs_mpz p;
+ mpz_t p;
mpz_init (p);
extract_big_integer (env, args[0], p);
mpz_nextprime (p, p);
mpz_clear (p);
return result;
@}
+
+int
+emacs_module_init (struct emacs_runtime *ert)
+@{
+ emacs_env *env = ert->get_environment (ert);
+ emacs_value symbol = env->intern (env, "next-prime");
+ emacs_value func
+ = env->make_function (env, 1, 1, next_prime, NULL, NULL);
+ emacs_value args[] = @{symbol, func@};
+ env->funcall (env, env->intern (env, "defalias"), 2, args);
+ return 0;
+@}
@end example
@deftypefn Function emacs_value make_float (emacs_env *@var{env}, double @var{d})