2012-11-16

Prizma napló #2

A két szemem fókuszpontjainak távolsága kb ötöde szemüvegben, mint szemüveg nélkül. A mérési nehézségekhez képest egész jóra sikerültek a lencsék.

A kilincset egyszer-egyszer még mindig eltévesztem, de már csak pár centivel.

Az autók mozgásával kapcsolatban nincsen a korábban tapasztalt bizonytalanság (amit rögtön nem is írtam le).

A szivárvány effektet már csak nagyon ritka fényviszonyok mellett látom. Cserébe minden egy picit olyan, mintha finoman meg lenne rajzolva a kontúrja.

Eddig még egyszer sem sikerült elfelejtenem, hogy rajtam van, azaz még nem szoktam meg.

2012-11-09

Prizma napló #1

Minden kontúr szivárványos. A szemész hölgy ezen nem lepődött meg. Azt mondta, hogy meg fogom tanulni a szivárvány nem látását.

Vélt vagy valós térélmény javulás

Emlékezetből pontosan fogom a kilincset, látás alapján 10 centit tévedtem elsőre.

Bizonytalan voltam elsőre egy-két tárgy darabszámát illetően.

A szemüveg felvétele és levétele után nem tapasztalom a megjósolt lehetséges tüneteket (több perces átszokási idő, kettős látás, bizonytalan távolság érzékelés)

Szemüveg nélkül a bal szemem a domináns, szemüvegben a jobb.

Prizma napló #0

Körülbelül egy hónapja volt a melóhelyemen egy szemészeti szűrés, amelyen kiderült (csodák csodája), hogy szemtengely ferdülésem van. Nem volt meg a helyszínen minden műszerük ami a paraméterek pontos kiméréséhez szükségesek lettek volna, ezért elhívtak a székesfehérvári bázisukra további vizsgálatokra, amelyre el is mentem.

A színpad úgy néz ki, hogy egy szemésztáblára felfestenek egy szálkeresztet úgy, hogy a függőleges és a vízszintes szár más-más polarizációval látszott, nekem pedig egy olyan szemüveget (szemészeti lencseállványt) adtak amely elé polár-szűrőket helyeztek. Így a bal szememmel csak a függőleges szárat láttam a jobb szememmel csak a vízszinteset.

Ilyenkor jött a belépő mutatvány. Képes vagyok-e az agyammal mindkét szem képét egyszerre látni. Némi játék után a mutatvány sikerült. A körülbelül 5 méterre lévő falon egymástól fél méter távolságra megláttam az ábra két komponensét. Függőleges irányban is volt némi elcsúszás, az eltérés nagyja vízszintesen volt.

Ekkor következett a prizma típusú lencsék cserélgetése, amelyek a szemeimből kiinduló nézést megpróbálták párhuzamosra téríteni (értjük). A függőleges irányú igazítás tökéletessé vált, a vízszintes nem nagyon akart összejönni. Az agyam elutasította azt az ötletet, hogy a bal és a jobb szemem által látott tárgy megegyezik. Amikor a két komponensnek elvileg egymáson kellett volna lennie, akkor a vízszintes komponens el kezdett gyors tempóban ugrálni a függőleges komponens két oldala között.

Az így kimért közelítő értékeket elfogadtuk és felvéstük az adatlapra. Ez alapján elkészíthették számomra azt a szemüveget, amihez ha jól hozzászokom, akkor újabb mérések következhetnek. Ha az agyam tényleg megtanulja a normál emberek látását és sikerül pontosan kimérni a szemtengely ferdülést, akkor az egy műtéttel drasztikusan csökkenthető. Szerencsés esetben meg is szűnhet.

A szemüveget ma vettem át és el is kezdtem hordani. A viccesebb vizuális élményeimet pedig meg is fogom osztani itt a blogon. Meg amúgy is, diagnosztikai szempontból esetleg hasznos lehet, ha naplózva vannak.

2012-04-27

Easy but not too slow integer to string conversion

In my previous post I compared the speed of different methods of converting integer to string. The problem was that these solutions both relied on the environment somehow and cannot be used on an adhoc manner like messages[i] = std::string("Error found at line #") + IntToString(lineNumbers[i]) + ".";. These both need some circumstancial preparation like creating a buffer (char buffer[...]) or a std::stringstream outside the loop and resetting it after usage. So I started on a journey to create a kitchen-ready preparation-less yet not too slow implementation for my imaginary IntToString() function.

#include <iostream>
#include <limits>
#include <sstream>
#define __STDC_FORMAT_MACROS
#include <inttypes.h>

// Utility functions and structs

template<typename Unsigned>
char * DigitsToString(Unsigned i, char * endPtr)
{
    char *&cursor(endPtr);
    *cursor = 0;
    if(!i)
    {
        *--cursor = '0';
        return cursor;
    }
    for(;i;i/=10)
    {
        *--cursor = char(i%10+'0');
    }
    return cursor;
}

