pointset.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. #include "pointset.h"
  2. #include <cassert>
  3. // for subprocesses
  4. #include <cstdlib>
  5. #include <unistd.h>
  6. #include <sys/wait.h>
  7. #include <fcntl.h>
  8. // extern "C" {
  9. // #include "discr_calc/dem_discr.h"
  10. // }
  11. pointset::pointset(int dim, int npoints) : dim(dim), npoints(npoints) {
  12. assert(dim > 0);
  13. assert(npoints > 0);
  14. data = new double*[npoints];
  15. for(int y = 0; y < npoints; y++)
  16. data[y] = new double[dim];
  17. }
  18. pointset::~pointset() {
  19. for(int y = 0; y < npoints; y++)
  20. delete[] data[y];
  21. delete[] data;
  22. }
  23. double* pointset::point(int i) {
  24. assert(0 <= i && i < npoints);
  25. return data[i];
  26. }
  27. double pointset::discrepancy() {
  28. // computing by direct call
  29. // (it does not seem to work several times... -> have a look on global variables)
  30. // double lower;
  31. // return oydiscr(data, dim, npoints, &lower);
  32. // computing by launching discr_calc/dem_discr as a child process
  33. double result;
  34. int status = -1, pid;
  35. int pipefd_in[2], pipefd_out[2], null; // in/out : from parent's point of view
  36. if(pipe(pipefd_in) || pipe(pipefd_out)) {
  37. perror("pipe()");
  38. exit(1);
  39. }
  40. switch(pid = fork()) {
  41. case -1: // error
  42. perror("fork()");
  43. exit(1);
  44. case 0: // child
  45. close(pipefd_in[0]);
  46. close(pipefd_out[1]);
  47. // replace stdin
  48. dup2(pipefd_out[0], 0);
  49. // replace stdout
  50. dup2(pipefd_in[1], 1);
  51. // replace stderr :P
  52. null = open("/dev/null", O_RDONLY);
  53. dup2(null, 2);
  54. close(null);
  55. // launch process !
  56. char dim_str[20], npoints_str[20];
  57. sprintf(dim_str, "%d", dim);
  58. sprintf(npoints_str, "%d", npoints);
  59. execl("discr_calc/dem_discr", "dem_discr", dim_str, npoints_str, (char*)NULL);
  60. // if we get to this line, the command has failed
  61. perror("execl()");
  62. exit(1);
  63. default: // father
  64. close(pipefd_in[1]);
  65. close(pipefd_out[0]);
  66. // write data into pipefd_in
  67. FILE *f = fdopen(pipefd_out[1], "w");
  68. if(f == NULL) {
  69. perror("fdopen()");
  70. exit(1);
  71. }
  72. dump(f);
  73. fclose(f);
  74. close(pipefd_out[1]);
  75. // read result
  76. f = fdopen(pipefd_in[0], "r");
  77. if(f == NULL) {
  78. perror("fdopen()");
  79. exit(1);
  80. }
  81. if(fscanf(f, "%lf", &result) != 1) {
  82. perror("fscanf()");
  83. exit(1);
  84. }
  85. fclose(f);
  86. close(pipefd_in[0]);
  87. // wait for child to terminate
  88. waitpid(pid, &status, 0);
  89. if(status != 0) {
  90. fprintf(stderr, "child process terminate with status %d\n", status);
  91. exit(1);
  92. }
  93. }
  94. return result;
  95. }
  96. void pointset::dump(FILE* f) {
  97. for(int y = 0; y < npoints; y++)
  98. for(int x = 0; x < dim; x++)
  99. fprintf(f, "%lf%c", data[y][x], (x==dim-1) ? '\n' : '\t');
  100. }