From 31108639cea3a3356d272b6230281d78557d7a03 Mon Sep 17 00:00:00 2001 From: Cedric Bastoul Date: Mon, 18 Jul 2011 19:30:29 +0200 Subject: [PATCH] Hybrid precision (32, 64, GMP) --- configure.in | 63 +-- doc/openscop.texi | 84 +++- include/Makefile.am | 1 + include/openscop/{vector.h => int.h} | 88 ++-- include/openscop/macros.h | 130 +----- include/openscop/openscop.h | 1 + include/openscop/relation.h | 17 +- include/openscop/scop.h.in | 3 - include/openscop/util.h | 1 + include/openscop/vector.h | 10 +- source/Makefile.am | 1 + source/body.c | 16 +- source/int.c | 794 +++++++++++++++++++++++++++++++++++ source/relation.c | 220 ++++++---- source/util.c | 32 ++ source/vector.c | 120 +++--- 16 files changed, 1210 insertions(+), 371 deletions(-) copy include/openscop/{vector.h => int.h} (72%) create mode 100644 source/int.c diff --git a/configure.in b/configure.in index fe99817..b70fa1f 100644 --- a/configure.in +++ b/configure.in @@ -80,7 +80,6 @@ AM_INIT_AUTOMAKE([1.9 tar-ustar no-define foreign dist-bzip2]) dnl default version BITS="64" -OPENSCOP_INT_T=OPENSCOP_INT_T_IS_LONGLONG dnl /************************************************************************** @@ -93,8 +92,6 @@ AC_PROG_CC AC_PROG_LN_S AC_PROG_MAKE_SET AC_CHECK_PROG(CD, cd) -AC_CHECK_PROG(TR, tr) -AC_CHECK_PROG(SED, sed, sed) AC_PROG_LIBTOOL AC_CHECK_PROGS(DOXYGEN,doxygen,doxygen) @@ -119,8 +116,9 @@ dnl documentation says it does... gmp_package="yes" gmp_include_package="yes" gmp_library_package="yes" +gmp_flag="OPENSCOP_GMP_IS_HERE" -NEED_MP="no" +ASKED_FOR_GMP="no" dnl --with-gmp=gmp-path AC_ARG_WITH(gmp, @@ -129,47 +127,22 @@ AC_ARG_WITH(gmp, gmp_package=$withval && GMP_INC=$gmp_package/include && GMP_LIB=$gmp_package/lib && - OPENSCOP_INT_T=OPENSCOP_INT_T_IS_MP && - NEED_MP="yes"]) + ASKED_FOR_GMP="yes"]) AC_ARG_WITH(gmp-include, [ --with-gmp-include=DIR DIR where gmp.h is installed], [ echo "Package gmp-include : $withval" && gmp_include_package=$withval && GMP_INC=$gmp_include_package && - OPENSCOP_INT_T=OPENSCOP_INT_T_IS_MP && - NEED_MP="yes"]) + ASKED_FOR_GMP="yes"]) AC_ARG_WITH(gmp-library, [ --with-gmp-library=DIR DIR where the gmp library is installed], [ echo "Package gmp-library : $withval" && gmp_library_package=$withval && GMP_LIB=$gmp_library_package && - OPENSCOP_INT_T=OPENSCOP_INT_T_IS_MP && - NEED_MP="yes"]) - -AC_ARG_ENABLE(int-version, - [ --enable-int-version 'int' (32 bits) version is built], - [ echo "Package int : $enableval" && - BITS="32" && - OPENSCOP_INT_T=OPENSCOP_INT_T_IS_LONG]) - -AC_ARG_ENABLE(llint-version, - [ --enable-llint-version 'long long int' (64 bits) version is built], - [ echo "Package long long int : $enableval" && - BITS="64" && - OPENSCOP_INT_T=OPENSCOP_INT_T_IS_LONGLONG]) - -AC_ARG_ENABLE(mp-version, - [ --enable-mp-version 'MP' (multiple precision) version is built], - [ echo "Package mp : $enableval" && - BITS="MP" && - OPENSCOP_INT_T=OPENSCOP_INT_T_IS_MP && - CPPFLAGS="$CPPFLAGS -DLINEAR_VALUE_IS_MP" - NEED_MP="yes"]) - -dnl FIXME: should be removed... -CPPFLAGS="$CPPFLAGS -D$OPENSCOP_INT_T" + ASKED_FOR_GMP="yes"]) + dnl /************************************************************************** dnl * Where is GMP? * @@ -181,21 +154,18 @@ AC_MSG_CHECKING(whether gmp works) if test "$gmp_package" = "no"; then echo "GMP package not defined" AC_MSG_RESULT(no) - TO_BUILD_MP="" else - if test "$NEED_MP" = "no"; then + if test "$ASKED_FOR_GMP" = "no"; then echo "Mode normal GMP" - TO_BUILD="$TO_BUILD MP" AC_CHECK_HEADER(gmp.h, [AC_CHECK_LIB(gmp, __gmpz_init, - [LIBS="$LIBS -lgmp"], - [echo "Can't find gmp library." && - echo "MP version will not be builded." && - TO_BUILD_MP=""])], + [LIBS="$LIBS -lgmp" && + CPPFLAGS="-D$gmp_flag $CPPFLAGS"], + [echo "Cannot find gmp library." && + echo "MP precision will not be supported."])], [echo "Can't find gmp headers." && - echo "MP version will not be builded." && - TO_BUILD_MP=""]) + echo "MP precision will not be supported."]) else dnl Default given by --with-X is "yes", --without-X is "no". We also dnl initialized manually all gmp_package* variables to "yes" (thus they are @@ -204,7 +174,6 @@ else if test "$gmp_package" != "yes" ; then echo "(GMP path has been set by user)" GMP_DIR=$gmp_package - dnl Useful for AC_CHECK_X to find what we want. CPPFLAGS="-I$GMP_DIR/include $CPPFLAGS" LDFLAGS="-L$GMP_DIR/lib $LDFLAGS" fi @@ -219,11 +188,12 @@ else AC_CHECK_HEADER(gmp.h, [], - [AC_MSG_ERROR(Can't find gmp headers.)]) + [AC_MSG_ERROR("Cannot find gmp headers.")]) AC_CHECK_LIB(gmp, __gmpz_init, - [LIBS="$LIBS -lgmp"], - [AC_MSG_ERROR(Can't find gmp library.)]) + [LIBS="$LIBS -lgmp" && + CPPFLAGS="-D$gmp_flag $CPPFLAGS"], + [AC_MSG_ERROR("Cannot find gmp library.")]) AC_MSG_RESULT(yes) fi @@ -237,7 +207,6 @@ dnl **************************************************************************/ dnl Substitutions to do. AC_SUBST(BITS) -AC_SUBST(OPENSCOP_INT_T) AC_SUBST(ac_aux_dir) dnl Configure Makefiles. diff --git a/doc/openscop.texi b/doc/openscop.texi index 0ca8745..38ccb6b 100644 --- a/doc/openscop.texi +++ b/doc/openscop.texi @@ -1865,13 +1865,14 @@ representation (@pxref{OpenScop Core Part File Format Specification}). @group struct openscop_relation @{ int type; /* What this relation is encoding */ + int precision; /* Precision of the matrix elements */ int nb_rows; /* Number of rows */ int nb_columns; /* Number of columns */ int nb_output_dims; /* Number of output dimensions */ int nb_input_dims; /* Number of input dimensions */ int nb_local_dims; /* Number of local dimensions */ int nb_parameters; /* Number of parameters */ - openscop_int_t ** m; /* Matrix of constraints */ + void ** m; /* Matrix of constraints */ struct openscop_relation * next; /* Next relation in the union */ @}; typedef struct openscop_relation openscop_relation_t; @@ -1894,7 +1895,17 @@ may provide some information about what the relation is encoding: @end itemize The various numbers provide the details on the relation itself (@pxref{Relation Representation}) while the @code{m} field points to -the constraint matrix. +the constraint matrix. The precision of the constraint matrix elements is +provided by the @code{precision} field. It can take the following +values: +@itemize @bullet +@item 32: 32 bits precision, elements are @code{long int} + (@code{OPENSCOP_PRECISION_SP}), +@item 64: 64 bits precision, elements are @code{long long int} + (@code{OPENSCOP_PRECISION_DP}), +@item 0: multiple precision, elements are GNU GMP Library's + @code{mpz_t} (@code{OPENSCOP_PRECISION_MP}). +@end itemize @node openscop_relation_list_t @subsubsection openscop_relation_list_t @@ -2069,7 +2080,7 @@ in the @code{parameters} field. The order matters: @code{parameters[0]} corresponds to the first parameter column in the context and the relation, @code{parameters[1]} corresponds to the second one, and so on. The parameter information can be either -generic @code{(void *)} or textual @code{char *)} depending on the +generic (@code{void *}) or textual (@code{char *}) depending on the @code{parameter_type} field: 1 (OPENSCOP_TYPE_STRING) means the information is textual while 0 (OPENSCOP_TYPE_GENERIC) means the information is generic. Finally, it contains the list of @@ -2090,7 +2101,7 @@ by the @code{openscop_scop_dump} function): | | | Language: C | | -| +-- openscop_relation_t (CONTEXT) +| +-- openscop_relation_t (CONTEXT, 64 bits) | | 1 3 0 0 0 1 | | [ 1 1 -1 ] | | @@ -2098,14 +2109,14 @@ by the @code{openscop_scop_dump} function): | | | +-- openscop_statement_t (S1) | | | -| | +-- openscop_relation_t (DOMAIN) +| | +-- openscop_relation_t (DOMAIN, 64 bits) | | | 4 5 2 0 0 1 | | | [ 1 1 0 0 0 ] | | | [ 1 -1 0 1 -1 ] | | | [ 1 0 1 0 0 ] | | | [ 1 0 -1 1 -1 ] | | | -| | +-- openscop_relation_t (SCATTERING) +| | +-- openscop_relation_t (SCATTERING, 64 bits) | | | 5 10 5 2 0 1 | | | [ 0 -1 0 0 0 0 0 0 0 0 ] | | | [ 0 0 -1 0 0 0 1 0 0 0 ] @@ -2115,7 +2126,7 @@ by the @code{openscop_scop_dump} function): | | | | | +-- openscop_relation_list_t | | | | -| | | +-- openscop_relation_t (WRITE) +| | | +-- openscop_relation_t (WRITE, 64 bits) | | | | 3 8 3 2 0 1 | | | | [ 0 -1 0 0 0 0 0 1 ] | | | | [ 0 0 -1 0 1 0 0 0 ] @@ -2132,7 +2143,7 @@ by the @code{openscop_scop_dump} function): | | V | | openscop_statement_t (S2) | | | -| | +-- openscop_relation_t (DOMAIN) +| | +-- openscop_relation_t (DOMAIN, 64 bits) | | | 6 6 3 0 0 1 | | | [ 1 1 0 0 0 0 ] | | | [ 1 -1 0 0 1 -1 ] @@ -2141,7 +2152,7 @@ by the @code{openscop_scop_dump} function): | | | [ 1 0 0 1 0 0 ] | | | [ 1 0 0 -1 1 -1 ] | | | -| | +-- openscop_relation_t (SCATTERING) +| | +-- openscop_relation_t (SCATTERING, 64 bits) | | | 7 13 7 3 0 1 | | | [ 0 -1 0 0 0 0 0 0 0 0 0 0 0 ] | | | [ 0 0 -1 0 0 0 0 0 1 0 0 0 0 ] @@ -2153,7 +2164,7 @@ by the @code{openscop_scop_dump} function): | | | | | +-- openscop_relation_list_t | | | | -| | | +-- openscop_relation_t (WRITE) +| | | +-- openscop_relation_t (WRITE, 64 bits) | | | | 3 9 3 3 0 1 | | | | [ 0 -1 0 0 0 0 0 0 1 ] | | | | [ 0 0 -1 0 1 0 0 0 0 ] @@ -2162,7 +2173,7 @@ by the @code{openscop_scop_dump} function): | | | V | | | openscop_relation_list_t | | | | -| | | +-- openscop_relation_t (READ) +| | | +-- openscop_relation_t (READ, 64 bits) | | | | 3 9 3 3 0 1 | | | | [ 0 -1 0 0 0 0 0 0 1 ] | | | | [ 0 0 -1 0 1 0 0 0 0 ] @@ -2171,7 +2182,7 @@ by the @code{openscop_scop_dump} function): | | | V | | | openscop_relation_list_t | | | | -| | | +-- openscop_relation_t (READ) +| | | +-- openscop_relation_t (READ, 64 bits) | | | | 3 9 3 3 0 1 | | | | [ 0 -1 0 0 0 0 0 0 2 ] | | | | [ 0 0 -1 0 1 0 0 0 0 ] @@ -2180,7 +2191,7 @@ by the @code{openscop_scop_dump} function): | | | V | | | openscop_relation_list_t | | | | -| | | +-- openscop_relation_t (READ) +| | | +-- openscop_relation_t (READ, 64 bits) | | | | 3 9 3 3 0 1 | | | | [ 0 -1 0 0 0 0 0 0 3 ] | | | | [ 0 0 -1 0 0 0 1 0 0 ] @@ -2451,6 +2462,7 @@ source projects should consider to provide some OpenScop file input and output, so they can be incorporated to any OpenScop-based tool chain.}. @menu +* Precision:: * Base Functions:: * Example of OpenScop Library Utilization:: * Installation:: @@ -2458,6 +2470,31 @@ and output, so they can be incorporated to any OpenScop-based tool chain.}. * Development:: @end menu +@node Precision +@section Precision + +The OpenScop specification does not impose a specific type for the +constraint matrix elements. For a maximum flexibility, the OpenScop library +offers an hybrid precision implementation. It supports 32 bits, 64 bits and +multiple precision (relying on GNU GMP) relations transparently. At relation +allocation time, users have two ways to set the precision. The first way is +to call an allocation function with a precision parameter. The second way is +to rely on the environment variable @code{OPENSCOP_PRECISION}. +The accepted values for this variable are @code{32} for 32 bits precision, +@code{64} for 64 bits precision and @code{0} for multiple precision. When this +variable is set, its value becomes the default precision for relation elements. +For instance, to ensure the OpenScop library will use 64 bits precision +by default, the user may set: +@example +export OPENSCOP_PRECISION=64 +@end example +@noindent if his shell is, e.g., bash or +@example +setenv OPENSCOP_PRECISION 64 +@end example +@noindent if his shell is, e.g., tcsh. The user should ad this line to +his .bashrc or .tcshrc (or whatever convenient file) to make this +setting permanent. @node Base Functions @section Base Functions @@ -2585,6 +2622,25 @@ openscop_relation_p openscop_relation_malloc(int nb_rows, int nb_columns); @end group @end example +@noindent The precision of the relation elements will depend on the +@code{OPENSCOP_PRECISION} environment variable (@pxref{Precision}) if it is set, +or the maximum available precision if it is not set. Another allocation +function is provided to explicitly set a given precision: + +@example +@group +openscop_relation_p openscop_relation_pmalloc(int precision, + int nb_rows, int nb_columns); +@end group +@end example + +@noindent The @code{precision} field may take the following values: +@itemize @bullet +@item @code{OPENSCOP_PRECISION_SP} for 32 bits precision, +@item @code{OPENSCOP_PRECISION_DP} for 64 bits precision, +@item @code{OPENSCOP_PRECISION_MP} for multiple precision, +@end itemize + @node Deallocating @subsection Deallocating: openscop_@emph{structure}_free @@ -2685,7 +2741,7 @@ more test.scop | ./example @node License @subsection License First of all, it would be very kind to refer the present document in any -publication that result from the use of the OpenScop specification or library, +publication that results from the use of the OpenScop specification or library, @pxref{Bas11} (a bibtex entry is provided behind the title page of this manual, along with the copyright notice). The OpenScop Library is provided under the 3-clause BSD license: diff --git a/include/Makefile.am b/include/Makefile.am index 23064fc..f4679d7 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -91,6 +91,7 @@ pkginclude_HEADERS = \ openscop/relation_list.h \ openscop/body.h \ openscop/macros.h \ + openscop/int.h \ openscop/names.h \ openscop/strings.h \ openscop/util.h \ diff --git a/include/openscop/vector.h b/include/openscop/int.h similarity index 72% copy from include/openscop/vector.h copy to include/openscop/int.h index 8244f1d..dec2a91 100644 --- a/include/openscop/vector.h +++ b/include/openscop/int.h @@ -2,9 +2,9 @@ /*+-----------------------------------------------------------------** ** OpenScop Library ** **-----------------------------------------------------------------** - ** vector.h ** + ** int.h ** **-----------------------------------------------------------------** - ** First version: 01/05/2008 ** + ** First version: 18/07/2011 ** **-----------------------------------------------------------------** @@ -61,60 +61,62 @@ *****************************************************************************/ -#ifndef OPENSCOP_VECTOR_H -# define OPENSCOP_VECTOR_H +#ifndef OPENSCOP_INT_H +# define OPENSCOP_INT_H -# include # include +# ifdef OPENSCOP_GMP_IS_HERE +# include +# endif -# if defined(__cplusplus) -extern "C" - { -# endif +/*+*************************************************************************** + * Basic Functions * + *****************************************************************************/ -/** - * The openscop_vector_t structure stores a vector information in the PolyLib - * format (the first entry has a specific meaning). When a vector - * describes a linear constraint, a 0 means it is an equality == 0, a 1 means - * an inequality >= 0. When the vector describes an array access, a number - * different than 0 is the array identifier. - */ -struct openscop_vector { - unsigned size; /**< The number of vector entries */ - openscop_int_t * v; /**< An array of values */ -}; -typedef struct openscop_vector openscop_vector_t; -typedef struct openscop_vector * openscop_vector_p; +void openscop_int_dump_precision(FILE *, int); +int openscop_int_sizeof(int); +void * openscop_int_address(int, void *, int); +void openscop_int_init(int, void *, int); +void openscop_int_assign(int, void *, int, void *, int); +void openscop_int_set_si(int, void *, int, int); +int openscop_int_get_si(int, void *, int); +void openscop_int_init_set_si(int, void *, int, int); +void openscop_int_clear(int, void *, int); +void openscop_int_print(FILE *, int, void *, int); +void openscop_int_sprint(char *, int, void *, int); +void openscop_int_sread(char *, int, void *, int); /*+*************************************************************************** - * Structure display function * + * Arithmetic Operations * *****************************************************************************/ -void openscop_vector_idump(FILE *, openscop_vector_p, int); -void openscop_vector_dump(FILE *, openscop_vector_p); -/*+*************************************************************************** - * Memory allocation/deallocation function * - *****************************************************************************/ -openscop_vector_p openscop_vector_malloc(unsigned); -void openscop_vector_free(openscop_vector_p); +void openscop_int_increment(int, void *, int, void *, int); +void openscop_int_add(int, void *, int, void *, int, void *, int); +void openscop_int_add_ui(int, void *, int, void *, int, int); +void openscop_int_mul(int, void *, int, void *, int, void *, int); +void openscop_int_mul_si(int, void *, int, void *, int, int); +void openscop_int_sub(int, void *, int, void *, int, void *, int); +void openscop_int_oppose(int, void *, int, void *, int); /*+*************************************************************************** - * Processing functions * + * Conditional Operations * *****************************************************************************/ -openscop_vector_p openscop_vector_add_scalar(openscop_vector_p, int); -openscop_vector_p openscop_vector_mul_scalar(openscop_vector_p, int); -openscop_vector_p openscop_vector_add(openscop_vector_p, openscop_vector_p); -openscop_vector_p openscop_vector_sub(openscop_vector_p, openscop_vector_p); -void openscop_vector_tag_inequality(openscop_vector_p); -void openscop_vector_tag_equality(openscop_vector_p); -int openscop_vector_equal(openscop_vector_p, openscop_vector_p); - -# if defined(__cplusplus) - } -# endif -#endif /* define OPENSCOP_VECTOR_H */ + + +int openscop_int_eq(int, void *, int, void *, int); +int openscop_int_ne(int, void *, int, void *, int); +int openscop_int_pos(int, void *, int); +int openscop_int_neg(int, void *, int); +int openscop_int_zero(int, void *, int); +int openscop_int_notzero(int, void *, int); +int openscop_int_one(int, void *, int); +int openscop_int_mone(int, void *, int); +int openscop_int_divisible(int, void *, int, void *, int); + + +#endif /* define OPENSCOP_INT_H */ diff --git a/include/openscop/macros.h b/include/openscop/macros.h index 4942ffc..3393b4d 100644 --- a/include/openscop/macros.h +++ b/include/openscop/macros.h @@ -65,30 +65,24 @@ # define OPENSCOP_MACROS_H -# if defined(OPENSCOP_INT_T_IS_LONGLONG) -# define OPENSCOP_FMT "%4lld" -# define OPENSCOP_FMT_TXT "%lld" -# define openscop_int_t long long +# define OPENSCOP_TAG_START_SCOP "" +# define OPENSCOP_TAG_END_SCOP "" -# elif defined(OPENSCOP_INT_T_IS_LONG) -# define OPENSCOP_FMT "%4ld" -# define OPENSCOP_FMT_TXT "%ld" -# define openscop_int_t long int +# define OPENSCOP_PRECISION_ENV "OPENSCOP_PRECISION" +# define OPENSCOP_PRECISION_ENV_SP "32" +# define OPENSCOP_PRECISION_ENV_DP "64" +# define OPENSCOP_PRECISION_ENV_MP "0" +# define OPENSCOP_PRECISION_SP 32 +# define OPENSCOP_PRECISION_DP 64 +# define OPENSCOP_PRECISION_MP 0 -# elif defined(OPENSCOP_INT_T_IS_MP) /* GNUMP */ -#include -# define OPENSCOP_FMT "%4s" -# define OPENSCOP_FMT_TXT "%s" -# define openscop_int_t mpz_t +# define OPENSCOP_FMT_SP "%4ld" +# define OPENSCOP_FMT_DP "%4lld" +# define OPENSCOP_FMT_MP "%4s" +# define OPENSCOP_FMT_TXT_SP "%ld" +# define OPENSCOP_FMT_TXT_DP "%lld" +# define OPENSCOP_FMT_TXT_MP "%s" -# else -# error Define OPENSCOP_INT_T_IS_xxx to use this file. - -# endif - - -# define OPENSCOP_TAG_START_SCOP "" -# define OPENSCOP_TAG_END_SCOP "" # define OPENSCOP_DEBUG 0 // 1 for debug mode, 0 otherwise. # define OPENSCOP_BACKEND_C 0 @@ -137,105 +131,17 @@ exit(1); \ } while (0) -# define OPENSCOP_malloc(ptr,type,size) \ +# define OPENSCOP_malloc(ptr, type, size) \ do { \ if (((ptr) = (type)malloc(size)) == NULL) \ OPENSCOP_error("memory overflow"); \ } while (0) -# define OPENSCOP_realloc(ptr,type,size) \ +# define OPENSCOP_realloc(ptr, type, size) \ do { \ - if (((ptr) = (type)realloc(ptr,size)) == NULL) \ + if (((ptr) = (type)realloc(ptr, size)) == NULL) \ OPENSCOP_error("memory overflow"); \ } while (0) -/*+*************************************************************************** - * OPENSCOP GMP MACROS * - *****************************************************************************/ -# ifdef OPENSCOP_INT_T_IS_MP -/* Basic Macros */ -# define OPENSCOP_INT_init(val) mpz_init(val) -# define OPENSCOP_INT_assign(v1,v2) mpz_set(v1,v2) -# define OPENSCOP_INT_set_si(val,i) mpz_set_si(val,i) -# define OPENSCOP_INT_get_si(val) mpz_get_si(val) -# define OPENSCOP_INT_init_set_si(val,i) mpz_init_set_si(val,i) -# define OPENSCOP_INT_clear(val) mpz_clear(val) -# define OPENSCOP_INT_dump(Dst,fmt,val) \ - do { \ - char *str; \ - str = mpz_get_str(0,10,val); \ - fprintf(Dst,fmt,str); \ - free(str); \ - } while (0) -# define OPENSCOP_INT_sprint(Dst,fmt,val) \ - do { \ - char * str; \ - str = mpz_get_str(0,10,val); \ - sprintf(Dst,fmt,str); \ - free(str); \ - } while (0) - -/* Boolean operators on 'openscop_int_t' */ -# define OPENSCOP_INT_eq(v1,v2) (mpz_cmp(v1,v2) == 0) -# define OPENSCOP_INT_ne(v1,v2) (mpz_cmp(v1,v2) != 0) - -/* Binary operators on 'openscop_int_t' */ -# define OPENSCOP_INT_increment(ref,val) mpz_add_ui(ref,val,1) -# define OPENSCOP_INT_addto(ref,val1,val2) mpz_add(ref,val1,val2) -# define OPENSCOP_INT_multo(ref,val1,val2) mpz_mul(ref,val1,val2) -# define OPENSCOP_INT_add_int(ref,val,vint) mpz_add_ui(ref,val,(long)vint) -# define OPENSCOP_INT_subtract(ref,val1,val2) mpz_sub(ref,val1,val2) -# define OPENSCOP_INT_oppose(ref,val) mpz_neg(ref,val) -# define OPENSCOP_INT_fdiv(ref,n,d) mpz_fdiv_q(ref,n,d) - -/* Conditional operations on 'openscop_int_t' */ -# define OPENSCOP_INT_pos_p(val) (mpz_sgn(val) > 0) -# define OPENSCOP_INT_neg_p(val) (mpz_sgn(val) < 0) -# define OPENSCOP_INT_zero_p(val) (mpz_sgn(val) == 0) -# define OPENSCOP_INT_notzero_p(val) (mpz_sgn(val) != 0) -# define OPENSCOP_INT_one_p(val) (mpz_cmp_si(val,1) == 0) -# define OPENSCOP_INT_mone_p(val) (mpz_cmp_si(val,-1) == 0) -# define OPENSCOP_INT_divisible(val1,val2) mpz_divisible_p(val1,val2) - -/*+*************************************************************************** - * OPENSCOP BASIC TYPES MACROS * - *****************************************************************************/ -# else -/* Basic Macros */ -# define OPENSCOP_INT_init(val) val = 0 -# define OPENSCOP_INT_assign(v1,v2) v1 = v2 -# define OPENSCOP_INT_set_si(val,i) val = (openscop_int_t)i -# define OPENSCOP_INT_get_si(val) val -# define OPENSCOP_INT_init_set_si(val,i) val = (openscop_int_t)i -# define OPENSCOP_INT_clear(val) val = 0 -# define OPENSCOP_INT_dump(Dst,fmt,val) fprintf(Dst,fmt,val) -# define OPENSCOP_INT_sprint(Dst,fmt,val) sprintf(Dst,fmt,val) - -/* Boolean operators on 'openscop_int_t' */ -# define OPENSCOP_INT_eq(v1,v2) (v1 == v2) -# define OPENSCOP_INT_ne(v1,v2) (v1 != v2) -# define OPENSCOP_INT_lt(v1,v2) (v1 < v2) -# define OPENSCOP_INT_gt(v1,v2) (v1 > v2) - -/* Binary operators on 'openscop_int_t' */ -# define OPENSCOP_INT_increment(ref,val) ref = val + (openscop_int_t)1 -# define OPENSCOP_INT_addto(ref,val1,val2) ref = val1 + val2 -# define OPENSCOP_INT_multo(ref,val1,val2) ref = val1 * val2 -# define OPENSCOP_INT_add_int(ref,val,vint) ref = val+(openscop_int_t)vint -# define OPENSCOP_INT_subtract(ref,val1,val2) ref = val1 - val2 -# define OPENSCOP_INT_oppose(ref,val) ref = -val -# define OPENSCOP_INT_fdiv(ref,n,d) ref = n / d - -/* Conditional operations on 'openscop_int_t' */ -# define OPENSCOP_INT_pos_p(val) OPENSCOP_INT_gt(val,0) -# define OPENSCOP_INT_neg_p(val) OPENSCOP_INT_lt(val,0) -# define OPENSCOP_INT_zero_p(val) OPENSCOP_INT_eq(val,0) -# define OPENSCOP_INT_notzero_p(val) OPENSCOP_INT_ne(val,0) -# define OPENSCOP_INT_one_p(val) OPENSCOP_INT_eq(val,1) -# define OPENSCOP_INT_mone_p(val) OPENSCOP_INT_eq(val,-1) -# define OPENSCOP_INT_divisible(val1,val2) ((val1 % val2) == 0) - -# endif - #endif /* define OPENSCOP_MACROS_H */ diff --git a/include/openscop/openscop.h b/include/openscop/openscop.h index 6d37f0a..0d1ca68 100644 --- a/include/openscop/openscop.h +++ b/include/openscop/openscop.h @@ -66,6 +66,7 @@ # include +# include # include # include # include diff --git a/include/openscop/relation.h b/include/openscop/relation.h index 83511c9..075d527 100644 --- a/include/openscop/relation.h +++ b/include/openscop/relation.h @@ -66,6 +66,7 @@ # include # include +# include # include # include # include @@ -104,14 +105,15 @@ extern "C" */ struct openscop_relation { int type; /**< Semantics about the relation */ - int nb_rows; /**< The number of rows */ - int nb_columns; /**< The number of columns */ - int nb_output_dims; /**< The number of output dimensions */ - int nb_input_dims; /**< The number of input dimensions */ - int nb_local_dims; /**< The number of local (existentially + int precision; /**< Precision of relation matrix elements*/ + int nb_rows; /**< Number of rows */ + int nb_columns; /**< Number of columns */ + int nb_output_dims; /**< Number of output dimensions */ + int nb_input_dims; /**< Number of input dimensions */ + int nb_local_dims; /**< Number of local (existentially quantified) dimensions */ - int nb_parameters; /**< The number of parameters */ - openscop_int_t ** m; /**< An array of pointers to the beginning + int nb_parameters; /**< Number of parameters */ + void ** m; /**< An array of pointers to the beginning of each row of the relation matrix */ struct openscop_relation * next; /**< Pointer to the next relation in the union of relations (NULL if none) */ @@ -144,6 +146,7 @@ openscop_relation_p openscop_relation_read_arrays(FILE *, char ***, int *); /*+*************************************************************************** * Memory allocation/deallocation function * *****************************************************************************/ +openscop_relation_p openscop_relation_pmalloc(int, int, int); openscop_relation_p openscop_relation_malloc(int, int); void openscop_relation_free_inside(openscop_relation_p); void openscop_relation_free(openscop_relation_p); diff --git a/include/openscop/scop.h.in b/include/openscop/scop.h.in index 0616ab5..2610a42 100644 --- a/include/openscop/scop.h.in +++ b/include/openscop/scop.h.in @@ -73,9 +73,6 @@ # define OPENSCOP_RELEASE "@PACKAGE_VERSION@" # define OPENSCOP_VERSION "@BITS@" -# ifndef @OPENSCOP_INT_T@ -# define @OPENSCOP_INT_T@ -# endif # include # include diff --git a/include/openscop/util.h b/include/openscop/util.h index 5881309..921e9b5 100644 --- a/include/openscop/util.h +++ b/include/openscop/util.h @@ -81,6 +81,7 @@ char * openscop_util_read_tail(FILE *); char * openscop_util_read_uptotag(FILE *, char *); char * openscop_util_tag_content(char *, char *, char *); void openscop_util_safe_strcat(char **, char *, int *); +int openscop_util_get_precision(); # if defined(__cplusplus) diff --git a/include/openscop/vector.h b/include/openscop/vector.h index 8244f1d..7f12146 100644 --- a/include/openscop/vector.h +++ b/include/openscop/vector.h @@ -66,6 +66,8 @@ # include # include +# include +# include # if defined(__cplusplus) @@ -82,8 +84,9 @@ extern "C" * different than 0 is the array identifier. */ struct openscop_vector { - unsigned size; /**< The number of vector entries */ - openscop_int_t * v; /**< An array of values */ + int size; /**< Number of vector entries */ + int precision; /**< Precision of the integer elements. */ + void * v; /**< An array of values */ }; typedef struct openscop_vector openscop_vector_t; typedef struct openscop_vector * openscop_vector_p; @@ -99,7 +102,8 @@ void openscop_vector_dump(FILE *, openscop_vector_p); /*+*************************************************************************** * Memory allocation/deallocation function * *****************************************************************************/ -openscop_vector_p openscop_vector_malloc(unsigned); +openscop_vector_p openscop_vector_pmalloc(int, int); +openscop_vector_p openscop_vector_malloc(int); void openscop_vector_free(openscop_vector_p); diff --git a/source/Makefile.am b/source/Makefile.am index b8046ff..3363579 100644 --- a/source/Makefile.am +++ b/source/Makefile.am @@ -97,6 +97,7 @@ libopenscop_la_SOURCES = \ body.c \ vector.c \ strings.c \ + int.c \ names.c \ util.c diff --git a/source/body.c b/source/body.c index 07af853..64c6b53 100644 --- a/source/body.c +++ b/source/body.c @@ -130,7 +130,7 @@ void openscop_body_idump(FILE * file, openscop_body_p body, int level) { /** * openscop_body_dump function: - * This function prints the content of a openscop_body_t structure + * this function prints the content of an openscop_body_t structure * (*body) into a file (file, possibly stdout). * \param file[in] File where informations are printed. * \param body[in] The body whose information has to be printed. @@ -142,7 +142,7 @@ void openscop_body_dump(FILE * file, openscop_body_p body) { /** * openscop_body_print function: - * This function prints the content of a openscop_body_t structure + * this function prints the content of an openscop_body_t structure * (*body) into a file (file, possibly stdout) in the OpenScop format. * \param file[in] File where informations are printed. * \param body[in] The body whose information has to be printed. @@ -171,7 +171,7 @@ void openscop_body_print(FILE * file, openscop_body_p body) { /** * openscop_body_read function: - * This function reads a openscop_body_t structure from an input stream + * this function reads an openscop_body_t structure from an input stream * (possibly stdin). * \param[in] file The input stream. * \param[in] nb_iterators The number of iterators. @@ -220,7 +220,7 @@ openscop_body_p openscop_body_read(FILE * file, int nb_iterators) { /** * openscop_body_malloc function: - * This function allocates the memory space for a openscop_body_t + * this function allocates the memory space for an openscop_body_t * structure and sets its fields with default values. Then it returns a pointer * to the allocated space. * \return A pointer to an empty body with fields set to default values. @@ -239,7 +239,7 @@ openscop_body_p openscop_body_malloc() { /** * openscop_body_free function: - * This function frees the allocated memory for a openscop_body_t + * this function frees the allocated memory for an openscop_body_t * structure. * \param[in,out] body The pointer to the body we want to free. */ @@ -262,7 +262,7 @@ void openscop_body_free(openscop_body_p body) { /** * openscop_body_clone function: - * This functions builds and returns a "hard copy" (not a pointer copy) of an + * this functions builds and returns a "hard copy" (not a pointer copy) of an * openscop_body_t data structure provided as parameter. However, let us * recall here that non-string elements are untouched by the OpenScop Library. * \param[in] body The pointer to the body we want to copy. @@ -287,7 +287,7 @@ openscop_body_p openscop_body_clone(openscop_body_p body) { /** * openscop_body_equal function: - * This function returns true if the two bodies are the same, false + * this function returns true if the two bodies are the same, false * otherwise (the usr field is not tested). However, let us * recall here that non-string elements are untouched by the OpenScop Library. * \param b1 The first body. @@ -335,7 +335,7 @@ int openscop_body_equal(openscop_body_p b1, openscop_body_p b2) { /** * openscop_body_integrity_check function: - * This function checks that a body is "well formed" according to some + * this function checks that a body is "well formed" according to some * expected properties (setting an expected value to OPENSCOP_UNDEFINED means * that we do not expect a specific value). It returns 0 if the check failed * or 1 if no problem has been detected. diff --git a/source/int.c b/source/int.c new file mode 100644 index 0000000..d8f11fe --- /dev/null +++ b/source/int.c @@ -0,0 +1,794 @@ + + /*+-----------------------------------------------------------------** + ** OpenScop Library ** + **-----------------------------------------------------------------** + ** int.c ** + **-----------------------------------------------------------------** + ** First version: 18/07/2011 ** + **-----------------------------------------------------------------** + + + ***************************************************************************** + * OpenScop: Structures and formats for polyhedral tools to talk together * + ***************************************************************************** + * ,___,,_,__,,__,,__,,__,,_,__,,_,__,,__,,___,_,__,,_,__, * + * / / / // // // // / / / // // / / // / /|,_, * + * / / / // // // // / / / // // / / // / / / /\ * + * |~~~|~|~~~|~~~|~~~|~~~|~|~~~|~|~~~|~~~|~~~|~|~~~|~|~~~|/_/ \ * + * | G |C| P | = | L | P |=| = |C| = | = | = |=| = |=| C |\ \ /\ * + * | R |l| o | = | e | l |=| = |a| = | = | = |=| = |=| L | \# \ /\ * + * | A |a| l | = | t | u |=| = |n| = | = | = |=| = |=| o | |\# \ \ * + * | P |n| l | = | s | t |=| = |d| = | = | = | | |=| o | | \# \ \ * + * | H | | y | | e | o | | = |l| | | = | | | | G | | \ \ \ * + * | I | | | | e | | | | | | | | | | | | | \ \ \ * + * | T | | | | | | | | | | | | | | | | | \ \ \ * + * | E | | | | | | | | | | | | | | | | | \ \ \ * + * | * |*| * | * | * | * |*| * |*| * | * | * |*| * |*| * | / \* \ \ * + * | O |p| e | n | S | c |o| p |-| L | i | b |r| a |r| y |/ \ \ / * + * '---'-'---'---'---'---'-'---'-'---'---'---'-'---'-'---' '--' * + * * + * Copyright (C) 2008 University Paris-Sud 11 and INRIA * + * * + * (3-clause BSD license) * + * Redistribution and use in source and binary forms, with or without * + * modification, are permitted provided that the following conditions * + * are met: * + * * + * 1. Redistributions of source code must retain the above copyright notice, * + * this list of conditions and the following disclaimer. * + * 2. Redistributions in binary form must reproduce the above copyright * + * notice, this list of conditions and the following disclaimer in the * + * documentation and/or other materials provided with the distribution. * + * 3. The name of the author may not be used to endorse or promote products * + * derived from this software without specific prior written permission. * + * * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * * + * OpenScop Library, a library to manipulate OpenScop formats and data * + * structures. Written by: * + * Cedric Bastoul and * + * Louis-Noel Pouchet * + * * + *****************************************************************************/ + +# include +# include +# include + + +/*+*************************************************************************** + * Basic Functions * + *****************************************************************************/ + + +/** + * openscop_int_dump_precision function: + * this function prints in a human readable fashion the precision + * corresponding to the "precision" parameter. + * \param[in] file The file where to print the precision. + * \param[in] precision The precision to print. + */ +void openscop_int_dump_precision(FILE * file, int precision) { + + switch (precision) { + case OPENSCOP_PRECISION_SP: + fprintf(file, "32 bits"); + break; + case OPENSCOP_PRECISION_DP: + fprintf(file, "64 bits"); + break; +#ifdef OPENSCOP_GMP_IS_HERE + case OPENSCOP_PRECISION_MP: + fprintf(file, "GMP"); + break; +#endif + default: + fprintf(file, "unknown precision %d", precision); + } +} + + +int openscop_int_sizeof(int precision) { + switch (precision) { + case OPENSCOP_PRECISION_SP: + return sizeof(long int); + + case OPENSCOP_PRECISION_DP: + return sizeof(long long int); + +#ifdef OPENSCOP_GMP_IS_HERE + case OPENSCOP_PRECISION_MP: + return sizeof(mpz_t); +#endif + + default: + OPENSCOP_error("unknown precision"); + } +} + + +void * openscop_int_address(int precision, void * base, int offset) { + switch (precision) { + case OPENSCOP_PRECISION_SP: + return (long int *)base + offset; + + case OPENSCOP_PRECISION_DP: + return (long long int *)base + offset; + +#ifdef OPENSCOP_GMP_IS_HERE + case OPENSCOP_PRECISION_MP: + return (mpz_t *)base + offset; +#endif + + default: + OPENSCOP_error("unknown precision"); + } +} + + +void openscop_int_init(int precision, void * value_base, int value_offset) { + void * value = openscop_int_address(precision, value_base, value_offset); + + switch (precision) { + case OPENSCOP_PRECISION_SP: + *(long int *)value = 0; + break; + + case OPENSCOP_PRECISION_DP: + *(long long int *)value = 0; + break; + +#ifdef OPENSCOP_GMP_IS_HERE + case OPENSCOP_PRECISION_MP: + mpz_init(*(mpz_t *)value); + break; +#endif + + default: + OPENSCOP_error("unknown precision"); + } +} + + +void openscop_int_assign(int precision, + void * val1_base, int val1_offset, + void * val2_base, int val2_offset) { + void * val1 = openscop_int_address(precision, val1_base, val1_offset); + void * val2 = openscop_int_address(precision, val2_base, val2_offset); + + switch (precision) { + case OPENSCOP_PRECISION_SP: + *(long int *)val1 = *(long int *)val2; + break; + + case OPENSCOP_PRECISION_DP: + *(long long int *)val1 = *(long long int *)val2; + break; + +#ifdef OPENSCOP_GMP_IS_HERE + case OPENSCOP_PRECISION_MP: + mpz_set(*(mpz_t *)val1, *(mpz_t *)val2); + break; +#endif + + default: + OPENSCOP_error("unknown precision"); + } +} + + +void openscop_int_set_si(int precision, void * value_base, int value_offset, + int i) { + void * value = openscop_int_address(precision, value_base, value_offset); + + switch (precision) { + case OPENSCOP_PRECISION_SP: + *(long int *)value = (long int)i; + break; + + case OPENSCOP_PRECISION_DP: + *(long long int *)value = (long long int)i; + break; + +#ifdef OPENSCOP_GMP_IS_HERE + case OPENSCOP_PRECISION_MP: + mpz_set_si(*(mpz_t *)value, i); + break; +#endif + + default: + OPENSCOP_error("unknown precision"); + } +} + + +int openscop_int_get_si(int precision, void * value_base, int value_offset) { + void * value = openscop_int_address(precision, value_base, value_offset); + + switch (precision) { + case OPENSCOP_PRECISION_SP: + return *(int *)value; + + case OPENSCOP_PRECISION_DP: + return *(int *)value; + +#ifdef OPENSCOP_GMP_IS_HERE + case OPENSCOP_PRECISION_MP: + return mpz_get_si(*(mpz_t *)value); +#endif + + default: + OPENSCOP_error("unknown precision"); + } +} + + +void openscop_int_init_set_si(int precision, + void * value_base, int value_offset, int i) { + void * value = openscop_int_address(precision, value_base, value_offset); + + switch (precision) { + case OPENSCOP_PRECISION_SP: + *(long int *)value = (long int)i; + break; + + case OPENSCOP_PRECISION_DP: + *(long long int *)value = (long long int)i; + break; + +#ifdef OPENSCOP_GMP_IS_HERE + case OPENSCOP_PRECISION_MP: + mpz_init_set_si(*(mpz_t *)value, i); + break; +#endif + + default: + OPENSCOP_error("unknown precision"); + } +} + + +void openscop_int_clear(int precision, void * value_base, int value_offset) { + void * value = openscop_int_address(precision, value_base, value_offset); + + switch (precision) { + case OPENSCOP_PRECISION_SP: + *(long int *)value = 0; + break; + + case OPENSCOP_PRECISION_DP: + *(long long int *)value = 0; + break; + +#ifdef OPENSCOP_GMP_IS_HERE + case OPENSCOP_PRECISION_MP: + mpz_clear(*(mpz_t *)value); + break; +#endif + + default: + OPENSCOP_error("unknown precision"); + } +} + + +/** + * openscop_int_print function: + * this function displays an integer value into a file (file, possibly stdout). + * \param file The file where the integer has to be printed. + * \param precision The precision of the integer. + * \param value Address of the integer value. + */ +void openscop_int_print(FILE * file, int precision, + void * value_base, int value_offset) { + void * value = openscop_int_address(precision, value_base, value_offset); + + switch (precision) { + case OPENSCOP_PRECISION_SP: + fprintf(file, OPENSCOP_FMT_SP, *(long int *)value); + break; + + case OPENSCOP_PRECISION_DP: + fprintf(file, OPENSCOP_FMT_DP, *(long long int *)value); + break; + +#ifdef OPENSCOP_GMP_IS_HERE + case OPENSCOP_PRECISION_MP: { + char * str; + str = mpz_get_str(0, 10, *(mpz_t *)value); //TODO: 10 -> #define + fprintf(file, OPENSCOP_FMT_MP, str); + free(str); + break; + } +#endif + + default: + OPENSCOP_error("unknown precision"); + } +} + + +/** + * openscop_int_sprint function: + * this function prints an integer value into a string. + * \param string The string where the integer has to be printed. + * \param precision The precision of the integer. + * \param value Address of the integer value. + */ +void openscop_int_sprint(char * string, int precision, + void * value_base, int value_offset) { + void * value = openscop_int_address(precision, value_base, value_offset); + + switch (precision) { + case OPENSCOP_PRECISION_SP: + sprintf(string, OPENSCOP_FMT_SP, *(long int *)value); + break; + + case OPENSCOP_PRECISION_DP: + sprintf(string, OPENSCOP_FMT_DP, *(long long int *)value); + break; + +#ifdef OPENSCOP_GMP_IS_HERE + case OPENSCOP_PRECISION_MP: { + char * str; + str = mpz_get_str(0, 10, *(mpz_t *)value); //TODO: 10 -> #define + sprintf(string, OPENSCOP_FMT_MP, str); + free(str); + break; + } +#endif + + default: + OPENSCOP_error("unknown precision"); + } +} + + +void openscop_int_sread(char * string, int precision, + void * value_base, int value_offset) { + void * value = openscop_int_address(precision, value_base, value_offset); + int nb_read; + + switch (precision) { + case OPENSCOP_PRECISION_SP: + nb_read = sscanf(string, OPENSCOP_FMT_TXT_SP, (long int *)value); + if (nb_read == 0) + OPENSCOP_error("failed to read an integer"); + break; + + case OPENSCOP_PRECISION_DP: + nb_read = sscanf(string, OPENSCOP_FMT_TXT_DP, (long long int *)value); + if (nb_read == 0) + OPENSCOP_error("failed to read an integer"); + break; + +#ifdef OPENSCOP_GMP_IS_HERE + case OPENSCOP_PRECISION_MP: { + long long int tmp; + nb_read = sscanf(string, OPENSCOP_FMT_TXT_DP, &tmp); + if (nb_read == 0) + OPENSCOP_error("failed to read an integer"); + mpz_set_si(*(mpz_t *)value, tmp); + break; + } +#endif + + default: + OPENSCOP_error("unknown precision"); + } +} + + +/*+*************************************************************************** + * Arithmetic Operations * + *****************************************************************************/ + + +void openscop_int_increment(int precision, + void * result_base, int result_offset, + void * value_base, int value_offset) { + void * result = openscop_int_address(precision, result_base, result_offset); + void * value = openscop_int_address(precision, value_base, value_offset); + + switch (precision) { + case OPENSCOP_PRECISION_SP: + *(long int *)result = *(long int *)value + (long int)1; + break; + + case OPENSCOP_PRECISION_DP: + *(long long int *)result = *(long long int *)value + (long long int)1; + break; + +#ifdef OPENSCOP_GMP_IS_HERE + case OPENSCOP_PRECISION_MP: + mpz_add_ui(*(mpz_t *)result, *(mpz_t *)value, 1); + break; +#endif + + default: + OPENSCOP_error("unknown precision"); + } +} + + +void openscop_int_add(int precision, + void * result_base, int result_offset, + void * val1_base, int val1_offset, + void * val2_base, int val2_offset) { + void * result = openscop_int_address(precision, result_base, result_offset); + void * val1 = openscop_int_address(precision, val1_base, val1_offset); + void * val2 = openscop_int_address(precision, val2_base, val2_offset); + + switch (precision) { + case OPENSCOP_PRECISION_SP: + *(long int *)result = *(long int *)val1 + *(long int *)val2; + break; + + case OPENSCOP_PRECISION_DP: + *(long long int *)result = *(long long int *)val1 + + *(long long int *)val2; + break; + +#ifdef OPENSCOP_GMP_IS_HERE + case OPENSCOP_PRECISION_MP: + mpz_add(*(mpz_t *)result, *(mpz_t *)val1, *(mpz_t *)val2); + break; +#endif + + default: + OPENSCOP_error("unknown precision"); + } +} + + +void openscop_int_add_ui(int precision, + void * result_base, int result_offset, + void * value_base, int value_offset, int i) { + void * result = openscop_int_address(precision, result_base, result_offset); + void * value = openscop_int_address(precision, value_base, value_offset); + + switch (precision) { + case OPENSCOP_PRECISION_SP: + *(long int *)result = *(long int *)value + (long int)i; + break; + + case OPENSCOP_PRECISION_DP: + *(long long int *)result = *(long long int *)value + (long long int)i; + break; + +#ifdef OPENSCOP_GMP_IS_HERE + case OPENSCOP_PRECISION_MP: + mpz_add_ui(*(mpz_t *)result, *(mpz_t *)value, (long int)i); + break; +#endif + + default: + OPENSCOP_error("unknown precision"); + } +} + + +void openscop_int_mul(int precision, + void * result_base, int result_offset, + void * val1_base, int val1_offset, + void * val2_base, int val2_offset) { + void * result = openscop_int_address(precision, result_base, result_offset); + void * val1 = openscop_int_address(precision, val1_base, val1_offset); + void * val2 = openscop_int_address(precision, val2_base, val2_offset); + + switch (precision) { + case OPENSCOP_PRECISION_SP: + *(long int *)result = *(long int *)val1 * *(long int *)val2; + break; + + case OPENSCOP_PRECISION_DP: + *(long long int *)result = *(long long int *)val1 * + *(long long int *)val2; + break; + +#ifdef OPENSCOP_GMP_IS_HERE + case OPENSCOP_PRECISION_MP: + mpz_mul(*(mpz_t *)result, *(mpz_t *)val1, *(mpz_t *)val2); + break; +#endif + + default: + OPENSCOP_error("unknown precision"); + } +} + + +void openscop_int_mul_si(int precision, + void * result_base, int result_offset, + void * value_base, int value_offset, int i) { + void * result = openscop_int_address(precision, result_base, result_offset); + void * value = openscop_int_address(precision, value_base, value_offset); + + switch (precision) { + case OPENSCOP_PRECISION_SP: + *(long int *)result = *(long int *)value * (long int)i; + break; + + case OPENSCOP_PRECISION_DP: + *(long long int *)result = *(long long int *)value * (long long int)i; + break; + +#ifdef OPENSCOP_GMP_IS_HERE + case OPENSCOP_PRECISION_MP: + mpz_mul_si(*(mpz_t *)result, *(mpz_t *)value, i); + break; +#endif + + default: + OPENSCOP_error("unknown precision"); + } +} + + +void openscop_int_sub(int precision, + void * result_base, int result_offset, + void * val1_base, int val1_offset, + void * val2_base, int val2_offset) { + void * result = openscop_int_address(precision, result_base, result_offset); + void * val1 = openscop_int_address(precision, val1_base, val1_offset); + void * val2 = openscop_int_address(precision, val2_base, val2_offset); + + switch (precision) { + case OPENSCOP_PRECISION_SP: + *(long int *)result = *(long int *)val1 - *(long int *)val2; + break; + + case OPENSCOP_PRECISION_DP: + *(long long int *)result = *(long long int *)val1 - + *(long long int *)val2; + break; + +#ifdef OPENSCOP_GMP_IS_HERE + case OPENSCOP_PRECISION_MP: + mpz_sub(*(mpz_t *)result, *(mpz_t *)val1, *(mpz_t *)val2); + break; +#endif + + default: + OPENSCOP_error("unknown precision"); + } +} + + +void openscop_int_oppose(int precision, + void * result_base, int result_offset, + void * value_base, int value_offset) { + void * result = openscop_int_address(precision, result_base, result_offset); + void * value = openscop_int_address(precision, value_base, value_offset); + + switch (precision) { + case OPENSCOP_PRECISION_SP: + *(long int *)result = -*(long int *)value; + break; + + case OPENSCOP_PRECISION_DP: + *(long long int *)result = -*(long long int *)value; + break; + +#ifdef OPENSCOP_GMP_IS_HERE + case OPENSCOP_PRECISION_MP: + mpz_neg(*(mpz_t *)result, *(mpz_t *)value); + break; +#endif + + default: + OPENSCOP_error("unknown precision"); + } +} + + +/*+*************************************************************************** + * Conditional Operations * + *****************************************************************************/ + + +int openscop_int_eq(int precision, + void * val1_base, int val1_offset, + void * val2_base, int val2_offset) { + void * val1 = openscop_int_address(precision, val1_base, val1_offset); + void * val2 = openscop_int_address(precision, val2_base, val2_offset); + + switch (precision) { + case OPENSCOP_PRECISION_SP: + return (*(long int *)val1 == *(long int *)val2); + + case OPENSCOP_PRECISION_DP: + return (*(long long int *)val1 == *(long long int *)val2); + +#ifdef OPENSCOP_GMP_IS_HERE + case OPENSCOP_PRECISION_MP: + return (mpz_cmp(*(mpz_t *)val1, *(mpz_t *)val2) == 0); +#endif + + default: + OPENSCOP_error("unknown precision"); + } +} + + +int openscop_int_ne(int precision, + void * val1_base, int val1_offset, + void * val2_base, int val2_offset) { + void * val1 = openscop_int_address(precision, val1_base, val1_offset); + void * val2 = openscop_int_address(precision, val2_base, val2_offset); + + switch (precision) { + case OPENSCOP_PRECISION_SP: + return (*(long int *)val1 != *(long int *)val2); + + case OPENSCOP_PRECISION_DP: + return (*(long long int *)val1 != *(long long int *)val2); + +#ifdef OPENSCOP_GMP_IS_HERE + case OPENSCOP_PRECISION_MP: + return (mpz_cmp(*(mpz_t *)val1, *(mpz_t *)val2) != 0); +#endif + + default: + OPENSCOP_error("unknown precision"); + } +} + + +int openscop_int_pos(int precision, void * value_base, int value_offset) { + void * value = openscop_int_address(precision, value_base, value_offset); + + switch (precision) { + case OPENSCOP_PRECISION_SP: + return (*(long int *)value > 0); + + case OPENSCOP_PRECISION_DP: + return (*(long long int *)value > 0); + +#ifdef OPENSCOP_GMP_IS_HERE + case OPENSCOP_PRECISION_MP: + return (mpz_sgn(*(mpz_t *)value) > 0); +#endif + + default: + OPENSCOP_error("unknown precision"); + } +} + + +int openscop_int_neg(int precision, void * value_base, int value_offset) { + void * value = openscop_int_address(precision, value_base, value_offset); + + switch (precision) { + case OPENSCOP_PRECISION_SP: + return (*(long int *)value < 0); + + case OPENSCOP_PRECISION_DP: + return (*(long long int *)value < 0); + +#ifdef OPENSCOP_GMP_IS_HERE + case OPENSCOP_PRECISION_MP: + return (mpz_sgn(*(mpz_t *)value) < 0); +#endif + + default: + OPENSCOP_error("unknown precision"); + } +} + + +int openscop_int_zero(int precision, void * value_base, int value_offset) { + void * value = openscop_int_address(precision, value_base, value_offset); + + switch (precision) { + case OPENSCOP_PRECISION_SP: + return (*(long int *)value == 0); + + case OPENSCOP_PRECISION_DP: + return (*(long long int *)value == 0); + +#ifdef OPENSCOP_GMP_IS_HERE + case OPENSCOP_PRECISION_MP: + return (mpz_sgn(*(mpz_t *)value) == 0); +#endif + + default: + OPENSCOP_error("unknown precision"); + } +} + + +int openscop_int_notzero(int precision, void * value_base, int value_offset) { + void * value = openscop_int_address(precision, value_base, value_offset); + + switch (precision) { + case OPENSCOP_PRECISION_SP: + return (*(long int *)value != 0); + + case OPENSCOP_PRECISION_DP: + return (*(long long int *)value != 0); + +#ifdef OPENSCOP_GMP_IS_HERE + case OPENSCOP_PRECISION_MP: + return (mpz_sgn(*(mpz_t *)value) != 0); +#endif + + default: + OPENSCOP_error("unknown precision"); + } +} + + +int openscop_int_one(int precision, void * value_base, int value_offset) { + void * value = openscop_int_address(precision, value_base, value_offset); + + switch (precision) { + case OPENSCOP_PRECISION_SP: + return (*(long int *)value == (long int)1); + + case OPENSCOP_PRECISION_DP: + return (*(long long int *)value == (long long int)1); + +#ifdef OPENSCOP_GMP_IS_HERE + case OPENSCOP_PRECISION_MP: + return (mpz_cmp_si(*(mpz_t *)value, 1) == 0); +#endif + + default: + OPENSCOP_error("unknown precision"); + } +} + + +int openscop_int_mone(int precision, void * value_base, int value_offset) { + void * value = openscop_int_address(precision, value_base, value_offset); + + switch (precision) { + case OPENSCOP_PRECISION_SP: + return (*(long int *)value == (long int)-1); + + case OPENSCOP_PRECISION_DP: + return (*(long long int *)value == (long long int)-1); + +#ifdef OPENSCOP_GMP_IS_HERE + case OPENSCOP_PRECISION_MP: + return (mpz_cmp_si(*(mpz_t *)value, -1) == 0); +#endif + + default: + OPENSCOP_error("unknown precision"); + } +} + + +int openscop_int_divisible(int precision, + void * val1_base, int val1_offset, + void * val2_base, int val2_offset) { + void * val1 = openscop_int_address(precision, val1_base, val1_offset); + void * val2 = openscop_int_address(precision, val2_base, val2_offset); + + switch (precision) { + case OPENSCOP_PRECISION_SP: + return ((*(long int *)val1 % *(long int *)val2) == 0); + + case OPENSCOP_PRECISION_DP: + return ((*(long long int *)val1 % *(long long int *)val2) == 0); + +#ifdef OPENSCOP_GMP_IS_HERE + case OPENSCOP_PRECISION_MP: + return mpz_divisible_p(*(mpz_t *)val1, *(mpz_t *)val2); +#endif + + default: + OPENSCOP_error("unknown precision"); + } +} diff --git a/source/relation.c b/source/relation.c index aeffd6d..4452fd4 100644 --- a/source/relation.c +++ b/source/relation.c @@ -145,6 +145,8 @@ void openscop_relation_idump(FILE * file, if (relation != NULL) { fprintf(file, "+-- openscop_relation_t ("); openscop_relation_print_type(file, relation); + fprintf(file, ", "); + openscop_int_dump_precision(file, relation->precision); fprintf(file, ")\n"); } else { @@ -158,6 +160,8 @@ void openscop_relation_idump(FILE * file, fprintf(file, "|\t"); fprintf(file, "| openscop_relation_t ("); openscop_relation_print_type(file, relation); + fprintf(file, ", "); + openscop_int_dump_precision(file, relation->precision); fprintf(file, ")\n"); } else @@ -179,7 +183,7 @@ void openscop_relation_idump(FILE * file, fprintf(file, "[ "); for (j = 0; j < relation->nb_columns; j++) { - OPENSCOP_INT_dump(file, OPENSCOP_FMT, relation->m[i][j]); + openscop_int_print(file, relation->precision, relation->m[i], j); fprintf(file, " "); } @@ -218,21 +222,24 @@ void openscop_relation_dump(FILE * file, openscop_relation_p relation) { } - +#if 0 /** * openscop_relation_expression_element function: * this function returns a string containing the printing of a value (possibly * an iterator or a parameter with its coefficient or a constant). - * \param[in] val The coefficient or constant value. - * \param[in,out] first Pointer to a boolean set to 1 if the current value is - * the first of an expresion, 0 otherwise (maybe updated). - * \param[in] cst A boolean set to 1 if the value is a constant, - * 0 otherwise. - * \param[in] name String containing the name of the element. + * \param[in] val Address of the coefficient or constant value. + * \param[in] precision The precision of the value. + * \param[in,out] first Pointer to a boolean set to 1 if the current value + * is the first of an expresion, 0 otherwise (maybe + * updated). + * \param[in] cst A boolean set to 1 if the value is a constant, + * 0 otherwise. + * \param[in] name String containing the name of the element. * \return A string that contains the printing of a value. */ static -char * openscop_relation_expression_element(openscop_int_t val, int * first, +char * openscop_relation_expression_element(void * val, + int precision, int * first, int cst, char * name) { char * temp = (char *)malloc(OPENSCOP_MAX_STRING * sizeof(char)); char * body = (char *)malloc(OPENSCOP_MAX_STRING * sizeof(char)); @@ -242,8 +249,8 @@ char * openscop_relation_expression_element(openscop_int_t val, int * first, sval[0] = '\0'; // statements for the 'normal' processing. - if (OPENSCOP_INT_notzero_p(val) && (!cst)) { - if ((*first) || OPENSCOP_INT_neg_p(val)) { + if (openscop_int_notzero(val) && (!cst)) { + if ((*first) || openscop_int_neg(val)) { if (OPENSCOP_INT_one_p(val)) { // case 1 sprintf(sval, "%s", name); } @@ -313,7 +320,8 @@ char * openscop_relation_expression(openscop_relation_p relation, // First the iterator part. for (i = 1; i <= names->nb_iterators; i++) { sval = openscop_relation_expression_element( - relation->m[row][i], &first, 0, names->iterators[i-1]); + &(relation->m[row][i]), relation->precision, &first, 0, + names->iterators[i-1]); strcat(sline, sval); free(sval); } @@ -322,7 +330,7 @@ char * openscop_relation_expression(openscop_relation_p relation, for (i = names->nb_iterators + 1; i <= names->nb_iterators + names->nb_localdims; i++) { sval = openscop_relation_expression_element( - relation->m[row][i], &first, 0, + &(relation->m[row][i]), relation->precision, &first, 0, names->localdims[i - names->nb_iterators - 1]); strcat(sline, sval); free(sval); @@ -333,15 +341,15 @@ char * openscop_relation_expression(openscop_relation_p relation, i <= names->nb_iterators + names->nb_localdims + names->nb_parameters; i++) { sval = openscop_relation_expression_element( - relation->m[row][i], &first, 0, + &(relation->m[row][i]), relation->precision, &first, 0, names->parameters[i - names->nb_iterators - names->nb_localdims - 1]); strcat(sline, sval); free(sval); } // Finally the constant part (yes, I reused it). - sval = openscop_relation_expression_element(relation->m[row][i], - &first, 1, NULL); + sval = openscop_relation_expression_element( + &(relation->m[row][i]), relation->precision, &first, 1, NULL); strcat(sline, sval); free(sval); @@ -550,7 +558,7 @@ void openscop_relation_print_comment(FILE * file, } } } - +#endif /** * openscop_relation_print function: @@ -574,7 +582,8 @@ void openscop_relation_print(FILE * file, return; } - printable_comments = openscop_relation_printable_comments(relation, names); + //printable_comments = openscop_relation_printable_comments(relation, names); + printable_comments = 0; // Count the number of parts in the union and print it if it is not 1. r = relation; @@ -609,12 +618,12 @@ void openscop_relation_print(FILE * file, for (i = 0; i < relation->nb_rows; i++) { for (j = 0; j < relation->nb_columns; j++) { - OPENSCOP_INT_dump(file, OPENSCOP_FMT, relation->m[i][j]); + openscop_int_print(file, relation->precision, relation->m[i], j); fprintf(file, " "); } - if (printable_comments) - openscop_relation_print_comment(file, relation, i, names); + //if (printable_comments) + // openscop_relation_print_comment(file, relation, i, names); fprintf(file, "\n"); } @@ -693,7 +702,8 @@ return_type: /** * openscop_relation_read function: * this function reads a relation into a file (foo, posibly stdin) and - * returns a pointer this relation. + * returns a pointer this relation. The relation is set to the maximum + * available precision. * \param[in] file The input stream. * \return A pointer to the relation structure that has been read. */ @@ -706,9 +716,9 @@ openscop_relation_p openscop_relation_read(FILE * foo) { int read_properties = 1; int first = 1; int type; + int precision = openscop_util_get_precision(); char * c, s[OPENSCOP_MAX_STRING], str[OPENSCOP_MAX_STRING]; openscop_relation_p relation, relation_union = NULL, previous = NULL; - openscop_int_t * p = NULL; type = openscop_relation_read_type(foo); @@ -742,7 +752,7 @@ openscop_relation_p openscop_relation_read(FILE * foo) { } // Allocate the union part and fill its properties. - relation = openscop_relation_malloc(nb_rows, nb_columns); + relation = openscop_relation_pmalloc(precision, nb_rows, nb_columns); relation->type = type; relation->nb_output_dims = nb_output_dims; relation->nb_input_dims = nb_input_dims; @@ -750,9 +760,6 @@ openscop_relation_p openscop_relation_read(FILE * foo) { relation->nb_parameters = nb_parameters; // Read the matrix of constraints. - if ((relation->nb_rows != 0) && (relation->nb_columns != 0)) - p = relation->m[0]; - for (i = 0; i < relation->nb_rows; i++) { c = openscop_util_skip_blank_and_comments(foo, s); if (c == NULL) @@ -763,15 +770,8 @@ openscop_relation_p openscop_relation_read(FILE * foo) { OPENSCOP_error("not enough columns"); if (sscanf(c, "%s%n", str, &n) == 0) OPENSCOP_error("not enough rows"); -#if defined(OPENSCOP_INT_T_IS_MP) - long long val; - if (sscanf(str, "%lld", &val) == 0) - OPENSCOP_error("failed to read an integer (in a relation)"); - mpz_set_si(*p++, val); -#else - if (sscanf(str, OPENSCOP_FMT_TXT, p++) == 0) - OPENSCOP_error("failed to read an integer (in a relation)"); -#endif + + openscop_int_sread(str, precision, relation->m[i], j); c += n; } } @@ -799,18 +799,20 @@ openscop_relation_p openscop_relation_read(FILE * foo) { /** - * openscop_relation_malloc function: - * this function allocates the memory space for a openscop_relation_t - * structure and sets its fields with default values. Then it returns a - * pointer to the allocated space. + * openscop_relation_pmalloc function: + * (precision malloc) this function allocates the memory space for an + * openscop_relation_t structure and sets its fields with default values. + * Then it returns a pointer to the allocated space. + * \param[in] precision The precision of the constraint matrix. * \param[in] nb_rows The number of row of the relation to allocate. * \param[in] nb_columns The number of columns of the relation to allocate. * \return A pointer to an empty relation with fields set to default values * and a ready-to-use constraint matrix. */ -openscop_relation_p openscop_relation_malloc(int nb_rows, int nb_columns) { +openscop_relation_p openscop_relation_pmalloc(int precision, + int nb_rows, int nb_columns) { openscop_relation_p relation; - openscop_int_t ** p, * q; + void ** p, * q; int i, j; OPENSCOP_malloc(relation, openscop_relation_p, sizeof(openscop_relation_t)); @@ -821,32 +823,49 @@ openscop_relation_p openscop_relation_malloc(int nb_rows, int nb_columns) { relation->nb_input_dims = OPENSCOP_UNDEFINED; relation->nb_parameters = OPENSCOP_UNDEFINED; relation->nb_local_dims = OPENSCOP_UNDEFINED; + relation->precision = precision; if ((nb_rows == 0) || (nb_columns == 0) || (nb_rows == OPENSCOP_UNDEFINED) || (nb_columns == OPENSCOP_UNDEFINED)) { relation->m = NULL; } else { - OPENSCOP_malloc(p, openscop_int_t **, - nb_rows * sizeof(openscop_int_t *)); - OPENSCOP_malloc(q, openscop_int_t *, - nb_rows * nb_columns * sizeof(openscop_int_t)); + OPENSCOP_malloc(p, void **, nb_rows * sizeof(void *)); + OPENSCOP_malloc(q, void *, + nb_rows * nb_columns * openscop_int_sizeof(precision)); relation->m = p; for (i = 0; i < nb_rows; i++) { - *p++ = q; + relation->m[i] = openscop_int_address(precision, q, i * nb_columns); for (j = 0; j < nb_columns; j++) - OPENSCOP_INT_init_set_si(*(q+j),0); - q += nb_columns; + openscop_int_init_set_si(precision, relation->m[i], j, 0); } } - + relation->next = NULL; - + return relation; } /** + * openscop_relation_malloc function: + * this function allocates the memory space for an openscop_relation_t + * structure and sets its fields with default values. Then it returns a + * pointer to the allocated space. The precision of the constraint matrix + * elements corresponds to the precision environment variable or to the + * highest available precision if it is not defined. + * \param[in] nb_rows The number of row of the relation to allocate. + * \param[in] nb_columns The number of columns of the relation to allocate. + * \return A pointer to an empty relation with fields set to default values + * and a ready-to-use constraint matrix. + */ +openscop_relation_p openscop_relation_malloc(int nb_rows, int nb_columns) { + int precision = openscop_util_get_precision(); + return openscop_relation_pmalloc(precision, nb_rows, nb_columns); +} + + +/** * openscop_relation_free_inside function: * this function frees the allocated memory for the inside of a * openscop_relation_t structure, i.e. only m. @@ -854,7 +873,7 @@ openscop_relation_p openscop_relation_malloc(int nb_rows, int nb_columns) { */ void openscop_relation_free_inside(openscop_relation_p relation) { int i, nb_elements; - openscop_int_t * p; + void * p; if (relation == NULL) return; @@ -865,7 +884,7 @@ void openscop_relation_free_inside(openscop_relation_p relation) { p = relation->m[0]; for (i = 0; i < nb_elements; i++) - OPENSCOP_INT_clear(*p++); + openscop_int_clear(relation->precision, p, i); if (relation->m != NULL) { if (nb_elements > 0) @@ -929,7 +948,8 @@ openscop_relation_p openscop_relation_ncopy(openscop_relation_p relation, if (n > relation->nb_rows) OPENSCOP_error("not enough rows to copy in the relation"); - node = openscop_relation_malloc(n, relation->nb_columns); + node = openscop_relation_pmalloc(relation->precision, + n, relation->nb_columns); node->type = relation->type; node->nb_output_dims = relation->nb_output_dims; node->nb_input_dims = relation->nb_input_dims; @@ -938,7 +958,9 @@ openscop_relation_p openscop_relation_ncopy(openscop_relation_p relation, for (i = 0; i < n; i++) for (j = 0; j < relation->nb_columns; j++) - OPENSCOP_INT_assign(node->m[i][j], relation->m[i][j]); + openscop_int_assign(relation->precision, + node->m[i], j, + relation->m[i], j); if (first) { first = 0; @@ -985,13 +1007,16 @@ void openscop_relation_replace_vector(openscop_relation_p relation, openscop_vector_p vector, int row) { int i; - if ((relation == NULL) || (vector == NULL) || - (relation->nb_columns != vector->size) || + if ((relation == NULL) || (vector == NULL) || + (relation->precision != vector->precision) || + (relation->nb_columns != vector->size) || (row >= relation->nb_rows) || (row < 0)) OPENSCOP_error("vector cannot replace relation row"); for (i = 0; i < vector->size; i++) - OPENSCOP_INT_assign(relation->m[row][i], vector->v[i]); + openscop_int_assign(relation->precision, + relation->m[row], i, + vector->v, i); } @@ -1008,16 +1033,22 @@ void openscop_relation_add_vector(openscop_relation_p relation, openscop_vector_p vector, int row) { int i; - if ((relation == NULL) || (vector == NULL) || - (relation->nb_columns != vector->size) || + if ((relation == NULL) || (vector == NULL) || + (relation->precision != vector->precision) || + (relation->nb_columns != vector->size) || (row >= relation->nb_rows) || (row < 0)) OPENSCOP_error("vector cannot be added to relation"); - if (OPENSCOP_INT_get_si(relation->m[row][0]) == 0) - OPENSCOP_INT_assign(relation->m[row][0], vector->v[0]); + if (openscop_int_get_si(relation->precision, relation->m[row], 0) == 0) + openscop_int_assign(relation->precision, + relation->m[row], 0, + vector->v, 0); for (i = 1; i < vector->size; i++) - OPENSCOP_INT_addto(relation->m[row][i], relation->m[row][i], vector->v[i]); + openscop_int_add(relation->precision, + relation->m[row], i, + relation->m[row], i, + vector->v, i); } @@ -1034,16 +1065,22 @@ void openscop_relation_sub_vector(openscop_relation_p relation, openscop_vector_p vector, int row) { int i; - if ((relation == NULL) || (vector == NULL) || - (relation->nb_columns != vector->size) || + if ((relation == NULL) || (vector == NULL) || + (relation->precision != vector->precision) || + (relation->nb_columns != vector->size) || (row >= relation->nb_rows) || (row < 0)) OPENSCOP_error("vector cannot be subtracted to row"); - if (OPENSCOP_INT_get_si(relation->m[row][0]) == 0) - OPENSCOP_INT_assign(relation->m[row][0], vector->v[0]); + if (openscop_int_get_si(relation->precision, relation->m[row], 0) == 0) + openscop_int_assign(relation->precision, + relation->m[row], 0, + vector->v, 0); for (i = 1; i < vector->size; i++) - OPENSCOP_INT_subtract(relation->m[row][i], relation->m[row][i], vector->v[i]); + openscop_int_sub(relation->precision, + relation->m[row], i, + relation->m[row], i, + vector->v, i); } @@ -1080,7 +1117,7 @@ openscop_relation_p openscop_relation_from_vector(openscop_vector_p vector) { if (vector == NULL) return NULL; - relation = openscop_relation_malloc(1, vector->size); + relation = openscop_relation_pmalloc(vector->precision, 1, vector->size); openscop_relation_replace_vector(relation, vector, 0); return relation; } @@ -1099,14 +1136,15 @@ void openscop_relation_replace_constraints(openscop_relation_p r1, openscop_relation_p r2, int row) { int i, j; - if ((r1 == NULL) || (r2 == NULL) || + if ((r1 == NULL) || (r2 == NULL) || + (r1->precision != r2->precision) || (r1->nb_columns != r1->nb_columns) || ((row + r2->nb_rows) > r1->nb_rows) || (row < 0)) OPENSCOP_error("relation rows could not be replaced"); for (i = 0; i < r2->nb_rows; i++) for (j = 0; j < r2->nb_columns; j++) - OPENSCOP_INT_assign(r1->m[i+row][j], r2->m[i][j]); + openscop_int_assign(r1->precision, r1->m[i+row], j, r2->m[i], j); } @@ -1129,21 +1167,26 @@ void openscop_relation_insert_constraints(openscop_relation_p r1, return; if ((r1->nb_columns != r2->nb_columns) || + (r1->precision != r2->precision) || (row > r1->nb_rows) || (row < 0)) OPENSCOP_error("constraints cannot be inserted"); // We use a temporary relation just to reuse existing functions. Cleaner. - temp = openscop_relation_malloc(r1->nb_rows+r2->nb_rows, r1->nb_columns); + temp = openscop_relation_pmalloc(r1->precision, + r1->nb_rows + r2->nb_rows, + r1->nb_columns); for (i = 0; i < row; i++) for (j = 0; j < r1->nb_columns; j++) - OPENSCOP_INT_assign(temp->m[i][j], r1->m[i][j]); + openscop_int_assign(r1->precision, temp->m[i], j, r1->m[i], j); openscop_relation_replace_constraints(temp, r2, row); for (i = row + r2->nb_rows; i < r2->nb_rows + r1->nb_rows; i++) for (j = 0; j < r1->nb_columns; j++) - OPENSCOP_INT_assign(temp->m[i][j], r1->m[i-r2->nb_rows][j]); + openscop_int_assign(r1->precision, + temp->m[i], j, + r1->m[i-r2->nb_rows], j); openscop_relation_free_inside(r1); @@ -1185,7 +1228,9 @@ openscop_relation_p openscop_relation_concat_constraints( OPENSCOP_warning("relation concatenation is done on the first elements " "of union only"); - new = openscop_relation_malloc(r1->nb_rows+r2->nb_rows, r1->nb_columns); + new = openscop_relation_pmalloc(r1->precision, + r1->nb_rows + r2->nb_rows, + r1->nb_columns); openscop_relation_replace_constraints(new, r1, 0); openscop_relation_replace_constraints(new, r2, r1->nb_rows); @@ -1209,6 +1254,7 @@ int openscop_relation_equal(openscop_relation_p r1, openscop_relation_p r2) { return 1; if ((r1->type != r2->type) || + (r1->precision != r2->precision) || (r1->nb_rows != r2->nb_rows) || (r1->nb_columns != r2->nb_columns) || (r1->nb_output_dims != r2->nb_output_dims) || @@ -1219,7 +1265,7 @@ int openscop_relation_equal(openscop_relation_p r1, openscop_relation_p r2) { for (i = 0; i < r1->nb_rows; ++i) for (j = 0; j < r1->nb_columns; ++j) - if (OPENSCOP_INT_ne(r1->m[i][j], r2->m[i][j])) + if (openscop_int_ne(r1->precision, r1->m[i], j, r2->m[i], j)) return 0; r1 = r1->next; @@ -1415,8 +1461,8 @@ int openscop_relation_integrity_check(openscop_relation_p relation, // made of 0 or 1 only. if ((relation->nb_rows > 0) && (relation->nb_columns > 0)) { for (i = 0; i < relation->nb_rows; i++) { - if (!OPENSCOP_INT_zero_p(relation->m[i][0]) && - !OPENSCOP_INT_one_p(relation->m[i][0])) { + if (!openscop_int_zero(relation->precision, relation->m[i], 0) && + !openscop_int_one(relation->precision, relation->m[i], 0)) { OPENSCOP_warning("first column of a relation is not " "strictly made of 0 or 1"); openscop_relation_dump(stderr, relation); @@ -1504,6 +1550,7 @@ int openscop_relation_get_array_id(openscop_relation_p relation) { int reference_array_id = OPENSCOP_UNDEFINED; int nb_array_id; int row_id = 0; + int precision; if (relation == NULL) return OPENSCOP_UNDEFINED; @@ -1514,6 +1561,8 @@ int openscop_relation_get_array_id(openscop_relation_p relation) { } while (relation != NULL) { + precision = relation->precision; + // There should be room to store the array identifier. if ((relation->nb_rows < 1) || (relation->nb_columns < 3)) { @@ -1529,7 +1578,7 @@ int openscop_relation_get_array_id(openscop_relation_p relation) { // - check that (-m[i][#columns -1] / m[i][1]) > 0. nb_array_id = 0; for (i = 0; i < relation->nb_rows; i++) { - if (!OPENSCOP_INT_zero_p(relation->m[i][1])) { + if (!openscop_int_zero(precision, relation->m[i], 1)) { nb_array_id ++; row_id = i; } @@ -1543,18 +1592,21 @@ int openscop_relation_get_array_id(openscop_relation_p relation) { return OPENSCOP_UNDEFINED; } for (i = 0; i < relation->nb_columns - 1; i++) { - if ((i != 1) && !OPENSCOP_INT_zero_p(relation->m[row_id][i])) { + if ((i != 1) && !openscop_int_zero(precision, relation->m[row_id], i)) { OPENSCOP_warning("non integer array identifier"); return OPENSCOP_UNDEFINED; } } - if (!OPENSCOP_INT_divisible(relation->m[row_id][relation->nb_columns - 1], - relation->m[row_id][1])) { + if (!openscop_int_divisible(precision, + relation->m[row_id], relation->nb_columns - 1, + relation->m[row_id], 1)) { OPENSCOP_warning("rational array identifier"); return OPENSCOP_UNDEFINED; } - array_id = -OPENSCOP_INT_get_si(relation->m[row_id][relation->nb_columns-1]); - array_id /= OPENSCOP_INT_get_si(relation->m[row_id][1]); + array_id = -openscop_int_get_si(precision, + relation->m[row_id], + relation->nb_columns - 1); + array_id /= openscop_int_get_si(precision, relation->m[row_id], 1); if (array_id <= 0) { OPENSCOP_warning("negative or 0 identifier in access function"); return OPENSCOP_UNDEFINED; diff --git a/source/util.c b/source/util.c index be01fba..6e86175 100644 --- a/source/util.c +++ b/source/util.c @@ -268,3 +268,35 @@ void openscop_util_safe_strcat(char ** dst, char * src, int * hwm) { strcat(*dst, src); } + + +/** + * openscop_util_get_precision function: + * this function returns the precision defined by the precision environment + * variable or the highest available precision if it is not defined. + * \return environment precision if defined or highest available precision. + */ +int openscop_util_get_precision() { + int precision = OPENSCOP_PRECISION_DP; + char * precision_env; + +#ifdef OPENSCOP_GMP_IS_HERE + precision = OPENSCOP_PRECISION_MP; +#endif + + precision_env = getenv(OPENSCOP_PRECISION_ENV); + if (precision_env != NULL) { + if (!strcmp(precision_env, OPENSCOP_PRECISION_ENV_SP)) + precision = OPENSCOP_PRECISION_SP; + else if (!strcmp(precision_env, OPENSCOP_PRECISION_ENV_DP)) + precision = OPENSCOP_PRECISION_DP; + else if (!strcmp(precision_env, OPENSCOP_PRECISION_ENV_MP)) + precision = OPENSCOP_PRECISION_MP; + else + OPENSCOP_warning("bad precision environment value"); + } + + return precision; +} + + diff --git a/source/vector.c b/source/vector.c index b3cb922..32cffda 100644 --- a/source/vector.c +++ b/source/vector.c @@ -79,9 +79,9 @@ * depression or, for the lucky ones, getting a headache... It includes an * indentation level (level) in order to work with others print_structure * functions. - * \param file File where informations are printed. - * \param vector The vector whose information have to be printed. - * \param level Number of spaces before printing, for each line. + * \param[in] file File where informations are printed. + * \param[in] vector The vector whose information have to be printed. + * \param[in] level Number of spaces before printing, for each line. */ void openscop_vector_idump(FILE * file, openscop_vector_p vector, int level) { int j; @@ -90,36 +90,38 @@ void openscop_vector_idump(FILE * file, openscop_vector_p vector, int level) { // Go to the right level. for (j = 0; j < level; j++) fprintf(file,"|\t"); - fprintf(file,"+-- openscop_vector_t\n"); + fprintf(file,"+-- openscop_vector_t ("); + openscop_int_dump_precision(file, vector->precision); + fprintf(file, ")\n"); for (j = 0; j <= level; j++) fprintf(file,"|\t"); - fprintf(file,"%d\n",vector->size); + fprintf(file,"%d\n", vector->size); // Display the vector. for (j = 0; j <= level; j++) - fprintf(file,"|\t"); + fprintf(file, "|\t"); - fprintf(file,"[ "); + fprintf(file, "[ "); for (j = 0; j < vector->size; j++) { - OPENSCOP_INT_dump(file,OPENSCOP_FMT,vector->v[j]); - fprintf(file," "); + openscop_int_print(file, vector->precision, vector->v, j); + fprintf(file, " "); } - fprintf(file,"]\n"); + fprintf(file, "]\n"); } else { // Go to the right level. for (j = 0; j < level; j++) - fprintf(file,"|\t"); - fprintf(file,"+-- NULL vector\n"); + fprintf(file, "|\t"); + fprintf(file, "+-- NULL vector\n"); } // The last line. for (j = 0; j <= level; j++) - fprintf(file,"|\t"); - fprintf(file,"\n"); + fprintf(file, "|\t"); + fprintf(file, "\n"); } @@ -127,11 +129,11 @@ void openscop_vector_idump(FILE * file, openscop_vector_p vector, int level) { * openscop_vector_dump function: * This function prints the content of a openscop_vector_t structure * (*vector) into a file (file, possibly stdout). - * \param file File where informations are printed. - * \param vector The vector whose information have to be printed. + * \param[in] file File where informations are printed. + * \param[in] vector The vector whose information have to be printed. */ void openscop_vector_dump(FILE * file, openscop_vector_p vector) { - openscop_vector_idump(file,vector,0); + openscop_vector_idump(file, vector, 0); } @@ -141,46 +143,60 @@ void openscop_vector_dump(FILE * file, openscop_vector_p vector) { /** - * openscop_vector_malloc function: - * This function allocates the memory space for a openscop_vector_t structure - * and sets its fields with default values. Then it returns a pointer to the - * allocated space. - * \param size The number of entries of the vector to allocate. + * openscop_vector_pmalloc function: + * (precision malloc) this function allocates the memory space for an + * openscop_vector_t structure and sets its fields with default values. Then + * it returns a pointer to the allocated space. + * \param[in] precision The precision of the vector entries. + * \param[in] size The number of entries of the vector to allocate. * \return A pointer to the newly allocated openscop_vector_t structure. */ -openscop_vector_p openscop_vector_malloc(unsigned size) { +openscop_vector_p openscop_vector_pmalloc(int precision, int size) { openscop_vector_p vector; - openscop_int_t * p; int i; OPENSCOP_malloc(vector, openscop_vector_p, sizeof(openscop_vector_t)); vector->size = size; + vector->precision = precision; if (size == 0) { vector->v = NULL; } else { - OPENSCOP_malloc(p, openscop_int_t *, size * sizeof(openscop_int_t)); - vector->v = p; + OPENSCOP_malloc(vector->v, void *, size * openscop_int_sizeof(precision)); for (i = 0; i < size; i++) - OPENSCOP_INT_init_set_si(vector->v[i],0); + openscop_int_init_set_si(precision, vector->v, i, 0); } return vector; } /** + * openscop_vector_malloc function: + * This function allocates the memory space for a openscop_vector_t structure + * and sets its fields with default values. Then it returns a pointer to the + * allocated space. The precision of the vector elements corresponds to the + * precision environment variable or to the highest available precision if it + * is not defined. + * \param[in] size The number of entries of the vector to allocate. + * \return A pointer to the newly allocated openscop_vector_t structure. + */ +openscop_vector_p openscop_vector_malloc(int size) { + int precision = openscop_util_get_precision(); + return openscop_vector_pmalloc(precision, size); +} + + +/** * openscop_vector_free function: * This function frees the allocated memory for a openscop_vector_t structure. - * \param vector The pointer to the vector we want to free. + * \param[in] vector The pointer to the vector we want to free. */ void openscop_vector_free(openscop_vector_p vector) { int i; - openscop_int_t * p; if (vector != NULL) { - p = vector->v; for (i = 0; i < vector->size; i++) - OPENSCOP_INT_clear(*p++); + openscop_int_clear(vector->precision, vector->v, i); free(vector->v); free(vector); @@ -198,23 +214,25 @@ void openscop_vector_free(openscop_vector_p vector) { * This function adds a scalar to the vector representation of an affine * expression (this means we add the scalar only to the very last entry of the * vector). It returns a new vector resulting from this addition. - * \param vector The basis vector. - * \param scalar The scalar to add to the vector. + * \param[in] vector The basis vector. + * \param[in] scalar The scalar to add to the vector. * \return A pointer to a new vector, copy of the basis one plus the scalar. */ openscop_vector_p openscop_vector_add_scalar(openscop_vector_p vector, int scalar) { - int i; + int i, precision, last; openscop_vector_p result; if ((vector == NULL) || (vector->size < 2)) OPENSCOP_error("incompatible vector for addition"); - result = openscop_vector_malloc(vector->size); + precision = vector->precision; + last = vector->size - 1; + + result = openscop_vector_pmalloc(precision, vector->size); for (i = 0; i < vector->size; i++) - OPENSCOP_INT_assign(result->v[i],vector->v[i]); - OPENSCOP_INT_add_int(result->v[vector->size - 1], - vector->v[vector->size - 1],scalar); + openscop_int_assign(precision, result->v, i, vector->v, i); + openscop_int_add_ui(precision, result->v, last, vector->v, last, scalar); return result; } @@ -234,12 +252,13 @@ openscop_vector_p openscop_vector_add(openscop_vector_p v1, int i; openscop_vector_p v3; - if ((v1 == NULL) || (v2 == NULL) || (v1->size != v2->size)) + if ((v1 == NULL) || (v2 == NULL) || + (v1->size != v2->size) || (v1->precision != v2->precision)) OPENSCOP_error("incompatible vectors for addition"); - v3 = openscop_vector_malloc(v1->size); + v3 = openscop_vector_pmalloc(v1->precision, v1->size); for (i = 0; i < v1->size; i++) - OPENSCOP_INT_addto(v3->v[i],v1->v[i],v2->v[i]); + openscop_int_add(v1->precision, v3->v, i, v1->v, i, v2->v, i); return v3; } @@ -259,12 +278,13 @@ openscop_vector_p openscop_vector_sub(openscop_vector_p v1, int i; openscop_vector_p v3; - if ((v1 == NULL) || (v2 == NULL) || (v1->size != v2->size)) + if ((v1 == NULL) || (v2 == NULL) || + (v1->size != v2->size) || (v1->precision != v2->precision)) OPENSCOP_error("incompatible vectors for subtraction"); - v3 = openscop_vector_malloc(v1->size); + v3 = openscop_vector_pmalloc(v1->precision, v1->size); for (i = 0; i < v1->size; i++) - OPENSCOP_INT_subtract(v3->v[i],v1->v[i],v2->v[i]); + openscop_int_sub(v1->precision, v3->v, i, v1->v, i, v2->v, i); return v3; } @@ -281,7 +301,7 @@ openscop_vector_p openscop_vector_sub(openscop_vector_p v1, void openscop_vector_tag_inequality(openscop_vector_p vector) { if ((vector == NULL) || (vector->size < 1)) OPENSCOP_error("vector cannot be tagged"); - OPENSCOP_INT_set_si(vector->v[0],1); + openscop_int_set_si(vector->precision, vector->v, 0, 1); } @@ -296,7 +316,7 @@ void openscop_vector_tag_inequality(openscop_vector_p vector) { void openscop_vector_tag_equality(openscop_vector_p vector) { if ((vector == NULL) || (vector->size < 1)) OPENSCOP_error("vector cannot be tagged"); - OPENSCOP_INT_set_si(vector->v[0],0); + openscop_int_set_si(vector->precision, vector->v, 0, 0); } @@ -314,11 +334,11 @@ int openscop_vector_equal(openscop_vector_p v1, openscop_vector_p v2) { if (v1 == v2) return 1; - if (v1->size != v2->size) + if ((v1->size != v2->size) || (v1->precision != v2->precision)) return 0; for (i = 0; i < v1->size; i++) - if (OPENSCOP_INT_ne(v1->v[i], v2->v[i])) + if (openscop_int_ne(v1->precision, v1->v, i, v2->v, i)) return 0; return 1; @@ -336,10 +356,10 @@ int openscop_vector_equal(openscop_vector_p v1, openscop_vector_p v2) { openscop_vector_p openscop_vector_mul_scalar(openscop_vector_p v, int scalar) { int i; - openscop_vector_p result = openscop_vector_malloc(v->size); + openscop_vector_p result = openscop_vector_pmalloc(v->precision, v->size); for(i = 0; i < v->size; i++) - OPENSCOP_INT_multo(result->v[i], scalar, v->v[i]); + openscop_int_mul_si(v->precision, result->v, i, v->v, i, scalar); return result; } -- 2.11.4.GIT