| miscellaneous.tex - libzahl - big integer library | |
| git clone git://git.suckless.org/libzahl | |
| Log | |
| Files | |
| Refs | |
| README | |
| LICENSE | |
| --- | |
| miscellaneous.tex (10583B) | |
| --- | |
| 1 \chapter{Miscellaneous} | |
| 2 \label{chap:Miscellaneous} | |
| 3 | |
| 4 In this chapter, we will learn some miscellaneous | |
| 5 functions. It might seem counterintuitive to start | |
| 6 with miscellanea, but it is probably a good idea | |
| 7 to read this before arithmetics and more advanced | |
| 8 topics. You may read \secref{sec:Marshalling} | |
| 9 later. Before reading this chapter you should | |
| 10 have read \chapref{chap:Get started}. | |
| 11 | |
| 12 | |
| 13 \vspace{1cm} | |
| 14 \minitoc | |
| 15 | |
| 16 | |
| 17 \newpage | |
| 18 \section{Assignment} | |
| 19 \label{sec:Assignment} | |
| 20 | |
| 21 To be able to do anything useful, we must assign | |
| 22 values to integers. There are three functions for | |
| 23 this: {\tt zseti}, {\tt zsetu}, and {\tt zsets}. | |
| 24 The last letter in the names of these function | |
| 25 describe the data type of the input, `i', `u', | |
| 26 and `s' stand for `integer', `unsigned integer', | |
| 27 and `string`, respectively. These resemble the | |
| 28 rules for the format strings in the family of | |
| 29 {\tt printf}-functions. `Integer' of course refer | |
| 30 to `signed integer'; for integer types in C, | |
| 31 part from {\tt char}, the keyword {\tt signed} | |
| 32 is implicit. | |
| 33 | |
| 34 Consider {\tt zseti}, | |
| 35 | |
| 36 \begin{alltt} | |
| 37 \textcolor{c}{z_t two;} | |
| 38 \textcolor{c}{zinit(two);} | |
| 39 zseti(two, 2); | |
| 40 \end{alltt} | |
| 41 | |
| 42 \noindent | |
| 43 assignes {\tt two} the value 2. The data type of | |
| 44 the second parameter of {\tt zseti} is {\tt int64\_t}. | |
| 45 It will accept any integer value in the range | |
| 46 $[-2^{63},~2^{63} - 1] = [-9223372036854775808,~9223372036854775807]$, | |
| 47 independently of the machine.\footnote{{\tt int64\_t} | |
| 48 is defined to be a signed 64-bit integer using two's | |
| 49 complement representation.} If this range so not wide | |
| 50 enough, it may be possible to use {\tt zsetu}. Its | |
| 51 second parameter of the type {\tt uint64\_t}, and thus | |
| 52 its range is $[0,~2^{64} - 1] = [0,~18446744073709551615]$. | |
| 53 If a need negative value is desired, {\tt zsetu} can be | |
| 54 combined with {\tt zneg} \psecref{sec:Sign manipulation}. | |
| 55 | |
| 56 For enormous constants or textual input, {\tt zsets} | |
| 57 can be used. {\tt zsets} will accept any numerical | |
| 58 value encoded in decimal ASCII, that only contain | |
| 59 digits, \emph{not} decimal points, whitespace, | |
| 60 apostrophes, et cetera. However, an optional plus | |
| 61 sign or, for negative numbers, an ASCII minus sign | |
| 62 may be used as the very first character. Note that | |
| 63 a proper UCS minus sign is not supported. | |
| 64 | |
| 65 Using what we have learned so far, and {\tt zstr} | |
| 66 which we will learn about in \secref{sec:String output}, | |
| 67 we can construct a simple program that calculates the | |
| 68 sum of a set of numbers. | |
| 69 | |
| 70 \begin{alltt} | |
| 71 \textcolor{c}{#include <stdio.h> | |
| 72 #include <stdlib.h> | |
| 73 #include <zahl.h>} | |
| 74 | |
| 75 int | |
| 76 main(int argc, char *argv[]) \{ | |
| 77 z_t sum, temp; | |
| 78 \textcolor{c}{jmp_buf failenv; | |
| 79 char *sbuf, *argv0 = *argv; | |
| 80 if (setjmp(failenv)) \{ | |
| 81 zperror(argv0); | |
| 82 return 1; | |
| 83 \} | |
| 84 zsetup(failenv); | |
| 85 zinit(sum); | |
| 86 zinit(term);} | |
| 87 zsetu(sum, 0); | |
| 88 for (argv++; *argv; argv++) \{ | |
| 89 zsets(term, *argv); | |
| 90 zadd(sum, sum, term); | |
| 91 \} | |
| 92 \textcolor{c}{printf("\%s\textbackslash{}n", (sbuf = zstr(sum, NU… | |
| 93 free(sbuf); | |
| 94 zfree(sum); | |
| 95 zfree(term); | |
| 96 zunsetup(); | |
| 97 return 0;} | |
| 98 \} | |
| 99 \end{alltt} | |
| 100 | |
| 101 Another form of assignment available in libzahl is | |
| 102 copy-assignment. This done using {\tt zset}. As | |
| 103 easily observable, {\tt zset} is named like | |
| 104 {\tt zseti}, {\tt zsetu}, and {\tt zsets}, but | |
| 105 without the input-type suffix. The lack of a | |
| 106 input-type suffix means that the input type is | |
| 107 {\tt z\_t}. {\tt zset} copies value of second | |
| 108 parameter into the reference in the first. For | |
| 109 example, if {\tt v}, of the type {\tt z\_t}, has | |
| 110 value 10, then {\tt a} will too after the instruction | |
| 111 | |
| 112 \begin{alltt} | |
| 113 zset(a, v); | |
| 114 \end{alltt} | |
| 115 | |
| 116 {\tt zset} does not necessarily make an exact | |
| 117 copy of the input. If, in the example above, the | |
| 118 {\tt a->alloced} is greater than or equal to | |
| 119 {\tt v->used}, {\tt a->alloced} and {\tt a->chars} | |
| 120 are preserved, of course, the content of | |
| 121 {\tt a->chars} is overridden. If however, | |
| 122 {\tt a->alloced} is less then {\tt v->used}, | |
| 123 {\tt a->alloced} is assigned a minimal value at | |
| 124 least as great as {\tt v->used} that is a power | |
| 125 of 2, and {\tt a->chars} is updated accordingly | |
| 126 as described in \secref{sec:Integer structure}. | |
| 127 This of course does not apply if {\tt v} has the | |
| 128 value 0; in such cases {\tt a->sign} is simply | |
| 129 set to 0. | |
| 130 | |
| 131 {\tt zset}, {\tt zseti}, {\tt zsetu}, and | |
| 132 {\tt zsets} require that the output-parameter | |
| 133 has been initialised with {\tt zinit} or an | |
| 134 equally acceptable method as described in | |
| 135 \secref{sec:Create an integer}. | |
| 136 | |
| 137 {\tt zset} is often unnecessary, of course | |
| 138 there are cases where it is needed. In some case | |
| 139 {\tt zswap} is enough, and advantageous. | |
| 140 {\tt zswap} is defined as | |
| 141 | |
| 142 \begin{alltt} | |
| 143 \textcolor{c}{static inline} void | |
| 144 zswap(z_t a, z_t b) | |
| 145 \{ | |
| 146 z_t t; | |
| 147 *t = *a; | |
| 148 *a = *b; | |
| 149 *b = *t; | |
| 150 \} | |
| 151 \end{alltt} | |
| 152 | |
| 153 \noindent | |
| 154 however its implementation is optimised to be | |
| 155 around three times as fast. It just swaps the members | |
| 156 of the parameters, and thereby the values. There | |
| 157 is no rewriting of {\tt .chars} involved; thus | |
| 158 it runs in constant time. It also does not | |
| 159 require that any argument has been initialised. | |
| 160 After the call, {\tt a} will be initialised | |
| 161 if and only if {\tt b} was initialised, and | |
| 162 vice versa. | |
| 163 | |
| 164 | |
| 165 \newpage | |
| 166 \section{String output} | |
| 167 \label{sec:String output} | |
| 168 | |
| 169 Few useful things can be done without creating | |
| 170 textual output of calculations. To convert a | |
| 171 {\tt z\_t} to ASCII string in decimal, we use the | |
| 172 function {\tt zstr}, declared as | |
| 173 | |
| 174 \begin{alltt} | |
| 175 char *zstr(z_t a, char *buf, size_t n); | |
| 176 \end{alltt} | |
| 177 | |
| 178 \noindent | |
| 179 {\tt zstr} will store the string it creates into | |
| 180 {\tt buf} and return {\tt buf}. However, if {\tt buf} | |
| 181 is {\tt NULL}, a new memory segment is allocated | |
| 182 and returned. {\tt n} should be at least the length | |
| 183 of the resulting string sans NUL termiantion, but | |
| 184 not larger than the allocation size of {\tt buf} | |
| 185 minus 1 byte for NUL termiantion. If {\tt buf} is | |
| 186 {\tt NULL}, {\tt n} may be 0. However if {\tt buf} | |
| 187 is not {\tt NULL}, it is unsafe to let {\tt n} be | |
| 188 0, unless {\tt buf} has been allocated by {\tt zstr} | |
| 189 for a value of {\tt a} at least as larger as the | |
| 190 value of {\tt a} in the new call to {\tt zstr}. | |
| 191 Combining non-\texttt{NULL} {\tt buf} with 0 {\tt n} | |
| 192 is unsafe because {\tt zstr} will use a very fast | |
| 193 formula for calculating a value that is at least | |
| 194 as large as the resulting output length, rather | |
| 195 than the exact length. | |
| 196 | |
| 197 The length of the string output by {\tt zstr} can | |
| 198 be predicted by {\tt zstr\_length}, decleared as | |
| 199 | |
| 200 \begin{alltt} | |
| 201 size_t zstr_length(z_t a, unsigned long long int radix); | |
| 202 \end{alltt} | |
| 203 | |
| 204 \noindent | |
| 205 It will calculated the length of {\tt a} represented | |
| 206 in radix {\tt radix}, sans NUL termination. If | |
| 207 {\tt radix} is 10, the length for a decimal | |
| 208 representation is calculated. | |
| 209 | |
| 210 Sometimes it is possible to never allocate a {\tt buf} | |
| 211 for {\tt zstr}. For example, in an implementation | |
| 212 of {\tt factor}, you can reuse the string of the | |
| 213 value to factorise, since all of its factors are | |
| 214 guaranteed to be no longer than the factored value. | |
| 215 | |
| 216 \begin{alltt} | |
| 217 void | |
| 218 factor(char *value) | |
| 219 \{ | |
| 220 size_t n = strlen(value); | |
| 221 z_t product, factor; | |
| 222 zsets(product, value); | |
| 223 printf("\%s:", value); | |
| 224 while (next_factor(product, factor)) | |
| 225 printf(" \%s", zstr(factor, value, n)); | |
| 226 printf("\verb|\|n"); | |
| 227 \} | |
| 228 \end{alltt} | |
| 229 | |
| 230 Other times it is possible to allocate just | |
| 231 once, for example of creating a sorted output. | |
| 232 In such cases, the allocation can be done almost | |
| 233 transparently. | |
| 234 | |
| 235 \begin{alltt} | |
| 236 void | |
| 237 output_presorted_decending(z_t *list, size_t n) | |
| 238 \{ | |
| 239 char *buf = NULL; | |
| 240 while (n--) | |
| 241 printf("\%s\verb|\|n", (buf = zstr(*list++, buf, 0))); | |
| 242 \} | |
| 243 \end{alltt} | |
| 244 | |
| 245 \noindent | |
| 246 Note, this example assumes that all values are | |
| 247 non-negative. | |
| 248 | |
| 249 | |
| 250 | |
| 251 \newpage | |
| 252 \section{Comparison} | |
| 253 \label{sec:Comparison} | |
| 254 | |
| 255 libzahl defines four functions for comparing | |
| 256 integers: {\tt zcmp}, {\tt zcmpi}, {\tt zcmpu}, | |
| 257 and {\tt zcmpmag}. These follow the same naming | |
| 258 convention as {\tt zset}, {\tt zseti}, and | |
| 259 {\tt zsetu}, as described in \secref{sec:Assignment}. | |
| 260 {\tt zcmpmag} compares the absolute value, the | |
| 261 magnitude, rather than the proper value. These | |
| 262 functions are declared as | |
| 263 | |
| 264 \begin{alltt} | |
| 265 int zcmp(z_t a, z_t b); | |
| 266 int zcmpi(z_t a, int64_t b); | |
| 267 int zcmpu(z_t a, uint64_t b); | |
| 268 int zcmpmag(z_t a, z_t b); | |
| 269 \end{alltt} | |
| 270 | |
| 271 \noindent | |
| 272 They behave similar to {\tt memcmp} and | |
| 273 {\tt strcmp}.\footnote{And {\tt wmemcmp} and | |
| 274 {\tt wcscmp} if you are into that mess.} | |
| 275 The return value is defined | |
| 276 | |
| 277 \vspace{1em} | |
| 278 \( | |
| 279 \mbox{sgn}(a - b) = | |
| 280 \left \lbrace \begin{array}{rl} | |
| 281 -1 & \quad \textrm{if}~a < b \\ | |
| 282 0 & \quad \textrm{if}~a = b \\ | |
| 283 +1 & \quad \textrm{if}~a > b | |
| 284 \end{array} \right . | |
| 285 \) | |
| 286 \vspace{1em} | |
| 287 | |
| 288 \noindent | |
| 289 for {\tt zcmp}, {\tt zcmpi}, and {\tt zcmpu}. | |
| 290 The return for {\tt zcmpmag} value is defined | |
| 291 | |
| 292 \vspace{1em} | |
| 293 \( | |
| 294 \mbox{sgn}(\lvert a \rvert - \lvert b \rvert) = | |
| 295 \left \lbrace \begin{array}{rl} | |
| 296 -1 & \quad \textrm{if}~\lvert a \rvert < \lvert b \rvert \\ | |
| 297 0 & \quad \textrm{if}~\lvert a \rvert = \lvert b \rvert \\ | |
| 298 +1 & \quad \textrm{if}~\lvert a \rvert > \lvert b \rvert | |
| 299 \end{array} \right . | |
| 300 \) | |
| 301 \vspace{1em} | |
| 302 | |
| 303 \noindent | |
| 304 It is discouraged, stylistically, to compare against | |
| 305 $-1$ and $+1$, rather, you should always compare | |
| 306 against $0$. Think of it as returning $a - b$, or | |
| 307 $\lvert a \rvert - \lvert b \rvert$ in the case of | |
| 308 {\tt zcmpmag}. | |
| 309 | |
| 310 | |
| 311 \newpage | |
| 312 \section{Marshalling} | |
| 313 \label{sec:Marshalling} | |
| 314 | |
| 315 libzahl is designed to provide efficient communication | |
| 316 for multi-processes applications, including running on | |
| 317 multiple nodes on a cluster computer. However, these | |
| 318 facilities require that it is known that all processes | |
| 319 run the same version of libzahl, and run on compatible | |
| 320 microarchitectures, that is, the processors must have | |
| 321 endianness, and the intrinsic integer types in C must | |
| 322 have the same widths on all processors. When this is not | |
| 323 the case, string conversion can be used (see \secref{sec:Assignment} | |
| 324 and \secref{sec:String output}), but when it is the case | |
| 325 {\tt zsave} and {\tt zload} can be used. {\tt zsave} and | |
| 326 {\tt zload} are declared as | |
| 327 | |
| 328 \begin{alltt} | |
| 329 size_t zsave(z_t a, char *buf); | |
| 330 size_t zload(z_t a, const char *buf); | |
| 331 \end{alltt} | |
| 332 | |
| 333 \noindent | |
| 334 {\tt zsave} stores a version- and microarchitecture-dependent | |
| 335 binary representation of {\tt a} in {\tt buf}, and returns | |
| 336 the number of bytes written to {\tt buf}. If {\tt buf} is | |
| 337 {\tt NULL}, the numbers bytes that would have be written is | |
| 338 returned. {\tt zload} unmarshals an integers from {\tt buf}, | |
| 339 created with {\tt zsave}, into {\tt a}, and returns the number | |
| 340 of read bytes. {\tt zload} returns the value returned by | |
| 341 {\tt zsave}. |