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
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) |
|
}
|
|
|