1/*.......1.........2.........3.........4.........5.........6.........7.........8
2================================================================================
3
4FILE divide/cfunc.mod
5
6Public Domain
7
8Georgia Tech Research Corporation
9Atlanta, Georgia 30332
10PROJECT A-8503-405
11
12
13AUTHORS
14
15    6 Jun 1991     Jeffrey P. Murray
16
17
18MODIFICATIONS
19
20     2 Oct 1991    Jeffrey P. Murray
21
22
23SUMMARY
24
25    This file contains the model-specific routines used to
26    functionally describe the divide code model.
27
28
29INTERFACES
30
31    FILE                 ROUTINE CALLED
32
33    CMutil.c             void cm_smooth_corner();
34
35
36REFERENCED FILES
37
38    Inputs from and outputs to ARGS structure.
39
40
41NON-STANDARD FEATURES
42
43    NONE
44
45===============================================================================*/
46
47/*=== INCLUDE FILES ====================*/
48
49#include <math.h>
50
51
52
53/*=== CONSTANTS ========================*/
54
55
56
57
58/*=== MACROS ===========================*/
59
60
61
62
63/*=== LOCAL VARIABLES & TYPEDEFS =======*/
64
65
66
67
68/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/
69
70
71
72
73
74/*==============================================================================
75
76FUNCTION void cm_divide()
77
78AUTHORS
79
80     2 Oct 1991     Jeffrey P. Murray
81
82MODIFICATIONS
83
84    NONE
85
86SUMMARY
87
88    This function implements the divide code model.
89
90INTERFACES
91
92    FILE                 ROUTINE CALLED
93
94    CMutil.c             void cm_smooth_corner();
95
96RETURNED VALUE
97
98    Returns inputs and outputs via ARGS structure.
99
100GLOBAL VARIABLES
101
102    NONE
103
104NON-STANDARD FEATURES
105
106    NONE
107
108==============================================================================*/
109
110
111/*=== CM_DIVIDE ROUTINE ===*/
112
113
114void cm_divide(ARGS)
115
116{
117    double den_lower_limit;  /* denominator lower limit */
118	double den_domain;       /* smoothing range for the lower limit */
119	double threshold_upper;  /* value above which smoothing occurs */
120	double threshold_lower;  /* value below which smoothing occurs */
121    double numerator;        /* numerator input */
122	double denominator;      /* denominator input */
123	double limited_den;      /* denominator value if limiting is needed */
124	double den_partial;      /* partial of the output wrt denominator */
125	double out_gain;         /* output gain */
126    double num_gain;         /* numerator gain */
127	double den_gain;         /* denominator gain */
128
129    Mif_Complex_t ac_gain;
130
131
132
133    /* Retrieve frequently used parameters... */
134
135    den_lower_limit = PARAM(den_lower_limit);
136    den_domain = PARAM(den_domain);
137    out_gain = PARAM(out_gain);
138    num_gain = PARAM(num_gain);
139    den_gain = PARAM(den_gain);
140
141
142    if (PARAM(fraction) == MIF_TRUE)    /* Set domain to absolute value */
143        den_domain = den_domain * den_lower_limit;
144
145    threshold_upper = den_lower_limit +   /* Set Upper Threshold */
146                         den_domain;
147
148    threshold_lower = den_lower_limit -   /* Set Lower Threshold */
149                         den_domain;
150
151    numerator = (INPUT(num) + PARAM(num_offset)) * num_gain;
152    denominator = (INPUT(den) + PARAM(den_offset)) * den_gain;
153
154    if ((denominator < threshold_upper) && (denominator >= 0)) {  /* Need to limit den...*/
155
156        if (denominator > threshold_lower)   /* Parabolic Region */
157            cm_smooth_corner(denominator,den_lower_limit,
158                        den_lower_limit,den_domain,0.0,1.0,
159                        &limited_den,&den_partial);
160
161        else {                            /* Hard-Limited Region */
162            limited_den = den_lower_limit;
163            den_partial = 0.0;
164        }
165    }
166	else
167    if ((denominator > -threshold_upper) && (denominator < 0)) {  /* Need to limit den...*/
168        if (denominator < -threshold_lower)   /* Parabolic Region */
169            cm_smooth_corner(denominator,-den_lower_limit,
170                        -den_lower_limit,den_domain,0.0,1.0,
171                        &limited_den,&den_partial);
172
173        else {                            /* Hard-Limited Region */
174            limited_den = -den_lower_limit;
175            den_partial = 0.0;
176        }
177    }
178    else {                         /* No limiting needed */
179        limited_den = denominator;
180        den_partial = 1.0;
181    }
182
183    if (ANALYSIS != MIF_AC) {
184
185        OUTPUT(out) = PARAM(out_offset) + out_gain *
186                         ( numerator/limited_den );
187        PARTIAL(out,num) = out_gain * num_gain / limited_den;
188        PARTIAL(out,den) = -out_gain * numerator * den_gain *
189                            den_partial / (limited_den * limited_den);
190
191    }
192    else {
193        ac_gain.real = out_gain * num_gain / limited_den;
194        ac_gain.imag= 0.0;
195        AC_GAIN(out,num) = ac_gain;
196
197        ac_gain.real = -out_gain * numerator * den_gain *
198                            den_partial / (limited_den * limited_den);
199        ac_gain.imag= 0.0;
200        AC_GAIN(out,den) = ac_gain;
201    }
202
203}
204