diff options
author | dos-reis <gdr@axiomatics.org> | 2007-08-14 05:14:52 +0000 |
---|---|---|
committer | dos-reis <gdr@axiomatics.org> | 2007-08-14 05:14:52 +0000 |
commit | ab8cc85adde879fb963c94d15675783f2cf4b183 (patch) | |
tree | c202482327f474583b750b2c45dedfc4e4312b1d /src/hyper/pages/ug10.ht | |
download | open-axiom-ab8cc85adde879fb963c94d15675783f2cf4b183.tar.gz |
Initial population.
Diffstat (limited to 'src/hyper/pages/ug10.ht')
-rw-r--r-- | src/hyper/pages/ug10.ht | 1119 |
1 files changed, 1119 insertions, 0 deletions
diff --git a/src/hyper/pages/ug10.ht b/src/hyper/pages/ug10.ht new file mode 100644 index 00000000..aff71675 --- /dev/null +++ b/src/hyper/pages/ug10.ht @@ -0,0 +1,1119 @@ +% Copyright The Numerical Algorithms Group Limited 1992-94. All rights reserved. +% !! DO NOT MODIFY THIS FILE BY HAND !! Created by ht.awk. +\texht{\setcounter{chapter}{9}}{} % Chapter 10 + +% +\newcommand{\ugIntProgTitle}{Interactive Programming} +\newcommand{\ugIntProgNumber}{10.} +% +% ===================================================================== +\begin{page}{ugIntProgPage}{10. Interactive Programming} +% ===================================================================== +\beginscroll + +Programming in the interpreter is easy. +So is the use of \Language{}'s graphics facility. +Both are rather flexible and allow you to use them for many +interesting applications. +However, both require learning some basic ideas and skills. + +All graphics examples in the \Gallery{} section are either +produced directly by interactive commands or by interpreter +programs. +Four of these programs are introduced here. +By the end of this chapter you will know enough about graphics and +programming in the interpreter to not only understand all these +examples, but to tackle interesting and difficult problems on your +own. +\downlink{``\ugAppGraphicsTitle''}{ugAppGraphicsPage} in Appendix \ugAppGraphicsNumber\ignore{ugAppGraphics} lists all the remaining commands and +programs used to create these images. + +\beginmenu + \menudownlink{{10.1. Drawing Ribbons Interactively}}{ugIntProgDrawingPage} + \menudownlink{{10.2. A Ribbon Program}}{ugIntProgRibbonPage} + \menudownlink{{10.3. Coloring and Positioning Ribbons}}{ugIntProgColorPage} + \menudownlink{{10.4. Points, Lines, and Curves}}{ugIntProgPLCPage} + \menudownlink{{10.5. A Bouquet of Arrows}}{ugIntProgColorArrPage} + \menudownlink{{10.6. Drawing Complex Vector Fields}}{ugIntProgVecFieldsPage} + \menudownlink{{10.7. Drawing Complex Functions}}{ugIntProgCompFunsPage} + \menudownlink{{10.8. Functions Producing Functions}}{ugIntProgFunctionsPage} + \menudownlink{{10.9. Automatic Newton Iteration Formulas}}{ugIntProgNewtonPage} +\endmenu +\endscroll +\autobuttons +\end{page} +% +% +\newcommand{\ugIntProgDrawingTitle}{Drawing Ribbons Interactively} +\newcommand{\ugIntProgDrawingNumber}{10.1.} +% +% ===================================================================== +\begin{page}{ugIntProgDrawingPage}{10.1. Drawing Ribbons Interactively} +% ===================================================================== +\beginscroll +% + +We begin our discussion of interactive graphics with the creation +of a useful facility: plotting ribbons of two-graphs in +three-space. +Suppose you want to draw the \twodim{} graphs of \smath{n} +functions \texht{$f_i(x), 1 \leq i \leq n,$}{\spad{f_i(x), 1 <= i +<= 5,}} all over some fixed range of \smath{x}. +One approach is to create a \twodim{} graph for each one, then +superpose one on top of the other. +What you will more than likely get is a jumbled mess. +Even if you make each function a different color, the result is +likely to be confusing. + +A better approach is to display each of the \smath{f_i(x)} in three +%-% \HDindex{ribbon}{ugIntProgDrawingPage}{10.1.}{Drawing Ribbons Interactively} +dimensions as a ``ribbon'' of some appropriate width along the +\smath{y}-direction, laying down each ribbon next to the +previous one. +A ribbon is simply a function of \smath{x} and \smath{y} depending +only on \smath{x.} + +We illustrate this for \smath{f_i(x)} defined as simple powers of +\smath{x} for \smath{x} ranging between \smath{-1} and \smath{1}. + +\psXtc{ +Draw the ribbon for \texht{$z = x^2$}{\spad{z=x ** 2}}. +}{ +\graphpaste{draw(x**2,x=-1..1,y=0..1)} +}{ +\epsffile[0 0 295 295]{../ps/ribbon1.ps} +} + +Now that was easy! +What you get is a ``wire-mesh'' rendition of the ribbon. +That's fine for now. +Notice that the mesh-size is small in both the \smath{x} and the +\smath{y} directions. +\Language{} normally computes points in both these directions. +This is unnecessary. +One step is all we need in the \smath{y}-direction. +To have \Language{} economize on \spad{y}-points, we re-draw the +ribbon with option \spad{var2Steps == 1}. + +\psXtc{ +Re-draw the ribbon, but with option \spad{var2Steps == 1} +so that only \spad{1} step is computed in the +\smath{y} direction. +}{ +\graphpaste{vp := draw(x**2,x=-1..1,y=0..1,var2Steps==1) \bound{d1}} +}{ +\epsffile[0 0 295 295]{../ps/ribbon2.ps} +} + +The operation has created a viewport, that is, a graphics window +on your screen. +We assigned the viewport to \spad{vp} and now we manipulate +its contents. + + +Graphs are objects, like numbers and algebraic expressions. +You may want to do some experimenting with graphs. +For example, say +\begin{verbatim} +showRegion(vp, "on") +\end{verbatim} +to put a bounding box around the ribbon. +Try it! +Issue \spad{rotate(vp, -45, 90)} to rotate the +figure \smath{-45} longitudinal degrees and \smath{90} latitudinal +degrees. + +\psXtc{ +Here is a different rotation. +This turns the graph so you can view it along the \smath{y}-axis. +}{ +\spadpaste{rotate(vp, 0, -90)\bound{d3}\free{d1}} +}{ +\epsffile[0 0 295 295]{../ps/ribbon2r.ps} +} + +There are many other things you can do. +In fact, most everything you can do interactively using the +\threedim{} control panel (such as translating, zooming, resizing, +coloring, perspective and lighting selections) can also be done +directly by operations (see \downlink{``\ugGraphTitle''}{ugGraphPage} in Chapter \ugGraphNumber\ignore{ugGraph} for more details). + +When you are done experimenting, say \spad{reset(vp)} to restore the +picture to its original position and settings. + + +Let's add another ribbon to our picture---one +for \texht{$x^3$}{\spad{x**3}}. +Since \smath{y} ranges from \smath{0} to \smath{1} for the +first ribbon, now let \smath{y} range from \smath{1} to +\smath{2.} +This puts the second ribbon next to the first one. + +How do you add a second ribbon to the viewport? +One method is +to extract the ``space'' component from the +viewport using the operation +\spadfunFrom{subspace}{ThreeDimensionalViewport}. +You can think of the space component as the object inside the +window (here, the ribbon). +Let's call it \spad{sp}. +To add the second ribbon, you draw the second ribbon using the +option \spad{space == sp}. + +\xtc{ +Extract the space component of \spad{vp}. +}{ +\spadpaste{sp := subspace(vp)\bound{d5}\free{d1}} +} + +\psXtc{ +Add the ribbon for +\texht{$x^3$}{\spad{x**3}} alongside that for +\texht{$x^2$}{\spad{x**2}}. +}{ +\graphpaste{vp := draw(x**3,x=-1..1,y=1..2,var2Steps==1, space==sp)\bound{d6}\free{d5}} +}{ +\epsffile[0 0 295 295]{../ps/ribbons.ps} +} + +Unless you moved the original viewport, the new viewport covers +the old one. +You might want to check that the old object is still there by +moving the top window. + +Let's show quadrilateral polygon outlines on the ribbons and then +enclose the ribbons in a box. + +\psXtc{ +Show quadrilateral polygon outlines. +}{ +\spadpaste{drawStyle(vp,"shade");outlineRender(vp,"on")\bound{d10}\free{d6}} +}{ +\epsffile[0 0 295 295]{../ps/ribbons2.ps} +} +\psXtc{ +Enclose the ribbons in a box. +}{ +\spadpaste{rotate(vp,20,-60); showRegion(vp,"on")\bound{d11}\free{d10}} +}{ +\epsffile[0 0 295 295]{../ps/ribbons2b.ps} +} + +This process has become tedious! +If we had to add two or three more ribbons, we would have to +repeat the above steps several more times. +It is time to write an interpreter program to help us take care of +the details. + +\endscroll +\autobuttons +\end{page} +% +% +\newcommand{\ugIntProgRibbonTitle}{A Ribbon Program} +\newcommand{\ugIntProgRibbonNumber}{10.2.} +% +% ===================================================================== +\begin{page}{ugIntProgRibbonPage}{10.2. A Ribbon Program} +% ===================================================================== +\beginscroll +% + +The above approach creates a new viewport for each additional +ribbon. +A better approach is to build one object composed of all ribbons +before creating a viewport. +To do this, use \spadfun{makeObject} rather than \spadfun{draw}. +The operations have similar formats, but +\spadfun{draw} returns a viewport and +\spadfun{makeObject} returns a space object. + +We now create a function \userfun{drawRibbons} of two arguments: +\spad{flist}, a list of formulas for the ribbons you want to draw, +and \spad{xrange}, the range over which you want them drawn. +Using this function, you can just say +\begin{verbatim} +drawRibbons([x**2, x**3], x=-1..1) +\end{verbatim} +to do all of the work required in the last section. +Here is the \userfun{drawRibbons} program. +Invoke your favorite editor and create a file called {\bf ribbon.input} +containing the following program. + +\beginImportant + +\noindent +{\tt 1.\ \ \ drawRibbons(flist,\ xrange)\ ==}\newline +{\tt 2.\ \ \ \ \ sp\ :=\ createThreeSpace()}\newline +{\tt 3.\ \ \ \ \ y0\ :=\ 0}\newline +{\tt 4.\ \ \ \ \ for\ f\ in\ flist\ repeat}\newline +{\tt 5.\ \ \ \ \ \ \ makeObject(f,\ xrange,\ y=y0..y0+1,\ }\newline +{\tt 6.\ \ \ \ \ \ \ \ \ \ space==sp,\ var2Steps\ ==\ 1)}\newline +{\tt 7.\ \ \ \ \ \ \ y0\ :=\ y0\ +\ 1}\newline +{\tt 8.\ \ \ \ \ vp\ :=\ makeViewport3D(sp,\ "Ribbons")}\newline +{\tt 9.\ \ \ \ \ drawStyle(vp,\ "shade")}\newline +{\tt 10.\ \ \ \ outlineRender(vp,\ "on")}\newline +{\tt 11.\ \ \ \ showRegion(vp,"on")}\newline +{\tt 12.\ \ \ \ n\ :=\ \#\ flist}\newline +{\tt 13.\ \ \ \ zoom(vp,n,1,n)}\newline +{\tt 14.\ \ \ \ rotate(vp,0,75)}\newline +{\tt 15.\ \ \ \ vp}\newline +\caption{The first \protect\pspadfun{drawRibbons} function.}\label{fig-ribdraw1} +\endImportant + +Here are some remarks on the syntax used in the \pspadfun{drawRibbons} function +(consult \downlink{``\ugUserTitle''}{ugUserPage} in Chapter \ugUserNumber\ignore{ugUser} for more details). +Unlike most other programming languages which use semicolons, +parentheses, or {\it begin}--{\it end} brackets to delineate the +structure of programs, the structure of an \Language{} program is +determined by indentation. +The first line of the function definition always begins in column 1. +All other lines of the function are indented with respect to the first +line and form a \spadgloss{pile} (see \downlink{``\ugLangBlocksTitle''}{ugLangBlocksPage} in Section \ugLangBlocksNumber\ignore{ugLangBlocks}). + +The definition of \userfun{drawRibbons} +consists of a pile of expressions to be executed one after +another. +Each expression of the pile is indented at the same level. +Lines 4-7 designate one single expression: +since lines 5-7 are indented with respect to the others, these +lines are treated as a continuation of line 4. +Also since lines 5 and 7 have the same indentation level, these +lines designate a pile within the outer pile. + +The last line of a pile usually gives the value returned by the +pile. +Here it is also the value returned by the function. +\Language{} knows this is the last line of the function because it +is the last line of the file. +In other cases, a new expression beginning in column one signals +the end of a function. + +The line \spad{drawStyle(vp,"shade")} is given after the viewport +has been created to select the draw style. +We have also used the \spadfunFrom{zoom}{ThreeDimensionalViewport} +option. +Without the zoom, the viewport region would be scaled equally in +all three coordinate directions. + +Let's try the function \userfun{drawRibbons}. +First you must read the file to give \Language{} the function definition. + +\xtc{ +Read the input file. +}{ +\spadpaste{)read ribbon \bound{s0}} +} +\psXtc{ +Draw ribbons for \texht{$x, x^2,\dots, x^5$}{x, x**2,...,x**5} +for \texht{$-1 \leq x \leq 1$}{-1 <= x <= 1} +}{ +\graphpaste{drawRibbons([x**i for i in 1..5],x=-1..1) \free{s0}} +}{ +\epsffile[0 0 295 295]{../ps/ribbons5.ps} +} + + +\endscroll +\autobuttons +\end{page} +% +% +\newcommand{\ugIntProgColorTitle}{Coloring and Positioning Ribbons} +\newcommand{\ugIntProgColorNumber}{10.3.} +% +% ===================================================================== +\begin{page}{ugIntProgColorPage}{10.3. Coloring and Positioning Ribbons} +% ===================================================================== +\beginscroll +% + +Before leaving the ribbon example, we make two improvements. +Normally, the color given to each point in the space is a +function of its height within a bounding box. +The points at the bottom of the +box are red, those at the top are purple. + +To change the normal coloring, you can give +an option \spad{colorFunction == {\it function}}. +When \Language{} goes about displaying the data, it +determines the range of colors used for all points within the box. +\Language{} then distributes these numbers uniformly over the number of hues. +Here we use the simple color function +\texht{$(x,y) \mapsto i$}{(x,y) +-> i} for the +\eth{\smath{i}} ribbon. + +Also, we add an argument \spad{yrange} so you can give the range of +\spad{y} occupied by the ribbons. +For example, if the \spad{yrange} is given as +\spad{y=0..1} and there are \smath{5} ribbons to be displayed, each +ribbon would have width \smath{0.2} and would appear in the +range \texht{$0 \leq y \leq 1$}{\spad{0 <= y <= 1}}. + +Refer to lines 4-9. +Line 4 assigns to \spad{yVar} the variable part of the +\spad{yrange} (after all, it need not be \spad{y}). +Suppose that \spad{yrange} is given as \spad{t = a..b} where \spad{a} and +\spad{b} have numerical values. +Then line 5 assigns the value of \spad{a} to the variable \spad{y0}. +Line 6 computes the width of the ribbon by dividing the difference of +\spad{a} and \spad{b} by the number, \spad{num}, of ribbons. +The result is assigned to the variable \spad{width}. +Note that in the for-loop in line 7, we are iterating in parallel; it is +not a nested loop. + +\beginImportant + +\noindent +{\tt 1.\ \ \ drawRibbons(flist,\ xrange,\ yrange)\ ==}\newline +{\tt 2.\ \ \ \ \ sp\ :=\ createThreeSpace()}\newline +{\tt 3.\ \ \ \ \ num\ :=\ \#\ flist}\newline +{\tt 4.\ \ \ \ \ yVar\ :=\ variable\ yrange}\newline +{\tt 5.\ \ \ \ \ y0:Float\ \ \ \ :=\ lo\ segment\ yrange}\newline +{\tt 6.\ \ \ \ \ width:Float\ :=\ (hi\ segment\ yrange\ -\ y0)/num}\newline +{\tt 7.\ \ \ \ \ for\ f\ in\ flist\ for\ color\ in\ 1..num\ repeat}\newline +{\tt 8.\ \ \ \ \ \ \ makeObject(f,\ xrange,\ yVar\ =\ y0..y0+width,}\newline +{\tt 9.\ \ \ \ \ \ \ \ \ var2Steps\ ==\ 1,\ colorFunction\ ==\ (x,y)\ +->\ color,\ \_}\newline +{\tt 10.\ \ \ \ \ \ \ \ space\ ==\ sp)}\newline +{\tt 11.\ \ \ \ \ \ y0\ :=\ y0\ +\ width}\newline +{\tt 12.\ \ \ \ vp\ :=\ makeViewport3D(sp,\ "Ribbons")}\newline +{\tt 13.\ \ \ \ drawStyle(vp,\ "shade")}\newline +{\tt 14.\ \ \ \ outlineRender(vp,\ "on")}\newline +{\tt 15.\ \ \ \ showRegion(vp,\ "on")}\newline +{\tt 16.\ \ \ \ vp}\newline +\caption{The final \protect\pspadfun{drawRibbons} function.}\label{fig-ribdraw2} +\endImportant + + +\endscroll +\autobuttons +\end{page} +% +% +\newcommand{\ugIntProgPLCTitle}{Points, Lines, and Curves} +\newcommand{\ugIntProgPLCNumber}{10.4.} +% +% ===================================================================== +\begin{page}{ugIntProgPLCPage}{10.4. Points, Lines, and Curves} +% ===================================================================== +\beginscroll +% +What you have seen so far is a high-level program using the +graphics facility. +We now turn to the more basic notions of points, lines, and curves +in \threedim{} graphs. +These facilities use small floats (objects +of type \spadtype{DoubleFloat}) for data. +Let us first give names to the small float values \smath{0} and +\smath{1}. +\xtc{ +The small float 0. +}{ +\spadpaste{zero := 0.0@DFLOAT \bound{d1}} +} +\xtc{ +The small float 1. +}{ +\spadpaste{one := 1.0@DFLOAT \bound{d2}} +} +The \spadSyntax{@} sign means ``of the type.'' Thus \spad{zero} is +\smath{0.0} of the type \spadtype{DoubleFloat}. +You can also say \spad{0.0::DFLOAT}. + +Points can have four small float components: \smath{x, y, z} coordinates and an +optional color. +A ``curve'' is simply a list of points connected by straight line +segments. +\xtc{ +Create the point \spad{origin} with color zero, that is, the lowest color +on the color map. +}{ +\spadpaste{origin := point [zero,zero,zero,zero] \free{d1}\bound{d3}} +} +\xtc{ +Create the point \spad{unit} with color zero. +}{ +\spadpaste{unit := point [one,one,one,zero] \free{d1 d2}\bound{d4}} +} +\xtc{ +Create the curve (well, here, a line) from +\spad{origin} to \spad{unit}. +}{ +\spadpaste{line := [origin, unit] \free{d3 d4} \bound{d5}} +} + +We make this line segment into an arrow by adding an arrowhead. +The arrowhead extends to, +say, \spad{p3} on the left, and to, say, \spad{p4} on the right. +To describe an arrow, you tell \Language{} to draw the two curves +\spad{[p1, p2, p3]} and \spad{[p2, p4].} +We also decide through experimentation on +values for \spad{arrowScale}, the ratio of the size of +the arrowhead to the stem of the arrow, and \spad{arrowAngle}, +the angle between the arrowhead and the arrow. + +Invoke your favorite editor and create +an input file called {\bf arrows.input}. +This input file first defines the values of +%\spad{origin},\spad{unit}, +\spad{arrowAngle} and \spad{arrowScale}, then +defines the function \userfun{makeArrow}\texht{$(p_1, p_2)$}{(p1, p2)} to +draw an arrow from point \texht{$p_1$}{p1} to \texht{$p_2$}{p2}. + +\beginImportant + +\noindent +%\xmpLine{origin := point [0.0@DFLOAT,0.0@DFLOAT,0.0@DFLOAT,0.0@DFLOAT]}{The point 0 with color 0.} +%\xmpLine{unit := point [1.0@DFLOAT,1.0@DFLOAT,1.0@DFLOAT,0.0@DFLOAT]}{A second point with color 0.} +%\xmpLine{}{} +{\tt 1.\ \ \ arrowAngle\ :=\ \%pi-\%pi/10.0@DFLOAT}\newline +{\tt 2.\ \ \ arrowScale\ :=\ 0.2@DFLOAT}\newline +{\tt 3.\ \ \ }\newline +{\tt 4.\ \ \ makeArrow(p1,\ p2)\ ==}\newline +{\tt 5.\ \ \ \ \ delta\ :=\ p2\ -\ p1}\newline +{\tt 6.\ \ \ \ \ len\ :=\ arrowScale\ *\ length\ delta}\newline +{\tt 7.\ \ \ \ \ theta\ :=\ atan(delta.1,\ delta.2)}\newline +{\tt 8.\ \ \ \ \ c1\ :=\ len*cos(theta\ +\ arrowAngle)}\newline +{\tt 9.\ \ \ \ \ s1\ :=\ len*sin(theta\ +\ arrowAngle)}\newline +{\tt 10.\ \ \ \ c2\ :=\ len*cos(theta\ -\ arrowAngle)}\newline +{\tt 11.\ \ \ \ s2\ :=\ len*sin(theta\ -\ arrowAngle)}\newline +{\tt 12.\ \ \ \ z\ \ :=\ p2.3*(1\ -\ arrowScale)}\newline +{\tt 13.\ \ \ \ p3\ :=\ point\ [p2.1\ +\ c1,\ p2.2\ +\ s1,\ z,\ p2.4]}\newline +{\tt 14.\ \ \ \ p4\ :=\ point\ [p2.1\ +\ c2,\ p2.2\ +\ s2,\ z,\ p2.4]}\newline +{\tt 15.\ \ \ \ [[p1,\ p2,\ p3],\ [p2,\ p4]]}\newline +\endImportant + +Read the file and then create +an arrow from the point \spad{origin} to the point \spad{unit}. +\xtc{ +Read the input file defining \userfun{makeArrow}. +}{ +\spadpaste{)read arrows\bound{v1}} +} +\xtc{ +Construct the arrow (a list of two curves). +}{ +\spadpaste{arrow := makeArrow(origin,unit)\bound{v2}\free{v1 d3 d4}} +} +\xtc{ +Create an empty object \spad{sp} of type \spad{ThreeSpace}. +}{ +\spadpaste{sp := createThreeSpace()\bound{c1}} +} +\xtc{ +Add each curve of the arrow to the space \spad{sp}. +}{ +\spadpaste{for a in arrow repeat sp := curve(sp,a)\bound{v3}\free{v2}\free{c1}} +} +\psXtc{ +Create a \threedim{} viewport containing that space. +}{ +\graphpaste{vp := makeViewport3D(sp,"Arrow")\bound{v4}\free{v3}} +}{ +\epsffile[0 0 295 295]{../ps/arrow.ps} +} +\psXtc{ +Here is a better viewing angle. +}{ +\spadpaste{rotate(vp,200,-60)\bound{v5}\free{v4}} +}{ +\epsffile[0 0 295 295]{../ps/arrowr.ps} +} + + +\endscroll +\autobuttons +\end{page} +% +% +\newcommand{\ugIntProgColorArrTitle}{A Bouquet of Arrows} +\newcommand{\ugIntProgColorArrNumber}{10.5.} +% +% ===================================================================== +\begin{page}{ugIntProgColorArrPage}{10.5. A Bouquet of Arrows} +% ===================================================================== +\beginscroll + +%\Language{} gathers up all the points of a graph and looks at the range +%of color values given as integers. +%If theses color values range from a minimum value of \spad{a} to a maximum +%value of \spad{b}, then the \spad{a} values are colored red (the +%lowest color in our spectrum), and \spad{b} values are colored +%purple (the highest color), and those in the middle are colored +%green. +%When all the points are the same color as above, \Language{} +%chooses green. + +Let's draw a ``bouquet'' of arrows. +Each arrow is identical. The arrowheads are +uniformly placed on a circle parallel to the \smath{xy}-plane. +Thus the position of each arrow differs only +by the angle \texht{$\theta$}{theta}, +\texht{$0 \leq \theta < 2\pi$}{\spad{0 <= theta < 2*\%pi}}, +between the arrow and +the \smath{x}-axis on the \smath{xy}-plane. + +Our bouquet is rather special: each arrow has a different +color (which won't be evident here, unfortunately). +This is arranged by letting the color of each successive arrow be +denoted by \texht{$\theta$}{theta}. +In this way, the color of arrows ranges from red to green to violet. +Here is a program to draw a bouquet of \smath{n} arrows. + +\beginImportant + +\noindent +{\tt 1.\ \ \ drawBouquet(n,title)\ ==}\newline +{\tt 2.\ \ \ \ \ angle\ :=\ 0.0@DFLOAT}\newline +{\tt 3.\ \ \ \ \ sp\ :=\ createThreeSpace()}\newline +{\tt 4.\ \ \ \ \ for\ i\ in\ 0..n-1\ repeat}\newline +{\tt 5.\ \ \ \ \ \ \ start\ :=\ point\ [0.0@DFLOAT,0.0@DFLOAT,0.0@DFLOAT,angle]\ }\newline +{\tt 6.\ \ \ \ \ \ \ end\ \ \ :=\ point\ [cos\ angle,\ sin\ angle,\ 1.0@DFLOAT,\ angle]}\newline +{\tt 7.\ \ \ \ \ \ \ arrow\ :=\ makeArrow(start,end)}\newline +{\tt 8.\ \ \ \ \ \ \ for\ a\ in\ makeArrow(start,end)\ repeat\ }\newline +{\tt 9.\ \ \ \ \ \ \ \ \ curve(sp,a)}\newline +{\tt 10.\ \ \ \ \ \ angle\ :=\ angle\ +\ 2*\%pi/n}\newline +{\tt 11.\ \ \ \ makeViewport3D(sp,title)}\newline +\endImportant + +\xtc{ +Read the input file. +}{ +\spadpaste{)read bouquet\bound{b1}} +} +\psXtc{ +A bouquet of a dozen arrows. +}{ +\graphpaste{drawBouquet(12,"A Dozen Arrows")\free{b1}} +}{ +\epsffile[0 0 295 295]{../ps/bouquet.ps} +} +\ + +%\head{section}{Diversion: When Things Go Wrong}{ugIntProgDivTwo} +% +%Up to now, if you have typed in all the programs exactly as they are in +%the book, you have encountered no errors. +%In practice, however, it is easy to make mistakes. +%Computers are unforgiving: your program must be letter-for-letter correct +%or you will encounter some error. +% +%One thing that can go wrong is that you can create a syntactically +%incorrect program. +%As pointed out in Diversion 1, the meaning of \Language{} programs is +%affected by indentation. +% +%The \Language{} parser will ensure that all parentheses, brackets, and +%braces balance, and that commas and operators appear in the correct +%context. +%For example, change line ?? +%to ?? +%and run. +% +%A common mistake is to misspell an identifier or operation name. +%These are generally easy to spot since the interpreter will tell you the +%name of the operation together with the type and number of arguments which +%it is trying to find. +% +%Another mistake is to either to omit an argument or to give too many. +%Again \Language{} will notify you of the offending operation. +% +%Indentation makes your programs more readable. +%However there are several ways to create a syntactically valid program. +%A most common problem occurs when a line is either indented improperly. +%% either or what? +%If this is a first line of a pile, then all the other lines will act as an +%inner pile to the first line. +%If it is a line of the pile other than the first line, \Language{} then +%thinks that this line is a continuation of the previous line. +%More frequently than not, a syntactically correct expression is created. +%Almost never however will this be a semantically correct. +%Only when the program is run will an error be discovered. +%For example, change line ?? +%to ?? +%and run. + +\endscroll +\autobuttons +\end{page} +% +% +\newcommand{\ugIntProgVecFieldsTitle}{Drawing Complex Vector Fields} +\newcommand{\ugIntProgVecFieldsNumber}{10.6.} +% +% ===================================================================== +\begin{page}{ugIntProgVecFieldsPage}{10.6. Drawing Complex Vector Fields} +% ===================================================================== +\beginscroll + +We now put our arrows to good use drawing complex vector fields. +These vector fields give a representation of complex-valued +functions of complex variables. +Consider a Cartesian coordinate grid of points \smath{(x, y)} in +the plane, and some complex-valued function \smath{f} defined on +this grid. +At every point on this grid, compute the value of \texht{$f(x + +iy)$}{f(x + y*\%i)} and call it \smath{z}. +Since \smath{z} has both a real and imaginary value for a given +\smath{(x,y)} grid point, there are four dimensions to plot. +What do we do? +We represent the values of \smath{z} by arrows planted at each +grid point. +Each arrow represents the value of \smath{z} in polar coordinates +\texht{$(r,\theta)$}{(r, theta)}. +The length of the arrow is proportional to \smath{r}. +Its direction is given by \texht{$\theta$}{theta}. + +The code for drawing vector fields is in the file {\bf vectors.input}. +We discuss its contents from top to bottom. + +Before showing you the code, we have two small +matters to take care of. +First, what if the function has large spikes, say, ones that go off +to infinity? +We define a variable \spad{clipValue} for this purpose. When +\spad{r} exceeds the value of \spad{clipValue}, then the value of +\spad{clipValue} is used instead of that for \spad{r}. +For convenience, we define a function \spad{clipFun(x)} which uses +\spad{clipValue} to ``clip'' the value of \spad{x}. + +% +\beginImportant + +\noindent +{\tt 1.\ \ \ clipValue\ :\ DFLOAT\ :=\ 6}\newline +{\tt 2.\ \ \ clipFun(x)\ ==\ min(max(x,-clipValue),clipValue)}\newline +\endImportant + +Notice that we identify \spad{clipValue} as a small float but do +not declare the type of the function \userfun{clipFun}. +As it turns out, \userfun{clipFun} is called with a +small float value. +This declaration ensures that \userfun{clipFun} never does a +conversion when it is called. + +The second matter concerns the possible ``poles'' of a +function, the actual points where the spikes have infinite +values. +\Language{} uses normal \spadtype{DoubleFloat} arithmetic which +does not directly handle infinite values. +If your function has poles, you must adjust your step size to +avoid landing directly on them (\Language{} calls \spadfun{error} +when asked to divide a value by \axiom{0}, for example). + +We set the variables \spad{realSteps} and \spad{imagSteps} to +hold the number of steps taken in the real and imaginary +directions, respectively. +Most examples will have ranges centered around the origin. +To avoid a pole at the origin, the number of points is taken +to be odd. + +\beginImportant + +\noindent +{\tt 1.\ \ \ realSteps:\ INT\ :=\ 25}\newline +{\tt 2.\ \ \ imagSteps:\ INT\ :=\ 25}\newline +{\tt 3.\ \ \ )read\ arrows}\newline +\endImportant + +Now define the function \userfun{drawComplexVectorField} to draw the arrows. +It is good practice to declare the type of the main function in +the file. +This one declaration is usually sufficient to ensure that other +lower-level functions are compiled with the correct types. + +\beginImportant + +\noindent +{\tt 4.\ \ \ C\ :=\ Complex\ DoubleFloat}\newline +{\tt 5.\ \ \ S\ :=\ Segment\ DoubleFloat}\newline +{\tt 6.\ \ \ drawComplexVectorField:\ (C\ ->\ C,\ S,\ S)\ ->\ VIEW3D}\newline +\endImportant + +The first argument is a function mapping complex small floats into +complex small floats. +The second and third arguments give the range of real and +imaginary values as segments like \spad{a..b}. +The result is a \threedim{} viewport. +Here is the full function definition: + +\beginImportant + +\noindent +{\tt 7.\ \ \ drawComplexVectorField(f,\ realRange,imagRange)\ ==}\newline +{\tt 8.\ \ \ \ \ delReal\ :=\ (hi(realRange)-lo(realRange))/realSteps}\newline +{\tt 9.\ \ \ \ \ delImag\ :=\ (hi(imagRange)-lo(imagRange))/imagSteps}\newline +{\tt 10.\ \ \ \ sp\ :=\ createThreeSpace()}\newline +{\tt 11.\ \ \ \ real\ :=\ lo(realRange)}\newline +{\tt 12.\ \ \ \ for\ i\ in\ 1..realSteps+1\ repeat}\newline +{\tt 13.\ \ \ \ \ \ imag\ :=\ lo(imagRange)}\newline +{\tt 14.\ \ \ \ \ \ for\ j\ in\ 1..imagSteps+1\ repeat}\newline +{\tt 15.\ \ \ \ \ \ \ \ z\ :=\ f\ complex(real,imag)}\newline +{\tt 16.\ \ \ \ \ \ \ \ arg\ :=\ argument\ z}\newline +{\tt 17.\ \ \ \ \ \ \ \ len\ :=\ clipFun\ sqrt\ norm\ z}\newline +{\tt 18.\ \ \ \ \ \ \ \ p1\ :=\ \ point\ [real,\ imag,\ 0.0@DFLOAT,\ arg]}\newline +{\tt 19.\ \ \ \ \ \ \ \ scaleLen\ :=\ delReal\ *\ len}\newline +{\tt 20.\ \ \ \ \ \ \ \ p2\ :=\ point\ [p1.1\ +\ scaleLen*cos(arg),}\newline +{\tt 21.\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ p1.2\ +\ scaleLen*sin(arg),0.0@DFLOAT,\ arg]}\newline +{\tt 22.\ \ \ \ \ \ \ \ arrow\ :=\ makeArrow(p1,\ p2)}\newline +{\tt 23.\ \ \ \ \ \ \ \ for\ a\ in\ arrow\ repeat\ curve(sp,\ a)}\newline +{\tt 24.\ \ \ \ \ \ \ \ imag\ :=\ imag\ +\ delImag}\newline +{\tt 25.\ \ \ \ \ \ real\ :=\ real\ +\ delReal}\newline +{\tt 26.\ \ \ \ makeViewport3D(sp,\ "Complex\ Vector\ Field")}\newline +\endImportant + +As a first example, let us draw \spad{f(z) == sin(z)}. +There is no need to create a user function: just pass the +\spadfunFrom{sin}{Complex DoubleFloat} from \spadtype{Complex DoubleFloat}. +\xtc{ +Read the file. +}{ +\spadpaste{)read vectors \bound{readVI}} +} +\psXtc{ +Draw the complex vector field of \spad{sin(x)}. +}{ +\graphpaste{drawComplexVectorField(sin,-2..2,-2..2) \free{readVI}} +}{ +\epsffile[0 0 295 295]{../ps/vectorSin.ps} +} +\ + +\endscroll +\autobuttons +\end{page} +% +% +\newcommand{\ugIntProgCompFunsTitle}{Drawing Complex Functions} +\newcommand{\ugIntProgCompFunsNumber}{10.7.} +% +% ===================================================================== +\begin{page}{ugIntProgCompFunsPage}{10.7. Drawing Complex Functions} +% ===================================================================== +\beginscroll + +Here is another way to graph a complex function of complex +arguments. +For each complex value \smath{z}, compute \smath{f(z)}, again +expressing the value in polar coordinates \smath{(r,\theta{})}. +We draw the complex valued function, again considering the +\smath{(x,y)}-plane as the complex plane, using \smath{r} as the +height (or \smath{z}-coordinate) and \smath{\theta} as the color. +This is a standard plot---we learned how to do this in +\downlink{``\ugGraphTitle''}{ugGraphPage} in Chapter \ugGraphNumber\ignore{ugGraph}---but here we write a new program to illustrate +the creation of polygon meshes, or grids. + +Call this function \userfun{drawComplex}. +It displays the points using the ``mesh'' of points. +The function definition is in three parts. + +\beginImportant + +\noindent +{\tt 1.\ \ \ drawComplex:\ (C\ ->\ C,\ S,\ S)\ ->\ VIEW3D}\newline +{\tt 2.\ \ \ drawComplex(f,\ realRange,\ imagRange)\ ==}\newline +{\tt 3.\ \ \ \ \ delReal\ :=\ (hi(realRange)-lo(realRange))/realSteps}\newline +{\tt 4.\ \ \ \ \ delImag\ :=\ (hi(imagRange)-lo(imagRange))/imagSteps}\newline +{\tt 5.\ \ \ \ \ llp:List\ List\ Point\ DFLOAT\ :=\ []}\newline +\endImportant + +Variables \spad{delReal} and \spad{delImag} give the step +sizes along the real and imaginary directions as computed by the values +of the global variables \spad{realSteps} and \spad{imagSteps}. +The mesh is represented by a list of lists of points \spad{llp}, +initially empty. +Now \spad{[ ]} alone is ambiguous, so +to set this initial value +you have to tell \Language{} what type of empty list it is. +Next comes the loop which builds \spad{llp}. + +\beginImportant + +\noindent +{\tt 1.\ \ \ \ \ real\ :=\ lo(realRange)}\newline +{\tt 2.\ \ \ \ \ for\ i\ in\ 1..realSteps+1\ repeat}\newline +{\tt 3.\ \ \ \ \ \ \ imag\ :=\ lo(imagRange)}\newline +{\tt 4.\ \ \ \ \ \ \ lp\ :=\ []\$(List\ Point\ DFLOAT)}\newline +{\tt 5.\ \ \ \ \ \ \ for\ j\ in\ 1..imagSteps+1\ repeat}\newline +{\tt 6.\ \ \ \ \ \ \ \ \ z\ :=\ f\ complex(real,imag)}\newline +{\tt 7.\ \ \ \ \ \ \ \ \ pt\ :=\ point\ [real,imag,\ clipFun\ sqrt\ norm\ z,\ }\newline +{\tt 8.\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ argument\ z]}\newline +{\tt 9.\ \ \ \ \ \ \ \ \ lp\ :=\ cons(pt,lp)}\newline +{\tt 10.\ \ \ \ \ \ \ \ imag\ :=\ imag\ +\ delImag}\newline +{\tt 11.\ \ \ \ \ \ real\ :=\ real\ +\ delReal}\newline +{\tt 12.\ \ \ \ \ \ llp\ :=\ cons(lp,\ llp)}\newline +\endImportant + +The code consists of both an inner and outer loop. +Each pass through the inner loop adds one list \spad{lp} of points +to the list of lists of points \spad{llp}. +The elements of \spad{lp} are collected in reverse order. + +\beginImportant + +\noindent +{\tt 13.\ \ \ \ makeViewport3D(mesh(llp),\ "Complex\ Function")}\newline +\endImportant + +The operation \spadfun{mesh} then creates an object of type +\spadtype{ThreeSpace(DoubleFloat)} from the list of lists of points. +This is then passed to \spadfun{makeViewport3D} to display the +image. + +Now add this function directly to your {\bf vectors.input} +file and re-read the file using \spad{)read vectors}. +We try \userfun{drawComplex} using +a user-defined function \spad{f}. + +\xtc{ +Read the file. +}{ +\spadpaste{)read vectors \bound{readVI}} +} +\xtc{ +This one has a pole at \smath{z=0}. +}{ +\spadpaste{f(z) == exp(1/z)\bound{e1}} +} +\psXtc{ +Draw it with an odd number of steps to avoid the pole. +}{ +\graphpaste{drawComplex(f,-2..2,-2..2)\free{e1 readVI}} +}{ +\epsffile[0 0 295 295]{../ps/complexExp.ps} +} +\ + +\endscroll +\autobuttons +\end{page} +% +% +\newcommand{\ugIntProgFunctionsTitle}{Functions Producing Functions} +\newcommand{\ugIntProgFunctionsNumber}{10.8.} +% +% ===================================================================== +\begin{page}{ugIntProgFunctionsPage}{10.8. Functions Producing Functions} +% ===================================================================== +\beginscroll + +In \downlink{``\ugUserMakeTitle''}{ugUserMakePage} in Section \ugUserMakeNumber\ignore{ugUserMake}, you learned how to use the operation +\spadfun{function} to create a function from symbolic formulas. +Here we introduce a similar operation which not only +creates functions, but functions from functions. + +The facility we need is provided by the package +\spadtype{MakeUnaryCompiledFunction(E,S,T)}. +%-% \HDexptypeindex{MakeUnaryCompiledFunction}{ugIntProgFunctionsPage}{10.8.}{Functions Producing Functions} +This package produces a unary (one-argument) compiled +function from some symbolic data +generated by a previous computation.\footnote{% +\spadtype{MakeBinaryCompiledFunction} is available for binary +functions.} +%-% \HDexptypeindex{MakeBinaryCompiledFunction}{ugIntProgFunctionsPage}{10.8.}{Functions Producing Functions} +The \spad{E} tells where the symbolic data comes from; +the \spad{S} and \spad{T} give \Language{} the +source and target type of the function, respectively. +The compiled function produced has type +\spadsig{\spad{S}}{\spad{T}}. +To produce a compiled function with definition \spad{p(x) == expr}, call +\spad{compiledFunction(expr, x)} from this package. +The function you get has no name. +You must to assign the function to the variable \spad{p} to give it that name. +% +\xtc{ +Do some computation. +}{ +\spadpaste{(x+1/3)**5\bound{p1}} +} +\xtc{ +Convert this to an anonymous function of \spad{x}. +Assign it to the variable \spad{p} to give the function a name. +}{ +\spadpaste{p := compiledFunction(\%,x)\$MakeUnaryCompiledFunction(POLY FRAC INT,DFLOAT,DFLOAT)\bound{p2}\free{p1}} +} +\xtc{ +Apply the function. +}{ +\spadpaste{p(sin(1.3))\bound{p3}\free{p2}} +} + +For a more sophisticated application, read on. + +\endscroll +\autobuttons +\end{page} +% +% +\newcommand{\ugIntProgNewtonTitle}{Automatic Newton Iteration Formulas} +\newcommand{\ugIntProgNewtonNumber}{10.9.} +% +% ===================================================================== +\begin{page}{ugIntProgNewtonPage}{10.9. Automatic Newton Iteration Formulas} +% ===================================================================== +\beginscroll + +We resume +our continuing saga of arrows and complex functions. +Suppose we want to investigate the behavior of Newton's iteration function +%-% \HDindex{Newton iteration}{ugIntProgNewtonPage}{10.9.}{Automatic Newton Iteration Formulas} +in the complex plane. +Given a function \smath{f}, we want to find the complex values +\smath{z} such that \smath{f(z) = 0}. + +The first step is to produce a Newton iteration formula for +a given \smath{f}: +\texht{$x_{n+1} = x_n - {{f(x_n)}\over{f'(x_n)}}.$}{% +\spad{x(n+1) = x(n) - f(x(n))/f'(x(n))}.} +We represent this formula by a function \smath{g} +that performs the computation on the right-hand side, that is, +\texht{$x_{n+1} = {g}(x_n)$}{\spad{x(n+1) = g(x(n))}}. + +The type \spadtype{Expression Integer} (abbreviated \spadtype{EXPR +INT}) is used to represent general symbolic expressions in +\Language{}. +%-% \HDexptypeindex{Expression}{ugIntProgNewtonPage}{10.9.}{Automatic Newton Iteration Formulas} +To make our facility as general as possible, we assume +\smath{f} has this type. +Given \smath{f}, we want +to produce a Newton iteration function \spad{g} which, +given a complex point \texht{$x_n$}{x(n)}, delivers the next +Newton iteration point \texht{$x_{n+1}$}{x(n+1)}. + +This time we write an input file called {\bf newton.input}. +We need to import \spadtype{MakeUnaryCompiledFunction} (discussed +in the last section), call it with appropriate types, and then define +the function \spad{newtonStep} which references it. +Here is the function \spad{newtonStep}: + +\beginImportant + +\noindent +{\tt 1.\ \ \ C\ :=\ Complex\ DoubleFloat}\newline +{\tt 2.\ \ \ complexFunPack:=MakeUnaryCompiledFunction(EXPR\ INT,C,C)}\newline +{\tt 3.\ \ \ }\newline +{\tt 4.\ \ \ newtonStep(f)\ ==}\newline +{\tt 5.\ \ \ \ \ fun\ \ :=\ complexNumericFunction\ f}\newline +{\tt 6.\ \ \ \ \ deriv\ :=\ complexDerivativeFunction(f,1)}\newline +{\tt 7.\ \ \ \ \ (x:C):C\ +->}\newline +{\tt 8.\ \ \ \ \ \ \ x\ -\ fun(x)/deriv(x)}\newline +{\tt 9.\ \ \ }\newline +{\tt 10.\ \ complexNumericFunction\ f\ ==}\newline +{\tt 11.\ \ \ \ v\ :=\ theVariableIn\ f}\newline +{\tt 12.\ \ \ \ compiledFunction(f,\ v)\$complexFunPack}\newline +{\tt 13.\ \ }\newline +{\tt 14.\ \ complexDerivativeFunction(f,n)\ ==}\newline +{\tt 15.\ \ \ \ v\ :=\ theVariableIn\ f}\newline +{\tt 16.\ \ \ \ df\ :=\ D(f,v,n)}\newline +{\tt 17.\ \ \ \ compiledFunction(df,\ v)\$complexFunPack}\newline +{\tt 18.\ \ }\newline +{\tt 19.\ \ theVariableIn\ f\ ==\ \ }\newline +{\tt 20.\ \ \ \ vl\ :=\ variables\ f}\newline +{\tt 21.\ \ \ \ nv\ :=\ \#\ vl}\newline +{\tt 22.\ \ \ \ nv\ >\ 1\ =>\ error\ "Expression\ is\ not\ univariate."}\newline +{\tt 23.\ \ \ \ nv\ =\ 0\ =>\ 'x}\newline +{\tt 24.\ \ \ \ first\ vl}\newline +\endImportant + +Do you see what is going on here? +A formula \spad{f} is passed into the function \userfun{newtonStep}. +First, the function turns \spad{f} into a compiled program mapping +complex numbers into complex numbers. Next, it does the same thing +for the derivative of \spad{f}. Finally, it returns a function which +computes a single step of Newton's iteration. + +The function \userfun{complexNumericFunction} extracts the variable +from the expression \spad{f} and then turns \spad{f} into a function +which maps complex numbers into complex numbers. The function +\userfun{complexDerivativeFunction} does the same thing for the +derivative of \spad{f}. The function \userfun{theVariableIn} +extracts the variable from the expression \spad{f}, calling the function +\spadfun{error} if \spad{f} has more than one variable. +It returns the dummy variable \spad{x} if \spad{f} has no variables. + +Let's now apply \userfun{newtonStep} to the formula for computing +cube roots of two. +% +\xtc{ +Read the input file with the definitions. +}{ +\spadpaste{)read newton\bound{n1}} +} +\xtc{}{ +\spadpaste{)read vectors \bound{n1a}} +} + +\xtc{ +The cube root of two. +}{ +\spadpaste{f := x**3 - 2\bound{n2}\free{n1 n1a}} +} +\xtc{ +Get Newton's iteration formula. +}{ +\spadpaste{g := newtonStep f\bound{n3}\free{n2}} +} +\xtc{ +Let \spad{a} denote the result of +applying Newton's iteration once to the complex number \spad{1 + \%i}. +}{ +\spadpaste{a := g(1.0 + \%i)\bound{n4}\free{n3}} +} +\xtc{ +Now apply it repeatedly. How fast does it converge? +}{ +\spadpaste{[(a := g(a)) for i in 1..]\bound{n5}\free{n4}} +} +\xtc{ +Check the accuracy of the last iterate. +}{ +\spadpaste{a**3\bound{n6}\free{n5}} +} + +In \downlink{`MappingPackage1'}{MappingPackageOneXmpPage}\ignore{MappingPackage1}, we show how functions can be +manipulated as objects in \Language{}. +A useful operation to consider here is \spadop{*}, which means +composition. +For example \spad{g*g} causes the Newton iteration formula +to be applied twice. +Correspondingly, \spad{g**n} means to apply the iteration formula +\spad{n} times. + +% +\xtc{ +Apply \spad{g} twice to the point \spad{1 + \%i}. +}{ +\spadpaste{(g*g) (1.0 + \%i)\bound{n10}\free{n3}} +} +\xtc{ +Apply \spad{g} 11 times. +}{ +\spadpaste{(g**11) (1.0 + \%i)\bound{n11}\free{n10}} +} + +Look now at the vector field and surface generated +after two steps of Newton's formula for the cube root of two. +The poles in these pictures represent bad starting values, and the +flat areas are the regions of convergence to the three roots. +% +\psXtc{ +The vector field. +}{ +\graphpaste{drawComplexVectorField(g**3,-3..3,-3..3)\free{n3}} +}{ +\epsffile[0 0 295 295]{../ps/vectorRoot.ps} +} +\psXtc{ +The surface. +}{ +\graphpaste{drawComplex(g**3,-3..3,-3..3)\free{n3}} +}{ +\epsffile[0 0 295 295]{../ps/complexRoot.ps} +} +\ + + +\endscroll +\autobuttons +\end{page} +% |