Thanks to Ben Pfaff for this suggestion.
#include <config.h>
#include <data/val-type.h>
#include <data/casereader.h>
#include <config.h>
#include <data/val-type.h>
#include <data/casereader.h>
#include <stdlib.h>
#include <data/casereader-provider.h>
#include <stdlib.h>
#include <data/casereader-provider.h>
by reading from SUBREADER and appending an additional value,
generated by FUNC. AUX is an optional parameter which
gets passed to FUNC. FUNC will also receive N as it, which is
by reading from SUBREADER and appending an additional value,
generated by FUNC. AUX is an optional parameter which
gets passed to FUNC. FUNC will also receive N as it, which is
- the ordinal number of the case in the reader. DESTROY is an
+ the ordinal number of the case in the reader. DESTROY is an
optional parameter used to destroy AUX.
After this function is called, SUBREADER must not ever again
optional parameter used to destroy AUX.
After this function is called, SUBREADER must not ever again
double cc;
distinct_func *distinct;
void *aux;
double cc;
distinct_func *distinct;
void *aux;
+ enum rank_error *err;
+ double prev_value;
};
static bool car_destroy (void *car_);
};
static bool car_destroy (void *car_);
/* Creates and returns a new casereader whose cases are produced
by reading from SUBREADER and appending an additional value,
/* Creates and returns a new casereader whose cases are produced
by reading from SUBREADER and appending an additional value,
- which is the rank of the observation. SUBREADER must be sorted
- on V. W is the weight variable of the dictionary containing V,
- or NULL if there is no weight variable.
+ which is the rank of the observation. W is the weight variable
+ of the dictionary containing V, or NULL if there is no weight
+ variable.
+
+ The following preconditions must be met:
+
+ 1. SUBREADER must be sorted on V.
+
+ 2. The weight variables, must be non-negative.
+
+ If either of these preconditions are not satisfied, then the rank
+ variables may not be correct. In this case, if ERR is non-null,
+ it will be set according to the erroneous conditions encountered.
If DISTINCT_CALLBACK is non-null, then it will be called exactly
once for every case containing a distinct value of V. AUX is
If DISTINCT_CALLBACK is non-null, then it will be called exactly
once for every case containing a distinct value of V. AUX is
casereader_create_append_rank (struct casereader *subreader,
const struct variable *v,
const struct variable *w,
casereader_create_append_rank (struct casereader *subreader,
const struct variable *v,
const struct variable *w,
distinct_func *distinct_callback,
void *aux
)
distinct_func *distinct_callback,
void *aux
)
car->clone = casereader_clone (subreader);
car->distinct = distinct_callback;
car->aux = aux;
car->clone = casereader_clone (subreader);
car->distinct = distinct_callback;
car->aux = aux;
+ car->err = err;
+ car->prev_value = SYSMIS;
return casereader_create_translator (subreader, car->value_ofs + 1,
car_translate, car_destroy, car);
return casereader_create_translator (subreader, car->value_ofs + 1,
car_translate, car_destroy, car);
{
struct casereader_append_rank *car = car_;
{
struct casereader_append_rank *car = car_;
- double value = case_data (input, car->var)->f;
+ const double value = case_data (input, car->var)->f;
+
+ if ( car->prev_value != SYSMIS)
+ {
+ if (car->err && value < car->prev_value)
+ *car->err |= RANK_ERR_UNSORTED;
+ }
if ( car->n_common == 1)
{
if ( car->n_common == 1)
{
casenumber k = 0;
double weight = 1.0;
if (car->weight)
casenumber k = 0;
double weight = 1.0;
if (car->weight)
- weight = case_data (input, car->weight)->f;
+ {
+ weight = case_data (input, car->weight)->f;
+ if ( car->err && weight < 0 )
+ *car->err |= RANK_ERR_NEGATIVE_WEIGHT;
+ }
if ( vxx == value)
{
if (car->weight)
if ( vxx == value)
{
if (car->weight)
- weight += case_data (&c, car->weight)->f;
+ {
+ double w = case_data (&c, car->weight)->f;
+
+ if ( car->err && w < 0 )
+ *car->err |= RANK_ERR_NEGATIVE_WEIGHT;
+
+ weight += w;
+ }
else
weight += 1.0;
car->n_common++;
else
weight += 1.0;
car->n_common++;
case_move (output, input);
case_resize (output, car->value_ofs + 1);
case_data_rw_idx (output, car->value_ofs)->f = car->mean_rank ;
case_move (output, input);
case_resize (output, car->value_ofs + 1);
case_data_rw_idx (output, car->value_ofs)->f = car->mean_rank ;
+ car->prev_value = value;
casereader_create_arithmetic_sequence (struct casereader *,
double first, double increment);
casereader_create_arithmetic_sequence (struct casereader *,
double first, double increment);
+enum rank_error
+ {
+ RANK_ERR_NONE = 0,
+ RANK_ERR_NEGATIVE_WEIGHT = 0x01,
+ RANK_ERR_UNSORTED = 0x02
+ };
+
typedef void distinct_func (double v, casenumber n, double w, void *aux);
struct casereader *
casereader_create_append_rank (struct casereader *,
const struct variable *v, const struct variable *w,
typedef void distinct_func (double v, casenumber n, double w, void *aux);
struct casereader *
casereader_create_append_rank (struct casereader *,
const struct variable *v, const struct variable *w,
distinct_func *distinct_callback, void *aux);
distinct_func *distinct_callback, void *aux);