template<typename Unsigned>
std::string UnsignedToString(Unsigned i)
{
    const size_t bufsize = std::numeric_limits<Unsigned>::digits10 + 1;
    char buffer[bufsize];
    return DigitsToString(i,buffer+bufsize-1);
}

template<typename Signed>
std::string SignedToString(Signed i)
{
    if(i>=0)
    {
        return UnsignedToString(i);
    }
    const size_t bufsize = std::numeric_limits<Signed>::digits10 + 2;
    char buffer[bufsize];
    char *cursor = DigitsToString(-i,buffer+bufsize-1);
    *--cursor = '-';
    return cursor;
}

template<bool is_signed,typename Integral>
struct ToStringConverter { };

template<typename Integral>
struct ToStringConverter<false,Integral>
{
    static std::string Do(Integral i){ return UnsignedToString(i); }
};

template<typename Integral>
struct ToStringConverter<true,Integral>
{
    static std::string Do(Integral i){ return SignedToString(i); }
};

// The IntToString()

template<typename Integral>
std::string IntToString(Integral i)
{
    return ToStringConverter<std::numeric_limits<Integral>::is_signed,Integral>::Do(i);
}

// Testing my IntToString()

template<typename Integral, Integral count>
void testFun()
{
    for(Integral i=0; i<count; ++i)
    {
        IntToString(i);
    }
}

// An std::stringstream based integer to string conversion

template<typename T>
std::string StreamedToString(const T& i)
{
    std::stringstream ss;
    ss << i;
    return ss.str();
}

// Testing of the std::stringstream based integer to string conversion

template<typename Integral, Integral count>
void testStream()
{
    for(Integral i=0; i<count; ++i)
    {
        StreamedToString(i);
    }
}

#ifndef TEST_CASE
#define TEST_CASE 1
#endif

int main()
{
#if TEST_CASE == 1
    testFun<uint64_t,100*1000*1000>();
#endif
#if TEST_CASE == 2
    testStream<uint64_t,100*1000*1000>();
#endif
    return 0;
}

This is far from being a market-ready product, but it might be useful. Speed test:

$ g++ -W -Wall -Wextra -pedantic -O2 int_to_str_speed2.cpp -DTEST_CASE=1 -o int_to_str_speed2
$ time ./int_to_str_speed2

real    0m12.404s
user    0m12.397s
sys     0m0.008s
$ g++ -W -Wall -Wextra -pedantic -O2 int_to_str_speed2.cpp -DTEST_CASE=2 -o int_to_str_speed2
$ time ./int_to_str_speed2

real    1m36.204s
user    1m36.174s
sys     0m0.008s

Speedy integer to string conversion in C++

Test

This is a log entry about playing around the question. There are robust ways of converting integers to string already implemented out there, for example FastFormat. Good for them. Let's see how I played on my playground.

I measured the speed of sprintf(), snprintf() and my own implementation. I tried to make most of the decisions compile-time. I didn't care to write time measurement into my program, instead I'm using GNU's time utility with three different versions of my program separated using macros.

#include <iostream>
#include <cstdio>
#include <limits>
#define __STDC_FORMAT_MACROS
#include <inttypes.h>

#ifndef TEST_CASE
#define TEST_CASE 1
#endif
#ifndef TESTCOUNT
#define TESTCOUNT 100*1000*1000
#endif
#ifndef INTTYPE
#define INTTYPE uint64_t
#define INTFMT PRIu64
#endif

template<typename Integral>
char *myUIntToStr(Integral i, char *endPtr)
{
    char *&cursor(endPtr);
    if(!i)
    {
        *--cursor='0';
        return cursor;
    }
    for(;i;i/=10)
    {
        *--cursor = char(i%10+'0');
    }
    return cursor;
}

int main()
{
    const size_t BUFSIZE = std::numeric_limits<INTTYPE>::digits10 + 2;
    char buffer[BUFSIZE];
    buffer[BUFSIZE-1] = 0;
#if TEST_CASE == 1
    for(INTTYPE i = 0; i<TESTCOUNT; ++i)
    {
        sprintf(buffer,"%" PRIu64,i);
    }
#endif
#if TEST_CASE == 2
    for(INTTYPE i = 0; i<TESTCOUNT; ++i)
    {
        snprintf(buffer,BUFSIZE,"%" PRIu64,i);
    }
#endif
#if TEST_CASE == 3
    char * const endPtr = buffer + BUFSIZE - 1;
    char * output;
    for(INTTYPE i = 0; i<TESTCOUNT; ++i)
    {
        output = myUIntToStr(i,endPtr);
    }
#endif
#if TEST_CASE == 4
    std::stringstream ss;
    for(INTTYPE i = 0; i<TESTCOUNT; ++i)
    {
        ss << i;
        ss.str(""); // clearing
    }
#endif
    return 0;
}

