1 rem muligraph cct049 6/5/79 blue tape 100 rem - multigraph - a 'basic' program to graph up to 26 user defined functions 110 rem - automatic self scaling,floating origin,feint points 120 rem - axes : linear or log (see document) 125 rem 130 rem - Copyright Julian.H.Stacey, Canterbury,1977 145 rem 185 rem ************************************************************************* 190 print 195 let g$ = "2/4/79 version" 200 print "entering multigraph - copyright - ";g$ 210 print 220 let f = 0 230 print "how many functions have you entered ?"; 240 input m 250 if m < 1 then 280 260 if m > 26 then 280 270 if m = int(m) then 650 280 print 290 print "document available from author, or ukc (2960 basic) library,"; 310 print 320 print "before running program, enter functions to be printed," 340 print "in the 1100-1200 & 7100-7200 blocks of lines as follows :-" 350 print " 1100 def fna(x)= your 1 st function of x" 360 print " 1102 def fnb(x)= your 2 nd function of x" 370 let q$ = chr$(127) 380 print " 7100 print *f: ";q$;"a = your 1st function";q$ 390 print " 7102 print *f: ";q$;"b = your 2nd function";q$ 400 print " etc" 410 print " use function letters in alphanumeric order, omit no intermediate letters." 420 print " if required,use any remaining function letters,in any order," 430 print " to assist construction of printed functions, input these earlier" 440 print " in program, before printed functions ie :-" 450 print " 1050 def fns(x)=sin(p*x/180) 7050 print *f: ";q$;"s(x)=sin(p*x/180)";q$ 460 print 470 print " variables p,k,e are already defined as 4*arctan(1),log(10),10^(1/k)" 480 print " variables q,r,t,u,q1,q2, etc are unassigned (set at run time," 490 print " if required), insert before all def functions ie :-" 500 print " 1000 let q=1.6021 e-19 7000 print *f: ";q$;"q=1.6021 e-19";a$ 510 print 520 print "if required input graph title in line block 6900-6950 as follows :-" 530 print " 6900 print *f: ";a$;"your graph title";q$ 540 print " 6902 print *f: ";q$;"continued";q$ 550 print 560 print "functions need only be input once,if multigraph is accessed" 570 print "via ukc file name pregraph, this generates :-" 580 print " def fna(x) = . . . & print *f: ";a$;"a(x) = . . . ";q$ 590 print "from one input of ";a$;"a(x) = . .(5 ";q$ 600 print 610 print "functions at present are :-" 620 gosub 6990 630 print 640 goto 4290 650 rem - define pi,log(10),e 660 let p = 4*atn(1) 670 let k = log(10) 680 let e = 10^(1/k) 690 rem ************************************************************************* 700 rem - user defined variables & functions below 1300 rem ************************************************************************ 1310 rem - parameter input 1315 print "input the following :-" 1320 print "min x,max x,points/function,max/easy scale,"; 1330 print "feint points,lineprinter,file" 1340 print "example: -8 , 27 , 5 , max ,"; 1350 print " yes , n , no" 1360 input x1,x2,n,a$,c$,d$,b$ 1370 if x1 <> x2 then 1410 1380 print "min x = max x not allowed - reinput min x,max x :"; 1390 input x1,x2 1400 goto 1370 1410 if n <= 0 then 1430 1420 if n = int(n) then 1460 1430 print "how many graph points per function do you require ?"; 1440 input n 1450 goto 1410 1460 let n = 5*int((n+4)/5) 1470 rem - select scaling 1480 let c1 = 2 1490 if a$ = "max" then 1580 1500 if a$ = "m" then 1580 1510 let c1 = 1 1520 if a$ = "easy" then 1580 1530 if a$ = "e" then 1580 1540 print "do you want maximum graphspace utilisation, or easy scaling" 1550 print "for axis readoff ? - answer max or easy :"; 1560 input a$ 1570 goto 1470 1580 rem - decide background points 1590 if c$ = "yes" then 1660 1600 if c$ = "y" then 1660 1610 if c$ = "no" then 1660 1620 if c$ = "n" then 1660 1630 print "do you want background line points ? - answer yes or no :"; 1640 input c$ 1650 goto 1580 1660 rem - decide paper size 1670 margin *f: 0 1680 let s2 = 2 1690 if d$ = "yes" then 1800 1700 if d$ = "y" then 1800 1710 let s2 = 1 1720 if d$ = "no" then 1800 1730 if d$ = "n" then 1800 1740 print "will output device print >=115 chars/line ie lineprinter ?" 1750 print "answer yes or no :"; 1760 input d$ 1770 goto 1660 1800 rem - input ended 1802 rem - set 'graphs plotted' count to 0 1805 let c3 = 0 1820 rem ************************************************************************ 1830 rem - ensure x2>x1 1840 if x2 > x1 then 1880 1850 let z = x2 1860 let x2 = x1 1870 let x1 = z 1880 rem - find y1,y2 the min,max values of f(x), as the 1st stage of determining the limits of the graph 1890 optionbase 1 1900 dim m(27,3) 1910 let y1 = fna(x1) 1920 let y2 = fna(x1) 1930 for v = 0 to n 1940 gosub 4840 1950 for i = 2 to m+1 1960 if m(i,3) >= y1 then 1990 1970 let y1 = m(i,3) 1980 goto 2010 1990 if m(i,3) <= y2 then 2010 2000 let y2 = m(i,3) 2010 next i 2020 next v 2030 if y1 <> y2 then 2050 2031 print 2032 print "min f(x) = max f(x) - have you input: f(x)=constant, or" 2034 print "numbers beyond computer capability ie f(x)=10^30+sin(x) ?" 2035 print 2036 print "functions at present are :-" 2038 gosub 6990 2040 print 2042 goto 4290 2050 rem - find m1 & m2, the mantissae of y1 & y2, relative to the largest exponent e2 2060 if abs(y1) < abs(y2) then 2090 2070 let e2 = int(log(abs(y1*1.000001))/k)+1 2080 goto 2100 2090 let e2 = int(log(abs(y2*1.000001))/k)+1 2100 let m1 = y1*10^(-e2) 2110 let m2 = y2*10^(-e2) 2120 rem - prepare to calculate the lower, & upper graph limits l1 & l2 2130 let z = m2-m1 2220 let c = c1-1 2230 if z > 1.000001 then 2270 2235 rem - .999999 allows for the machine fractional error case z = .2 - .1 = .0999999 2240 let z = 10*z 2250 let c = c+1 2260 goto 2230 2270 rem - set a & b to increase or decrease mantissae to convenient limits,dependent where f(x) = 0 lies relative to the range of 2275 rem - the graph 2280 let a = 0 2290 let b = 1 2295 rem > > if min f(x) >= 0 then decrease [lower limit], & increase [upper limit] 2300 if y1 >= 0 then 2340 2310 let a = 1 2315 rem > > if min f(x) < 0 < max f(x) then increase [lower limit ], & increase [upper limit] 2320 if y2 > 0 then 2340 2330 let b = 0 2335 rem > > as max f(x) < 0, increase [lower limit], & decrease [upper limit] 2340 rem - calculate l1 & l2, the lower & upper graph limits 2350 let m1 = abs(m1) 2360 let m2 = abs(m2) 2365 rem > > if m1 is not .260001 or similar (attributable to machine round off), then do not prevent the limit being increased 2370 if m1*9.99999^c1 > int(m1*10.0001^c1) then 2390 2380 let a = 0 2390 let l1 = sgn(y1)*10^(e2-c)*(int(m1*10.00001^c)+a) 2400 if m2*9.99999^c1 > int(m2*10.0001^c1) then 2420 2410 let b = 0 2420 let l2 = sgn(y2)*10^(e2-c)*(int(m2*10.00001^c)+b) 2430 rem - decide scale factor now lower & upper limits are available 2440 let z = (l2-l1)*10^(c-e2-c1) 2450 let s = 1/z 2460 if a$ = "max" then 2530 2470 if a$ = "m" then 2530 2480 let s = 1 2490 if z > .5 then 2530 2500 let s = 2 2510 if z > .2 then 2530 2520 let s = 5 2530 let s = (10^(c1-c+e2))/(s*50*s2) 2540 rem - s is f(x) units per column tab,l1 is lower limit of f(x) axis 2550 rem ************************************************************************ 2560 rem - print graph 2570 if b$ = "no" then 2670 2580 if b$ = "n" then 2670 2590 print "wait while graph is filed in ";b$ 2600 let f = 1 2610 file *f: b$ 2620 margin *f: 0 2630 gosub 4320 2640 print *f: "this graph was stored in filename '";b$;"', & drawn by 'multigraph' (";g$;") - programmer: j.h.stacey" 2650 print *f: 2660 goto 2680 2670 gosub 4320 2680 gosub 6890 2690 print *f: "functions on horizontal axis - ordinate on vertical - "; 2700 print *f: "&=coincident point" 2710 print *f: 2720 gosub 4590 2730 gosub 4730 2740 rem - decide whether to plot y axis in graph(g=1),or at edge(g=2). 2750 let g = 2 2760 if l1 > 0 then 2790 2770 if l2 <= 0 then 2790 2780 let g = 1 2790 rem - set x5 for use truncating the ordinate axis print 2800 let x5 = int(log(4.99999*(x2-x1)/n)/k-2) 2810 rem - set nominal 1st line print order in the (_,2) column of the matrix 2820 for i = 1 to m+1 2830 let m(i,2) = i 2840 next i 2850 for v = 0 to n 2860 rem - one line printed per v increment 2870 let p2 = 15 2880 let p1 = 0 2890 gosub 4840 2900 rem - load new line tab values in (_,1), taking the alphabetic function values in (_,3), in the previous line order of (_,2) 2910 let m(1,1) = 14 2920 for i = g to m+1 2930 let m(i,1) = 15+(m(m(i,2),3)-l1)/s 2940 next i 2950 rem - check new line is in ascending order, if necessary correcting by backtracking 2960 for i = g+1 to m+1 2970 if m(i-1,1) <= m(i,1) then 3080 2980 let z = m(i,1) 2990 let z2 = m(i,2) 3000 for j = i-1 to g step -1 3010 if m(j,1) <= z then 3060 3020 let m(j+1,1) = m(j,1) 3030 let m(j+1,2) = m(j,2) 3040 next j 3050 let j = g-1 3060 let m(j+1,1) = z 3070 let m(j+1,2) = z2 3080 next i 3090 rem - print ordinate on 5th lines 3100 let v1 = v/5-int(v/5) 3110 if v1 > 0 then 3130 3120 print *f: sgn(h)*10^x5*int(abs(h)*10^(-x5)+.5); 3130 let w = 0 3140 for i = 1 to m+1 3150 rem - one non coincident point printed per increment 3160 if i = m+1 then 3270 3180 if int(.5+m(i,1)) <> int(.5+m(i+1,1)) then 3240 3190 if w = 1 then 4000 3200 gosub 4420 3210 print *f: tab(m(i,1));"&"; 3220 let w = 1 3230 goto 4000 3240 if w <> 1 then 3280 3250 let w = 0 3260 goto 4000 3270 if w = 1 then 4000 3280 rem - print normal point 3290 gosub 4420 3300 if m(i,2) > 10 then 3320 3310 on m(i,2) goto 3350,3440,3500,3520,3540,3560,3580,3600,3620,3640 3320 if m(i,2) > 20 then 3340 3330 on m(i,2)-10 goto 3660,3680,3700,3720,3740,3760,3780,3800,3820 3340 on m(i,2)-20 goto 3840,3860,3880,3900,3920,3940,3960,3980 3350 if v1 = 0 then 3420 3360 if d$ = "no" then 3400 3370 if d$ = "n" then 3400 3380 print *f: tab(m(i,1));"|"; 3390 goto 4000 3400 print *f: tab(m(i,1));"!"; 3410 goto 4000 3420 print *f: tab(m(i,1));"+"; 3430 goto 4000 3440 rem - print * if 1 function is to be plotted, a if more than 1 function 3450 if m > 1 then 3480 3460 print *f: tab(m(i,1));"*"; 3470 goto 4000 3480 print *f: tab(m(i,1));"a"; 3490 goto 4000 3500 print *f: tab(m(i,1));"b"; 3510 goto 4000 3520 print *f: tab(m(i,1));"c"; 3530 goto 4000 3540 print *f: tab(m(i,1));"d"; 3550 goto 4000 3560 print *f: tab(m(i,1));"e"; 3570 goto 4000 3580 print *f: tab(m(i,1));"f"; 3590 goto 4000 3600 print *f: tab(m(i,1));"g"; 3610 goto 4000 3620 print *f: tab(m(i,1));"h"; 3630 goto 4000 3640 print *f: tab(m(i,1));"i"; 3650 goto 4000 3660 print *f: tab(m(i,1));"j"; 3670 goto 4000 3680 print *f: tab(m(i,1));"k"; 3690 goto 4000 3700 print *f: tab(m(i,1));"l"; 3710 goto 4000 3720 print *f: tab(m(i,1));"m"; 3730 goto 4000 3740 print *f: tab(m(i,1));"n"; 3750 goto 4000 3760 print *f: tab(m(i,1));"o"; 3770 goto 4000 3780 print *f: tab(m(i,1));"p"; 3790 goto 4000 3800 print *f: tab(m(i,1));"q"; 3810 goto 4000 3820 print *f: tab(m(i,1));"r"; 3830 goto 4000 3840 print *f: tab(m(i,1));"s"; 3850 goto 4000 3860 print *f: tab(m(i,1));"t"; 3870 goto 4000 3880 print *f: tab(m(i,1));"u"; 3890 goto 4000 3900 print *f: tab(m(i,1));"v"; 3910 goto 4000 3920 print *f: tab(m(i,1));"w"; 3930 goto 4000 3940 print *f: tab(m(i,1));"x"; 3950 goto 4000 3960 print *f: tab(m(i,1));"y"; 3970 goto 4000 3980 print *f: tab(m(i,1));"z"; 3990 goto 4000 4000 if i < m+1 then 4030 4010 let p1 = 1 4020 gosub 4420 4030 next i 4040 print *f: 4050 next v 4060 gosub 4730 4070 gosub 4590 4080 gosub 4320 4085 rem ************************************************************************ 4090 rem - decide if graph needs to be output to a 2nd device 4100 if b$ = "no" then 4130 4110 if b$ = "n" then 4130 4120 print "graph in file ";b$ 4130 if c3 = 1 then 4290 4140 ft c3 = 1 4150 if b$ = "no" then 4170 4160 if b$ <> "n" then 4220 4170 print "do you want graph filed now ? - answer no, n, or filename :"; 4180 input b$ 4190 if b$ = "no" then 4290 4200 if b$ = "n" then 4290 4210 goto 2560 4220 print "do you want the graph replotted here ?"; 4230 input e$ 4240 let f = 0 4250 margin *f: 0 4260 let b$ = "no" 4270 if e$ = "yes" then 2560 4280 if e$ = "y" then 2560 4290 print "leaving multigraph - ";g$ 4300 end 4310 rem ************************************************************************ 4320 rem - subroutine - line mark off top & bottom of graph 4330 for i = 1 to 5 4340 print *f: 4350 if i <> 2 then 4390 4360 for j = 1 to 20+50*s2 4370 print *f: "-"; 4380 next j 4390 next i 4400 return 4410 rem ************************************************************************ 4420 rem - subroutine - background feint point plotter 4430 if c$ = "no" then 4570 4440 if c$ = "n" then 4570 4450 if v1 > 0 then 4570 4460 if p2 > int(m(i,1)+.5) then 4520 4470 if p2 = int(m(i,1)+.5) then 4510 4480 print *f: tab(p2);"."; 4490 let p2 = p2+10 4500 goto 4460 4510 let p2 = p2+10 4520 if p1 = 0 then 4570 4530 let z = 15+10*(1+int((m(i,1)-14.5)/10)) 4540 for j = z to 15+50*s2 step 10 4550 print *f: tab(j);"."; 4560 next j 4570 return 4580 rem ************************************************************************ 4590 rem - subroutine - print horizontal axis scale 4600 let z = int(log((l2-l1)/(5.00001*s2))/k)-c1-2 4610 for i = 0 to 50*s2 step 10 4620 let y = l1+i*s 4630 print *f: tab(i+14);sgn(y)*10^z*int(abs(y)*10^(-z)+.5); 4640 rem - print 0 on horiz. axis 4650 if -l1/s <= i+.5 then 4690 4660 if -l1/s >= i+9.5 then 4690 4670 if i = 50*s2 then 4690 4680 print *f: tab(15-l1/s);"0"; 4690 next i 4700 print *f: 4710 return 4720 rem ************************************************************************ 4730 rem - subroutine - print horizontal axis line 4740 print *f: tab(8);"-f(x)<-"; 4750 for i = 0 to 50*s2 4760 if i/10 = int(i/10) then 4790 4770 print *f: tab(i+15);"-"; 4780 goto 4800 4790 print *f: tab(i+15);"+"; 4800 next i 4810 print *f: tab(50*s2+16);"->f(x)" 4820 return 4830 rem ************************************************************************ 4840 rem - subroutine - fill matrix column (_,3) with function values 4850 let h = x1+(x2-x1)*v/n 4860 if m > 10 then 4880 4870 on m goto 5160,5150,5140,5130,5120,5110,5100,5090,5080,5070 4880 if m > 20 then 4900 4890 on m-10 goto 5060,5050,5040,5030,5020,5010,5000,4990,4980,4970 4900 on m-20 goto 4960,4950,4940,4930,4920,4910 4910 let m(27,3) = fnz(h) 4920 let m(26,3) = fny(h) 4930 let m(25,3) = fnx(h) 4940 let m(24,3) = fnw(h) 4950 let m(23,3) = fnv(h) 4960 let m(22,3) = fnu(h) 4970 let m(21,3) = fnt(h) 4980 let m(20,3) = fns(h) 4990 let m(19,3) = fnr(h) 5000 let m(18,3) = fnq(h) 5010 let m(17,3) = fnp(h) 5020 let m(16,3) = fno(h) 5030 let m(15,3) = fnn(h) 5040 let m(14,3) = fnm(h) 5050 let m(13,3) = fnl(h) 5060 let m(12,3) = fnk(h) 5070 let m(11,3) = fnj(h) 5080 let m(10,3) = fni(h) 5090 let m(9,3) = fnh(h) 5100 let m(8,3) = fng(h) 5110 let m(7,3) = fnf(h) 5120 let m(6,3) = fne(h) 5130 let m(5,3) = fnd(h) 5140 let m(4,3) = fnc(h) 5150 let m(3,3) = fnb(h) 5160 let m(2,3) = fna(h) 5170 let m(1,3) = 0 5180 return 5190 rem ************************************************************************ 6890 rem - subroutine - print graph header 6960 print *f: 6970 print *f: "functions defined as :-" 6980 rem - return deliberately omitted 6990 rem - subroutine - print functions 9010 return 9020 rem ************************************************************************ 9030 rem - constants used a,b,c,c1,c3,e,e2,f,g,h,k,l1,l2,m,m1,m2,n,p,p1, 9040 rem - p2,s,s2,v1,w,x1,x2,x5,y,y1,y2 temporary variables z,z2 9050 rem - loops i,j,v matrix m(27,3) strings a$,b$,c$,d$,e$,g$,q$