Banquet06.mw

25 Years of Maple:
Some Historical Comments
 

Keith Geddes
Maple Conference 2006
 

In the Beginning 

 

Image 

 

In the beginning (1980) there were two of us: Gaston Gonnet and Keith Geddes 

 

Pre-Maple 

 

 

 

 

 

 

 

 

 

 

Image 

 

The "red room" in the Math and Computer building at UW 

 

Early Computer Algebra Systems 

 

  • I used various CA systems in the 1970s
 

  • for teaching and research work
 

 

  • Formac (a preprocessor to PL/1)
 

  • batch processing
 

 

  • ALTRAN (a preprocessor to Fortran)
 

  • very Fortran-like programming
 

  • batch processing
 

  • restricted to polynomial and rational function manipulation
 

 

  • Communicate to the mainframe from a terminal
 

  • I recall the so-called "silent 700"
    (not very silent, but compared to an IBM 2741 type-ball terminal!)
 

  • I had a Teleterm terminal
    (cost $5200 in 1974)
 

  • connect to campus mainframe at 300 baud
 

 

  • The issue of memory size
 

  • we used a Honeywell time-sharing mainframe
 

  • 50K words (i.e., 200K bytes) of memory usage was "very large"
 

  • often wait overnight for processing to finish
 

  • would lead to high charges to my research grant
 

  • could not use more than a half-megabyte of memory
 

 

How large do integers need to be? 

 

  • For example, compute the GCD of two polynomials
 

  • In ALTRAN, max length for integers was 100 digits
    (this is the maximum that could be requested!)
 

  • 100 digits sounds "large enough" for many purposes
 

  • The Problem: Intermediate steps of an algorithm may generate very large integers
    (using the only GCD algorithms known at the time)
 

  • The GCD algorithm used was a variation of the ancient Euclid algorithm (based on PRS, meaning Polynomial Remainder Sequences)
 

  • The computation is ridiculously trivial in modern times!
    (with
    modern algorithms as well as fast computers)
 

> `assign`(poly1, `+`(`*`(2500000, `*`(`^`(x, 4))), `-`(`*`(487995500, `*`(`^`(x, 3)))), `-`(`*`(2442003501, `*`(`^`(x, 2)))), `*`(308523500, `*`(x)), 4504301))
 

`+`(`*`(2500000, `*`(`^`(x, 4))), `-`(`*`(487995500, `*`(`^`(x, 3)))), `-`(`*`(2442003501, `*`(`^`(x, 2)))), `*`(308523500, `*`(x)), 4504301) (1)
 

> `assign`(poly2, `+`(`*`(125000, `*`(`^`(x, 3))), `*`(1110250, `*`(`^`(x, 2))), `*`(2426470, `*`(x)), 2501))
 

`+`(`*`(125000, `*`(`^`(x, 3))), `*`(1110250, `*`(`^`(x, 2))), `*`(2426470, `*`(x)), 2501) (2)
 

> gcd(poly1, poly2)
 

`+`(2501, `*`(500, `*`(x))) (3)
 

 

Note: The maximum length of integers above is 10 digits. 

 

The old algorithm `gcd/reduced` (which uses a PRS algorithm) yields the same result. It even seems fast enough on modern computers.However, notice the large integers that can be generated by intermediate calculations!
 

We very soon ran into GCD computations that could not be completed on a system that limits the size of integers to only 100 digits. 

 

> trace(`gcd/reduced`, `gcd/reduced/prs`)
 

`gcd/reduced`, `gcd/reduced/prs` (4)
 

> `gcd/reduced`(poly1, poly2)
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

