From 95e2da06beccaef26fda146d853d3286c0737f97 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Sat, 15 Jun 2013 10:07:33 +0200 Subject: [PATCH] add isl_val_int_from_chunks and isl_val_get_abs_num_chunks These allow for a backend independent way of converting from/to multiple precision integers. Requested-by: Tobias Grosser Signed-off-by: Sven Verdoolaege --- doc/user.pod | 25 ++++++++++++++++++---- include/isl/val.h | 5 +++++ isl_val_gmp.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 4 deletions(-) diff --git a/doc/user.pod b/doc/user.pod index 9fbff364..47af6644 100644 --- a/doc/user.pod +++ b/doc/user.pod @@ -363,8 +363,14 @@ Specific integer values can be created using the following functions. long i); __isl_give isl_val *isl_val_int_from_ui(isl_ctx *ctx, unsigned long u); + __isl_give isl_val *isl_val_int_from_chunks(isl_ctx *ctx, + size_t n, size_t size, const void *chunks); -They can be copied and freed using the following functions. +The function C constructs an C +from the C I, each consisting of C bytes, stored at C. +The least significant digit is assumed to be stored first. + +Value objects can be copied and freed using the following functions. #include __isl_give isl_val *isl_val_copy(__isl_keep isl_val *v); @@ -377,9 +383,20 @@ They can be inspected using the following functions. long isl_val_get_num_si(__isl_keep isl_val *v); long isl_val_get_den_si(__isl_keep isl_val *v); double isl_val_get_d(__isl_keep isl_val *v); - -Note that C, C and -C can only be applied to rational values. + size_t isl_val_n_abs_num_chunks(__isl_keep isl_val *v, + size_t size); + int isl_val_get_abs_num_chunks(__isl_keep isl_val *v, + size_t size, void *chunks); + +C returns the number of I +of C bytes needed to store the absolute value of the +numerator of C. +C stores these digits at C, +which is assumed to have been preallocated by the caller. +The least significant digit is stored first. +Note that C, C, +C, C +and C can only be applied to rational values. An C can be modified using the following function. diff --git a/include/isl/val.h b/include/isl/val.h index f762a7b1..caf506dc 100644 --- a/include/isl/val.h +++ b/include/isl/val.h @@ -27,6 +27,8 @@ __isl_give isl_val *isl_val_infty(isl_ctx *ctx); __isl_give isl_val *isl_val_neginfty(isl_ctx *ctx); __isl_give isl_val *isl_val_int_from_si(isl_ctx *ctx, long i); __isl_give isl_val *isl_val_int_from_ui(isl_ctx *ctx, unsigned long u); +__isl_give isl_val *isl_val_int_from_chunks(isl_ctx *ctx, size_t n, + size_t size, const void *chunks); __isl_give isl_val *isl_val_copy(__isl_keep isl_val *v); void *isl_val_free(__isl_take isl_val *v); @@ -35,6 +37,9 @@ isl_ctx *isl_val_get_ctx(__isl_keep isl_val *val); long isl_val_get_num_si(__isl_keep isl_val *v); long isl_val_get_den_si(__isl_keep isl_val *v); double isl_val_get_d(__isl_keep isl_val *v); +size_t isl_val_n_abs_num_chunks(__isl_keep isl_val *v, size_t size); +int isl_val_get_abs_num_chunks(__isl_keep isl_val *v, size_t size, + void *chunks); __isl_give isl_val *isl_val_set_si(__isl_take isl_val *v, long i); diff --git a/isl_val_gmp.c b/isl_val_gmp.c index aed8bb18..42e8d444 100644 --- a/isl_val_gmp.c +++ b/isl_val_gmp.c @@ -1,3 +1,4 @@ +#include #include #include @@ -62,3 +63,66 @@ int isl_val_get_den_gmp(__isl_keep isl_val *v, mpz_t z) mpz_set(z, v->d); return 0; } + +/* Return a reference to an isl_val representing the unsigned + * integer value stored in the "n" chunks of size "size" at "chunks". + * The least significant chunk is assumed to be stored first. + */ +__isl_give isl_val *isl_val_int_from_chunks(isl_ctx *ctx, size_t n, + size_t size, const void *chunks) +{ + isl_val *v; + + v = isl_val_alloc(ctx); + if (!v) + return NULL; + + mpz_import(v->n, n, -1, size, 0, 0, chunks); + isl_int_set_si(v->d, 1); + + return v; +} + +/* Return the number of chunks of size "size" required to + * store the absolute value of the numerator of "v". + */ +size_t isl_val_n_abs_num_chunks(__isl_keep isl_val *v, size_t size) +{ + if (!v) + return 0; + + if (!isl_val_is_rat(v)) + isl_die(isl_val_get_ctx(v), isl_error_invalid, + "expecting rational value", return 0); + + size *= 8; + return (mpz_sizeinbase(v->n, 2) + size - 1) / size; +} + +/* Store a representation of the absolute value of the numerator of "v" + * in terms of chunks of size "size" at "chunks". + * The least significant chunk is stored first. + * The number of chunks in the result can be obtained by calling + * isl_val_n_abs_num_chunks. The user is responsible for allocating + * enough memory to store the results. + * + * In the special case of a zero value, isl_val_n_abs_num_chunks will + * return one, while mpz_export will not fill in any chunks. We therefore + * do it ourselves. + */ +int isl_val_get_abs_num_chunks(__isl_keep isl_val *v, size_t size, + void *chunks) +{ + if (!v || !chunks) + return -1; + + if (!isl_val_is_rat(v)) + isl_die(isl_val_get_ctx(v), isl_error_invalid, + "expecting rational value", return -1); + + mpz_export(chunks, NULL, -1, size, 0, 0, v->n); + if (isl_val_is_zero(v)) + memset(chunks, 0, size); + + return 0; +} -- 2.11.4.GIT