'===========================================================================
' Subject: FUNCTION GRAPHER                   Date: 11-24-96 (00:00)       
'  Author: Toshihiro Horie                    Code: QB, QBasic, PDS        
'  Origin: www.ocf.berkley.edu/~horie/      Packet: ALGOR.ABC
'===========================================================================
' Improved Function Grapher                     '
' Log, scaling, incr, and root bugs fixed.      '
' Copyright (c) 1996 Toshihiro Horie            '

CONST version = 6.72
DEFSNG A-Z
DECLARE FUNCTION atan! (x!)
DECLARE FUNCTION asin! (x!)
DECLARE FUNCTION acos! (x!)
DECLARE FUNCTION csc! (x!)
DECLARE FUNCTION sec! (x!)
DECLARE FUNCTION cot! (x!)
DECLARE FUNCTION log10 (x) : DECLARE FUNCTION ln (x)
DECLARE FUNCTION sinh (x) : DECLARE FUNCTION csch (x)
DECLARE FUNCTION cosh (x) : DECLARE FUNCTION sech (x)
DECLARE FUNCTION tanh (x) : DECLARE FUNCTION coth (x)
DECLARE FUNCTION acosh! (x!) : DECLARE FUNCTION asech! (x!)
DECLARE FUNCTION asinh! (x!) : DECLARE FUNCTION acsch! (x!)
DECLARE FUNCTION acoth! (x!) : DECLARE FUNCTION atanh! (x!)
DECLARE SUB grid (x1!, y1!, XS!, ys!, XC!, YC!, XN!, yn!, xm!, ym!)
DECLARE SUB radianmarks (XC, YC, XS, ys, XN)

CLEAR , , 32767: 'allocate more stack to error handler
ON ERROR GOTO 60

'ln(x) divided by LOG(10)/LOG(e) gives common log
'Common LOG is defined in function LOG10
'LN natural log is defined in func LN
CONST l = 2.3025851#
CONST e = 2.7182818#
CONST pi = 3.14159265357989#
CONST DX = 1 / 1048576

'##########################################################
  XS = 640: ys = 480:        'dimensions of the screen
  xm = 10: ym = 16:          'X AND Y DIMENSIONS OF GRID
'##########################################################


SCREEN 12: CLS : COLOR 15: LOCATE 1, 1
PRINT "FUNCTION GRAPHER Version "; version
PRINT "by Toshihiro Horie Rev 04/06/96"
COLOR 7: LOCATE 24, 4: PRINT "Scale: 1 green unit= 1"
GOSUB VARS
XC = XS \ 2: YC = ys \ 2
XN = XS / xm: yn = INT(XS / ym * 4 / 3)
incr = xm / XC * 4: M1 = 0
CALL grid(x1, y1, XS, ys, XC, YC, XN, yn, xm, ym)
REM =======================START GRAPHING!!!=================================
xi = incr
DEF SEG = 0: ' if scroll lock is on, then double the speed
IF (PEEK(&H417) AND &H10) THEN incr = incr * 2: DEF SEG

'DRAW FIRST POINT.......................
x = -XC / XN - 1
GOSUB equation
XP = x * XN + XC
YP = -Y * yn + YC
PSET (XP, YP), 15

DO
LOCATE 1, 67:  PRINT TIME$
'....................................................KEY CHECK....
in$ = INKEY$: xmode = 1
  IF in$ = "*" THEN xmode = 16
  IF in$ = "+" THEN xmode = 4
  IF in$ = "-" THEN xmode = 1 / 4
  IF in$ = "." THEN xmode = 8
  IF in$ = " " THEN xmode = -4: 'reverse
  IF in$ = "," THEN xmode = 1 / 8
xi = incr * xmode

