numbers; we will see later that they can be used to adapt programs

to special conditions.

You type And the result is

0<1 true

0=1 false

a+1>a true

false (with error message)

a>=b

"abc"<="b" true

"B">"a!" false

"b">"a?" true

(1,2)<>(0,4) true

(1,2)<(0,4) false

(1,a)>(0,b) true

Chapter 8: Algebraic Expressions 65

numeric a true not

and

known a false or

comparison

not pen a true ¿=

¡=

known "a" and numeric 1 true

¡¿

(0>1) or (a<a) false relations

greater-than-or-equal-to

a (with error messages)

0>1 or a<a less-than-or-equal-to

unequal-to

The tokens ˜>=™, ˜<=™, and ˜<>™ stand respectively for the relations greater-than- pair

numeric

or-equal-to, less-than-or-equal-to, and unequal-to. When strings are compared, pen

uses the order of words in a dictionary, except that it uses ASCII known

max

code to de¬ne ordering of individual characters; thus, all uppercase letters are min

considered to be less than all lowercase letters. (See Appendix C.) When pairs maximum

minimum

of numbers are compared, considers only the x coordinates, unless integers

the x coordinates are equal; in the latter case it compares the y coordinates. The

type of an expression can be ascertained by an expression like ˜pair a™, which is

true if and only if a is a pair. The expression ˜known a™ is true if and only if the

value of a is fully known.

EXERCISE 8.4

What causes the error messages in ˜0>1 or a<a™ ?

The rest of this chapter is entirely preceded by “dangerous bend” signs, so

you can safely omit it on ¬rst reading (unless you™re hooked and can™t stop).

expressions can include many operations that are less familiar but

still useful. For example, the max and min operations compute the maximum

and minimum of numbers, strings, or pairs:

You type And the result is

max(1,-2,4) 4

min(1,-2,4) -2

max("a","b","ab") "b"

min("a","b","ab") "a"

max((1,5),(0,6),(1,4)) (1,5)

min((1,5),(0,6),(1,4)) (0,6)

max(.5a+1,.5a-1) 0.5a+1

Numbers can be converted to integers in a variety of ways:

You type And the result is

floor 3.14159 3

floor -3.14159 -4

floor -epsilon -1

floor infinity 4095

ceiling 3.14159 4

ceiling -3.14159 -3

66 Chapter 8: Algebraic Expressions

round 3.14159 3 ¬‚oor

greatest integer

round -3.14159 -3 ceiling

least integer

round(1.1,2.8) (1,3)

round

round(3.5,-3.5) (4,-3) remainder

mod

a+0.5 (with error message)

round a abs

length

8 mod 3 2

absolute value

-8 mod 3 1 ++

Pythagorean addition

.8 mod .3 0.2

square root

Pythagorean subtraction

The ˜¬‚oor™ operation computes the greatest integer that is less than or equal to its +-+

operand; this quantity is often denoted by x in mathematics texts. Plain

also includes the analogous ˜ceiling™ operation x , which is the least integer greater

than or equal to x. Furthermore, ˜round x™ is the integer nearest to x; plain

computes this by using the formula x + .5 , and applies it to both components of a

pair if a pair is being rounded. The remainder of x with respect to y, written ˜x mod y™,

is calculated by using the formula x ’ y x/y .

You type And the result is

abs -7 7

abs(3,4) 5

length(3,4) 5

3++4 5

300++400 500

181.01933 (with error messages)

sqrt(300**2 + 400**2)

1++1 1.4142

0 ++ -7 7

5+-+4 3

√

The ˜++™ operation is called Pythagorean addition; a++b is the same thing as a2 + b2 .

Most of the square root operations in computer programs could probably be avoided

if ++ were more widely available, because people seem to want√ square roots primarily

when they are computing distances. Notice that a ++ b ++ c = a2 + b2 + c2 ; we have

the identity (a ++ b) ++ c = a ++ (b ++ c) as √ well as a ++ b = b ++ a. It is better

to use Pythagorean addition than to calculate a2 + b2 , because the computation of

a2 and b2 might produce numbers that are too large even when a ++ b is rather small.

There™s also an inverse operation, √

Pythagorean subtraction, which is denoted by ˜+-+™;

the quantity a +’+ b is equal to a2 ’ b2 .

EXERCISE 8.5

