превеждащ цикъл от Fortran към MATLAB

В момента превеждам ръчно код от Fortran на MATLAB и не съм сигурен как да преведа част от него. (Целият код всъщност е подпрограма от 2000 реда.) Кодът е по-долу.

C  Has series crossed neckline?
120        neckext=x(trough(peaknum-1))+
 *              dydx*real((t-trough(peaknum-1)))


        if(x(t).lt.neckext) goto 130
C      NO.  Here if series has not crossed neckline, nor new trough found
C           Check to see if new trough has been found.
        t=t+1
        if(t.ge.lastobs) goto 900
        if(x(t).lt.min) then
              min=x(t)
              mindate=t
              end if
        troughid=min*(1.0+cutoff)
        if(x(t).ge.troughid) goto 150
        goto 120

C      YES. Here if series crossed neckline before new trough found
130         dblcount=0
      if(poscount.ge.1) then
          DO 132 i=1,poscount
           if((enterdt(i)-2.le.t).and.(t.le.enterdt(i)+2)) then
           dblcount=dblcount+1
           end if    
132          continue
           if(dblcount.ge.1) then
C                write(30,2583) t,Cutnum
2583            format('DoubleCounting episode occurred at ',I5,
 *             ' with Cutoff = ',F3.1)
            goto 150
          end if
       end if

Проблемът ми е с тази част от кода:

        if(x(t).ge.troughid) goto 150
        goto 120

Когато превеждах тази част в MATLAB, пишех нещо като:

if x(t,:)>=troughid
    t=marker;
    minimum=x(t,:);
end

Но не знам какво да правя с етикета 120. Като го превеждам, пак ли пиша тази част? Защото доколкото разбирам, когато се върна на 120, кодът ще се изпълнява отново. Благодаря!

РЕДАКТИРАНЕ: Като отговор на въпроса на Крис какво правят етикетите 150 и 900, ще ги публикувам тук.

150        t=marker
           min=x(t)

И това е за етикета 900.

C  Last observation found.  This iteration finished.
900        continue

person Julio Galvez    schedule 04.09.2012    source източник
comment
И казват, че goto правят кода труден за следване!   -  person High Performance Mark    schedule 04.09.2012
comment
@HighPerformanceMark Вярно е. Толкова вярно. От друга страна, колко други езици имат огромни количества закален в битки цифров код? Предполагам, че това е знак на почит както към пълната простота на F66/F77, така и към четиридесет години студенти, проливащи кръв, достойнство и сълзи.   -  person sfstewman    schedule 04.09.2012
comment
Ако не сте го направили, струва си да разработите някои изчерпателни (и в идеалния случай автоматизирани) тестове, за да сте сигурни, че вашият порт действително възпроизвежда оригиналното поведение. Този вид работа е досадна и податлива на грешки. Един добър тестов пакет може да ви спести огромно количество време и разочарование, особено ако този код е важен за някаква по-голяма и по-сложна цел.   -  person sfstewman    schedule 04.09.2012
comment
Опитайте онлайн конвертора от F77 към F90 на polyhedron.com/plusfortonline.php за някои кодови фрагменти. Ще ви помогне да разгадаете goto твърденията.   -  person John Alexiou    schedule 04.09.2012
comment
Здравей @ja72, всъщност мислех да разделя кода на части и да го конвертирам във F90. Но работата е там, че кодът е много сложен и може да е трудно да се раздели на части. (Тъй като видях, че plusfort ви позволява да го правите само 100 реда наведнъж.)   -  person Julio Galvez    schedule 06.09.2012
comment
@sfstewman Какво имаш предвид с тестване? :)   -  person Julio Galvez    schedule 06.09.2012


Отговори (3)


Както вече трябва да е ясно, Matlab не включва никакъв вариант на команда "goto". Основният набор от команди на Matlab изглежда е проектиран около философията на "структурираното програмиране". (Което, ако си спомням правилно моята древна история на CS, беше големият дебат преди обектно-ориентираното програмиране.) Уикипедия има приличен обсъждане на структурното програмиране.

В мрачните дни преди структурираното програмиране хората се вълнуваха много от блок-схемите, тъй като това беше един от най-лесните начини за визуализиране и разбиране на част от код, използвайки много goto изрази (сега обикновено наричани спагети код).

