Autor |
Beitrag |
Mathematiker
      
Beiträge: 2622
Erhaltene Danke: 1448
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: So 12.08.12 18:09
Hallo,
nachdem Lelf sein superschnelles Faktorisierungsprogramm hier www.entwickler-ecke....ewtopic.php?t=109998 veröffentlichte, habe ich versucht den Quelltext unter Delphi 5 zu compilieren.
Dabei ist eine kuriose Situaton entstanden. In der UVarInt_Q tritt am Ende der 2.Prozedur sqroot
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227:
| function TVarInt.Sqroot: boolean; var qRest: TVarInt; begin qRest:= TVarInt.Create; try self.Sqroot(qRest); result:=(qRest.RLen = 0); finally qRest.Free; end; end;
function TVarInt.Sqroot(var qREM: TVarInt; mitRest: boolean=false): boolean; var xNorm, xBit, x: integer; q4, aL, xrem, w: int64; a3Ext, q4Ext: Extended; j, hQ: integer; i, n, m, q: integer; qminREM: TDig_V; aC, qDivisor, spSelf: TVarInt; procedure product(var x, y: TDig_V; f, a: integer); var i,j: integer; temp, carry: int64; begin carry:=0; j:=a + a; for i:=a to a + m -1 do begin temp:=int64(y[i])*f + carry; carry:=temp shr LOGBASE_V; x[j]:=temp and MODMASK_V; j:=j+1; end; x[j]:=carry; x[j+1]:=0; end; procedure differenz(var x, y: TDig_V; k, a: integer); var i: integer; begin for i:=k to k + a do begin if(x[i] >= y[i])then x[i]:=x[i] - y[i] else begin x[i]:=x[i] or BASE_V - y[i]; y[i+1]:=y[i+1] + 1; end; end; end; procedure add(var x: TDig_V; k, a: integer); begin x[a]:=x[a] + k; if(x[a] and BASE_V <> 0)then begin while(x[a] and BASE_V <> 0)do begin x[a]:=x[a] - BASE_V; a:=a + 1; x[a]:=x[a] + 1; end; end; end; function Compare(var i1, i2: TDig_V; a, b:integer): boolean; var i: integer; begin result:=false; for i:=a + b downto a do begin if i1[i] < i2[i] then exit else if i1[i] > i2[i] then begin result:=true; exit; end; end; end; procedure anpassenW; begin qDivisor.RNum[hQ shr 1]:=w; product(qminREM, qDivisor.RNum, w, hQ shr 1); end; begin if not(RSig)then begin result:=false; end else begin IF(self.isInt64)THEN BEGIN self.ConvertToInt64(aL); w:=trunc(Sqrt(aL/1)); xrem:=aL - int64(w*w); self.ToVar(w); qREM.ToVar(xrem); result:=(xrem = 0); END ELSE BEGIN a3Ext:=0; xNorm:=0; qDivisor:=TVarInt.Create; qREM.Assign(self); if(qREM.RLen mod 2 = 1)then begin qREM.LeftShiftbyBASE(1); xNorm:=xNorm + 15; end;
xBit:=GetHighestBitIndex30(qREM.RNum[qREM.RLen-1]); case xBit of 0..25: begin x:=(27 - xBit) shr 1; xNorm:=xNorm + x; qREM.LeftShift(x shl 1); end; 26, 27: ; else xNorm:=xNorm + 29; qREM.LeftShift(58); end; hQ:=qREM.RLen -1; aL:=int64(qREM.RNum[hQ]); aL:=aL shl LOGBASE_V + int64(qREM.RNum[hQ-1]);
w:=trunc(Sqrt(aL/1)); qDivisor.ToVar(w + w); xrem:=aL - int64(w*w); if(xrem < 0)then begin w:=w -1; qDivisor.RNum[0]:=w + w; qDivisor.RNum[1]:=0; xrem:=aL - int64(w*w); end;
aC:=TVarInt.Create(xrem); SetLength(qminREM, hQ+1);
for j:=hQ-1 to hQ do qREM.RNum[j]:=aC.RNum[j+1-hQ]; q:=(hQ + 1)shr 1; qDivisor.LenTest(q); qDivisor.LeftShiftbyBASE(q -1);
spSelf:= TVarInt.Create(self); RLen:=q; RNum[q-1]:=w; TRY dec(hQ, 2); n:=hQ + 1; m:=1; WHILE(hQ > 0)DO BEGIN n:=n - 2; m:=m + 1; if(m < 4)then begin a3Ext:=qDivisor.RNum[q-1] + qDivisor.RNum[q-2]/BASE_V end; q4:=0; for i:=n + m downto n + m -1 do q4:=q4 shl LOGBASE_V + qREM.RNum[i];
q4Ext:=q4 + qREM.RNum[n+m-2]/BASE_V; w:=trunc(q4Ext/a3Ext); if(w = 0)then begin RNum[hQ shr 1]:=0; hQ:=hQ - 2; continue; end; if(w >= BASE_V)then w:=high(TBase_V); anpassenW; while(Compare(qminREM, qREM.RNum, n, m))do begin w:= w -1; anpassenW; end; differenz(qREM.RNum, qminREM, n, m); RNum[hQ shr 1]:=w; hQ:=hQ - 2; add(qDivisor.RNum, w, q - m); END;
if(xNorm > 0)then self.RightShift(xNorm);
qREM.Trim; result:=(qREM.RLen = 0); if(not result)and(mitRest)then if(xNorm > 0)then begin xNorm:=xNorm shl 1; if(qREM.isSelf_mod_2k_ZERO(xNorm))then begin qREM.RightShift(xNorm); end else begin aC.Assign(self); aC.Square; qREM.Sub(spSelf, aC); end; end;
FINALLY aC.Free; qDivisor.Free; spSelf.Free; END; END; end; end; |
der "Interne Fehler C1093" auf. Was dieser Fehler bedeutet, weiß ich nicht, und im WWW habe ich auch nur Kryptisches gefunden.
Das Kuriose ist nun: Compiliere ich Lelfs Text anschließend noch einmal, ohne etwas zu ändern, dann geht es, geschätzt, in 20% der Fälle. Das Einfügen oder Ändern eines Kommentars, ja selbst ein einzelnes Leerzeichen führt zum Fehler C1093. Sofortiges neues Übersetzen funktioniert beim 3., 4.Fall oder erst, wenn ich die Änderung rückgängig gemacht habe.
Hat jemand eine Ahnung, was hier los ist? Ich bin absolut ratlos.
Lelf vermutet, dass es an meinem Delphi 5 liegt, aber es geht ja manchmal. Weiterhin hat Delphi_Laie vollkommen richtig darauf hingewiesen, das der Compiler deterministisch ist. Und alle anderen Programme lassen sich weiterhin problemlos übersetzen.
Beste Grüße
ein verzweifelnder Mathematiker 
_________________ Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
Zuletzt bearbeitet von Mathematiker am So 12.08.12 23:11, insgesamt 1-mal bearbeitet
|
|
Martok
      
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: So 12.08.12 20:45
Der Compiler ist zwar theoretisch deterministisch, aber nicht bugfrei. Interner Fehler bedeutet meistens, dass im Compiler eine Exception aufgetreten ist, eine Assertion fehlgeschlagen ist oder sonstige Späße.
Sehr gerne passiert das auch, wenn sich der Optimizer ausmanövriert hat.
Im Zweifelsfall solange Delphi neustarten bis es funktioniert.
Sowas finde ich immer noch besser, als wenn direkt falscher Code generiert wird  Da hab ich nämlich gestern eine Sache in D7 gefunden, wo reproduzierbar Blödsinn generiert wird. Habs aber grad mal in XE getestet, da haut das wieder hin.
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
Für diesen Beitrag haben gedankt: Mathematiker
|
|
Mathematiker 
      
