blob: 3b86486c2e4102f9fc15adde6e7cd36e6986bc85 [file] [log] [blame]
/*
* *****************************************************************************
*
* Copyright (c) 2018-2020 Gavin D. Howard and contributors.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* *****************************************************************************
*
* The second bc math library.
*
*/
define r(x,p){
auto t,n
if(x==0)return x
p=abs(p)$
n=(x<0)
x=abs(x)
t=x@p
if(p<scale(x)&&x-t>=5>>p+1)t+=1>>p
if(n)t=-t
return t
}
define ceil(x,p){
auto t,n
if(x==0)return x
p=abs(p)$
n=(x<0)
x=abs(x)
t=(x+(9>>p+1))@p
if(n)t=-t
return t
}
define f(n){
auto r
n=abs(n)$
for(r=1;n>1;--n)r*=n
return r
}
define perm(n,k){
auto f,g,s
if(k>n)return 0
n=abs(n)$
k=abs(k)$
f=f(n)
g=f(n-k)
s=scale
scale=0
f/=g
scale=s
return f
}
define comb(n,r){
auto s,f,g,h
if(r>n)return 0
n=abs(n)$
r=abs(r)$
s=scale
scale=0
f=f(n)
h=f(r)
g=f(n-r)
f/=h*g
scale=s
return f
}
define log(x,b){
auto p,s
s=scale
if(scale<K)scale=K
if(scale(x)>scale)scale=scale(x)
scale*=2
p=l(x)/l(b)
scale=s
return p
}
define l2(x){return log(x,2)}
define l10(x){return log(x,A)}
define root(x,n){
auto s,m,r,q,p
if(n<0)sqrt(n)
n=abs(n)$
if(n==0)x/n
if(n==1)return x
if(n==2)return sqrt(x)
s=scale
scale=0
if(x<0&&n%2==0)sqrt(x)
scale=s+2
m=(x<0)
x=abs(x)
p=n-1
q=10^ceil((length(x$)/n)$,0)
while(r!=q){
r=q
q=(p*r+x/r^p)/n
}
if(m)r=-r
scale=s
return r@s
}
define cbrt(x){return root(x,3)}
define pi(s){
auto t,v
if(s==0)return 3
s=abs(s)$
t=scale
scale=s+1
v=4*a(1)
scale=t
return v@s
}
define t(x){
auto s,c,l
l=scale
scale+=2
s=s(x)
c=c(x)
scale=l
return s/c
}
define a2(y,x){
auto a,p
if(!x&&!y)y/x
if(x<=0){
p=pi(scale+2)
if(y<0)p=-p
}
if(x==0)a=p/2
else{
scale+=2
a=a(y/x)+p
scale-=2
}
return a@scale
}
define sin(x){return s(x)}
define cos(x){return c(x)}
define atan(x){return a(x)}
define tan(x){return t(x)}
define atan2(y,x){return a2(y,x)}
define r2d(x){
auto r,i,s
s=scale
scale+=5
i=ibase
ibase=A
r=x*180/pi(scale)
ibase=i
scale=s
return r@s
}
define d2r(x){
auto r,i,s
s=scale
scale+=5
i=ibase
ibase=A
r=x*pi(scale)/180
ibase=i
scale=s
return r@s
}
define void output(x,b){
auto c
c=obase
obase=b
x
obase=c
}
define void hex(x){output(x,G)}
define void binary(x){output(x,2)}
define ubytes(x){
auto p,b,i
b=ibase
ibase=A
x=abs(x)$
i=2^8
for(p=1;i-1<x;p*=2){i*=i}
ibase=b
return p
}
define sbytes(x){
auto p,b,n,z
z=(x<0)
x=abs(x)
x=x$
n=ubytes(x)
b=ibase
ibase=A
p=2^(n*8-1)
if(x>p||(!z&&x==p))n*=2
ibase=b
return n
}
define void output_byte(x,i){
auto j,p,y,b
j=ibase
ibase=A
s=scale
scale=0
x=abs(x)$
b=x/(2^(i*8))
b%=2^8
y=log(256,obase)$
if(b>1)p=log(b,obase)$+1
else p=b
for(i=y-p;i>0;--i)print 0
if(b)print b
scale=s
ibase=j
}
define void output_uint(x,n){
auto i,b
b=ibase
ibase=A
for(i=n-1;i>=0;--i){
output_byte(x,i)
if(i)print" "
else print"\n"
}
ibase=b
}
define void hex_uint(x,n){
auto o
o=obase
obase=G
output_uint(x,n)
obase=o
}
define void binary_uint(x,n){
auto o
o=obase
obase=2
output_uint(x,n)
obase=o
}
define void uintn(x,n){
if(scale(x)){
print"Error: ",x," is not an integer.\n"
return
}
if(x<0){
print"Error: ",x," is negative.\n"
return
}
if(x>=2^(n*8)){
print"Error: ",x," cannot fit into ",n," unsigned byte(s).\n"
return
}
binary_uint(x,n)
hex_uint(x,n)
}
define void intn(x,n){
auto t
if(scale(x)){
print"Error: ",x," is not an integer.\n"
return
}
t=2^(n*8-1)
if(abs(x)>=t&&(x>0||x!=-t)){
print "Error: ",x," cannot fit into ",n," signed byte(s).\n"
return
}
if(x<0)x=2^(n*8)-(-x)
binary_uint(x,n)
hex_uint(x,n)
}
define void uint8(x){uintn(x,1)}
define void int8(x){intn(x,1)}
define void uint16(x){uintn(x,2)}
define void int16(x){intn(x,2)}
define void uint32(x){uintn(x,4)}
define void int32(x){intn(x,4)}
define void uint64(x){uintn(x,8)}
define void int64(x){intn(x,8)}
define void uint(x){uintn(x,ubytes(x))}
define void int(x){intn(x,sbytes(x))}