X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=src%2Fdata%2Fmissing-values.c;h=c4d40baae13c0c25c23d9bdd3226837a6c438844;hb=ce16a4a594e7ddfc277afc4abb7faaeb1a03d233;hp=fac56d0257bed1cf82b9d70895b96ed6f2103b9a;hpb=480a0746507ce73d26f528b56dc3ed80195096e0;p=pspp
diff --git a/src/data/missing-values.c b/src/data/missing-values.c
index fac56d0257..c4d40baae1 100644
--- a/src/data/missing-values.c
+++ b/src/data/missing-values.c
@@ -1,51 +1,61 @@
-/* PSPP - computes sample statistics.
+/* PSPP - a program for statistical analysis.
Copyright (C) 2005 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 the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
+ 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
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA. */
+ along with this program. If not, see . */
#include
#include "missing-values.h"
#include
#include
#include
+#include "variable.h"
#include
+/* Types of user-missing values.
+ Invisible--use access functions defined below instead. */
+enum mv_type
+ {
+ MVT_NONE = 0, /* No user-missing values. */
+ MVT_1 = 1, /* One user-missing value. */
+ MVT_2 = 2, /* Two user-missing values. */
+ MVT_3 = 3, /* Three user-missing values. */
+ MVT_RANGE = 4, /* A range of user-missing values. */
+ MVT_RANGE_1 = 5 /* A range plus an individual value. */
+ };
/* Initializes MV as a set of missing values for a variable of
the given WIDTH. Although only numeric variables and short
string variables may have missing values, WIDTH may be any
valid variable width. */
void
-mv_init (struct missing_values *mv, int width)
+mv_init (struct missing_values *mv, int width)
{
assert (width >= 0 && width <= MAX_STRING);
- mv->type = MV_NONE;
+ mv->type = MVT_NONE;
mv->width = width;
}
-void
-mv_set_type(struct missing_values *mv, enum mv_type type)
+/* Removes any missing values from MV. */
+void
+mv_clear (struct missing_values *mv)
{
- mv->type = type;
+ mv->type = MVT_NONE;
}
-
/* Copies SRC to MV. */
void
-mv_copy (struct missing_values *mv, const struct missing_values *src)
+mv_copy (struct missing_values *mv, const struct missing_values *src)
{
assert(src);
@@ -54,9 +64,9 @@ mv_copy (struct missing_values *mv, const struct missing_values *src)
/* Returns true if MV is an empty set of missing values. */
bool
-mv_is_empty (const struct missing_values *mv)
+mv_is_empty (const struct missing_values *mv)
{
- return mv->type == MV_NONE;
+ return mv->type == MVT_NONE;
}
/* Returns the width of the missing values that MV may
@@ -76,18 +86,18 @@ mv_add_value (struct missing_values *mv, const union value *v)
{
if (mv->width > MAX_SHORT_STRING)
return false;
- switch (mv->type)
+ switch (mv->type)
{
- case MV_NONE:
- case MV_1:
- case MV_2:
- case MV_RANGE:
+ case MVT_NONE:
+ case MVT_1:
+ case MVT_2:
+ case MVT_RANGE:
mv->values[mv->type & 3] = *v;
mv->type++;
return true;
- case MV_3:
- case MV_RANGE_1:
+ case MVT_3:
+ case MVT_RANGE_1:
return false;
}
NOT_REACHED ();
@@ -99,7 +109,7 @@ mv_add_value (struct missing_values *mv, const union value *v)
missing values. (Long string variables never accept missing
values.) */
bool
-mv_add_str (struct missing_values *mv, const char s[])
+mv_add_str (struct missing_values *mv, const char s[])
{
assert (mv->width > 0);
return mv_add_value (mv, (union value *) s);
@@ -109,7 +119,7 @@ mv_add_str (struct missing_values *mv, const char s[])
Returns true if successful, false if MV has no more room for
missing values. */
bool
-mv_add_num (struct missing_values *mv, double d)
+mv_add_num (struct missing_values *mv, double d)
{
assert (mv->width == 0);
return mv_add_value (mv, (union value *) &d);
@@ -119,24 +129,24 @@ mv_add_num (struct missing_values *mv, double d)
missing values MV. Returns true if successful, false if MV
has no room for a range, or if LOW > HIGH. */
bool
-mv_add_num_range (struct missing_values *mv, double low, double high)
+mv_add_num_range (struct missing_values *mv, double low, double high)
{
assert (mv->width == 0);
if (low > high)
return false;
- switch (mv->type)
+ switch (mv->type)
{
- case MV_NONE:
- case MV_1:
+ case MVT_NONE:
+ case MVT_1:
mv->values[1].f = low;
mv->values[2].f = high;
mv->type |= 4;
return true;
- case MV_2:
- case MV_3:
- case MV_RANGE:
- case MV_RANGE_1:
+ case MVT_2:
+ case MVT_3:
+ case MVT_RANGE:
+ case MVT_RANGE_1:
return false;
}
NOT_REACHED ();
@@ -147,16 +157,16 @@ mv_add_num_range (struct missing_values *mv, double low, double high)
bool
mv_has_value (const struct missing_values *mv)
{
- switch (mv->type)
+ switch (mv->type)
{
- case MV_1:
- case MV_2:
- case MV_3:
- case MV_RANGE_1:
+ case MVT_1:
+ case MVT_2:
+ case MVT_3:
+ case MVT_RANGE_1:
return true;
-
- case MV_NONE:
- case MV_RANGE:
+
+ case MVT_NONE:
+ case MVT_RANGE:
return false;
}
NOT_REACHED ();
@@ -166,7 +176,7 @@ mv_has_value (const struct missing_values *mv)
MV must contain an individual value (as determined by
mv_has_value()). */
void
-mv_pop_value (struct missing_values *mv, union value *v)
+mv_pop_value (struct missing_values *mv, union value *v)
{
assert (mv_has_value (mv));
mv->type--;
@@ -175,11 +185,11 @@ mv_pop_value (struct missing_values *mv, union value *v)
/* Stores a value in *V.
MV must contain an individual value (as determined by
- mv_has_value()).
+ mv_has_value()).
IDX is the zero based index of the value to get
*/
void
-mv_peek_value (const struct missing_values *mv, union value *v, int idx)
+mv_peek_value (const struct missing_values *mv, union value *v, int idx)
{
assert (idx >= 0 ) ;
assert (idx < 3);
@@ -188,7 +198,7 @@ mv_peek_value (const struct missing_values *mv, union value *v, int idx)
*v = mv->values[idx];
}
-void
+void
mv_replace_value (struct missing_values *mv, const union value *v, int idx)
{
assert (idx >= 0) ;
@@ -198,11 +208,11 @@ mv_replace_value (struct missing_values *mv, const union value *v, int idx)
}
-
-int
+/* Returns the number of individual (not part of a range) missing
+ values in MV. */
+int
mv_n_values (const struct missing_values *mv)
{
- assert(mv_has_value(mv));
return mv->type & 3;
}
@@ -210,18 +220,18 @@ mv_n_values (const struct missing_values *mv)
/* Returns true if MV contains a numeric range,
false if MV is empty (or contains only individual values). */
bool
-mv_has_range (const struct missing_values *mv)
+mv_has_range (const struct missing_values *mv)
{
- switch (mv->type)
+ switch (mv->type)
{
- case MV_RANGE:
- case MV_RANGE_1:
+ case MVT_RANGE:
+ case MVT_RANGE_1:
return true;
-
- case MV_NONE:
- case MV_1:
- case MV_2:
- case MV_3:
+
+ case MVT_NONE:
+ case MVT_1:
+ case MVT_2:
+ case MVT_3:
return false;
}
NOT_REACHED ();
@@ -231,7 +241,7 @@ mv_has_range (const struct missing_values *mv)
*HIGH. MV must contain a individual range (as determined by
mv_has_range()). */
void
-mv_pop_range (struct missing_values *mv, double *low, double *high)
+mv_pop_range (struct missing_values *mv, double *low, double *high)
{
assert (mv_has_range (mv));
*low = mv->values[1].f;
@@ -244,7 +254,7 @@ mv_pop_range (struct missing_values *mv, double *low, double *high)
*HIGH. MV must contain a individual range (as determined by
mv_has_range()). */
void
-mv_peek_range (const struct missing_values *mv, double *low, double *high)
+mv_peek_range (const struct missing_values *mv, double *low, double *high)
{
assert (mv_has_range (mv));
*low = mv->values[1].f;
@@ -256,23 +266,23 @@ mv_peek_range (const struct missing_values *mv, double *low, double *high)
is set to TYPE (in struct missing_values),
false otherwise. */
static bool
-using_element (unsigned type, int idx)
+using_element (unsigned type, int idx)
{
assert (idx >= 0 && idx < 3);
-
- switch (type)
+
+ switch (type)
{
- case MV_NONE:
+ case MVT_NONE:
return false;
- case MV_1:
+ case MVT_1:
return idx < 1;
- case MV_2:
+ case MVT_2:
return idx < 2;
- case MV_3:
+ case MVT_3:
return true;
- case MV_RANGE:
+ case MVT_RANGE:
return idx > 0;
- case MV_RANGE_1:
+ case MVT_RANGE_1:
return true;
}
NOT_REACHED ();
@@ -282,7 +292,7 @@ using_element (unsigned type, int idx)
NEW_WIDTH (inclusive) and OLD_WIDTH (exclusive),
false otherwise. */
static bool
-can_resize_string (const char *s, int old_width, int new_width)
+can_resize_string (const char *s, int old_width, int new_width)
{
int i;
@@ -302,17 +312,20 @@ can_resize_string (const char *s, int old_width, int new_width)
contains only spaces in the characters that will be
trimmed. */
bool
-mv_is_resizable (const struct missing_values *mv, int width)
+mv_is_resizable (const struct missing_values *mv, int width)
{
- assert ((width == 0) == (mv->width == 0));
- if (width > MAX_SHORT_STRING && mv->type != MV_NONE)
+ if ( var_type_from_width (width) != var_type_from_width (mv->width) )
+ return false;
+
+ if (width > MAX_SHORT_STRING && mv->type != MVT_NONE)
return false;
- else if (width >= mv->width)
+
+ if (width >= mv->width)
return true;
- else
+ else
{
int i;
-
+
for (i = 0; i < 3; i++)
if (using_element (mv->type, i)
&& !can_resize_string (mv->values[i].s, mv->width, width))
@@ -324,117 +337,104 @@ mv_is_resizable (const struct missing_values *mv, int width)
/* Resizes MV to the given WIDTH. WIDTH must fit the constraints
explained for mv_is_resizable(). */
void
-mv_resize (struct missing_values *mv, int width)
+mv_resize (struct missing_values *mv, int width)
{
assert (mv_is_resizable (mv, width));
- if (width > mv->width && mv->type != MV_NONE)
+ if (width > mv->width && mv->type != MVT_NONE)
{
int i;
-
+
for (i = 0; i < 3; i++)
memset (mv->values[i].s + mv->width, ' ', width - mv->width);
}
mv->width = width;
}
-/* Returns true if V is system missing or a missing value in MV,
- false otherwise. */
-bool
-mv_is_value_missing (const struct missing_values *mv, const union value *v)
-{
- return (mv->width == 0
- ? mv_is_num_missing (mv, v->f)
- : mv_is_str_missing (mv, v->s));
-}
-
-/* Returns true if D is system missing or a missing value in MV,
- false otherwise.
- MV must be a set of numeric missing values. */
-bool
-mv_is_num_missing (const struct missing_values *mv, double d)
-{
- assert (mv->width == 0);
- return d == SYSMIS || mv_is_num_user_missing (mv, d);
-}
-
-/* Returns true if S[] is a missing value in MV, false otherwise.
- MV must be a set of string missing values.
- S[] must contain exactly as many characters as MV's width. */
-bool
-mv_is_str_missing (const struct missing_values *mv, const char s[])
-{
- return mv_is_str_user_missing (mv, s);
-}
-
-/* Returns true if V is a missing value in MV, false otherwise. */
-bool
-mv_is_value_user_missing (const struct missing_values *mv,
- const union value *v)
-{
- return (mv->width == 0
- ? mv_is_num_user_missing (mv, v->f)
- : mv_is_str_user_missing (mv, v->s));
-}
-
/* Returns true if D is a missing value in MV, false otherwise.
MV must be a set of numeric missing values. */
-bool
-mv_is_num_user_missing (const struct missing_values *mv, double d)
+static bool
+is_num_user_missing (const struct missing_values *mv, double d)
{
const union value *v = mv->values;
assert (mv->width == 0);
- switch (mv->type)
+ switch (mv->type)
{
- case MV_NONE:
+ case MVT_NONE:
return false;
- case MV_1:
+ case MVT_1:
return v[0].f == d;
- case MV_2:
+ case MVT_2:
return v[0].f == d || v[1].f == d;
- case MV_3:
+ case MVT_3:
return v[0].f == d || v[1].f == d || v[2].f == d;
- case MV_RANGE:
+ case MVT_RANGE:
return v[1].f <= d && d <= v[2].f;
- case MV_RANGE_1:
+ case MVT_RANGE_1:
return v[0].f == d || (v[1].f <= d && d <= v[2].f);
}
NOT_REACHED ();
}
/* Returns true if S[] is a missing value in MV, false otherwise.
- MV must be a set of string missing values.
+ MV must be a set of string missing values.
S[] must contain exactly as many characters as MV's width. */
-bool
-mv_is_str_user_missing (const struct missing_values *mv,
+static bool
+is_str_user_missing (const struct missing_values *mv,
const char s[])
{
const union value *v = mv->values;
assert (mv->width > 0);
- switch (mv->type)
+ switch (mv->type)
{
- case MV_NONE:
+ case MVT_NONE:
return false;
- case MV_1:
+ case MVT_1:
return !memcmp (v[0].s, s, mv->width);
- case MV_2:
+ case MVT_2:
return (!memcmp (v[0].s, s, mv->width)
|| !memcmp (v[1].s, s, mv->width));
- case MV_3:
+ case MVT_3:
return (!memcmp (v[0].s, s, mv->width)
|| !memcmp (v[1].s, s, mv->width)
|| !memcmp (v[2].s, s, mv->width));
- case MV_RANGE:
- case MV_RANGE_1:
+ case MVT_RANGE:
+ case MVT_RANGE_1:
NOT_REACHED ();
}
NOT_REACHED ();
}
-/* Returns true if MV is a set of numeric missing values and V is
- the system missing value. */
+/* Returns true if V is a missing value in the given CLASS in MV,
+ false otherwise. */
+bool
+mv_is_value_missing (const struct missing_values *mv, const union value *v,
+ enum mv_class class)
+{
+ return (mv->width == 0
+ ? mv_is_num_missing (mv, v->f, class)
+ : mv_is_str_missing (mv, v->s, class));
+}
+
+/* Returns true if D is a missing value in the given CLASS in MV,
+ false otherwise.
+ MV must be a set of numeric missing values. */
+bool
+mv_is_num_missing (const struct missing_values *mv, double d,
+ enum mv_class class)
+{
+ assert (mv->width == 0);
+ return ((class & MV_SYSTEM && d == SYSMIS)
+ || (class & MV_USER && is_num_user_missing (mv, d)));
+}
+
+/* Returns true if S[] is a missing value in the given CLASS in
+ MV, false otherwise.
+ MV must be a set of string missing values.
+ S[] must contain exactly as many characters as MV's width. */
bool
-mv_is_value_system_missing (const struct missing_values *mv,
- const union value *v)
+mv_is_str_missing (const struct missing_values *mv, const char s[],
+ enum mv_class class)
{
- return mv->width == 0 && v->f == SYSMIS;
+ assert (mv->width > 0);
+ return class & MV_USER && is_str_user_missing (mv, s);
}