Подозирам, че ще трябва да съставите блок-схема на цялата подпрограма и след това да решите кои конструкции на контролен поток могат да се използват най-добре за пресъздаване на вашия код. Ако това е сравнително проста диаграма, тогава трябва да можете да пресъздадете целия код с if оператори или case оператори, въпреки че поредица от малки помощни функции може да бъде по-елегантна. Ако има по-сложна структура, тогава може да е необходима малко повече креативност за превод.

person Pursuit    schedule 04.09.2012
comment
Благодаря! Написах блок-схема на цялата подпрограма и открих, че структурата е сложна; бримките изглежда вървят напред-назад една с друга. Не съм сигурен обаче как да ги кодирам. Както и да е, мога ли да ви попитам каква е разликата между if и case изявления? Интуитивно те изглеждат еднакви. - person Julio Galvez; 07.09.2012
comment
В Matlab оператор case е най-вече стенограма за поредица от оператори if ... elseif ... elseif ... else ... end. Като цяло по-лесно за разбиране. - person Pursuit; 07.09.2012
comment
Благодаря! Сега, в случай, че някои цикли може да се припокриват един с друг (тъй като това беше случаят с резултата от моята блок-схема), какви трикове мога да използвам, за да разплитам припокриването? Кога обикновено използвам break, return и continue? - person Julio Galvez; 07.09.2012
comment
Лично аз никога не използвам break или continue. Притеснявам се, че ще изляза на неочаквано ниво. return е за ранно излизане от функция, която не изглежда да използвате. Що се отнася до разплитането на блок-схема на спагети, мисля, че това е отвъд това, което разумно мога да направя. Някакво търсене в гугъл за блок-схема на структурирано програмиране дава няколко инструкции по темата, напр. hancock.k12.ky.us/hchs/cisco/ програмиране/pdf/. - person Pursuit; 07.09.2012
comment
Благодаря ви много за това; беше много по-ясно от ръководството, което намерих онлайн! - person Julio Galvez; 08.09.2012

Можете да обвиете първата половина от кода си до след goto 120 в while цикъл. След това можете да излезете от този цикъл while, когато условието if(x(t) .lt. neckext) е изпълнено. Например, логиката може да изглежда по следния начин. Имайте предвид, че не съм се опитвал да конвертирам всичко в MATLAB (това е вашата работа!!), но се надявам, че ще ви помогне да започнете.

% Has series crossed neckline?
neckext = x(trough(peaknum-1)) + dydx*real((t-trough(peaknum-1)));

if (x(t) < neckext)
    % Code below `goto 120` here...

else
    while (x(t) >= neckext)
        % Code above `goto 120` here...
    end 
end

% `goto 150` code here?

Не съм съвсем сигурен дали горното е това, от което се нуждаете, тъй като без пълния код нямам представа какво трябва да правят goto 150 и goto 900 с програмния поток (освен че го правят трудно за следване).

person Chris    schedule 04.09.2012
comment
Здравей @Chris, това всъщност е подпрограма от 2000 реда, която превеждам. Както и да е, ще публикувам какво правят goto 150 и goto 900 с потока на програмата. 150 t=маркер min=x(t) 900 продължете - person Julio Galvez; 04.09.2012

Почти всички разрешени goto във Fortran могат да бъдат преведени в MATLAB чрез използване на while/break/continue конструкции. Написах (неиздадена) програма за автоматично премахване на goto от кода на Fortran, след което използвам моята програма, f2matlab, за да преведа кода в MATLAB/Octave.

person Ben Barrowes    schedule 04.09.2012
comment
Редактирах въпроса, за да премахна вашия имейл адрес. Вижте този мета въпрос и свързани въпроси за повече информация защо. На този сайт се предпочита отговорите да са самостоятелни, а не във формата „изпратете ми имейл и мога да го поправя вместо вас“. В бъдеще можете да споменете кода си, но опитайте да поставите връзка към (да речем към github), така че всеки, който чете този отговор, да може да следва решението, дори ако напуснете този сайт или промените имейл адреса. - person Chris; 05.09.2012