256 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Brainfuck
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			256 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Brainfuck
		
	
	
		
			Executable File
		
	
	
	
	
| /* libmath.b for bc for minix.  */
 | |
| 
 | |
| /*  This file is part of bc written for MINIX.
 | |
|     Copyright (C) 1991, 1992 Free Software Foundation, Inc.
 | |
| 
 | |
|     This program is free software; you can redistribute it and/or modify
 | |
|     it under the terms of the GNU General Public License as published by
 | |
|     the Free Software Foundation; either version 2 of the License , or
 | |
|     (at your option) any later version.
 | |
| 
 | |
|     This program is distributed in the hope that it will be useful,
 | |
|     but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|     GNU General Public License for more details.
 | |
| 
 | |
|     You should have received a copy of the GNU General Public License
 | |
|     along with this program; see the file COPYING.  If not, write to
 | |
|     the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 | |
| 
 | |
|     You may contact the author by:
 | |
|        e-mail:  phil@cs.wwu.edu
 | |
|       us-mail:  Philip A. Nelson
 | |
|                 Computer Science Department, 9062
 | |
|                 Western Washington University
 | |
|                 Bellingham, WA 98226-9062
 | |
|        
 | |
| *************************************************************************/
 | |
| 
 | |
| 
 | |
| scale = 20
 | |
| 
 | |
| /* Uses the fact that e^x = (e^(x/2))^2
 | |
|    When x is small enough, we use the series:
 | |
|      e^x = 1 + x + x^2/2! + x^3/3! + ...
 | |
| */
 | |
| 
 | |
| define e(x) {
 | |
|   auto  a, d, e, f, i, m, v, z
 | |
| 
 | |
|   /* Check the sign of x. */
 | |
|   if (x<0) {
 | |
|     m = 1
 | |
|     x = -x
 | |
|   } 
 | |
| 
 | |
|   /* Precondition x. */
 | |
|   z = scale;
 | |
|   scale = 4 + z + .44*x;
 | |
|   while (x > 1) {
 | |
|     f += 1;
 | |
|     x /= 2;
 | |
|   }
 | |
| 
 | |
|   /* Initialize the variables. */
 | |
|   v = 1+x
 | |
|   a = x
 | |
|   d = 1
 | |
| 
 | |
|   for (i=2; 1; i++) {
 | |
|     e = (a *= x) / (d *= i)
 | |
|     if (e == 0) {
 | |
|       if (f>0) while (f--)  v = v*v;
 | |
|       scale = z
 | |
|       if (m) return (1/v);
 | |
|       return (v/1);
 | |
|     }
 | |
|     v += e
 | |
|   }
 | |
| }
 | |
| 
 | |
| /* Natural log. Uses the fact that ln(x^2) = 2*ln(x)
 | |
|     The series used is:
 | |
|        ln(x) = 2(a+a^3/3+a^5/5+...) where a=(x-1)/(x+1)
 | |
| */
 | |
| 
 | |
| define l(x) {
 | |
|   auto e, f, i, m, n, v, z
 | |
| 
 | |
|   /* return something for the special case. */
 | |
|   if (x <= 0) return (1 - 10^scale)
 | |
| 
 | |
|   /* Precondition x to make .5 < x < 2.0. */
 | |
|   z = scale;
 | |
|   scale += 4;
 | |
|   f = 2;
 | |
|   i=0
 | |
|   while (x >= 2) {  /* for large numbers */
 | |
|     f *= 2;
 | |
|     x = sqrt(x);
 | |
|   }
 | |
|   while (x <= .5) {  /* for small numbers */
 | |
|     f *= 2;
 | |
|     x = sqrt(x);
 | |
|   }
 | |
| 
 | |
|   /* Set up the loop. */
 | |
|   v = n = (x-1)/(x+1)
 | |
|   m = n*n
 | |
| 
 | |
|   /* Sum the series. */
 | |
|   for (i=3; 1; i+=2) {
 | |
|     e = (n *= m) / i
 | |
|     if (e == 0) {
 | |
|       v = f*v
 | |
|       scale = z
 | |
|       return (v/1)
 | |
|     }
 | |
|     v += e
 | |
|   }
 | |
| }
 | |
| 
 | |
| /* Sin(x)  uses the standard series:
 | |
|    sin(x) = x - x^3/3! + x^5/5! - x^7/7! ... */
 | |
| 
 | |
| define s(x) {
 | |
|   auto  e, i, m, n, s, v, z
 | |
| 
 | |
|   /* precondition x. */
 | |
|   z = scale 
 | |
|   scale = 1.1*z + 1;
 | |
|   v = a(1)
 | |
|   if (x < 0) {
 | |
|     m = 1;
 | |
|     x = -x;
 | |
|   }
 | |
|   scale = 0
 | |
|   n = (x / v + 2 )/4
 | |
|   x = x - 4*n*v
 | |
|   if (n%2) x = -x
 | |
| 
 | |
|   /* Do the loop. */
 | |
|   scale = z + 2;
 | |
|   v = e = x
 | |
|   s = -x*x
 | |
|   for (i=3; 1; i+=2) {
 | |
|     e *= s/(i*(i-1))
 | |
|     if (e == 0) {
 | |
|       scale = z
 | |
|       if (m) return (-v/1);
 | |
|       return (v/1);
 | |
|     }
 | |
|     v += e
 | |
|   }
 | |
| }
 | |
