# (wrong string) ée

From: <git_AT_suckless.org>
Date: Wed, 11 May 2016 16:11:08 +0200 (CEST)

Author: Mattias Andrée <maandree_AT_kth.se>
AuthorDate: Wed May 11 16:10:53 2016 +0200
Commit: Mattias Andrée <maandree_AT_kth.se>
CommitDate: Wed May 11 16:10:53 2016 +0200

Work on the manual and zstr_length checks that the radix is valid

Signed-off-by: Mattias Andrée <maandree_AT_kth.se>

diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
_AT_@ -76,7 +76,9 @@ TEXSRC =\
doc/libzahl.tex\
doc/what-is-libzahl.tex\
doc/libzahls-design.tex\
- doc/get-started.tex
+ doc/get-started.tex\
+ doc/miscellaneous.tex\
+ doc/arithmetic.tex

HDR_PUBLIC = zahl.h $(HDR_SEMIPUBLIC) HDR =$(HDR_PUBLIC) $(HDR_PRIVATE) diff --git a/doc/arithmetic.tex b/doc/arithmetic.tex new file mode 100644 index 0000000..0cbc25d --- /dev/null +++ b/doc/arithmetic.tex _AT_@ -0,0 +1,52 @@ +\chapter{Arithmetic} +\label{chap:Arithmetic} + +In this chapter, we will learn how to perform basic +arithmetic with libzahl: addition, subtraction, +multiplication, division, modulus, exponentiation, +and Sign manipulation. + +\vspace{1cm} +\minitoc + + +\newpage +\section{Addition} +\label{sec:Addition} + +TODO % zadd + + +\newpage +\section{Subtraction} +\label{sec:Subtraction} + +TODO % zsub + + +\newpage +\section{Multiplication} +\label{sec:Multiplication} + +TODO % zmul zmodmul + + +\newpage +\section{Division} +\label{sec:Division} + +TODO % zdiv zmod zdivmod + + +\newpage +\section{Exponentiation} +\label{sec:Exponentiation} + +TODO % zpow zpowu zmodpow zmodpowu + + +\newpage +\section{Sign manipulation} +\label{sec:Sign manipulation} + +TODO % zabs zneg diff --git a/doc/get-started.tex b/doc/get-started.tex index 537b228..0b297ed 100644 --- a/doc/get-started.tex +++ b/doc/get-started.tex _AT_@ -147,6 +147,9 @@ error code, you instead look at the return value. case ZERROR_NEGATIVE: fprintf(stderr, "Undefined (negative input)\verb|\|n"); \textcolor{c}{return 1;} + case ZERROR_INVALID_RADIX: + fprintf(stderr, "Radix must be at least 2\verb|\|n"); + \textcolor{c}{return 1;} default: zperror(""); \textcolor{c}{return 1;} _AT_@ -228,7 +231,7 @@ for reuse. If you plan to reuse the variable later, you need to reinitialise it by calling {\tt zinit} again. -Alternatives to {\tt zseti} include: +Alternatives to {\tt zseti} include \psecref{sec:Assignment}: \begin{alltt} void zsetu(z_t a, uint64_t value); diff --git a/doc/libzahl.tex b/doc/libzahl.tex index ba4d902..c417fff 100644 --- a/doc/libzahl.tex +++ b/doc/libzahl.tex _AT_@ -80,6 +80,8 @@ all copies or substantial portions of the Document. \input doc/what-is-libzahl.tex \input doc/libzahls-design.tex \input doc/get-started.tex +\input doc/miscellaneous.tex +\input doc/arithmetic.tex \appendix diff --git a/doc/libzahls-design.tex b/doc/libzahls-design.tex index 060c1fd..dcc2cb1 100644 --- a/doc/libzahls-design.tex +++ b/doc/libzahls-design.tex _AT_@ -194,9 +194,9 @@ would write them using mathematical notation, this also holds true if you include the output parameter (as long as there is exactly one output,) for example -\vspace{1ex} +\vspace{1em}$a \gets b^c \mod d$-\vspace{1ex} +\vspace{1em} \noindent is written diff --git a/doc/miscellaneous.tex b/doc/miscellaneous.tex new file mode 100644 index 0000000..4b83822 --- /dev/null +++ b/doc/miscellaneous.tex _AT_@ -0,0 +1,341 @@ +\chapter{Miscellaneous} +\label{chap:Miscellaneous} + +In this chapter, we will learn some miscellaneous +functions. It might seem counterintuitive to start +with miscellanea, but it is probably a good idea +to read this before arithmetics and more advanced +topics. You may read \secref{sec:Marshalling} +later. Before reading this chapter you should +have read \chapref{chap:Get started}. + + +\vspace{1cm} +\minitoc + + +\newpage +\section{Assignment} +\label{sec:Assignment} + +To be able to do anything useful, we must assign +values to integers. There are three functions for +this: {\tt zseti}, {\tt zsetu}, and {\tt zsets}. +The last letter in the names of these function +describe the data type of the input, i', u', +and s' stand for integer', unsigned integer', +and string, respectively. These resemble the +rules for the format strings in the family of +{\tt printf}-functions. Integer' of course refer +to `signed integer'; for integer types in C, +part from {\tt char}, the keyword {\tt signed} +is implicit. + +Consider {\tt zseti}, + +\begin{alltt} + \textcolor{c}{z_t two;} + \textcolor{c}{zinit(two);} + zseti(two, 2); +\end{alltt} + +\noindent +assignes {\tt two} the value 2. The data type of +the second parameter of {\tt zseti} is {\tt int64\_t}. +It will accept any integer value in the range +$[-2^{63},~2^{63} - 1] = [-9223372036854775808,~9223372036854775807]$, +independently of the machine.\footnote{{\tt int64\_t} +is defined to be a signed 64-bit integer using two's +complement representation.} If this range so not wide +enough, it may be possible to use {\tt zsetu}. Its +second parameter of the type {\tt uint64\_t}, and thus +its range is$[0,~2^{64} - 1] = [0,~18446744073709551615]$. +If a need negative value is desired, {\tt zsetu} can be +combined with {\tt zneg} \psecref{sec:Sign manipulation}. + +For enormous constants or textual input, {\tt zsets} +can be used. {\tt zsets} will accept any numerical +value encoded in decimal ASCII, that only contain +digits, \emph{not} decimal points, whitespace, +apostrophes, et cetera. However, an optional plus +sign or, for negative numbers, an ASCII minus sign +may be used as the very first character. Note that +a proper UCS minus sign is not supported. + +Using what we have learned so far, and {\tt zstr} +which we will learn about in \secref{sec:String output}, +we can construct a simple program that calculates the +sum of a set of number. + +\begin{alltt} + \textcolor{c}{#include <stdio.h> + #include <stdlib.h> + #include <zahl.h>} + + int + main(int argc, char *argv[]) \{ + z_t sum, temp; + \textcolor{c}{jmp_buf failenv; + char *sbuf, *argv0 = *argv; + if (setjmp(failenv)) \{ + zperror(argv0); + return 1; + \} + zsetup(failenv); + zinit(sum); + zinit(term);} + zsetu(sum, 0); + for (argv++; *argv; argv++) \{ + zsets(term, *argv); + zadd(sum, sum, term); + \} + \textcolor{c}{printf("\%s\textbackslash{}n", (sbuf = zstr(sum, NULL, 0))); + free(sbuf); + zfree(sum); + zfree(term); + zunsetup(); + return 0;} + \} +\end{alltt} + +Another form of assignment available in libzahl is +copy-assignment. This done using {\tt zset}. As +easily observable, {\tt zset} is named like +{\tt zseti}, {\tt zsetu}, and {\tt zsetu}, but +without the input-type suffix. The lack of a +input-type suffix means that the input type is +{\tt z\_t}. {\tt zset} copies value of second +parameter into the reference in the first. For +example, if {\tt v}, of the type {\tt z\_t}, has +value 10, then {\tt a} will too after the instruction + +\begin{alltt} + zset(a, v); +\end{alltt} + +{\tt zset} does not necessarily make an exact +copy of the input. If, in the example above, the +{\tt a->alloced} is greater than or equal to +{\tt v->used}, {\tt a->alloced} and {\tt a->chars} +are preserved, of course, the content of +{\tt a->chars} is overridden. If however, +{\tt a->alloced} is less then {\tt v->used}, +{\tt a->alloced} is assigned a minimal value at +least as great as {\tt v->used} that is a power +of 2, and {\tt a->chars} is updated accordingly +as described in \secref{sec:Integer structure}. +This of course does not apply if {\tt v} has the +value 0; in such cases {\tt a->sign} is simply +set to 0. + +{\tt zset}, {\tt zseti}, {\tt zsetu}, and +{\tt zsets} require that the output-parameter +has been initialised with {\tt zinit} or an +equally acceptable method as described in +\secref{sec:Create an integer}. + +{\tt zset} is often unnecessary, of course +there are cases where it is need. In some case +{\tt zswap} is enough, and advantageous. +{\tt zswap} is defined as + +\begin{alltt} + \textcolor{c}{static inline} void + zswap(z_t a, z_t b) + \{ + z_t t; + *t = *a; + *a = *b; + *b = *t; + \} +\end{alltt} + +\noindent +however its implementation is optimised to be +around three times. It just swaps the members +of the parameters, and thereby the values, There +is no rewriting of {\tt .chars} involved; thus +it runs in constant time. It also does not +require that any argument has be initialised. +After the call, {\tt a} will be initialised +if and only if {\tt b} was initialised, and +vice versa. + + +\newpage +\section{String output} +\label{sec:String output} + +Few useful things can be done without creating +textual output of calculations. To convert a +{\tt z\_t} to ASCII string in decimal, we use the +function {\tt zstr}, declared as + +\begin{alltt} + char *zstr(z_t a, char *buf, size_t n); +\end{alltt} + +\noindent +{\tt zstr} will store the string it creates into +{\tt buf} and return {\tt buf}. However, if {\tt buf} +is {\tt NULL}, a new memory segment is allocated +and returned. {\tt n} should be at least the length +of the resulting string sans NUL termiantion, but +not larger than the allocation size of {\tt buf} +minus 1 byte for NUL termiantion. If {\tt buf} is +{\tt NULL}, {\tt n} may be 0. However if {\tt buf} +is not {\tt NULL}, it is unsafe to let {\tt n} be +0, unless {\tt buf} has been allocated by {\tt zstr} +for a value of {\tt a} at least as larger as the +value of {\tt a} in the new call to {\tt zstr}. +Combining non-\texttt{NULL} {\tt buf} with 0 {\tt n} +is unsafe because {\tt zstr} will use a very fast +formula for calculating a value that is at least +as large as the resulting output length, rather +than the exact length. + +The length of the string output by {\tt zstr} can +be predicted by {\tt zstr\_length}, decleared as + +\begin{alltt} + size_t zstr_length(z_t a, unsigned long long int radix); +\end{alltt} + +\noindent +It will calculated the length of {\tt a} represented +in radix {\tt radix}, sans NUL termination. If +{\tt radix} is 10, the length for a decimal +representation is calculated. + +Sometimes it is possible to never allocate a {\tt buf} +for {\tt zstr}. For example, in an implementation +of {\tt factor}, you can reuse the string of the +value to factorise, since all of its factors are +guaranteed to be no longer than the factored value. + +\begin{alltt} + void + factor(char *value) + \{ + size_t n = strlen(value); + z_t product, factor; + zsets(product, value); + printf("\%s:", value); + while (next_factor(product, factor)) + printf(" \%s", zstr(factor, value, n)); + printf("\verb|\|n"); + \} +\end{alltt} + +Other times it is possible to allocate just +once, for example of creating a sorted output. +In such cases, the allocation can be done almost +transparently. + +\begin{alltt} + void + output_presorted_decending(z_t *list, size_t n) + \{ + char *buf = NULL; + while (n--) + printf("\%s\verb|\|n", (buf = zstr(*list++, buf, 0))); + \} +\end{alltt} + +\noindent +Note, this example assumes that all values are +non-negative. + + + +\newpage +\section{Comparison} +\label{sec:Comparison} + +libzahl defines four functions for comparing +integers: {\tt zcmp}, {\tt zcmpi}, {\tt zcmpu}, +and {\tt zcmpmag}. These follow the same naming +convention as {\tt zset}, {\tt zseti}, and +{\tt zsetu}, as described in \secref{sec:Assignment}. +{\tt zcmpmag} compares the absolute value, the +magnitude, rather than the proper value. These +functions are declared as + +\begin{alltt} + int zcmp(z_t a, z_t b); + int zcmpi(z_t a, int64_t b); + int zcmpu(z_t a, uint64_t b); + int zcmpmag(z_t a, z_t b); +\end{alltt} + +\noindent +They behave similar to {\tt memcmp} and +{\tt strcmp}.\footnote{And {\tt wmemcmp} and +{\tt wcscmp} if you are into that mess.} +The return value is defined + +\vspace{1em} +$$+ \mbox{sgn}(a - b) = + \left \lbrace \begin{array}{rl} + -1 & \quad \textrm{if}~a < b \\ + 0 & \quad \textrm{if}~a = b \\ + +1 & \quad \textrm{if}~a > b + \end{array} \right . +$$ +\vspace{1em} + +\noindent +for {\tt zcmp}, {\tt zcmpi}, and {\tt zcmpu}. +The return for {\tt zcmpmag} value is defined + +\vspace{1em} +$$+ \mbox{sgn}(\lvert a \rvert - \lvert b \rvert) = + \left \lbrace \begin{array}{rl} + -1 & \quad \textrm{if}~\lvert a \rvert < \lvert b \rvert \\ + 0 & \quad \textrm{if}~\lvert a \rvert = \lvert b \rvert \\ + +1 & \quad \textrm{if}~\lvert a \rvert > \lvert b \rvert + \end{array} \right . +$$ +\vspace{1em} + +\noindent +It is discouraged, stylistically, to compare +against,$-1$and$+1$, rather, you should +always compare against$0$. Think of it as +returning$a - b$, or$\lvert a \rvert - \lvert b \rvert$+in the case of {\tt zcmpmag}. + + +\newpage +\section{Marshalling} +\label{sec:Marshalling} + +libzahl is designed to provide efficient communication +for multi-processes applications, including running on +multiple nodes on a cluster computer. However, these +facilities require that it is known that all processes +run the same version of libzahl, and run on compatible +microarchitectures, that is, the processors must have +endianness, and the intrinsic integer types in C must +have the same widths on all processors. When this is not +the case, string conversion (see \secref{sec:Assignment} +and \secref{sec:String output}), but when it is the case +{\tt zsave} and {\tt zload} can be used. {\tt zsave} and +{\tt zload} are declared as + +\begin{alltt} + size_t zsave(z_t a, char *buf); + size_t zload(z_t a, const char *buf); +\end{alltt} + +\noindent +{\tt zsave} stores a version- and microarchitecture-depend +binary representation of {\tt a} in {\tt buf}, and returns +the number of bytes written to {\tt buf}. If {\tt buf} is +{\tt NULL}, the numbers that will be written is returned. +{\tt zload} unmarshals an integers from {\tt buf}, created +with {\tt zsave}, into {\tt a}, and returns the number of +read bytes. {\tt zload} and will return the value returned +by {\tt zsave}. diff --git a/doc/what-is-libzahl.tex b/doc/what-is-libzahl.tex index cf74c38..46998bc 100644 --- a/doc/what-is-libzahl.tex +++ b/doc/what-is-libzahl.tex _AT_@ -117,16 +117,16 @@ rather than \noindent This can be compared to -\vspace{1ex} +\vspace{1em}$sum \gets augend + addend$-\vspace{1ex} +\vspace{1em} \noindent versus -\vspace{1ex} +\vspace{1em}$augend + addend \rightarrow sum\$.
-\vspace{1ex}
+\vspace{1em}

libzahl, GNU MP, and Hebimath use the output-first
convention. LibTomMath and TomsFastMath use the
diff --git a/man/zerror.3 b/man/zerror.3
index 8bc0e53..022983d 100644
--- a/man/zerror.3
+++ b/man/zerror.3
_AT_@ -72,6 +72,15 @@ values is
.B EDOM
and
.BR EINVAL .
+.TP
+A radix less than 2 was selected, which is invalid because,
+radix 0 is impossible as there would be no digits, and radix
+1 is impossible because only the value 0 can be represented
+in radix 1. The closest matching
+.I errno
+values is
+.BR EINVAL .
.SH RETURN VALUE
.B zerror
returns the error that caused libzahl a function to fail.
index 86d4213..d4f0173 100644
_AT_@ -24,10 +24,6 @@ must have been initialized with
.SH RETURN VALUE
The number of bytes read from
.IR buf .
-On failure, 0 is returned.
-.SH ERRORS
-This function may failure for any reason specified for
-.BR realloc (3).
.BR zinit (3),
.BR zsave (3),
diff --git a/man/zstr_length.3 b/man/zstr_length.3
index 3101756..7d2dd7a 100644
--- a/man/zstr_length.3
+++ b/man/zstr_length.3
_AT_@ -17,7 +17,7 @@ in the selected
.SH RETURN VALUE
The number of digits requires to represent
.I a
-i the selected
+in the selected
is returned.
diff --git a/src/zstr_length.c b/src/zstr_length.c
index 16638e6..869dbc5 100644
--- a/src/zstr_length.c
+++ b/src/zstr_length.c
_AT_@ -10,6 +10,8 @@ size_t
zstr_length(z_t a, unsigned long long int radix)
{
size_t size_total = 1, size_temp;
zset(num, a);
while (!zzero(num)) {
diff --git a/zahl.h b/zahl.h
index 0ca0565..b224338 100644
--- a/zahl.h
+++ b/zahl.h
_AT_@ -50,7 +50,8 @@ enum zerror {
ZERROR_0_POW_0, /* Indeterminate form: 0:th power of 0. (Translatable to EDOM.) */
ZERROR_0_DIV_0, /* Indeterminate form: 0 divided by 0. (Translatable to EDOM.) */
ZERROR_DIV_0, /* Undefined result: Division by 0. (Translatable to EDOM.) */
- ZERROR_NEGATIVE /* Argument must be non-negative. (Translatable to EDOM or EINVAL.) */
+ ZERROR_NEGATIVE, /* Argument must be non-negative. (Translatable to EDOM or EINVAL.) */
+ ZERROR_INVALID_RADIX /* Radix must be at least 2. (Translatable to EINVAL.) */
};

Received on Wed May 11 2016 - 16:11:08 CEST

This archive was generated by hypermail 2.3.0 : Wed May 11 2016 - 16:12:13 CEST