/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2007, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include <config.h>
+#include <float.h>
#include <gsl/gsl_cdf.h>
#include <gsl/gsl_matrix.h>
#include <math.h>
#include "linreg/sweep.h"
#include "tukey/tukey.h"
#include "math/categoricals.h"
+#include "math/interaction.h"
#include "math/covariance.h"
#include "math/levene.h"
#include "math/moments.h"
/* Workspace variable for each dependent variable */
struct per_var_ws
{
+ struct interaction *iact;
struct categoricals *cat;
struct covariance *cov;
struct levene *nl;
moments1_calculate (mom_i, &n_i, NULL, &var_i, 0, 0);
moments1_calculate (mom_j, &n_j, NULL, &var_j, 0, 0);
+
+ if ( n_i <= 1.0 || n_j <= 1.0)
+ return SYSMIS;
nom = pow2 (var_i/n_i + var_j/n_j);
denom = pow2 (var_i/n_i) / (n_i - 1) + pow2 (var_j/n_j) / (n_j - 1);
static double tukey_pinv (double std_err, double alpha, double df, int k, const struct moments1 *mom_i UNUSED, const struct moments1 *mom_j UNUSED)
{
+ if ( k < 2 || df < 2)
+ return SYSMIS;
+
return std_err / sqrt (2.0) * qtukey (1 - alpha, 1.0, k, df, 1, 0);
}
m = sqrt ((var_i/n_i + var_j/n_j) / 2.0);
+ if ( k < 2 || df < 2)
+ return SYSMIS;
+
return m * qtukey (1 - alpha, 1.0, k, df, 1, 0);
}
int k = pvw->n_groups;
double df = ph->dff (pvw, dd_i->mom, dd_j->mom);
double ts = ph->tsf (k, dd_i->mom, dd_j->mom, std_err);
+ if ( df == SYSMIS)
+ return SYSMIS;
return ph->p1f (ts, k - 1, df);
}
{
int k = pvw->n_groups;
double df = ph->dff (pvw, dd_i->mom, dd_j->mom);
+ if ( df == SYSMIS)
+ return SYSMIS;
return ph->pinv (std_err, cmd->alpha, df, k, dd_i->mom, dd_j->mom);
}
static double tukey_1tailsig (double ts, double df1, double df2)
{
- double twotailedsig = 1.0 - ptukey (ts, 1.0, df1 + 1, df2, 1, 0);
+ double twotailedsig;
+
+ if (df2 < 2 || df1 < 1)
+ return SYSMIS;
+
+ twotailedsig = 1.0 - ptukey (ts, 1.0, df1 + 1, df2, 1, 0);
return twotailedsig / 2.0;
}
static void output_oneway (const struct oneway_spec *, struct oneway_workspace *ws);
static void run_oneway (const struct oneway_spec *cmd, struct casereader *input, const struct dataset *ds);
+
+static void
+destroy_coeff_list (struct contrasts_node *coeff_list)
+{
+ struct coeff_node *cn = NULL;
+ struct coeff_node *cnx = NULL;
+ struct ll_list *cl = &coeff_list->coefficient_list;
+
+ ll_for_each_safe (cn, cnx, struct coeff_node, ll, cl)
+ {
+ free (cn);
+ }
+
+ free (coeff_list);
+}
+
+static void
+oneway_cleanup (struct oneway_spec *cmd)
+{
+ struct contrasts_node *coeff_list = NULL;
+ struct contrasts_node *coeff_next = NULL;
+ ll_for_each_safe (coeff_list, coeff_next, struct contrasts_node, ll, &cmd->contrast_list)
+ {
+ destroy_coeff_list (coeff_list);
+ }
+
+ free (cmd->posthoc);
+}
+
+
+
int
cmd_oneway (struct lexer *lexer, struct dataset *ds)
{
}
else
{
+ destroy_coeff_list (cl);
lex_error (lexer, NULL);
goto error;
}
ok = proc_commit (ds) && ok;
}
+ oneway_cleanup (&oneway);
free (oneway.vars);
return CMD_SUCCESS;
error:
+ oneway_cleanup (&oneway);
free (oneway.vars);
return CMD_FAILURE;
}
}
static void *
-makeit (void *aux1, void *aux2 UNUSED)
+makeit (const void *aux1, void *aux2 UNUSED)
{
const struct variable *var = aux1;
}
static void
-updateit (void *user_data,
- enum mv_class exclude,
- const struct variable *wv,
- const struct variable *catvar UNUSED,
- const struct ccase *c,
- void *aux1, void *aux2)
+killit (const void *aux1 UNUSED, void *aux2 UNUSED, void *user_data)
{
struct descriptive_data *dd = user_data;
- const struct variable *varp = aux1;
+ dd_destroy (dd);
+}
- const union value *valx = case_data (c, varp);
- struct descriptive_data *dd_total = aux2;
+static void
+updateit (const void *aux1, void *aux2, void *user_data,
+ const struct ccase *c, double weight)
+{
+ struct descriptive_data *dd = user_data;
- double weight;
+ const struct variable *varp = aux1;
- if ( var_is_value_missing (varp, valx, exclude))
- return;
+ const union value *valx = case_data (c, varp);
- weight = wv != NULL ? case_data (c, wv)->f : 1.0;
+ struct descriptive_data *dd_total = aux2;
moments1_add (dd->mom, valx->f, weight);
if (valx->f < dd->minimum)
for (v = 0; v < cmd->n_vars; ++v)
{
- struct interaction *inter = interaction_create (cmd->indep_var);
- ws.vws[v].cat = categoricals_create (&inter, 1, cmd->wv,
- cmd->exclude, makeit, updateit,
- CONST_CAST (struct variable *,
- cmd->vars[v]),
- ws.dd_total[v]);
+ struct payload payload;
+ payload.create = makeit;
+ payload.update = updateit;
+ payload.calculate = NULL;
+ payload.destroy = killit;
+
+ ws.vws[v].iact = interaction_create (cmd->indep_var);
+ ws.vws[v].cat = categoricals_create (&ws.vws[v].iact, 1, cmd->wv,
+ cmd->exclude, cmd->exclude);
+
+ categoricals_set_payload (ws.vws[v].cat, &payload,
+ CONST_CAST (struct variable *, cmd->vars[v]),
+ ws.dd_total[v]);
+
ws.vws[v].cov = covariance_2pass_create (1, &cmd->vars[v],
ws.vws[v].cat,
for (v = 0; v < cmd->n_vars; ++v)
{
+ const gsl_matrix *ucm;
+ gsl_matrix *cm;
struct per_var_ws *pvw = &ws.vws[v];
- gsl_matrix *cm = covariance_calculate_unnormalized (pvw->cov);
const struct categoricals *cats = covariance_get_categoricals (pvw->cov);
+ const bool ok = categoricals_sane (cats);
+
+ if ( ! ok)
+ {
+ msg (MW,
+ _("Dependent variable %s has no non-missing values. No analysis for this variable will be done."),
+ var_get_name (cmd->vars[v]));
+ continue;
+ }
+
+ ucm = covariance_calculate_unnormalized (pvw->cov);
+
+ cm = gsl_matrix_alloc (ucm->size1, ucm->size2);
+ gsl_matrix_memcpy (cm, ucm);
moments1_calculate (ws.dd_total[v]->mom, &pvw->n, NULL, NULL, NULL, NULL);
reg_sweep (cm, 0);
pvw->sse = gsl_matrix_get (cm, 0, 0);
+ gsl_matrix_free (cm);
pvw->ssa = pvw->sst - pvw->sse;
- pvw->n_groups = categoricals_total (cats);
+ pvw->n_groups = categoricals_n_total (cats);
pvw->mse = (pvw->sst - pvw->ssa) / (pvw->n - pvw->n_groups);
-
- gsl_matrix_free (cm);
}
for (v = 0; v < cmd->n_vars; ++v)
{
const struct categoricals *cats = covariance_get_categoricals (ws.vws[v].cov);
- categoricals_done (cats);
-
- if (categoricals_total (cats) > ws.actual_number_of_groups)
- ws.actual_number_of_groups = categoricals_total (cats);
+ if ( ! categoricals_is_complete (cats))
+ {
+ continue;
+ }
+
+ if (categoricals_n_total (cats) > ws.actual_number_of_groups)
+ ws.actual_number_of_groups = categoricals_n_total (cats);
}
casereader_destroy (input);
taint_destroy (taint);
finish:
+
for (v = 0; v < cmd->n_vars; ++v)
{
covariance_destroy (ws.vws[v].cov);
levene_destroy (ws.vws[v].nl);
dd_destroy (ws.dd_total[v]);
+ interaction_destroy (ws.vws[v].iact);
}
+
free (ws.vws);
free (ws.dd_total);
}
if (ll_count (cl) != ws->actual_number_of_groups)
{
msg (SW,
- _("In contrast list %zu, the number of coefficients (%d) does not equal the number of groups (%d). This contrast list will be ignored."),
+ _("In contrast list %zu, the number of coefficients (%zu) does not equal the number of groups (%d). This contrast list will be ignored."),
i, ll_count (cl), ws->actual_number_of_groups);
ll_remove (&coeff_list->ll);
+ destroy_coeff_list (coeff_list);
continue;
}
{
int v;
for (v = 0 ; v < cmd->n_vars; ++v)
- show_comparisons (cmd, ws, v);
+ {
+ const struct categoricals *cats = covariance_get_categoricals (ws->vws[v].cov);
+
+ if ( categoricals_is_complete (cats))
+ show_comparisons (cmd, ws, v);
+ }
}
}
tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("df"));
tab_text (t, 4, 0, TAB_CENTER | TAT_TITLE, _("Mean Square"));
tab_text (t, 5, 0, TAB_CENTER | TAT_TITLE, _("F"));
- tab_text (t, 6, 0, TAB_CENTER | TAT_TITLE, _("Significance"));
+ tab_text (t, 6, 0, TAB_CENTER | TAT_TITLE, _("Sig."));
for (i = 0; i < cmd->n_vars; ++i)
/* Sums of Squares */
- tab_double (t, 2, i * 3 + 1, 0, pvw->ssa, NULL);
- tab_double (t, 2, i * 3 + 3, 0, pvw->sst, NULL);
- tab_double (t, 2, i * 3 + 2, 0, pvw->sse, NULL);
+ tab_double (t, 2, i * 3 + 1, 0, pvw->ssa, NULL, RC_OTHER);
+ tab_double (t, 2, i * 3 + 3, 0, pvw->sst, NULL, RC_OTHER);
+ tab_double (t, 2, i * 3 + 2, 0, pvw->sse, NULL, RC_OTHER);
/* Degrees of freedom */
- tab_fixed (t, 3, i * 3 + 1, 0, df1, 4, 0);
- tab_fixed (t, 3, i * 3 + 2, 0, df2, 4, 0);
- tab_fixed (t, 3, i * 3 + 3, 0, n - 1, 4, 0);
+ tab_double (t, 3, i * 3 + 1, 0, df1, NULL, RC_INTEGER);
+ tab_double (t, 3, i * 3 + 2, 0, df2, NULL, RC_INTEGER);
+ tab_double (t, 3, i * 3 + 3, 0, n - 1, NULL, RC_INTEGER);
/* Mean Squares */
- tab_double (t, 4, i * 3 + 1, TAB_RIGHT, msa, NULL);
- tab_double (t, 4, i * 3 + 2, TAB_RIGHT, pvw->mse, NULL);
+ tab_double (t, 4, i * 3 + 1, TAB_RIGHT, msa, NULL, RC_OTHER);
+ tab_double (t, 4, i * 3 + 2, TAB_RIGHT, pvw->mse, NULL, RC_OTHER);
{
const double F = msa / pvw->mse ;
/* The F value */
- tab_double (t, 5, i * 3 + 1, 0, F, NULL);
+ tab_double (t, 5, i * 3 + 1, 0, F, NULL, RC_OTHER);
/* The significance */
- tab_double (t, 6, i * 3 + 1, 0, gsl_cdf_fdist_Q (F, df1, df2), NULL);
+ tab_double (t, 6, i * 3 + 1, 0, gsl_cdf_fdist_Q (F, df1, df2), NULL, RC_PVALUE);
}
}
n_rows += ws->actual_number_of_groups + 1;
t = tab_create (n_cols, n_rows);
+ tab_set_format (t, RC_WEIGHT, wfmt);
tab_headers (t, 2, 0, 2, 0);
/* Put a frame around the entire box, and vertical lines inside */
if ( v > 0)
tab_hline (t, TAL_1, 0, n_cols - 1, row);
- for (count = 0; count < categoricals_total (cats); ++count)
+ for (count = 0; count < categoricals_n_total (cats); ++count)
{
double T;
double n, mean, variance;
struct string vstr;
- const union value *gval = categoricals_get_value_by_category (cats, count);
+ const struct ccase *gcc = categoricals_get_case_by_category (cats, count);
const struct descriptive_data *dd = categoricals_get_user_data_by_category (cats, count);
moments1_calculate (dd->mom, &n, &mean, &variance, NULL, NULL);
ds_init_empty (&vstr);
- var_append_value_name (cmd->indep_var, gval, &vstr);
+ var_append_value_name (cmd->indep_var, case_data (gcc, cmd->indep_var), &vstr);
tab_text (t, 1, row + count,
TAB_LEFT | TAT_TITLE,
/* Now fill in the numbers ... */
- tab_double (t, 2, row + count, 0, n, wfmt);
+ tab_double (t, 2, row + count, 0, n, NULL, RC_WEIGHT);
- tab_double (t, 3, row + count, 0, mean, NULL);
+ tab_double (t, 3, row + count, 0, mean, NULL, RC_OTHER);
- tab_double (t, 4, row + count, 0, std_dev, NULL);
+ tab_double (t, 4, row + count, 0, std_dev, NULL, RC_OTHER);
- tab_double (t, 5, row + count, 0, std_error, NULL);
+ tab_double (t, 5, row + count, 0, std_error, NULL, RC_OTHER);
/* Now the confidence interval */
T = gsl_cdf_tdist_Qinv (q, n - 1);
tab_double (t, 6, row + count, 0,
- mean - T * std_error, NULL);
+ mean - T * std_error, NULL, RC_OTHER);
tab_double (t, 7, row + count, 0,
- mean + T * std_error, NULL);
+ mean + T * std_error, NULL, RC_OTHER);
/* Min and Max */
- tab_double (t, 8, row + count, 0, dd->minimum, fmt);
- tab_double (t, 9, row + count, 0, dd->maximum, fmt);
+ tab_double (t, 8, row + count, 0, dd->minimum, fmt, RC_OTHER);
+ tab_double (t, 9, row + count, 0, dd->maximum, fmt, RC_OTHER);
}
+ if (categoricals_is_complete (cats))
{
double T;
double n, mean, variance;
tab_text (t, 1, row + count,
TAB_LEFT | TAT_TITLE, _("Total"));
- tab_double (t, 2, row + count, 0, n, wfmt);
+ tab_double (t, 2, row + count, 0, n, NULL, RC_WEIGHT);
- tab_double (t, 3, row + count, 0, mean, NULL);
+ tab_double (t, 3, row + count, 0, mean, NULL, RC_OTHER);
- tab_double (t, 4, row + count, 0, std_dev, NULL);
+ tab_double (t, 4, row + count, 0, std_dev, NULL, RC_OTHER);
- tab_double (t, 5, row + count, 0, std_error, NULL);
+ tab_double (t, 5, row + count, 0, std_error, NULL, RC_OTHER);
/* Now the confidence interval */
T = gsl_cdf_tdist_Qinv (q, n - 1);
tab_double (t, 6, row + count, 0,
- mean - T * std_error, NULL);
+ mean - T * std_error, NULL, RC_OTHER);
tab_double (t, 7, row + count, 0,
- mean + T * std_error, NULL);
+ mean + T * std_error, NULL, RC_OTHER);
+
/* Min and Max */
- tab_double (t, 8, row + count, 0, ws->dd_total[v]->minimum, fmt);
- tab_double (t, 9, row + count, 0, ws->dd_total[v]->maximum, fmt);
+ tab_double (t, 8, row + count, 0, ws->dd_total[v]->minimum, fmt, RC_OTHER);
+ tab_double (t, 9, row + count, 0, ws->dd_total[v]->maximum, fmt, RC_OTHER);
}
- row += categoricals_total (cats) + 1;
+ row += categoricals_n_total (cats) + 1;
}
tab_submit (t);
tab_text (t, 1, 0, TAB_CENTER | TAT_TITLE, _("Levene Statistic"));
tab_text (t, 2, 0, TAB_CENTER | TAT_TITLE, _("df1"));
tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("df2"));
- tab_text (t, 4, 0, TAB_CENTER | TAT_TITLE, _("Significance"));
+ tab_text (t, 4, 0, TAB_CENTER | TAT_TITLE, _("Sig."));
tab_title (t, _("Test of Homogeneity of Variances"));
tab_text (t, 0, v + 1, TAB_LEFT | TAT_TITLE, s);
- tab_double (t, 1, v + 1, TAB_RIGHT, F, NULL);
- tab_fixed (t, 2, v + 1, TAB_RIGHT, df1, 8, 0);
- tab_fixed (t, 3, v + 1, TAB_RIGHT, df2, 8, 0);
+ tab_double (t, 1, v + 1, TAB_RIGHT, F, NULL, RC_OTHER);
+ tab_double (t, 2, v + 1, TAB_RIGHT, df1, NULL, RC_INTEGER);
+ tab_double (t, 3, v + 1, TAB_RIGHT, df2, NULL, RC_INTEGER);
/* Now the significance */
- tab_double (t, 4, v + 1, TAB_RIGHT, gsl_cdf_fdist_Q (F, df1, df2), NULL);
+ tab_double (t, 4, v + 1, TAB_RIGHT, gsl_cdf_fdist_Q (F, df1, df2), NULL, RC_PVALUE);
}
tab_submit (t);
++count, coeffi = ll_next (coeffi))
{
const struct categoricals *cats = covariance_get_categoricals (cov);
- const union value *val = categoricals_get_value_by_category (cats, count);
+ const struct ccase *gcc = categoricals_get_case_by_category (cats, count);
struct coeff_node *coeffn = ll_data (coeffi, struct coeff_node, ll);
struct string vstr;
ds_init_empty (&vstr);
- var_append_value_name (cmd->indep_var, val, &vstr);
+ var_append_value_name (cmd->indep_var, case_data (gcc, cmd->indep_var), &vstr);
tab_text (t, count + 2, 1, TAB_CENTER | TAT_TITLE, ds_cstr (&vstr));
ds_destroy (&vstr);
- tab_text_format (t, count + 2, c_num + 2, TAB_RIGHT, "%g", coeffn->coeff);
+ tab_text_format (t, count + 2, c_num + 2, TAB_RIGHT, "%.*g",
+ DBL_DIG + 1, coeffn->coeff);
}
++c_num;
}
df_numerator = pow2 (df_numerator);
tab_double (t, 3, (v * lines_per_variable) + i + 1,
- TAB_RIGHT, contrast_value, NULL);
+ TAB_RIGHT, contrast_value, NULL, RC_OTHER);
tab_double (t, 3, (v * lines_per_variable) + i + 1 +
n_contrasts,
- TAB_RIGHT, contrast_value, NULL);
+ TAB_RIGHT, contrast_value, NULL, RC_OTHER);
std_error_contrast = sqrt (pvw->mse * coef_msq);
/* Std. Error */
tab_double (t, 4, (v * lines_per_variable) + i + 1,
TAB_RIGHT, std_error_contrast,
- NULL);
+ NULL, RC_OTHER);
T = fabs (contrast_value / std_error_contrast);
tab_double (t, 5, (v * lines_per_variable) + i + 1,
TAB_RIGHT, T,
- NULL);
+ NULL, RC_OTHER);
/* Degrees of Freedom */
- tab_fixed (t, 6, (v * lines_per_variable) + i + 1,
- TAB_RIGHT, df,
- 8, 0);
+ tab_double (t, 6, (v * lines_per_variable) + i + 1,
+ TAB_RIGHT, df, NULL, RC_INTEGER);
/* Significance TWO TAILED !!*/
tab_double (t, 7, (v * lines_per_variable) + i + 1,
TAB_RIGHT, 2 * gsl_cdf_tdist_Q (T, df),
- NULL);
+ NULL, RC_PVALUE);
/* Now for the Variances NOT Equal case */
tab_double (t, 4,
(v * lines_per_variable) + i + 1 + n_contrasts,
TAB_RIGHT, sec_vneq,
- NULL);
+ NULL, RC_OTHER);
T = contrast_value / sec_vneq;
tab_double (t, 5,
(v * lines_per_variable) + i + 1 + n_contrasts,
TAB_RIGHT, T,
- NULL);
+ NULL, RC_OTHER);
df = df_numerator / df_denominator;
tab_double (t, 6,
(v * lines_per_variable) + i + 1 + n_contrasts,
TAB_RIGHT, df,
- NULL);
+ NULL, RC_OTHER);
+
+ {
+ double p = gsl_cdf_tdist_P (T, df);
+ double q = gsl_cdf_tdist_Q (T, df);
- /* The Significance */
- tab_double (t, 7, (v * lines_per_variable) + i + 1 + n_contrasts,
- TAB_RIGHT, 2 * gsl_cdf_tdist_Q (T,df),
- NULL);
+ /* The Significance */
+ tab_double (t, 7, (v * lines_per_variable) + i + 1 + n_contrasts,
+ TAB_RIGHT, 2 * ((T > 0) ? q : p),
+ NULL, RC_PVALUE);
+ }
}
if ( v > 0 )
tab_vline (t, TAL_2, heading_cols, 0, n_rows - 1);
- tab_title (t, _("Multiple Comparisons"));
+ tab_title (t, _("Multiple Comparisons (%s)"), var_to_string (cmd->vars[v]));
tab_text_format (t, 1, 1, TAB_LEFT | TAT_TITLE, _("(I) %s"), var_to_string (cmd->indep_var));
tab_text_format (t, 2, 1, TAB_LEFT | TAT_TITLE, _("(J) %s"), var_to_string (cmd->indep_var));
struct string vstr;
int j;
struct descriptive_data *dd_i = categoricals_get_user_data_by_category (cat, i);
- const union value *gval = categoricals_get_value_by_category (cat, i);
+ const struct ccase *gcc = categoricals_get_case_by_category (cat, i);
+
ds_init_empty (&vstr);
- var_append_value_name (cmd->indep_var, gval, &vstr);
+ var_append_value_name (cmd->indep_var, case_data (gcc, cmd->indep_var), &vstr);
if ( i != 0)
tab_hline (t, TAL_1, 1, n_cols - 1, r);
double std_err;
double weight_j, mean_j, var_j;
double half_range;
+ const struct ccase *cc;
struct descriptive_data *dd_j = categoricals_get_user_data_by_category (cat, j);
if (j == i)
continue;
ds_clear (&vstr);
- gval = categoricals_get_value_by_category (cat, j);
- var_append_value_name (cmd->indep_var, gval, &vstr);
+ cc = categoricals_get_case_by_category (cat, j);
+ var_append_value_name (cmd->indep_var, case_data (cc, cmd->indep_var), &vstr);
tab_text (t, 2, r + rx, TAB_LEFT | TAT_TITLE, ds_cstr (&vstr));
moments1_calculate (dd_j->mom, &weight_j, &mean_j, &var_j, 0, 0);
- tab_double (t, 3, r + rx, 0, mean_i - mean_j, 0);
+ tab_double (t, 3, r + rx, 0, mean_i - mean_j, NULL, RC_OTHER);
std_err = pvw->mse;
std_err *= weight_i + weight_j;
std_err /= weight_i * weight_j;
std_err = sqrt (std_err);
- tab_double (t, 4, r + rx, 0, std_err, 0);
+ tab_double (t, 4, r + rx, 0, std_err, NULL, RC_OTHER);
- tab_double (t, 5, r + rx, 0, 2 * multiple_comparison_sig (std_err, pvw, dd_i, dd_j, ph), 0);
+ tab_double (t, 5, r + rx, 0, 2 * multiple_comparison_sig (std_err, pvw, dd_i, dd_j, ph), NULL, RC_PVALUE);
half_range = mc_half_range (cmd, pvw, std_err, dd_i, dd_j, ph);
tab_double (t, 6, r + rx, 0,
- (mean_i - mean_j) - half_range, 0 );
+ (mean_i - mean_j) - half_range, NULL, RC_OTHER);
tab_double (t, 7, r + rx, 0,
- (mean_i - mean_j) + half_range, 0 );
+ (mean_i - mean_j) + half_range, NULL, RC_OTHER);
rx++;
}