C++Guns – RoboBlog blogging the bot

26.07.2024

C++ Guns: Overloading friend operator for class template - the right way

Filed under: Allgemein — Tags: — Thomas @ 14:07

Goal

Overload operator +=, << etc. as free function for a templated class with private member variables without boilerplate code.
Choose free function to achieve less coupling than with member functions.
In the example you can imagine the Type as Array2D for a use case.

Solution

template<typename T>
class Type {
public:
    // free function form of the operator
    // no repeat of the template parameters for class Type necessary
    // with the friend keyword this is still a free function but can 
    // access private variables like a member function
    friend Type& operator+=(Type& lhs, double value) {
        lhs.data += value; // can access private member variable
        return x;
    }

private:
    double data = 0;
};


void f(Type<double>& x) {
    x += 2.0;
}

Not a Solution

// forward declaration, not usual
template<typename T>
class Type;

// Definition of the function is placed bevor the definition of the type. 
// This is also not usual but needed for the friend declaration later in the code.
// Repeat of the template parameter.
template<typename T>
inline Type<T>& operator+=(Type<T>& lhs, double value) {
    lhs.data += value;    
    return lhs;
}

template<typename T>
class Type {

private:
    double data = 0;

    // templated friend declaration. watch the necessary but very unusual <> here.    
    friend Type& operator+= <>(Type& lhs, double value);
};

void f(Type<double>& x) {
    x += 2.0;
}

C.4: Make a function a member only if it needs direct access to the representation of a class https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-member
Sources: https://stackoverflow.com/questions/4660123/overloading-friend-operator-for-class-template

17.04.2024

Installing gcc, g++ and gfortran 13 from source

Filed under: Allgemein — Thomas @ 12:04

GCC 13.2

wget https://ftp.gwdg.de/pub/misc/gcc/releases/gcc-13.2.0/gcc-13.2.0.tar.gz
tar xzf gcc-13.2.0.tar.gz 
cd gcc-13.2.0/
./contrib/download_prerequisites 
mkdir build
cd build/
../configure --prefix=/home/thomas/opt/gcc-13.2 --enable-threads --enable-languages=c,c++,fortran --disable-nls  # disable Native Language Support (NLS) 
make -j 8 # took 50min
make install

OpenMPI 4.1

wget https://download.open-mpi.org/release/open-mpi/v4.1/openmpi-4.1.6.tar.bz2
tar xjf openmpi-4.1.6.tar.bz2 
cd openmpi-4.1.6/
./configure CC=~/opt/gcc-13.2/bin/gcc CXX=~/opt/gcc-13.2/bin/g++ F77=~/opt/gcc-13.2/bin/gfortran FC=~/opt/gcc-13.2/bin/gfortran --prefix ~/opt/openmpi-4.1.6_gcc-13

Open MPI configuration:
-----------------------
Version: 4.1.6
Build MPI C bindings: yes
Build MPI Fortran bindings: mpif.h, use mpi, use mpi_f08

Debug build: no

Miscellaneous
-----------------------
HWLOC support: internal (external hlwoc version is less than internal version 2.0)
Libevent support: internal
PMIx support: Internal
 
Transports
-----------------------
OpenFabrics Verbs: yes
Shared memory/copy in+copy out: yes
Shared memory/Linux CMA: yes
TCP: yes
 
Resource Managers
-----------------------
ssh/rsh: yes
 
OMPIO File Systems
-----------------------
Generic Unix FS: yes

make
make install

03.04.2024

C++ Guns: OmegaException class von Peter Muldoon

Filed under: Allgemein — Tags: — Thomas @ 21:04

Mal ausprobieren ob damit Exception einfacher in der Handhabung werden...
Aus Exceptionally Bad: The Misuse of Exceptions in C++ & How to Do Better - Peter Muldoon - CppCon 2023

Conclusion of the talk:

What should they used for ?
• Error tracing (logging)
• Stack unwinding (reset / termination)
• Data passing / Control flow (when necessary)

When should they used ?
• As “Rarely” as possible
• Serious/infrequent/unexpected errors
• With as few exception types as possible (as determined by catch functionality)

template<typename DATA_T>
class OmegaException {
public:
  OmegaException(std::string str, DATA_T data, const std::source_location& loc = std::source_location::current(), std::stacktrace trace = std::stacktrace::current())
:err_str_{std::move(str)}, user_data_{std::move(data)}, location_{loc}, backtrace_{trace} { }

  std::string& what() { return err_str_; }
  const std::string& what() const noexcept { return err_str_; }

  const std::source_location& where() const noexcept { return location_; }
  const std::stacktrace& stack() const noexcept { return backtrace_; }

  DATA_T& data(){ return user_data_;}
  const DATA_T& data() const noexcept { return user_data_; }

private:
  std::string err_str_;
  DATA_T user_data_;
  const std::source_location location_;
  const std::stacktrace backtrace_;
}

std::ostream& operator << (std::ostream& os, const std::source_location& location) {
  os << location.file_name() << "("
  << location.line() << ":"
  << location.column() << "), function `"
  << location.function_name() << "`";
  return os;
}

std::ostream& operator << (std::ostream& os, const std::stacktrace& backtrace) {
  for(auto iter = backtrace.begin(); iter != (backtrace.end()-3); ++iter) {
    os << iter->source_file() << "(" << iter->source_line()
   << ") : " << iter->description() << "\n";
  }
  return os;
}

///////////////

enum Errs1 { bad = 1, real_bad };
enum class Errs2 { not_bad = 10, not_good };

using MyExceptionErrs1 = OmegaException<Errs1>;
using MyExceptionErrs2 = OmegaException<Errs2>;

