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:

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:

So, depending on your needs, you may:

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