Introduction
Introduction Statistics Contact Development Disclaimer Help
tuse safe formatting parameters and option parsing - numtools - perform numeric…
git clone git://src.adamsgaard.dk/numtools
Log
Files
Refs
README
LICENSE
---
commit 8787e852ca96ee9c18d4ed1a45016996e464940a
parent d206d176dbb5704fda2d5cc33010f54b8f36ff38
Author: Anders Damsgaard <[email protected]>
Date: Wed, 11 May 2022 14:57:18 +0200
use safe formatting parameters and option parsing
Diffstat:
M max.1 | 29 ++++++++++++++++-------------
M max.c | 45 ++++++++++++++++++-----------…
M mean.1 | 29 ++++++++++++++++-------------
M mean.c | 45 ++++++++++++++++++-----------…
M min.1 | 29 ++++++++++++++++-------------
M min.c | 45 ++++++++++++++++++-----------…
M randcounts.1 | 38 +++++++++++++++++++++++------…
M randcounts.c | 98 ++++++++++++++++++-----------…
M randnum.c | 8 ++++----
M range.1 | 61 ++++++++++++++++-------------…
M range.c | 107 ++++++++++++++++++-----------…
M rangetest.c | 40 +++++++++++++++--------------…
M stddev.1 | 27 +++++++++++++++------------
M stddev.c | 52 ++++++++++++++++++-----------…
M stdvar.1 | 29 ++++++++++++++++-------------
M stdvar.c | 52 ++++++++++++++++++-----------…
M sum.1 | 29 ++++++++++++++++-------------
M sum.c | 45 ++++++++++++++++++-----------…
M transpose.1 | 6 +++---
M util.c | 9 ++++-----
M util.h | 2 +-
21 files changed, 469 insertions(+), 356 deletions(-)
---
diff --git a/max.1 b/max.1
t@@ -6,8 +6,9 @@
.Nd returns the maximum value for each column
.Sh SYNOPSIS
.Nm
-.Op Fl f Ar fmtstr
-.Op Fl h
+.Op Fl d Ar delimstr
+.Op Fl n
+.Op Fl p Ar prec
.Sh DESCRIPTION
.Nm
returns the maximum numerical value for each column in standard
t@@ -17,20 +18,22 @@ the same number of fields.
.Pp
The options are as follows:
.Bl -tag -width Ds
-.It Fl f Ar fmtstr
-Formatting string to use as documented in
-.Xr printf 3 .
-When including a format specifier (%..), only use forms that are
-compatible with
-.Vt double
-types.
-The default format string is '%.17g'.
-.It Fl h
-Show usage information and exit.
+.It Fl d Ar delimstr
+Separate output values by
+.Ar delimstr .
+The default delimiter is tab characters.
+.It Fl n
+Do not print a newline after the final value.
+.It Fl p prec
+Print the output values with
+.Ar prec
+digits of precision.
+By default, the output is printed with 17 digits of precision, which is
+full double precision on 64-bit systems.
.El
.Sh EXAMPLES
.Dl $ printf '1\et2\et3\en4\et5\et6\en' | max
-.Dl 4 5 6
+.Dl 4 5 6
.Sh SEE ALSO
.Xr mean 1 ,
.Xr min 1 ,
diff --git a/max.c b/max.c
t@@ -4,40 +4,45 @@
#include <unistd.h>
#include <limits.h>
-#include "arg.h"
#include "util.h"
-char *argv0;
-
static void
usage(void)
{
- errx(1, "usage: %s [-f fmtstr] [-h] ", argv0);
+ errx(1, "usage: max [-d delimstr] [-n] [-p prec]");
}
int
main(int argc, char *argv[])
{
- int ret;
+ int ch, prec = 17, finalnl = 1;
size_t i = 0, nf = 0, nr = 0, linesize = 0;
- char *line = NULL, *data = NULL, fmtstr[PATH_MAX] = "%.17g";
+ char *line = NULL, *data = NULL, *delimstr = "\t";
+ const char *errstr;
double val, *vals = NULL;
if (pledge("stdio", NULL) == -1)
err(2, "pledge");
- ARGBEGIN {
- case 'f':
- ret = snprintf(fmtstr, sizeof(fmtstr), "%s", EARGF(usage()));
- if (ret < 0 || (size_t)ret >= sizeof(fmtstr))
- errx(1, "%s: could not write fmtstr", __func__);
- break;
- case 'h':
- usage();
- break;
- default:
- usage();
- } ARGEND;
+ while ((ch = getopt(argc, argv, "d:np:")) != -1) {
+ switch (ch) {
+ case 'd':
+ delimstr = optarg;
+ break;
+ case 'n':
+ finalnl = 0;
+ break;
+ case 'p':
+ prec = strtonum(optarg, 0, INT_MAX, &errstr);
+ if (errstr != NULL)
+ errx(1, "bad precision value, %s: %s", errstr,…
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ /*argv += optind;*/
if (argc > 0)
usage();
t@@ -54,7 +59,9 @@ main(int argc, char *argv[])
}
nr++;
}
- printfarr(fmtstr, vals, nf);
+ printfarr(delimstr, prec, vals, nf);
+ if (finalnl)
+ putchar('\n');
free(line);
free(vals);
diff --git a/mean.1 b/mean.1
t@@ -6,8 +6,9 @@
.Nd returns the average value for each column
.Sh SYNOPSIS
.Nm
-.Op Fl f Ar fmtstr
-.Op Fl h
+.Op Fl d Ar delimstr
+.Op Fl n
+.Op Fl p Ar prec
.Sh DESCRIPTION
.Nm
returns the mean numerical value for each column in standard input.
t@@ -16,20 +17,22 @@ number of fields.
.Pp
The options are as follows:
.Bl -tag -width Ds
-.It Fl f Ar fmtstr
-Formatting string to use as documented in
-.Xr printf 3 .
-When including a format specifier (%..), only use forms that are
-compatible with
-.Vt double
-types.
-The default format string is '%.17g'.
-.It Fl h
-Show usage information and exit.
+.It Fl d Ar delimstr
+Separate output values by
+.Ar delimstr .
+The default delimiter is tab characters.
+.It Fl n
+Do not print a newline after the final value.
+.It Fl p prec
+Print the output values with
+.Ar prec
+digits of precision.
+By default, the output is printed with 17 digits of precision, which is
+full double precision on 64-bit systems.
.El
.Sh EXAMPLES
.Dl $ printf '1\et2\et3\en4\et5\et6\en' | mean
-.Dl 2.5 3.5 4.5
+.Dl 2.5 3.5 4.5
.Sh SEE ALSO
.Xr max 1 ,
.Xr min 1 ,
diff --git a/mean.c b/mean.c
t@@ -4,40 +4,45 @@
#include <unistd.h>
#include <limits.h>
-#include "arg.h"
#include "util.h"
-char *argv0;
-
static void
usage(void)
{
- errx(1, "usage: %s [-f fmtstr] [-h] ", argv0);
+ errx(1, "usage: mean [-d delimstr] [-n] [-p prec]");
}
int
main(int argc, char *argv[])
{
- int ret;
+ int ch, prec = 17, finalnl = 1;
size_t i = 0, nf = 0, nr = 0, linesize = 0;
- char *line = NULL, *data = NULL, fmtstr[PATH_MAX] = "%.17g";
+ char *line = NULL, *data = NULL, *delimstr = "\t";
+ const char *errstr;
double val, *vals = NULL;
if (pledge("stdio", NULL) == -1)
err(2, "pledge");
- ARGBEGIN {
- case 'f':
- ret = snprintf(fmtstr, sizeof(fmtstr), "%s", EARGF(usage()));
- if (ret < 0 || (size_t)ret >= sizeof(fmtstr))
- errx(1, "%s: could not write fmtstr", __func__);
- break;
- case 'h':
- usage();
- break;
- default:
- usage();
- } ARGEND;
+ while ((ch = getopt(argc, argv, "d:np:")) != -1) {
+ switch (ch) {
+ case 'd':
+ delimstr = optarg;
+ break;
+ case 'n':
+ finalnl = 0;
+ break;
+ case 'p':
+ prec = strtonum(optarg, 0, INT_MAX, &errstr);
+ if (errstr != NULL)
+ errx(1, "bad precision value, %s: %s", errstr,…
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ /*argv += optind;*/
if (argc > 0)
usage();
t@@ -57,7 +62,9 @@ main(int argc, char *argv[])
}
for (i = 0; i < nf; i++)
vals[i] /= (double)nr;
- printfarr(fmtstr, vals, nf);
+ printfarr(delimstr, prec, vals, nf);
+ if (finalnl)
+ putchar('\n');
free(line);
free(vals);
diff --git a/min.1 b/min.1
t@@ -6,8 +6,9 @@
.Nd returns the minimum value for each column
.Sh SYNOPSIS
.Nm
-.Op Fl f Ar fmtstr
-.Op Fl h
+.Op Fl d Ar delimstr
+.Op Fl n
+.Op Fl p Ar prec
.Sh DESCRIPTION
.Nm
returns the minimum numerical value for each column in standard
t@@ -17,20 +18,22 @@ number of fields.
.Pp
The options are as follows:
.Bl -tag -width Ds
-.It Fl f Ar fmtstr
-Formatting string to use as documented in
-.Xr printf 3 .
-When including a format specifier (%..), only use forms that are
-compatible with
-.Vt double
-types.
-The default format string is '%.17g'.
-.It Fl h
-Show usage information and exit.
+.It Fl d Ar delimstr
+Separate output values by
+.Ar delimstr .
+The default delimiter is tab characters.
+.It Fl n
+Do not print a newline after the final value.
+.It Fl p prec
+Print the output values with
+.Ar prec
+digits of precision.
+By default, the output is printed with 17 digits of precision, which is
+full double precision on 64-bit systems.
.El
.Sh EXAMPLES
.Dl $ printf '1\et2\et3\en4\et5\et6\en' | min
-.Dl 1 2 3
+.Dl 1 2 3
.Sh SEE ALSO
.Xr max 1 ,
.Xr mean 1 ,
diff --git a/min.c b/min.c
t@@ -4,40 +4,45 @@
#include <unistd.h>
#include <limits.h>
-#include "arg.h"
#include "util.h"
-char *argv0;
-
static void
usage(void)
{
- errx(1, "usage: %s [-f fmtstr] [-h] ", argv0);
+ errx(1, "usage: max [-d delimstr] [-n] [-p prec]");
}
int
main(int argc, char *argv[])
{
- int ret;
+ int ch, prec = 17, finalnl = 1;
size_t i = 0, nf = 0, nr = 0, linesize = 0;
- char *line = NULL, *data = NULL, fmtstr[PATH_MAX] = "%.17g";
+ char *line = NULL, *data = NULL, *delimstr = "\t";
+ const char *errstr;
double val, *vals = NULL;
if (pledge("stdio", NULL) == -1)
err(2, "pledge");
- ARGBEGIN {
- case 'f':
- ret = snprintf(fmtstr, sizeof(fmtstr), "%s", EARGF(usage()));
- if (ret < 0 || (size_t)ret >= sizeof(fmtstr))
- errx(1, "%s: could not write fmtstr", __func__);
- break;
- case 'h':
- usage();
- break;
- default:
- usage();
- } ARGEND;
+ while ((ch = getopt(argc, argv, "d:np:")) != -1) {
+ switch (ch) {
+ case 'd':
+ delimstr = optarg;
+ break;
+ case 'n':
+ finalnl = 0;
+ break;
+ case 'p':
+ prec = strtonum(optarg, -10, INT_MAX, &errstr);
+ if (errstr != NULL)
+ errx(1, "bad precision value, %s: %s", errstr,…
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ /*argv += optind;*/
if (argc > 0)
usage();
t@@ -54,7 +59,9 @@ main(int argc, char *argv[])
}
nr++;
}
- printfarr(fmtstr, vals, nf);
+ printfarr(delimstr, prec, vals, nf);
+ if (finalnl)
+ putchar('\n');
free(line);
free(vals);
diff --git a/randcounts.1 b/randcounts.1
t@@ -6,8 +6,10 @@
.Nd produces random counts in weighted bins
.Sh SYNOPSIS
.Nm
-.Op Fl h
-.Op Fl n Ar num
+.Op Fl d Ar delimstr
+.Op Fl n
+.Op Fl N Ar num
+.Op Fl p Ar prec
.Op Fl r Ar repeats
.Op Fl R
.Op Fl s Ar seed
t@@ -31,15 +33,28 @@ Output consists of the number of points per bin, in tab-se…
.Pp
The options are as follows:
.Bl -tag -width Ds
-.It Fl h
-Show usage information.
-.It Fl n Ar num
+.It Fl d Ar delimstr
+Separate output values by
+.Ar delimstr .
+The default delimiter is tab characters.
+.It Fl n
+Do not print a newline after the final value.
+.It Fl N Ar num
Number of points to place in the bins.
The default is 1.
.It Fl r Ar repeats
Repeat the binning several times, with one realization per line of output.
.It Fl R
Show the output as ratios (in the range [0;1]) instead of counts.
+.It Fl p prec
+Print the output values with
+.Ar prec
+digits of precision.
+This option only applies if called with the
+.Fl R
+option.
+By default, the output is printed with 17 digits of precision, which is
+full double precision on 64-bit systems.
.It Fl s Ar seed
Seed the pseudo-random number generator with this value, which is used
to generate reproducable binning.
t@@ -48,15 +63,18 @@ to generate reproducable binning.
Put one point in four bins with equal probability (25%).
Due to the randomness, your output may differ:
.Dl $ randcounts 0.25 0.25 0.25 0.25
-.Dl 0 1 0 0
+.Dl 0 1 0 0
.Pp
-Put 100 points in two bins with 75% and 25% probability, respectively:
-.Dl $ randcounts -n 100 0.75 0.25
+Put 100 points in two bins with 75% and 25% probability, respectively,
+and print the count ratios for each bin:
+.Dl $ randcounts -N 100 -R 0.75 0.25
+.Dl 0.72999999999999998 0.27000000000000002
.Pp
-Put 100 points in three equal bins 1000 times, and calculate the average bin s…
+Put 100 points in three equal bins 1000 times, and calculate the average
+bin sizes with
.Xr mean 1 :
.Dl $ randcounts -n 100 -r 1000 0.333 0.333 0.334 | mean
-.Dl 33.067 32.82 34.113
+.Dl 33.067 32.82 34.113
.Sh SEE ALSO
.Xr mean 1 ,
.Xr range 1 ,
diff --git a/randcounts.c b/randcounts.c
t@@ -5,68 +5,85 @@
#include <string.h>
#include <math.h>
#include <sys/time.h>
+#include <unistd.h>
-#include "arg.h"
#include "util.h"
-char *argv0;
-
static void
usage(void)
{
- errx(1, "usage: %s [-h] [-n num] [-r repeats] [-R] [-s seed] "
- "weight1 [weight2 ...]\n", argv0);
+ errx(1, "usage: randcounts [-d delimstr] [-n] [-N num] [-p prec]"
+ "[-r repeats] [-R] [-s seed] weight1 [weight2 ...]");
}
int
main(int argc, char *argv[])
{
- int i, s = 0, N;
+ int i, ch, nbins, prec = 17, finalnl = 1, s = 0;
long j, seed, *counts = NULL, n = 1, r, repeats = 1, ratio = 0;
double val = 0.0, weightsum = 0.0, *weights = NULL;
+ char *delimstr = "\t";
+ const char *errstr;
struct timeval t1;
if (pledge("stdio", NULL) == -1)
err(2, "pledge");
- ARGBEGIN {
- case 'h':
- usage();
- break;
- case 'n':
- n = atol(EARGF(usage()));
- break;
- case 'r':
- repeats = atol(EARGF(usage()));
- break;
- case 'R':
- ratio = 1;
- break;
- case 's':
- s = 1;
- seed = atol(EARGF(usage()));
- break;
- default:
- usage();
- } ARGEND;
-
+ while ((ch = getopt(argc, argv, "d:nN:r:Rp:s:")) != -1) {
+ switch (ch) {
+ case 'd':
+ delimstr = optarg;
+ break;
+ case 'n':
+ finalnl = 0;
+ break;
+ case 'N':
+ n = strtonum(optarg, 0, LONG_MAX, &errstr);
+ if (errstr != NULL)
+ errx(1, "bad num value, %s: %s", errstr, optar…
+ break;
+ case 'r':
+ repeats = strtonum(optarg, 0, LONG_MAX, &errstr);
+ if (errstr != NULL)
+ errx(1, "bad repeats value, %s: %s", errstr, o…
+ break;
+ case 'R':
+ ratio = 1;
+ break;
+ case 'p':
+ prec = strtonum(optarg, 0, INT_MAX, &errstr);
+ if (errstr != NULL)
+ errx(1, "bad precision value, %s: %s", errstr,…
+ break;
+ case 's':
+ seed = strtonum(optarg, 0, INT_MAX, &errstr);
+ if (errstr != NULL)
+ errx(1, "bad seed value, %s: %s", errstr, opta…
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
if (argc < 1)
usage();
- N = argc;
- if (!(weights = calloc(N, sizeof(double))) ||
- !(counts = calloc(N, sizeof(long))))
+ nbins = argc;
+ if (!(weights = calloc(nbins, sizeof(double))) ||
+ !(counts = calloc(nbins, sizeof(long))))
err(1, "calloc");
- for (i = 0; i < N; i++) {
- weights[i] = atof(argv[i]);
+ for (i = 0; i < nbins; i++) {
+ if (!sscanf(argv[i], "%lf", &weights[i]))
+ errx(1, "bad weight value: %s", argv[i]);
if (weights[i] <= 0.0)
errx(1, "weight %d is not positive (%g)", i, weights[i…
if (weights[i] > 1.0)
errx(1, "weight %d is greater than 1 (%g)", i, weights…
}
- for (i = 0; i < N; i++)
+ for (i = 0; i < nbins; i++)
weightsum += weights[i];
if (fabs(weightsum - 1.0) > 1e-3)
errx(1, "weights do not sum to 1 (%g)", weightsum);
t@@ -83,12 +100,12 @@ main(int argc, char *argv[])
#endif
for (r = 0; r < repeats; r++) {
- for (i = 0; i < N; i++)
+ for (i = 0; i < nbins; i++)
counts[i] = 0;
for (j = 0; j < n; j++) {
val = drand48();
weightsum = 0.0;
- for (i = 0; i < N; i++) {
+ for (i = 0; i < nbins; i++) {
weightsum += weights[i];
if (val <= weightsum) {
counts[i]++;
t@@ -96,15 +113,16 @@ main(int argc, char *argv[])
}
}
}
- for (i = 0; i < N; i++) {
+ for (i = 0; i < nbins; i++) {
if (ratio)
- printf("%.17g", (double)counts[i] / n);
+ printf("%.*g", prec, (double)counts[i] / n);
else
printf("%ld", counts[i]);
- if (i < N - 1)
- putchar('\t');
+ if (i < nbins - 1)
+ fputs(delimstr, stdout);
else
- putchar('\n');
+ if (finalnl)
+ putchar('\n');
}
}
diff --git a/randnum.c b/randnum.c
t@@ -20,9 +20,9 @@ usage(void)
int
main(int argc, char *argv[])
{
- int i, ret, ch, s = 0, prec = 17, finalnl = 1;
- long j, seed, n = 1;
- double val, minv = 0.0, maxv = 1.0;
+ int i, ch, s = 0, prec = 17, finalnl = 1;
+ long seed, n = 1;
+ double minv = 0.0, maxv = 1.0;
char *delimstr = "\n";
const char *errstr;
struct timeval t1;
t@@ -44,7 +44,7 @@ main(int argc, char *argv[])
errx(1, "bad num value, %s: %s", errstr, optar…
break;
case 'p':
- prec = strtonum(optarg, -10, INT_MAX, &errstr);
+ prec = strtonum(optarg, 0, INT_MAX, &errstr);
if (errstr != NULL)
errx(1, "bad precision value, %s: %s", errstr,…
break;
diff --git a/range.1 b/range.1
t@@ -7,11 +7,12 @@
.Sh SYNOPSIS
.Nm
.Op Fl b
+.Op Fl d Ar delimstr
.Op Fl e
-.Op Fl f Ar fmtstr
-.Op Fl h
.Op Fl l
-.Op Fl n Ar num
+.Op Fl n
+.Op Fl N Ar num
+.Op Fl p Ar prec
.Op Fl s
.Oo
.Op Ar min_val
t@@ -45,6 +46,10 @@ as the first value, making it a half-open interval
.Ar max_val ],
or an entirely open interval when combined with
.Op Ar e .
+.It Fl d Ar delimstr
+Separate output values by
+.Ar delimstr .
+The default delimiter is newlines.
.It Fl e
Do not include
.Ar max_val
t@@ -53,54 +58,50 @@ as the last value, making it a half-open interval
.Ar max_val [,
or an entirely open interval when combined with
.Op Ar b .
-.It Fl f Ar fmtstr
-Formatting string to use as documented in
-.Xr printf 3 .
-When including a format specifier (%..), only use forms that are
-compatible with
-.Vt double
-types.
-The default format string is '%.17g'.
-.It Fl h
-Show usage information.
.It Fl l
Produce output with even intervals in logarithmic space between 10^min_val
and 10^max_val.
-.It Fl n Ar num
+.It Fl n
+Do not print a newline after the final value.
+.It Fl N Ar num
Number of values to produce within the specified range.
The default is 10.
+.It Fl p prec
+Print the output values with
+.Ar prec
+digits of precision.
+By default, the output is printed with 17 digits of precision, which is
+full double precision on 64-bit systems.
.It Fl s
-Print the spacing between numbers and exit.
+Print the numerical spacing between numbers and exit.
.El
.Sh EXAMPLES
Generate four equally-spaced numbers in the closed default range [0;1]:
-.Dl $ range -n 4 -f '%.17g\en' 0 1
+.Dl $ range -N 4
.Dl 0
.Dl 0.33333333333333331
.Dl 0.66666666666666663
.Dl 1
.Pp
Generate four numbers in the range ]0;1[:
-.Dl $ range -b -e -n 4 0 1
-.Dl 0.2
-.Dl 0.4
-.Dl 0.6
-.Dl 0.8
+.Dl $ range -be -N 4
+.Dl 0.20000000000000001
+.Dl 0.40000000000000002
+.Dl 0.60000000000000009
+.Dl 0.80000000000000004
.Pp
-Repeat and modify a string three times:
-.Dl $ range -n 3 -f 'The best number is %.0g' 1 3
-.Dl The best number is 1
-.Dl The best number is 2
-.Dl The best number is 3
+Generate three space-separated numbers:
+.Dl $ range -d' ' -N 3 1 3
+.Dl 1 2 3
.Pp
Generate three numbers evenly distributed in logspace from 10^0 to 10^2:
-.Dl $ range -l -n 3 0 2
+.Dl $ range -l -N 3 0 2
.Dl 1
.Dl 10
.Dl 100
.Pp
Generate three numbers in the range [-2;-1]:
-.Dl $ range -n 3 -- -2 -1
+.Dl $ range -N 3 -- -2 -1
.Dl -2
.Dl -1.5
.Dl -1
t@@ -108,7 +109,7 @@ Generate three numbers in the range [-2;-1]:
.Xr max 1 ,
.Xr mean 1 ,
.Xr min 1 ,
-.Xr rangetest 1 ,
-.Xr sum 1
+.Xr randnum 1 ,
+.Xr rangetest 1
.Sh AUTHORS
.An Anders Damsgaard Aq Mt [email protected]
diff --git a/range.c b/range.c
t@@ -4,78 +4,95 @@
#include <limits.h>
#include <string.h>
#include <math.h>
+#include <unistd.h>
-#include "arg.h"
#include "util.h"
-char *argv0;
-
static void
usage(void)
{
- errx(1, "usage: %s [-b] [-e] [-f fmtstr] [-h] [-l] [-n num] [-s] "
- "[[min_val] max_val]\n", argv0);
+ errx(1, "usage: range [-b] [-d delimstr] [-e] [-l] [-n] [-N num] "
+ "[-p prec] [-s] [[min_val] max_val]");
}
int
main(int argc, char *argv[])
{
- int i, ret, n = 10, logrange = 0, openstart = 0, openend = 0,
- reportdx = 0;
- double minv = 0.0, maxv = 1.0, dx;
- char fmtstr[PATH_MAX] = "%.17g";
+ int i, j, ch, n = 10, logrange = 0, openstart = 0, openend = 0,
+ prec = 17, finalnl = 1, reportdx = 0;
+ double minv = 0.0, maxv = 1.0, dx, val;
+ const char *errstr;
+ char *delimstr = "\n";
if (pledge("stdio", NULL) == -1)
err(2, "pledge");
- ARGBEGIN {
- case 'b':
- openstart = 1;
- break;
- case 'e':
- openend = 1;
- break;
- case 'f':
- ret = snprintf(fmtstr, sizeof(fmtstr), "%s", EARGF(usage()));
- if (ret < 0 || (size_t)ret >= sizeof(fmtstr))
- errx(1, "%s: could not write fmtstr", __func__);
- break;
- case 'h':
- usage();
- break;
- case 'l':
- logrange = 1;
- break;
- case 'n':
- n = atoi(EARGF(usage()));
- break;
- case 's':
- reportdx = 1;
- break;
- default:
- usage();
- } ARGEND;
-
+ while ((ch = getopt(argc, argv, "bd:elnN:p:s")) != -1) {
+ switch (ch) {
+ case 'b':
+ openstart = 1;
+ break;
+ case 'd':
+ delimstr = optarg;
+ break;
+ case 'e':
+ openend = 1;
+ break;
+ case 'l':
+ logrange = 1;
+ break;
+ case 'n':
+ finalnl = 0;
+ break;
+ case 'N':
+ n = strtonum(optarg, 0, LONG_MAX, &errstr);
+ if (errstr != NULL)
+ errx(1, "bad num value, %s: %s", errstr, optar…
+ break;
+ case 'p':
+ prec = strtonum(optarg, -10, INT_MAX, &errstr);
+ if (errstr != NULL)
+ errx(1, "bad precision value, %s: %s", errstr,…
+ break;
+ case 's':
+ reportdx = 1;
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
if (argc > 2)
usage();
else if (argc == 2) {
- minv = atof(argv[0]);
- maxv = atof(argv[1]);
+ if (!sscanf(argv[0], "%lf", &minv))
+ errx(1, "bad minv value: %s", argv[0]);
+ if (!sscanf(argv[1], "%lf", &maxv))
+ errx(1, "bad maxv value: %s", argv[1]);
} else if (argc == 1)
- maxv = atof(argv[0]);
+ if (!sscanf(argv[0], "%lf", &maxv))
+ errx(1, "bad maxv value: %s", argv[0]);
dx = (maxv - minv) / (n - 1 + openend + openstart);
if (reportdx) {
- printf(fmtstr, dx);
+ printf("%.*g", prec, dx);
+ if (finalnl)
+ putchar('\n');
return 0;
}
- for (i = 0 + openstart; i < n + openstart; i++) {
+ for (i = 0; i < n; i++) {
+ j = i + openstart;
if (logrange)
- printf(fmtstr, pow(10, minv + i * dx));
+ val = pow(10, minv + j * dx);
else
- printf(fmtstr, minv + i * dx);
- putchar('\n');
+ val = minv + j * dx;
+ printf("%.*g", prec, val);
+ if (i < n - 1)
+ fputs(delimstr, stdout);
}
+ if (finalnl)
+ putchar('\n');
return 0;
}
diff --git a/rangetest.c b/rangetest.c
t@@ -3,19 +3,17 @@
#include <err.h>
#include <limits.h>
#include <string.h>
+#include <unistd.h>
-#include "arg.h"
#include "util.h"
#define VALUESTR "@VAL@"
-char *argv0;
-
static void
usage(void)
{
- errx(1, "usage: %s [-h] [-n maxiter] cmd min_val max_val\n"
- "where cmd must contain the string '" VALUESTR "'", argv0);
+ errx(1, "usage: rangetest [-n maxiter] cmd min_val max_val\n"
+ "where cmd must contain the string '" VALUESTR "'");
}
static int
t@@ -41,8 +39,7 @@ launch(char *cmd, char *cmd0, double val)
static void
binary_search(char *cmd, char *cmd0, double minv, double maxv, int maxiter)
{
- int minfail, maxfail;
- int iter = 0;
+ int minfail, maxfail, iter = 0;
double val;
minfail = launch(cmd, cmd0, minv);
t@@ -76,23 +73,24 @@ binary_search(char *cmd, char *cmd0, double minv, double m…
int
main(int argc, char *argv[])
{
- int maxiter = 10;
+ int ch, maxiter = 10;
double minv, maxv;
char cmd0[PATH_MAX] = "", cmd[PATH_MAX] = "";
+ const char *errstr;
- ARGBEGIN {
- case 'h':
- usage();
- break;
- case 'n':
- maxiter = atoi(EARGF(usage()));
- if (maxiter < 1)
- errx(1, "maxiter (-n) must be positive");
- break;
- default:
- usage();
- } ARGEND;
-
+ while ((ch = getopt(argc, argv, "N:")) != -1) {
+ switch (ch) {
+ case 'N':
+ maxiter = strtonum(optarg, 0, INT_MAX, &errstr);
+ if (errstr != NULL)
+ errx(1, "bad maxiter value, %s: %s", errstr, o…
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
if (argc == 3) {
if (strlcpy(cmd0, argv[0], sizeof(cmd0)) >= sizeof(cmd0))
err(1, "cmd too long");
diff --git a/stddev.1 b/stddev.1
t@@ -6,8 +6,9 @@
.Nd returns the standard deviation for each input column
.Sh SYNOPSIS
.Nm
-.Op Fl f Ar fmtstr
-.Op Fl h
+.Op Fl d Ar delimstr
+.Op Fl n
+.Op Fl p Ar prec
.Op Fl u
.Sh DESCRIPTION
.Nm
t@@ -19,16 +20,18 @@ The output is always in full double precision.
.Pp
The options are as follows:
.Bl -tag -width Ds
-.It Fl f Ar fmtstr
-Formatting string to use as documented in
-.Xr printf 3 .
-When including a format specifier (%..), only use forms that are
-compatible with
-.Vt double
-types.
-The default format string is '%.17g'.
-.It Fl h
-Show usage information and exit.
+.It Fl d Ar delimstr
+Separate output values by
+.Ar delimstr .
+The default delimiter is tab characters.
+.It Fl n
+Do not print a newline after the final value.
+.It Fl p prec
+Print the output values with
+.Ar prec
+digits of precision.
+By default, the output is printed with 17 digits of precision, which is
+full double precision on 64-bit systems.
.It Fl u
Return the uncorrected sample standard deviation instead.
.El
diff --git a/stddev.c b/stddev.c
t@@ -4,44 +4,50 @@
#include <unistd.h>
#include <math.h>
#include <limits.h>
+#include <unistd.h>
-#include "arg.h"
#include "util.h"
-char *argv0;
-
static void
usage(void)
{
- errx(1, "usage: %s [-f fmtstr] [-h] [-u]\n", argv0);
+ errx(1, "usage: stddev [-d delimstr] [-n] [-p prec] [-u]");
}
int
main(int argc, char *argv[])
{
- int ret;
+ int ch, prec = 17, finalnl = 1;
size_t i, j, nf = 0, nr = 0, correction = 1;
double *means = NULL, *stdvals = NULL, **vals = NULL;
- char fmtstr[PATH_MAX] = "%.17g";
+ const char *errstr;
+ char *delimstr = "\t";
if (pledge("stdio", NULL) == -1)
err(2, "pledge");
- ARGBEGIN {
- case 'f':
- ret = snprintf(fmtstr, sizeof(fmtstr), "%s", EARGF(usage()));
- if (ret < 0 || (size_t)ret >= sizeof(fmtstr))
- errx(1, "%s: could not write fmtstr", __func__);
- break;
- case 'h':
- usage();
- break;
- case 'u':
- correction = 0;
- break;
- default:
- usage();
- } ARGEND;
+ while ((ch = getopt(argc, argv, "d:np:u")) != -1) {
+ switch (ch) {
+ case 'd':
+ delimstr = optarg;
+ break;
+ case 'n':
+ finalnl = 0;
+ break;
+ case 'p':
+ prec = strtonum(optarg, -10, INT_MAX, &errstr);
+ if (errstr != NULL)
+ errx(1, "bad precision value, %s: %s", errstr,…
+ break;
+ case 'u':
+ correction = 0;
+ break;
+ default:
+ usage();
+ }
+ }
+ /*argc -= optind;*/
+ /*argv += optind;*/
nr = fscanmatrix(stdin, &vals, &nf);
t@@ -63,7 +69,9 @@ main(int argc, char *argv[])
stdvals[i] = sqrt(stdvals[i] / ((double)(nr - correction)));
}
- printfarr(fmtstr, stdvals, nf);
+ printfarr(delimstr, prec, stdvals, nf);
+ if (finalnl)
+ putchar('\n');
free(means);
free(stdvals);
diff --git a/stdvar.1 b/stdvar.1
t@@ -6,8 +6,9 @@
.Nd returns the standard variance for each input column
.Sh SYNOPSIS
.Nm
-.Op Fl f Ar fmtstr
-.Op Fl h
+.Op Fl d Ar delimstr
+.Op Fl n
+.Op Fl p Ar prec
.Op Fl u
.Sh DESCRIPTION
.Nm
t@@ -19,18 +20,20 @@ The output is always in full double precision.
.Pp
The options are as follows:
.Bl -tag -width Ds
-.It Fl f Ar fmtstr
-Formatting string to use as documented in
-.Xr printf 3 .
-When including a format specifier (%..), only use forms that are
-compatible with
-.Vt double
-types.
-The default format string is '%.17g'.
-.It Fl h
-Show usage information and exit.
+.It Fl d Ar delimstr
+Separate output values by
+.Ar delimstr .
+The default delimiter is tab characters.
+.It Fl n
+Do not print a newline after the final value.
+.It Fl p prec
+Print the output values with
+.Ar prec
+digits of precision.
+By default, the output is printed with 17 digits of precision, which is
+full double precision on 64-bit systems.
.It Fl u
-Return the uncorrected sample standard variance instead.
+Return the uncorrected sample standard deviation instead.
.El
.Sh EXAMPLES
Compute the corrected standard variance for some input numbers:
diff --git a/stdvar.c b/stdvar.c
t@@ -4,44 +4,50 @@
#include <unistd.h>
#include <math.h>
#include <limits.h>
+#include <unistd.h>
-#include "arg.h"
#include "util.h"
-char *argv0;
-
static void
usage(void)
{
- errx(1, "usage: %s [-f fmtstr] [-h] [-u]\n", argv0);
+ errx(1, "usage: stdvar [-d delimstr] [-n] [-p prec] [-u]");
}
int
main(int argc, char *argv[])
{
- int ret;
+ int ch, prec = 17, finalnl = 1;
size_t i, j, nf = 0, nr = 0, correction = 1;
double *means = NULL, *stdvars = NULL, **vals = NULL;
- char fmtstr[PATH_MAX] = "%.17g";
+ const char *errstr;
+ char *delimstr = "\t";
if (pledge("stdio", NULL) == -1)
err(2, "pledge");
- ARGBEGIN {
- case 'f':
- ret = snprintf(fmtstr, sizeof(fmtstr), "%s", EARGF(usage()));
- if (ret < 0 || (size_t)ret >= sizeof(fmtstr))
- errx(1, "%s: could not write fmtstr", __func__);
- break;
- case 'h':
- usage();
- break;
- case 'u':
- correction = 0;
- break;
- default:
- usage();
- } ARGEND;
+ while ((ch = getopt(argc, argv, "d:np:u")) != -1) {
+ switch (ch) {
+ case 'd':
+ delimstr = optarg;
+ break;
+ case 'n':
+ finalnl = 0;
+ break;
+ case 'p':
+ prec = strtonum(optarg, -10, INT_MAX, &errstr);
+ if (errstr != NULL)
+ errx(1, "bad precision value, %s: %s", errstr,…
+ break;
+ case 'u':
+ correction = 0;
+ break;
+ default:
+ usage();
+ }
+ }
+ /*argc -= optind;*/
+ /*argv += optind;*/
nr = fscanmatrix(stdin, &vals, &nf);
t@@ -63,7 +69,9 @@ main(int argc, char *argv[])
stdvars[i] /= (double)(nr - correction);
}
- printfarr(fmtstr, stdvars, nf);
+ printfarr(delimstr, prec, stdvars, nf);
+ if (finalnl)
+ putchar('\n');
free(means);
free(stdvars);
diff --git a/sum.1 b/sum.1
t@@ -6,8 +6,9 @@
.Nd returns the sum for each column
.Sh SYNOPSIS
.Nm
-.Op Fl f Ar fmtstr
-.Op Fl h
+.Op Fl d Ar delimstr
+.Op Fl n
+.Op Fl p Ar prec
.Sh DESCRIPTION
.Nm
returns the numerical sum for each column in standard input.
t@@ -16,20 +17,22 @@ same number of fields.
.Pp
The options are as follows:
.Bl -tag -width Ds
-.It Fl f Ar fmtstr
-Formatting string to use as documented in
-.Xr printf 3 .
-When including a format specifier (%..), only use forms that are
-compatible with
-.Vt double
-types.
-The default format string is '%.17g'.
-.It Fl h
-Show usage information and exit.
+.It Fl d Ar delimstr
+Separate output values by
+.Ar delimstr .
+The default delimiter is tab characters.
+.It Fl n
+Do not print a newline after the final value.
+.It Fl p prec
+Print the output values with
+.Ar prec
+digits of precision.
+By default, the output is printed with 17 digits of precision, which is
+full double precision on 64-bit systems.
.El
.Sh EXAMPLES
.Dl $ printf '1\et2\et3\en4\et5\et6\en' | sum
-.Dl 5 7 9
+.Dl 5 7 9
.Sh SEE ALSO
.Xr max 1 ,
.Xr mean 1 ,
diff --git a/sum.c b/sum.c
t@@ -4,40 +4,45 @@
#include <unistd.h>
#include <limits.h>
-#include "arg.h"
#include "util.h"
-char *argv0;
-
static void
usage(void)
{
- errx(1, "usage: %s [-f fmtstr] [-h] ", argv0);
+ errx(1, "usage: sum [-d delimstr] [-n] [-p prec]");
}
int
main(int argc, char *argv[])
{
- int ret;
+ int ch, prec = 17, finalnl = 1;
size_t i = 0, nf = 0, nr = 0, linesize = 0;
- char *line = NULL, *data = NULL, fmtstr[PATH_MAX] = "%.17g";
+ char *line = NULL, *data = NULL, *delimstr = "\t";
+ const char *errstr;
double val, *vals = NULL;
if (pledge("stdio", NULL) == -1)
err(2, "pledge");
- ARGBEGIN {
- case 'f':
- ret = snprintf(fmtstr, sizeof(fmtstr), "%s", EARGF(usage()));
- if (ret < 0 || (size_t)ret >= sizeof(fmtstr))
- errx(1, "%s: could not write fmtstr", __func__);
- break;
- case 'h':
- usage();
- break;
- default:
- usage();
- } ARGEND;
+ while ((ch = getopt(argc, argv, "d:np:")) != -1) {
+ switch (ch) {
+ case 'd':
+ delimstr = optarg;
+ break;
+ case 'n':
+ finalnl = 0;
+ break;
+ case 'p':
+ prec = strtonum(optarg, 0, INT_MAX, &errstr);
+ if (errstr != NULL)
+ errx(1, "bad precision value, %s: %s", errstr,…
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ /*argv += optind;*/
if (argc > 0)
usage();
t@@ -55,7 +60,9 @@ main(int argc, char *argv[])
}
nr++;
}
- printfarr(fmtstr, vals, nf);
+ printfarr(delimstr, prec, vals, nf);
+ if (finalnl)
+ putchar('\n');
free(line);
free(vals);
diff --git a/transpose.1 b/transpose.1
t@@ -16,9 +16,9 @@ Input fields must be tab-separated and each line must contai…
same number of fields.
.Sh EXAMPLES
.Dl $ printf '1\et2\et3\en4\et5\et6\en' | transpose
-.Dl 1 4
-.Dl 2 5
-.Dl 3 6
+.Dl 1 4
+.Dl 2 5
+.Dl 3 6
.Sh SEE ALSO
.Xr max 1 ,
.Xr mean 1 ,
diff --git a/util.c b/util.c
t@@ -45,16 +45,15 @@ printarr(double *arr, size_t len)
}
void
-printfarr(char *fmtstr, double *arr, size_t len)
+printfarr(char *delimstr, int prec, double *arr, size_t len)
{
size_t i;
for (i = 0; i < len; i++) {
- printf(fmtstr, arr[i]);
- if (i < len)
- printf(DELIMSTR);
+ printf("%.*g", prec, arr[i]);
+ if (i < len - 1)
+ fputs(delimstr, stdout);
}
- putchar('\n');
}
size_t
diff --git a/util.h b/util.h
t@@ -26,7 +26,7 @@ void * xreallocarray(void *m, size_t n, size_t s);
size_t allocarr(double **arr, const char *str, size_t maxlen);
int scannextval(char **str, double *val);
void printarr(double *arr, size_t len);
-void printfarr(char *fmtstr, double *arr, size_t len);
+void printfarr(char *delimstr, int prec, double *arr, size_t len);
size_t fscanmatrix(FILE *stream, double ***arr, size_t *nf);
#endif
You are viewing proxied material from mx1.adamsgaard.dk. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.