View Raw SPL
/* get important frequency values for continuous system - see freqs.spl */
freqsvals(a, b, npts)
{
local i, integ, w, xi, f, z;
if (argc == 2)
{
// assume cascade
(ep, tz, k) = cas2zp(a);
npts = b;
}
else
{
// direct form
ep = roots(b);
tz = roots(a);
}
if (isempty(ep))
{
ep = -1000;
}
// does not handle zeros greater than 1e8
ez = {ep[find(imag(ep) >= 0)], tz[find(abs(tz) < 1e8 && imag(tz) >= 0)]};
// round start and end to nearest decade
integ = abs(ez) < 1e-10; // cater for systems with pure integrators
highfreq = round(log10(max(3 * abs(real(ez) + integ) + 1.5 * imag(ez))) + 0.5);
lowfreq = round(log10(0.1 * min(abs(real(ez + integ)) + 2 * imag(ez))) - 0.5);
// base frequency range
diffzp = length(ep) - length(tz);
w = logspace(lowfreq, highfreq, npts + diffzp + 10 * (sum(abs(imag(tz)) < abs(real(tz))) > 0));
ez = ez[find(imag(ez) > abs(real(ez)))];
// poles and zeros for oscillations
if (not(isempty(ez)))
{
f = w;
npts2 = 2 + 8 / ceil(abs((diffzp + eps) / 10));
(dum, ind) = sort(-abs(real(ez)), 1);
z = {};
loop (i = ind)
{
r1 = max({0.8*imag(ez[i]) - 3 * abs(real(ez[i])), 10 ^ lowfreq});
r2 = 1.2 * imag(ez[i]) + 4 * abs(real(ez[i]));
z = z[find(z > r2 || z < r1)];
f = f[find(f > r2 || f < r1)];
z = {z, logspace(log10(r1), log10(r2), sum(w <= r2 && w >= r1) + npts2)};
}
w = sort({f, z}, 1);
}
/* interpolate on a uniform log grid */
xi = linspace(1, length(w), npts - 1);
w = xylookup(1..length(w), log10(w), xi);
/* add DC */
w = {0, 10^yvals(w)};
return(w);
}