rgsl/types/histograms.rs
1//
2// A rust binding for the GSL library by Guillaume Gomez (guillaume1.gomez@gmail.com)
3//
4
5/*!
6# Histograms
7
8This chapter describes functions for creating histograms. Histograms provide a convenient way of summarizing the distribution of a set of data.
9A histogram consists of a set of bins which count the number of events falling into a given range of a continuous variable x. In GSL the bins
10of a histogram contain floating-point numbers, so they can be used to record both integer and non-integer distributions. The bins can use arbitrary
11sets of ranges (uniformly spaced bins are the default). Both one and two-dimensional histograms are supported.
12
13Once a histogram has been created it can also be converted into a probability distribution function. The library provides efficient routines
14for selecting random samples from probability distributions. This can be useful for generating simulations based on real data.
15
16## Resampling from histograms
17
18A histogram made by counting events can be regarded as a measurement of a probability distribution. Allowing for statistical error, the height
19of each bin represents the probability of an event where the value of x falls in the range of that bin. The probability distribution function
20has the one-dimensional form p(x)dx where,
21
22p(x) = n_i/ (N w_i)
23In this equation n_i is the number of events in the bin which contains x, w_i is the width of the bin and N is the total number of events.
24The distribution of events within each bin is assumed to be uniform.
25!*/
26
27use crate::Value;
28use ffi::FFI;
29use std::io::{self, Write};
30
31ffi_wrapper!(Histogram, *mut sys::gsl_histogram, gsl_histogram_free);
32
33impl Histogram {
34 /// This function allocates memory for a histogram with n bins, and returns a pointer to a newly created gsl_histogram struct. If insufficient
35 /// memory is available a null pointer is returned and the error handler is invoked with an error code of Value::NoMem. The bins and ranges are
36 /// not initialized, and should be prepared using one of the range-setting functions below in order to make the histogram ready for use.
37 #[doc(alias = "gsl_histogram_alloc")]
38 pub fn new(n: usize) -> Option<Histogram> {
39 let tmp = unsafe { sys::gsl_histogram_alloc(n) };
40
41 if tmp.is_null() {
42 None
43 } else {
44 Some(Self::wrap(tmp))
45 }
46 }
47
48 /// This function sets the ranges of the existing histogram h using the array range of size size. The values of the histogram bins are reset
49 /// to zero. The range array should contain the desired bin limits. The ranges can be arbitrary, subject to the restriction that they are
50 /// monotonically increasing.
51 ///
52 /// The following example shows how to create a histogram with logarithmic bins with ranges [1,10), [10,100) and [100,1000).
53 ///
54 /// ```C
55 /// gsl_histogram * h = gsl_histogram_alloc (3);
56 ///
57 /// /* bin[0] covers the range 1 <= x < 10 */
58 /// /* bin[1] covers the range 10 <= x < 100 */
59 /// /* bin[2] covers the range 100 <= x < 1000 */
60 ///
61 /// double range[4] = { 1.0, 10.0, 100.0, 1000.0 };
62 ///
63 /// gsl_histogram_set_ranges (h, range, 4);
64 /// ```
65 ///
66 /// Note that the size of the range array should be defined to be one element bigger than the number of bins. The additional element is
67 /// required for the upper value of the final bin.
68 #[doc(alias = "gsl_histogram_set_ranges")]
69 pub fn set_ranges(&mut self, range: &[f64]) -> Result<(), Value> {
70 let ret = unsafe {
71 sys::gsl_histogram_set_ranges(self.unwrap_unique(), range.as_ptr(), range.len() as _)
72 };
73 result_handler!(ret, ())
74 }
75
76 /// This function sets the ranges of the existing histogram h to cover the range xmin to xmax uniformly. The values of the histogram bins
77 /// are reset to zero. The bin ranges are shown in the table below,
78 ///
79 /// `bin[0]` corresponds to xmin <= x < xmin + d
80 /// `bin[1]` corresponds to xmin + d <= x < xmin + 2 d
81 /// ......
82 /// bin[n-1] corresponds to xmin + (n-1)d <= x < xmax
83 /// where d is the bin spacing, d = (xmax-xmin)/n.
84 #[doc(alias = "gsl_histogram_set_ranges_uniform")]
85 pub fn set_ranges_uniform(&mut self, xmin: f64, xmax: f64) -> Result<(), Value> {
86 let ret =
87 unsafe { sys::gsl_histogram_set_ranges_uniform(self.unwrap_unique(), xmin, xmax) };
88 result_handler!(ret, ())
89 }
90
91 /// This function copies the self histogram into the pre-existing histogram dest, making dest into an exact copy of self. The two histograms
92 /// must be of the same size.
93 #[doc(alias = "gsl_histogram_memcpy")]
94 pub fn copy(&self, dest: &mut Histogram) -> Result<(), Value> {
95 let ret = unsafe { sys::gsl_histogram_memcpy(dest.unwrap_unique(), self.unwrap_shared()) };
96 result_handler!(ret, ())
97 }
98
99 /// This function returns a pointer to a newly created histogram which is an exact copy of the self histogram.
100 #[doc(alias = "gsl_histogram_clone")]
101 pub fn clone(&self) -> Option<Histogram> {
102 let tmp = unsafe { sys::gsl_histogram_clone(self.unwrap_shared()) };
103
104 if tmp.is_null() {
105 None
106 } else {
107 Some(Self::wrap(tmp))
108 }
109 }
110
111 /// This function updates the self histogram by adding one (1.0) to the bin whose range contains the coordinate x.
112 ///
113 /// If x lies in the valid range of the histogram then the function returns zero to indicate success. If x is less than the lower limit of
114 /// the histogram then the function returns Value::Dom, and none of bins are modified. Similarly, if the value of x is greater than or equal
115 /// to the upper limit of the histogram then the function returns Value::Dom, and none of the bins are modified. The error handler is not
116 /// called, however, since it is often necessary to compute histograms for a small range of a larger dataset, ignoring the values outside
117 /// the range of interest.
118 #[doc(alias = "gsl_histogram_increment")]
119 pub fn increment(&mut self, x: f64) -> Result<(), Value> {
120 let ret = unsafe { sys::gsl_histogram_increment(self.unwrap_unique(), x) };
121 result_handler!(ret, ())
122 }
123
124 /// This function is similar to gsl_histogram_increment but increases the value of the appropriate bin in the histogram h by the floating-point
125 /// number weight.
126 #[doc(alias = "gsl_histogram_accumulate")]
127 pub fn accumulate(&mut self, x: f64, weight: f64) -> Result<(), Value> {
128 let ret = unsafe { sys::gsl_histogram_accumulate(self.unwrap_unique(), x, weight) };
129 result_handler!(ret, ())
130 }
131
132 /// This function returns the contents of the i-th bin of the histogram h. If i lies outside the valid range of indices for the histogram then
133 /// the error handler is called with an error code of Value::Dom and the function returns 0.
134 #[doc(alias = "gsl_histogram_get")]
135 pub fn get(&self, i: usize) -> f64 {
136 unsafe { sys::gsl_histogram_get(self.unwrap_shared(), i) }
137 }
138
139 /// This function finds the upper and lower range limits of the i-th bin of the self histogram.
140 /// If the index i is valid then the corresponding range limits are stored in lower and upper.
141 /// The lower limit is inclusive (i.e. events with this coordinate are included in the bin) and
142 /// the upper limit is exclusive (i.e. events with the coordinate of the upper limit are
143 /// excluded and fall in the neighboring higher bin, if it exists). The function returns 0 to
144 /// indicate success. If i lies outside the valid range of indices for the histogram then
145 /// the error handler is called and the function returns an error code of Value::Dom.
146 ///
147 /// Returns `(lower, upper)`.
148 #[doc(alias = "gsl_histogram_get_range")]
149 pub fn range(&self, i: usize) -> Result<(f64, f64), Value> {
150 let mut lower = 0.;
151 let mut upper = 0.;
152 let ret = unsafe {
153 sys::gsl_histogram_get_range(self.unwrap_shared(), i, &mut lower, &mut upper)
154 };
155 result_handler!(ret, (lower, upper))
156 }
157
158 /// This function returns the maximum upper and minimum lower range limits and the number of bins of the self histogram. They provide a way
159 /// of determining these values without accessing the gsl_histogram struct directly.
160 #[doc(alias = "gsl_histogram_max")]
161 pub fn max(&self) -> f64 {
162 unsafe { sys::gsl_histogram_max(self.unwrap_shared()) }
163 }
164
165 /// This function returns the maximum upper and minimum lower range limits and the number of bins of the self histogram. They provide a way
166 /// of determining these values without accessing the gsl_histogram struct directly.
167 #[doc(alias = "gsl_histogram_min")]
168 pub fn min(&self) -> f64 {
169 unsafe { sys::gsl_histogram_min(self.unwrap_shared()) }
170 }
171
172 /// This function returns the maximum upper and minimum lower range limits and the number of bins of the self histogram. They provide a way
173 /// of determining these values without accessing the gsl_histogram struct directly.
174 #[doc(alias = "gsl_histogram_bins")]
175 pub fn bins(&self) -> usize {
176 unsafe { sys::gsl_histogram_bins(self.unwrap_shared()) }
177 }
178
179 /// This function resets all the bins in the self histogram to zero.
180 #[doc(alias = "gsl_histogram_reset")]
181 pub fn reset(&mut self) {
182 unsafe { sys::gsl_histogram_reset(self.unwrap_unique()) }
183 }
184
185 /// This function finds and sets the index i to the bin number which covers the coordinate x in
186 /// the self histogram. The bin is located using a binary search. The search includes an
187 /// optimization for histograms with uniform range, and will return the correct bin immediately
188 /// in this case. If x is found in the range of the histogram then the function sets the index i
189 /// and returns crate::Value::Success. If x lies outside the valid range of the histogram then the
190 /// function returns Value::Dom and the error handler is invoked.
191 ///
192 /// Returns `i`.
193 #[doc(alias = "gsl_histogram_find")]
194 pub fn find(&self, x: f64) -> Result<usize, Value> {
195 let mut i = 0;
196 let ret = unsafe { sys::gsl_histogram_find(self.unwrap_shared(), x, &mut i) };
197 result_handler!(ret, i)
198 }
199
200 /// This function returns the maximum value contained in the histogram bins.
201 #[doc(alias = "gsl_histogram_max_val")]
202 pub fn max_val(&self) -> f64 {
203 unsafe { sys::gsl_histogram_max_val(self.unwrap_shared()) }
204 }
205
206 /// This function returns the index of the bin containing the maximum value. In the case where several bins contain the same maximum value
207 /// the smallest index is returned.
208 #[doc(alias = "gsl_histogram_max_bin")]
209 pub fn max_bin(&self) -> usize {
210 unsafe { sys::gsl_histogram_max_bin(self.unwrap_shared()) }
211 }
212
213 /// This function returns the minimum value contained in the histogram bins.
214 #[doc(alias = "gsl_histogram_min_val")]
215 pub fn min_val(&self) -> f64 {
216 unsafe { sys::gsl_histogram_min_val(self.unwrap_shared()) }
217 }
218
219 /// This function returns the index of the bin containing the minimum value. In the case where several bins contain the same maximum value
220 /// the smallest index is returned.
221 #[doc(alias = "gsl_histogram_min_bin")]
222 pub fn min_bin(&self) -> usize {
223 unsafe { sys::gsl_histogram_min_bin(self.unwrap_shared()) }
224 }
225
226 /// This function returns the mean of the histogrammed variable, where the histogram is regarded as a probability distribution. Negative
227 /// bin values are ignored for the purposes of this calculation. The accuracy of the result is limited by the bin width.
228 #[doc(alias = "gsl_histogram_mean")]
229 pub fn mean(&self) -> f64 {
230 unsafe { sys::gsl_histogram_mean(self.unwrap_shared()) }
231 }
232
233 /// This function returns the standard deviation of the histogrammed variable, where the histogram is regarded as a probability distribution.
234 /// Negative bin values are ignored for the purposes of this calculation. The accuracy of the result is limited by the bin width.
235 #[doc(alias = "gsl_histogram_sigma")]
236 pub fn sigma(&self) -> f64 {
237 unsafe { sys::gsl_histogram_sigma(self.unwrap_shared()) }
238 }
239
240 /// This function returns the sum of all bin values. Negative bin values are included in the sum.
241 #[doc(alias = "gsl_histogram_sum")]
242 pub fn sum(&self) -> f64 {
243 unsafe { sys::gsl_histogram_sum(self.unwrap_shared()) }
244 }
245
246 /// This function returns true if the all of the individual bin ranges of the two histograms are identical, and false otherwise.
247 #[doc(alias = "gsl_histogram_equal_bins_p")]
248 pub fn equal_bins_p(&self, other: &Histogram) -> bool {
249 unsafe { sys::gsl_histogram_equal_bins_p(self.unwrap_shared(), other.unwrap_shared()) != 0 }
250 }
251
252 /// This function adds the contents of the bins in histogram other to the corresponding bins of self histogram, i.e. h'_1(i) = h_1(i) + h_2(i).
253 /// The two histograms must have identical bin ranges.
254 #[doc(alias = "gsl_histogram_add")]
255 pub fn add(&mut self, other: &Histogram) -> Result<(), Value> {
256 let ret = unsafe { sys::gsl_histogram_add(self.unwrap_unique(), other.unwrap_shared()) };
257 result_handler!(ret, ())
258 }
259
260 /// This function subtracts the contents of the bins in histogram other from the corresponding bins of self histogram, i.e. h'_1(i) = h_1(i) - h_2(i).
261 /// The two histograms must have identical bin ranges.
262 #[doc(alias = "gsl_histogram_sub")]
263 pub fn sub(&mut self, other: &Histogram) -> Result<(), Value> {
264 let ret = unsafe { sys::gsl_histogram_sub(self.unwrap_unique(), other.unwrap_shared()) };
265 result_handler!(ret, ())
266 }
267
268 /// This function multiplies the contents of the bins of self histogram by the contents of the corresponding bins in other histogram, i.e. h'_1(i) =
269 /// h_1(i) * h_2(i). The two histograms must have identical bin ranges.
270 #[doc(alias = "gsl_histogram_mul")]
271 pub fn mul(&mut self, other: &Histogram) -> Result<(), Value> {
272 let ret = unsafe { sys::gsl_histogram_mul(self.unwrap_unique(), other.unwrap_shared()) };
273 result_handler!(ret, ())
274 }
275
276 /// This function divides the contents of the bins of self histogram by the contents of the corresponding bins in other histogram, i.e. h'_1(i) = h_1(i)
277 /// / h_2(i). The two histograms must have identical bin ranges.
278 #[doc(alias = "gsl_histogram_div")]
279 pub fn div(&mut self, other: &Histogram) -> Result<(), Value> {
280 let ret = unsafe { sys::gsl_histogram_div(self.unwrap_unique(), other.unwrap_shared()) };
281 result_handler!(ret, ())
282 }
283
284 /// This function multiplies the contents of the bins of self histogram by the constant scale, i.e. h'_1(i) = h_1(i) * scale.
285 #[doc(alias = "gsl_histogram_scale")]
286 pub fn scale(&mut self, scale: f64) -> Result<(), Value> {
287 let ret = unsafe { sys::gsl_histogram_scale(self.unwrap_unique(), scale) };
288 result_handler!(ret, ())
289 }
290
291 /// This function shifts the contents of the bins of self histogram by the constant offset, i.e. h'_1(i) = h_1(i) + offset.
292 #[doc(alias = "gsl_histogram_shift")]
293 pub fn shift(&mut self, offset: f64) -> Result<(), Value> {
294 let ret = unsafe { sys::gsl_histogram_shift(self.unwrap_unique(), offset) };
295 result_handler!(ret, ())
296 }
297
298 #[allow(unused_must_use)]
299 pub fn print<W: Write>(
300 &self,
301 stream: &mut W, /*, range_format: &str, bin_format: &str*/
302 ) -> io::Result<()> {
303 unsafe {
304 let n = (*self.unwrap_shared()).n as isize;
305
306 for i in 0isize..n {
307 writeln!(
308 stream,
309 "{} {} {}",
310 *(*self.unwrap_shared()).range.offset(i),
311 *(*self.unwrap_shared()).range.offset(i + 1),
312 *(*self.unwrap_shared()).range.offset(i),
313 )?;
314 }
315
316 Ok(())
317 }
318 }
319}
320
321ffi_wrapper!(HistogramPdf, *mut sys::gsl_histogram_pdf, gsl_histogram_pdf_free,
322"The probability distribution function for a histogram consists of a set of bins which measure the \
323probability of an event falling into a given range of a continuous variable x. A probability \
324distribution function is defined by the following struct, which actually stores the cumulative \
325probability distribution function. This is the natural quantity for generating samples via the \
326inverse transform method, because there is a one-to-one mapping between the cumulative probability \
327distribution and the range [0,1]. It can be shown that by taking a uniform random number in this \
328range and finding its corresponding coordinate in the cumulative probability distribution we obtain \
329samples with the desired probability distribution.");
330
331impl HistogramPdf {
332 /// This function allocates memory for a probability distribution with n bins and returns a pointer to a newly initialized gsl_histogram_pdf
333 /// struct. If insufficient memory is available a null pointer is returned and the error handler is invoked with an error code of Value::NoMem.
334 #[doc(alias = "gsl_histogram_pdf_alloc")]
335 pub fn new(n: usize) -> Option<HistogramPdf> {
336 let tmp = unsafe { sys::gsl_histogram_pdf_alloc(n) };
337
338 if tmp.is_null() {
339 None
340 } else {
341 Some(Self::wrap(tmp))
342 }
343 }
344
345 /// This function initializes the probability distribution self with the contents of the histogram h. If any of the bins of h are negative then
346 /// the error handler is invoked with an error code of Value::Dom because a probability distribution cannot contain negative values.
347 #[doc(alias = "gsl_histogram_pdf_init")]
348 pub fn init(&mut self, h: &Histogram) -> Result<(), Value> {
349 let ret = unsafe { sys::gsl_histogram_pdf_init(self.unwrap_unique(), h.unwrap_shared()) };
350 result_handler!(ret, ())
351 }
352
353 /// This function uses r, a uniform random number between zero and one, to compute a single random sample from the probability distribution
354 /// self. The algorithm used to compute the sample s is given by the following formula,
355 ///
356 /// ```text
357 /// s = range[i] + delta * (range[i+1] - range[i])
358 /// ```
359 ///
360 /// where i is the index which satisfies `sum[i] <= r < sum[i+1]` and `delta` is
361 /// `(r - sum[i])/(sum[i+1] - sum[i])`.
362 #[doc(alias = "gsl_histogram_pdf_sample")]
363 pub fn sample(&self, r: f64) -> f64 {
364 unsafe { sys::gsl_histogram_pdf_sample(self.unwrap_shared(), r) }
365 }
366}
367
368ffi_wrapper!(Histogram2D, *mut sys::gsl_histogram2d, gsl_histogram2d_free,
369"A two dimensional histogram consists of a set of bins which count the number of events falling in \
370a given area of the (x,y) plane. The simplest way to use a two dimensional histogram is to record \
371two-dimensional position information, n(x,y). Another possibility is to form a joint distribution \
372by recording related variables. For example a detector might record both the position of an event \
373(x) and the amount of energy it deposited E. These could be histogrammed as the joint distribution \
374n(x,E).");
375
376impl Histogram2D {
377 /// This function allocates memory for a two-dimensional histogram with nx bins in the x direction and ny bins in the y direction. The
378 /// function returns a pointer to a newly created gsl_histogram2d struct. If insufficient memory is available a null pointer is returned
379 /// and the error handler is invoked with an error code of Value::NoMem. The bins and ranges must be initialized with one of the
380 /// functions below before the histogram is ready for use.
381 #[doc(alias = "gsl_histogram2d_alloc")]
382 pub fn new(nx: usize, ny: usize) -> Option<Histogram2D> {
383 let tmp = unsafe { sys::gsl_histogram2d_alloc(nx, ny) };
384
385 if tmp.is_null() {
386 None
387 } else {
388 Some(Self::wrap(tmp))
389 }
390 }
391
392 /// This function sets the ranges of the existing histogram h using the arrays xrange and yrange of size xsize and ysize respectively.
393 /// The values of the histogram bins are reset to zero.
394 #[doc(alias = "gsl_histogram2d_set_ranges")]
395 pub fn set_ranges(&mut self, xrange: &[f64], yrange: &[f64]) -> Result<(), Value> {
396 let ret = unsafe {
397 sys::gsl_histogram2d_set_ranges(
398 self.unwrap_unique(),
399 xrange.as_ptr(),
400 xrange.len() as _,
401 yrange.as_ptr(),
402 yrange.len() as _,
403 )
404 };
405 result_handler!(ret, ())
406 }
407
408 /// This function sets the ranges of the existing histogram h to cover the ranges xmin to xmax and ymin to ymax uniformly. The values
409 /// of the histogram bins are reset to zero.
410 #[doc(alias = "gsl_histogram2d_set_ranges_uniform")]
411 pub fn set_ranges_uniform(
412 &mut self,
413 xmin: f64,
414 xmax: f64,
415 ymin: f64,
416 ymax: f64,
417 ) -> Result<(), Value> {
418 let ret = unsafe {
419 sys::gsl_histogram2d_set_ranges_uniform(self.unwrap_unique(), xmin, xmax, ymin, ymax)
420 };
421 result_handler!(ret, ())
422 }
423
424 /// This function copies the histogram src into the pre-existing histogram dest, making dest into an exact copy of src. The two histograms
425 /// must be of the same size.
426 #[doc(alias = "gsl_histogram2d_memcpy")]
427 pub fn copy(&self, dest: &mut Histogram2D) -> Result<(), Value> {
428 let ret =
429 unsafe { sys::gsl_histogram2d_memcpy(dest.unwrap_unique(), self.unwrap_shared()) };
430 result_handler!(ret, ())
431 }
432
433 /// his function returns a pointer to a newly created histogram which is an exact copy of the histogram self.
434 #[doc(alias = "gsl_histogram2d_clone")]
435 pub fn clone(&self) -> Option<Histogram2D> {
436 let tmp = unsafe { sys::gsl_histogram2d_clone(self.unwrap_shared()) };
437
438 if tmp.is_null() {
439 None
440 } else {
441 Some(Self::wrap(tmp))
442 }
443 }
444
445 /// This function updates the histogram h by adding one (1.0) to the bin whose x and y ranges contain the coordinates (x,y).
446 ///
447 /// If the point (x,y) lies inside the valid ranges of the histogram then the function returns zero to indicate success. If (x,y) lies
448 /// outside the limits of the histogram then the function returns Value::Dom, and none of the bins are modified. The error handler is not
449 /// called, since it is often necessary to compute histograms for a small range of a larger dataset, ignoring any coordinates outside the
450 /// range of interest.
451 #[doc(alias = "gsl_histogram2d_increment")]
452 pub fn increment(&mut self, x: f64, y: f64) -> Result<(), Value> {
453 let ret = unsafe { sys::gsl_histogram2d_increment(self.unwrap_unique(), x, y) };
454 result_handler!(ret, ())
455 }
456
457 /// This function is similar to gsl_histogram2d_increment but increases the value of the appropriate bin in the histogram h by the floating-point
458 /// number weight.
459 #[doc(alias = "gsl_histogram2d_accumulate")]
460 pub fn accumulate(&mut self, x: f64, y: f64, weight: f64) -> Result<(), Value> {
461 let ret = unsafe { sys::gsl_histogram2d_accumulate(self.unwrap_unique(), x, y, weight) };
462 result_handler!(ret, ())
463 }
464
465 /// This function returns the contents of the (i,j)-th bin of the histogram h. If (i,j) lies outside the valid range of indices for the
466 /// histogram then the error handler is called with an error code of Value::Dom and the function returns 0.
467 #[doc(alias = "gsl_histogram2d_get")]
468 pub fn get(&self, i: usize, j: usize) -> f64 {
469 unsafe { sys::gsl_histogram2d_get(self.unwrap_shared(), i, j) }
470 }
471
472 /// This function finds the upper and lower range limits of the i-th and j-th bins in the x and
473 /// y directions of the histogram h. The range limits are stored in xlower and xupper or ylower
474 /// and yupper. The lower limits are inclusive (i.e. events with these coordinates are included
475 /// in the bin) and the upper limits are exclusive (i.e. events with the value of the upper
476 /// limit are not included and fall in the neighboring higher bin, if it exists). The functions
477 /// return 0 to indicate success. If i or j lies outside the valid range of indices for the
478 /// histogram then the error handler is called with an error code of Value::Dom.
479 ///
480 /// Returns `(xlower, xupper)`.
481 #[doc(alias = "gsl_histogram2d_get_xrange")]
482 pub fn xrange(&self, i: usize) -> Result<(f64, f64), Value> {
483 let mut xlower = 0.;
484 let mut xupper = 0.;
485 let ret = unsafe {
486 sys::gsl_histogram2d_get_xrange(self.unwrap_shared(), i, &mut xlower, &mut xupper)
487 };
488 result_handler!(ret, (xlower, xupper))
489 }
490
491 /// This function finds the upper and lower range limits of the i-th and j-th bins in the x and
492 /// y directions of the histogram h. The range limits are stored in xlower and xupper or ylower
493 /// and yupper. The lower limits are inclusive (i.e. events with these coordinates are included
494 /// in the bin) and the upper limits are exclusive (i.e. events with the value of the upper
495 /// limit are not included and fall in the neighboring higher bin, if it exists). The functions
496 /// return 0 to indicate success. If i or j lies outside the valid range of indices for the
497 /// histogram then the error handler is called with an error code of Value::Dom.
498 ///
499 /// Returns `(ylower, yupper)`.
500 #[doc(alias = "gsl_histogram2d_get_yrange")]
501 pub fn yrange(&self, j: usize) -> Result<(f64, f64), Value> {
502 let mut ylower = 0.;
503 let mut yupper = 0.;
504 let ret = unsafe {
505 sys::gsl_histogram2d_get_yrange(self.unwrap_shared(), j, &mut ylower, &mut yupper)
506 };
507 result_handler!(ret, (ylower, yupper))
508 }
509
510 /// This function returns the maximum upper and minimum lower range limits and the number of bins for the x and y directions of the histogram h.
511 /// They provide a way of determining these values without accessing the gsl_histogram2d struct directly.
512 #[doc(alias = "gsl_histogram2d_xmax")]
513 pub fn xmax(&self) -> f64 {
514 unsafe { sys::gsl_histogram2d_xmax(self.unwrap_shared()) }
515 }
516
517 /// This function returns the maximum upper and minimum lower range limits and the number of bins for the x and y directions of the histogram h.
518 /// They provide a way of determining these values without accessing the gsl_histogram2d struct directly.
519 #[doc(alias = "gsl_histogram2d_xmin")]
520 pub fn xmin(&self) -> f64 {
521 unsafe { sys::gsl_histogram2d_xmin(self.unwrap_shared()) }
522 }
523
524 /// This function returns the maximum upper and minimum lower range limits and the number of bins for the x and y directions of the histogram h.
525 /// They provide a way of determining these values without accessing the gsl_histogram2d struct directly.
526 #[doc(alias = "gsl_histogram2d_nx")]
527 pub fn nx(&self) -> usize {
528 unsafe { sys::gsl_histogram2d_nx(self.unwrap_shared()) }
529 }
530
531 /// This function returns the maximum upper and minimum lower range limits and the number of bins for the x and y directions of the histogram h.
532 /// They provide a way of determining these values without accessing the gsl_histogram2d struct directly.
533 #[doc(alias = "gsl_histogram2d_ymax")]
534 pub fn ymax(&self) -> f64 {
535 unsafe { sys::gsl_histogram2d_ymax(self.unwrap_shared()) }
536 }
537
538 /// This function returns the maximum upper and minimum lower range limits and the number of bins for the x and y directions of the histogram h.
539 /// They provide a way of determining these values without accessing the gsl_histogram2d struct directly.
540 #[doc(alias = "gsl_histogram2d_ymin")]
541 pub fn ymin(&self) -> f64 {
542 unsafe { sys::gsl_histogram2d_ymin(self.unwrap_shared()) }
543 }
544
545 /// This function returns the maximum upper and minimum lower range limits and the number of bins for the x and y directions of the histogram h.
546 /// They provide a way of determining these values without accessing the gsl_histogram2d struct directly.
547 #[doc(alias = "gsl_histogram2d_ny")]
548 pub fn ny(&self) -> usize {
549 unsafe { sys::gsl_histogram2d_ny(self.unwrap_shared()) }
550 }
551
552 /// This function resets all the bins of the histogram h to zero.
553 #[doc(alias = "gsl_histogram2d_reset")]
554 pub fn reset(&mut self) {
555 unsafe { sys::gsl_histogram2d_reset(self.unwrap_unique()) }
556 }
557
558 /// This function finds and sets the indices i and j to the bin which covers the coordinates
559 /// (x,y). The bin is located using a binary search. The search includes an optimization for
560 /// histograms with uniform ranges, and will return the correct bin immediately in this case. If
561 /// (x,y) is found then the function sets the indices (i,j) and returns crate::Value::Success. If
562 /// (x,y) lies outside the valid range of the histogram then the function returns Value::Dom and
563 /// the error handler is invoked.
564 ///
565 /// Returns `(i, j)`.
566 #[doc(alias = "gsl_histogram2d_find")]
567 pub fn find(&self, x: f64, y: f64) -> Result<(usize, usize), Value> {
568 let mut i = 0;
569 let mut j = 0;
570 let ret = unsafe { sys::gsl_histogram2d_find(self.unwrap_shared(), x, y, &mut i, &mut j) };
571 result_handler!(ret, (i, j))
572 }
573
574 /// This function returns the maximum value contained in the histogram bins.
575 #[doc(alias = "gsl_histogram2d_max_val")]
576 pub fn max_val(&self) -> f64 {
577 unsafe { sys::gsl_histogram2d_max_val(self.unwrap_shared()) }
578 }
579
580 /// This function finds the indices of the bin containing the maximum value in the histogram h
581 /// and stores the result in (i,j). In the case where several bins contain the same maximum
582 /// value the first bin found is returned.
583 ///
584 /// Returns `(i, j)`.
585 #[doc(alias = "gsl_histogram2d_max_bin")]
586 pub fn max_bin(&self) -> (usize, usize) {
587 let mut i = 0;
588 let mut j = 0;
589 unsafe { sys::gsl_histogram2d_max_bin(self.unwrap_shared(), &mut i, &mut j) };
590 (i, j)
591 }
592
593 /// This function returns the minimum value contained in the histogram bins.
594 #[doc(alias = "gsl_histogram2d_min_val")]
595 pub fn min_val(&self) -> f64 {
596 unsafe { sys::gsl_histogram2d_min_val(self.unwrap_shared()) }
597 }
598
599 /// This function finds the indices of the bin containing the minimum value in the histogram h
600 /// and stores the result in (i,j). In the case where several bins contain the same maximum
601 /// value the first bin found is returned.
602 ///
603 /// Returns `(i, j)`.
604 #[doc(alias = "gsl_histogram2d_min_bin")]
605 pub fn min_bin(&self) -> (usize, usize) {
606 let mut i = 0;
607 let mut j = 0;
608 unsafe { sys::gsl_histogram2d_min_bin(self.unwrap_shared(), &mut i, &mut j) };
609 (i, j)
610 }
611
612 /// This function returns the mean of the histogrammed x variable, where the histogram is regarded as a probability distribution. Negative
613 /// bin values are ignored for the purposes of this calculation.
614 #[doc(alias = "gsl_histogram2d_xmean")]
615 pub fn xmean(&self) -> f64 {
616 unsafe { sys::gsl_histogram2d_xmean(self.unwrap_shared()) }
617 }
618
619 /// This function returns the mean of the histogrammed y variable, where the histogram is regarded as a probability distribution. Negative
620 /// bin values are ignored for the purposes of this calculation.
621 #[doc(alias = "gsl_histogram2d_ymean")]
622 pub fn ymean(&self) -> f64 {
623 unsafe { sys::gsl_histogram2d_ymean(self.unwrap_shared()) }
624 }
625
626 /// This function returns the standard deviation of the histogrammed x variable, where the histogram is regarded as a probability
627 /// distribution. Negative bin values are ignored for the purposes of this calculation.
628 #[doc(alias = "gsl_histogram2d_xsigma")]
629 pub fn xsigma(&self) -> f64 {
630 unsafe { sys::gsl_histogram2d_xsigma(self.unwrap_shared()) }
631 }
632
633 /// This function returns the standard deviation of the histogrammed y variable, where the histogram is regarded as a probability
634 /// distribution. Negative bin values are ignored for the purposes of this calculation.
635 #[doc(alias = "gsl_histogram2d_ysigma")]
636 pub fn ysigma(&self) -> f64 {
637 unsafe { sys::gsl_histogram2d_ysigma(self.unwrap_shared()) }
638 }
639
640 /// This function returns the covariance of the histogrammed x and y variables, where the histogram is regarded as a probability
641 /// distribution. Negative bin values are ignored for the purposes of this calculation.
642 #[doc(alias = "gsl_histogram2d_cov")]
643 pub fn cov(&self) -> f64 {
644 unsafe { sys::gsl_histogram2d_cov(self.unwrap_shared()) }
645 }
646
647 /// This function returns the sum of all bin values. Negative bin values are included in the sum.
648 #[doc(alias = "gsl_histogram2d_sum")]
649 pub fn sum(&self) -> f64 {
650 unsafe { sys::gsl_histogram2d_sum(self.unwrap_shared()) }
651 }
652
653 /// This function returns 1 if all the individual bin ranges of the two histograms are identical, and 0 otherwise.
654 #[doc(alias = "gsl_histogram2d_equal_bins_p")]
655 pub fn equal_bins_p(&self, other: &Histogram2D) -> bool {
656 unsafe {
657 sys::gsl_histogram2d_equal_bins_p(self.unwrap_shared(), other.unwrap_shared()) != 0
658 }
659 }
660
661 /// This function adds the contents of the bins in histogram h2 to the corresponding bins of histogram h1, i.e. h'_1(i,j) = h_1(i,j)
662 /// + h_2(i,j). The two histograms must have identical bin ranges.
663 #[doc(alias = "gsl_histogram2d_add")]
664 pub fn add(&mut self, other: &Histogram2D) -> Result<(), Value> {
665 let ret = unsafe { sys::gsl_histogram2d_add(self.unwrap_unique(), other.unwrap_shared()) };
666 result_handler!(ret, ())
667 }
668
669 /// This function subtracts the contents of the bins in histogram h2 from the corresponding bins of histogram h1, i.e. h'_1(i,j) = h_1(i,j)
670 /// - h_2(i,j). The two histograms must have identical bin ranges.
671 #[doc(alias = "gsl_histogram2d_sub")]
672 pub fn sub(&mut self, other: &Histogram2D) -> Result<(), Value> {
673 let ret = unsafe { sys::gsl_histogram2d_sub(self.unwrap_unique(), other.unwrap_shared()) };
674 result_handler!(ret, ())
675 }
676
677 /// This function multiplies the contents of the bins of histogram h1 by the contents of the corresponding bins in histogram h2, i.e. h'_1(i,j)
678 /// = h_1(i,j) * h_2(i,j). The two histograms must have identical bin ranges.
679 #[doc(alias = "gsl_histogram2d_mul")]
680 pub fn mul(&mut self, other: &Histogram2D) -> Result<(), Value> {
681 let ret = unsafe { sys::gsl_histogram2d_mul(self.unwrap_unique(), other.unwrap_shared()) };
682 result_handler!(ret, ())
683 }
684
685 /// This function divides the contents of the bins of histogram h1 by the contents of the corresponding bins in histogram h2, i.e. h'_1(i,j) =
686 /// h_1(i,j) / h_2(i,j). The two histograms must have identical bin ranges.
687 #[doc(alias = "gsl_histogram2d_div")]
688 pub fn div(&mut self, other: &Histogram2D) -> Result<(), Value> {
689 let ret = unsafe { sys::gsl_histogram2d_div(self.unwrap_unique(), other.unwrap_shared()) };
690 result_handler!(ret, ())
691 }
692
693 /// This function multiplies the contents of the bins of histogram h by the constant scale, i.e. h'_1(i,j) = h_1(i,j) scale.
694 #[doc(alias = "gsl_histogram2d_scale")]
695 pub fn scale(&mut self, scale: f64) -> Result<(), Value> {
696 let ret = unsafe { sys::gsl_histogram2d_scale(self.unwrap_unique(), scale) };
697 result_handler!(ret, ())
698 }
699
700 /// This function shifts the contents of the bins of histogram h by the constant offset, i.e. h'_1(i,j) = h_1(i,j) + offset.
701 #[doc(alias = "gsl_histogram2d_shift")]
702 pub fn shift(&mut self, offset: f64) -> Result<(), Value> {
703 let ret = unsafe { sys::gsl_histogram2d_shift(self.unwrap_unique(), offset) };
704 result_handler!(ret, ())
705 }
706}
707
708ffi_wrapper!(
709 Histogram2DPdf,
710 *mut sys::gsl_histogram2d_pdf,
711 gsl_histogram2d_pdf_free,
712 "As in the one-dimensional case, a two-dimensional histogram made by counting events can be \
713regarded as a measurement of a probability distribution. Allowing for statistical error, the \
714height of each bin represents the probability of an event where (x,y) falls in the range of that \
715bin. For a two-dimensional histogram the probability distribution takes the form p(x,y) dx dy \
716where,
717
718p(x,y) = n_{ij}/ (N A_{ij})
719
720In this equation n_{ij} is the number of events in the bin which contains (x,y), A_{ij} is the \
721area of the bin and N is the total number of events. The distribution of events within each bin is \
722assumed to be uniform."
723);
724
725impl Histogram2DPdf {
726 /// This function allocates memory for a two-dimensional probability distribution of size nx-by-ny and returns a pointer to a newly initialized
727 /// gsl_histogram2d_pdf struct. If insufficient memory is available a null pointer is returned and the error handler is invoked with an error
728 /// code of Value::NoMem.
729 #[doc(alias = "gsl_histogram2d_pdf_alloc")]
730 pub fn new(nx: usize, ny: usize) -> Option<Histogram2DPdf> {
731 let tmp = unsafe { sys::gsl_histogram2d_pdf_alloc(nx, ny) };
732
733 if tmp.is_null() {
734 None
735 } else {
736 Some(Self::wrap(tmp))
737 }
738 }
739
740 ///This function initializes the two-dimensional probability distribution calculated p from the histogram h. If any of the bins of h are
741 /// negative then the error handler is invoked with an error code of GSL_EDOM because a probability distribution cannot contain negative
742 /// values.
743 #[doc(alias = "gsl_histogram2d_pdf_init")]
744 pub fn init(&mut self, h: &Histogram2D) -> Result<(), Value> {
745 let ret = unsafe { sys::gsl_histogram2d_pdf_init(self.unwrap_unique(), h.unwrap_shared()) };
746 result_handler!(ret, ())
747 }
748
749 /// This function uses two uniform random numbers between zero and one, r1 and r2, to compute a
750 /// single random sample from the two-dimensional probability distribution p.
751 ///
752 /// Returns `(x, y)`.
753 #[doc(alias = "gsl_histogram2d_pdf_sample")]
754 pub fn sample(&self, r1: f64, r2: f64) -> Result<(f64, f64), Value> {
755 let mut x = 0.;
756 let mut y = 0.;
757 let ret = unsafe {
758 sys::gsl_histogram2d_pdf_sample(self.unwrap_shared(), r1, r2, &mut x, &mut y)
759 };
760 result_handler!(ret, (x, y))
761 }
762}