D. J. Bernstein

Time

libtai
# The taia library interface

## Times with 1-attosecond precision

#include <taia.h>
struct taia *t*;

A `struct taia` value is
a number between 0 inclusive and 2^64 exclusive.
The number is a multiple of 10^-18.
The format of `struct taia`
is designed to speed up common operations;
applications should not look inside `struct taia`.
A `struct taia` variable
is commonly used to store a
TAI64NA label.
Each TAI64NA label refers to one attosecond of real time.
The number in the `struct taia`
is the second count,
plus 10^-9 times the nanosecond count,
plus 10^-18 times the attosecond count.

A `struct taia` variable
may also be used to store the numerical difference between two TAI64NA labels.

## Current time

#include <taia.h>
struct taia *t*;
taia_now(&*t*);

`taia_now`
puts the current time into
*t*.
More precisely:
`taia_now`
puts into *t*
its best guess as to the TAI64NA label for the 1-attosecond interval
that contains the current time.
The current implementation of `taia_now`
assumes that the `struct timeval`
returned by the UNIX `gettimeofday` function
represents the number of TAI seconds since 1970-01-01 00:00:10 TAI.
This matches the convention used by
the Olson tz library in ``right'' mode.
Beware that many clocks are not set accurately,
and even the best scientific clocks are nowhere near 1-attosecond accuracy;
however, an inaccurate clock
may still produce reasonably accurate time differences.

## Binary input and output

#include <taia.h>
struct taia *t*;
char *buf*[TAIA_PACK];
taia_pack(*buf*,&*t*);
taia_unpack(*buf*,&*t*);

`taia_pack` converts a TAI64NA label from internal format
in *t* to
external TAI64NA format
in *buf*.
`taia_pack` converts a TAI64NA label from
external TAI64NA format
in *buf*
to internal format
in *t*.

TAIA_PACK is 16.

## ASCII output

#include <taia.h>
struct taia *t*;
char **s*;
unsigned int *len*;
*len* = taia_fmtfrac(*s*,&*t*);

`taia_fmtfrac` prints the 18-digit fraction part of *t*
in decimal,
without a decimal point but with leading zeros,
into the character buffer *s*,
without a terminating \0.
It returns 18, the number of characters written.
*s* may be zero;
then `taia_fmtfrac` returns 18 without printing anything.
The macro `TAIA_FMTFRAC` is defined as 19;
this is enough space for the output of `taia_fmtfrac`
and a terminating \0.

## Arithmetic

#include <taia.h>
struct taia *t*;
struct taia *a*;
struct taia *b*;
struct tai *sec*;
double *d*;
int *i*;
*d* = taia_approx(&*t*);
taia_tai(&*t*,&*sec*);
*d* = taia_frac(&*t*);
*i* = taia_less(&*a*,&*b*);
taia_add(&*t*,&*a*,&*b*);
taia_sub(&*t*,&*a*,&*b*);
taia_half(&*t*,&*a*);

`taia_approx`
returns a double-precision approximation to
*t*.
The result of `taia_approx` is always nonnegative.
`taia_tai`
places into *sec*
the integer part of *t*.
*sec*
is a `struct tai` variable.
If *t* contains a TAI64NA label
then *sec* will contain the corresponding TAI64 label.

`taia_frac`
returns a double-precision approximation to
the fraction part of
*t*.
The result of `taia_frac` is always nonnegative.

`taia_less`
returns 1 if
*a*
is less than
*b*,
0 otherwise.

`taia_add`
adds
*a*
to
*b*
modulo 2^64 and puts the result into
*t*.
The inputs and output may overlap.

`taia_sub`
subtracts
*b*
from
*a*
modulo 2^64 and puts the result into
*t*.
The inputs and output may overlap.

`taia_half`
divides
*a*
by 2, rounding down to a multiple of 10^-18, and puts the result into
*t*.
The input and output may overlap.