c# - Refactor multiple goto statements from the loop body -


i struggling replicate following fortran 77 subroutine c# method. main problem trying rid of fortran's goto statements.

the fortran c# conversion looks fine, still goto statements remained. there way of them can replaced conditionals or other ways? thank you.

here fortran subroutine:

c program temp       subroutine temp (acl,adu,aeff,c,cair,cb,cbare,       + cclo,count1,csum,di,ed,emcl,emsk,enbal,       + enbal2,ere,erel,esw,eswdif,eswphy,eswpot,       + evap,facl,fcl,fec,feff,food,h,hc,he,ht,htcl,icl,j,       + mbody,p,po,r1,r2,rbare,rcl,       + rclo,rclo2,rdcl,rdsk,rob,rsum,sex,sigm,sw,swf,swm,       + ta,tbody,tcl,tcore,tmrt,tsk,v,vb,vb1,vb2,       + vpa,vpts,wetsk,wd,wr,ws,wsum,xx)        real acl,adu,aeff,c(0:10),cair,cb,cbare,       + cclo,csum,di,ed,emcl,emsk,enbal,       + enbal2,ere,erel,esw,eswdif,eswphy,eswpot,       + evap,facl,fcl,fec,feff,food,h,hc,he,ht,htcl,icl,       + mbody,p,po,r1,r2,rbare,rcl,       + rclo,rclo2,rdcl,rdsk,rob,rsum,sigm,sw,swf,swm,       + ta,tbody,tcl,tcore(1:7),tmrt,tsk,v,vb,vb1,vb2,       + vpa,vpts,wetsk,wd,wr,ws,wsum,xx        integer count1,count3,j,sex        wetsk = 0.        adu = 0.203 * mbody ** 0.425 * ht ** 0.725        hc = 2.67 + ( 6.5 * v ** 0.67)        hc = hc * (p /po) ** 0.55        feff = 0.725  c        facl = (- 2.36 + 173.51 * icl - 100.76 * icl * icl + 19.28       + * (icl ** 3.)) / 100.  c        if (facl .gt.1.) facl = 1.        rcl = (icl/6.45)/facl        if (icl.ge.2.) y = 1.        if ((icl .gt. 0.6) .and. (icl .lt. 2.)) y = (ht - 0.2) / ht        if ((icl .le. 0.6) .and. (icl .gt. 0.3)) y = 0.5        if ((icl .le. 0.3) .and. (icl .gt. 0.)) y = 0.1        r2 = adu * (fcl - 1. + facl) / (2. * 3.14 * ht * y)        r1 = facl * adu / (2. * 3.14 * ht * y)        di = r2 - r1  c temperature       90 j = 1,7        tsk = 34.        count1 = 0        tcl = (ta + tmrt + tsk) / 3.        count3 = 1        enbal2 = 0.     20 acl = adu * facl + adu * (fcl - 1.)        rclo2 = emcl*sigm *((tcl+273.2)** 4.-(tmrt+273.2)** 4.)*feff        htcl = 6.28 * ht * y * di / (rcl * alog(r2/r1) * acl)        tsk = 1. / htcl * (hc * (tcl - ta) + rclo2) + tcl  c radiation        aeff = adu * feff        rbare = aeff * (1.-facl) * emsk * sigm *       + ((tmrt + 273.2) ** 4. - (tsk + 273.2) ** 4.)        rclo = feff * acl * emcl * sigm *       + ((tmrt + 273.2) ** 4. - (tcl + 273.2) ** 4.)        rsum = rbare + rclo  c convect       cbare = hc * (ta - tsk) * adu * (1. - facl)        cclo = hc * (ta - tcl ) * acl        csum = cbare + cclo  c core       c(0) = h + ere        c(1) = adu * rob * cb        c(2) = 18. - 0.5 * tsk        c(3) = 5.28 * adu * c(2)        c(4) = 0.0208 * c(1)        c(5) = 0.76075 * c(1)        c(6) = c(3) - c(5) - tsk * c(4)        c(7) = - c(0) * c(2) - tsk * c(3) + tsk * c(5)        c(8) = c(6) * c(6) - 4. * c(4) * c(7)        c(9) = 5.28 * adu - c(5) - c(4) * tsk        c(10) = c(9) * c(9) - 4. * c(4) *       + (c(5) * tsk - c(0) - 5.28 * adu * tsk)  c        if (tsk.eq.36.) tsk=36.01        tcore(7) = c(0) / (5.28 * adu + c(1) * 6.3 / 3600.) + tsk        tcore(3) = c(0) / (5.28 * adu + (c(1) * 6.3 / 3600.) /       + (1 + 0.5 * (34. -tsk))) + tsk        if (c(10) .lt. 0.) goto 22        tcore(6) = (- c(9) - c(10) ** 0.5) / (2. * c(4))        tcore(1) = (- c(9) + c(10) ** 0.5) / (2. * c(4))     22 if (c(8) .lt. 0.) goto 24        tcore(2) = (- c(6) + abs(c(8)) ** 0.5) / (2. * c(4))        tcore(5) = (- c(6) - abs(c(8)) ** 0.5) / (2. * c(4))     24 tcore(4) = c(0) / (5.28 * adu + c(1) * 1. / 40.) + tsk  c transparence       tbody = 0.1 * tsk + 0.9 * tcore (j)        swm = 304.94 * (tbody - 36.6) * adu / 3600000.        vpts = 6.11 * 10. ** (7.45 * tsk / (235. + tsk))        if (tbody .le. 36.6) swm = 0.        swf = 0.7 * swm        if(sex .eq. 1) sw = swm        if(sex .eq. 2) sw = swf        eswphy = - sw * evap        = 0.633 * hc / (p * cair)        fec = 1. / (1. + 0.92 * hc * rcl)        eswpot = * (vpa - vpts) * adu * evap * fec        wetsk = eswphy / eswpot        if (wetsk .gt. 1.) wetsk = 1.        eswdif = eswphy - eswpot        if (eswdif .le. 0.) esw = eswpot        if (eswdif .gt. 0.) esw = eswphy        if (esw .gt. 0.) esw = 0.  c difference       rdsk = 0.79 * 10. ** 7.        rdcl = 0.        ed = evap / (rdsk + rdcl) * adu * (1 - wetsk) * (vpa-vpts)  c vb        vb1 = 34. - tsk        vb2 = tcore(j) - 36.6        if (vb2 .lt.0.) vb2 = 0.        if (vb1 .lt.0.) vb1 = 0.        vb = (6.3 + 75. * (vb2)) / (1. + 0.5 * vb1)  c balance       enbal = h + ed + ere + esw + csum + rsum + food  c cover       if (count1 .eq.0) xx = 1.        if (count1 .eq.1) xx = 0.1        if (count1 .eq.2) xx = 0.01        if (count1 .eq.3) xx = 0.001        if (enbal .gt. 0.) tcl = tcl + xx        if (enbal .lt. 0.) tcl = tcl - xx        if ((enbal .le. 0.) .and. (enbal2 .gt. 0.)) goto 30        if ((enbal .ge. 0.) .and. (enbal2 .lt. 0.)) goto 30        enbal2 = enbal        count3 = count3 + 1  c        if (count3 .gt. 200) goto 30        goto 20     30 if ((count1 .eq.0.).or.(count1.eq.1.).or.(count1.eq.2.))           count1 = count1 + 1.           enbal2 = 0.           goto 20        end if  c        if (count1 .eq. 3.)  c           if ((j .eq. 2) .or. (j .eq. 5)) goto 40           if ((j .eq. 6) .or. (j .eq. 1)) goto 50           if (j .eq. 3) goto 60           if (j .eq. 7) goto 70           if (j .eq. 4) goto 80        end if     40 if (c(8) .lt. 0.) goto 90        if ((tcore(j) .ge. 36.6) .and. (tsk .le. 34.050)) goto 80        goto 90     50 if (c(10) .lt. 0. ) goto 90        if ((tcore(j) .ge. 36.6) .and. (tsk .gt. 33.850)) goto 80        goto 90     60 if ((tcore(j) .lt. 36.6) .and. (tsk .le. 34.000)) goto 80        goto 90     70 if ((tcore(j) .lt. 36.6) .and. (tsk .gt. 34.000)) goto 80        goto 90     80 if ((j .ne. 4) .and. (vb .ge. 91.)) goto 90        if ((j. eq. 4) .and. (vb .lt. 89.)) goto 90        if (vb .gt. 90.) vb = 90.  c losses       ws = sw * 3600. * 1000.        if (ws .gt.2000.) ws = 2000.        wd = ed / evap * 3600. * (-1000.)        wr = erel / evap * 3600. * (-1000.)        wsum = ws + wr + wd        goto 100     90 continue    100 return        end  