{--> enter gcd/reduced, args = 2500000*x^4-487995500*x^3-2442003501*x^2+308523500*x+4504301, 125000*x^3+1110250*x^2+2426470*x+2501
{--> enter gcd/reduced/prs, args = 2500000*x^4-487995500*x^3-2442003501*x^2+308523500*x+4504301, 125000*x^3+1110250*x^2+2426470*x+2501
{x}
x
`+`(`*`(2500000, `*`(`^`(x, 4))), `-`(`*`(487995500, `*`(`^`(x, 3)))), `-`(`*`(2442003501, `*`(`^`(x, 2)))), `*`(308523500, `*`(x)), 4504301)
`+`(`*`(125000, `*`(`^`(x, 3))), `*`(1110250, `*`(`^`(x, 2))), `*`(2426470, `*`(x)), 2501)
1
{--> enter gcd/reduced/prs, args = 2500000, 487995500
{}
500
<-- exit gcd/reduced/prs (now in gcd/reduced/content) = 500}
{--> enter gcd/reduced/prs, args = 500, 2442003501
{}
1
<-- exit gcd/reduced/prs (now in gcd/reduced/content) = 1}
`+`(`*`(2500000, `*`(`^`(x, 4))), `-`(`*`(487995500, `*`(`^`(x, 3)))), `-`(`*`(2442003501, `*`(`^`(x, 2)))), `*`(308523500, `*`(x)), 4504301)
{--> enter gcd/reduced/prs, args = 125000, 1110250
{}
250
<-- exit gcd/reduced/prs (now in gcd/reduced/content) = 250}
{--> enter gcd/reduced/prs, args = 250, 2426470
{}
10
<-- exit gcd/reduced/prs (now in gcd/reduced/content) = 10}
{--> enter gcd/reduced/prs, args = 10, 2501
{}
1
<-- exit gcd/reduced/prs (now in gcd/reduced/content) = 1}
`+`(`*`(125000, `*`(`^`(x, 3))), `*`(1110250, `*`(`^`(x, 2))), `*`(2426470, `*`(x)), 2501)
{--> enter gcd/reduced/prs, args = 1, 1
{}
1
<-- exit gcd/reduced/prs (now in gcd/reduced/prs) = 1}
1
`+`(229881134437500000, `*`(31891686562500000000, `*`(`^`(x, 2))), `*`(159568174029375000000, `*`(x)))
`+`(`*`(125000, `*`(`^`(x, 3))), `*`(1110250, `*`(`^`(x, 2))), `*`(2426470, `*`(x)), 2501)
true
15625000000
`+`(`-`(1010642222433794921630859375000000000000000), `-`(`*`(202047625436584350585937500000000000000000, `*`(x))))
`+`(`-`(1010642222433794921630859375000000000000000), `-`(`*`(202047625436584350585937500000000000000000, `*`(x))))
`+`(229881134437500000, `*`(31891686562500000000, `*`(`^`(x, 2))), `*`(159568174029375000000, `*`(x)))
true
1017079671800743066406250000000000000000
0
{--> enter gcd/reduced/prs, args = 12931048027941398437500000000000, 64681102235762874984375000000000
{}
25862096055882796875000000000
<-- exit gcd/reduced/prs (now in gcd/reduced/content) = 25862096055882796875000000000}
`+`(2501, `*`(500, `*`(x)))
<-- exit gcd/reduced/prs (now in gcd/reduced) = 2501+500*x}
`+`(2501, `*`(500, `*`(x)))
<-- exit gcd/reduced (now at top level) = 2501+500*x}
`+`(2501, `*`(500, `*`(x))) (5)
 

>
 

 

  • The point of the above trace of a computation: Large intermediate integers arise, much larger than the size of integers in the input and the output
 

  • By the late 1970s, I made some use of MACSYMA
 

  • Developed at MIT
 

  • How did I use it?
    By dialing long-distance to a DEC 10 computer at MIT in Boston
 

 

  • My question to my Computer Science colleagues:
 

  • How can we get a computer that would run MACSYMA at U of Waterloo?
 

  • My colleagues answer: That is the wrong question!
 

1980: The Age of Maple arrives! 

 

 

 

 

Image 

 

 

 

 

 

 

 

 

 

 

 

How many Person-Years of R&D for Maple? 

 

 

 

 

 

> `assign`(PersonsPerYear, [[1981, 2], [1982, 4], [1983, 6], [1984, 10], [1986, 14], [1988, 16], [1990, 17], [1993, 25], [1996, 30], [1999, 40], [2003, 48], [2006, 50]]); -1
`assign`(PersonsPerYear, [[1981, 2], [1982, 4], [1983, 6], [1984, 10], [1986, 14], [1988, 16], [1990, 17], [1993, 25], [1996, 30], [1999, 40], [2003, 48], [2006, 50]]); -1
`assign`(PersonsPerYear, [[1981, 2], [1982, 4], [1983, 6], [1984, 10], [1986, 14], [1988, 16], [1990, 17], [1993, 25], [1996, 30], [1999, 40], [2003, 48], [2006, 50]]); -1
`assign`(PersonsPerYear, [[1981, 2], [1982, 4], [1983, 6], [1984, 10], [1986, 14], [1988, 16], [1990, 17], [1993, 25], [1996, 30], [1999, 40], [2003, 48], [2006, 50]]); -1
 

> `assign`(DataPlot, plot(PersonsPerYear, Y = 1980 .. 2006, style = point, symbol = BOX, symbolsize = 14)); -1
 

> DataPlot
 

Plot_2d
 

