Fast portable arithmetic shifting with C/C++ (to multiply with power-of-two)

There are certain situations when one wants to shift integers either left or right based on runtime parameters, for example to calculate a×2b.

Simply calculating a << b can result in errors:

  • if a is negative, the operation is undefined behavior.
  • if b is negative, the operation is undefined behavior.
  • if a is signed and a 1-bit get shifted in the sign bit, then until C++14 this is undefined behavior and since C++14 it results in the sign-bit being set, which may or may not be desired.
  • with a >> b, if a is negative and b isn’t then the result is implementation defined in C++, it might not be a×2b.

A solution can be the following:

  • Depending on the sign of b, simply do << b or >> (-b).
  • If a is negative and b is positive:
    •   -a       = [1] (-a is positive)
        -a << b  = [2] (-a 2b in a well-defined way)
      -(-a << b) = [3] (-(-a 2b) = a 2b in a well-defined way)
    • In [1], we negate a. This is only undefined if a is the minimum value, for example -128 and can not be converted to +128 in 8 bits. This is the only case which results in UB, but the result would be unrepresentable anyway.
    • In [2], we get –a×2b in a well-defined way and finally in [3] we get a×2b.
  • If a is negative and b is negative:
    •    a        = 1jk..rs..yz  [1] (j..z are the bits)
        ~a        = 0JK..RS..YZ  [2] (N = ~n)
        ~a >> -b  = 00..0JK..RS  [3]
      ~(~a >> -b) = 11..1jk..rs  [4]
    • In [1], we have the original number, a, which is negative.
    • In [2], we get the ones-complement which is abs(a)-1.
    • In [3], we get (abs(a)-1)×2b = abs(a)×2b-1×2b = abs(a)×2b rounded down
    • In [4], we get a×2b-1 where a×2b is rounded up.
    • As it can be seen, this sequence of operations is equivalent to an arithmetic right shift.

The code can be viewed here.

Most platforms implement arithmetic shifting for signed values anyway, meaning they use the arithmetic shift instructions so the above exercise becomes pointless. Even worse, look at the assembly generated here: https://godbolt.org/g/YN1qr4

All the branches are there in the generic shifting function even though they are optimized away to single instructions (SAL, SAR, SHR on x86 and MOV ASL, MOV ASR, MOV LSR on ARM) when the shift amount is known at compile time.

It is best if we rely on builtin arithmetic shifting when possible. To test for this at compile-time, we can verify that shifting -1 = 0xFFFF right by one results in -1. The results can be seen here: https://godbolt.org/g/puIcAF The generic shift function shift_by_int avoids branching and uses less instructions on all platforms.

The code:

#include <type_traits>

template <typename T>
constexpr auto builtin_shr(T value, int amount) noexcept
    -> decltype(value >> amount)
{
    return value >> amount;
}

template <typename T>
struct uses_arithmetic_shift : std::integral_constant<bool, builtin_shr(T(-1), 1) == -1> {};

template <typename T = int>
constexpr T shift_by_portable(T value, int amount) noexcept
{
    return value < 0 ?
      amount < 0 ? ~(~value >> -amount) : -(-value << amount) :
      amount < 0 ? value >> -amount : value << amount;
}

template <typename T = int>
constexpr T shift_by_arithmetic(T value, int amount) noexcept
{
    // Only use with negative T values when the compiler translates right shift to arithmetic shift instructions.
    return amount < 0 ? value >> -amount : value << amount;
}


template <typename T = int>
constexpr T shift_by(T value, int amount) noexcept
{
    return uses_arithmetic_shift<T>::value ? shift_by_arithmetic(value, amount) : shift_by_portable(value, amount);
}

Recreating this with C macros is left as an exercise to the reader.

Számítógépekről: az első adag

Elkészült az első adag írásom “arról, amit mindenkinek tudnia kell a számítógépekről.” Első körben pár elméleti dologról (bitek, bájtok, adatok), hardverekről, az operációs rendszerről, a hibákról (úgy általában) és a vírusokról, biztonsági problémákról lesz szó.

Ha valamit nem érthetően írtam le, akkor figyelmeztessetek a hozzászólások között.

Amúgy kíváncsi leszek, hogy kinek fog ez újakat mondani, ki találja majd hasznosnak. Ha mondjuk lesz pár ember, akit érdekelt, akkor az internetről, a netes biztonságról és még pár konkrét alkalmazásról írva be is fogom fejezni, amit elkezdtem.

Szóval akit érdekel, az a menüből (baloldalt) nyissa meg a Számítógépekről című oldalt. Vagy kattintson ide.

