Ramón Casero Cañas on Thu, 23 Jan 2003 18:18:48 +0100 (MET)


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

PARI hangs with initialize / freeall / initialize


For my program the inversion takes very little, and it needs memory, so at
the beginning of the function there's a pari stack initialization, and before
returning, the stack is freed. But two consecutive calls to the function hang
the Linux terminal where the program runs. A CTRL-C says

  ***   user interrupt.

but it doesn't release the terminal, and the CPU load remain 100%.  A kill
command must be executed from another terminal in order to stop the program. 

The test program is compiled and linked with g++ 2.95.4:


---------------------------------------------------------------------

/* File m_modulo2.cpp */

#include <iostream>                      // for std::cout
#include <exception>
#include <typeinfo>
// #include <fstream>                       // for ifstream
typedef enum{FALSE, TRUE} mybool;
#define exor(a, b) ((mybool)(a != b))
extern "C" {
// #include "include/gamatrix.h"
/* mybool inverse_mat_mod2(mybool **_a, unsigned _size); */
mybool inverse_mat_mod2(mybool **_a, unsigned _size, mybool _CHECK);
/* print_c_boolmatrix: print a C boolean matrix */
void print_c_boolmatrix(mybool **_a, unsigned _m, unsigned _n);
}
/* main */
/*
   argv[] (IN): file names array
   ---
   return n:   n files were succesfully read, n > 0
   return 0:   none of the files could be read
   return -1:  unexpected error
   ---
   read steiner problem from files
*/
int main(int argc, char *argv[]) {

  try {

    unsigned m, n;

    std::cout << "Hola mundo" << std::endl;
//     boost::array<BoolMatrix::index, 2> shape = {{ 5, 8 }};
//     BoolMatrix *A;
//     boost::array<BoolMatrix::index, 2> dims = {{20, 15}};
//     A.reshape(dims);
//     print_multi_array(A);

    const unsigned a_size = 32;
    const bool a_const[a_size][a_size] =
      {
        {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0,
         1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1},
        {1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
         1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0},
        {0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1,
         1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0},
        {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0,
         0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0},
        {0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
         1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
         1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0},
        {0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0,
         1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0,
         0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1},
        {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
         0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1},
        {0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0},
        {0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1},
        {1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
         0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0},
        {0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0,
         0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0,
         0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
         1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0},
        {0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
         1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1},
        {0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1,
         1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
        {0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1,
         0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0},
        {0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0,
         1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0},
        {0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1,
         0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1},
        {0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
         0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0},
        {0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1,
         0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0},
        {1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
         0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0},
        {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0,
         1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0},
        {1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1,
         0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1},
        {0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0,
         0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0,
         0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0},
        {0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
         0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0},
        {0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
         0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1},
        {0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1,
         0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0},
        {1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1,
         0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}
      };

    mybool **a;
    a = new (mybool *)[a_size];
    for (m = 0; m < a_size; ++m) {
      a[m] = new mybool[a_size];
      for (n = 0; n < a_size; ++n) {
        a[m][n] = (mybool)a_const[m][n];
      }
    }
//     print_c_boolmatrix(a, a_size, a_size);

    if (inverse_mat_mod2(a, a_size, TRUE)) {
      std::cout << "right inversion" << std::endl;
//       print_c_boolmatrix(a, a_size, a_size);
    }
    else {
      std::cout << "wrong inversion" << std::endl;
      return 0;
    }

    if (inverse_mat_mod2(a, a_size, TRUE)) {
      std::cout << "right inversion" << std::endl;
//       print_c_boolmatrix(a, a_size, a_size);
    }
    else {
      std::cout << "wrong inversion" << std::endl;
      return 0;
    }


    return 1;
  }
  catch (char *s) {
    std::cout << "exception! " << s << std::endl;
    return 0;
  }
  catch (std::exception& e) {
    std::cout << "exception! " << e.what() << std::endl;
  }
  catch (...) {
    std::cout << "unexpected exception!" << std::endl;
    return -1;
  }

}

---------------------------------------------------------------------------


The functions file is compiled with gcc 2.95.4


---------------------------------------------------------------------

/* File gamatrix.cpp */
/* Thanks to Karim Belabas and Bill Allombert for his help with this
   code */

// #include <iostream>                      // for std::cout
#include "include/gamatrix.h"
#include <pari/pari.h>
// #include "/usr/src/pari-2.2.4.alpha/src/basemath/base3.c"
// GEN u_FpM_inv(GEN a, ulong p);

void freeall(void); // thanks, Karim
void pari_sig_init(void (*f)(int));  // thanks, Karim
// extern "C" {
//   void pari_sig_init(void (*f)(int));
// }

/* inverse_mat_mod2: overwrites a matrix modulo 2 with its inverse;
 * input is a mybool matrix, but internally, PARI library types are
 * used */
/* return true if it has inverse and false if not or cannot be
   computed */
/* mybool inverse_mat_mod2(mybool **_a, unsigned _size) { */
/*   return inverse_mat_mod2(_a, _size, true); */
/* } */

mybool inverse_mat_mod2(mybool **_a, unsigned _size, mybool _CHECK) {
  GEN a;           // temp matrix by columns
  unsigned i, j;   // counter
  unsigned sizepari = _size + 1;
  GEN z;           // auxiliary element of the matrix
  GEN v;           // auxiliary element of the matrix
  long paristacksize = 500000;
  long total_size = sizepari * sizepari + _size * _size * 9; // thanks,
Karim
  GEN determinant;
  GEN ainv;

  printf("inverse_mat_mod2: getting into pari function\n");
//   std::cout << "getting into pari function" << std::cout;

  paristacksize = sizeof(long) * total_size * 10; // thanks again
  pari_init(paristacksize, 2); // init PARI stack

  printf("inverse_mat_mod2: stack initialized\n");
//   std::cout << "inverse_mat_mod2: stack initialized" << std::cout;

  /* allocate memory for the temp matrix
   * note: remember that PARI matrices of mxn need (m+1)x(n+1), and
   * that elements go a[1], a[2], ..., while a[0] is for type
   * information */
  printf("inverse_mat_mod2: size = %d\n", _size);
//   std::cout << "inverse_mat_mod2: size = " << _size << std::endl;
  a = cgetg(sizepari, t_MAT); // `a' has _size columns
  for (i = 1; i <= _size; ++i) { // allocate `a' columns of _size elements
    a[i] = lgetg(sizepari, t_COL);
  }
  for (i = 1; i <= _size; ++i) { // allocate space for elements
    v = (GEN)a[i];
    for (j = 1; j <= _size; ++j) {
      v[j] = lgetg(3, t_INTMOD);
      z = (GEN)v[j];
      z[1] = lstoi(2); // modulo 2
      if (_a[j-1][i-1]) z[2] = un; else z[2] = zero;//lstoi(0);
    }
  }
  printf("inverse_mat_mod2: assigment done\n");
//   std::cout << "inverse_mat_mod2: assigment done" << std::endl;

  /* compute determinant to check invertibility */
  determinant = det(a);
  printf("Hi\n");
  if (determinant == gzero) {
    printf("determinant is zero\n");
  printf("By\n");
    freeall();
  printf("By\n");
    pari_sig_init(SIG_DFL);
  printf("By\n");
    return FALSE;
  }

  /* invert matrix */
  ainv = ginv(a);
  printf("inverse_mat_mod2: matrix inverted\n");
//   std::cout << "inverse_mat_mod2: matrix inverted" << std::endl;

  /* check whether the inverse is valid */
  if (_CHECK) {
    GEN a_ainv;
    a_ainv = gmul(a, ainv);
    for (i = 1; i <= _size; ++i) {
      v = (GEN)a_ainv[i];
      for (j = 1; j <= _size; ++j) {
        z = (GEN)v[j];
        if ((i == j) != itos((GEN)z[2])) {
          freeall();
          pari_sig_init(SIG_DFL);
          return FALSE;
        }
      }
    }
  }

  /* for no _CHECK or valid inversion, overwrite input array with
     inverse matrix */
  for (i = 1; i <= _size; ++i) {
    v = (GEN)ainv[i];
    for (j = 1; j <= _size; ++j) {
      z = (GEN)v[j];
      _a[j-1][i-1] = (mybool)itos((GEN)z[2]);
    }
  }

  /* free PARI's memory (thanks Karim) */
  freeall();
  pari_sig_init(SIG_DFL);

  return TRUE;
}

/* print_c_myboolmatrix: print a C myboolean matrix */
void print_c_boolmatrix(mybool **_a, unsigned _m, unsigned _n) {

  unsigned m, n;

  printf("{\n");
  for (m = 0; m < _m; ++m) {
    printf("{");
    for (n = 0; n < _n; ++n) {
      printf("%d ", _a[m][n]);
      if (n == _n - 1) {
        printf("}\n");
      }
      else {
        printf(" ");
      }
    }
  }
  printf("}\n");

  return;
}

/* XOR function */
/* mybool exor(mybool a, mybool b) { return (mybool)(a != b); } */

----------------------------------------------------------------------

And the included headers file just have

-------------------------------------------------------------------

#ifndef MODULO2_H
#define MODULO2_H

typedef enum{FALSE, TRUE} mybool;

/* inverse_mat_mod2: overwrites a matrix modulo 2 with its inverse;
 * input is a bool matrix, but internally, PARI library types are
 * used */
/* mybool inverse_mat_mod2(mybool **_a, unsigned _size); */
mybool inverse_mat_mod2(mybool **_a, unsigned _size, mybool _CHECK);
/* print_c_boolmatrix: print a C boolean matrix */
void print_c_boolmatrix(mybool **_a, unsigned _m, unsigned _n);
/* logic XOR function */
/* mybool exor(mybool a, mybool b); */
#define exor(a, b) ((mybool)(a != b))

#endif

--------------------------------------------------------------------

regards,

Ramón.

-- 
+++ GMX - Mail, Messaging & more  http://www.gmx.net +++
NEU: Mit GMX ins Internet. Rund um die Uhr für 1 ct/ Min. surfen!