123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- #include "polygon.hpp"
- Coefficients Polygon::coefficients;
- Polygon::Polygon(string str){
- Vertex v(0,0);
- indices.insert({v,0});
- vertices.push_back(v);
- length=0;
- size_t i=0;
- size_t l=str.size();
- if(l==0) return;
- char c=str[0];
- while(i<l){
- char s=c;
- int64 xs=0;
- int64 ys=0;
- switch(s){
- case 'l':
- xs=-1;
- break;
- case 'r':
- xs=1;
- break;
- case 'u':
- ys=1;
- break;
- case 'd':
- ys=-1;
- break;
- default:
- Error::string_error("Invalid step",str,i);
- break;
- };
- size_t j=++i;
- size_t n=0;
- if(i<l){
- c=str[i];
- while(i<l and '0'<=c and c<='9'){
- n=n*10+c-'0';
- if(++i==l) break;
- c=str[i];
- }
- }
- if(i==j) n=1; // No digits after step s
- for(size_t k=0;k<n;++k){
- v.x+=xs;
- v.y+=ys;
- ++length;
- auto res=indices.insert({v,length});
- if(!res.second and (i<l or k<n-1)) Error::string_error("Not self avoiding",str,j-1);
- if(res.second) vertices.push_back(v);
- }
- }
- if(v.x!=0 or v.y!=0) Error::error("Not a polygon");
- compute_B();
- compute_fp();
- }
- void Polygon::add_vertex(const int32& x,const int32& y){
- Vertex w(x,y);
- if(indices.find(w)==indices.end()){
- indices.insert({w,vertices.size()});
- vertices.push_back(w);
- }
- }
- void
- Polygon::add_neighbours(const int32& x,const int32& y){
- add_vertex(x,y+1);
- add_vertex(x,y-1);
- add_vertex(x-1,y);
- add_vertex(x+1,y);
- }
- void
- Polygon::compute_B(){
- for(size_t i=0;i<length;++i){
- int32 x=vertices[i].x;
- int32 y=vertices[i].y;
- add_neighbours(x,y);
- }
- B.init(vertices.size());
- B.clear();
- for(size_t i=0;i<length;++i){
- Vertex& v=vertices[i];
- size_t r=indices[Vertex(v.x+1,v.y)];
- size_t l=indices[Vertex(v.x-1,v.y)];
- size_t u=indices[Vertex(v.x,v.y+1)];
- size_t d=indices[Vertex(v.x,v.y-1)];
- B.set(i,r);
- B.set(r,i);
- B.set(i,l);
- B.set(l,i);
- B.set(i,u);
- B.set(u,i);
- B.set(i,d);
- B.set(d,i);
- }
- }
- void
- Polygon::compute_C(Matrix& C){
- C.init(vertices.size());
- size_t n=vertices.size();
- for(size_t i=0;i<n;++i){
- for(size_t j=0;j<n;++j){
- Vertex& vi=vertices[i];
- Vertex& vj=vertices[j];
- double dx=abs(vi.x-vj.x);
- double dy=abs(vi.y-vj.y);
- C.set(i,j,coefficients.get(dx,dy));
- }
- }
- }
- void
- Polygon::compute_M(Matrix& M,const Matrix& C){
- //M=[I+1/4*C*B|1]=[I+1/4*C*tB|1]
- size_t n=vertices.size();
- mpfr_t temp;
- mpfr_init2(temp,prec);
- M.init(n,n+1);
- M.clear();
- for(size_t i=0;i<n;++i){
- for(size_t j=0;j<n;++j){
- mpfr_set_zero(temp,0);
- for(size_t k=0;k<n;++k){
- if(B.get(k,j)!=0){
- mpfr_add(temp,temp,C.get(i,k),MPFR_RNDN);
- }
- }
- mpfr_div_ui(temp,temp,4,MPFR_RNDN);
- M.set(i,j,temp);
- }
- mpfr_add_ui(M.get(i,i),M.get(i,i),1,MPFR_RNDN);
- mpfr_set_ui(M.get(i,n),1,MPFR_RNDN);
- }
- }
- void
- Polygon::compute_fp(){
- Matrix C,M;
- compute_C(C);
- compute_M(M,C);
- size_t n=vertices.size();
- mpfr_t det,temp;
- mpfr_init2(det,prec);
- mpfr_init2(fp,prec);
- mpfr_init2(temp,prec);
- mpfr_set_zero(fp,0);
- M.Gauss(det);
- mpfr_printf("Det = %Re\n",det);
- for(size_t i=0;i<n;++i){
- mpfr_set_ui(temp,B.get_diag_square_sym(i),MPFR_RNDN);
- mpfr_fma(fp,temp,M.get(i,n),fp,MPFR_RNDN);
- }
- mpfr_mul(fp,fp,det,MPFR_RNDN);
- mpfr_div_ui(fp,fp,4,MPFR_RNDN);
- mpfr_clear(det);
- mpfr_clear(temp);
- }
|