Beiträge: 2622
Erhaltene Danke: 1448
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: So 12.08.12 21:51
Hallo Martok,
Martok hat folgendes geschrieben : | Sehr gerne passiert das auch, wenn sich der Optimizer ausmanövriert hat. |
Genau das ist es!  Ich habe die Codeoptimierung abgeschaltet und schon ist alles wieder ok.
Besten Dank
Mathematiker
_________________ Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
|
|
Delphi-Laie
      
Beiträge: 1600
Erhaltene Danke: 232
Delphi 2 - RAD-Studio 10.1 Berlin
|
Verfasst: So 12.08.12 22:35
Mathematiker hat folgendes geschrieben : | Martok hat folgendes geschrieben : | Sehr gerne passiert das auch, wenn sich der Optimizer ausmanövriert hat. |
Genau das ist es! Ich habe die Codeoptimierung abgeschaltet und schon ist alles wieder ok. |
Darf ich fragen, wo man diese findet?
Vielleicht ist das eine mit Delphi 5 neuhinzugekommene Eigenschaft des Delphis. Aus Delphi 4 ist mir das unbekannt, aber ich bin andererseits kein Maulwurf und habe deshalb nicht den Spürsinn, in alle erreichbaren Tiefen auch tatsächlich zu gelangen.
Compiler hin, Optimierung her, ich bin überzeugt, daß da etwas am Quelltext "unsauber" ist. Einen solchen wahrscheinlich subtilen Fehler zu finden, zudem noch, daß etliche Units infragekommen und dann auch noch in fremden Quelltexten, ist eine in der gesamten, prall bis an die Decke gefüllte Scheune versteckte Stecknadel. Schon im eigenen Quelltext wäre das ein schwer zu gewinnendes Heimspiel.
|
|
Mathematiker 
      