Minden, amit számítógépekről tudni kell

Már régóta van egy olyan tervem, hogy megírok mindent (mindent!), amit a számítógépekről és az internetről mindenkinek tudni kell. Ez sokkal kevesebb dolog, mint amennyi akkor lenne, ha a célkitűzésem az lenne, hogy mindent leírok, amit a rendszergazdáknak, programozóknak vagy egy hekkernek tudnia kell.

Hogy pontosan miről van szó? Hát arról, hogy például egy processzor, egy merevlemez, a többi vas és az internetszolgáltató segítségével hogy tudod te most konkrétan ezt a szöveget olvasni. Vagy, amire külön hangsúlyt fektetnék, hogy gonosz emberek hányféleképp tudnak téged átvágni az interneten vagy máshol.

Ezt amúgy simán kéne oktatni már attól a kortól, amikor egy gyerek rendszeresen használja a számítógépet, az internetet (hozzávetőlegesen: óvoda, középső csoport), de legalábbis számtech órán el kéne ezeket mondani mindenkinek. Ehelyett ezt nem tudja senki, az érettségin meg kultúrtörténeti nyavalyákat kérdeznek. De az oktatási rendszer szidását most meghagyom másnak.

Nagyjából ennyi is lenne, mert nem kell mindenkinek értenie ennél többhöz. De ehhez azért kéne. Ez most az októberi érettségi előtt még hasznos is lehet, ha elkészül, de közben azért a magam kedvéért is csinálom (szeretek írni). Ja és az is eszembe jutott, hogy ugyanezt a végén videó- vagy podcastformátumban is meg lehetne csinálni mindenféle menő grafikával, vizuálisabb magyarázatokkal stb. – hmm, valaki?

Ha a projekt kész lesz, akkor az anyag felül a Számítógépekről című linkre kattintva lesz elérhető. Egyelőre persze csak tervek és vázlatok vannak azon a linken. Akit a kész anyag érdekel, ne féljen, szólok, ha kész lesz. Akit már a vázlatok is érdekelnek, az nyugodtan nézze meg. Sőt, aki ért hozzá, az megírhatja, hogy mit kéne máshogy csinálnom (miről írjak még/máshogy/kevesebbet), aki pedig a témához nem ért, de a végeredmény érdekelné, az szólhat, ha valamit érthetetlenül írtam le, fogalmazzam át. Akit pedig nem érdekel az egész, az úgysem jutott el eddig a mondatig, de semmi esetre se kattintson majd a hivatkozásra.

Sorozatok

Készítettem egy kis programot, ami a sorozatokkal tanult mindenféle műveleteket tudja elvégezni. Egyrészt azért csináltam, hogy programozzak (vö. csak úgy), másrészt, hogy a házifeladatokat tudjam ellenőrizni. Utóbbi célból ti is használhatjátok. A használati utasítás onnantól kezdve, hogy mit kell telepíteni, odáig, hogy a parancssorba mit kell beírni, illetve a program forráskódja a bitbucketen érhető el.

Programozás–számolgatás vektorokkal

Programozgattam most egy kicsit, hogy lement a fizika OKTV második fordulója és volt egy kis szabad időm. Előszöris az online html szerkesztőm helyett csináltam valami újat (amiről majd írok bővebben is, ha teljesen kész lesz), de mindezt azért csináltam, hogy vektorokkal számolgathassunk egy kicsit.

Szóval azt csináltam, hogy elkészítettem egy sablont, vagy minek hívják, aminek a segítségével el lehet végezni tetszőleges koordinátájú vektorokkal a matekórán eddig tanult alapműveleteket. Inkább megmutatom, vagyis annál még egy picit bonyolultabb, szóval leírom mit csináljatok, hogy lássátok miről beszélek.Continue reading “Programozás–számolgatás vektorokkal”

Kupacrendezés – a HeapSort algoritmus

Bevezetés

Régen programoztam már utoljára. Múlt héten gondoltam egyet, és megírtam C# nyelven a HeapSort algoritmust (magyarul kupacrendező algoritmust), mert jó szórakozás, hasznos, továbbá azért is, hogy leírhassam a blogomon a működését. A teljesség vagy a pontosság igénye nélkül – próbáltam mindent leírni, amit tudok, de nem vagyok még ennek a témának a szakértője.

