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}