Code conventions
================

Language dialect
----------------

For greater portability, the code should be ANSI C compatible where possible.  
We note the following exceptions:

    - Inlined functions, inlined assembly.  We define alternative keywords 
      __asm__ and __inline__ in flint.h so that gcc allows compiling with 
      the flags "-ansi -pendatic" nonetheless.

Primitive types
---------------

Depending on the main interpretation of the value of a variable, where 
possible the following primitive datatype should be used:

    | bit counts up to a single limb         | ulong                       |
    | bit counts, multiprecision             | mp_bitcnt_t                 |
    | byte counts (strings)                  | size_t                      |
    | limb counts in multiprecision integers | mp_size_t                   |
    | limbs (unsigned/signed)                | mp_limb_t/ mp_limb_signed_t |
    | mp_limb_t arrays                       | mp_ptr/ mp_srcptr           |
    | ui/ si function constants              | ulong/ slong                |
    | exponents (unsigned/signed)            | ulong/ slong                |
    | polynomial lengths                     | slong                       |
    | number of indeterminates               | slong                       |
    | row/ column indices                    | slong                       |
    | precision for mpfr types               | mpfr_prec_t                 |

The typical definitions of these in terms of primitive types are:

    | mp_bitcnt_t   | ulong, or ulong long                                 |
    | mp_size_t     | long, or long long                                   |
    | mp_limb_t     | ulong, or ulong long                                 |
    | mp_ptr        | mp_limb_t *                                          |
    | mp_srcptr     | const mp_limb_t *                                    |
    | slong         | long or long long                                    |
    | ulong         | ulong or ulong long                                  |

Constant integers
-----------------

Because the ulong/slong types can be (unsigned) long on Linux and (unsigned)
long long on Windows, we cannot use the usual 123456789UL to declare them.

Instead, we provide two macros:

  WORD(123456789) /* slong constant */
  UWORD(123456789) /* ulong constant */

Format specifiers
-----------------

Again, because a ulong/slong use different types on Windows and Linux, we cannot
use the format specifers %lu/%ld in printf. For this purpose we provide the
flint_printf functions, which is the same as printf, except that it supports:

   flint_printf("%wu", d); /* print ulong */
   flint_printf("%wd", d); /* print slong */

Use of const
------------

Input parameters to functions should be marked const in the following cases:

* complex types that are passed by reference, e.g. fmpz_poly_t

They should not be used on output parameters or for simple types or simple
structs which are passed by value and not reference, e.g. nmod_t.

Random functions
----------------

When writing functions which produce random values the order of operands should 
follow one of the following:

if the function returns its random value, the state comes first, e.g:

a = n_randint(state, n)

if the function sets its first argument to a random value, the state
comes second, e.g.

nmod_poly_randtest(poly, state, len, bits)

Conversion functions
--------------------

When naming functions which convert between objects of different modules, use
the convention module1_get_module2 and module1_set_module2, where module1 is
notionally the more complex of the two modules. E.g. fmpz_poly_get_nmod_poly.
The set function should set an object of module1 to the value of an object of
module2, and the get function should do the opposite.

Function prototypes
-------------------

All function prototypes in .h files in FLINT require a FLINT_DLL declaration in
front of them. Please keep the initial part of the prototype all on a single
line, rather than placing the FLINT_DLL and/or return type on a different
line, e.g. prototypes should look like this:

FLINT_DLL void myfunc(blah, ....
      ...., blah, blah)

Note that dll import/export is handled differently for inlines. Please don't
add FLINT_DLL to inline functions. Rather, add a single FLINT_DLL to the
non-inline branch inside the relevant BLAH_INLINES_C #define at the top of the
.h file.

Code formatting
---------------

The C code should follow the style produced by the following call to "indent",

    indent -bap -blf -bli0 -cbi0 -cdw -cli4 -cs -i4 -l79 -nbad -nbc -nce -npcs -nprs -nut -pmt -psl -saf -sai -saw -sbi0 -ss -ts4

which is explained as follows:

    -bap   Force blank lines after procedure bodies
    -blf   Put braces on line following function definition line
    -bli0  Indent braces 0 spaces
    -cbi0  Indent braces after a case label 0 spaces
    -cdw   Cuddle while of do {} while
    -cli4  Case label indent of 4 spaces
    -cs    Put a space after a cast operator
    -i4    Set indentation level to 4 spaces
    -l79   Set maximum line length for non-comment lines to 79
    -nbad  Do not force blank lines after declarations
    -nbc   Do not force newlines after commas in declarations
    -nce   Do not cuddle else
    -npcs  Do not put a space after the function in function calls
    -nprs  Do not put a space after every ( and before every )
    -nut   Use spaces instead of tabs
    -pmt   Preserve access and modificaion times on output files
    -psl   Put the type of a procedure on the line before its name
    -saf   Put a space before each for
    -sai   Space after each for
    -saw   Space after every while
    -sbi0  Indent braces of a struct, union or enum 0 spaces
    -ss    On one-line for and while statements, for a blank before ;
    -ts4   Set tab size to 4 spaces