IF UCASE$(in$) = "Q" THEN GOSUB ASK
IF in$ = CHR$(27) THEN END
'INCREMENT THE X, FIND SLOPE............
'if flat curve then speed up
'IF ABS(M1) < .1 THEN xmode = 1.5
x = x + xi
GOSUB equation
M1 = (Y - yold) / (x - xold)
'.................................................BOUNDARY CHECK..1
IF Y > (YC / yn) + 16 OR Y < (-YC / yn) - 16 THEN
   Errflag2 = 1
   xi = incr * 2
   GOTO SKIP
 ELSE
   xi = incr
END IF
'TRANSLATE TO SCREEN COORDINATES..................................1.5
XP = x * XN + XC
YP = -Y * yn + YC
IF Errflag2 = 1 THEN PSET (XP, YP), 15: Errflag2 = 0
IF Errflag = 1 THEN PSET (XP, YP), 15: Errflag = 0
'DRAW LINE F(X)...................................SLOPE CHECK.....2
IF ABS(M1) > 64 THEN xi = incr / 8
IF ABS(M1) > 256 THEN
        ' vert asymptote - probably
        'LINE (XP, 0)-(XP, 479), 7, , &HCCCC
        xi = incr / 16
        PSET (XP, YP), 15
ELSE
        xi = incr
        LINE -(XP, YP), 15
END IF
'CIRCLE (XP, YP), 3, 12
'PSET (XP - 1, YP), 14: PSET (XP + 1, YP), 14: PSET (XP, YP), 14
'FIND CRITICAL POINTS.............................................3
IF MOLD * M1 < 0 THEN '(Mean Value Theorem)
      CIRCLE (xold * XN + XC, -yold * yn + YC), 4, 11
      COLOR 11
      LOCATE 28, 4: PRINT USING "(+###.###"; xold;
      PRINT USING ",+#####.###) "; yold
      COLOR 15
      PSET (XP, YP), 15
END IF
SKIP:
'SHOW SLOPE AND X,Y COORDINATE....................................4
LOCATE 25, 4: PRINT USING "(+###.##"; x;
PRINT USING ",+#####.##) "; Y
IF SGN(Y) * SGN(yold) <= 0 THEN '...............x-roots (misses mins)
      LOCATE 27, 4: PRINT USING "RootX=###.##"; xold
END IF
MOLD = (Y - yold) / (x - xold)
xold = x: yold = Y
IF x <> 0 THEN LOCATE 26, 4: PRINT USING "slope=+####.##   "; MOLD

skip2:
LOOP WHILE x < (XC / XN)
END
'======================================================================

ASK:
xold = x
LOCATE 1, 1: PRINT STRING$(80, 255);
LOCATE 1, 1: INPUT "X COORDINATE"; x: GOSUB equation: y0 = Y
x = x + DX: GOSUB equation: der1 = (Y - y0) / (DX)
LOCATE 1, 38: PRINT USING "Y COORDINATE IS +######.###"; y0
LOCATE 2, 35: PRINT USING "1st DERIVATIVE  IS +######.####"; der1
Y = 0: y0 = 0: der1 = 0: x = xold
RETURN

60 :
xi = .05
XPE = x * XN + XC: CIRCLE (XPE, YC), 8, 8
LOCATE 25, 5: PRINT USING "Error: ####.##   "; x
Errflag = 1
RESUME skip2

VARS:
'fill in the polynomial's coefficients here
'Don't forget to take out the apostrophe
'before the Y=C4*X^4+C3*X^3... equation
'note:CA/X, CB/X^2, etc. causes overflows near x=0
C4 = .2
C3 = 0
C2 = -1
C1 = 0
C0 = 2
CA = 0
CB = 0
CC = 0
RETURN

equation:
'=================================================================================================
'Use LOG10(X) instead of LOG(X) for common logs!!!!
Y = e ^ x
'  y = C4 * X ^ 4 + C3 * X ^ 3 + C2 * X ^ 2 + C1 * X + C0 + CA / X + CB / X ^ 2 + CC / X ^ 3
'          4th         3rd         2nd         1st       0th      -1th        -2nd       -3rd
'=================================================================================================
RETURN

