/CC@{A,B,C,D,E@}=@{'@var{npre},@var{pre},@var{suf},@var{nsuf}','@var{npre}.@var{pre}.@var{suf}.@var{nsuf}'@}
/DECIMAL=@{DOT,COMMA@}
/FORMAT=@var{fmt_spec}
+ /SMALL=@var{number}
/WIB=@{NATIVE,MSBFIRST,LSBFIRST,VAX@}
/WRB=@{NATIVE,ISL,ISB,IDL,IDB,VF,VD,VG,ZS,ZL@}
Allows the default numeric input/output format to be specified. The
default is F8.2. @xref{Input and Output Formats}.
+@item SMALL
+This controls how @pspp{} formats small numbers in pivot tables, in
+cases where @pspp{} does not otherwise have a well-defined format for
+the numbers. When such a number has a magnitude less than the value
+set here, @pspp{} formats the number in scientific notation;
+otherwise, it formats it in standard notation. The default is 0.0001.
+Set a value of 0 to disable scientific notation.
+
@item WIB
@anchor{SET WIB}
int syntax;
struct fmt_settings styles;
+ double small;
enum settings_output_devices output_routing[SETTINGS_N_OUTPUT_TYPES];
ENHANCED, /* global_algorithm */
ENHANCED, /* syntax */
FMT_SETTINGS_INIT, /* styles */
+ .0001, /* small */
/* output_routing */
{SETTINGS_DEVICE_LISTING | SETTINGS_DEVICE_TERMINAL,
return &the_settings.styles;
}
+double
+settings_get_small (void)
+{
+ return the_settings.small;
+}
+
+void
+settings_set_small (double small)
+{
+ the_settings.small = small;
+}
+
/* Returns a string of the form "$#,###.##" according to FMT,
which must be of type FMT_DOLLAR. The caller must free the
string. */
const struct fmt_settings *settings_get_fmt_settings (void);
+double settings_get_small (void);
+void settings_set_small (double);
+
char * settings_dollar_template (const struct fmt_spec *fmt);
/* Routing of different kinds of output. */
scompression=scompress:on/off;
scripttab=string;
seed=custom;
+ small=double;
tnumbers=custom;
tvars=custom;
tb1=string;
settings_set_safer_mode ();
if (cmd.sbc_scompression)
settings_set_scompression (cmd.scompress == STC_ON);
+ if (cmd.sbc_small)
+ settings_set_small (cmd.n_small[0]);
if (cmd.sbc_undefined)
settings_set_undefined (cmd.undef == STC_WARN);
if (cmd.sbc_wib)
#include "output/pivot-table.h"
+#include <math.h>
#include <stdlib.h>
#include "data/data-out.h"
#define _(msgid) gettext (msgid)
#define N_(msgid) msgid
-static const struct fmt_spec *pivot_table_get_format (
- const struct pivot_table *, const char *s);
+static void pivot_table_use_rc (const struct pivot_table *, const char *s,
+ struct fmt_spec *, bool *honor_small);
\f
/* Pivot table display styling. */
static void
pivot_category_set_rc (struct pivot_category *category, const char *s)
{
- const struct fmt_spec *format = pivot_table_get_format (
- category->dimension->table, s);
- if (format)
- category->format = *format;
+ if (!s)
+ return;
+
+ pivot_table_use_rc (category->dimension->table, s,
+ &category->format, &category->honor_small);
/* Ensure that the category itself, in addition to the cells within it, takes
the format. (It's kind of rare for a category to have a numeric format
though.) */
struct pivot_value *name = category->name;
if (name->type == PIVOT_VALUE_NUMERIC && !name->numeric.format.w)
- name->numeric.format = format ? *format : *settings_get_format ();
+ pivot_table_use_rc (category->dimension->table, s,
+ &name->numeric.format, &name->numeric.honor_small);
}
static void
return NULL;
}
-static const struct fmt_spec *
-pivot_table_get_format (const struct pivot_table *table, const char *s)
+static void
+pivot_table_use_rc (const struct pivot_table *table, const char *s,
+ struct fmt_spec *format, bool *honor_small)
{
- if (!s)
- return NULL;
- else if (!strcmp (s, PIVOT_RC_OTHER))
- return settings_get_format ();
- else if (!strcmp (s, PIVOT_RC_COUNT) && !overridden_count_format)
- return &table->weight_format;
- else
+ if (s)
{
- const struct result_class *rc = pivot_result_class_find (s);
- return rc ? &rc->format : NULL;
+ if (!strcmp (s, PIVOT_RC_OTHER))
+ {
+ *format = *settings_get_format ();
+ *honor_small = true;
+ }
+ else if (!strcmp (s, PIVOT_RC_COUNT) && !overridden_count_format)
+ {
+ *format = table->weight_format;
+ *honor_small = false;
+ }
+ else
+ {
+ const struct result_class *rc = pivot_result_class_find (s);
+ if (rc)
+ {
+ *format = rc->format;
+ *honor_small = false;
+ }
+ else
+ {
+ printf ("unknown class %s\n", s);
+ }
+ }
}
}
table->command_c = output_get_command_name ();
table->look = pivot_table_look_ref (pivot_table_look_get_default ());
table->settings = fmt_settings_copy (settings_get_fmt_settings ());
+ table->small = settings_get_small ();
hmap_init (&table->cells);
if (c->format.w)
{
value->numeric.format = c->format;
+ value->numeric.honor_small = c->honor_small;
goto done;
}
}
}
value->numeric.format = *settings_get_format ();
+ value->numeric.honor_small = true;
done:;
}
value->numeric.value_label != NULL);
if (show & SETTINGS_VALUE_SHOW_VALUE)
{
+ const struct fmt_spec *f = &value->numeric.format;
+ const struct fmt_spec *format
+ = (f->type == FMT_F
+ && value->numeric.honor_small
+ && value->numeric.x != 0
+ && fabs (value->numeric.x) < pt->small
+ ? &(struct fmt_spec) { .type = FMT_E, .w = 40, .d = f->d }
+ : f);
+
char *s = data_out (&(union value) { .f = value->numeric.x },
- "UTF-8", &value->numeric.format, &pt->settings);
+ "UTF-8", format, &pt->settings);
ds_put_cstr (out, s + strspn (s, " "));
free (s);
}
const char *rc)
{
if (value->type == PIVOT_VALUE_NUMERIC)
- {
- const struct fmt_spec *f = pivot_table_get_format (table, rc);
- if (f)
- value->numeric.format = *f;
- }
+ pivot_table_use_rc (table, rc,
+ &value->numeric.format, &value->numeric.honor_small);
}
bool show_label_in_corner;
/* Leaf only. */
- struct fmt_spec format;
size_t group_index; /* In ->parent->subs[]. */
size_t data_index; /* In ->dimension->data_leaves[]. */
size_t presentation_index; /* In ->dimension->presentation_leaves[]. */
+ struct fmt_spec format; /* Default format for values in this category. */
+ bool honor_small; /* Honor pivot_table 'small' setting? */
};
static inline bool
char *var_name; /* May be NULL. */
char *value_label; /* May be NULL. */
enum settings_value_show show; /* Show value or label or both? */
+ bool honor_small; /* Honor value of pivot table 'small'? */
}
numeric;
}
static void
-put_format (struct buf *buf, const struct fmt_spec *f)
+put_format (struct buf *buf, const struct fmt_spec *f, bool honor_small)
{
- put_u32 (buf, (fmt_to_io (f->type) << 16) | (f->w << 8) | f->d);
+ int type = f->type == FMT_F && honor_small ? 40 : fmt_to_io (f->type);
+ put_u32 (buf, (type << 16) | (f->w << 8) | f->d);
}
static int
{
put_byte (buf, 2);
put_value_mod (buf, value, NULL);
- put_format (buf, &value->numeric.format);
+ put_format (buf, &value->numeric.format, value->numeric.honor_small);
put_double (buf, value->numeric.x);
put_string (buf, value->numeric.var_name);
put_string (buf, value->numeric.value_label);
{
put_byte (buf, 1);
put_value_mod (buf, value, NULL);
- put_format (buf, &value->numeric.format);
+ put_format (buf, &value->numeric.format, value->numeric.honor_small);
put_double (buf, value->numeric.x);
}
break;
put_byte (buf, 4);
put_value_mod (buf, value, NULL);
put_format (buf,
- &(struct fmt_spec) { FMT_A, strlen (value->string.s), 0 });
+ &(struct fmt_spec) { FMT_A, strlen (value->string.s), 0 },
+ false);
put_string (buf, value->string.value_label);
put_string (buf, value->string.var_name);
put_show_values (buf, value->string.show);
300 threehundred
end data.
+set small=0.
examine x
/statistics = extreme
/id = y
9 7 9 9 7
END DATA
+SET SMALL=0.
FACTOR /VARIABLES=TRAIT1 TO TRAIT5
/ROTATION=NOROTATE /* NOROTATE may have caused the problem. */
/EXTRACTION=PC
])
AT_DATA([stringcat.sps], [dnl
-set format=F20.3.
+set format=F20.3 /small=0.
data list notable file='lr-cat2.data' list /read honcomp wiz science *.
string ses(a1).
│ ┊c3 72│73┊74│75│76┊77│78│79┊80
])
AT_CLEANUP
+
+AT_SETUP([pivot table - small numbers])
+AT_DATA([pivot.txt], [[
+/title "small numbers"
+/row "exponent"*("0", "-1", "-2", "-3", "-4", "-5", "-6", "-7", "-8", "-9")
+/col "sign"*("positive", "negative")
+/col "result class"*("general" RC_OTHER, "specific" RC_RESIDUAL)
+/cell[0, 0, 0] = 1
+/cell[1, 0, 0] = .1
+/cell[2, 0, 0] = .01
+/cell[3, 0, 0] = .001
+/cell[4, 0, 0] = .0001
+/cell[5, 0, 0] = .00001
+/cell[6, 0, 0] = .000001
+/cell[7, 0, 0] = .0000001
+/cell[8, 0, 0] = .00000001
+/cell[9, 0, 0] = .000000001
+/cell[0, 0, 1] = -1
+/cell[1, 0, 1] = -.1
+/cell[2, 0, 1] = -.01
+/cell[3, 0, 1] = -.001
+/cell[4, 0, 1] = -.0001
+/cell[5, 0, 1] = -.00001
+/cell[6, 0, 1] = -.000001
+/cell[7, 0, 1] = -.0000001
+/cell[8, 0, 1] = -.00000001
+/cell[9, 0, 1] = -.000000001
+/cell[0, 1, 0] = 1
+/cell[1, 1, 0] = .1
+/cell[2, 1, 0] = .01
+/cell[3, 1, 0] = .001
+/cell[4, 1, 0] = .0001
+/cell[5, 1, 0] = .00001
+/cell[6, 1, 0] = .000001
+/cell[7, 1, 0] = .0000001
+/cell[8, 1, 0] = .00000001
+/cell[9, 1, 0] = .000000001
+/cell[0, 1, 1] = -1
+/cell[1, 1, 1] = -.1
+/cell[2, 1, 1] = -.01
+/cell[3, 1, 1] = -.001
+/cell[4, 1, 1] = -.0001
+/cell[5, 1, 1] = -.00001
+/cell[6, 1, 1] = -.000001
+/cell[7, 1, 1] = -.0000001
+/cell[8, 1, 1] = -.00000001
+/cell[9, 1, 1] = -.000000001
+]])
+AT_CHECK([pivot-table-test --table-look $srcdir/output/look.stt pivot.txt --box unicode], [0], [dnl
+small numbers
+╭────────┬─────────────────────────────────────╮
+│ │ result class │
+│ ├───────────────────┬─────────────────┤
+│ │ general │ specific │
+│ ├───────────────────┼─────────────────┤
+│ │ sign │ sign │
+│ ├─────────┬─────────┼────────┬────────┤
+│exponent│ positive│ negative│positive│negative│
+├────────┼─────────┼─────────┼────────┼────────┤
+│0 │ 1.00│ 1.00│ -1.00│ -1.00│
+│-1 │ .10│ .10│ -.10│ -.10│
+│-2 │ .01│ .01│ -.01│ -.01│
+│-3 │ .00│ .00│ .00│ .00│
+│-4 │ .00│ .00│ .00│ .00│
+│-5 │1.00E-005│1.00E-005│ .00│ .00│
+│-6 │1.00E-006│1.00E-006│ .00│ .00│
+│-7 │1.00E-007│1.00E-007│ .00│ .00│
+│-8 │1.00E-008│1.00E-008│ .00│ .00│
+│-9 │1.00E-009│1.00E-009│ .00│ .00│
+╰────────┴─────────┴─────────┴────────┴────────╯
+])
+AT_CLEANUP
\ No newline at end of file