In many cases the arithmetic correctness of a program or interoperability of a binary format can be achieved by using fixed size integers like uint64_t instead of the fluffy definition of short, int, long, etc.. These fixed size integers are defined in the inttypes.h header file of the C99 standard. I don't know any standard options for this purpose under C++03, so I chose to use this second best solution. I'm using this decision for a while and the time is finally on my side: The C++11 standard includes this header. The defining of __STDC_FORMAT_MACROS before including this header results in the creation of printf() formatters for those types (without the % sign).

In theory this is a portable source code in practice (sic), in practice I haven't tried. This thing is only a proof of a concept.

The original idea for the conversion implementation came from abelenky at a stackoverflow.com question which was about the alternatives to itoa(). I added that the buffer is allocated outside the function on stack (something like for free) and a pointer to its end passed into the function.

Environment

  • OS: Debian (6.0.4 Squeezee) GNU/Linux (2.6.32-5-amd64)
  • G++ 4.4.5
  • CPU: Intel(R) Core(TM)2 CPU 6400 @ 2.13GHz

Results

$ g++ -W -Wall -pedantic -Wextra -O2 -DTEST_CASE=1 sprintf_speed.cpp -o sprintf_speed
$ time ./sprintf_speed

real    0m16.776s
user    0m16.757s
sys     0m0.012s
$ g++ -W -Wall -pedantic -Wextra -O2 -DTEST_CASE=2 sprintf_speed.cpp -o sprintf_speed
$ time ./sprintf_speed

real    0m16.951s
user    0m16.953s
sys     0m0.000s
$ g++ -W -Wall -pedantic -Wextra -O2 -DTEST_CASE=3 sprintf_speed.cpp -o sprintf_speed
$ time ./sprintf_speed

real    0m4.295s
user    0m4.296s
sys     0m0.000s
$ g++ -W -Wall -pedantic -Wextra -O2 -DTEST_CASE=4 sprintf_speed.cpp -o sprintf_speed
$ time ./sprintf_speed

real    0m15.443s
user    0m15.429s
sys     0m0.012s

The difference between the sprintf() and snprintf() version was around 2 to 4 percent consistently in favor of sprintf(). It's unfair to compare these guys to my solution because they also have to parse their given formatter parameter. I believe that my solution is somewhat optimal. The fourth case with std::stringstream is there for reference, that is the clean C++ style portable way for doing the conversion. Surprisingly fast.

2012-03-14

Invoking template constructor of a template class

#include <iostream>
#include <deque>
#include <list>

template<typename T>
class Holder
{
public:
    Holder(){}

    template<typename I>
    Holder(I begin, I end)
      : m_data(begin,end)
    { }
private:
    typedef std::deque<T> Data;
    Data m_data;
};

int main()
{
    std::list<int> ints;
    ints.push_back(3);
    ints.push_back(4);
    ints.push_back(5);

    // Works implicitly:
    Holder<int> HoldedInts(ints.begin(), ints.end());
    Holder<int> *pHI_1 = new Holder<int>(ints.begin(), ints.end());
    delete pHI_1;

    // Does not work explicitly:
    // Holder<int> HoldedInts<std::list<int>::const_iterator>(ints.begin(), ints.end());
    // Holder<int> *pHI_1 = new Holder<int><std::list<int>::const_iterator>(ints.begin(), ints.end());
    // delete pHI_1;

    return 0;
}

2012-03-02

shared_ptr vs inheritance

A picture is worth a thousand words

#include <iostream>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>

class A: public boost::enable_shared_from_this<A>
{
public:
    typedef A Self;
    typedef Self Root;
    typedef boost::shared_ptr<Self> SPtr;

public:
    A(){ std::cerr << "DEBUG: A::A()" << std::endl; }
    virtual ~A(){ std::cerr << "DEBUG: A::~A()" << std::endl; }
    SPtr getSPtr()
    {
        return shared_from_this();
    }
};

class B: public A
{
public:
    typedef B Self;
    typedef A Base;
    typedef Base::Root Root;
    typedef boost::shared_ptr<Self> SPtr;

public:
    B(){ std::cerr << "DEBUG: B::B()" << std::endl; }
    virtual ~B(){ std::cerr << "DEBUG: B::~B()" << std::endl; }
    SPtr getSPtr()
    {
        return boost::dynamic_pointer_cast<Self>(Root::getSPtr());
    }
};

#define CHECKPOINT std::cerr << "CHECKPOINT: " __FILE__ " (" << __LINE__ << ")" << std::endl

int main()
{
    CHECKPOINT;
    A::SPtr spX(new A);
    CHECKPOINT;
    B::SPtr spY(new B);
    CHECKPOINT;

    return 0;
}

Compile!

g++ -W -Wall -Wextra -pedantic -Os shared_vs_inheritance.cpp -o shared_vs_inheritance

Run!

CHECKPOINT: shared_vs_inheritance.cpp (42)
DEBUG: A::A()
CHECKPOINT: shared_vs_inheritance.cpp (44)
DEBUG: A::A()
DEBUG: B::B()
CHECKPOINT: shared_vs_inheritance.cpp (46)
DEBUG: B::~B()
DEBUG: A::~A()
DEBUG: A::~A()