File TRANSC.PS

Directory of image this file is from
This file as a plain text file

program dummy(output);{ elementary functions as implemented for PDP8 Pascal }

{--------------------------------------------------------------------}

  { These functions are specially coded for the PDP8 FPP,
    and assume the machine has a guard digit.
    Coded by James F. Miner and John T. Easton,
    University of Minnesota.

    References.

    1. "Software Manual for the Elementary Functions",
       William J. Cody, Jr.   Argonne National Laboratory
       and
       William Waite.	      Department of Electrical Engineering
			      University of Colorado.

       Copyright 1980 Prentice-Hall, Inc., Englewood Cliffs,
		      New Jersey  07632.

    2. "FPP8-A Maintenance Manual"  EK-FPP8A-MM-001
       Digital Equipment Corporation, Maynard Massachusetts.

  }
{$L-}

{--------------------------------------------------------------------}

  function sin(x: real): real;

    const  eps = { 2 ** (-23/2) } 0.0003452;
	   c1 = 3.140625;
	   c2 = 9.67653589793e-4;
	   ymax = 9099.0242; { pi * 2 ** (23/2) }
	   PiInverse = { 1/pi } 0.31830988618379067154;

    var   y, z, sgn, xn, f, g: real;
	  n: integer;

  begin { sin }
    z := abs(x);
    y := z { for comparibility with cos };
    if x < 0 then sgn := -1.0 else sgn := 1.0;
    if y > ymax then
      begin
	writeln(output,'*** magnitude of sin operand is too large.');
	sin := 0 { halt }
      end
    else
      begin
	n := round(y * PiInverse);
	xn := n;
	if odd(n) then sgn := - sgn;
	f := (z - xn * c1) - xn * c2;
	if abs(f) < eps then sin := sgn * f
	else
	  begin  g := sqr(f);
	    sin := sgn * ( f + f * ( ( ( ( 0.2601903036e-5 * g
					  -0.1980741872e-3)* g
					+  0.8333025139e-2)* g
				      -    0.1666665668e+0)* g
				   )
			 )
	  end
      end
  end { sin } ;

{--------------------------------------------------------------------}

  function cos(x: real): real;

    const  eps = { 2 ** (-23/2) } 0.0003452;
	   c1 = 3.140625;
	   c2 = 9.67653589793e-4;
	   ymax = 9099.0242; { pi * 2 ** (23/2) }
	   PiInverse = { 1/pi } 0.31830988618379067154;
	   PiOver2 = { pi/2 } 1.57079632679489661923;

    var   y, z, sgn, xn, f, g: real;
	  n: integer;

  begin { cos }
    z := abs(x);
    y := z + PiOver2;
    sgn := 1.0;
    if y > ymax then
      begin
	writeln(output,'*** magnitude of cos operand is too large.');
	cos := 0 { halt }
      end
    else
      begin
	n := round(y * PiInverse);
	xn := n - 0.5 { cos only };
	if odd(n) then sgn := - sgn;
	f := (z - xn * c1) - xn * c2;
	if abs(f) < eps then cos := sgn * f
	else
	  begin  g := sqr(f);
	    cos := sgn * ( f + f * ( ( ( ( 0.2601903036e-5 * g
					  -0.1980741872e-3)* g
					+  0.8333025139e-2)* g
				      -    0.1666665668e+0)* g
				   )
			 )
	  end
      end
  end { cos } ;

{--------------------------------------------------------------------}

  function arctan(x: real): real;

    const  eps = { 2 ** (-23/2) } 0.0003452;
	   k1 = 0.26794919243112270647 { 2-sqrt(3) };
	   k2 = 1.73205080756887729353 { sqrt(3) };
	   k3 = 0.73205080756887729353 { sqrt(3)-1 };

    var   f, result, g: real;
	  n: 0..3;

  begin { arctan }
    f := abs(x);
    if f > 1.0 then begin n := 2; f := 1.0 / f end
    else n := 0;
    if f > k1 then
      begin  n := n + 1;
	f := ( ( (k3 * f - 0.5) - 0.5) + f) / (k2 + f)
      end;
    if abs(f) < eps then result := f
    else
      begin  g := sqr(f);
	result := f + f * ( ( -0.5090958253e-1 * g - 0.4708325141e0 ) * g
			   /(g + 0.1412500740e1) )
      end;
    if n > 1 then result := - result;
    case n of
      0:  { null } ;
      1:  result := result + 0.52359877559829887308 { pi/6 };
      2:  result := result + 1.57079632679489661923 { pi/2 };
      3:  result := result + 1.04719755119659774615 { pi/3 }
    end;
    if x < 0 then arctan := - result else arctan := result
  end { arctan } ;