| 
 | |
| /* Cosine : cos(x) = sin(x+pi/2) */
 | |
| define c(x) {
 | |
|   auto v;
 | |
|   scale += 1;
 | |
|   v = s(x+a(1)*2);
 | |
|   scale -= 1;
 | |
|   return (v/1);
 | |
| }
 | |
| 
 | |
| /* Arctan: Using the formula:
 | |
|      atan(x) = atan(c) + atan((x-c)/(1+xc)) for a small c (.2 here)
 | |
|    For under .2, use the series:
 | |
|      atan(x) = x - x^3/3 + x^5/5 - x^7/7 + ...   */
 | |
| 
 | |
| define a(x) {
 | |
|   auto a, e, f, i, m, n, s, v, z
 | |
| 
 | |
|   /* Special case and for fast answers */
 | |
|   if (x==1) {
 | |
|     if (scale <= 25) return (.7853981633974483096156608/1)
 | |
|     if (scale <= 40) return (.7853981633974483096156608458198757210492/1)
 | |
|     if (scale <= 60) \
 | |
|       return (.785398163397448309615660845819875721049292349843776455243736/1)
 | |
|   }
 | |
|   if (x==.2) {
 | |
|     if (scale <= 25) return (.1973955598498807583700497/1)
 | |
|     if (scale <= 40) return (.1973955598498807583700497651947902934475/1)
 | |
|     if (scale <= 60) \
 | |
|       return (.197395559849880758370049765194790293447585103787852101517688/1)
 | |
|   }
 | |
| 
 | |
|   /* Negative x? */
 | |
|   if (x<0) {
 | |
|     m = 1;
 | |
|     x = -x;
 | |
|   }
 | |
| 
 | |
|   /* Save the scale. */
 | |
|   z = scale;
 | |
| 
 | |
|   /* Note: a and f are known to be zero due to being auto vars. */
 | |
|   /* Calculate atan of a known number. */ 
 | |
|   if (x > .2)  {
 | |
|     scale = z+4;
 | |
|     a = a(.2);
 | |
|   }
 | |
|    
 | |
|   /* Precondition x. */
 | |
|   scale = z+2;
 | |
|   while (x > .2) {
 | |
|     f += 1;
 | |
|     x = (x-.2) / (1+x*.2);
 | |
|   }
 | |
| 
 | |
|   /* Initialize the series. */
 | |
|   v = n = x;
 | |
|   s = -x*x;
 | |
| 
 | |
|   /* Calculate the series. */
 | |
|   for (i=3; 1; i+=2) {
 | |
|     e = (n *= s) / i;
 | |
|     if (e == 0) {
 | |
|       scale = z;
 | |
|       if (m) return ((f*a+v)/-1);
 | |
|       return ((f*a+v)/1);
 | |
|     }
 | |
|     v += e
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Bessel function of integer order.  Uses the following:
 | |
|    j(-n,x) = (-1)^n*j(n,x) 
 | |
|    j(n,x) = x^n/(2^n*n!) * (1 - x^2/(2^2*1!*(n+1)) + x^4/(2^4*2!*(n+1)*(n+2))
 | |
|             - x^6/(2^6*3!*(n+1)*(n+2)*(n+3)) .... )
 | |
| */
 | |
| define j(n,x) {
 | |
|   auto a, d, e, f, i, m, s, v, z
 | |
| 
 | |
|   /* Make n an integer and check for negative n. */
 | |
|   z = scale;
 | |
|   scale = 0;
 | |
|   n = n/1;
 | |
|   if (n<0) {
 | |
|     n = -n;
 | |
|     if (n%2 == 1) m = 1;
 | |
|   }
 | |
| 
 | |
|   /* Compute the factor of x^n/(2^n*n!) */
 | |
|   f = 1;
 | |
|   for (i=2; i<=n; i++) f = f*i;
 | |
|   scale = 1.5*z;
 | |
|   f = x^n / 2^n / f;
 | |
| 
 | |
|   /* Initialize the loop .*/
 | |
|   v = e = 1;
 | |
|   s = -x*x/4
 | |
|   scale = 1.5*z
 | |
| 
 | |
|   /* The Loop.... */
 | |
|   for (i=1; 1; i++) {
 | |
|     e =  e * s / i / (n+i);
 | |
|     if (e == 0) {
 | |
|        scale = z
 | |
|        if (m) return (-f*v/1);
 | |
|        return (f*v/1);
 | |
|     }
 | |
|     v += e;
 | |
|   }
 | |
| }
 | 
