Imported Upstream version 4.6.0
[debian/atlc] / src / non_gui / calculate_integer_values.c
1 /* atlc - arbitrary transmission line calculator, for the analysis of
2 transmission lines are directional couplers. 
3
4 Copyright (C) 2002. Dr. David Kirkby, PhD (G8WRB).
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either package_version 2
9 of the License, or (at your option) any later package_version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
19 USA.
20
21 Dr. David Kirkby, e-mail drkirkby at ntlworld.com 
22
23 */
24
25 /* The following calculates the odd and even mode impedances between two
26 zero thickness strips of width w, spaced a distance s between two
27 groundplanes of spacing h. */
28
29 #include "config.h"
30 #include "definitions.h"
31
32 #ifdef HAVE_STDLIB_H
33 #include <stdlib.h>
34 #endif
35
36 double calculate_integer_values(struct transmission_line_properties *optimise,int nmax,int accuracy_level)
37 {
38   double grid_size, error, error_max=1e6; 
39   int i, min_pixels, max_pixels, n, min_critical_pixels, max_critical_pixels;
40   int most_critical=0, step=1; 
41   double min_pixel_size, max_pixel_size;
42   double W, H;
43
44   for(i=0;i<9;++i)
45     optimise->best[i]=-1;   /* A silly value, indicating it is not acceptable */
46  
47   /* Let the number of pixel in the image be between 2^n and 2^(n+2) */
48
49   min_pixels=(int) pow(2.0,(double)(accuracy_level-1));
50   max_pixels=(int) pow(2.0,(double)(accuracy_level+1));
51
52   /* Although the stucture W by H has an exact area of W*H, we will    
53   allocate some pixels to  this, which will be much smaller than
54   the W*H. Each pixel will have a variable area, which we don't  
55   know yet, but can put upper and lower limits on it. 
56   */
57
58   W=optimise->float_values[0];  /* The calculated W and H  */ 
59   H=optimise->float_values[1];
60   min_pixel_size=sqrt(W*H/max_pixels);
61   max_pixel_size=sqrt(W*H/min_pixels);
62
63   /* find the most critical dimension */
64   for(n=0;n<nmax;n++)
65   {
66     if(optimise->importance[n]==MOST_IMPORTANT)
67       most_critical=n;
68   }
69   /* we will allocate a number of pixels to this most critical 
70   dimension, set by */
71   
72   min_critical_pixels = optimise->float_values[most_critical]/max_pixel_size;
73   max_critical_pixels = optimise->float_values[most_critical]/min_pixel_size;
74
75
76   /* Normally we would try every combination of i, but it may be necessary to keep it even or odd */
77   if(optimise->odd_or_even[most_critical] == ODD  &&  min_critical_pixels%2==0) 
78     min_critical_pixels--;
79   else if(optimise->odd_or_even[most_critical] == EVEN  &&  min_critical_pixels%2==1) 
80     min_critical_pixels--;
81   if(optimise->odd_or_even[most_critical] != DONT_CARE)
82     step=2;
83
84   for(i=min_critical_pixels; i<max_critical_pixels;i+=step)
85   {
86     /* set the most critical dimension to i pixels, trying every i 
87     between two set limits */
88
89     optimise->int_values[most_critical]=i;
90     grid_size=optimise->float_values[most_critical]/i;
91
92     /* Now set all the others to the optimal, assuming i would be used
93     for the most critical dimension */
94     error=0.0;
95     for(n=0; n<nmax;++n)
96     {
97       optimise->int_values[n]=(int) (0.5+optimise->float_values[n]/grid_size);
98       if (optimise->importance[n] != NOT_IMPORTANT)
99       {
100        error+=fabs((double)optimise->int_values[n]*grid_size-optimise->float_values[n]);
101       }
102     }
103     /* Since the numbers generated for the integers seeme to differ on different
104     computers, I've suspected the problem might be that an error is very
105     similar at two different sets of integer values. Hence I will only
106     consider the error lower its lower by 1e-9. That should avoid silly
107     rounding problems. */
108
109     if(error<(error_max-TINY)) /* The 1e-9 avoids different results on different*/
110     {                          /* machines due to rounding errors */
111      error_max=error;
112      for(n=0; n<nmax;++n)
113        optimise->best[n]=optimise->int_values[n];
114     }
115   }
116   return(error_max); /* return the error */
117 }