1
0
Fork 0
Libraries for bc and dc.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

179 lines
4.6 KiB

#!/usr/local/bin/bc -l funcs.bc collatz.bc
### Collatz_Continuous.BC - Attempt to extend the Collatz iteration to
### all real numbers
# For functions with the k parameter:
# always return x/2 for even x
# for k=0, returns 3x+1 for odd x [Standard Collatz]
# for k=1, returns (3x+1)/2 for odd x [First Simplification]
# for k=other, returns (3x+1)/(k+1) for odd x [Side effect]
# i.e. for integers, return the same as for collatz_next() in
# collatz.bc
# for x=non integer, interpolates between odd and even values
# cosine interpolation
define collatz_cos_(x,k) { return x/2+(1-cos(pi()*x))/2*((3*x+1)/pow(2,k)-x/2) }
define collatz_cos(x) {
if(!check_collatz_mode_())return 0
return collatz_cos_(x,collatz_mode_-1)
}
# as above but performs true linear interpolation
define collatz_lin_(x,k) {
auto l,p,a,b
l=floor(x);p=l-2*floor(l/2)
if(l==x)if(p){
return (3*x+1)/pow(2,k)
} else {
return x/2
}
if(p){
a=(3*l+1)/pow(2,k);b=(l+1)/2
} else {
a=l/2;b=(3*l+4)/pow(2,k)
}
return a+(x-l)*(b-a)
}
define collatz_lin(x) {
if(!check_collatz_mode_())return 0
return collatz_lin_(x,collatz_mode_-1)
}
# as above but performs pseudo-linear interpolation
define collatz_linb_(x,k) { return x/2+(1-abs(1-x+2*floor(x/2)))*((3*x+1)/pow(2,k)-x/2) }
define collatz_linb(x) {
if(!check_collatz_mode_())return 0
return collatz_linb_(x,collatz_mode_-1)
}
# as above but performs piecewise cosine interpolation
define collatz_pcos_(x,k) {
auto l,p,a,b
l=floor(x);p=l-2*floor(l/2)
if(l==x)if(p){
return (3*x+1)/pow(2,k)
} else {
return x/2
}
x=(1-cos(pi()*x))/2
if(p){
a=(3*l+1)/pow(2,k);b=(l+1)/2
x=1-x
} else {
a=l/2;b=(3*l+4)/pow(2,k)
}
return a+x*(b-a)
}
define collatz_pcos(x) {
if(!check_collatz_mode_())return 0
return collatz_pcos_(x,collatz_mode_-1)
}
## Inverse functions
# Workhorse for invlin and arcpcos.
define collatz_piecewise__(y,k) {
# Assumes a,b,ca,cb,t,s,x are POSIXly defined elsewhere
a=(pow(2,k)*y-1)/3;b=y+y
if((y>0)==(a>b)){t=a;a=b;b=t}
s=1;if(a<0)s=-1
t=s*floor(s*b);a=s*ceil(s*a)
ca=collatz_lin_(a,k);cb=collatz_lin_(t,k)
x=0
if(y==ca)return x=a
if(y==cb)return x=b
cb=collatz_lin_(b=a+s,k)
while(b*s<=t*s){
if(y==cb){x=b;break}
if((ca<y&&y<cb)||(cb<y&&y<ca)){x=1;break}
ca=cb;a=b;b+=s;cb=collatz_lin_(b,k)
}
if(y<0){t=a;a=b;b=t; t=ca;ca=cb;cb=t}
}
# Attempt to find a solution to y=collatz_lin_(x,k) for x
# . Where y is integer, finds a valid Collatz inverse
# Otherwise finds solution with smallest magnitude
define collatz_invlin_(y,k) {
auto a,b,ca,cb,t,s,x
if(y==0)return 0
if(y==-1||y==1)return y*2^k
.=collatz_piecewise__(y,k)
if(cb==ca)return 2*y/1
if(x==1)x=(y-ca)/(cb-ca)+a
return x
}
define collatz_invlin(y) {
if(!check_collatz_mode_())return 0
return collatz_invlin_(y,collatz_mode_-1)
}
# Attempt to find a solution to y=collatz_pcos_(x,k) for x
# . Where y is integer, finds a valid Collatz inverse
# Otherwise finds solution with smallest magnitude
define collatz_arcpcos_(y,k) {
auto a,b,ca,cb,t,s,x
if(y==floor(y))return collatz_invlin_(y,k)
.=collatz_piecewise__(y,k)
if(x!=1)return x
x=(y-ca)/(cb-ca);x=1-x-x
x=arccos(x)/pi()+a
return x
}
define collatz_arcpcos(y) {
if(!check_collatz_mode_())return 0
return collatz_arcpcos_(y,collatz_mode_-1)
}
# TO DO: improve the following further
# Attempt to find a solution to y=collatz_cos_(x,k) for x
define collatz_arccos_(y,k) {
auto os,x,t,d,nd,v,eps;
if(y==floor(y))return collatz_invlin_(y,k)
os=scale;eps=A^-os;scale+=length(y)-scale(y)+1
x=collatz_arcpcos_(y,k) # got to start somewhere
if(x==floor(x))x-=eps
v=1/4;d=1
while(d>eps&&v){
t=collatz_cos_(x-v,k)
nd=abs(t-y)
if(nd>d){
t=collatz_cos_(x+v,k)
nd=abs(t-y)
if(nd>d){nd=d}else{x+=v}
}else{x-=v}
d=nd;v/=2
}
scale=os;return x/1
}
define collatz_arccos(y) {
if(!check_collatz_mode_())return 0
return collatz_arccos_(y,collatz_mode_-1)
}
# Attempt to find a solution to y=collatz_linb_(x,k) for x
define collatz_invlinb_(y,k) {
auto os,x,t,d,nd,v,eps;
if(y==floor(y))return collatz_invlin_(y,k)
os=scale;eps=A^-os;scale+=length(y)-scale(y)+1
x=collatz_invlin_(y,k) # got to start somewhere
if(x==floor(x))x-=eps
v=1/4;d=1
while(d>eps&&v){
t=collatz_linb_(x-v,k)
nd=abs(t-y)
if(nd>d){
t=collatz_linb_(x+v,k)
nd=abs(t-y)
if(nd>d){nd=d}else{x+=v}
}else{x-=v}
d=nd;v/=2
}
scale=os;return x/1
}
define collatz_invlinb(y) {
if(!check_collatz_mode_())return 0
return collatz_invlinb_(y,collatz_mode_-1)
}