gsl_histogram__pdf2d.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /* histogram/pdf2d.c
  2. *
  3. * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 3 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. */
  19. #include "gsl__config.h"
  20. #include <stdlib.h>
  21. #include "gsl_errno.h"
  22. #include "gsl_histogram.h"
  23. #include "gsl_histogram2d.h"
  24. #include "gsl_histogram__find.c"
  25. int
  26. gsl_histogram2d_pdf_sample (const gsl_histogram2d_pdf * p,
  27. double r1, double r2,
  28. double *x, double *y)
  29. {
  30. size_t k;
  31. int status;
  32. /* Wrap the exclusive top of the bin down to the inclusive bottom of
  33. the bin. Since this is a single point it should not affect the
  34. distribution. */
  35. if (r2 == 1.0)
  36. {
  37. r2 = 0.0;
  38. }
  39. if (r1 == 1.0)
  40. {
  41. r1 = 0.0;
  42. }
  43. status = find (p->nx * p->ny, p->sum, r1, &k);
  44. if (status)
  45. {
  46. GSL_ERROR ("cannot find r1 in cumulative pdf", GSL_EDOM);
  47. }
  48. else
  49. {
  50. size_t i = k / p->ny;
  51. size_t j = k - (i * p->ny);
  52. double delta = (r1 - p->sum[k]) / (p->sum[k + 1] - p->sum[k]);
  53. *x = p->xrange[i] + delta * (p->xrange[i + 1] - p->xrange[i]);
  54. *y = p->yrange[j] + r2 * (p->yrange[j + 1] - p->yrange[j]);
  55. return GSL_SUCCESS;
  56. }
  57. }
  58. gsl_histogram2d_pdf *
  59. gsl_histogram2d_pdf_alloc (const size_t nx, const size_t ny)
  60. {
  61. const size_t n = nx * ny;
  62. gsl_histogram2d_pdf *p;
  63. if (n == 0)
  64. {
  65. GSL_ERROR_VAL ("histogram2d pdf length n must be positive integer",
  66. GSL_EDOM, 0);
  67. }
  68. p = (gsl_histogram2d_pdf *) malloc (sizeof (gsl_histogram2d_pdf));
  69. if (p == 0)
  70. {
  71. GSL_ERROR_VAL ("failed to allocate space for histogram2d pdf struct",
  72. GSL_ENOMEM, 0);
  73. }
  74. p->xrange = (double *) malloc ((nx + 1) * sizeof (double));
  75. if (p->xrange == 0)
  76. {
  77. free (p); /* exception in constructor, avoid memory leak */
  78. GSL_ERROR_VAL ("failed to allocate space for histogram2d pdf xranges",
  79. GSL_ENOMEM, 0);
  80. }
  81. p->yrange = (double *) malloc ((ny + 1) * sizeof (double));
  82. if (p->yrange == 0)
  83. {
  84. free (p->xrange);
  85. free (p); /* exception in constructor, avoid memory leak */
  86. GSL_ERROR_VAL ("failed to allocate space for histogram2d pdf yranges",
  87. GSL_ENOMEM, 0);
  88. }
  89. p->sum = (double *) malloc ((n + 1) * sizeof (double));
  90. if (p->sum == 0)
  91. {
  92. free (p->yrange);
  93. free (p->xrange);
  94. free (p); /* exception in constructor, avoid memory leak */
  95. GSL_ERROR_VAL ("failed to allocate space for histogram2d pdf sums",
  96. GSL_ENOMEM, 0);
  97. }
  98. p->nx = nx;
  99. p->ny = ny;
  100. return p;
  101. }
  102. int
  103. gsl_histogram2d_pdf_init (gsl_histogram2d_pdf * p, const gsl_histogram2d * h)
  104. {
  105. size_t i;
  106. const size_t nx = p->nx;
  107. const size_t ny = p->ny;
  108. const size_t n = nx * ny;
  109. if (nx != h->nx || ny != h->ny)
  110. {
  111. GSL_ERROR ("histogram2d size must match pdf size", GSL_EDOM);
  112. }
  113. for (i = 0; i < n; i++)
  114. {
  115. if (h->bin[i] < 0)
  116. {
  117. GSL_ERROR ("histogram bins must be non-negative to compute"
  118. "a probability distribution", GSL_EDOM);
  119. }
  120. }
  121. for (i = 0; i < nx + 1; i++)
  122. {
  123. p->xrange[i] = h->xrange[i];
  124. }
  125. for (i = 0; i < ny + 1; i++)
  126. {
  127. p->yrange[i] = h->yrange[i];
  128. }
  129. {
  130. double mean = 0, sum = 0;
  131. for (i = 0; i < n; i++)
  132. {
  133. mean += (h->bin[i] - mean) / ((double) (i + 1));
  134. }
  135. p->sum[0] = 0;
  136. for (i = 0; i < n; i++)
  137. {
  138. sum += (h->bin[i] / mean) / n;
  139. p->sum[i + 1] = sum;
  140. }
  141. }
  142. return GSL_SUCCESS;
  143. }
  144. void
  145. gsl_histogram2d_pdf_free (gsl_histogram2d_pdf * p)
  146. {
  147. free (p->xrange);
  148. free (p->yrange);
  149. free (p->sum);
  150. free (p);
  151. }