FUNCTION acos (x)
'0<=y<=pi
IF x < 0 THEN
      acos = ATN(SQR(1 - x * x) / x) + pi
ELSEIF x = 0 THEN
      acos = pi / 2
ELSE
      acos = ATN(SQR(1 - x * x) / x) '(normal)
END IF
END FUNCTION

FUNCTION acosh (x)
'x >= 1
acosh = ln(x + SQR(x ^ 2 - 1))
END FUNCTION

FUNCTION acoth (x)
'³x³ > 1
acoth = .5 * ln((x + 1) / (x - 1))
END FUNCTION

FUNCTION acsch (x)
'x <> 0
acsch = ln(1 / x + SQR(1 + x ^ 2) / ABS(x))
END FUNCTION

FUNCTION asech (x)
'0 < x ó 1
asech = ln((1 + SQR(1 - x ^ 2)) / x)
IF x > 1 THEN END
END FUNCTION

FUNCTION asin (x)
asin = ATN(x / SQR(1 - x * x))
END FUNCTION

FUNCTION asinh (x)
asinh = ln(x + SQR(x ^ 2 + 1))
END FUNCTION

FUNCTION atan (x)
atan = ATN(x)
END FUNCTION

FUNCTION atanh (x)
'³x³ < 1
IF x >= 1 THEN END
atanh = .5 * ln((1 + x) / (1 - x))
END FUNCTION

FUNCTION cosh (x)
cosh = (e ^ x + e ^ -x) / 2
END FUNCTION

FUNCTION cot (x)
cot = 1 / TAN(x)
END FUNCTION

FUNCTION coth (x)
'undefined at x=0
coth = 1 / tanh(x)
END FUNCTION

FUNCTION csc (x)
csc = 1 / SIN(x)
END FUNCTION

FUNCTION csch (x)
'undefined at x=0
csch = 1 / sinh(x)
END FUNCTION

SUB eqs
'  y = (PI / 2 - X) * TAN(X)
'  y = sinh(x)
'  Y = atanh(x)
'  Y = tanh(X)
'  Y = (2 * x) / (SQR(x ^ 2 + x + 1))              'AP CALC AB 1995 #1B
'  Y = (X + 2) / (X ^ 2 + X + 1) ^ 1.5             '1st der #1B
'  Y = e ^ (-X ^ 2)                                      'Bell curve
'  Y = -2 * X * e ^ (-X ^ 2)                             '1st der
'  Y = 2 * X * e ^ (-X ^ 2) * (2 * X ^ 2 - 1)            '2nd der
'  Y = X * ln(X)
' --above are test questions from ch7
'  Y = (1 / X ^ 2) ^ X
'  Y = (2 ^ (COS(X) - 2)) / X
'  Y = (3 ^ (SIN(X) - 1)) / X
'  Y = X ^ (X + 1)
'  Y = X ^ ln(X)
'  Y = X ^ (-SQR(3))
'  Y = X ^ (SQR(2))
'  Y = (1 + 1 / X) ^ X        'e AS X->infinity
'  Y = X ^ (1 / X)
'  Y = X ^ (1 / ln(X))
'  Y = (ln(X)) ^ (-2)
'  Y = 1 / x - 1 / SQR(x)               '\________
'  Y = X * (1 - COS(X)) / (X - SIN(X))  '\/~~~^~~~\/
'  Y = (ln(X)) ^ 2
'  Y = e ^ x - x + 3 * SIN(5 * x) - 2
'  Y = 1 - 2 * COS(x) ^ 3

END SUB

SUB grid (x1, y1, XS, ys, XC, YC, XN, yn, xm, ym)