> `assign`(Digits, 4); -1
 

> `assign`(BaseYear, 1980); -1
 

> `assign`(normalize, proc (Y) options operator, arrow; `if`(`::`(Y, name), 'normalize(Y)', `+`(Y, `-`(BaseYear))) end proc)
 

proc (Y) options operator, arrow; `if`(`::`(Y, name), 'normalize(Y)', `+`(Y, `-`(BaseYear))) end proc (6)
 

> `assign`(scaling, proc (l) options operator, arrow; [normalize(l[1]), l[2]] end proc); -1
 

> `assign`(PersonsPerYear, map(scaling, PersonsPerYear))
 

[[1, 2], [2, 4], [3, 6], [4, 10], [6, 14], [8, 16], [10, 17], [13, 25], [16, 30], [19, 40], [23, 48], [26, 50]]
[[1, 2], [2, 4], [3, 6], [4, 10], [6, 14], [8, 16], [10, 17], [13, 25], [16, 30], [19, 40], [23, 48], [26, 50]]
(7)
 

> CurveFitting:-LeastSquares(PersonsPerYear, t, curve = `+`(`*`(a, `*`(`^`(t, 4))), `*`(b, `*`(`^`(t, 3))), `*`(c, `*`(`^`(t, 2))), `*`(d, `*`(t)), e))
 

`+`(`-`(`/`(524409913342839223, 180252270121727441)), `*`(`/`(10019562801089320883, 2163027241460729292), `*`(t)), `-`(`*`(`/`(718741378209151125, 1442018160973819528), `*`(`^`(t, 2)))), `*`(`/`(66981...
`+`(`-`(`/`(524409913342839223, 180252270121727441)), `*`(`/`(10019562801089320883, 2163027241460729292), `*`(t)), `-`(`*`(`/`(718741378209151125, 1442018160973819528), `*`(`^`(t, 2)))), `*`(`/`(66981...
(8)
 

> `assign`(persons, evalf(sort(%)))
 

`+`(`-`(`*`(0.6017e-3, `*`(`^`(t, 4)))), `*`(0.3097e-1, `*`(`^`(t, 3))), `-`(`*`(.4984, `*`(`^`(t, 2)))), `*`(4.632, `*`(t)), `-`(2.909)) (9)
 

> `assign`(persons, subs(t = normalize(Y), persons)); -1
 

> `assign`(CurvePlot, plot(persons, Y = 1980 .. 2006)); -1
 

> plots[display]({CurvePlot, DataPlot})
 

Plot_2d
 

> `assign`(PersonYears, int(persons, Y = 1981 .. 2006)); -1
 

> `assign`(PersonYears, evalf(PersonYears))
 

679.1 (10)
 

>
 

 

Voila! 

 

1981-1985 

Image 

 

Michael Monagan and Greg Fee 

 

 

 

 

 

 

 

Image 

 

Benton Leong and Howard Johnson 

 

 

Image 

 

A good view of the "ASCII Maple logo" 

 

 

 

 

Image 

 

Stan Devitt, Stephen Watt, Bruce Char, Benton Leong, Keith Geddes 

(in Linz, Austria for the 1985 Eurocal conference) 

 

 

Image 

 

A geeky picture of me in Linz, Austria (1985) 

 

 

 

1986-2006: More Pictures 

 

Image 

 

ISSAC '88 in Rome -- the first to be named "ISSAC" 

 

 

ImageRome 1988 

 

 

ImageBruce Char and Mark Mutrie, Maple Retreat 1989 

 

 

ImageMaple booth, NCTM 1992, Quebec City 

 

 

ImageA view of the competition, NCTM 1992, Quebec City 

 

 

ImageStephen Watt and I with hosts, Kiev 1993 

 

 

ImageKiev 1993 

 

 

ImageThe vodka banquet, Kiev 1993 

 

 

ImageW. Kahan, K. Geddes, D. Jeffrey, G. Labahn, Ha Le, Maple Retreat 1994 

 

 

ImageRob Corless family, Maple Retreat 1994 

 

 

Image 

G. Gonnet, B. Salvy, M. Bronstein, Maple Retreat 1994 

 

 

ImageErich Kaltofen with Allan Bonadio and ??, Maple Retreat 1994 

 

 

ImageGroup picture, Maple Retreat 1994 

 

 

ImageHard at work at the Maple Retreat, Sparrow Lake, Ontario, 1997 

 

 

Image 

A view outside the ISSAC '97 conference, Maui, Hawaii 

 

 

ImageKeith and Debbie, ISSAC '97, Maui, Hawaii