📄 cfunc.mod
字号:
if (INIT==1) { /* First pass...allocate storage for previous value... */ /* Allocate storage for last_x_value */ STATIC_VAR(last_x_value) = (double *) malloc(sizeof(double)); last_x_value = STATIC_VAR(last_x_value); /* Allocate storage for breakpoint domain & range values */ STATIC_VAR(x) = (double *) calloc(size, sizeof(double)); x = STATIC_VAR(x); if (x == '\0') { cm_message_send(allocation_error); } STATIC_VAR(y) = (double *) calloc(size, sizeof(double)); y = STATIC_VAR(y); if (y == '\0') { cm_message_send(allocation_error); } /* Retrieve x and y values. */ for (i=0; i<size; i++) { x[i] = PARAM(x_array[i]); y[i] = PARAM(y_array[i]); } } else { last_x_value = STATIC_VAR(last_x_value); x = STATIC_VAR(x); y = STATIC_VAR(y); } /* See if input_domain is absolute...if so, test against */ /* breakpoint segments for violation of 50% rule... */ if (PARAM(fraction) == MIF_FALSE) { if ( 3 < size ) { for (i=1; i<(size-2); i++) { /* Test for overlap...0.999999999 factor is to */ /* prevent floating point problems with comparison. */ if ( (test1 = x[i+1] - x[i]) < (test2 = 0.999999999 * (2.0 * input_domain)) ) { cm_message_send(limit_error); } } } } /* Retrieve x_input value. */ x_input = INPUT(in); /* If this is the first call, set *last_x_value to x_input */ if (INIT == 1) *last_x_value=x_input; /*** Add debugging printf statement ***/ /* printf("Last x_input=%e, Current x_input=%e,\n", *last_x_value,x_input); */ /**** Add internal limiting to input value ****/ /* Determine region of input, and limit accordingly */ if ( *last_x_value < x[0] ) { /** Non-limited input less than x[0] **/ /* Obtain the test value of the input, if it has changed excessively */ if ( (x[0] - x_input) > (x[1] - x[0]) ) { test = limit_x_value(x_input,x[0],x_input,FRACTION,last_x_value); } else { test = limit_x_value(x[0],x[1],x_input,FRACTION,last_x_value); } /* If the test value is greater than x[0], force to x[0] */ if ( test >= x[0] ) { x_input = *last_x_value = x[0]; /* Alert the simulator to non-convergence */ cm_analog_not_converged(); } else { x_input = *last_x_value = test; } } else if ( *last_x_value >= x[size-1] ) { /** Non-Limited input greater than x[size-1] **/ /* Obtain the test value of the input, if it has changed excessively */ if ( (x_input - x[size-1]) > (x[size-1] - x[size-2]) ) { test = limit_x_value(x[size-1],x_input,x_input,FRACTION,last_x_value); } else { test = limit_x_value(x[size-2],x[size-1],x_input,FRACTION,last_x_value); } /* If the test value is less than x[size-1], force to x[size-1] */ /* minus some epsilon value. */ if ( test < x[size-1] ) { x_input = *last_x_value = x[size-1] - EPSILON; /* Alert the simulator to non-convergence */ cm_analog_not_converged(); } else { x_input = *last_x_value = test; } } else { for (i=1; i<size; i++) { if ( *last_x_value < x[i] ) { /* Obtain the test value of the input */ test = limit_x_value(x[i-1],x[i],x_input,FRACTION,last_x_value); /* If the test value is greater than x[i], force to x[i] */ if ( test > x[i] ) { x_input = *last_x_value = x[i]; /* Alert the simulator to non-convergence */ cm_analog_not_converged(); break; } else /* If the test value is less than x[i-1], force to x[i-1] */ /* minus some epsilon value... */ if ( test < x[i-1] ) { x_input = *last_x_value = x[i-1] - EPSILON; /* Alert the simulator to non-convergence */ cm_analog_not_converged(); break; } else { /* Use returned value for next input */ x_input = *last_x_value = test; break; } } } } /* Assign new limited value back to the input for */ /* use in the matrix calculations.... */ INPUT(in) = x_input; /*** Add debugging printf statement ***/ /* printf("Limited x_input=%e\n\n", x_input); */ /**** End internal limiting ****/ /* Determine segment boundaries within which x_input resides */ if (x_input <= (x[0] + x[1])/2.0) {/*** x_input below lowest midpoint ***/ dout_din = (y[1] - y[0])/(x[1] - x[0]); /* Compute new output */ out = y[0] + (x_input - x[0]) * dout_din; } else { if (x_input >= (x[size-2] + x[size-1])/2.0) { /*** x_input above highest midpoint ***/ dout_din = (y[size-1] - y[size-2]) / (x[size-1] - x[size-2]); out = y[size-1] + (x_input - x[size-1]) * dout_din; } else { /*** x_input within bounds of end midpoints... ***/ /*** must determine position progressively & then ***/ /*** calculate required output. ***/ for (i=1; i<size; i++) { if (x_input < (x[i] + x[i+1])/2.0) { /* approximate position known... */ lower_seg = (x[i] - x[i-1]); upper_seg = (x[i+1] - x[i]); /* Calculate input_domain about this region's breakpoint.*/ if (PARAM(fraction) == MIF_TRUE) { /* Translate input_domain */ /* into an absolute.... */ if ( lower_seg <= upper_seg ) /* Use lower */ /* segment */ /* for % calc.*/ input_domain = input_domain * lower_seg; else /* Use upper */ /* segment */ /* for % calc.*/ input_domain = input_domain * upper_seg; } /* Set up threshold values about breakpoint... */ threshold_lower = x[i] - input_domain; threshold_upper = x[i] + input_domain; /* Determine where x_input is within region & determine */ /* output and partial values.... */ if (x_input < threshold_lower) { /* Lower linear region */ dout_din = (y[i] - y[i-1])/lower_seg; out = y[i] + (x_input - x[i]) * dout_din; } else { if (x_input < threshold_upper) { /* Parabolic region */ lower_slope = (y[i] - y[i-1])/lower_seg; upper_slope = (y[i+1] - y[i])/upper_seg; cm_smooth_corner(x_input,x[i],y[i],input_domain, lower_slope,upper_slope,&out,&dout_din); } else { /* Upper linear region */ dout_din = (y[i+1] - y[i])/upper_seg; out = y[i] + (x_input - x[i]) * dout_din; } } break; /* Break search loop...x_input has been found, */ /* and out and dout_din have been assigned. */ } } } } if(ANALYSIS != MIF_AC) { /* Output DC & Transient Values */ OUTPUT(out) = out; PARTIAL(out,in) = dout_din; } else { /* Output AC Gain */ ac_gain.real = dout_din; ac_gain.imag= 0.0; AC_GAIN(out,in) = ac_gain; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -