Letztes Wort loeschen
-
mr. wrong schrieb:
void mrwrong(std::string& s) { const char x = ' '; __m128i zero = _mm_setzero_si128(); __m128i cx16 = _mm_set1_epi8(x); const char *start=s.c_str(), *b = start + s.size(); for (int i=s.size()%16;i--;) if (*--b == x) goto end; for (b -= 16;; b -= 16) { __m128i x = _mm_loadu_si128((__m128i const *)b); unsigned u = _mm_movemask_epi8(_mm_cmpeq_epi8(zero, x)); unsigned v = _mm_movemask_epi8(_mm_cmpeq_epi8(cx16, x)) & ~u & (u - 1); if (v) { b += __builtin_ctz(v); goto end; } if (__builtin_expect(b == start,0)) { return; } } end: s.erase(b - start); }
-
Das muss ich erst mal verdauen, da lernt man doch die Profis schätzen.

-
bedenke aber, dass der Code mr. wongs code plattform- und compilerabhängig ist.
Wenn es weiterhin unabhängig sein soll, musst du schon mit präprozessorcommandos etwas basteln, um im Notfall auf deine alte Methode zurückzuspringen.
-
Unabhängig vom OS sollte es schon sein. Ich programmiere mit dem Qt-Creator unter OSX und die Sachen sollten dann aber auch unter Linux, Windows und Android laufen.
Nichts desto Trotz ist die Lösung von MrWrong schon beeindruckend. Ich habe früher auf dem Amiga mit dem Seka-Assembler so Demos programmiert und daher ist eine Restfaszination für die einzig reale Computersprache immer noch da.
Mittlerweile bin ich aber über die vielen Abstraktionsebenen doch froh

EDIT: So, ohne Spezialfälle habe ich es jetzt so gelöst. Gibt es damit auch Probleme?
_text.erase(_text.find_last_of(' '));
-
CppNeuland schrieb:
EDIT: So, ohne Spezialfälle habe ich es jetzt so gelöst. Gibt es damit auch Probleme?
_text.erase(_text.find_last_of(' '));Ja, string::erase() löst eine out_of_range exception aus falls im string kein Leerzeichen gefunden wird (find_last_of() == string::npos).
- osdt
-
Nathan schrieb:
mr. wrong schrieb:
void mrwrong(std::string& s) { const char x = ' '; __m128i zero = _mm_setzero_si128(); __m128i cx16 = _mm_set1_epi8(x); const char *start=s.c_str(), *b = start + s.size(); for (int i=s.size()%16;i--;) if (*--b == x) goto end; for (b -= 16;; b -= 16) { __m128i x = _mm_loadu_si128((__m128i const *)b); unsigned u = _mm_movemask_epi8(_mm_cmpeq_epi8(zero, x)); unsigned v = _mm_movemask_epi8(_mm_cmpeq_epi8(cx16, x)) & ~u & (u - 1); if (v) { b += __builtin_ctz(v); goto end; } if (__builtin_expect(b == start,0)) { return; } } end: s.erase(b - start); }
Ich dachte bis jetzt "goto" soll man nicht verwenden?
-
mrwrong: 1531876 ns arcoth: 3441873 ns neuland: 5500253 ns [...] mrwrong: 968054 ns arcoth : 3047209 ns neuland: 4573583 ns mrwrong: 958147 ns arcoth : 3222022 ns neuland: 4567348 nsDie Ausgabe bekomme ich, wenn ich mrwrongs, CppNeulands neuesten und meinen Code, der im Übrigen - soweit ich sehe - plattformunabhängig ist, vergleiche. Am meisten unnötige Zeit schluckt wohl die Funktion
qword qword_from( char const* p ) { return *p | ( qword(p[1]) << 8 ) | ( qword(p[2]) << 16 ) | ( qword(p[3]) << 24 ) | ( qword(p[4]) << 32 ) | ( qword(p[5]) << 40 ) | ( qword(p[6]) << 48 ) | ( qword(p[7]) << 56 ); }, dafür nimmt mrwrong in seiner Variante natürlich
_mm_loadu_si128. Wenn ich stattdessen die UB-Methode nehme,qword qword_from( char const* p ) { return *reinterpret_cast<qword const*>(p); }bekomme ich etwa
mrwrong: 1502699 ns arcoth : 1395314 ns neuland: 7582803 ns [...] mrwrong: 981523 ns arcoth : 1093849 ns neuland: 4553076 ns mrwrong: 887963 ns arcoth : 1098256 ns neuland: 4938181 nsIch dachte bis jetzt "goto" soll man nicht verwenden?
Das ist nur eine Faustregel, um Spaghetti-Code zu vermeiden. Hier vereinfacht es den Code.
-
osdt schrieb:
CppNeuland schrieb:
EDIT: So, ohne Spezialfälle habe ich es jetzt so gelöst. Gibt es damit auch Probleme?
_text.erase(_text.find_last_of(' '));Ja, string::erase() löst eine out_of_range exception aus falls im string kein Leerzeichen gefunden wird (find_last_of() == string::npos).
- osdt
Aja, na dann versuche ich es mal so:
size_t pos = _text.find_last_of(' '); if ( pos != string::npos ) _text.erase(pos);
-
Und wenn der ganze String ein Wort ist?
-
Spezialfälle habe ich jetzt nicht mit drin, aber in diesem Fall wird ja erase übersprungen. Die ganze Sache ist eh nur um das Command Pattern mal an einem konkreten Minimalbeispiel mir klar zu machen. Das wird also nie so irgendwie produktiv laufen.
Ich hatte halt zwei Beispielklassen mit Text, eine kann Zeichen hinzufügen und das letzte Zeichen löschen und eine kann dies mit Worten tun. Und beim Wort löschen kam ich dann auf die erste Lösung hier...der Rest ist bekannt.