### Table of Contents

# DFTrig

DFTrig is a simple C library for efficient calculation of basic trigonometric functions (sine/cosine) by lookup table, table generator included.

## Description

Some time ago, I needed to draw a watch dial on the small display of car trip computer. I decided to calculate sine / cosine values by lookup table, and I was very surprised when I failed to find a ready-made universal tool for that. So I had to write such tool myself.

DFTrig consists of two parts:

- Lookup table generator
`tablegen`

(written in Java, but that doesn't matter much) that receives several options and produces C code (`const struct`

with lookup table) - Small C module that works with lookup table generated by
`tablegen`

.

Of course, lookup table contains only minimal information: sine values for just a single quadrant, i.e. [0, 90] degrees. That is fairly enough to calculate sine / cosine for any angle.

The behavior is quite customizable. You may specify:

- Factor by which each item in the lookup table is multiplied (on per-table basis);
- Step in degrees between each item in the table (on per-table basis);
- Type of items in the table (common for the whole C project).

So, depending on your needs, you may:

- Generate single table for the whole application with max factor, so that any subsystem of your C project may use that single table, providing desired factor, and it will be recalculated if requested factor is other than that of the table;
- Generate multiple tables, each with ad hoc factor, and each subsystem of your C project uses its dedicated table. Then, values can be returned from table as is, without recalculation; that works faster.

More, if you don't need for 1-degree resolution in some particular table, you may specify step other than 1. Say, in my case with watch dial, I needed for 1 minute resolution, i.e. 6 degrees. This reduces the size of table dramatically (six times), which may be considerable in the embedded world.

## Usage

C module needs to be configured by file `dftrig_cfg.h`

; currently there is just one option: `DFTRIG_VALUE_TYPE`

, it represents type of the values in the lookup table. There is default configuration file provided: `dftrig_cfg_default.h`

, so, initially just copy it as `dftrig_cfg.h`

and edit accordingly to your needs.

The library archive (see download links at the bottom) contains source of both Java `tablegen`

and C module, as well as precompiled `tablegen.jar`

.

Example: generate table of integers with step 6 and max factor that may fit in one byte (255) :

java -jar tablegen.jar --type int --factor 255 --step 6

Tablegen will generate the file `dftrig_lookup_tbl_255.c`

with the following contents:

/* * This structure is auto-generated by dftrig's tablegen utility. * Exact command: java -jar tablegen.jar --type int --factor 255 --step 6 * Please don't edit it by hand! Use tablegen instead. */ const T_DFTrigLookupTbl dftrig_lookup_tbl_255 = { .factor = 255, .step = 6, .table = { [0] = 0, /* sin(0 degrees) * 255 */ [1] = 27, /* sin(6 degrees) * 255 */ [2] = 53, /* sin(12 degrees) * 255 */ [3] = 79, /* sin(18 degrees) * 255 */ [4] = 104, /* sin(24 degrees) * 255 */ [5] = 127, /* sin(30 degrees) * 255 */ [6] = 150, /* sin(36 degrees) * 255 */ [7] = 171, /* sin(42 degrees) * 255 */ [8] = 190, /* sin(48 degrees) * 255 */ [9] = 206, /* sin(54 degrees) * 255 */ [10] = 221, /* sin(60 degrees) * 255 */ [11] = 233, /* sin(66 degrees) * 255 */ [12] = 243, /* sin(72 degrees) * 255 */ [13] = 249, /* sin(78 degrees) * 255 */ [14] = 254, /* sin(84 degrees) * 255 */ [15] = 255, /* sin(90 degrees) * 255 */ }, };

Now you should copy contents of that file and paste it somewhere in your project, and then you may get sine like that:

//-- get sin(30) * 255 (returns 127) dftrig__sin__get_by_deg(&dftrig_lookup_tbl_255, 30, 255); //-- get sin(78) * 100 (returns 98) dftrig__sin__get_by_deg(&dftrig_lookup_tbl_255, 78, 100);

In the former case, requested factor `255`

matches that of table, so, value is returned from table as is without recalculation, that works fast. In the latter case, requested factor `100`

is different, so, value from table is recalculated before returning. If you want to avoid recalculation, you may generate second table, with factor 100, and probably step 3:

/* * This structure is auto-generated by dftrig's tablegen utility. * Exact command: java -jar tablegen.jar --type int --factor 100 --step 3 * Please don't edit it by hand! Use tablegen instead. */ const T_DFTrigLookupTbl dftrig_lookup_tbl_100 = { .factor = 100, .step = 3, .table = { [0] = 0, /* sin(0 degrees) * 100 */ [1] = 5, /* sin(3 degrees) * 100 */ [2] = 10, /* sin(6 degrees) * 100 */ [3] = 16, /* sin(9 degrees) * 100 */ [4] = 21, /* sin(12 degrees) * 100 */ [5] = 26, /* sin(15 degrees) * 100 */ [6] = 31, /* sin(18 degrees) * 100 */ [7] = 36, /* sin(21 degrees) * 100 */ [8] = 41, /* sin(24 degrees) * 100 */ [9] = 45, /* sin(27 degrees) * 100 */ [10] = 50, /* sin(30 degrees) * 100 */ [11] = 54, /* sin(33 degrees) * 100 */ [12] = 59, /* sin(36 degrees) * 100 */ [13] = 63, /* sin(39 degrees) * 100 */ [14] = 67, /* sin(42 degrees) * 100 */ [15] = 71, /* sin(45 degrees) * 100 */ [16] = 74, /* sin(48 degrees) * 100 */ [17] = 78, /* sin(51 degrees) * 100 */ [18] = 81, /* sin(54 degrees) * 100 */ [19] = 84, /* sin(57 degrees) * 100 */ [20] = 87, /* sin(60 degrees) * 100 */ [21] = 89, /* sin(63 degrees) * 100 */ [22] = 91, /* sin(66 degrees) * 100 */ [23] = 93, /* sin(69 degrees) * 100 */ [24] = 95, /* sin(72 degrees) * 100 */ [25] = 97, /* sin(75 degrees) * 100 */ [26] = 98, /* sin(78 degrees) * 100 */ [27] = 99, /* sin(81 degrees) * 100 */ [28] = 99, /* sin(84 degrees) * 100 */ [29] = 100, /* sin(87 degrees) * 100 */ [30] = 100, /* sin(90 degrees) * 100 */ }, };

And use that table for calculation with factor `100`

. There is always a tradeoff between performance / memory.

## License

License: BSD.

## Download

Library is hosted at bitbucket: https://bitbucket.org/dfrank/dftrig

## Discussion