throw MyExceptionErrs1(“Bad Order id", real_bad);

catch(const MyExceptionErrs1& e) {
  std::cout << "Failed to process with code (" << e.data() << ") : "
  << e.what() << “\n" << e.where() << std::endl;
}

/*
Failed to process with code (2) : Bad Order id
/app/example.cpp(76:69), function `Order findOrder(unsigned int
*/


//////////////

struct bucket {
  int id_;
  Msg msg_;
};

using MyExceptionBucket = OmegaException< bucket >;

throw MyExceptionBucket ("bad error", bucket{cliendId, amsg});

catch(MyExceptionBucket& eb) {
  std::cout << "Failed to process id (" << e.data().id_ << ") : "
  << e.what() << "\n" << e.stack() << std::endl;
  send_error(eb.data().msg_);
}

/*
Failed to process id (222) : Bad Order id
example.cpp(76) : findOrder(unsigned int)
example.cpp(82) : processOrder(unsigned int)
example.cpp(97) : main
*/

Filed under: Allgemein — Tags: — Thomas @ 21:04

Mal ausprobieren ob damit Exception einfacher in der Handhabung werden...
Aus Exceptionally Bad: The Misuse of Exceptions in C++ & How to Do Better - Peter Muldoon - CppCon 2023

Conclusion of the talk:

What should they used for ?
• Error tracing (logging)
• Stack unwinding (reset / termination)
• Data passing / Control flow (when necessary)

When should they used ?
• As “Rarely” as possible
• Serious/infrequent/unexpected errors
• With as few exception types as possible (as determined by catch functionality)

template<typename DATA_T>
class OmegaException {
public:
  OmegaException(std::string str, DATA_T data, const std::source_location& loc = std::source_location::current(), std::stacktrace trace = std::stacktrace::current())
:err_str_{std::move(str)}, user_data_{std::move(data)}, location_{loc}, backtrace_{trace} { }

  std::string& what() { return err_str_; }
  const std::string& what() const noexcept { return err_str_; }

  const std::source_location& where() const noexcept { return location_; }
  const std::stacktrace& stack() const noexcept { return backtrace_; }

  DATA_T& data(){ return user_data_;}
  const DATA_T& data() const noexcept { return user_data_; }

private:
  std::string err_str_;
  DATA_T user_data_;
  const std::source_location location_;
  const std::stacktrace backtrace_;
}

std::ostream& operator << (std::ostream& os, const std::source_location& location) {
  os << location.file_name() << "("
  << location.line() << ":"
  << location.column() << "), function `"
  << location.function_name() << "`";
  return os;
}

std::ostream& operator << (std::ostream& os, const std::stacktrace& backtrace) {
  for(auto iter = backtrace.begin(); iter != (backtrace.end()-3); ++iter) {
    os << iter->source_file() << "(" << iter->source_line()
   << ") : " << iter->description() << "\n";
  }
  return os;
}

///////////////

enum Errs1 { bad = 1, real_bad };
enum class Errs2 { not_bad = 10, not_good };

using MyExceptionErrs1 = OmegaException<Errs1>;
using MyExceptionErrs2 = OmegaException<Errs2>;

throw MyExceptionErrs1(“Bad Order id", real_bad);

catch(const MyExceptionErrs1& e) {
  std::cout << "Failed to process with code (" << e.data() << ") : "
  << e.what() << “\n" << e.where() << std::endl;
}

/*
Failed to process with code (2) : Bad Order id
/app/example.cpp(76:69), function `Order findOrder(unsigned int
*/


//////////////

struct bucket {
  int id_;
  Msg msg_;
};

using MyExceptionBucket = OmegaException< bucket >;

throw MyExceptionBucket ("bad error", bucket{cliendId, amsg});

catch(MyExceptionBucket& eb) {
  std::cout << "Failed to process id (" << e.data().id_ << ") : "
  << e.what() << "\n" << e.stack() << std::endl;
  send_error(eb.data().msg_);
}

/*
Failed to process id (222) : Bad Order id
example.cpp(76) : findOrder(unsigned int)
example.cpp(82) : processOrder(unsigned int)
example.cpp(97) : main
*/

27.02.2024

C++ Guns: Analyse AVX _mm256_i32gather_pd instruction

Filed under: Allgemein — Tags: , — Thomas @ 17:02

In scientific application using triangular grids it is often the case to load a value from all three vertices of the triangle which is spread across RAM. In order to use SIMD instruction to speed up execution time of the program the three values must be stored into a single SIMD register to perform e.g. a parallel multiplication (for a scalar product). One approach to archive this is to load the values one by one into multiple registers and combine them in an additional step. Would it be a better approach to load the three values in on step into one register? This can be done with the AVX gather instruction.

As I don't know how to use SIMD Intrinsics in fortran, this example is C++ only.

We start by native approach how to load three values into a SIMD register using intrinsics datatypes like __m256d which can hold up to four 64bit double precision floating-point values where actually only three are used.

__m256d f1(const std::vector<double>& values, const std::array<int,3>& idx) {
    const __m256d vec{ values[idx[0]], values[idx[1]], values[idx[2]]};
    return vec;
}

This generate the following assembler code independent of passed optimization flags -O1 -O2 -O3

        movq    (%rdi), %rax                         #                                                           
        movslq  (%rsi), %rcx                         # load idx0 in register rcx                                 
        movslq  4(%rsi), %rdx                        # load idx1 in register rdx                                 
        movslq  8(%rsi), %rsi                        # load idx2 in register rsi                                 
        vmovsd  (%rax,%rcx,8), %xmm0                 # load values[idx[0]] into xmm0                             
        vmovq   (%rax,%rsi,8), %xmm1                 # load values[idx[2]] into xmm1
        vmovhpd (%rax,%rdx,8), %xmm0, %xmm0          # load values[idx[1]] into hight part of xmm0
        vinsertf128     $0x1, %xmm1, %ymm0, %ymm0    # combine xmm0 and xmm1 into 512bit register ymm0
        ret 

To load 3 values at once we can use the _mm256_mask_i32gather_pd instruction which take a base address and offsets in a variable of type __m128i. To only load 3 instead of 4 values there is an additional mask variable.

The C++ code looks like this now:

__m256d f2(const std::vector<double>& values, const std::array<int,3>& idx) {
    // mask to load 3 instead of 4 values
    const __m128i mask = _mm_setr_epi32(-1, -1, -1, 0);
    // Copy Element Node IDs into SIMD register
    const __m128i vindex = _mm_maskload_epi32(idx.data(), mask);
    // Load 3 double values
    constexpr int scale = 8;
    // mask to load 3 values but this time as 256d variable (but docu say it must be 256i, bug?)
    const __m256d mask2 = _mm256_setr_pd (-1, -1, -1, 0);
    const __m256d vec{_mm256_mask_i32gather_pd (__m256d{}, values.data(), vindex, mask2, scale)};
    return vec;
}

This generate the following assembler code independent of passed optimization flags -O1 -O2 -O3

        movq    (%rdi), %rax                          #                                                     
        vmovapd .LC1(%rip), %ymm2                     # load mask2 into ymm2
        vxorpd  %xmm0, %xmm0, %xmm0                   # zero register xmm0                                    
        vmovdqa .LC0(%rip), %xmm1                     # load mask1 into xmm1
        vpmaskmovd      (%rsi), %xmm1, %xmm1          # load idx into xmm1  
        vgatherdpd      %ymm2, (%rax,%xmm1,8), %ymm0  # load values[idx] into ymm0
        ret

With AVX512 it is even possible the gather and scatter 3 values at ones. This time the mask variable is easier to create.

void f3(std::vector<double>& values, const std::array<int,3>& idx) {
    // Copy Element Node IDs into SIMD register
    constexpr int mask = 0b00000111;
    const __m128i vindex = _mm_maskz_loadu_epi32(mask, idx.data());
    // Load 3 double values
    constexpr int scale = 8;
    const __m256d vec{_mm256_mmask_i32gather_pd (__m256d{}, mask, vindex, values.data(), scale)};        
    // Store 3 double vales
    _mm256_mask_i32scatter_pd(values.data(), mask, vindex, vec, scale);
}

This generate the following assembler code independent of passed optimization flags -O1 -O2 -O3

        movl    $7, %eax                              # load mask into eax
        vxorpd  %xmm0, %xmm0, %xmm0                   # zero register xmm0
        kmovw   %eax, %k1                             # convert mask into the mask register k1
        movq    (%rdi), %rax                          # 
        vmovdqu32       (%rsi), %xmm1{%k1}{z}         # load idx into xmm1
        kmovw   %k1, %k2                              # copy mask register. why is that so? bug?
        vgatherdpd      (%rax,%xmm1,8), %ymm0{%k2}    # load values[idx] into ymm0
        vscatterdpd     %ymm0, (%rax,%xmm1,8){%k1}    # stpre ymm0 into values[idx]
        vzeroupper                                    # can be optimization away?
        ret

To measure I created a little testcase with the presented different variants on the following CPUs: Intel Core i5-10500, Intel Xeon E5-2695 v4, Intel Core i9-7900X. Unfortunately there is no speedup using AVX. There is even no slowdown (except for 1-2%).

https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=m256_i32gather&expand=4474&ig_expand=4252,4250,2125,3720,4058,3723,3723&techs=AVX_ALL

07.02.2024

Analyse: Frozen Throne: Randgruppen TD2 Rapper Mod

Filed under: Allgemein — Thomas @ 22:02
TV Glozer Flying only
Name Kosten Dmg Range Type freeze splash dmg/gold Dmg Range Cooldown Type freeze splash dmg/gold
Ernie Berrt 10 16-26 950 Siege no no 2.3
Barbara Salesch 35 31-45 900 Chaos no no 1.08
Günter Jauch 80 51-81 850 Normal no yes 0.83 (2) 105-250 1400 0.3 Pirce no yes 2.2 (8.8)
GZSZ 155 146-224 950 Spells no no 1.2
Anime Guy 260 225-510 1100 Normal no yes 1.4 (3)
MTV VIVA 390 345-440 1050 Chaos no yes 1.0 (2.3)
Big Brother 800 770-1550 3000 Chaos YES no 1.45

Auslands Helden
Name

Kosten Dmg Range Type freeze splash
Tengu Man 10 34-46 1000 Pierce no no
Clown Man 35 96-138 600 Normal no no
Aqua Man 155 120-155 1200 Magic no no
Sword Man 265 256-286 500 Pierce no no
Astro Man 400 388-452 2000 Hero no no
Green Devil 750 801-900 3000 Chaos no yes

Aushilfs Helden Flying only
Name

Kosten Dmg Range Type freeze splash dmg/gold Dmg Range Cooldown Type freeze splash dmg/gold
Spring Man 10 10-14 650 Pierce no no 1.2 (2.4)
Splash Man 60 75-105 700 Magic no yes 1.5 (3) 1000-2000 1500 4.0 Pierce no yes
Freeze Man 150 147-149 750 Siege yes no
Shade Man 225 207-263 1000 Pierce no no
Turbo Man 500 510-600 1000 Hero no no
Ninja Mask 750 801-900 3000 Chaos no yes

Aushilfsnazi
Name

Kosten Dmg Range Type freeze splash
Skinhead 24 22-26 600 Siege no yes
Kämtner 65 48-54 300 Normal no no
Altnazi 100 91-115 350 Normal no no
Parzival 120 101-101 1200 Chaos no no
Faschismus 340 156-204 1100 Magic no yes
Bushido 550 472-516 550 Chaos no yes
Führer 870 951-1050 3000 Chaos no no

Dealer
Name Kosten Dmg Range Type freeze splash
Alkopopskonsument 15 17-21 650 Pierce no no
Kettenraucher 55 26-60 650 Siege no yes
LSD Ulli 125 70-115 800 Magic no no
Pornomann 165 169-197 1400 Normal no yes
Z 300 194-218 850 Siege no yes
Xtasy Dude 410 376-406 600 Pierce no yes
David Hasselhoff 850 901-1000 3000 Chaos no no

Gastarbeiter
Name Kosten Dmg Range Type freeze splash dmg/gold
Osteuropäer 5 7-13 550 Magic no no 2 (2.5)
Asiate 20 27-33 650 Pierce no no 1.5 (3.0)
Türke 65 65-85 700 Siege no yes 1.15
Araber 130 79-91 950 Spells no no 0.653
Italiener 175 107-163 950 Magic no no 0.771
Holländer 425 206-236 1000 Normal YES yes 0.52 (2.08)
Roberto Blanco 750 801-900 3000 Chaos no no

Haider, Alfons
Name Kosten Dmg Range Type freeze splash
Arschficker

10 14-18 1000 Magic no no
Priester

40 21-27 1400 Normal YES no
Lesbe

90 80-110 1500 Normal no no
Gayporn

135 78-150 450 Chaos no no
Ufer wechseln 200 111-125 1400 Normal no yes
Dirk Bach 350 301-400 1200 Pierce no yes
Ronaldo 750 801-900 3000 Chaos no no

Kapital Wessi
Name Kosten Dmg Range Type freeze splash
Polizist 25 17-21 800 Siege no yes
Kapitalist 70 43-49 300 Normal no no
Manager 110 86-110 300 Normal ?? no
CDU/CSU 150 131-131 1200 Chaos no no
Finanzhai
Otto Waalkes
Schröder

Nachwuchs Rapper
Name Kosten Dmg Range Type freeze splash dmg/gold
Möchtergern Rapper

10 15-19 1000 Pierce no no 1.7 (3.4)
Freestyler

50 27-33 900 Pierce no no 0.6 (1.2)
Fler

90 67-87 700 Spells no yes 0.856
Sido

120 63-90 500 Hero no no 0.667
Dendeman

200 155-200 600 Spells no yes 0.89
Bushido

550 472-516 550 Chaos no yes 0.9
Aggro Berlin

750 801-900 10000 Chaos no no

Ossi Arbeiter
Name Kosten Dmg Range Type freeze splash
Soldat

12 17-21 800 Pierce no no
Mitläufer

45 51-57 750 Pierce no no
Mauerwachturm

90 65-85 700 Siege no yes
SED Zentrale 140 104-116 700 Spells no no
Stasi Offizier 230 147-203 950 Magic no no
Erich Honecker 375 226-256 1000 Normal no yes
Karl Marx 750 801-900 3000 Chaos no no

Pro Gamer
Name Kosten Dmg Range Type freeze splash
Konsolennoob

10 11-12 800 Pierce no no
WoW Zocker

40 21-27 900 Magic no no
C&C Kaputti

85 64-80 600 Siege no yes
UT Bekloppter
W3 Zocker
Diablo Freak
CS Owner

700 751-850 3100 Chaos no no

Udo Jürgens
Name Kosten Dmg Range Type freeze splash
Pensionist 14 16-24 800 Pierce no no
Leprakranker 55 64-80 1400 Siege no yes
Coolman 135 110-130 1080 Magic no yes
Dauererektion 200 109-137 800 Chaos no no
aids kranker 265 236-266 950 Spells no no
Michael J Fox 450 356-410 800 Siege no yes
Mr T 800 801-900 3000 Chaos no no

01.01.2024

Analye: Frozen Throne Tower Defense Warcraft III

Filed under: Allgemein — Thomas @ 23:01

Flame
40 70 110 150 260
40-80 60-150 90-300 150-750 240-1800
800 1000 1200 1500 1800

Lightning
Geld 40 60 80 120 150
Schaden 80-160 120-300 175-525 230-800 340-1500
Reichweite 1300 1500 1750 2000 2300

Froizen

60 80 100 120 80
30-70 40-130 55 -265 80-460 135-1325
800 1000 1200 1500 1800


Fizz Tower

frozenthronefizztower

Bei Tower 5 bekommt man den meisten schaden pro Geld. Das ist erst mal nicht verwunderlich. Aber der ist teuer und man kann ihn sich nicht leisten. Stattdessen also viel Tower 1 2 oder 3 kaufen? Tower 4 ist Betrug, man bekommt weniger Schaden pro Geld als bei Tower 3. Der Tower 3 schneidet am besten ab. Also diese bauen wie Sand am Meer.


Canon Tower

frozenthronecanontower

Bei den Cannonball Towers gibt es keine Präferenz bezüglich Schaden pro Geld. Zwar gibt es bei Tower 2,3 und 4 weniger Schaden pro Geld, aber durch die Splash Damage Funktion gleicht sich das wieder aus. Tipp: Die Tower erst aufrüsten wenn nötig, damit mehr Geld für die Fizzfizz Tower übrig ist.


Flame Tower

frozenthroneflametower

Der Flame Tower ist schon in der ersten Ausbau Stufe mit 2 Schaden pro Geld so gut wie der Canon Tower in vollem Ausbau, aber natürlich nicht so start. Der Schaden pro Geld Ratio steigt ab Ausbau Stufe 4 und 5 sehr stark an. Allerdings sind diese sehr teuer, so dass man sie nur im fortgeschrittenen Spiel bauen kann und sollte.


Lightning Tower

frozenthronelighttower

Den Lightning Tower auszubauen lohnt nicht! Man bekommt immer weniger Schaden pro Geld. Natürlich steigt die Reichweite des Towers, aber da die Flieger in der Regel sehr schnell unterwegs sind, kann der Tower so oder so nicht oft schließen. Womöglich bringt es etwas, den Tower an eine Ecke zu stellen, wo die Flieger eine Kehrtwendung machen.


Reichweiten Vergleich

frozenthronetowerrange

Die Reichweite des Canonballtowers ist im Mittel grob 1.3 mal höher als die des Fizz Towes. Daher diesen Tower dort platzieren wo er lange gerade Stecken beschießen kann, ohne dass der Turm sich viel drehen muss.


Map Analyse von Azote Vil's TEAM TD v1.3 (99Lv)

Tower Kosten 10 15 20 30 40 = 115

Strategie: Die Gegner laufen im Waagrechten und zweiten senkrechten Teil in einer Linie, fast mittig näher zur Inneren Mauer hin. Mit Tower die Gegner aufhalten ist nicht nötig. Die Flieger sind das größte Problem.

Flying Levels: 10 14 16 18 26 27 31 44 45 46 64 68 69 70 71 73 74
Rekord: Level 72

Level Geld
start 50
1 50 + 20
2 55 + 20
3 +20
4 +20
5 +20
6 +20
7 +20
8 +20
9 +20
10 +20 5-6 tower nötig
11 +20
12 +20
13 +40 !
14 +40 9 tower nötig
15
16 +2 10 langen nicht
17
18 +2 12 langen nicht
19 +2
20 +2
21 +2
22 +2
23 +2
24 +2
25 +3
26 +3 18 langen nicht
27 +3 19 langen nicht
28 +3
29 +3
30 +3
31 +3 22 lange nicht
32 +3
33 +3
34 +3
35 +3-6
36 +4
37 +4-6
38 +30-35
39 +4
40 +4
41 +4
42 +4
43 +4
44 +4 44 langen nicht
45 +4 44 lange nicht
46 +25 fliege
47 +4
48 +4
49 +5
50 +5
51 +5
52 +5
53 +5
54 +5
55 +5
56 +5
57 +5
58 +5
59 +5
60 +6
61 +6
62 +6
63 +6
64 +6 74 alle
65 +6
66 +6
67 +6
68 +6 78 eioner durhc
69 +6 3 durch
70 +7 7 durch
71 +7 11 durch
72

08.12.2023

C++ Guns: Compiler kürzt Formel

Filed under: Allgemein — Thomas @ 13:12

compiler_kürzt_formel

24.07.2023

C++ Guns: DOS codepage 437 to UTF8

Filed under: Allgemein — Tags: , — Thomas @ 09:07

Wenn die üblichen Encodings wie UTF8, Latin1, ISO-8859-15 nicht funktionieren kann man CP437 versuchen. Das ist der Original-Zeichensatz des IBM-PC ab 1981. Dieser enthält Umlaute die in den üblicherweise eingestellten Encodings nicht angezeigt werden.

Hier mein erster Versuch CP437 nach UTF8 zu konvertieren. Die Sourcecode Datei und der Compiler und das ganze Betriebssystem ist selbstverständlich auf UTF8 eingestellt, sonst funktioniert es nicht.

std::string cp437toUTF8(std::string_view str) {
    std::string result;
    result.reserve(str.size());
    for(unsigned char c : str) {
        switch(c) {
        case 129: result.append("ü"); break;
        case 132: result.append("ä"); break;
        case 142: result.append("Ä"); break;
        case 148: result.append("ö"); break;
        case 153: result.append("Ö"); break;
        case 154: result.append("Ü"); break;
        case 225: result.append("ß"); break;
        default: result.push_back(c);
        }
    }

    return result;
}

[1] https://de.wikipedia.org/wiki/Codepage_437
[2] https://www.ascii-code.com/CP437

28.06.2023

Ganglia SSD Metrics

Filed under: Allgemein — Tags: — Thomas @ 14:06

GMETRIC="/usr/bin/gmetric -c /etc/ganglia/gmond.conf"
DEV=/dev/sda

temperature=$(sudo smartctl -A $DEV | grep Temperature_Celsius |  awk '{print $10}')
Reallocated_Sector_Ct=$(sudo smartctl -A $DEV | grep Reallocated_Sector_Ct |  awk '{print $10}')
Current_Pending_Sector=$(sudo smartctl -A $DEV | grep Current_Pending_Sector |  awk '{print $10}')
Offline_Uncorrectable=$(sudo smartctl -A $DEV | grep Offline_Uncorrectable |  awk '{print $10}')
UDMA_CRC_Error_Count=$(sudo smartctl -A $DEV | grep UDMA_CRC_Error_Count |  awk '{print $10}')
Program_Fail_Count_Chip=$(sudo smartctl -A $DEV | grep Program_Fail_Count_Chip |  awk '{print $10}')
Erase_Fail_Count_Chip=$(sudo smartctl -A $DEV | grep Erase_Fail_Count_Chip |  awk '{print $10}')
Wear_Leveling_Count=$(sudo smartctl -A $DEV | grep Wear_Leveling_Count  |  awk '{print $10}')
Used_Rsvd_Blk_Cnt_Chip=$(sudo smartctl -A $DEV | grep Used_Rsvd_Blk_Cnt_Chip  |  awk '{print $10}')
Program_Fail_Cnt_Total=$(sudo smartctl -A $DEV | grep Program_Fail_Cnt_Total  |  awk '{print $10}')
Erase_Fail_Count_Total=$(sudo smartctl -A $DEV | grep Erase_Fail_Count_Total  |  awk '{print $10}')

echo "temperature" $temperature
echo "Reallocated_Sector_Ct" $Reallocated_Sector_Ct
echo "Current_Pending_Sector" $Current_Pending_Sector
echo "Offline_Uncorrectable" $Offline_Uncorrectable
echo "UDMA_CRC_Error_Count" $UDMA_CRC_Error_Count
echo "Program_Fail_Count_Chip" $Program_Fail_Count_Chip
echo "Erase_Fail_Count_Chip" $Erase_Fail_Count_Chip
echo "Wear_Leveling_Count " $Wear_Leveling_Count 
echo "Used_Rsvd_Blk_Cnt_Chip" $Used_Rsvd_Blk_Cnt_Chip
echo "Program_Fail_Cnt_Total" $Program_Fail_Cnt_Total
echo "Erase_Fail_Count_Total" $Erase_Fail_Count_Total


$GMETRIC  -t float -n "Temperature" -u "Celcius" -g "SSD" -v $temperature
$GMETRIC  -t float -n "Reallocated_Sector_Ct" -g "SSD" -v $Reallocated_Sector_Ct
$GMETRIC  -t float -n "Current_Pending_Sector" -g "SSD" -v $Current_Pending_Sector
$GMETRIC  -t float -n "Offline_Uncorrectable" -g "SSD" -v $Offline_Uncorrectable
$GMETRIC  -t float -n "UDMA_CRC_Error_Count" -g "SSD" -v $UDMA_CRC_Error_Count
$GMETRIC  -t float -n "Program_Fail_Count_Chip" -g "SSD" -v $Program_Fail_Count_Chip
$GMETRIC  -t float -n "Erase_Fail_Count_Chip" -g "SSD" -v $Erase_Fail_Count_Chip
$GMETRIC  -t float -n "Wear_Leveling_Count" -g "SSD" -v $Wear_Leveling_Count
$GMETRIC  -t float -n "Used_Rsvd_Blk_Cnt_Chip" -g "SSD" -v $Used_Rsvd_Blk_Cnt_Chip
$GMETRIC  -t float -n "Program_Fail_Cnt_Total" -g "SSD" -v $Program_Fail_Cnt_Total
$GMETRIC  -t float -n "Erase_Fail_Count_Total" -g "SSD" -v $Erase_Fail_Count_Total

Older Posts »

Powered by WordPress