and here c# attempt replicate upper fortran subroutine:

using system;  public static class globalmembers_temp {  //c program temp // --------------------------------------------     public static void temp(acl, adu, aeff, c, cair, cb, cbare, cclo, count1, csum, di, ed , emcl , emsk , enbal , enbal2 , ere , erel , esw , eswdif , eswphy , eswpot , evap , facl , fcl , fec , feff , food , h , hc , , ht , htcl , icl , j , mbody , p , po , r1 , r2 , rbare , rcl , rclo , rclo2 , rdcl , rdsk , rob , rsum , sex , sigm , sw , swf , swm , ta , tbody , tcl, tcore , tmrt , tsk , v , vb , vb1 , vb2 , vpa , vpts , wetsk , wd , wr , ws , wsum , xx)     {         float acl;         float adu;         float aeff;         float[] c = new float[11];  // ???         float cair;         float cb;         float cbare;         float cclo;         float csum;         float di;         float ed;         float emcl;         float emsk;         float enbal;         float enbal2;         float ere;         float erel;         float esw;         float eswdif;         float eswphy;         float eswpot;         float evap;         float facl;         float fcl;         float fec;         float feff;         float food;         float h;         float hc;         float he;         float ht;         float htcl;         float icl;         float mbody;         float p;         float po;         float r1;         float r2;         float rbare;         float rcl;         float rclo;         float rclo2;         float rdcl;         float rdsk;         float rob;         float rsum;         float sigm;         float sw;         float swf;         float swm;         float ta;         float tbody;         float tcl;         float[] tcore = new float[7];   // ???         float tmrt;         float tsk;         float v;         float vb;         float vb1;         float vb2;         float vpa;         float vpts;         float wetsk;         float wd;         float wr;         float ws;         float wsum;         float xx;         int count1;         int count3;         int j;         int sex;         wetsk = 0.0;         adu = 0.203 * mbody * *0.425 * ht * *0.725;         hc = 2.67 + (6.5 * v * *0.67);         hc = hc * (p / po) * *0.55;         feff = 0.725;         //c rcl = icl / 6.45         facl = (-2.36 + 173.51 * icl - 100.76 * icl * icl + 19.28 * (icl * *3.0)) / 100.0;         //c         if (facl > 1.0)         {             facl = 1.0;         }         rcl = (icl / 6.45) / facl;         if (icl >= 2.0)         {             y = 1.0;         }         if ((icl > 0.6)) && ((icl < 2.0))          {             y = (ht - 0.2) / ht;         }         if ((icl <= 0.6)) && ((icl > 0.3))          {             y = 0.5;         }         if ((icl <= 0.3)) && ((icl > 0.0))          {             y = 0.1;         }         r2 = adu * (fcl - 1.0 + facl) / (2.0 * 3.14 * ht * y);         r1 = facl * adu / (2.0 * 3.14 * ht * y);         di = r2 - r1;         //c temperature         (90 j = 1, 7)         {             tsk = 34.0;             count1 = 0;             tcl = (ta + tmrt + tsk) / 3.0;             count3 = 1;             enbal2 = 0.0;     g20:             acl = adu * facl + adu * (fcl - 1.0);             rclo2 = emcl * sigm * ((tcl + 273.2) * *4.0 - (tmrt + 273.2) * *4.0) * feff;             htcl = 6.28 * ht * y * di / (rcl * alog(r2 / r1) * acl);             tsk = 1.0 / htcl * (hc * (tcl - ta) + rclo2) + tcl;             //c radiation             aeff = adu * feff;             rbare = aeff * (1.0 - facl) * emsk * sigm * ((tmrt + 273.2) * *4.0 - (tsk + 273.2) * *4.0);             rclo = feff * acl * emcl * sigm * ((tmrt + 273.2) * *4.0 - (tcl + 273.2) * *4.0);             rsum = rbare + rclo;             //c convect             cbare = hc * (ta - tsk) * adu * (1.0 - facl);             cclo = hc * (ta - tcl) * acl;             csum = cbare + cclo;             //c core             c[0] = h + ere;             c[1] = adu * rob * cb;             c[2] = 18.0 - 0.5 * tsk;             c[3] = 5.28 * adu * c[2];             c[4] = 0.0208 * c[1];             c[5] = 0.76075 * c[1];             c[6] = c[3] - c[5] - tsk * c[4];             c[7] = -c[0] * c[2] - tsk * c[3] + tsk * c[5];             c[8] = c[6] * c[6] - 4.0 * c[4] * c[7];             c[9] = 5.28 * adu - c[5] - c[4] * tsk;             c[10] = c[9] * c[9] - 4.0 * c[4] * (c[5] * tsk - c[0] - 5.28 * adu * tsk);             //c             if (tsk == 36.0)             {                 tsk = 36.01;             }             tcore[7] = c[0] / (5.28 * adu + c[1] * 6.3 / 3600.0) + tsk;             tcore[3] = c[0] / (5.28 * adu + (c[1] * 6.3 / 3600.0) / (1 + 0.5 * (34.0 - tsk))) + tsk;             if (c[10] < 0.0)             {                 goto g22;             }             tcore[6] = (-c[9] - c[10] * *0.5) / (2.0 * c[4]);             tcore[1] = (-c[9] + c[10] * *0.5) / (2.0 * c[4]);     g22:             if (c[8] < 0.0)             {                 goto g24;             }             tcore[2] = (-c[6] + math.abs(c[8]) * *0.5) / (2.0 * c[4]);             tcore[5] = (-c[6] - math.abs(c[8]) * *0.5) / (2.0 * c[4]);     g24:             tcore[4] = c[0] / (5.28 * adu + c[1] * 1.0 / 40.0) + tsk;             //c transparence             tbody = 0.1 * tsk + 0.9 * tcore[j];             swm = 304.94 * (tbody - 36.6) * adu / 3600000.0;             vpts = 6.11 * 10.0 * *(7.45 * tsk / (235.0 + tsk));             if (tbody <= 36.6)             {                 swm = 0.0;             }             swf = 0.7 * swm;             if (sex == 1)             {                 sw = swm;             }             if (sex == 2)             {                 sw = swf;             }             eswphy = -sw * evap;             = 0.633 * hc / (p * cair);             fec = 1.0 / (1.0 + 0.92 * hc * rcl);             eswpot = * (vpa - vpts) * adu * evap * fec;             wetsk = eswphy / eswpot;             if (wetsk > 1.0)             {                 wetsk = 1.0;             }             eswdif = eswphy - eswpot;             if (eswdif <= 0.0)             {                 esw = eswpot;             }             if (eswdif > 0.0)             {                 esw = eswphy;             }             if (esw > 0.0)             {                 esw = 0.0;             }             //c difference             rdsk = 0.79 * 10.0 * *7.0;             rdcl = 0.0;             ed = evap / (rdsk + rdcl) * adu * (1 - wetsk) * (vpa - vpts);             //c vb             vb1 = 34.0 - tsk;             vb2 = tcore[j] - 36.6;             if (vb2 < 0.0)             {                 vb2 = 0.0;             }             if (vb1 < 0.0)             {                 vb1 = 0.0;             }             vb = (6.3 + 75.0 * (vb2)) / (1.0 + 0.5 * vb1);             //c balance             enbal = h + ed + ere + esw + csum + rsum + food;             //c cover             if (count1 == 0)             {                 xx = 1.0;             }             if (count1 == 1)             {                 xx = 0.1;             }             if (count1 == 2)             {                 xx = 0.01;             }             if (count1 == 3)             {                 xx = 0.001;             }             if (enbal > 0.0)             {                 tcl = tcl + xx;             }             if (enbal < 0.0)             {                 tcl = tcl - xx;             }             if ((enbal <= 0.0)) && ((enbal2 > 0.0))              {                 goto g30;             }             if ((enbal >= 0.0)) && ((enbal2 < 0.0))              {                 goto g30;             }             enbal2 = enbal;             count3 = count3 + 1;             //c             if (count3 > 200)             {                 goto g30;             }             goto g20;     g30:             if ((count1 == 0.0))             {                 || ((count1 == 1.0)) || ((count1 == 2.0))                 {                 count1 = count1 + 1.0;                 enbal2 = 0.0;                 goto g20;                 }             }             //c             if (count1 == 3.0)             {                 //c                 if ((j == 2))                 {                     || ((j == 5)) goto g40;                 }                 if ((j == 6))                 {                     || ((j == 1)) goto g50;                 }                 if (j == 3)                 {                     goto g60;                 }                 if (j == 7)                 {                     goto g70;                 }                 if (j == 4)                 {                     goto g80;                 }             }     g40:             if (c[8] < 0.0)             {                 goto g90;             }             if ((tcore[j] >= 36.6)) && ((tsk <= 34.050))             {                 goto g80;             }             goto g90;     g50:             if (c[10] < 0.0)             {                 goto g90;             }             if ((tcore[j] >= 36.6)) && ((tsk > 33.850))             {                 goto g80;             }             goto g90;     g60:             if ((tcore[j] < 36.6)) && ((tsk <= 34.000))             {                 goto g80;             }             goto g90;     g70:             if ((tcore[j] < 36.6)) && ((tsk > 34.000))             {                 goto g80;                }             goto g90;     g80:             if ((j != 4)) && ((vb >= 91.0))              {                 goto g90;             }             if ((j.eq.4)) && ((vb < 89.0))             {                  goto g90;             }             if (vb > 90.0)             {                 vb = 90.0;             }             //c losses             ws = sw * 3600.0 * 1000.0;             if (ws > 2000.0)             {                 ws = 2000.0;             }             wd = ed / evap * 3600.0 * (-1000.0);             wr = erel / evap * 3600.0 * (-1000.0);             wsum = ws + wr + wd;             goto g100;          }     g100:         return;     } } 

you can try turn code state machine each state represents single goto inside loop.

for need turn method class, contains parameters , variables class fields, , has 1 constructor initializes appropriate fields , (optionally) runs "method".

i won't transition method because far huge example, give following:

original not converted method:

public static void do(int32 param1, int32 param2) {                 int32 loopi;     int32 outbefore,          outafter,         outgoto1 = 0,         outgoto2 = 0;     int32[] outvalues = new int32[7];      console.writeline("method:");      console.writeline("dobeforeloop");     outbefore = param1 + param2;      boolean wasingoto2 = false;      (loopi = 0; loopi < 7; loopi++)     {         console.writeline("iteration {0}", loopi);          console.writeline("fortranloopmethodstate.loopcyclestart");         outvalues[loopi] = loopi;      goto1:         console.writeline("fortranloopmethodstate.goto1");         outgoto1 = loopi + param1;          if (wasingoto2)         {             wasingoto2 = false;             goto end;         }          wasingoto2 = true;         console.writeline("fortranloopmethodstate.goto2");         outgoto2 = loopi + param2;         goto goto1;     end:         donothing(); // don't use break, we?     }      console.writeline("doafterloop");     outafter = param1 - param2;      console.writeline(outgoto1);     console.writeline(outgoto2); } 

converted method:

public class executefortranmethod {     private enum fortranloopmethodstate     {         loopcyclestart,         goto1,         goto2,         loopcycleended     }      #region params      private int32 param1;     private int32 param2;      #endregion       #region variables      public int32 loopi;     public int32 outbefore,          outafter,         outgoto1,         outgoto2;     public int32[] outvalues = new int32[7];      #endregion       #region constructors      public executefortranmethod(int32 param1, int32 param2)     {         this.param1 = param1;         this.param2 = param2;          this.invoke();     }      #endregion       #region methods      private void invoke()     {         console.writeline("state machine class:");          this.dobeforeloop();          (this.loopi = 0; this.loopi < 7; this.loopi++)         {             console.writeline("iteration {0}", this.loopi);              var state = fortranloopmethodstate.loopcyclestart;                         {                 state = doloop(state);             }             while (state != fortranloopmethodstate.loopcycleended);         }          this.doafterloop();     }      #endregion       #region "method" body methods      private void dobeforeloop()     {         console.writeline("dobeforeloop");         this.outbefore = this.param1 + this.param2;     }      private void doafterloop()     {         console.writeline("doafterloop");         this.outafter = this.param1 - this.param2;     }      boolean wasingoto2;      private fortranloopmethodstate doloop(fortranloopmethodstate state)     {         switch (state)         {             case fortranloopmethodstate.loopcyclestart:                 {                     console.writeline("fortranloopmethodstate.loopcyclestart");                     this.outvalues[this.loopi] = this.loopi;                     return fortranloopmethodstate.goto1;                 }             case fortranloopmethodstate.goto1:                 {                     console.writeline("fortranloopmethodstate.goto1");                     this.outgoto1 = this.loopi + this.param1;                      if (this.wasingoto2)                     {                         this.wasingoto2 = false;                         return fortranloopmethodstate.loopcycleended;                     }                     return fortranloopmethodstate.goto2;                 }             case fortranloopmethodstate.goto2:                 {                     this.wasingoto2 = true;                     console.writeline("fortranloopmethodstate.goto2");                     this.outgoto2 = this.loopi + this.param2;                     return fortranloopmethodstate.goto1;                 }             default:                 throw new invalidoperationexception("the state invalid");         }     }      #endregion }    

program.cs

do(10, 20); console.writeline();  var result = new executefortranmethod(10, 20);  console.writeline(result.outgoto1); console.writeline(result.outgoto2);  console.writeline("press key"); console.readkey(true);     

as can see outputs equivalent. won't describe how can transfer actual method, because tedious (but not unreal) task no real shortcuts , of ideas clear when read tiny example.

p.s.1: while there no real shortucts (except of course of writing small tool can generate such state machine classes given code), may simplify manual job bit of regular expressions search , replace (ctrl+f). example, replacing pattern goto(\d+) case state.goto$1 { replace gotos switch case stubs.

p.s.2: if there far many switch cases(gotos) may want replace switch dictionary lookup.

p.s.3: and many have pointed it, i'd still recommend try understand original code flow , rewrite scratch.


Comments

Popular posts from this blog

c# - Better 64-bit byte array hash -

webrtc - Which ICE candidate am I using and why? -

php - Zend Framework / Skeleton-Application / Composer install issue -