When the author was preparing these examples he typed ˜0++-7™ and was

surprised to get the answer ˜0™. Why should this not have been a surprise?

EXERCISE 8.6

(For mathematicians.) Although the Pythagorean addition operation is asso-

ciative and commutative, says that 5++4++2++2 = 7 = 2++2++4++5

yet 2 ++ 4 ++ 5 ++ 2 = 6.99998. Why?

Chapter 8: Algebraic Expressions 67

uses the names ˜sind™ and ˜cosd™ for the trigonometric functions sind

cosd

sine and cosine, because ™s operations are designed to deal with

trigonometric

angles expressed in degrees. But it turns out that programmers rarely need to refer sine

to sines and cosines explicitly, because the ˜dir™ and ˜angle™ functions provide most of cosine

dir

what a font designer needs. angle

mlog

You type And the result is mexp

sind 30 0.5

cosd 30 0.86603

sind -30 -0.5

cosd 360 1

sind 10 ++ cosd 10 1

dir 30 (0.86603,0.5)

dir -90 (0,-1)

angle(1,1) 45

angle(1,2) 63.43495

angle(1,-2) -63.43495

sind 63.43495 / cosd 63.43495 1.99997

angle up 90

angle left 180

angle(-1000,-epsilon) -180

angle dir 60 60.00008

0 (with error message)

angle(0,0)

Plain de¬nes ˜dir x™ to be the pair of values (cosd x, sind x); this is a vector,

which points x degrees above the rightward horizon. Conversely, the ˜angle™ operator

determines the angle that corresponds to a given vector.

Logarithms and exponentials are computed with respect to an unusual base,

designed to enhance the accuracy of calculations involving ¬xed-radix numbers

™s range. The values mlog x = 256 ln x and mexp x = ex/256 produce

in

reasonably good results when x —— y is computed by the formula mexp(y — mlog x).

You type And the result is

mlog 2 177.44568

mexp mlog 2 2

mexp 8 mlog 2 256

mexp 256 2.71828

mlog 2.71828 255.99954

mlog 2.71829 256.00098

15 mlog 2 2661.68518

mexp 2661.68518 32767.99998

32767.99998 (with error message)

mexp 2661.68519

mexp-2661.68519 0.00003

68 Chapter 8: Algebraic Expressions

also generates two ¬‚avors of random numbers. It is very unlikely uniformdeviate

normaldeviate

that you will get the particular values shown in the following examples, when

scaled

you do the experiment yourself, because the results come out di¬erent each time the xscaled

computer is asked for a new random number (unless you have speci¬ed a “seed value” yscaled

dir

as explained in Chapter 21).

You type And the result might be

uniformdeviate 100 47.4241

uniformdeviate 100 97.28148

uniformdeviate -100 -36.16279

(normaldeviate,normaldeviate) (0.46236,-1.87648)

The value of ˜uniformdeviate 100™ is a random number between 0 and 100; the value

of ˜normaldeviate™ is a normally distributed random number whose mean value is zero

and whose standard deviation is unity. Chapter 21 explains what this means and gives

several applications.

Besides all of these operations on numbers, has a rich collection

of operations on pairs, some of which are indicated in the following examples:

You type And the result is

right (1,0)

(1,2)+(3,4) (4,6)

1/3(3,10) (1,3.33333)

z2-z1 (-x1+x2,-y1+y2)

.2[z1,z2] (0.8x1+0.2x2,0.8y1+0.2y2)

3z (3x,3y)

z scaled 3 (3x,3y)

z xscaled 2 yscaled 1/2 (2x,0.5y)

z shifted (2,3) (x+2,y+3)

z shifted 3right (x+3,y)

z slanted 1/6 (x+0.16667y,y)

z rotated 90 (-y,x)

z rotated 30 (-0.5y+0.86603x,0.86603y+0.5x)

xpart(z rotated 30) -0.5y+0.86603x

ypart(z rotated 30) 0.86603y+0.5x

(3,4) (with error message)

(1,2)*(3,4)

(1,2)zscaled(3,4) (-5,10)

(a,b)zscaled(3,4) (3a-4b,4a+3b)

(a,b)zscaled dir 30 (0.86603a-0.5b,0.5a+0.86603b)

(1,2)dotprod(3,4) 11

(a,b)dotprod(3,4) 3a+4b