{--------------------------------------------------------------------}

  function intxp(x : real) : integer;
    type
      trick = record case boolean of
		false: (reel:real);
		true:  (expon: -2048..2047; hi,lo: 0..4095)
	      end;
    var z : trick;
  begin { intxp }
    z.reel := x;
    intxp := z.expon
  end	{ intxp };

{--------------------------------------------------------------------}

  function setxp(x : real; n : integer) : real;
    type
      trick = record case boolean of
		false: (reel:real);
		true:  (expon: -2048..2047; hi,lo: 0..4095)
	      end;
    var z : trick;
  begin { setxp }
    z.reel := x;
    z.expon := n;
    setxp := z.reel
  end	{ setxp };

{--------------------------------------------------------------------}

  function adx(x : real; n : integer) : real;
    type
      trick = record case boolean of
		false: (reel:real);
		true:  (expon: -2048..2047; hi,lo: 0..4095)
	      end;
    var z : trick;
  begin { adx }
    z.reel := x;
    z.expon := z.expon + n;
    adx := z.reel
  end	{ adx };

{--------------------------------------------------------------------}

  function exp(x : real) : real;

    const
      ln2inverse = 1.4426950408889634074 { 1.0/ln(2) };
      c1 = 0.693359375 { 355/512  or .543 octal };
      c2 = -2.1219444005469058277e-4;
      bigx = 1416.0898 { <~ln(maxreal) };
      smallx = -1416.0898 { >~ln(leastreal) };
      eps = 5.9604645e-8 { (2**(-23)) / 2 };

      p0 = 0.24999999950;
      p1 = 0.41602886268e-2;
      q0 = 0.5;
      q1 = 0.49987178778e-1;

    var
      n : integer;
      xn, g, r, z, gpz : real;

  begin { exp }
    if x > bigx then
      begin
	writeln(output,' ** operand of exp is too large');
	exp := 0.0 { halt }
      end
    else if x < smallx then
      begin
	writeln(output,' ** operand of exp is too small');
	exp := 0.0 { halt }
      end
    else if abs(x) < eps then exp := 1.0
    else
      begin
	n := round(x * ln2inverse);
	xn := n;
	g := (x - xn * c1) - xn * c2;
	z := sqr(g);
	gpz := (p1 * z + p0) * g;
	r := gpz / ((q1 * z + q0) - gpz) + 0.5;
	exp := adx(r,(n+1)) { r * 2**(n+1) }
      end
  end { exp };

{--------------------------------------------------------------------}

  function ln(x : real) : real;

    const
      c0 = 0.70710678118654752440 { sqrt(0.5) };
      c1 = 0.6933593 { 355/512	or in octal .543 };
      c2 = -2.121944400546905827679e-4;
      a0 = -0.5527074855;
      b0 = -0.6632718214e1;

    var
      n : integer;
      f, znum, zden, w, z : real;
  begin { ln }
    if x <= 0.0 then
      begin
	writeln(output,' ** operand of ln must be positive');
	ln := 0.0 { halt }
      end
    else
      begin
	n := intxp(x);
	f := setxp(x,0);
	if f <= c0 then
	  begin
	    n := n - 1;
	    znum := f - 0.5;
	    zden := 0.5 * znum + 0.5
	  end
	else
	  begin
	    znum := (f - 0.5) - 0.5;
	    zden := 0.5 * f + 0.5
	  end;
	z := znum / zden;
	w := sqr(z);
	ln := ( ( ( w*a0 / (w+b0) )*z + z ) + c2*n ) + c1*n
      end
  end	{ ln };

{--------------------------------------------------------------------}

  function sqrt(x : real) : real;

    var
      n : integer;
      f, y, z : real;

  begin { sqrt }
    if x < 0.0 then
      begin
	writeln(output,' ** argument to SQRT is negative');
	sqrt := 0.0 { halt }
      end
    else if x = 0.0 then sqrt := 0.0
    else
      begin
	n := intxp(x);
	f := setxp(x,0);
	y := 0.41731 + 0.59016 * f;
	z := y + f / y;
	y := 0.25 * z  +  f / z;
	if odd(n) then
	  begin
	    y := y * 0.707106781186547 { sqrt(0.5) };
	    n := n + 1
	  end;
	sqrt := adx(y, n div 2) { (2 ** (n div 2) ) * y }
      end
  end { sqrt };

{--------------------------------------------------------------------}

begin { dummy }
end   { dummy }.



Feel free to contact me, David Gesswein djg@pdp8online.com with any questions, comments on the web site, or if you have related equipment, documentation, software etc. you are willing to part with.  I am interested in anything PDP-8 related, computers, peripherals used with them, DEC or third party, or documentation. 

PDP-8 Home Page   PDP-8 Site Map   PDP-8 Site Search