get-started.tex - libzahl - big integer library
 (HTM) git clone git://git.suckless.org/libzahl
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       get-started.tex (6604B)
       ---
            1 \chapter{Get started}
            2 \label{chap:Get started}
            3 
            4 In this chapter, you will learn the basics of libzahl.
            5 You should read the sections in order.
            6 
            7 \vspace{1cm}
            8 \minitoc
            9 
           10 
           11 % TODO add a section a linking and stuff here.
           12 
           13 
           14 \newpage
           15 \section{Initialisation}
           16 \label{sec:Initialisation}
           17 
           18 Before using libzahl, it must be initialised. When
           19 initialising, you must select a location whither libzahl
           20 long jumps on error.
           21 
           22 \begin{alltt}
           23    #include <zahl.h>
           24 
           25    int
           26    main(void)
           27    \{
           28        jmp_buf jmpenv;
           29        if (setjmp(jmpenv))
           30            return 1; \textcolor{c}{/* \textrm{Exit on error} */}
           31        zsetup(jmpenv);
           32        \textcolor{c}{/* \textrm{\ldots} */}
           33        return 0;
           34    \}
           35 \end{alltt}
           36 
           37 {\tt zsetup} also initialises temporary variables used
           38 by libzahl's functions, and constants used by libzahl's
           39 functions. Furthermore, it initialises the memory pool
           40 and a stack which libzahl uses to keep track of temporary
           41 allocations that need to be pooled for use if a function
           42 fails.
           43 
           44 It is recommended to also uninitialise libzahl when you
           45 are done using it, for example before the program exits.
           46 
           47 \begin{alltt}
           48    \textcolor{c}{int
           49    main(void)
           50    \{
           51        jmp_buf jmpenv;
           52        if (setjmp(jmpenv))
           53            return 1; /* \textrm{Exit on error} */
           54        zsetup(jmpenv);
           55        /* \textrm{\ldots} */}
           56        zunsetup();
           57        \textcolor{c}{return 0;
           58    \}}
           59 \end{alltt}
           60 
           61 {\tt zunsetup} frees all memory that has been reclaimed to
           62 the memory pool, and all memory allocated by {\tt zsetup}.
           63 Note that this does not free integers that are still
           64 in use. It is possible to simply call {\tt zunsetup}
           65 directly followed by {\tt zsetup} to free all pooled
           66 memory.
           67 
           68 
           69 \newpage
           70 \section{Exceptional conditions}
           71 \label{sec:Exceptional conditions}
           72 
           73 Exceptional conditions, casually called `errors',
           74 are treated in libzahl using long jumps.
           75 
           76 \begin{alltt}
           77    int
           78    main(int argc, char *argv[])
           79    \{
           80        jmp_buf jmpenv;
           81        if (setjmp(jmpenv))
           82            return 1; \textcolor{c}{/* \textrm{Exit on error} */}
           83        zsetup(jmpenv);
           84        return 0;
           85    \}
           86 \end{alltt}
           87 
           88 Just exiting on error is not a particularly good
           89 idea. Instead, you may want to print an error message.
           90 This is done with {\tt zperror}.
           91 
           92 \begin{alltt}
           93    if (setjmp(jmpenv)) \{
           94        zperror(\textcolor{c}{*argv});
           95        \textcolor{c}{return 1;}
           96    \}
           97 \end{alltt}
           98 
           99 \noindent
          100 {\tt zperror} works just like {\tt perror}. It
          101 outputs an error description to standard error.
          102 A line break is printed at the end of the message.
          103 If the argument passed to {\tt zperror} is neither
          104 {\tt NULL} nor an empty string, it is printed in
          105 front of the description, with a colon and a
          106 space separating the passed string and the description.
          107 For example, {\tt zperror("my-app")} may output
          108 
          109 \begin{verbatim}
          110    my-app: Cannot allocate memory
          111 \end{verbatim}
          112 
          113 libzahl also provides {\tt zerror}. Calling this
          114 function will provide you with an error code and
          115 a textual description.
          116 
          117 \begin{alltt}
          118    \textcolor{c}{if (setjmp(jmpenv)) \{}
          119        const char *description;
          120        zerror(&description);
          121        fprintf(stderr, "\%s: \%s\verb|\|n", *argv, description);
          122        \textcolor{c}{return 1;}
          123    \textcolor{c}{\}}
          124 \end{alltt}
          125 
          126 \noindent
          127 This code behaves like the example above that
          128 calls {\tt zperror}. If you are interested in the
          129 error code, you instead look at the return value.
          130 
          131 \begin{alltt}
          132    \textcolor{c}{if (setjmp(jmpenv)) \{}
          133        enum zerror e = zerror(NULL);
          134        switch (e) \{
          135        case ZERROR_ERRNO_SET:
          136            perror("");
          137            \textcolor{c}{return 1;}
          138        case ZERROR_0_POW_0:
          139            fprintf(stderr, "Indeterminate form: 0^0\verb|\|n");
          140            \textcolor{c}{return 1;}
          141        case ZERROR_0_DIV_0:
          142            fprintf(stderr, "Indeterminate form: 0/0\verb|\|n");
          143            \textcolor{c}{return 1;}
          144        case ZERROR_DIV_0:
          145            fprintf(stderr, "Do not divide by zero, dummy\verb|\|n");
          146            \textcolor{c}{return 1;}
          147        case ZERROR_NEGATIVE:
          148            fprintf(stderr, "Undefined (negative input)\verb|\|n");
          149            \textcolor{c}{return 1;}
          150        case ZERROR_INVALID_RADIX:
          151            fprintf(stderr, "Radix must be at least 2\verb|\|n");
          152            \textcolor{c}{return 1;}
          153        default:
          154            zperror("");
          155            \textcolor{c}{return 1;}
          156        \}
          157    \textcolor{c}{\}}
          158 \end{alltt}
          159 
          160 To change the point whither libzahl's functions
          161 jump, call {\tt setjmp} and {\tt zsetup} again.
          162 
          163 \begin{alltt}
          164    jmp_buf jmpenv;
          165    if (setjmp(jmpenv)) \{
          166        \textcolor{c}{/* \textrm{\ldots} */}
          167    \}
          168    zsetup(jmpenv);
          169    \textcolor{c}{/* \textrm{\ldots} */}
          170    if (setjmp(jmpenv)) \{
          171        \textcolor{c}{/* \textrm{\ldots} */}
          172    \}
          173    zsetup(jmpenv);
          174 \end{alltt}
          175 
          176 
          177 \newpage
          178 \section{Create an integer}
          179 \label{sec:Create an integer}
          180 
          181 To do any real work with libzahl, we need integers. The
          182 data type for a big integer in libzahl is {\tt z\_t}
          183 \psecref{sec:Integer structure}. Before a {\tt z\_t}
          184 can be assigned a value, it must be initialised.
          185 
          186 \begin{alltt}
          187    z_t a;
          188    \textcolor{c}{/* \textrm{\ldots} */
          189    zsetup(jmpenv);}
          190    zinit(a);
          191    \textcolor{c}{/* \textrm{\ldots} */
          192    zunsetup();}
          193 \end{alltt}
          194 
          195 \noindent
          196 {\tt zinit(a)} is actually a less cumbersome and optimised
          197 alternative to calling {\tt memset(a, 0, sizeof(z\_t))}.
          198 It sets the values of two members: {\tt .alloced} and
          199 {\tt .chars}, to 0 and {\tt NULL}. This is necessary,
          200 otherwise the memory allocated could be fooled to deallocate
          201 a false pointer, causing the program to abort.
          202 
          203 Once the reference has been initialised, you may assign it
          204 a value. The simplest way to do this is by calling
          205 
          206 \begin{alltt}
          207    void zseti(z_t a, int64_t value);
          208 \end{alltt}
          209 
          210 \noindent
          211 For example {\tt zseti(a, 1)}, assignes the value 1 to
          212 the {\tt z\_t} {\tt a}.
          213 
          214 When you are done using a big integer reference, you should
          215 call {\tt zfree} to let libzahl know that it should pool
          216 the allocation of the {\tt .chars} member.
          217 
          218 \begin{alltt}
          219    z_t a;
          220    zinit(a);
          221    \textcolor{c}{/* \textrm{\ldots} */}
          222    zfree(a); \textcolor{c}{/* \textrm{before \texttt{zunsetup}} */}
          223 \end{alltt}
          224 
          225 \noindent
          226 Instead of calling {\tt zfree(a)}, it is possible — but
          227 strongly discouraged — to call {\tt free(a->chars)}.
          228 Note however, by doing so, the allocation is not pooled
          229 for reuse.
          230 
          231 If you plan to reuse the variable later, you need to
          232 reinitialise it by calling {\tt zinit} again.
          233 
          234 Alternatives to {\tt zseti} include \psecref{sec:Assignment}:
          235 
          236 \begin{alltt}
          237    void zsetu(z_t a, uint64_t value);
          238    void zsets(z_t a, const char *value);
          239    void zset(z_t a, z_t value); \textcolor{c}{/* \textrm{copy \texttt{value} into \texttt{a}} */}
          240 \end{alltt}