dir 21 dotprod dir 51 0.86603

(3,4)dotprod((30,40)rotated 90) 0

Chapter 8: Algebraic Expressions 69

(Recall that plain converts ˜z$™ into ˜(x$,y$)™ when $ is any su¬x .) The xpart

ypart

operations exhibited here are almost all self-evident. When a point or vector is rotated,

shifted

it is moved counterclockwise about (0, 0) through a given number of degrees. - right

computes the rotated coordinates by using sines and cosines in an appropriate slanted

zscaled

way; you don™t have to remember the formulas! Although you cannot use ˜*™ to multiply dotprod

a pair by a pair, you can use ˜zscaled™ to get the e¬ect of complex number multiplication: z

Since (1 + 2i) times (3 + 4i) is ’5 + 10i, we have (1, 2) zscaled (3, 4) = (’5, 10). There™s rotated

sines

also a multiplication that converts pairs into numbers: (a, b) dotprod (c, d) = ac + bd. cosines

This is the “dot product,” often written ˜(a, b) · (c, d)™ in mathematics texts; it turns zscaled

complex number

out to be equal to a ++ b times c ++ d times the cosine of the angle between the vectors

multiplication

(a, b) and (c, d). Since cosd 90—¦ = 0, two vectors are perpendicular to each other if and dot product

only if their dot product is zero. perpendicular

product

string

There are operations on strings, paths, and the other types too; we shall study

point

such things carefully in later chapters. For now, it will su¬ce to give a few direction

examples, keeping in mind that the ¬le expr.mf de¬nes s with any subscript to be a length

cycle

string, while p with any subscript is a path. Furthermore s1 has been given the value

"abra", while p1 is ˜(0, 0) . . (3, 3)™ and p2 is ˜(0, 0) . . (3, 3) . . cycle ™.

You type And the result is

s2 unknown string s2

s1&"cad"&s1 "abracadabra"

length s1 4

length p1 1

length p2 2

cycle p1 false

cycle p2 true

substring (0,2) of s1 "ab"

substring (2,infinity) of s1 "ra"

point 0 of p1 (0,0)

point 1 of p1 (3,3)

point .5 of p1 (1.5,1.5)

point infinity of p1 (3,3)

point .5 of p2 (3,0)

point 1.5 of p2 (0,3)

point 2 of p2 (0,0)

point 2+epsilon of p2 (0.00009,-0.00009)

point -epsilon of p2 (-0.00009,0.00009)

point -1 of p1 (0,0)

direction 0 of p1 (1,1)

direction 0 of p2 (4,-4)

direction 1 of p2 (-4,4)

The length of a path is the number of ˜. .™ steps that it contains; the construction

˜cycle path ™ can be used to tell whether or not a particular path is cyclic. If you say

70 Chapter 8: Algebraic Expressions

just ˜p1™ you get to see path p1 with its control points: control points

substring

subpath

(0,0)..controls (1,1) and (2,2)

ampersand

..(3,3)

Similarly, ˜p2™ is

(0,0)..controls (2,-2) and (5,1)

..(3,3)..controls (1,5) and (-2,2)

..cycle

and ˜subpath (0,1) of p2™ is analogous to a substring:

(0,0)..controls (2,-2) and (5,1)

..(3,3)

The expression ˜point t of p2 ™ gives the position of a point that moves along path p2 ,

starting with the initial point (0, 0) at t = 0, then reaching point (3, 3) at t = 1,

etc.; the value at t = 1/2 is the third-order midpoint obtained by the construction of

Chapter 3, using intermediate control points (2, ’2) and (5, 1). Since p2 is a cyclic

path of length 2, point (t + 2) of p2 is the same as point t. Path p1 is not cyclic, so its

points turn out to be identical to point 0 when t < 0, and identical to point 1 when

t > 1. The expression ˜direction t of path ™ is similar to ˜point t of path ™; it yields a

vector for the direction of travel at time t.

Paths are not necessarily traversed

at constant speed. For example, the

diagram at the right shows point t of p2 at

twenty equally spaced values of t. -

moves faster in this case at time 1.0

than at time 1.2; but the points are spread (Figure 8a will be inserted here; too bad you

out fairly well, so the concept of fractional can™t see it now.)

time can be useful. The diagram shows, in-

cidentally, that path p2 is not an especially

