marți, 10 ianuarie 2012

Fata nevazuta a template-urilor. Capitolul 3 - Generare de cod.

   Generarea de cod la compilare este mai degraba un subiect cunoscut celor care scriu librarii. Chiar si asa merita dezbatuta problema  generarii din zbor a unor structuri.
    Inainte de toate o structura presupune o succesiune de tipuri de date, cu alte cuvinte avem nevoie de descriptorul structurii dupa care se va produce generarea. In economia template-urilor asta presupune stocarea tipurilor. Ne dorim in cele ce urmeaza sa stocam o serie de campuri, tipuri de forma urmatoare: TYPELIST_X(t1,t2....tx), unde t1,t2...tx sunt tipurile enuntate. Intrucat numarul tipurilor necesare rezolvarii problemei curente nu este cunoscut, singura modalitate si cea mai facila este stocarea tipurilor intr-o list, una cate una. Lucrurile ar arata ceva de genul: TYPELIST_X(t1,t2....tx) = TYPELIST(t1, TYPELIST_X(t1, TYPELIST_X-1(t2,t3....tx)). Nodul unei astfel de liste ar arata astfel:

template<typename H, typename T>
struct Typelist
{
      typedef H Head;
      typedef T Tail;
};

Va fi desigur nevoie si de un terminator de lista. Sa-i spunem struct NullType{}
Iata si cum vom genera o astfel de lista:

#define TYPELIST_1(T1)Typelist<T1,NullType>
#define TYPELIST_2(T1,T2)Typelist<T1,TYPELIST_1(T2) >
#define TYPELIST_3(T1,T2,T3)Typelist<T1,TYPELIST_2(T2,T3) >
#define TYPELIST_4(T1,T2,T3,T4)Typelist<T1,TYPELIST_3(T2,T3,T4) >

De dragul exemplului ne vom opri la o lista cu patru tipuri. Pentru o functionare acoperitoare, definitiile trebuie extinse la X tipuri dorite.
Acum descriptorul poate fi definit. Sa zicem ca vrem o structura care tine coordonatele unui punct (x,y,z).
typedef TYPELIST_4(float,float,float,NullType)  FieldTraits;

Inainte de a trece mai departe avem nevoie de cateva functii ajutatore pentru manevrarea unei astfel de liste.
Determinarea dimensiunii listei
Recusivitatea va crea structurile conform figurii de mai jos. Capul listei va contine constanta cu lungimea listei.

template<typename TList>
struct Length
{
    enum{result = 1 + Length<TList::Tail>::result};
}; 
O specializare care sa opreasca recursivitatea. 
template<>
struct Length<NullType>
{
   enum{result = 0};
};


Numarul structurilor ce se genereaza intern, nu afecteaza consumul de memorie ci doar timpul necesar compilarii si dimensiunea codului. Dat fiind faptul ca lucrurile se petrec la compilare sa zicem ca ne permitem si liste mult mai mari.

Aflarea tipului de la un anumit index

template<typename TList, int i>
struct TypeAt
{
    typedef typename TypeAt<typename TList::Tail, i-1>::result result;
};
Specializarea necesara opririi recursivitatii:

template<typename TList>
struct TypeAt<TList,0>
{
    typedef typename TList::Head result;
};

Aflarea indexului unui anumit tip

Definitia generala:
template<typename TList, typename T> struct IndexOf;

Specializare pentru situatia in care tipul cautat coincide cu capul de lista, adica situatia in care am ajuns pe nodul cautat.
template<typename T, typename TAIL>
struct IndexOf<Typelist<T,TAIL>,T>
{
    enum {result = 0};
};
Specializare pentru situatia in care tipul nu exista in lista(se ajunge pe sfarsitul listei).
template<typename T>
struct IndexOf<NullType,T>
{
    enum {result = -1};//not found
};
Cautarea generala:
template<typename HEAD, typename TAIL, typename T>
struct IndexOf<Typelist<HEAD,TAIL>, T>
{
    enum {temp = IndexOf<TAIL,T>::result } ;
    enum {result = temp==-1? -1 : 1 + temp};
};

Acum ca avem functiile necesare operarii descriptorului unei structuri putem insfarsit sa definim structura. O prima metoda ar fi sa avem o structura ce mosteneste pentru fiecare camp o structura ce detine campul de tipul respectiv, o structura generica de tipul:
template<typename T>
struct Holder{ T value_;}
Daca am avea un descriptor: Typelist(int,float,double,NullType) atunci structura finala ar mosteni clasele: Holder<int>,Holder<float>, Holder<double>, Holder<NullType>. In cazul cu cele trei coordonate, structura va mosteni 3 clase identice de tipul float.
Iata si modul in care se genereaza structura:
template<typename TList, template<class> class Unit>
struct GenStructByInheritance<Typelist<T1,T2>,Unit>
{
       typedef GenStructByInheritance<T1,Unit> left;
       typedef GenStructByInheritance<T2,Unit> right;
 };
template<typename AtomicType, template<class> class Unit>
struct  GenStructByInheritance:public Unit<AtomicType>
{
        typedef Unit<AtomicType> left;
 };

typedef GenStructByInheritance<FieldTraits,Holder> Point3f; 
Inca o functie ajutatoare care de data aceasta ne va ajuta sa accesam campurile structurii : 
template<int N>
typename TypeAt<FieldTraits, N>::result& Field(Point3f& obj)
{
    typedef TypeAt<FieldTraits, N>::result type;
    return ((Holder<type>&) obj).value_;
};
And voila:
Point3f mypoint;
float& x = Field<0>(mypoint);
float& y = Field<1>(mypoint);
float& z = Field<2>(mypoint);

miercuri, 4 ianuarie 2012

Fata nevazuta a template-urilor. Capitolul2 - Detectia pointerilor.

 
   Am spus in tutorialul anterior ca avand doua calificari ale unei structuri template, compilatorul va selecta pe cea mai apropiata dintre ele. Iata un exemplu simplu prin care se va face detectia unui tip pointer.

template<typename T>
struct PointerType
{
    enum{ispointer = false};
};
template<typename T>struct PointerType<T*>
{
    enum{ispointer = true};
};
    Aveti in fata o prima calificare generica ce primeste orice tip inclusiv pointeri si decide in modul default ca tipul nu este pointer si o supracalificare ce va fi utilizata de compilator in cazul in care tipul coincide unui pointer. Se  suprascrie intr-un fel regula anterioara. Iata si testul final:
 bool res = PointerType<int>::ispointer; //FALSE
res = PointerType<int*>::ispointer; //TRUE

marți, 3 ianuarie 2012

Fata nevazuta a template-urilor. Partea 1 - Detectia mostenirilor

    Majoritatea celor ce ajung sa foloseasca template-uri o fac de cele mai multe ori datorita versatilitatii sectiunii de cod/clasa pe care au elaborato. Putini stiu insa fata nevazuta a template-urilor si posibilitatile lor. In acest scurt tutorial o sa va arat cum se face detectia la compilare a relatiilor de legatura/mostenire intre doua clase A si B.
         Se stie ca functia sizeof reuseste sa returneze dimensiunea oricat de complicata ar arata expresia ce ii este trimisa ca argument. Defapt nici nu evalueaza expresia, sa zicem ca pur si simplu foloseste  tipul atasat expresiei.  De aici putem conchide ca si compilatorul stie cate ceva si despre relatiile de mostenire dintre obiecte.
          Vom scrie o clasa  template, ce primeste cele doua tipuri de date si  decide daca exista o relatie de legatura intre cele doua. Mai exact returneaza existenta relatiei U->T.

template<class T, class U>
struct Conversion
{
    typedef char size1;
    typedef struct {
        char dummy[2];
    }size2;
    static T TType;
    static size1 Test(U);
    static size2 Test(...);
public:
    enum{exists = sizeof(Test(TType)) == sizeof(size1), sametype = false};
};
          Clasa declara doua tipuri care sa fie in mod evident diferite ca dimensiune: size1 si size2. Pe langa aceastea, clasa mai vine si cu doua functii Test: una generica ce foloseste puncte de suspensie si returneaza dimensiunea size2 si una explicita ce returneaza dimensiunea size1. Definitiile lor nu sunt necesare fiindca am zis ca functia sizeof " arunca" expresia si returneaza doar tipul. Acuma, daca tipul T este cu adevarat derivat din tipul U, compilatorul  va folosi cea mai calificata functie Test, adica functia Test(U) intrucat compilatorul "stie" ca se poate face downcast de la tipul T la tipul U.  Variabila exists se va dezvolta in sizeof(Test(U)) == sizeof(size1) care este un adevar evident.
         Pe langa asta va trebui sa ne asiguram si ca cele doua tipuri nu sunt identice pentru a putea vorbi de mostenire. Vom face o calificare partiala a clasei pentru situatia asta.

template<class T>
struct Conversion<T,T>
{
    enum{exists = 1, sametype = 1};
};

Iata si testul final:


struct A
{
    int dummy1;
};
struct B:public A
{
    int dummy2[3];
};

bool inheritance = Conversion<B,A>::exists && !Conversion<B,A>::sametype; // TRUE
inheritance = Conversion<B,size_t>::exists && !Conversion<B,A>::sametype; // FALSE

luni, 2 ianuarie 2012

Aplicarea filtrului de culoare degrade

Filtru de culoare sau procesare computerizata? In cele ce urmeaza va voi arata in cativa pasi simpli cum puteti substitui un filtru de culoare degrade folosind ca software de editare Photoshop. Ca imagine de test va propun urmatoarea:


1. Selectati din panoul din dreapta Adjustments->PhotoFilter





2. Selectati din filtrele disponibile Cool Filter(80) si modificati densitatea pana la o valoare multumitoare.

3. Cu layer-ul masca selectat alegeti un gradient liniar  din bara de unelte(unelta Gradient) si trasati o linie verticala de sus in jos astfel incat numai cerul sa fie colorat. Veti obtine astfel o imagine cu un aspect mai rece.


 Daca doriti o colorare uniforma atunci e necesar un filtrul de culoare simplu. Puteti foarte bine realiza acest lucru selectand din meniu Image->Adjustments->PhotoFilter si calibrand in mod analog densitatea.




marți, 14 iunie 2011

In cautarea autohtonului surprinzator

  ZIUA 1 (Moieciu de Jos)

    Cele mai frumoase lucruri vin pe neasteptate si sunt cu atat mai surprinzatoare pe masura ce le prinzi gustul si le descoperi. Iar atunci cand esti convins ca vei avea un concediu monoton intr-o pensiune unde cu greu vei gasi ceva de facut, tocmai atunci lucrurile din jur iti acorda rolul de personaj intr-o tura de documentare geografica.
   Nu mai era nimic de facut, scena era pregatita, bagajul facut asa ca urc in masina pentru un drum ce totaliza 200 km pana in Moieciu de Jos, sat aflat intre masivele Piatra Craiului si Bucegi.
   Descoperim la destinatie o pensiune cocheta cu spatii de relaxare pentru adulti si de joaca pentru cei mici. Pret de cateva zile am fost singurii turisti cazati asa ca ne-am putut odihni in voie.






   Dar cum calatorului ii sade bine cu drumul, ne trezim dupa un somn revigorant de pranz cu gandul de duca. Incercam sa abordam drumul judetean spre Cheile Gradistei. Incercarea a fost zadarnicita de drumul prost, asa ce ne intoarcem la pensiune nu inainte de a fura dupa-amiezii cateva cadre.




   ZIUA 2 (Castelul Bran)

   Desemnam micul dejun ca moment al zilei in care ne planificam destinatia. Aveam cu noi harta muntilor Piatra Craiului, care includea si o harta rutiera pe coperta, ce ne-a servit ca ghid orientativ pentru niste picioare dornice sa oboseasca un pic.
   Hotaram sa incepem vacanta usor, cu o vizita la Castelul Bran situat la vreo 2 km de Moieciu de Jos. Ne intalnim aici cu multi copii neastamparati veniti cu scoala si multi turisti straini, ce par incantati  ca si noi de ceea ce vad.






  ZIUA 3 (Satul Pestera)

   Din Moieciu de Jos urcam cateva serpentine spre satul Pestera, loc unde ne abandonam masina si o luam incetisor la pas spre Pestera Liliecilor. Pe drum, nu pot sa nu remarc ca ne aflam pe un traseu turistic marcat cu cruce rosie ce duce pana in zona La Table prin Valea cu Pietre si Saua Joaca. Traseul pare tocmai bun pentru ciclism montan.







    Pe drum reusim sa ne facem si un prieten, care ne urmeaza cu devotament peste tot.



    O luam pe un drum laturalnic spre pestera, urmati de micul si blanosul nostru prieten care cauta in permanenta umbra.

 

  ZIUA 4 (Cetatea Rasnov si Prapastiile Zarnestilor)

    Ziua a patra ne gaseste un pic mai indrazneti. La fel ca si in zilele precedente parasim pensiunea imediat dupa micul dejun. Destinatia noastra este Rasnov.  Ne deplasam pe drumul cu pretentii de drum european E574, care este plin de petice, fapt ce-ti lasa mereu impresia ca ai facut pana.
   Lasam masina jos in vale si incepem urcusul spre cetate. Cei mai comozi dintre vizitatori opteaza sa urce cu trenuletul delec confortabil pe piatra cubica.



     In interiorul cetatii personaje medievale fac deliciul copiilor. E un loc extraordinar si sper sa se faca eforturi de conservare si restaurare in continuare. Cetatea este plasata pe o veche asezare dacica si cu atat mai mult isi merita cunoscut trecutul.







Orasul Rasnov vazut din cetate



     In cetate exista un turn de veghe din care se poate vedea foarte bine atata masivul Piatra Craiului cat si masivul Bucegi.



Vedere spre Piatra Craiului

Vedere spre Bucegi

   Ne incheiem ziua in Prapastiile Zarnestilor cu putin timp inainte ca ploaia si fulgerele sa se dezlantuie, intr-o atmosfera calma de nori pufosi si miros placut de brad.




  ZIUA 5 (Pestera Fundata sau Pestera Valea Cetatii Rasnov)

    O prezenta statornica de milenii, nestiuta de nimeni pana in 1940 si explorata doar de speologi sau aventurieri pana in decembrie 2010,  pestera Fundata ne primeste pe o ploaie torentiala sa ne dezvaluie secretele. Denumirea a fost schimbata intrucat majoritatea turistilor mergeau in trecut spre localitatea Fundata care este exact in directia opusa.
   Asezata la iesirea din orasul Rasnov, pestera are spatiul de vizitare amenajat in cele mai mici detalii. Jos in vale este amenajata o parcare.



   Vizitarea pesterii presupune urcarea unui drum forestier de 850 m pe drum pietruit, prevazut cu cosuri de gunoi  de o parte si de alta a drumului si  cu toalete publice. Valea joasa, malurile inalte si padurea deasa de foioase de o parte si de alta a vaii creaza un spatiu ireal. Chiar insasi casa de bilete arata ca o casuta din poveste.


 



    Accesul in pestera se face doar in prezenta unui ghid, asta fiindca in trecut turistii au facut ravagii. Stalactite rupte ce zaceau pe podea au fost reconditionate, camioane de gunoaie au fost adunate. Costul total al reamenajarii pesterii a ajuns undeva la 300.000 de euro. Aici, in pestera Fundata, in fiecare sambata are loc un concert de muzica clasica asta fiindca spatiul are o acustica deosebita, nu necesita statii de amplificare si nici nu afecteaza peretii si tavanele pesterii.





     
     In final nu pot sa spun decat ca in cautarea autohtonului ne-am intalnim cu surprinzatorul locurilor. Si aventura abia incepuse,