A HeapSort egy rendezőalgoritmus, azaz fog egy tetszőleges elemekből álló tömböt (számsort) és sorba rendezi az elemeket. Ez egy egyszerű, de érdekes algoritmus, több okból is.

  1. A rendezőalgoritmusok mind érdekesek, ugyanis nem tehetjük azt meg, hogy minden elemet minden elemmel összehasonlítunk, mert az n * (n – 1) / 2 összehasonlítást igényelne és az algoritmushoz szükséges műveletek száma négyzetesen arányos lenne az elemek számával.

    Az első diagramm mutatja, hogy optimálisan mennyi művelet elvégzésére van szükség az adatok arányában. A második diagrammon látszik, hogy ha a kettő négyzetesen arányos, akkor egy bizonyos adatmennyiség felett elfogadhatatlanul sok művelet elvégzésére van szükség, irtózatosan lelassul a program.Continue reading “Kupacrendezés – a HeapSort algoritmus”

Valami készül

private void siftDown(int i)
{
     var swapWith = i;
     if (2 * i + 1 < heapCount)
     {
         if (2 * i + 2 < heapCount)
         {
             if (array[i].CompareTo(array[2 * i + 2]) < 0 &&
                 array[2 * i + 1].CompareTo(array[2 * i + 2]) < 0)
                 swapWith = 2 * i + 2;
             else
                 if (array[i].CompareTo(array[2 * i + 1]) < 0)
                     swapWith = 2 * i + 1;
         }
         else
             if (array[i].CompareTo(array[2 * i + 1]) < 0)
                 swapWith = 2 * i + 1;
     }
     if (i == swapWith)
         return;
     swap(i, swapWith);
     if (lacksHeapProperty(swapWith))
         siftDown(swapWith);
}

A teljes algoritmust és a hozzá tartozó programot hamarosan közzé teszem. (Gondolom, ennek hatására olvasóimat most a várakozás-vágyakozás eksztatikus érzése keríti hatalmába, de hát ez van.)

Eltévedt SEO az erdőben

Tudjátok mi a SEO?

Search Engine Optimization. Keresőoptimalizálás. Magyarul: az, amikor eléred, hogy a Google a barátod legyen, és téged rakjon A Lista tetejére (tudod, rákeresnek valamire, van egy lista, és te a legfelsőre kattintasz). Ez ilyen járulékos hülyeségeket eredményez, minthogy több látogatója lesz az oldaladnak, több cuccodat veszik meg, több zsét szedhetsz a hirdetőktől, satöbbi.

A lényeg az, hogy könnyebben megtalálnak.

Tudjátok mi az erdő? Oké.

De azért mégis; ötvözzük a kettőt. Az internet “az erdő.” Sűrű, sötét, naaagy (kerek) erdő. A SEO meg arra jó, hogy az arra tévedő emberek a (kerek) erdőben téged könnyebben megtaláljanak. Állhat abból, hogy ha teszem azt bioetanolos interaktív táblákat értékesítesz a nagyérdeműnek, akkor kiírod a saját fádra nagy betűvel, hogy “Bioetanolos interaktív táblák eladók.” Meg a témába vágó blogokon reklámozod magad. Meg mindenhol reklámozod magad.Continue reading “Eltévedt SEO az erdőben”

Az Apple kedvelőinek tetszik a Windows 7

Windows 7Hogy ezt hol olvastam? Sehol. Akkor?

Nos, tény, hogy az Apple-centrikus blogok közül csak az AppleInsider írt az új oprendszer bemutatásáról, szépen, tárgyilagosan. A többiek még csak meg sem említették, hogy kinek a mijére hasonlít az új tálca, pedig az ilyenekre rá szoktak harapni. A nagy hallgatásból arra következtetek, hogy tetszik nekik. Ami jó. Nem találnak rajta fogást, ezért nem írnak róla. Azért jó, mert eszerint a Microsoft tanult a hibáiból és egy olyan rendszert hozott össze, ami még nekik is tetszik. Jó dolog ez a verseny, mindenki csak jól jár vele. Éljen az Apple! Éljen a Microsoft!

Continue reading “Az Apple kedvelőinek tetszik a Windows 7”

A Microsoft vezérigazgatója

Nem Bill Gates, ő már nyugdíjas. Steve Ballmer.

Előzmények: A Microsoft I’m a PC reklámkampánya.

http://images.video.msn.com/flash/soapbox1_1.swf

Naszóval ez volt a reklámkampány egyik reklámja. Aztán van egy honlap, ahová fel lehet tölteni videókat amin megmondhatod a világna, hogy te is pécé vagy.

És akkor jön Steve Ballmer, a Microsoft egyes számú legeslegfőbb vezérigazgatója…
http://www.istartedsomething.com/pcview/style/player.swf
Már nem az első eset, hogy kiráz a hideg ettől az embertől…