Replace numerous instances of xzalloc with XZALLOC
[pspp] / src / output / charts / np-plot.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2004, 2008, 2009, 2011 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18
19 #include "output/charts/np-plot.h"
20
21 #include <gsl/gsl_cdf.h>
22
23 #include "data/casereader.h"
24 #include "libpspp/cast.h"
25 #include "math/np.h"
26 #include "output/chart-provider.h"
27
28 #include "gl/minmax.h"
29
30 static struct chart *
31 make_np_plot (const struct np *np, const struct casereader *reader,
32               const char *label, bool detrended)
33 {
34   if (np->n <= 1.0)
35     return NULL;
36
37   struct np_plot_chart *npp = XZALLOC (struct np_plot_chart);
38   chart_init (&npp->chart, &np_plot_chart_class, label);
39   npp->data = casereader_clone (reader);
40   npp->y_min = np->y_min;
41   npp->y_max = np->y_max;
42   npp->dns_min = np->dns_min;
43   npp->dns_max = np->dns_max;
44   npp->detrended = detrended;
45
46   /* Slope and intercept of the ideal normal probability line. */
47   npp->slope = 1.0 / np->stddev;
48   npp->intercept = -np->mean / np->stddev;
49
50   npp->y_first = gsl_cdf_ugaussian_Pinv (1 / (np->n + 1));
51   npp->y_last = gsl_cdf_ugaussian_Pinv (np->n / (np->n + 1));
52
53   /* Need to make sure that both the scatter plot and the ideal fit into the
54      plot. */
55   npp->x_lower = MIN (np->y_min, (npp->y_first - npp->intercept) / npp->slope);
56   npp->x_upper = MAX (np->y_max, (npp->y_last  - npp->intercept) / npp->slope);
57   npp->slack = (npp->x_upper - npp->x_lower) * 0.05;
58
59   return &npp->chart;
60 }
61
62 /* Creates and returns a normal probability plot corresponding to
63    the calculations in NP and the data in READER, and label the
64    plot with LABEL.  The data in READER must have Y-values in
65    value index NP_IDX_Y and NS-values in value index NP_IDX_NS.
66
67    Returns a null pointer if the data set is empty.
68
69    The caller retains ownership of NP and READER. */
70 struct chart *
71 np_plot_create (const struct np *np, const struct casereader *reader,
72                 const char *label)
73 {
74   return make_np_plot (np, reader, label, false);
75 }
76
77 /* Creates and returns a detrended normal probability plot
78    corresponding to the calculations in NP and the data in
79    READER, and label the plot with LABEL.  The data in READER
80    must have Y-values in value index NP_IDX_Y and DNS-values in
81    value index NP_IDX_DNS.
82
83    Returns a null pointer if the data set is empty.
84
85    The caller retains ownership of NP and READER. */
86 struct chart *
87 dnp_plot_create (const struct np *np, const struct casereader *reader,
88                  const char *label)
89 {
90   return make_np_plot (np, reader, label, true);
91 }
92
93 static void
94 np_plot_chart_destroy (struct chart *chart)
95 {
96   struct np_plot_chart *npp = to_np_plot_chart (chart);
97   casereader_destroy (npp->data);
98   free (npp);
99 }
100
101 const struct chart_class np_plot_chart_class =
102   {
103     np_plot_chart_destroy
104   };