summaryrefslogtreecommitdiff
path: root/generate_table.c
blob: 9fd05bcc2f31889d4f4eb68c61a8bda2cff9de57 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <math.h>
#include <stdio.h>
#include <stdlib.h>

// s(-1) n(14) off(+1)   x =   x - ( x >> 14 )
// s( 1) n(-4) off( 0)   x =       ( x <<  4 )
// s( 1) n( 8) off(-1)   x = - x + ( x <<  8 )

typedef enum { use_2pn, use_1_2pn, use_2pm_2pn, use_1_2pm_2pn } tr_flag;
typedef struct {
  double factor;
  int     n;
  int     m;
  int     nsign;
  tr_flag flag;
} table_record;

static int g_records;
static table_record g_tr[8192];

static int compare_record( const void *a, const void *b ) {
  if( ((table_record*)a)->factor > ((table_record*)b)->factor )
    return 1;
  if( ((table_record*)a)->factor < ((table_record*)b)->factor )
    return -1;
  return 0;
}

static void add_record( double v, int n, int nsign, int m, tr_flag flag )
{
    g_tr[g_records].factor = v;
    g_tr[g_records].n      = n;
    g_tr[g_records].m      = m;
    g_tr[g_records].nsign  = nsign;
    g_tr[g_records].flag   = flag;
    ++g_records;
}

static void dump_record( int record )
{
  if( record >= g_records ) return; // should warn?
  double factor = g_tr[record].factor;
  int n         = g_tr[record].n;
  int m         = g_tr[record].m;
  int nsign     = g_tr[record].nsign;
  tr_flag flag  = g_tr[record].flag;

  switch( flag ) {
    case use_2pn:
      printf( "%0+25.21lf x =   x %s %2d\n", factor, n>=0?"<<":">>", (int)abs(n) );
      break;
    case use_1_2pn:
      printf( "%0+25.21lf x%s=   x %s %2d\n", factor, nsign==-1?"-":"+", n>=0?"<<":">>", (int)abs(n) );
      break;
    case use_2pm_2pn:
    case use_1_2pm_2pn:
      printf( "%0+25.21lf x%s= ( x %s %2d ) %s ( x %s %2d )\n", factor, flag==use_2pm_2pn?" ":"-", m>=0?"<<":">>", (int)abs(m), nsign==-1?"-":"+", n>=0?"<<":">>", (int)abs(n));
      break;
  }
}

int main() {
  int n, m, nsign;

  // loop over all constructs in the form +-1*x^+-2n, n=-31..+31
  for (n=-31; n<= 31; ++n )
    for ( nsign=-1; nsign<=1; nsign+=2 )
    {
      // The one term only case
      double v = (double)nsign * pow( 2., (double)n );
      if( v > 0.0 )
          add_record( log(v), n, nsign, m, use_2pn );

      // Loop over second term
      for (m=-31; m<=31; ++m )
      {
        double v = pow( 2.0, (double)m ) + (double)nsign * pow( 2., (double)n );
        if( v <= 0.0 )
          continue;
        add_record( log(v), n, nsign, m, m ? use_2pm_2pn : use_1_2pn );
        if( v < 1.0 )
          add_record( log(1.0 - v), n, nsign, m, use_1_2pm_2pn );
      }
    }

  qsort( g_tr, g_records, sizeof(*g_tr), compare_record );

  for (n=0; n<g_records; ++n )
    dump_record(n);

  return 0;
}