good approximation to a circle; there is no

left-right symmetry, although the curve from

point 1 to point 2 is a mirror image of the

curve from point 0 to point 1. This lack of

circularity is not surprising, since p2 was de¬ned by simply specifying two points, (0, 0)

and (3, 3); at least four points are needed to get a path that is convincingly round.

The ampersand operation ˜&™ can be used to splice paths together in much the

same way as it concatenates strings. For example, if you type ˜p2 & p1™, you

get the path of length 3 that is obtained by breaking the cyclic connection at the end

of path p2 and attaching p1 :

(0,0)..controls (2,-2) and (5,1)

..(3,3)..controls (1,5) and (-2,2)

..(0,0)..controls (1,1) and (2,2)

..(3,3)

Concatenated paths must have identical endpoints at the junction.

Chapter 8: Algebraic Expressions 71

You can even “slow down the clock” by concatenating subpaths that have precedence

primary

non-integer time speci¬cations. For example, here™s what you get if you ask

secondary

for ˜subpath (0,.5) of p2 & subpath (.5,2) of p2 & cycle™: tertiary

expression

(0,0)..controls (1,-1) and (2.25,-0.75) ± primary

(

..(3,0)..controls (3.75,0.75) and (4,2)

)

..(3,3)..controls (1,5) and (-2,2) ± secondary

..cycle ± tertiary

± expression

When t goes from 0 to 1 in subpath (0, .5) of p2 , you get the same points as when t

goes from 0 to .5 in p2 ; when t goes from 0 to 1 in subpath (.5, 2) of p2 , you get the

same points as when t goes from .5 to 1 in p2 ; but when t goes from 1 to 2 in subpath

(.5, 2) of p2 , it™s the same as the segment from 1 to 2 in p2 .

Let™s conclude this chapter by discussing the exact rules of precedence by

which decides what operations to do ¬rst. The informal notion of

“magnetism” gives a good intuitive picture of what happens, but syntax rules express

things unambiguously in borderline cases.

The four levels of precedence correspond to four kinds of formulas, which

are called primaries, secondaries, tertiaries, and expressions. A primary is

a variable or a constant or a tightly bound unit like ˜2x™ or ˜sqrt 2™; a secondary is a

primary or a sequence of primaries connected by multiplicative operators like ˜*™ or

˜scaled™; a tertiary is a secondary or a sequence of secondaries connected by additive

operators like ˜+™ or ˜++™; an expression is a tertiary or a sequence of tertiaries connected

by external operators like ˜<™ or ˜..™. For example, the expression

a+b/2>3c*sqrt4d

is composed of the primaries ˜a™, ˜b™, ˜2™, ˜3c™, and ˜sqrt4d™; the last of these is a primary

containing ˜4d™ as a primary within itself. The subformulas ˜a™, ˜b/2™, and ˜3c*sqrt4d™

are secondaries; the subformulas ˜a+b/2™ and ˜3c*sqrt4d™ are tertiaries.

If an expression is enclosed in parentheses, it becomes a primary that can be

used to build up larger secondaries, tertiaries, etc.

The full syntax for expressions is quite long, but most of it falls into a simple

pattern. If ±, β, and γ are any “types””numeric, boolean, string, etc.”then

± variable refers to a variable of type ±, β primary refers to a primary of type β,

and so on. Almost all of the syntax rules ¬t into the following general framework:

± primary ’’ ± variable | ± constant | ( ± expression )

| operator that takes type β to type ± β primary

± secondary ’’ ± primary

| β secondary multiplicative op taking types β and γ to ± γ primary

± tertiary ’’ ± secondary

| β tertiary additive op taking types β and γ to ± γ secondary

± expression ’’ ± tertiary

| β expression external op taking types β and γ to ± γ tertiary

These schematic rules don™t give the whole story, but they do give the general structure

of the plot.

72 Chapter 8: Algebraic Expressions

Chapter 25 spells out all of the syntax rules for all types of expressions. We numeric primary

[

shall consider only a portion of the numeric and pair cases here, in order to

,

have a foretaste of the complete menu: ]

length

numeric primary ’’ numeric atom length

| numeric atom [ numeric expression , numeric expression ] length

angle

| length string primary xpart

| length path primary ypart

numeric atom

| length pair primary (

| angle pair primary )