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;
}
|