diff --git a/contrib/kbipack/compute_normal_form.c b/contrib/kbipack/compute_normal_form.c deleted file mode 100644 index f86e043cc27e27144738acbffcbe7eafd6e7a6b3..0000000000000000000000000000000000000000 --- a/contrib/kbipack/compute_normal_form.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - COMPUTE_NORMAL_FORM - - Hermite and Smith normal forms of integer matrices. - - Implementation: Dense matrix with GMP-library's mpz_t elements to - hold huge integers. - - Algorithm: Kannan - Bachem algorithm with improvement by - Chou and Collins. Expects a large number of unit invariant - factors and takes advantage of them as they appear. - - References: - [1] Ravindran Kannan, Achim Bachem: - "Polynomial algorithms for computing the Smith and Hermite normal - forms of an integer matrix", - SIAM J. Comput., vol. 8, no. 5, pp. 499-507, 1979. - [2] Tsu-Wu J.Chou, George E. Collins: - "Algorithms for the solution of systems of linear Diophantine - equations", - SIAM J. Comput., vol. 11, no. 4, pp. 687-708, 1982. - [3] GMP homepage http://www.swox.com/gmp/ - [4] GNU gmp page http://www.gnu.org/software/gmp/ - - Copyright (C) 3.11.2003 Saku Suuriniemi TUT/CEM - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Saku Suuriniemi, TUT/Electromagetics - P.O.Box 692, FIN-33101 Tampere, Finland - saku.suuriniemi@tut.fi - - $Id: compute_normal_form.c,v 1.1 2009-03-30 14:10:57 matti Exp $ -*/ - - -#include<stdlib.h> -#include<stdio.h> -#include<string.h> -#include"gmp_matrix_io.h" -#include"gmp_normal_form.h" - -typedef enum {HERMITE, SMITH} nf_flag; -typedef enum {NOT_WANTED, WANTED} w_flag; - -static int nf_parse_options(int arg_counter, char ** args, - char ** p_infile_name, char ** p_outfile_name, - nf_flag * p_normal_form_requested, - inverted_flag * p_left_inverted, - inverted_flag * p_right_inverted, - w_flag * p_help_wanted, - w_flag * p_verbose_wanted) -{ - size_t ind1, ind2; - size_t outfilename_length; - - /* If no infile is specified, the error is indisputable. - => Print help and exit. - Infile should be the last argument. */ - - if(strncmp(args[arg_counter-1], "-", 1) == 0) - { - *(p_help_wanted) = WANTED; - return EXIT_SUCCESS; - } - - /* Should I find arguments? */ - if(arg_counter > 2) - { - for(ind1 = 1; ind1 < arg_counter-1; ind1++) - { - /* No multiple infile names ! */ - if(strncmp(args[ind1], "-", 1) != 0) - { - *(p_help_wanted) = WANTED; - return EXIT_SUCCESS; - } - - /* Parse the option letters after '-' one by one */ - for(ind2 = 1; ind2 < strlen(args[ind1]); ind2++) - { - switch(args[ind1][ind2]) - { - case 'h': - *(p_help_wanted) = WANTED; - return EXIT_SUCCESS; - break; - case 'H': - *(p_normal_form_requested) = HERMITE; - break; - case 'S': - *(p_normal_form_requested) = SMITH; - break; - case 'l': - *(p_left_inverted) = INVERTED; - break; - case 'r': - *(p_right_inverted) = INVERTED; - break; - case 'v': - *(p_verbose_wanted) = WANTED; - break; - } - } - } - } - - /* Get the infile name */ - * p_infile_name = (char *) calloc(strlen(args[arg_counter-1]) + 1, - sizeof(char)); - if(* p_infile_name == NULL) - { - return EXIT_FAILURE; - } - - strcpy(* p_infile_name, args[arg_counter-1]); - - /* Create the outfile name */ - outfilename_length = strcspn( * p_infile_name, "."); - * p_outfile_name = (char *) calloc(outfilename_length + 1, - sizeof(char)); - if( * p_outfile_name == NULL) - { - free( * p_infile_name); - return EXIT_FAILURE; - } - - strncpy(* p_outfile_name, * p_infile_name, outfilename_length); - (* p_outfile_name)[outfilename_length] = '\0'; - - return EXIT_SUCCESS; -} - -static int nf_print_help(void) -{ - fprintf(stdout, "Usage: compute_normal_form [-hHSlrv] infile\n"); - fprintf(stdout, "\n"); - fprintf(stdout, "Description: Compute the Hermite/Smith normal form of an integer matrix.\n"); - fprintf(stdout, "\n"); - fprintf(stdout, "Input: \"infile\" is an ascii file, which contains an integer matrix\n"); - fprintf(stdout, " in the sparse coordinate format:\n"); - fprintf(stdout, "\n"); - fprintf(stdout, " # All comments before the data\n"); - fprintf(stdout, " rows columns nonzeros\n"); - fprintf(stdout, " row1 col1 value1\n"); - fprintf(stdout, " row2 col2 value2\n"); - fprintf(stdout, " ...\n"); - fprintf(stdout, "\n"); - fprintf(stdout, " No multiple infiles, please.\n"); - fprintf(stdout, "\n"); - fprintf(stdout, "Options: -h This help\n"); - fprintf(stdout, " -H Compute the Hermite normal form (default)\n"); - fprintf(stdout, " -S Compute the Smith normal form\n"); - fprintf(stdout, " -l Left factor inverted (A = P^(T)LU instead of PA = LU for Hermite, \n"); - fprintf(stdout, " U^(-1)A = SV instead of A = USV for Smith)\n"); - fprintf(stdout, " -r Right factor inverted (PAU^(-1) = L instead of PA = LU for Hermite, \n"); - fprintf(stdout, " AV^(-1) = US instead of A = USV for Smith)\n"); - fprintf(stdout, " -v Verbose. Print the matrix and the decomposition to sdtout, \n"); - fprintf(stdout, " so that the user may check that the problem is read and written\n"); - fprintf(stdout, " correctly.\n"); - fprintf(stdout, "\n"); - fprintf(stdout, "Output: For inpur matrix in e.g. \"infile.coord\", writes ascii files\n"); - fprintf(stdout, " \"infile.left\", \"infile.can\", and \"infile.right\", which \n"); - fprintf(stdout, " contain the left factor, canonical form, and the right factor, \n"); - fprintf(stdout, " respectively. The matrices are written in the sparse coordinate\n"); - fprintf(stdout, " format.\n"); - fprintf(stdout, "\n"); - fprintf(stdout, "Note: The return values may be big enough to not fit the standard integer types.\n"); - fprintf(stdout, "\n"); - fprintf(stdout, "Copyright (C) 3.11.2003 Saku Suuriniemi, Tampere University of Technology/Electromagnetics\n"); - fprintf(stdout, " P.O.Box 692, FIN-33101 Tampere, Finland. saku.suuriniemi@tut.fi\n"); - fprintf(stdout, "\n"); - fprintf(stdout, "Licenced under GNU General Public Licence (GPL) version 2 or later, ABSOLUTELY NO WARRANTY.\n"); - - return EXIT_SUCCESS; -} - - -static char* append_suffix(const char * file_base_name, const char * suffix) -{ - char * filename; - - if((file_base_name == NULL) || (suffix == NULL)) - { - return NULL; - } - - filename = - (char*) calloc(strlen(file_base_name)+strlen(suffix)+2, - sizeof(char)); - - if(filename == NULL) - { - return NULL; - } - - strcpy(filename, file_base_name); - strcat(filename, "."); - strcat(filename, suffix); - - return filename; -} - - - -int main(int argc, char * argv[]) -{ - char * infile_name; - char * file_base_name; - char * outfile_name; - gmp_matrix * A; - gmp_normal_form * normal_form; - w_flag help_wanted; - w_flag verbose_wanted; - nf_flag normal_form_requested; - inverted_flag left_inverted; - inverted_flag right_inverted; - - if(argc == 1) - { - fprintf(stdout, "Please try \"compute_normal_form -h\" for help.\n"); - return EXIT_SUCCESS; - } - - /* Default settings before option parsing */ - normal_form_requested = HERMITE; - left_inverted = NOT_INVERTED; - right_inverted = NOT_INVERTED; - help_wanted = NOT_WANTED; - verbose_wanted = NOT_WANTED; - - if( nf_parse_options(argc, argv, - &infile_name, &file_base_name, - &normal_form_requested, - &left_inverted, &right_inverted, - &help_wanted, - &verbose_wanted) - == EXIT_FAILURE ) - { - return EXIT_FAILURE; - } - - /* In this case, no dynamical memory has been allocated by - nf_parse_options ! */ - if(help_wanted == WANTED) - { - return nf_print_help(); - } - - if(verbose_wanted == WANTED) - { - fprintf(stdout, "Computing "); - if(normal_form_requested == HERMITE) - { - fprintf(stdout, "Hermite"); - } - else - { - fprintf(stdout, "Smith"); - } - fprintf(stdout, " normal form\n"); - if(left_inverted == INVERTED) - { - fprintf(stdout, "The left factor will be inverted.\n"); - } - if(right_inverted == INVERTED) - { - fprintf(stdout, "The right factor will be inverted.\n"); - } - fprintf(stdout, "Matrix read from file %s\n", infile_name); - } - - /*************************************************************/ - /* We have all we need to get to the computational business: */ - /*************************************************************/ - - /* Read the matrix */ - A = gmp_matrix_read_coord(infile_name); - free(infile_name); - - if(verbose_wanted == WANTED) - { - fprintf(stdout, "Input matrix:\n"); - gmp_matrix_fprintf(stdout, A); - } - - /* Compute the requested normal form */ - switch(normal_form_requested) - { - case SMITH: - normal_form = create_gmp_Smith_normal_form(A, left_inverted, right_inverted); - break; - - default: - normal_form = create_gmp_Hermite_normal_form(A, left_inverted, right_inverted); - break; - } - - - if(verbose_wanted == WANTED) - { - fprintf(stdout, "Left factor:\n"); - gmp_matrix_fprintf(stdout, normal_form->left); - fprintf(stdout, "Canonical form:\n"); - gmp_matrix_fprintf(stdout, normal_form->canonical); - fprintf(stdout, "Right factor:\n"); - gmp_matrix_fprintf(stdout, normal_form->right); - } - - /* Save the result to the output files */ - outfile_name = append_suffix(file_base_name, "left"); - if( gmp_matrix_write_coord(outfile_name, normal_form -> left) - == EXIT_SUCCESS) - { - if(verbose_wanted == WANTED) - fprintf(stdout, "Left factor successfully writen to file %s\n", outfile_name); - } - - free(outfile_name); - - outfile_name = append_suffix(file_base_name, "can"); - if( gmp_matrix_write_coord(outfile_name, normal_form -> canonical) - == EXIT_SUCCESS) - { - if(verbose_wanted == WANTED) - fprintf(stdout, "Canonical form successfully writen to file %s\n", outfile_name); - } - free(outfile_name); - - outfile_name = append_suffix(file_base_name, "right"); - if( gmp_matrix_write_coord(outfile_name, normal_form -> right) - == EXIT_SUCCESS) - { - if(verbose_wanted == WANTED) - fprintf(stdout, "Right factor successfully writen to file %s\n", outfile_name); - } - free(outfile_name); - - free(file_base_name); - destroy_gmp_normal_form(normal_form); - - return EXIT_SUCCESS; -} diff --git a/contrib/kbipack/gmp_blas.c b/contrib/kbipack/gmp_blas.c deleted file mode 100644 index 6003888d5b67598c71dd23a44d50e5702f2c0feb..0000000000000000000000000000000000000000 --- a/contrib/kbipack/gmp_blas.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - Source file for integer-oriented elementary versions of some - subroutines of BLAS. There routines are chosen to facilitate the - computation of Hermite and Smith normal forms of matrices of - modest size. - - Copyright (C) 28.10.2003 Saku Suuriniemi TUT/CEM - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Saku Suuriniemi, TUT/Electromagetics - P.O.Box 692, FIN-33101 Tampere, Finland - saku.suuriniemi@tut.fi - - $Id: gmp_blas.c,v 1.1 2009-03-30 14:10:57 matti Exp $ -*/ - -/* #include<stdio.h> */ -#include"gmp_blas.h" - -void gmp_blas_swap(size_t n, mpz_t* x, size_t incx, mpz_t* y, size_t incy) -{ - mpz_t elbow; - size_t ind; - - mpz_init(elbow); - - for(ind = 0; ind < n; ind++) - { - mpz_set(elbow , x[ind*incx]); - mpz_set(x[ind*incx], y[ind*incy]); - mpz_set(y[ind*incy], elbow); - } - mpz_clear(elbow); - - return; -} - -void gmp_blas_scal(size_t n, mpz_t a, mpz_t* x, size_t incx) -{ - size_t ind; - - for(ind = 0; ind < n; ind++) - { - mpz_mul (x[ind*incx], x[ind*incx], a); - } - - return; -} - -void gmp_blas_copy(size_t n, const mpz_t* x, size_t incx, mpz_t* y, size_t incy) -{ - size_t ind; - - for(ind = 0; ind < n; ind++) - { - mpz_set(y[ind*incy], x[ind*incx]); - } - - return; -} - -void gmp_blas_axpy(size_t n, mpz_t a, const mpz_t* x, size_t incx, - mpz_t* y, size_t incy) -{ - size_t ind; - - for(ind = 0; ind < n; ind++) - { - mpz_addmul (y[ind*incy], a, x[ind*incx]); - } - - return; -} - -void -gmp_blas_dot(mpz_t * d, size_t n, - const mpz_t* x, size_t incx, - const mpz_t* y, size_t incy) -{ - size_t ind; - - mpz_set_si(*d,0); - - for(ind = 0; ind < n; ind++) - { - mpz_addmul (*d, x[ind*incx], y[ind*incy]); - } - - return; -} - -/* x <- ax + by - y <- cx + dy */ -void gmp_blas_rot(size_t n, - mpz_t a, mpz_t b, mpz_t* x, size_t incx, - mpz_t c, mpz_t d, mpz_t* y, size_t incy) -{ - mpz_t ax; - mpz_t by; - mpz_t cx; - mpz_t dy; - - size_t ind; - - mpz_init(ax); - mpz_init(by); - mpz_init(cx); - mpz_init(dy); - - for(ind = 0; ind < n; ind++) - { - mpz_mul (ax, a, x[ind*incx]); - mpz_mul (by, b, y[ind*incy]); - mpz_mul (cx, c, x[ind*incx]); - mpz_mul (dy, d, y[ind*incy]); - mpz_add (x[ind*incx], ax, by); - mpz_add (y[ind*incy], cx, dy); - } - - mpz_clear(ax); - mpz_clear(by); - mpz_clear(cx); - mpz_clear(dy); - - return; -} - - -/* Returns k such that x[(k-1)*incx] != 0 holds for the first time. - If none found, returns n+1. */ -size_t gmp_blas_inz (size_t n, const mpz_t* x, size_t incx) -{ - size_t ind; - - for(ind = 0; ind < n; ind++) - { - if(mpz_sgn (x[ind*incx]) != 0) - { - return ind+1; - } - } - - /* No nonzeros found */ - return n+1; -} - -size_t gmp_blas_iamax(size_t n, const mpz_t* x, size_t incx) -{ - size_t ind; - size_t ind_so_far; - mpz_t max_so_far; - - mpz_init(max_so_far); - mpz_set_si(max_so_far, 0); - ind_so_far = 0; - - for(ind = 0; ind < n; ind++) - { - if(mpz_cmpabs (x[ind*incx], max_so_far) > 0) - { - mpz_set(max_so_far, x[ind*incx]); - ind_so_far = ind; - } - } - - /* No nonzeros found */ - if(mpz_sgn (max_so_far) == 0) - { - mpz_clear(max_so_far); - return n + 1; - } - - /* Nonzero maximal by modulus element found */ - mpz_clear(max_so_far); - return ind_so_far + 1; -} - - -size_t gmp_blas_iamin(size_t n, const mpz_t* x, size_t incx) -{ - size_t ind; - size_t ind_so_far; - mpz_t min_so_far; - - ind_so_far = gmp_blas_inz (n, x, incx); - - /* No nonzeros found? */ - if(ind_so_far == n+1) - { - return n+1; - } - - /* OK, There is at leat one nonzero element */ - mpz_init(min_so_far); - mpz_set(min_so_far, x[(ind_so_far-1)*incx]); - - /* Scan through te rest of the elements to see if smaller - elements by modulus are found */ - for(ind = ind_so_far-1; ind < n; ind++) - { - if(mpz_sgn (x[ind*incx]) != 0) - { - if(mpz_cmpabs (x[ind*incx], min_so_far) < 0) - { - mpz_set(min_so_far, x[ind*incx]); - ind_so_far = ind + 1; - } - } - } - - /* Nonzero minimal by modulus element found */ - mpz_clear(min_so_far); - return ind_so_far; -} diff --git a/contrib/kbipack/gmp_matrix.c b/contrib/kbipack/gmp_matrix.c deleted file mode 100644 index a9a4f9eeee77aef68f069eb842ed68f63895c769..0000000000000000000000000000000000000000 --- a/contrib/kbipack/gmp_matrix.c +++ /dev/null @@ -1,823 +0,0 @@ -/* - Source file for integer-oriented matrix, relying on the arbitrary - precision integers from the GNU gmp package. - - Copyright (C) 28.10.2003 Saku Suuriniemi TUT/CEM - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Saku Suuriniemi, TUT/Electromagetics - P.O.Box 692, FIN-33101 Tampere, Finland - saku.suuriniemi@tut.fi - - $Id: gmp_matrix.c,v 1.5 2009-05-05 11:35:01 matti Exp $ -*/ - - -#include<stdlib.h> -#include"gmp_matrix.h" - -gmp_matrix * -create_gmp_matrix(size_t r, size_t c, - const mpz_t * e) -{ - gmp_matrix * new_matrix; - size_t ind; - - new_matrix = (gmp_matrix * ) malloc(sizeof(gmp_matrix)); - if(new_matrix == NULL) - { - return NULL; - } - - new_matrix -> storage = (mpz_t *) calloc(r*c, sizeof(mpz_t)); - if(new_matrix -> storage == NULL) - { - free(new_matrix); - return NULL; - } - - new_matrix -> rows = r; - new_matrix -> cols = c; - - for(ind = 0; ind < r*c; ind ++) - { - mpz_init (new_matrix -> storage[ind]); - mpz_set (new_matrix -> storage[ind], e[ind]); - } - - return new_matrix; -} - -gmp_matrix * -create_gmp_matrix_int(size_t r, size_t c, - const long int * e) -{ - gmp_matrix * new_matrix; - size_t ind; - - new_matrix = (gmp_matrix * ) malloc(sizeof(gmp_matrix)); - if(new_matrix == NULL) - { - return NULL; - } - - new_matrix -> storage = (mpz_t *) calloc(r*c, sizeof(mpz_t)); - if(new_matrix -> storage == NULL) - { - free(new_matrix); - return NULL; - } - - new_matrix -> rows = r; - new_matrix -> cols = c; - - for(ind = 0; ind < r*c; ind ++) - { - mpz_init (new_matrix -> storage[ind]); - mpz_set_si (new_matrix -> storage[ind], e[ind]); - } - - return new_matrix; -} - - -gmp_matrix * -create_gmp_matrix_identity(size_t dim) -{ - gmp_matrix * new_matrix; - size_t ind; - - new_matrix = (gmp_matrix * ) malloc(sizeof(gmp_matrix)); - if(new_matrix == NULL) - { - return NULL; - } - - new_matrix -> storage = (mpz_t *) calloc(dim*dim, sizeof(mpz_t)); - if(new_matrix -> storage == NULL) - { - free(new_matrix); - return NULL; - } - - new_matrix -> rows = dim; - new_matrix -> cols = dim; - - for(ind = 0; ind < dim*dim; ind ++) - { - mpz_init_set_si (new_matrix -> storage[ind], 0); - } - - for(ind = 0; ind < dim; ind ++) - { - mpz_set_ui(new_matrix -> storage[ind*(dim+1)], 1); - } - - return new_matrix; -} - - -gmp_matrix * -create_gmp_matrix_zero(size_t rows, size_t cols) -{ - gmp_matrix * new_matrix; - size_t ind; - - new_matrix = (gmp_matrix * ) malloc(sizeof(gmp_matrix)); - if(new_matrix == NULL) - { - return NULL; - } - - new_matrix -> storage = (mpz_t *) calloc(rows*cols, sizeof(mpz_t)); - if(new_matrix -> storage == NULL) - { - free(new_matrix); - return NULL; - } - - new_matrix -> rows = rows; - new_matrix -> cols = cols; - - for(ind = 0; ind < rows*cols; ind ++) - { - mpz_init_set_si (new_matrix -> storage[ind], 0); - } - return new_matrix; -} - -gmp_matrix * -copy_gmp_matrix(const gmp_matrix * matrix, - const size_t start_row, const size_t start_col, - const size_t end_row, const size_t end_col) -{ - gmp_matrix * new_matrix; - size_t ind; - size_t r; - size_t c; - size_t old_rows; - size_t old_cols; - size_t i; - size_t j; - - new_matrix = (gmp_matrix * ) malloc(sizeof(gmp_matrix)); - if(new_matrix == NULL) - { - return NULL; - } - - r = end_row-start_row+1; - c = end_col-start_col+1; - if(r < 1 || c < 1) return NULL; - - new_matrix -> storage = (mpz_t *) calloc(r*c, sizeof(mpz_t)); - if(new_matrix -> storage == NULL) - { - free(new_matrix); - return NULL; - } - - new_matrix -> rows = r; - new_matrix -> cols = c; - - old_rows = matrix -> rows; - old_cols = matrix -> cols; - - ind = 0; - for(j = 1; j <= old_cols; j++){ - if(j >= start_col && j <= end_col){ - for(i = 1; i <= old_rows; i++){ - if(i >= start_row && i <= end_row){ - mpz_init (new_matrix -> storage[ind]); - mpz_set (new_matrix -> storage[ind], matrix -> storage[(j-1)*old_rows+(i-1)]); - ind++; - } - } - } - } - - return new_matrix; -} - -int -destroy_gmp_matrix(gmp_matrix * m) -{ - size_t ind, nmb_storage;; - - if(m == NULL) - { - return EXIT_FAILURE; - } - - if(m -> storage == NULL) - { - free(m); - return EXIT_FAILURE; - } - - nmb_storage = (m -> rows)*(m -> cols); - - for(ind = 0; ind < nmb_storage; ind++) - { - mpz_clear(m -> storage[ind]); - } - - free(m -> storage); - free(m); - return EXIT_SUCCESS; -} - - -size_t -gmp_matrix_rows(const gmp_matrix * m) -{ - if(m == NULL) - { - return 0; - } - - return m -> rows; -} - - -size_t -gmp_matrix_cols(const gmp_matrix * m) -{ - if(m == NULL) - { - return 0; - } - - return m -> cols; -} - -/* elem <- (matrix(row, col)) */ -int -gmp_matrix_get_elem(mpz_t elem, size_t row, size_t col, - const gmp_matrix * m) -{ -#ifdef DEBUG - - if(m == NULL) - { - return EXIT_FAILURE; - } - -#endif - - mpz_set(elem, m -> storage[(col-1)*(m -> rows)+row-1]); - return EXIT_SUCCESS; -} - -/* (matrix(row, col)) <- elem */ -int -gmp_matrix_set_elem(mpz_t elem, size_t row, size_t col, - const gmp_matrix * m) -{ -#ifdef DEBUG - - if(m == NULL) - { - return EXIT_FAILURE; - } - -#endif - - mpz_set(m -> storage[(col-1)*(m -> rows)+row-1], elem); - return EXIT_SUCCESS; -} - -int -gmp_matrix_swap_rows(size_t row1, size_t row2, gmp_matrix * m) -{ - if(m == NULL) - { - return EXIT_FAILURE; - } - if((row1 < 1) || (row1 > m->rows) || (row2 < 1) || (row2 > m->rows)) - { - return EXIT_FAILURE; - } - - /* printf("Swapping rows %i %i\n", row1, row2); */ - gmp_blas_swap(m -> cols, - &(m -> storage[row1-1]), m -> rows, - &(m -> storage[row2-1]), m -> rows); - - return EXIT_SUCCESS; -} - -int -gmp_matrix_swap_cols(size_t col1, size_t col2, gmp_matrix * m) -{ - if(m == NULL) - { - return EXIT_FAILURE; - } - if((col1 < 1) || (col1 > m->cols) || (col2 < 1) || (col2 > m->cols)) - { - return EXIT_FAILURE; - } - - /* printf("Swapping cols %i %i\n", col1, col2); */ - gmp_blas_swap(m -> rows, - &(m -> storage[(m->rows)*(col1-1)]), 1, - &(m -> storage[(m->rows)*(col2-1)]), 1); - - return EXIT_SUCCESS; -} - -int -gmp_matrix_negate_row(size_t row, gmp_matrix * m) -{ - mpz_t minus_one; - - if(m == NULL) - { - return EXIT_FAILURE; - } - if((row < 1) || (row > m->rows)) - { - return EXIT_FAILURE; - } - - mpz_init(minus_one); - mpz_set_si(minus_one, -1); - gmp_blas_scal(m -> cols, minus_one, (&m -> storage[row-1]), m -> rows); - mpz_clear(minus_one); - return EXIT_SUCCESS; -} - -int -gmp_matrix_negate_col(size_t col, gmp_matrix * m) -{ - mpz_t minus_one; - if(m == NULL) - { - return EXIT_FAILURE; - } - if((col < 1) || (col > m->cols)) - { - return EXIT_FAILURE; - } - mpz_init(minus_one); - mpz_set_si(minus_one, -1); - gmp_blas_scal(m -> rows, minus_one, - &(m -> storage[(m->rows)*(col-1)]), 1); - mpz_clear(minus_one); - return EXIT_SUCCESS; -} - -/* row2 <- a*row1 + row2*/ -int -gmp_matrix_add_row(mpz_t a, size_t row1, size_t row2, - gmp_matrix * m) -{ - if(m == NULL) - { - return EXIT_FAILURE; - } - if((row1 < 1) || (row1 > m->rows) || (row2 < 1) || (row2 > m->rows)) - { - return EXIT_FAILURE; - } - - gmp_blas_axpy(m->cols, a, - (const mpz_t *) &(m->storage[row1-1]), m->rows, - &(m->storage[row2-1]), m->rows); - - return EXIT_SUCCESS; -} - -int -gmp_matrix_add_col(mpz_t a, size_t col1, size_t col2, - gmp_matrix * m) -{ - if(m == NULL) - { - return EXIT_FAILURE; - } - if((col1 < 1) || (col1 > m->cols) || (col2 < 1) || (col2 > m->cols)) - { - return EXIT_FAILURE; - } - - gmp_blas_axpy(m->rows, a, - (const mpz_t *) &(m -> storage[(m->rows)*(col1-1)]), 1, - &(m -> storage[(m->rows)*(col2-1)]), 1); - - return EXIT_SUCCESS; -} - -/* row1 <- a*row1 + b*row2 - row2 <- c*row1 + d*row2 */ -int -gmp_matrix_row_rot(mpz_t a, mpz_t b, size_t row1, - mpz_t c, mpz_t d, size_t row2, - gmp_matrix * m) -{ - if(m == NULL) - { - return EXIT_FAILURE; - } - if((row1 < 1) || (row1 > m->rows) || (row2 < 1) || (row2 > m->rows)) - { - return EXIT_FAILURE; - } - - gmp_blas_rot(m->cols, - a, b, &(m->storage[row1-1]), m->rows, - c, d, &(m->storage[row2-1]), m->rows); - - return EXIT_SUCCESS; -} -int -gmp_matrix_col_rot(mpz_t a, mpz_t b, size_t col1, - mpz_t c, mpz_t d, size_t col2, - gmp_matrix * m) -{ - if(m == NULL) - { - return EXIT_FAILURE; - } - if((col1 < 1) || (col1 > m->cols) || (col2 < 1) || (col2 > m->cols)) - { - return EXIT_FAILURE; - } - -/* printf("a: %i b: %i c: %i d:%i col1: %i col2: %i\n", */ -/* mpz_get_si(a), */ -/* mpz_get_si(b), */ -/* mpz_get_si(c), */ -/* mpz_get_si(d), */ -/* col1, col2); */ - - gmp_blas_rot(m->rows, - a, b, &(m -> storage[(m->rows)*(col1-1)]), 1, - c, d, &(m -> storage[(m->rows)*(col2-1)]), 1); - - return EXIT_SUCCESS; -} - -size_t -gmp_matrix_col_inz (size_t r1, size_t r2, size_t c, - gmp_matrix * m) -{ - size_t result; - - if(m == NULL) - { - return 0; - } - if((r1 < 1) || (r1 > m->rows) || - (r2 < 1) || (r2 > m->rows) || - (r2 < r1) || (c < 1) || (c > m->cols)) - { - return 0; - } - - result = gmp_blas_inz(r2-r1+1, - (const mpz_t *) &(m->storage[(c-1)*(m->rows)+r1-1]), - 1); - - if(result > r2-r1+1) - { - return 0; - } - - return result; -} - -size_t -gmp_matrix_row_inz (size_t r, size_t c1, size_t c2, - gmp_matrix * m) -{ - size_t result; - - if(m == NULL) - { - return 0; - } - if((r < 1) || (r > m->rows) || - (c1 < 1) || (c1 > m->cols) || - (c2 < c1) || (c2 < 1) || (c2 > m->cols)) - { - return 0; - } - - result = gmp_blas_inz(c2-c1+1, - (const mpz_t *) &(m->storage[(c1-1)*(m->rows)+r-1]), - m->rows); - - if(result > c2-c1+1) - { - return 0; - } - - return result; -} - - -int -gmp_matrix_is_diagonal(const gmp_matrix * M) -{ - size_t i,j; - size_t rows, cols; - - if(M == NULL) - { - return 0; - } - - rows = M->rows; - cols = M->cols; - - for(j = 1; j <= cols; j ++) - { - for(i = 1; i <= rows; i ++) - { - if((mpz_cmp_si(M->storage[(i-1)+(j-1)*rows], 0) != 0) && - (i != j)) - { - return 0; - } - } - } - - return 1; -} - - -int -gmp_matrix_transp(gmp_matrix * M) -{ - mpz_t * new_storage; - size_t i,j; - size_t rows, cols; - - if(M == NULL) - { - return EXIT_FAILURE; - } - - rows = M->rows; - cols = M->cols; - - new_storage = (mpz_t *) calloc(rows*cols, sizeof(mpz_t)); - if(new_storage == NULL) - { - return EXIT_FAILURE; - } - - if(rows == 1){ - for(i = 1; i <= cols; i++) - { - mpz_init_set(new_storage[i-1], - M-> storage[i-1]); - mpz_clear(M-> storage[i-1]); - } - } - else if(cols == 1){ - for(i = 1; i <= rows; i++) - { - mpz_init_set(new_storage[i-1], - M-> storage[i-1]); - mpz_clear(M-> storage[i-1]); - } - } - else{ - for(i = 1; i <= rows; i++) - { - for(j = 1; j <= cols; j++) - { - mpz_init_set(new_storage[(j-1)+(i-1)*cols], - M-> storage[(i-1)+(j-1)*rows]); - mpz_clear(M-> storage[(i-1)+(j-1)*rows]); - } - } - } - - free(M->storage); - - M -> storage = new_storage; - M -> rows = cols; - M -> cols = rows; - - return EXIT_SUCCESS; -} - -int -gmp_matrix_sum(gmp_matrix * A, const gmp_matrix * B) -{ - size_t i,j; - size_t rows_A, cols_A, rows_B, cols_B; - - if((A == NULL) || (B == NULL)) - { - return EXIT_FAILURE; - } - - rows_A = A->rows; - cols_A = A->cols; - rows_B = B->rows; - cols_B = B->cols; - - if(cols_A != cols_B || rows_A != rows_B) - { - return EXIT_FAILURE; - } - mpz_t a; - mpz_init_set_si(a, 1); - /* Compute the sum */ - for(i = 1; i <= rows_A; i++) - { - - } - - return EXIT_SUCCESS; -} - -int -gmp_matrix_right_mult(gmp_matrix * A, const gmp_matrix * B) -{ - mpz_t * new_storage; - size_t i,j; - size_t rows_A, cols_A, rows_B, cols_B; - - if((A == NULL) || (B == NULL)) - { - return EXIT_FAILURE; - } - - rows_A = A->rows; - cols_A = A->cols; - rows_B = B->rows; - cols_B = B->cols; - - if(cols_A != rows_B) - { - return EXIT_FAILURE; - } - - /* Create new storage for the product */ - new_storage = (mpz_t *) calloc(rows_A*cols_B, sizeof(mpz_t)); - if(new_storage == NULL) - { - return EXIT_FAILURE; - } - - /* Compute the product to the storage */ - for(j = 1; j <= cols_B; j++) - { - for(i = 1; i <= rows_A; i++) - { - mpz_init (new_storage[(i-1)+(j-1)*rows_A]); - gmp_blas_dot(&(new_storage[(i-1)+(j-1)*rows_A]), - cols_A, - (const mpz_t *) &(A->storage[i-1]), rows_A, - (const mpz_t *) &(B->storage[(j-1)*rows_B]), 1); - } - } - - /* Get rid of the old storage */ - for(i = 1; i <= rows_A*cols_A; i++) - { - mpz_clear (A->storage[i-1]); - } - free(A->storage); - - /* Update A */ - A -> storage = new_storage; - A -> cols = cols_B; - - return EXIT_SUCCESS; -} - -int -gmp_matrix_left_mult(const gmp_matrix * A, gmp_matrix * B) -{ - mpz_t * new_storage; - size_t i,j; - size_t rows_A, cols_A, rows_B, cols_B; - - if((A == NULL) || (B == NULL)) - { - return EXIT_FAILURE; - } - - rows_A = A->rows; - cols_A = A->cols; - rows_B = B->rows; - cols_B = B->cols; - - if(cols_A != rows_B) - { - return EXIT_FAILURE; - } - - /* Create new storage for the product */ - new_storage = (mpz_t *) calloc(rows_A*cols_B, sizeof(mpz_t)); - if(new_storage == NULL) - { - return EXIT_FAILURE; - } - - /* Compute the product to the storage */ - for(j = 1; j <= cols_B; j++) - { - for(i = 1; i <= rows_A; i++) - { - mpz_init (new_storage[(i-1)+(j-1)*rows_A]); - gmp_blas_dot(&(new_storage[(i-1)+(j-1)*rows_A]), - cols_A, - (const mpz_t *) &(A->storage[i-1]), rows_A, - (const mpz_t *) &(B->storage[(j-1)*rows_B]), 1); - } - } - - /* Get rid of the old storage */ - for(i = 1; i <= rows_B*cols_B; i++) - { - mpz_clear (B->storage[i-1]); - } - free(B->storage); - - /* Update A */ - B -> storage = new_storage; - B -> rows = rows_A; - - return EXIT_SUCCESS; -} - - -int gmp_matrix_printf(const gmp_matrix * m) -{ - - mpz_t outz; - size_t rows, cols, i, j; - - if(m == NULL) - { - return EXIT_FAILURE; - } - - rows = m->rows; - cols = m->cols; - mpz_init(outz); - for(i = 1; i <= rows ; i++) - { - for(j = 1; j <= cols ; j++) - { - gmp_matrix_get_elem(outz, i, j, m); - mpz_out_str (stdout, 10, outz); - printf(" "); - } - printf("\n"); - } - - mpz_clear(outz); - - return EXIT_SUCCESS; -} - -int gmp_matrix_fprintf(FILE* stream, const gmp_matrix * m) -{ - mpz_t outz; - size_t rows, cols, i, j; - - if(m == NULL) - { - return EXIT_FAILURE; - } - - rows = m->rows; - cols = m->cols; - mpz_init(outz); - for(i = 1; i <= rows ; i++) - { - for(j = 1; j <= cols ; j++) - { - gmp_matrix_get_elem(outz, i, j, m); - mpz_out_str (stream, 10, outz); - printf(" "); - } - printf("\n"); - } - - mpz_clear(outz); - - return EXIT_SUCCESS; -} diff --git a/contrib/kbipack/gmp_matrix_io.c b/contrib/kbipack/gmp_matrix_io.c deleted file mode 100644 index ca1c6e48778d682500163b4934ecd981949da23d..0000000000000000000000000000000000000000 --- a/contrib/kbipack/gmp_matrix_io.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - IO-routines for gmp integer matrices in coordinate format. - - Copyright (C) 19.11.2003 Saku Suuriniemi TUT/CEM - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Saku Suuriniemi, TUT/Electromagetics - P.O.Box 692, FIN-33101 Tampere, Finland - saku.suuriniemi@tut.fi - - $Id: gmp_matrix_io.c,v 1.1 2009-03-30 14:10:57 matti Exp $ - */ - -#include<stdio.h> -#include<stdlib.h> -#include<string.h> -#include "gmp_matrix_io.h" - -gmp_matrix * gmp_matrix_read_coord(char* filename) -{ - FILE * p_file; - size_t read_values; - size_t row, col, nrows, ncols, dummy; - int val; - char buffer[1000]; - gmp_matrix * new_matrix; - - p_file = fopen(filename, "r"); - if(p_file == NULL) - return NULL; - - /* Matlab and Octave typically include comments on ascii files. */ - /* They start with # */ - fgets(buffer, 999, p_file); - while(strncmp(buffer, "#",1) == 0) - { - fgets(buffer, 999, p_file); - } - - /* First read the size of the matrix */ - read_values = sscanf(buffer, "%lu %lu %lu", &nrows, &ncols, &dummy); - - /* Create the matrix */ - new_matrix = create_gmp_matrix_zero(nrows, ncols); - if(new_matrix == NULL) - { - fclose(p_file); - return NULL; - } - - /* Read the values to the matrix */ - while(read_values != EOF) - { - read_values = fscanf(p_file, "%u %u %i\n", &row, &col, &val); - if( (row <= nrows) && (row > 0) && (col <= ncols) && (col > 0) ) - { - mpz_set_si ( new_matrix->storage[(row-1)+(col-1)*nrows], val ); - } - } - fclose(p_file); - - return new_matrix; -} - -int gmp_matrix_write_coord(char* filename, const gmp_matrix * M) -{ - - FILE * p_file; - size_t written_values; - size_t row, col, nrows, ncols, nnz; - mpz_t outz; - - if(M == NULL) - { - return EXIT_FAILURE; - } - - nrows = M->rows; - ncols = M->cols; - - p_file = fopen(filename, "w"); - if(p_file == NULL) - return 0; - - nnz = 0; - /* Compute the number of nonzeros for coordinate format */ - mpz_init(outz); - for(col = 1; col <= ncols ; col++) - { - for(row = 1; row <= nrows ; row++) - { - gmp_matrix_get_elem(outz, row, col, M); - if( mpz_cmp_si (outz, 0) != 0) - { - nnz++; - } - } - } - - /* First write the size of the matrix */ - written_values = fprintf(p_file, "%u %u %u\n", nrows, ncols, nnz); - - /* Write the values to the matrix */ - for(col = 1; col <= ncols ; col++) - { - for(row = 1; row <= nrows ; row++) - { - gmp_matrix_get_elem(outz, row, col, M); - if( mpz_cmp_si (outz, 0) != 0) - { - fprintf(p_file, "%u %u ", row, col); - mpz_out_str (p_file, 10, outz); - fprintf(p_file, "\n"); - } - } - } - mpz_clear(outz); - - fclose(p_file); - - return EXIT_SUCCESS; -} diff --git a/contrib/kbipack/gmp_normal_form.c b/contrib/kbipack/gmp_normal_form.c deleted file mode 100644 index 42785337e7e54cf85e1bc82b1dc0ea52b14ed925..0000000000000000000000000000000000000000 --- a/contrib/kbipack/gmp_normal_form.c +++ /dev/null @@ -1,783 +0,0 @@ -/* - Implementation for integer computation of Hermite and Smith normal - forms of matrices of modest size. - - Implementation: Dense matrix with GMP-library's mpz_t elements to - hold huge integers. - - Algorithm: Kannan - Bachem algorithm with improvement by - Chou and Collins. Expects a large number of unit invariant - factors and takes advantage of them as they appear. - - References: - [1] Ravindran Kannan, Achim Bachem: - "Polynomial algorithms for computing the Smith and Hermite normal - forms of an integer matrix", - SIAM J. Comput., vol. 8, no. 5, pp. 499-507, 1979. - [2] Tsu-Wu J.Chou, George E. Collins: - "Algorithms for the solution of systems of linear Diophantine - equations", - SIAM J. Comput., vol. 11, no. 4, pp. 687-708, 1982. - [3] GMP homepage http://www.swox.com/gmp/ - [4] GNU gmp page http://www.gnu.org/software/gmp/ - - Copyright (C) 30.10.2003 Saku Suuriniemi TUT/CEM - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Saku Suuriniemi, TUT/Electromagetics - P.O.Box 692, FIN-33101 Tampere, Finland - saku.suuriniemi@tut.fi - - $Id: gmp_normal_form.c,v 1.1 2009-03-30 14:10:57 matti Exp $ -*/ - -#include<stdlib.h> -#include"gmp_blas.h" -#include"gmp_matrix.h" -#include"gmp_normal_form.h" - - -/* The unaltered matrix and identity left and right factors */ -static gmp_normal_form * -create_gmp_trivial_normal_form(gmp_matrix * A, - inverted_flag left_inverted, - inverted_flag right_inverted) -{ - size_t rows, cols; - - gmp_normal_form * new_nf; - if(A == NULL) - { - return NULL; - } - - new_nf = (gmp_normal_form *) malloc(sizeof(gmp_normal_form)); - if(new_nf == NULL) - { - destroy_gmp_matrix(A); - return NULL; - } - - rows = A -> rows; - cols = A -> cols; - - if((rows == 0) || (cols == 0)) - { - destroy_gmp_matrix(A); - return NULL; - } - - new_nf->left = create_gmp_matrix_identity(rows); - if(new_nf->left == NULL) - { - destroy_gmp_matrix(A); - free(new_nf); - return NULL; - } - - new_nf->right = create_gmp_matrix_identity(cols); - if(new_nf->right == NULL) - { - destroy_gmp_matrix(A); - destroy_gmp_matrix(new_nf->left); - free(new_nf); - return NULL; - } - - new_nf -> canonical = A; - new_nf -> left_inverted = left_inverted; - new_nf -> right_inverted = right_inverted; - - return new_nf; -} - -static int -gmp_Hermite_eliminate_step(gmp_matrix * L, gmp_matrix * U, - size_t col, inverted_flag right_inverted) -{ - size_t ind, row_limit; - mpz_t pivot, elem; - mpz_t bez1, bez2, gc_div; - mpz_t cff1, cff2; - - mpz_init(pivot); - mpz_init(elem); - mpz_init(bez1); - mpz_init(bez2); - mpz_init(cff1); - mpz_init(cff2); - mpz_init(gc_div); - - row_limit = (L->rows >= col) ? - col-1 : - L->rows; - - for(ind = 1; ind <= row_limit; ind++) - { - gmp_matrix_get_elem(elem, ind, col, L); - - /* Eliminate only if nonzero */ - if(mpz_sgn (elem) != 0) - { - gmp_matrix_get_elem(pivot, ind, ind, L); - - /* Extended Euclid's: - bez1*pivot+bez2*elem = gc_div */ - gmp_blas_rotg(gc_div, bez1, bez2, pivot, elem); - - /* Make cff1 = -elem/gc_div */ - mpz_divexact(cff1, elem, gc_div); - mpz_neg (cff1, cff1); - /* Make cff2 = pivot/gc_div */ - mpz_divexact(cff2, pivot, gc_div); - - /* Update the HNF canonical matrix */ - gmp_matrix_col_rot(bez1, bez2, ind, - cff1, cff2, col, - L); - - /* Update the unimodular factor matrix */ - if(right_inverted == INVERTED) - { - gmp_matrix_col_rot(bez1, bez2, ind, - cff1, cff2, col, - U); - } - else - { - - /* [bez1, -elem/gc_div] [pivot/gc_div, elem/gc_div] - [bez2, pivot/gc_div] [-bez2, bez1 ] = I_2 */ - mpz_neg(cff1, cff1); - mpz_neg(bez2, bez2); - gmp_matrix_row_rot(cff2, cff1, ind, - bez2, bez1, col, - U); - } - } - } - mpz_clear(pivot); - mpz_clear(elem); - mpz_clear(bez1); - mpz_clear(bez2); - mpz_clear(cff1); - mpz_clear(cff2); - mpz_clear(gc_div); - - return EXIT_SUCCESS; -} - - - -static int -gmp_Hermite_reduce_step(gmp_matrix * L, gmp_matrix * U, - size_t col, inverted_flag right_inverted) -{ - - size_t i, j; - mpz_t pivot, elem; - mpz_t cff; - - mpz_init(pivot); - mpz_init(elem); - mpz_init(cff); - - if(col > (L->rows)) - { - return EXIT_FAILURE; - } - - /* printf("Col = %i\n", col); - printf("L before\n"); - gmp_matrix_printf(L);*/ - - for(j = col-1; j >= 1; j--) - { - for(i = j+1; i <= col; i++) - { - gmp_matrix_get_elem(pivot, i, i, L); - gmp_matrix_get_elem(elem, i, j, L); - /* printf(" i %i j %i\n",i,j); */ - - if((mpz_cmpabs(elem, pivot) >= 0) || (mpz_sgn(elem) < 0)) - { - /* The objective: - 0 <= elem + k*pivot < pivot - -elem <= k*pivot < pivot - elem - -elem/pivot <= k < - elem/pivot + 1 - - Solution: - k = ceil(-elem/pivot) - */ - - /* Make cff = -elem */ - mpz_neg (cff, elem); - mpz_cdiv_q (cff, cff, pivot); - - /* printf("col %i j %i\n", i, j); - printf("elem %i k %i pivot %i\n", - mpz_get_si(elem), - mpz_get_si(cff), - mpz_get_si(pivot));*/ - - - gmp_matrix_add_col(cff, i, j, L); - - /* Update the unimodular factor matrix */ - if(right_inverted == INVERTED) - { - gmp_matrix_add_col(cff, i, j, U); - } - - /* [1 0] [ 1 0] = [1 0] - [cff 1] [-cff 1] [0 1] */ - else - { - mpz_neg (cff, cff); - gmp_matrix_add_row(cff, j, i, U); - } - - /* printf("\n"); - gmp_matrix_printf(L);*/ - - } - } - } - -/* printf("L after\n"); */ -/* gmp_matrix_printf(L); */ - - mpz_clear(pivot); - mpz_clear(elem); - mpz_clear(cff); - return EXIT_SUCCESS; -} - - -static int -gmp_normal_form_make_Hermite(gmp_normal_form * nf) -{ - size_t rows, cols; - size_t pivot_ind; - size_t schur, colind; - mpz_t pivot; - gmp_matrix * canonical; - gmp_matrix * left; - gmp_matrix * right; - - if(nf == NULL) - { - return EXIT_FAILURE; - } - - /* OK, it's safe to get to business */ - canonical = nf->canonical; - left = nf->left; - right = nf->right; - rows = canonical -> rows; - cols = canonical -> cols; - - mpz_init(pivot); - - /* "schur" denotes where the present Schur complement starts */ - schur = 1; - - while((schur <= rows) && (schur <= cols)) - { - /* Eliminate a column */ - if (schur > 1) - { - gmp_Hermite_eliminate_step(canonical, right, - schur, nf->right_inverted); - } - - /* Find a pivot */ - pivot_ind = gmp_matrix_col_inz(schur, rows, schur, canonical); - - - /* If no nonzeros was found, the column is all zero, hence - settled with. Permute it to the end and decrement cols. */ - if(pivot_ind == 0) - { - gmp_matrix_swap_cols(schur, cols, canonical); - - if(nf -> right_inverted == INVERTED) - { - gmp_matrix_swap_cols(schur, cols, right); - } - else - { - gmp_matrix_swap_rows(schur, cols, right); - } - - cols--; - - /* When the whole column was zeroed, the diagonal - elements may have got reduced. Reduce the sub- - diagonals as well*/ - - if(schur > 1) - { - gmp_Hermite_reduce_step (canonical, right, schur-1, - nf -> right_inverted); - } - } - - /* A nonzero pivot was found. Permute it to the diagonal position, - make it positive, and reduce the off-diagonals. - The schur complement now starts from the next diagonal. */ - else - { - pivot_ind = schur+pivot_ind-1; - gmp_matrix_swap_rows(schur, pivot_ind, canonical); - - if(nf->left_inverted == INVERTED) - { - gmp_matrix_swap_rows(schur, pivot_ind, left); - } - else - { - gmp_matrix_swap_cols(schur, pivot_ind, left); - } - - /* Make the pivot positive */ - gmp_matrix_get_elem(pivot, schur, schur, canonical); - - if(mpz_cmp_si(pivot, 0) < 0) - { - gmp_matrix_negate_col(schur, canonical); - - if(nf->right_inverted == INVERTED) - { - gmp_matrix_negate_col(schur, right); - } - else - { - gmp_matrix_negate_row(schur, right); - } - } - - /* Reduce off-diagonals */ - gmp_Hermite_reduce_step (canonical, right, schur, nf -> right_inverted); - - schur++; - } - } - - /* The Schur complement is now empty. There may still be uneliminated - columns left (in case of a wide matrix) */ - - colind = schur; - while (colind <= cols) - { - gmp_Hermite_eliminate_step (canonical, right, colind, nf->right_inverted); - gmp_Hermite_reduce_step (canonical, right, schur-1, nf->right_inverted); - colind++; - } - - mpz_clear(pivot); - - return EXIT_SUCCESS; -} - - - -gmp_normal_form * -create_gmp_Hermite_normal_form(gmp_matrix * A, - inverted_flag left_inverted, - inverted_flag right_inverted) -{ - gmp_normal_form * new_nf; - - if(A == NULL) - { - return NULL; - } - - new_nf = - create_gmp_trivial_normal_form(A, left_inverted, right_inverted); - - if(new_nf == NULL) - { - /* A has been destroyed already */ - return NULL; - } - - if(gmp_normal_form_make_Hermite(new_nf) != EXIT_SUCCESS) - { - destroy_gmp_normal_form(new_nf); - return NULL; - } - - return new_nf; -} - - -gmp_normal_form * -create_gmp_Smith_normal_form(gmp_matrix * A, - inverted_flag left_inverted, - inverted_flag right_inverted) -{ - - gmp_normal_form * new_nf; - gmp_matrix * canonical; - gmp_matrix * elbow; - inverted_flag elbow_flag; - size_t rows, cols; - size_t i, j; - size_t subd_ind, row_undivisible; - size_t last_ready_row, first_ready_col, ind; - mpz_t pivot; - mpz_t remainder; - - if(A == NULL) - { - return NULL; - } - - new_nf = - create_gmp_trivial_normal_form(A, left_inverted, right_inverted); - - if(new_nf == NULL) - { - /* A has been destroyed already */ - return NULL; - } - - canonical = new_nf -> canonical; - mpz_init(pivot); - mpz_init(remainder); - rows = canonical->rows; - cols = canonical->cols; - last_ready_row = 0; - first_ready_col = (cols < rows) ? (cols+1) : (rows+1); - - while(first_ready_col > last_ready_row + 1) - { - /*******/ - /* HNF */ - /*******/ - - if(gmp_normal_form_make_Hermite(new_nf) != EXIT_SUCCESS) - { - destroy_gmp_normal_form(new_nf); - mpz_clear(pivot); - mpz_clear(remainder); - return NULL; - } - -#ifdef DEBUG - printf("HNF\n"); - gmp_matrix_printf (new_nf -> left); - gmp_matrix_printf (new_nf -> canonical); - gmp_matrix_printf (new_nf -> right); -#endif - - /**********************/ - /* Find ready columns */ - /**********************/ - - /* If a diagonal entry is zero, so is the corresponding - column. The zero diagonals always reside in the end. - Seek until zero diagonal encountered, but stay within the matrix! */ - ind = 1; - while ( (ind < first_ready_col) && - (mpz_cmp_si(canonical -> storage[(ind-1)+(ind-1)*rows], 0) != 0) - ) - { - ind ++; - } - first_ready_col = ind; - - /* Note: The number of ready cols is settled after the first HNF, - but the check is cheap. */ - - /**********************************************/ - /* Permute unit diagonals such that they lead */ - /**********************************************/ - - /* If the recently computed HNF has ones on the diagonal, their - corresponding rows are all zero (except the diagonal). - They are then settled, because the next LHNF kills the elements - on their columns. */ - - ind = last_ready_row+1; - - /* Stay within the nonzero cols of the matrix */ - while (ind < first_ready_col) - { - /* Unit diagonal encountered */ - if(mpz_cmp_si ( canonical->storage[(ind-1) + (ind-1)*rows], - 1) == 0) - { - /* If not in the beginning, permute to extend the leading minor - with unit diagonals */ - if(ind != last_ready_row+1) - { - gmp_matrix_swap_rows(last_ready_row+1, ind, - new_nf -> canonical); - - if(left_inverted == INVERTED) - { - gmp_matrix_swap_rows(last_ready_row+1, ind, - new_nf -> left); - } - else - { - gmp_matrix_swap_cols(last_ready_row+1, ind, - new_nf -> left); - } - - gmp_matrix_swap_cols(last_ready_row+1, ind, - new_nf -> canonical); - - if(right_inverted == INVERTED) - { - gmp_matrix_swap_cols(last_ready_row+1, ind, - new_nf -> right); - } - else - { - gmp_matrix_swap_rows(last_ready_row+1, ind, - new_nf -> right); - } - } - last_ready_row ++; - } - ind++; - } - -#ifdef DEBUG - printf("Leading units\n"); - gmp_matrix_printf (new_nf -> left); - gmp_matrix_printf (new_nf -> canonical); - gmp_matrix_printf (new_nf -> right); -#endif - - /********/ - /* LHNF */ - /********/ - - /* Extravagant strategy: Compute HNF of an explicit tranpose. */ - - /* 1. Transpose everything in the normal form */ - if(gmp_matrix_transp(canonical) != EXIT_SUCCESS) - { - destroy_gmp_normal_form(new_nf); - mpz_clear(pivot); - mpz_clear(remainder); - return NULL; - } - if(gmp_matrix_transp(new_nf->left) != EXIT_SUCCESS) - { - destroy_gmp_normal_form(new_nf); - mpz_clear(pivot); - mpz_clear(remainder); - return NULL; - } - if(gmp_matrix_transp(new_nf->right) != EXIT_SUCCESS) - { - destroy_gmp_normal_form(new_nf); - mpz_clear(pivot); - mpz_clear(remainder); - return NULL; - } - - elbow = new_nf ->left; - new_nf ->left = new_nf ->right; - new_nf ->right = elbow; - elbow_flag = new_nf ->left_inverted; - new_nf ->left_inverted = new_nf ->right_inverted; - new_nf ->right_inverted = elbow_flag; - - /* 2. Compute HNF of the transpose */ - if(gmp_normal_form_make_Hermite(new_nf) != EXIT_SUCCESS) - { - destroy_gmp_normal_form(new_nf); - mpz_clear(pivot); - mpz_clear(remainder); - return NULL; - } - - /* 3. Transpose everything back */ - if(gmp_matrix_transp(canonical) != EXIT_SUCCESS) - { - destroy_gmp_normal_form(new_nf); - mpz_clear(pivot); - mpz_clear(remainder); - return NULL; - } - if(gmp_matrix_transp(new_nf->left) != EXIT_SUCCESS) - { - destroy_gmp_normal_form(new_nf); - mpz_clear(pivot); - mpz_clear(remainder); - return NULL; - } - if(gmp_matrix_transp(new_nf->right) != EXIT_SUCCESS) - { - destroy_gmp_normal_form(new_nf); - mpz_clear(pivot); - mpz_clear(remainder); - return NULL; - } - elbow = new_nf ->left; - new_nf ->left = new_nf ->right; - new_nf ->right = elbow; - elbow_flag = new_nf ->left_inverted; - new_nf ->left_inverted = new_nf ->right_inverted; - new_nf ->right_inverted = elbow_flag; - - -#ifdef DEBUG - printf("LHNF\n"); - gmp_matrix_printf (new_nf -> left); - gmp_matrix_printf (new_nf -> canonical); - gmp_matrix_printf (new_nf -> right); -#endif - - - /*****************************************************/ - /* Check if more of the leading normal form is ready */ - /*****************************************************/ - - /* The matrix is in LHNF, i.e. it is upper triangular. - If the row trailing the top left diagonal element is - zero, the diagonal element may be an invariant factor - on its final position, and the stage may be ready. - - The stage may not still be ready: The leading diagonal element - of D may not divide the rest of the Schur complement. */ - - subd_ind = 0; - row_undivisible = 0; - - /* Explanation of loop conditions: - 1.) No relative primes found from Schur complement - 2.) Stay within the Schur complement - 3.) If a nonzero is found from the trailing row, the stage is - definitely not ready */ - while (row_undivisible == 0 && - last_ready_row + 1 < first_ready_col && - subd_ind == 0) - { - subd_ind = - gmp_matrix_row_inz(last_ready_row+1, - last_ready_row+2, cols, - canonical); - - /* printf("subd_ind %i\n", subd_ind); - printf("last_ready_row %i\n", last_ready_row); */ - - /* No nonzeros found, the stage may be ready */ - if (subd_ind == 0) - { - mpz_set (pivot, - canonical->storage[(last_ready_row)+ - (last_ready_row)*rows]); - - /* Check whether the pivot divides all elements in the Schur - complement */ - row_undivisible = 0; - for(j = last_ready_row+2; j < first_ready_col; j++) - { - for(i = last_ready_row+2; i <= j; i++) - { - mpz_tdiv_r (remainder, - canonical->storage[(i-1)+ - (j-1)*rows], - pivot); - - if(mpz_cmp_si(remainder, 0) !=0) - { - row_undivisible = i; - /* col_undivisible = j; */ - } - } - } - - /* printf("Row undivisible %i\n", row_undivisible); */ - - /* If a relative prime was found from the Schur complement, - add that row to the first row of the Schur complement */ - if(row_undivisible != 0) - { - mpz_set_si (remainder, 1); - gmp_matrix_add_row(remainder, - row_undivisible, last_ready_row+1, - canonical); - - /* [ 1 0] [1 0] = [1 0] - [-1 1] [1 1] [0 1] */ - - if(left_inverted == INVERTED) - { - gmp_matrix_add_row(remainder, - row_undivisible, last_ready_row+1, - new_nf->left); - } - else - { - mpz_neg (remainder, remainder); - gmp_matrix_add_col(remainder, - last_ready_row+1, row_undivisible, - new_nf->left); - } - } - /* The Schur complement is smaller by one again */ - else - { - last_ready_row++; - } - } - } - } /* The main loop ends here */ - - mpz_clear(pivot); - mpz_clear(remainder); - return new_nf; -} - -int destroy_gmp_normal_form(gmp_normal_form * nf) -{ - int status; - - if(nf == NULL) - { - return EXIT_FAILURE; - } - - status = EXIT_SUCCESS; - if(destroy_gmp_matrix(nf -> left) == EXIT_FAILURE) - { - status = EXIT_FAILURE; - } - - if(destroy_gmp_matrix(nf -> canonical) == EXIT_FAILURE) - { - status = EXIT_FAILURE; - } - - if(destroy_gmp_matrix(nf -> right) == EXIT_FAILURE) - { - status = EXIT_FAILURE; - } - free(nf); - - return status; -} - -