# odd-even transposition sort ############################## resource main() int dim=100; getarg(1,dim); op right[dim](int) # lies: "von rechts an gegeben" op left[dim](int) # lies: "von links an gegeben" op back[dim](int) # Ruecksenden int data[dim]; op transposer(int element, int id, int dim); op tp2(int element, int id, int dim); op tp_in(int element, int id, int dim); procedure out() { int i = dim; for[i=1 to dim] { writes(data[i]," "); } write(); } int i = dim; while (i > 0) { data[i--] = dim - i; } out(); optype worker = (int, int, int) cap worker w = transposer int mode = 1 getarg(2,mode) if (mode == 3) { w = tp_in; } else { if (mode == 2) { w = tp2; } else { if (mode != 1) { write("Fehler: nicht unterstuetzter Modus"); } } } for [i=1 to dim] { fork w(data[i],i,dim); # fork transposer(data[i],i,dim); # fork tp2(data[i],i,dim); # fork tp_in(data[i],i,dim); } for [i=1 to dim] { receive back[i](data[i]); } out(); ############################################################# # # straight-forward-Version: # proc transposer(element, id, dim) { int received; int counter = 1; while(counter <= dim) { if (id % 2 == 0) { # gerade ID: # erst ungerade-Tausch, nur senden und empfangen: if (id > 1) { # (falls linker Nachbar vorhanden: also IMMER!) send right[id-1](element); receive left[id](element); } # jetzt gerade-Tausch, selbst agieren: if (id+1 <= dim) { # (falls rechter Nachbar vorhanden) receive right[id](received); if (received < element) { element :=: received; } send left[id+1](received); } } else { # ungerade ID, komplementäre Aktionen # erst ungerade-Tausch, selbst: if ( id+1 <= dim ) { # (falls rechter Nachbar vorhanden) receive right[id](received); if (received < element) { element :=: received; } send left[id+1](received); } # jetzt gerade-Tausch (passiv): if (id > 1) { # (falls linker Nachbar vorhanden send right[id-1](element); receive left[id](element); } } counter+=2 } send back[id](element); } ############################################################ # # Bestimmung von Schritt und Modus (aktiv/passiv) in einem: # proc tp2(element, id, dim) { int received; int counter = 1; while(counter <= dim ) { if (((id + counter) & 1) == 0) { # gerade ID/gerader Schritt oder umgekehrt => aktiv if (id+1 <= dim) { # (falls rechter Nachbar vorhanden) receive right[id](received); if (received < element) { element :=: received; } send left[id+1](received); } } else { # ungerade ID/gerader Schritt, oder gerade ID/ungerader Schritt => passiv if (id > 1) { # (falls linker Nachbar vorhanden send right[id-1](element); receive left[id](element); } } counter+=1; } send back[id](element); } ############################################################ # # Version mit in: # proc tp_in(element, id, dim) { int counter = 1 # Start: gerade IDs (erster Schritt passiv) senden if ((id & 1) == 0) { send right[id-1](element) # element zum Nachbarn (dort rechte Seite) geben } while (counter <= dim) { # iteriere: Tausch mit rechtem Nachbarn, evtl. Vergleich (aktiv) # letzter Prozess ueberspringt den aktiven Schritt! if (id == dim & ((id + counter) & 1) == 0) { counter++; send right[id-1](element); # (schon fuer naechsten Schritt) } else { # erster Prozess ueberspringt den inaktiven Schritt if (id == 1 & ((id + counter) & 1) == 1) { counter++; } else { in # inaktiver Prozess: gerade ID / ungerader Schritt, oder umgekehrt left[id](received) st (id > 1) & ((id + counter) & 1) == 1 -> counter++; # Element von links zurueck erhalten element = received # aktiver Prozess: ungerade/ungerade oder gerade/gerade [] right[id](received) st id < dim & ((id + counter) & 1) == 0 -> counter++; # Element von rechts erhalten, vergleichen if (element > received) { element :=: received; } send left[id+1](received); # zurueckgeben nach "links(id+1)" # naechsten Schritt vorbereiten: if (id > 1) { send right[id-1](element); } ni } }} send back[id](element) } end main