Jeśli w praktyce obliczamy wartości funkcji sinus lub cosinus dla danego kąta, to bardzo często zdarza się, że tak naprawdę potrzebujemy ich obu. Jest tak przy obliczaniu punktów okręgu, przy rozkładzie wektorów sił i jeszcze dla wielu innych okoliczności. Zależy nam naturalnie, aby policzyć to wszystko tak szybko, jak tylko się da, dlatego dobrze jest stosować funkcje w rodzaju sincos, które wyznaczają obie wartości jednocześnie.
Niestety nie każdy język programowania taką funkcję posiada. Mają ją języki shaderowe (GLSL, HLSL i asembler GPU) oraz np. Delphi, ale już nasz ulubiony C++ nie. Można by oczywiście uzupełnić ten brak poprzez taką implementację:
ale chyba nie trzeba nikogo przekonywać, że większego sensu ona nie ma :) Nie występuje tu bowiem żaden zysk na wydajności, bo wartości są obliczane oddzielnie.
Co więc można zrobić? Ano wykorzystać to, co drzemie w jednostce zmiennoprzecinkowej procesora, ale nie jest używane przez wszystkie języki wyższego poziomu. Istnieje mianowicie instrukcja FSINCOS, która wykonuje całą potrzebną “magię”. Należy ją tylko opakować:
Jakkolwiek tajemniczo to może wyglądać, funkcja ta po prostu ładuje argument (kąt) na stos FPU, by potem odebrać wyniki – cosinus i sinus. W przypadku operowania na liczbach typu float
nie ma możliwości podania zbyt dużego/małego argumentu, więc nie trzeba sprawdzać rejestru flag.
I tyle – funkcja mała, acz użyteczna. Asembler czasem się przydaje, proszę państwa ;P
Oto stereotyp typowego programisty: przygarbiony osobnik, koniecznie płci męskiej, z zapałem stukający w klawisze celem produkcji niezrozumiałego wyrobu tekstopodobnego i odchodzący od ekranu tylko w stanach wyższej konieczności. Czy to brzmi znajomo? Być może tak. Nie sądzę jednak, żeby ktokolwiek chciał przypisać sobie taką definicję. Jest ona zresztą zupełnie nieuzasadniona!
Koder bowiem istotą społeczną jest i nie ma co do tego żadnych wątpliwości. Aby sie jednak o tym przekonać, należy ów gatunek zaobserwować w jego naturalnym środowisku – czyli w grupie osób o podobnych zainteresowaniach i pasjach. Wówczas okazuje się, że kod jest jak pewna firma produkująca telefony komórkowe – łączy ludzi :)
Taką okazją są oczywiście wszelkie zloty, zjazdy, konwenty, itp. Nie inaczej jest już od pięciu lat z doroczną konferencją IGK w Siedlcach. Trzeba zresztą przyznać, że słówko ‘konferencja’ pasuje do tej imprezy w stopniu wybitnie zmiennym. Zdarzają się edycje, które rzeczywiście przypominają naukowe konferencje lub (uwaga, trudne słowo) sympozja. Jest tak zwykle wtedy, gdy odpowiednie zareklamowanie imprezy powoduje przyciągnięcie większej liczby uczestników oraz sponsorów, co przekłada się na bogatszą agendę. W skrajnym przypadku mogą to być nawet dwie równoległe sesje referatów, co aczkolwiek zdarzyło się dotąd tylko raz.
Jeśli zaś na miejscu nie pojawia się tłum gości, a plan poszczególnych dni nie jest wypełniony do ostatniej minuty, konferencja nabiera bardziej kameralnego charakteru. W tej kategorii modelowym przykładem jest rzecz jasna pionierska edycja nr 1. W tych latach bardziej ujawnia się ten drugi – oprócz merytorycznego – aspekt konferencji: traktowanie jej przede wszystkim jako spotkania ludzi, którzy na czymś dobrze się znają i oprócz wymiany doświadczeń chcą też dobrze się bawić.
A oto nietrudno, a dzięki szybkiemu rozwojowi techniki jest właściwie coraz prościej :) Weźmy na przykład grupę koderów i umieśćmy ją w sali, której jedynym znaczącym elementem jest duży stół i krzesła. Za parę minut zobaczymy tam skleconą naprędce, lecz działająca bez problemów sieć opartą o switche, crossowane kable, WiFi i co tylko się da. Jakimś magicznym sposobem zawsze przecież znajdzie się jedno gniazdko, jedno miejsce i jeden kawałek skrętki więcej ;-)
Istnieją też bardziej wyrafinowane i zorganizowane formy rozrywki niż zwyczajowe rozgrywki w gry sieciowe. Można na przykład zaaranżować tematyczny quiz, w którym uczestnicy odpowiadają na pytania z dziedziny – a jakże – kodowania oczywiście. Ten pomysł nie jest nowy ani oryginalny – to już prawie tradycja na GDC (Game Developers Conference). Jak się okazało, przeniesienie go na polski grunt okazało się całkiem niezłym posunięciem. Zwłaszcza, że ta zupełnie oddolna inicjatywa została w końcu wsparta przez organizatorów IGK i zrealizowana przy ich pomocy.
I być może za rok zostanie przynajmniej powtórzona, a może nawet nie będzie jedynym tego typu ‘nadobowiązkowym’ wydarzeniem. Bo przecież kodowanie kodowaniem, ale – nie ma co ukrywać – grać też trzeba, prawda? ;]
Jednym z zabawnych aspektów konferencji takich jak IGK jest możliwość spotkania ludzi, których dotąd znaliśmy jedynie za pośrednictwem internetowych form kontaktu, takich jak fora czy komunikatory. Przez ten czas zdążyliśmy zapewne wyrobić sobie jakieś wyobrażenia o tym, kto kryje się pod ciągiem znaków składających się na dany nick. Zależnie od tego, czego te przypuszczenia dotyczą, ich trafność może wahać się od całkiem wysokiej do niemal zerowej.
Zawsze jednak jest to ciekawe przeżycie, a ich mnogość to jeden z argumentów przemawiających za uczestniczeniem w konferencjach w rodzaju IGK :) Przybycie po raz pierwszy na tą imprezę jest często oznaką, że dana osoba zabawi na Warsztacie nieco dłużej, nie zniknie bez śladu i nie straci zainteresowania tematyką programowania gier. Od reguły są oczywiście wyjątki, które, jak wiemy, głównie ją potwierdzają.
Nie da się jednak ukryć, że konferencja – mająca od początku swoje korzenie w pomyśle na “zjazd Warsztatu” – stała się najważniejszym, corocznym wydarzeniem tego community. I fakt, że co roku widzimy na niej nowe – warsztatowe – twarze oznacza, że jako społeczność trzymamy się mimo wszystko całkiem dobrze :)
Niniejszym uważam pakowanie się za oficjalnie zakończone – plus minus pewne drobne szczegóły, rzecz jasna. W tym roku dość sporo okoliczności wydaje się zresztą być przeciwko mojemu bezproblemowemu udziałowi w konferencji IGK. Począwszy od faktu, że od paru dni leczę jakąś zatokowopodobną grypę i kuracja jeszcze trocha potrwa, a skończywszy na tym, że nie będę mógł zjawić na miejscu od samego początku. To z kolei wina uczelni i pewnego “arcyważnego” kolokwium, na którym niestety muszę być :P
I dlatego ominie mnie chociażby tradycyjne zgrupowanie na dworcu Warszawa Wschodnia, skąd zdecydowana większość podróżujących na konferencję dokonywała przesiadki. Pamiętam jeszcze bardzo dobrze, jak niezwykłe było to spotkanie cztery lata temu, podczas pierwszej edycji konferencji… Czasami zazdroszczę tym, którzy pojawią się na niej po raz pierwszy – ale w sumie chyba jednak wolę być “starym wyjadaczem” ;P
Na szczęście moje spóźnienie nie powinno być wielkie ani godne żałowania – w końcu pierwszy dzień to tylko rekla… tj. prezentacje zaproszonych firm :) Bardziej interesujące rzeczy w postaci referatów oraz konkursu Compo są bowiem kwestią następnych dni.
Jak powszechnie wiadomo, obchodzimy dzisiaj tak zwany Prima Aprilis. Dosłownie mówiąc, świętujemy więc fakt, że dzisiejsza data to 1 kwietnia. To oczywiście nie jedyny dziwny akcent tego dnia – na przykład dlatego, iż nie omieszkam przy tej okazji zająć się pewną interesującą oraz dziwną (to słowo zdecydowanie kluczowe) ciekawostką. Chodzi o quines.
Quine to program napisany w dowolnym języku (i nie tylko), którego jedynym zadaniem wyprodukowanie pewnego specyficznego rezultatu. Wypisuje on bowiem na wyjściu… swój własny kod źródłowy. Na pierwszy rzut oka można pomyśleć, że takie programy nie istnieją – albo że wręcz nie mogą istnieć! Bo przecież jeśli kod ma coś wypisywać, to “coś” musi być w tym kodzie zawarte. Czyli każda instrukcja typu print "a"
implikuje konieczność wypisania na wejściu tekstu "print \"a\""
. Ale instrukcja, która ten tekst pokazuje, sama też musi być wyświetlona… Mamy więc print "a"
, print "print \"a\""
, print "print \"print \\\"a\\\"\""
, i tak dalej. Błędne koło!
Lecz quines istnieją. Każdy program tego typu składa się zasadniczo z dwóch części:
#include
, using
, import
, nagłówki funkcji main
i inne podobne konstrukcjeprintf
Krótkim, bo niezawierającym dużej ilości zbędnych śmieci pierwszego typu przykładem jest poniższy quine napisany w Pythonie:
Jak widać, cała treść programu jest zapisana w pojedynczej zmiennej. W miejscu, gdzie w tym “wewnętrznym” kodzie powinna wystąpić wartość owej zmiennej, unikamy sprzężenia zwrotnego poprzez wstawienie znacznika formatującego (czyli %s
). Zostanie on potem zastąpiony dopiero w instrukcji drukującej print a%`a`
(w Pythonie print a%b
to odpowiednik printf(a, b)
z C).
Potrzebny jest jeszcze jeden trik, który pozwoli wypisać cudzysłowy (albo apostrofy) bez konieczności ich espace‘owania (które prowadziłoby do nieskończonego ciągu: "
, \"
, \\\"
, \\\\\\\"
…). Tutaj użyto operatora `
(backtick) specyficznego dla Pythona; inną możliwością jest wydrukowanie cudzysłowu przy pomocy jego kodu ANSI (34).
Widać więc, że quines wcale nie przeczą związkom przyczynowo-skutkowym, następstwu zdarzeń, nie powodują paradoksu dziadka ani zniszczenia Wszechświata :] Oczywiście nie mieszczą się też w nawet najszerzej pojętej kategorii rzeczy przydatnych – ale na dzisiejszą okazję są jak znalazł :)
…i to wielkimi krokami. Mam oczywiście na myśli doroczną konferencję IGK, której piąta już edycja rozpocznie się w Siedlcach już w ten piątek. Wpadł mi właśnie w ręce skrócony informator, który zawiera wiele ciekawych informacji. Są oczywiście podstawowe wiadomości logistyczne związane z tym, jak na miejsce konferencji w ogóle trafić. Te są jednak potrzebne głównie tym, którzy wybierają się tam pierwszy raz; takim wyjadaczom jak ja, stawiającym się na (prawie) każdej edycji, nie są już w ogóle potrzebne :-)
Znacznie bardziej interesujące są tematy referatów, które będzie można usłyszeć na miejscu. Tym razem cztery z nich (czyli więcej niż połowa wszystkich!) będą wygłoszone przez osoby związane z Warsztatem, co mieści się około zwyczajowej średniej. Rarytasem będzie pewnie wykład poprowadzony przez jednego z twórców Wiedźmina, a dokładniej przez głównego projektanta rozgrywki, który opowie o produkcji i projektowaniu gier.
Zatem będzie ciekawie. Już nie mogę się doczekać :)
Niestety, przestrzenie nazw w C++ nie mają takiego wdzięku jak pakiety w Javie czy assemblies w .NET. Zwłaszcza w połączeniu z plikami nagłówkowymi potrafią one sprawić nieco problemów. Jeśli bowiem nie będziemy uważali, to możemy dość łatwo zniwelować korzyści, jakie płyną z ich używania.
Ale po kolei. Jeśli mamy do czynienia z modułem kodu (plikiem .cpp), to możemy bez żadnych skrupułów umieszczać w nim deklaracje using
lub using namespace
. Jeśli tylko nie prowadzi to do niejednoznaczności, wszystko jest w porządku, bowiem zasięg tych deklaracji ogranicza się tylko i wyłącznie do tego jednego pliku.
Gorzej jest niestety z plikami nagłówkowymi. Ponieważ włączane są one tu i ówdzie przy pomocy dyrektywy #include
, nie można tak po prostu wpisywać w nich deklaracji using namespace
. Zostałyby one bowiem rozpropagowane do wszystkich plików, które dany nagłówek włączają, efektywnie niwelując wszelkie korzyści zamknięcia fragmentów kodu w przestrzeń nazw. Bo co to za namespace, który wszyscy “rozpakowują” i przenoszą jego zawartość do przestrzeni globalnej?…
Dlatego nie ma rady: w plikach nagłówkowych można używać wyłącznie nazw kwalifikowanych – poprzedzonych wszystkimi nazwami przestrzeni, jak np. XC::Base::GC::BlockInfo
. W przeciwnym wypadku na pewno zaśmiecimy sobie którąś z przestrzeni (najczęściej globalną) identyfikatorami, które do niej nie należą – co będzie widoczne w systemach podpowiadania takich jak IntelliSense.