Beiträge: 2622
Erhaltene Danke: 1448
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: So 12.08.12 22:38
Hallo Delphi_Laie,
Delphi-Laie hat folgendes geschrieben : | Darf ich fragen, wo man diese findet? |
in Delphi 5 findest Du das unter Projekt | Optionen | Compiler und dann Codeerzeugung | Optimierung.
Ob es das unter Delphi 4 gibt, weiß ich aber nicht.
Beste Grüße
Mathematiker
_________________ Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
Für diesen Beitrag haben gedankt: Delphi-Laie
|
|
jaenicke
      
Beiträge: 19314
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: So 12.08.12 22:40
Bei aktuellen Delphiversionen führt die Verwendung von Generics jetzt ganz gerne zu solchen internen Fehlern (z.B. URW913, ...), insbesondere, wenn man dabei auf Features kommt, die so gar nicht gedacht waren (aber trotzdem zufällig funktionieren). (Ja, ich nutze die dann auch ganz gerne mal.  )
Dafür hatte ich ohne Generics keine solchen Probleme mehr.
|
|
Delphi-Laie
      
Beiträge: 1600
Erhaltene Danke: 232
Delphi 2 - RAD-Studio 10.1 Berlin
|
Verfasst: So 12.08.12 22:54
Mathematiker hat folgendes geschrieben : | Hallo Delphi_Laie,
Delphi-Laie hat folgendes geschrieben : | Darf ich fragen, wo man diese findet? |
in Delphi 5 findest Du das unter Projekt | Optionen | Compiler und dann Codeerzeugung | Optimierung.
Ob es das unter Delphi 4 gibt, weiß ich aber nicht. |
Jippie, danke, gibt es auch dort, fiel mir bis heute noch nie auf.
"Codeerzeugung", ein einzelnes, unscheinbares Häkchen, empfinde ich allerdings schon als ein wenig oberflächlich. Was mag dort wohl alles (in welcher Hinsicht auch immer) "optimiert" werden und was alles nicht? Sogar der C++-Builder der Version 3 bietet mehr (und daß es dort so etwas gibt, weiß ich hingegen):
Codeoptimierung:
-aus
-Geschwindigkeit
-ausgewählte:
. -Pentium-Befehlsplan
. -Intrinsische Funktionen als Inline
. -Induzierte Variablen
. -Gemeinsame Teilausdrücke entfernen.
Da beide Compiler aus gleichem Hause stammen, ist mir unklar, warum man die Delphianer diesbezüglich an der kurzen Leine hält. Naja, vielleicht liegt es an grundverschiedenen Compilern (deren Architektur, Funktionsweise o.ä.).
Ergänzung: Diese Codeoptmierung gibt es auch schon in Delphi 3 und sogar in Delphi 2. Sollte mich nicht wundern, wenn sogar Delphi 1 sie schon beinhaltete...
Zuletzt bearbeitet von Delphi-Laie am Mo 13.08.12 12:07, insgesamt 1-mal bearbeitet
|
|
Mathematiker 
      
Beiträge: 2622
Erhaltene Danke: 1448
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: Mo 13.08.12 10:04
Hallo,
man muss nicht die ganze Codeoptimierung für das Programm abschalten.
Es genügt offensichtlich vor der kritischen Methode {$O-} und nach ihrem Ende {$O+} einzufügen. Dann wird der Großteil des Quelltextes optimiert und die sich "bösartig" verhaltende Methode eben nicht.
Ergebnis: Die Exe wird wieder kleiner und scheinbar auch der Programmablauf schneller.
Beste Grüße
Mathematiker
_________________ Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
|
|
Delphi-Laie
      
Beiträge: 1600
Erhaltene Danke: 232
Delphi 2 - RAD-Studio 10.1 Berlin
|
Verfasst: Mo 13.08.12 17:19
Mathematiker hat folgendes geschrieben : | Hallo,
man muss nicht die ganze Codeoptimierung für das Programm abschalten.
Es genügt offensichtlich vor der kritischen Methode {$O-} und nach ihrem Ende {$O+} einzufügen. Dann wird der Großteil des Quelltextes optimiert und die sich "bösartig" verhaltende Methode eben nicht. |
Ja klar, Quelltextanweisung übstimmt generelle Anweisung in den Projektoptionen.
Wenn Du schon diese Möglichkeit hast, dann ist es doch nur noch eine Fleißaufgabe, den Fehler im Quelltext soweit einzugrenzen, bis er schließlich umzingelt ist (die entscheidende(n) Anweisung(en)) - oder muß man immer für eine komplette Routine die Optimierung an-/zu- bzw. abschalten?
Mathematiker hat folgendes geschrieben : | Ergebnis: Die Exe wird wieder kleiner und scheinbar auch der Programmablauf schneller. |
Scheinbar? Läßt sich das nicht - wenigstens grob - messen und bestätigen?
Kleine Exe mag ich immer (scheue allerdings den Aufwand, den Luckie mit seinem NonVCL-Hinauswurf betreibt, das ist schon "Hardcore"), schnelle Exe mag ich noch viel mehr - wer nicht?
|
|
|