FOR x1 = XC TO XS STEP XN: LINE (x1, 0)-(x1, ys), 10, , &HAAAA: NEXT x1: REM Vertical down
FOR x1 = XC TO 0 STEP -XN: LINE (x1, 0)-(x1, ys), 10, , &HAAAA: NEXT x1: REM Vertical up
FOR y1 = YC TO ys STEP yn: LINE (0, y1)-(XS, y1), 2, , &HAAAA: NEXT y1:  REM Horizontal right
FOR y1 = YC TO 0 STEP -yn: LINE (0, y1)-(XS, y1), 2, , &HAAAA: NEXT y1:  REM Horizontal left

CN = -1
FOR x1 = XC TO XS STEP XN
        CN = CN + 1: IF CN MOD 5 = 0 THEN CL = 12 ELSE CL = 14
        LINE (x1, YC)-(x1, YC + 3), CL
        LINE (x1 + 1, YC)-(x1 + 1, YC + 3), CL
NEXT x1
CN = -1
FOR x1 = XC TO 0 STEP -XN
        CN = CN + 1: IF CN MOD 5 = 0 THEN CL = 12 ELSE CL = 14
        LINE (x1, YC)-(x1, YC + 3), CL
        LINE (x1 + 1, YC)-(x1 + 1, YC + 3), CL
NEXT x1
CN = -1
FOR y1 = YC TO ys STEP yn
        CN = CN + 1: IF CN MOD 5 = 0 THEN CL = 12 ELSE CL = 14
        LINE (XC, y1)-(XC + 4, y1), CL
NEXT y1
CN = -1
FOR y1 = YC TO 0 STEP -yn
        CN = CN + 1: IF CN MOD 5 = 0 THEN CL = 12 ELSE CL = 14
        LINE (XC, y1)-(XC + 4, y1), CL
NEXT y1
COLOR 15: LOCATE 30, 1
'PRINT "± KEYBOARD GUIDE:  [*] for WARP, [+] for FAST, [-] FOR SLOW, [Escape] to stop. ±";
LOCATE 29, 60: PRINT "[" + LTRIM$(STR$(-xm \ 2)) + "," + LTRIM$(STR$(-ym \ 2)) + "]";
PRINT "x[" + LTRIM$(STR$(xm \ 2)) + "," + LTRIM$(STR$(ym \ 2)) + "]";

LINE (XC, 0)-(XC, ys), 15: LINE (0, YC)-(XS, YC), 15:          REM Center

radianmarks XC, YC, XS, ys, XN

END SUB

FUNCTION ln (x)
'the LOG function in QBASIC returns natural log for some odd reason...
ln = LOG(x)
END FUNCTION

FUNCTION log10 (x)
log10 = LOG(x) / l
END FUNCTION

SUB radianmarks (XC, YC, XS, ys, XN)
CL1 = 9: CL2 = 4
CN = -1: FOR x1 = XC TO XS STEP (XN * pi / 2)
        CN = CN + 1: IF CN MOD 2 = 0 THEN CL = CL1 ELSE CL = CL2
        LINE (x1, YC)-(x1, YC - 3), CL
        DRAW "D2R1L2R1"
        'LINE (X1 + 1, YC)-(X1 + 1, YC - 3), CL
NEXT x1
CN = -1: FOR x1 = XC TO 0 STEP (-XN * pi / 2)
        CN = CN + 1: IF CN MOD 2 = 0 THEN CL = CL1 ELSE CL = CL2
        LINE (x1, YC)-(x1, YC - 3), CL
        DRAW "D2R1L2R1"
        'LINE (X1 - 1, YC)-(X1 + 1, YC - 3), CL
NEXT x1
END SUB

FUNCTION sec (x)
sec = 1 / COS(x)
END FUNCTION

FUNCTION sech (x)
sech = 1 / cosh(x)
END FUNCTION

FUNCTION sinh (x)
sinh = (e ^ x - e ^ -x) / 2
END FUNCTION

FUNCTION tanh (x)
tanh = sinh(x) / cosh(x)
END FUNCTION
