A PWfunction is a point-wise defined function. It is one way of representing data found in a file. It is essentially a table that associates to some points θi a value fi. The BEP program start with converting such a function into a Fourier series, which is completely different way of representing the data.
In the case of continuous-time systems, the transfer function F depends on a complex variable s, is generally analytic in the half-plane Re(s)>0 and data are given for s on the imaginary axis, s=i*ω. In the case of discrete-time systems the transfer function F depends on a complex variable z, is analytic in the unit disk |z|<1 and data are given for z on the unit circle, z=exp(i*θ).
This changes the order of items, by increasing θ
(1) x3:= #Pw 4 10 1 2 3 3 4 7 5 6 2 7 8; (1) <pw function: 10 = 1 + 2 %i, 3 = 3 + 4 %i, 7 = 5 + 6 %i, 2 = 7 + 8 %i> (2) #:pw:reorder(x3); (2) <pw function: 2 = 7 + 8 %i, 3 = 3 + 4 %i, 7 = 5 + 6 %i, 10 = 1 + 2 %i>
These four functions can be used to get or set a value. The functions getcoef and setcoef can also be used to set a value.
[Endymion] (setq x #Pw 4 1 2 3 4 5 6 7 8 9 10 11 12) #Pw 4 1 2 3 4 5 6 7 8 9 10 11 12 [Endymion] (#:pw:get_theta x 0) 1 [Endymion] (#:pw:get_val x 0) [3i+2] [Endymion] (#:pw:set_val x 0 8) 8 [Endymion] (#:pw:set_theta x 0 7) 7 [Endymion] (getcoef x 3) [12i+11] [Endymion] (setcoef x 3 4) 4
You can consider a PWfunction as an array, so that X[i] is the same as getcoef(X,i). You can also consider it as an array with two indices: if the first index theta or omega then #:pw:get_theta is used, if it is value, then getcoef is used. In these cases, the second index is an integer. The index can also be assoc: in this case the second index is some θ and the value associated to this θ is returned. In all these cases, the value in the array can be modified. The first index can also be interpolate; in this case the value associated to this θ is returned, using linear interpolation if appropriate.
(2) x:= #Pw 4 1 2 3 4 5 6 7 8 9 10 11 12; (2) <pw function: 1 = 2 + 3 %i, 4 = 5 + 6 %i, 7 = 8 + 9 %i, 10 = 11 + 12 %i> (3) x[0]; (3) 2 + 3 %i (4) x[0]:=#C(0,1); (4) %i (6) x[theta,3]; (6) 10 (7) x[omega,3]; (7) 10 (8) x[value,3]; (8) 11 + 12 %i (9) x[assoc,10]; (9) 11 + 12 %i (10) x[assoc,10]:=14; (10) 14 (11) x; (11) <pw function: 1 = %i, 4 = 5 + 6 %i, 7 = 8 + 9 %i, 10 = 14> (12) x["interpolation",8]; (12) 10 + 6 %i
Given a PW function f defined by pairs (xi,fi), and a function g, the first function replaces fi by g(xi) (this should be a complex number). The second function replaces xi by h(xi).
[Endymion] (setq x (#:pw:alloc_function 10 0 9)) #Pw 10 0 0 0 1 0 0 2 0 0 3 0 0 4 0 0 5 0 0 6 0 0 7 0 0 8 0 0 9 0 0 [Endymion] (#:pw:fill_function x (lambda (u)(+ 3 (* u #C(2 1))))) #Pw 10 0 3 0 1 5 1 2 7 2 3 9 3 4 11 4 5 13 5 6 15 6 7 17 7 8 19 8 9 21 9 [Endymion] (#:pw:change_theta x (lambda (u)(+ u 3))) #Pw 10 3 3 0 4 5 1 5 7 2 6 9 3 7 11 4 8 13 5 9 15 6 10 17 7 11 19 8 12 21 9 [Endymion] (#:pw:fill_function 'x 'ncons) #:pw:fill_function : Not a pw function : x [Endymion] (#:pw:fill_function x 5) funcall : undefined function : 5 [Endymion] (#:pw:fill_function x 'car) car : not a list : 3 [Endymion] (#:pw:fill_function x 'cons) cons : wrong number of arguments : 1 this should be 2 [Endymion] (#:pw:fill_function x 'ncons) #:pw:fill_function : not a real number : (3) [Endymion] (#:pw:change_theta x 'ncons) #:pw:change_theta : not a real number : (3) [Endymion] (#:pw:change_theta x 'cons) cons : wrong number of arguments : 1 this should be 2 [Endymion] (#:pw:change_theta x 'car) car : not a list : 3 [Endymion] (#:pw:change_theta x '0) funcall : undefined function : 0
Same example, in symbolic mode
(1) x:=#Pw 10 0 0 0 1 0 0 2 0 0 3 0 0 4 0 0 5 0 0 6 0 0 7 0 0 8 0 0 9 0 0; (1) <pw function: 0 = 0, 1 = 0, 2 = 0, 3 = 0, 4 = 0, 5 = 0, 6 = 0, 7 = 0, 8 = 0, 9 = 0> (2) #:pw:fill_function(x,lambda(u, 3+u*#C(2,1))); (2) <pw function: 0 = 3, 1 = 5 + %i, 2 = 7 + 2 %i, 3 = 9 + 3 %i, 4 = 11 + 4 %i, 5 = 13 + 5 %i, 6 = 15 + 6 %i, 7 = 17 + 7 %i, 8 = 19 + 8 %i, 9 = 21 + 9 %i> (3) #:pw:change_theta(x,lambda(u, u+3)); (3) <pw function: 3 = 3, 4 = 5 + %i, 5 = 7 + 2 %i, 6 = 9 + 3 %i, 7 = 11 + 4 %i, 8 = 13 + 5 %i, 9 = 15 + 6 %i, 10 = 17 + 7 %i, 11 = 19 + 8 %i, 12 = 21 + 9 %i>
This function takes as argument a PWfunction, and replaces the real and imaginary parts of the values by 1. The function can be be used as a dummy weight for splines. The effect is the same as (#:pw:fill_function f (lambda (u) #C(1 1)))
[Endymion] (#:pw:set_to_one (#:pw:alloc_function 4 0 3)) #Pw 4 0 1 1 1 1 1 2 1 1 3 1 1 [Endymion] (#:pw:set_to_one 'x) #:pw:set_to_one : Not a pw function : x
These two function take as arguments a PWfunction F and a real number t or complex number v. They add t to each θ or subtract v from each value. The example below shows how these functions could be written in Endymion.
(1) incr(x,y)::=buildq(x:=x+y)?; (2) Shift_theta(f,t):= <<for i in 0...size(f)-1 do incr(f["theta",i], t), f >>; (2) <FUNCTION: Shift_theta> (3) Sub_inf(f,t):= <<for i in 0...size(f)-1 do incr(f[i], -t), f >>; (3) <FUNCTION: Sub_inf> (4) x:=#Pw 4 1 2 3 4 5 6 7 8 9 10 11 12; (4) <pw function: 1 = 2 + 3 %i, 4 = 5 + 6 %i, 7 = 8 + 9 %i, 10 = 11 + 12 %i> (5) #:pw:shift_theta(x,3); (5) <pw function: 4 = 2 + 3 %i, 7 = 5 + 6 %i, 10 = 8 + 9 %i, 13 = 11 + 12 %i> (6) Shift_theta(x,3); (6) <pw function: 7 = 2 + 3 %i, 10 = 5 + 6 %i, 13 = 8 + 9 %i, 16 = 11 + 12 %i> (7) #:pw:sub_inf(x,#C(2 3)); (7) <pw function: 7 = 0, 10 = 3 + 3 %i, 13 = 6 + 6 %i, 16 = 9 + 9 %i> (8) Sub_inf(x,#C(3, 3)); (8) <pw function: 7 = - 3 - 3 %i, 10 = 0, 13 = 3 + 3 %i, 16 = 6 + 6 %i>
This function takes as argument a PW function. The assumption is that the points θi are in increasing order. Assume θj <= a < θj+1. In this case, all pairs (θi,fi) with i less than j are discarded. Moreover θj is replaced by a, and fj is obtained by linear interpolation. The same behavior is applied to the upper bound b. The last argument c is optional, it is ignored unless the value is 1 or 2. Here 1 means: truncate only the lower bound, and 2 means truncate only the upper bound.
[Endymion] (setq x6 (#:pw:alloc_function 5 1 5)) #Pw 5 1 0 0 2 0 0 3 0 0 4 0 0 5 0 0 [Endymion] (defun ff(x) (+ (* x #C(2 1)) 3)) ff [Endymion] (#:pw:fill_function x6 'ff) #Pw 5 1 5 1 2 7 2 3 9 3 4 11 4 5 13 5 [Endymion] (#:pw:skip_unwanted x6 1 5) #Pw 5 1 5 1 2 7 2 3 9 3 4 11 4 5 13 5 [Endymion] (#:pw:skip_unwanted x6 1.3 4.5) #Pw 5 1.3 5.6 1.3 2 7 2 3 9 3 4 11 4 4.5 12 4.5 [Endymion] (#:pw:skip_unwanted x6 1.4 4.5) #Pw 5 1.4 5.8 1.4 2 7 2 3 9 3 4 11 4 4.5 12 4.5 [Endymion] (#:pw:skip_unwanted x6 2.4 4.5) #Pw 4 2.4 7.8 2.4 3 9 3 4 11 4 4.5 12 4.5 [Endymion] (#:pw:skip_unwanted x6 2.4 3.5) #Pw 3 2.4 7.8 2.4 3 9 3 3.5 10 3.5 [Endymion] (#:pw:skip_unwanted x6 2.5 2.6 1) #Pw 3 2.5 8 2.5 3 9 3 3.5 10 3.5 [Endymion] (#:pw:skip_unwanted x6 2.6 3.4 2) #Pw 3 2.5 8 2.5 3 9 3 3.4 9.8 3.4 [Endymion] (#:pw:skip_unwanted x6 1.4 3.5) #:pw:skip_unwanted : Lower bound too small : 1.4 [Endymion] (#:pw:skip_unwanted x6 10.4 3.5) #:pw:skip_unwanted : Lower bound too large : 10.4 [Endymion] (#:pw:skip_unwanted x6 3. 1.4) #:pw:skip_unwanted : Upper bound too small : 1.4 [Endymion] (#:pw:skip_unwanted x6 3. 10.4) #:pw:skip_unwanted : Upper bound too large : 10.4 [Endymion] (#:pw:skip_unwanted x6 'x 3.5) #:pw:skip_unwanted : not a real number : x [Endymion] (#:pw:skip_unwanted x6 3.5 'c) #:pw:skip_unwanted : not a real number : c [Endymion] (#:pw:skip_unwanted 'x6 3.5 4.2) #:pw:skip_unwanted : Not a pw function : x6
This function takes as argument a PW function. The points θi are assumed to be in increasing order. The function modifies F in such a way that the mean value of the data points is PI. Said otherwise, the sum of the first and last θ is 2PI. If the second argument is not true, this is obtained by shifting all points θi. Otherwise, it is obtained by truncating the interval; note that truncation works only if PI is in the data interval.
[Endymion] (setq x5 (#:pw:alloc_function 5 1 5)) #Pw 5 1 0 0 2 0 0 3 0 0 4 0 0 5 0 0 [Endymion] (defun ff(x) x) ff [Endymion] (#:pw:fill_function x5 'ff) #Pw 5 1 1 0 2 2 0 3 3 0 4 4 0 5 5 0 [Endymion] (#:pw:make_symmetric x5 false) #Pw 5 1.14159265358979 1 0 2.14159265358979 2 0 3.14159265358979 3 0 4.14159265358979 4 0 5.14159265358979 5 0 [Endymion] (setq x5 (#:pw:alloc_function 10 0 9)) #Pw 10 0 0 0 1 0 0 2 0 0 3 0 0 4 0 0 5 0 0 6 0 0 7 0 0 8 0 0 9 0 0 [Endymion] (#:pw:fill_function x5 'ff) #Pw 10 0 0 0 1 1 0 2 2 0 3 3 0 4 4 0 5 5 0 6 6 0 7 7 0 8 8 0 9 9 0 [Endymion] (#:pw:make_symmetric x5 true) #Pw 8 0 0 0 1 1 0 2 2 0 3 3 0 4 4 0 5 5 0 6 6 0 6.28318530717959 6.28318530717959 0 [Endymion] (setq x5 (#:pw:alloc_function 7 0 6)) #Pw 7 0 0 0 1 0 0 2 0 0 3 0 0 4 0 0 5 0 0 6 0 0 [Endymion] (#:pw:fill_function x5 'ff) #Pw 7 0 0 0 1 1 0 2 2 0 3 3 0 4 4 0 5 5 0 6 6 0 [Endymion] (#:pw:make_symmetric x5 true) #Pw 7 0.283185307179586 0.283185307179586 0 1 1 0 2 2 0 3 3 0 4 4 0 5 5 0 6 6 0 [Endymion] (setq x5 (#:pw:alloc_function 3 10 11)) #Pw 3 10 0 0 10.5 0 0 11 0 0 [Endymion] (#:pw:make_symmetric x5 true) #:pw:make_symmetric : Upper bound too small : -3.71681469282041 [Endymion] (#:pw:make_symmetric 'x5 true) #:pw:make_symmetric : Not a pw function : x5
Given a PWfunction F, this function computes a and b such that F(z) and a*z+b take the same value at z0 and z1, and replaces f(z) by f(z)-(a*z+b). Here z=exp(i*θ), z0 and z1 correspond to the first and last θ. The function could be defined as follows.
get_z(F,i)::=buildq(#exp(%%i*F["theta",i])); /* The z associated to θi */ subline(F):= let(n = size(F), let([t1 = get_z(F,0), t2 = get_z(F,n-1), u = F[0], v = F[n-1], a=0,b=0], a:=(u-v)/(t1-t2), b:=(t1*v-t2*u)/(t1-t2), for i in 0...n-1 do decrement(F[i], b+a*get_z(F,i)), #cons(a,b))); /* return a and b as a Lisp cons */
The function (#:pw:alloc_function n a b) creates a PW function, with n evaluation points, between a and b, filled with zeroes. Some examples of what can be done.
[Endymion] (setq x (#:pw:alloc_function 10 0 9)) #Pw 10 0 0 0 1 0 0 2 0 0 3 0 0 4 0 0 5 0 0 6 0 0 7 0 0 8 0 0 9 0 0 [Endymion] (#:pw:set_to_one x) #Pw 10 0 1 1 1 1 1 2 1 1 3 1 1 4 1 1 5 1 1 6 1 1 7 1 1 8 1 1 9 1 1 [Endymion] (#:pw:fill_function x (lambda (u)(+ 3 (* u #C(2 1))))) #Pw 10 0 3 0 1 5 1 2 7 2 3 9 3 4 11 4 5 13 5 6 15 6 7 17 7 8 19 8 9 21 9 [Endymion] (#:pw:set_theta x 3 3.3) 3.3 [Endymion] (#:pw:get_theta x 3) 3.3 [Endymion] (setcoef x 3 #C(9.6 3.3)) [3.3i+9.6] [Endymion] (getcoef x 3) [3.3i+9.6] [Endymion] (#:pw:skip_unwanted x 2 5.5) #Pw 5 2 7 2 3.3 9.6 3.3 4 11 4 5 13 5 5.5 14 5.5 [Endymion] (#:pw:change_theta x (lambda(u) (* 2 u))) #Pw 5 4 7 2 6.6 9.6 3.3 8 11 4 10 13 5 11 14 5.5 [Endymion] (#:pw:shift_theta x -3) #Pw 5 1 7 2 3.6 9.6 3.3 5 11 4 7 13 5 8 14 5.5 [Endymion] (#:pw:sub_inf x 3) #Pw 5 1 4 2 3.6 6.6 3.3 5 8 4 7 10 5 8 11 5.5 [Endymion] (setq x5 (#:pw:alloc_function 5 1 5)) #Pw 5 1 0 0 2 0 0 3 0 0 4 0 0 5 0 0 [Endymion] (#:pw:make_symmetric x5 false) #Pw 5 1.14159265358979 0 0 2.14159265358979 0 0 3.14159265358979 0 0 4.14159265358979 0 0 5.14159265358979 0 0 [Endymion] (setq x5 (#:pw:alloc_function 10 0 9)) #Pw 10 0 0 0 1 0 0 2 0 0 3 0 0 4 0 0 5 0 0 6 0 0 7 0 0 8 0 0 9 0 0 [Endymion] (#:pw:make_symmetric x5 true) #Pw 8 0 0 0 1 0 0 2 0 0 3 0 0 4 0 0 5 0 0 6 0 0 6.28318530717959 0 0
back to home page © INRIA 2008 Last modified $Date: 2008/10/13 07:45:27 $