<commit_before>// @(#)root/test:$Name:  $:$Id: MainEvent.cxx,v 1.8 2001/01/15 01:28:08 rdm Exp $
// Author: Rene Brun   19/01/97

////////////////////////////////////////////////////////////////////////
//
//             A simple example with a ROOT tree
//             =================================
//
//  This program creates :
//    - a ROOT file
//    - a tree
//  Additional arguments can be passed to the program to control the flow
//  of execution. (see comments describing the arguments in the code).
//      Event  nevent comp split fill
//  All arguments are optional: Default is
//      Event  400      1    1     1
//
//  In this example, the tree consists of one single "super branch"
//  The statement ***tree->Branch("event", event, 64000,split);*** below
//  will parse the structure described in Event.h and will make
//  a new branch for each data member of the class if split is set to 1.
//    - 5 branches corresponding to the basic types fNtrack,fNseg,fNvertex
//           ,fFlag and fTemperature.
//    - 3 branches corresponding to the members of the subobject EventHeader.
//    - one branch for each data member of the class Track of TClonesArray.
//    - one branch for the object fH (histogram of class TH1F).
//
//  if split = 0 only one single branch is created and the complete event
//  is serialized in one single buffer.
//  if comp = 0 no compression at all.
//  if comp = 1 event is compressed.
//  if comp = 2 same as 1. In addition branches with floats in the TClonesArray
//                         are also compressed.
//  The 4th argument fill can be set to 0 if one wants to time
//     the percentage of time spent in creating the event structure and
//     not write the event in the file.
//  In this example, one loops over nevent events.
//  The branch "event" is created at the first event.
//  The branch address is set for all other events.
//  For each event, the event header is filled and ntrack tracks
//  are generated and added to the TClonesArray list.
//  For each event the event histogram is saved as well as the list
//  of all tracks.
//
//  The number of events can be given as the first argument to the program.
//  By default 400 events are generated.
//  The compression option can be activated/deactivated via the second argument.
//
//   ---Running/Linking instructions----
//  This program consists of the following files and procedures.
//    - Event.h event class description
//    - Event.C event class implementation
//    - MainEvent.C the main program to demo this class might be used (this file)
//    - EventCint.C  the CINT dictionary for the event and Track classes
//        this file is automatically generated by rootcint (see Makefile),
//        when the class definition in Event.h is modified.
//
//   ---Analyzing the Event.root file with the interactive root
//        example of a simple session
//   Root > TFile f("Event.root")
//   Root > T.Draw("fNtrack")   //histogram the number of tracks per event
//   Root > T.Draw("fPx")       //histogram fPx for all tracks in all events
//   Root > T.Draw("fXfirst:fYfirst","fNtrack>600")
//                              //scatter-plot for x versus y of first point of each track
//   Root > T.Draw("fH.GetRMS()")  //histogram of the RMS of the event histogram
//
//   Look also in the same directory at the following macros:
//     - eventa.C  an example how to read the tree
//     - eventb.C  how to read events conditionally
//
////////////////////////////////////////////////////////////////////////

#include <stdlib.h>

#include "TROOT.h"
#include "TFile.h"
#include "TNetFile.h"
#include "TRandom.h"
#include "TTree.h"
#include "TBranch.h"
#include "TClonesArray.h"
#include "TStopwatch.h"

#include "Event.h"

//______________________________________________________________________________
int main(int argc, char **argv)
{
   TROOT simple("simple","Example of creation of a tree");

   Int_t nevent = 400;     // by default create 400 events
   Int_t comp   = 1;       // by default file is compressed
   Int_t split  = 1;       // by default, split Event in sub branches
   Int_t write  = 1;       // by default the tree is filled
   Int_t hfill  = 0;       // by default histograms are not filled
   Int_t read   = 0;
   Int_t arg4   = 1;
   Int_t arg5   = 600;     //default number of tracks per event
   Int_t netf   = 0;

   if (argc > 1)  nevent = atoi(argv[1]);
   if (argc > 2)  comp   = atoi(argv[2]);
   if (argc > 3)  split  = atoi(argv[3]);
   if (argc > 4)  arg4   = atoi(argv[4]);
   if (argc > 5)  arg5   = atoi(argv[5]);
   if (arg4 ==  0) { write = 0; hfill = 0; read = 1;}
   if (arg4 ==  1) { write = 1; hfill = 0;}
   if (arg4 ==  2) { write = 0; hfill = 0;}
   if (arg4 == 10) { write = 0; hfill = 1;}
   if (arg4 == 11) { write = 1; hfill = 1;}
   if (arg4 == 20) { write = 0; read  = 1;}  //read sequential
   if (arg4 == 25) { write = 0; read  = 2;}  //read random
   if (arg4 >= 30) { netf  = 1; }            //use TNetFile
   if (arg4 == 30) { write = 0; read  = 1;}  //netfile + read sequential
   if (arg4 == 35) { write = 0; read  = 2;}  //netfile + read random
   if (arg4 == 36) { write = 1; }            //netfile + write sequential

   TFile *hfile;
   TTree *tree;
   Event *event = 0;

   // Fill event, header and tracks with some random numbers
   //   Create a timer object to benchmark this loop
   TStopwatch timer;
   timer.Start();
   Int_t nb = 0;
   Int_t ev;
   Int_t bufsize;
   Double_t told = 0;
   Double_t tnew = 0;
   Int_t printev = 100;
   if (arg5 < 100) printev = 1000;
   if (arg5 < 10)  printev = 10000;

   Track::Class()->IgnoreTObjectStreamer();
   Track::Class()->BypassStreamer();

//         Read case
   if (read) {
      if (netf) {
         hfile = new TNetFile("root://localhost/root/test/EventNet.root");
         hfile->UseCache(10);
      } else
         hfile = new TFile("Event.root");
      tree = (TTree*)hfile->Get("T");
      TBranch *branch = tree->GetBranch("event");
      branch->SetAddress(&event);
      Int_t nentries = (Int_t)tree->GetEntries();
      nevent = TMath::Max(nevent,nentries);
      if (read == 1) {  //read sequential
         for (ev = 0; ev < nevent; ev++) {
            if (ev%printev == 0) {
               tnew = timer.RealTime();
               printf("event:%d, rtime=%f s\n",ev,tnew-told);
               told=tnew;
               timer.Continue();
            }
            nb += tree->GetEntry(ev);        //read complete event in memory
         }
      } else {    //read random
         Int_t evrandom;
         for (ev = 0; ev < nevent; ev++) {
            if (ev%printev == 0) cout<<"event="<<ev<<endl;
            evrandom = Int_t(nevent*gRandom->Rndm(1));
            nb += tree->GetEntry(evrandom);  //read complete event in memory
         }
      }
   } else {
//         Write case
      // Create a new ROOT binary machine independent file.
      // Note that this file may contain any kind of ROOT objects, histograms,
      // pictures, graphics objects, detector geometries, tracks, events, etc..
      // This file is now becoming the current directory.
      if (netf) {
         hfile = new TNetFile("root://localhost/root/test/EventNet.root","RECREATE","TTree benchmark ROOT file");
         hfile->UseCache(10);
      } else
         hfile = new TFile("Event.root","RECREATE","TTree benchmark ROOT file");
      hfile->SetCompressionLevel(comp);

     // Create histogram to show write_time in function of time
     Float_t curtime = -0.5;
     Int_t ntime = nevent/printev;
     TH1F *htime = new TH1F("htime","Real-Time to write versus time",ntime,0,ntime);
     HistogramManager *hm = 0;
     if (hfill) {
        TDirectory *hdir = new TDirectory("histograms", "all histograms");
        hm = new HistogramManager(hdir);
     }

     // Create a ROOT Tree and one superbranch
      TTree *tree = new TTree("T","An example of a ROOT tree");
      tree->SetAutoSave(1000000000);  // autosave when 1 Gbyte written
      bufsize = 64000;
      if (split)  bufsize /= 4;
      event = new Event();
      TBranch *branch = tree->Bronch("event", "Event", &event, bufsize,split);
      branch->SetAutoDelete(kFALSE);
      char etype[20];

      for (ev = 0; ev < nevent; ev++) {
         if (ev%printev == 0) {
            tnew = timer.RealTime();
            printf("event:%d, rtime=%f s\n",ev,tnew-told);
            htime->Fill(curtime,tnew-told);
            curtime += 1;
            told=tnew;
            timer.Continue();
         }

         Float_t sigmat, sigmas;
         gRandom->Rannor(sigmat,sigmas);
         Int_t ntrack   = Int_t(arg5 +arg5*sigmat/120.);
         Float_t random = gRandom->Rndm(1);

         sprintf(etype,"type%d",ev%5);
         event->SetType(etype);
         event->SetHeader(ev, 200, 960312, random);
         event->SetNseg(Int_t(10*ntrack+20*sigmas));
         event->SetNvertex(Int_t(1+20*gRandom->Rndm()));
         event->SetFlag(UInt_t(random+0.5));
         event->SetTemperature(random+20.);

         for(UChar_t m = 0; m < 10; m++) {
            event->SetMeasure(m, Int_t(gRandom->Gaus(m,m+1)));
         }
         for(UChar_t i0 = 0; i0 < 4; i0++) {
            for(UChar_t i1 = 0; i1 < 4; i1++) {
               event->SetMatrix(i0,i1,gRandom->Gaus(i0*i1,1));
            }
         }

         //  Create and Fill the Track objects
         for (Int_t t = 0; t < ntrack; t++) event->AddTrack(random);

         if (write) nb += tree->Fill();  //fill the tree

         if (hm) hm->Hfill(event);      //fill histograms

         event->Clear();
      }
      if (write) {
         hfile->Write();
         tree->Print();
      }
   }

   //  Stop timer and print results
   timer.Stop();
   Float_t mbytes = 0.000001*nb;
   Double_t rtime = timer.RealTime();
   Double_t ctime = timer.CpuTime();

   printf("\n%d events and %d bytes processed.\n",nevent,nb);
   printf("RealTime=%f seconds, CpuTime=%f seconds\n",rtime,ctime);
   if (read) {
      printf("You read %f Mbytes/Realtime seconds\n",mbytes/rtime);
      printf("You read %f Mbytes/Cputime seconds\n",mbytes/ctime);
   } else {
      printf("compression level=%d, split=%d, arg4=%d\n",comp,split,arg4);
      printf("You write %f Mbytes/Realtime seconds\n",mbytes/rtime);
      printf("You write %f Mbytes/Cputime seconds\n",mbytes/ctime);
      //printf("file compression factor = %f\n",hfile.GetCompressionFactor());
   }
   hfile->Close();
   return 0;
}
<commit_msg>A wrong version of MainEvent was checked in..<commit_after>// @(#)root/test:$Name:  $:$Id: MainEvent.cxx,v 1.9 2001/02/09 10:24:46 brun Exp $
// Author: Rene Brun   19/01/97

////////////////////////////////////////////////////////////////////////
//
//             A simple example with a ROOT tree
//             =================================
//
//  This program creates :
//    - a ROOT file
//    - a tree
//  Additional arguments can be passed to the program to control the flow
//  of execution. (see comments describing the arguments in the code).
//      Event  nevent comp split fill
//  All arguments are optional: Default is
//      Event  400      1    1     1
//
//  In this example, the tree consists of one single "super branch"
//  The statement ***tree->Branch("event", event, 64000,split);*** below
//  will parse the structure described in Event.h and will make
//  a new branch for each data member of the class if split is set to 1.
//    - 5 branches corresponding to the basic types fNtrack,fNseg,fNvertex
//           ,fFlag and fTemperature.
//    - 3 branches corresponding to the members of the subobject EventHeader.
//    - one branch for each data member of the class Track of TClonesArray.
//    - one branch for the object fH (histogram of class TH1F).
//
//  if split = 0 only one single branch is created and the complete event
//  is serialized in one single buffer.
//  if comp = 0 no compression at all.
//  if comp = 1 event is compressed.
//  if comp = 2 same as 1. In addition branches with floats in the TClonesArray
//                         are also compressed.
//  The 4th argument fill can be set to 0 if one wants to time
//     the percentage of time spent in creating the event structure and
//     not write the event in the file.
//  In this example, one loops over nevent events.
//  The branch "event" is created at the first event.
//  The branch address is set for all other events.
//  For each event, the event header is filled and ntrack tracks
//  are generated and added to the TClonesArray list.
//  For each event the event histogram is saved as well as the list
//  of all tracks.
//
//  The number of events can be given as the first argument to the program.
//  By default 400 events are generated.
//  The compression option can be activated/deactivated via the second argument.
//
//   ---Running/Linking instructions----
//  This program consists of the following files and procedures.
//    - Event.h event class description
//    - Event.C event class implementation
//    - MainEvent.C the main program to demo this class might be used (this file)
//    - EventCint.C  the CINT dictionary for the event and Track classes
//        this file is automatically generated by rootcint (see Makefile),
//        when the class definition in Event.h is modified.
//
//   ---Analyzing the Event.root file with the interactive root
//        example of a simple session
//   Root > TFile f("Event.root")
//   Root > T.Draw("fNtrack")   //histogram the number of tracks per event
//   Root > T.Draw("fPx")       //histogram fPx for all tracks in all events
//   Root > T.Draw("fXfirst:fYfirst","fNtrack>600")
//                              //scatter-plot for x versus y of first point of each track
//   Root > T.Draw("fH.GetRMS()")  //histogram of the RMS of the event histogram
//
//   Look also in the same directory at the following macros:
//     - eventa.C  an example how to read the tree
//     - eventb.C  how to read events conditionally
//
////////////////////////////////////////////////////////////////////////

#include <stdlib.h>

#include "TROOT.h"
#include "TFile.h"
#include "TNetFile.h"
#include "TRandom.h"
#include "TTree.h"
#include "TBranch.h"
#include "TClonesArray.h"
#include "TStopwatch.h"

#include "Event.h"

//______________________________________________________________________________
int main(int argc, char **argv)
{
   TROOT simple("simple","Example of creation of a tree");

   Int_t nevent = 400;     // by default create 400 events
   Int_t comp   = 1;       // by default file is compressed
   Int_t split  = 1;       // by default, split Event in sub branches
   Int_t write  = 1;       // by default the tree is filled
   Int_t hfill  = 0;       // by default histograms are not filled
   Int_t read   = 0;
   Int_t arg4   = 1;
   Int_t arg5   = 600;     //default number of tracks per event
   Int_t netf   = 0;

   if (argc > 1)  nevent = atoi(argv[1]);
   if (argc > 2)  comp   = atoi(argv[2]);
   if (argc > 3)  split  = atoi(argv[3]);
   if (argc > 4)  arg4   = atoi(argv[4]);
   if (argc > 5)  arg5   = atoi(argv[5]);
   if (arg4 ==  0) { write = 0; hfill = 0; read = 1;}
   if (arg4 ==  1) { write = 1; hfill = 0;}
   if (arg4 ==  2) { write = 0; hfill = 0;}
   if (arg4 == 10) { write = 0; hfill = 1;}
   if (arg4 == 11) { write = 1; hfill = 1;}
   if (arg4 == 20) { write = 0; read  = 1;}  //read sequential
   if (arg4 == 25) { write = 0; read  = 2;}  //read random
   if (arg4 >= 30) { netf  = 1; }            //use TNetFile
   if (arg4 == 30) { write = 0; read  = 1;}  //netfile + read sequential
   if (arg4 == 35) { write = 0; read  = 2;}  //netfile + read random
   if (arg4 == 36) { write = 1; }            //netfile + write sequential

   TFile *hfile;
   TTree *tree;
   Event *event = 0;

   // Fill event, header and tracks with some random numbers
   //   Create a timer object to benchmark this loop
   TStopwatch timer;
   timer.Start();
   Int_t nb = 0;
   Int_t ev;
   Int_t bufsize;
   Double_t told = 0;
   Double_t tnew = 0;
   Int_t printev = 100;
   if (arg5 < 100) printev = 1000;
   if (arg5 < 10)  printev = 10000;

   Track::Class()->IgnoreTObjectStreamer();
   Track::Class()->BypassStreamer();

//         Read case
   if (read) {
      if (netf) {
         hfile = new TNetFile("root://localhost/root/test/EventNet.root");
         hfile->UseCache(10);
      } else
         hfile = new TFile("Event.root");
      tree = (TTree*)hfile->Get("T");
      TBranch *branch = tree->GetBranch("event");
      branch->SetAddress(&event);
      Int_t nentries = (Int_t)tree->GetEntries();
      nevent = TMath::Max(nevent,nentries);
      if (read == 1) {  //read sequential
         for (ev = 0; ev < nevent; ev++) {
            if (ev%printev == 0) {
               tnew = timer.RealTime();
               printf("event:%d, rtime=%f s\n",ev,tnew-told);
               told=tnew;
               timer.Continue();
            }
            nb += tree->GetEntry(ev);        //read complete event in memory
         }
      } else {    //read random
         Int_t evrandom;
         for (ev = 0; ev < nevent; ev++) {
            if (ev%printev == 0) cout<<"event="<<ev<<endl;
            evrandom = Int_t(nevent*gRandom->Rndm(1));
            nb += tree->GetEntry(evrandom);  //read complete event in memory
         }
      }
   } else {
//         Write case
      // Create a new ROOT binary machine independent file.
      // Note that this file may contain any kind of ROOT objects, histograms,
      // pictures, graphics objects, detector geometries, tracks, events, etc..
      // This file is now becoming the current directory.
      if (netf) {
         hfile = new TNetFile("root://localhost/root/test/EventNet.root","RECREATE","TTree benchmark ROOT file");
         hfile->UseCache(10);
      } else
         hfile = new TFile("Event.root","RECREATE","TTree benchmark ROOT file");
      hfile->SetCompressionLevel(comp);

     // Create histogram to show write_time in function of time
     Float_t curtime = -0.5;
     Int_t ntime = nevent/printev;
     TH1F *htime = new TH1F("htime","Real-Time to write versus time",ntime,0,ntime);
     HistogramManager *hm = 0;
     if (hfill) {
        TDirectory *hdir = new TDirectory("histograms", "all histograms");
        hm = new HistogramManager(hdir);
     }

     // Create a ROOT Tree and one superbranch
      TTree *tree = new TTree("T","An example of a ROOT tree");
      tree->SetAutoSave(1000000000);  // autosave when 1 Gbyte written
      bufsize = 64000;
      if (split)  bufsize /= 4;
      event = new Event();
      TBranch *branch = tree->Branch("event", "Event", &event, bufsize,split);
      branch->SetAutoDelete(kFALSE);
      char etype[20];

      for (ev = 0; ev < nevent; ev++) {
         if (ev%printev == 0) {
            tnew = timer.RealTime();
            printf("event:%d, rtime=%f s\n",ev,tnew-told);
            htime->Fill(curtime,tnew-told);
            curtime += 1;
            told=tnew;
            timer.Continue();
         }

         Float_t sigmat, sigmas;
         gRandom->Rannor(sigmat,sigmas);
         Int_t ntrack   = Int_t(arg5 +arg5*sigmat/120.);
         Float_t random = gRandom->Rndm(1);

         sprintf(etype,"type%d",ev%5);
         event->SetType(etype);
         event->SetHeader(ev, 200, 960312, random);
         event->SetNseg(Int_t(10*ntrack+20*sigmas));
         event->SetNvertex(Int_t(1+20*gRandom->Rndm()));
         event->SetFlag(UInt_t(random+0.5));
         event->SetTemperature(random+20.);

         for(UChar_t m = 0; m < 10; m++) {
            event->SetMeasure(m, Int_t(gRandom->Gaus(m,m+1)));
         }
         for(UChar_t i0 = 0; i0 < 4; i0++) {
            for(UChar_t i1 = 0; i1 < 4; i1++) {
               event->SetMatrix(i0,i1,gRandom->Gaus(i0*i1,1));
            }
         }

         //  Create and Fill the Track objects
         for (Int_t t = 0; t < ntrack; t++) event->AddTrack(random);

         if (write) nb += tree->Fill();  //fill the tree

         if (hm) hm->Hfill(event);      //fill histograms

         event->Clear();
      }
      if (write) {
         hfile->Write();
         tree->Print();
      }
   }

   //  Stop timer and print results
   timer.Stop();
   Float_t mbytes = 0.000001*nb;
   Double_t rtime = timer.RealTime();
   Double_t ctime = timer.CpuTime();

   printf("\n%d events and %d bytes processed.\n",nevent,nb);
   printf("RealTime=%f seconds, CpuTime=%f seconds\n",rtime,ctime);
   if (read) {
      printf("You read %f Mbytes/Realtime seconds\n",mbytes/rtime);
      printf("You read %f Mbytes/Cputime seconds\n",mbytes/ctime);
   } else {
      printf("compression level=%d, split=%d, arg4=%d\n",comp,split,arg4);
      printf("You write %f Mbytes/Realtime seconds\n",mbytes/rtime);
      printf("You write %f Mbytes/Cputime seconds\n",mbytes/ctime);
      //printf("file compression factor = %f\n",hfile.GetCompressionFactor());
   }
   hfile->Close();
   return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2001,2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * $Id$
 */

#if !defined(UNION_DATATYPEVALIDATOR_HPP)
#define UNION_DATATYPEVALIDATOR_HPP

#include <xercesc/validators/datatype/DatatypeValidator.hpp>

XERCES_CPP_NAMESPACE_BEGIN

class VALIDATORS_EXPORT UnionDatatypeValidator : public DatatypeValidator
{
public:

    // -----------------------------------------------------------------------
    //  Public ctor/dtor
    // -----------------------------------------------------------------------
	/** @name Constructors and Destructor. */
    //@{

    UnionDatatypeValidator
    (
        MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
    );

    //
    // constructor for native Union datatype validator
    // <simpleType name="nativeUnion">
    //      <union   memberTypes="member1 member2 ...">
    // </simpleType>
    //
    UnionDatatypeValidator
    (
        RefVectorOf<DatatypeValidator>* const memberTypeValidators
        , const int finalSet
        , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
    );

    //
    // constructor for derived Union datatype validator
    // <simpleType name="derivedUnion">
    //      <restriction base="nativeUnion">
    //          <pattern     value="patter_value"/>
    //          <enumeration value="enum_value"/>
    //      </restriction>
    // </simpleType>
    //
    UnionDatatypeValidator
    (
        DatatypeValidator* const baseValidator
        , RefHashTableOf<KVStringPair>* const facets
        , RefArrayVectorOf<XMLCh>* const enums
        , const int finalSet
        , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
        , RefVectorOf<DatatypeValidator>* const memberTypeValidators = 0
        , const bool memberTypesInherited = true
    );

    virtual ~UnionDatatypeValidator();

	//@}

	virtual const RefArrayVectorOf<XMLCh>* getEnumString() const;

    // -----------------------------------------------------------------------
    // Getter methods
    // -----------------------------------------------------------------------
    /** @name Getter Functions */
    //@{
    /**
      * Returns whether the type is atomic or not
      */
    virtual bool isAtomic() const;

    virtual const XMLCh* getCanonicalRepresentation
                        (
                          const XMLCh*         const rawData
                        ,       MemoryManager* const memMgr = 0
                        ,       bool                 toValidate = false
                        ) const;

    //@}

    // -----------------------------------------------------------------------
    // Validation methods
    // -----------------------------------------------------------------------
    /** @name Validation Function */
    //@{

    /**
     * validate that a string matches the boolean datatype
     * @param content A string containing the content to be validated
     *
     * @exception throws InvalidDatatypeException if the content is
     * is not valid.
     */

	virtual void validate
                 (
                  const XMLCh*             const content
                ,       ValidationContext* const context = 0
                ,       MemoryManager*     const manager = XMLPlatformUtils::fgMemoryManager
                  );

    /**
      * Checks whether a given type can be used as a substitute
      *
      * @param  toCheck    A datatype validator of the type to be used as a
      *                    substitute
      *
      * To be redefined in UnionDatatypeValidator
      */

    virtual bool isSubstitutableBy(const DatatypeValidator* const toCheck);

    //@}

    // -----------------------------------------------------------------------
    // Compare methods
    // -----------------------------------------------------------------------
    /** @name Compare Function */
    //@{

    /**
     * Compare two boolean data types
     *
     * @param content1
     * @param content2
     * @return
     */
    int compare(const XMLCh* const, const XMLCh* const
        , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
        );

    //@}

    /**
      * Returns an instance of the base datatype validator class
	  * Used by the DatatypeValidatorFactory.
      */
    virtual DatatypeValidator* newInstance
    (
        RefHashTableOf<KVStringPair>* const facets
        , RefArrayVectorOf<XMLCh>* const enums
        , const int finalSet
        , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
    );

    /***
     * Support for Serialization/De-serialization
     ***/
    DECL_XSERIALIZABLE(UnionDatatypeValidator)

    RefVectorOf<DatatypeValidator>* getMemberTypeValidators() const;

private:
    // -----------------------------------------------------------------------
    //  Unimplemented constructors and operators
    // -----------------------------------------------------------------------
    UnionDatatypeValidator(const UnionDatatypeValidator&);
    UnionDatatypeValidator& operator=(const UnionDatatypeValidator&);

    virtual void checkContent(const XMLCh*             const content
                            ,       ValidationContext* const context
                            , bool                           asBase
                            ,       MemoryManager*     const manager);

    void init(DatatypeValidator*            const baseValidator
            , RefHashTableOf<KVStringPair>* const facets
            , RefArrayVectorOf<XMLCh>*      const enums
            , MemoryManager*                const manager);

    void cleanUp();

    RefArrayVectorOf<XMLCh>*  getEnumeration() const;

    void                 setEnumeration(RefArrayVectorOf<XMLCh>*, bool);

    // -----------------------------------------------------------------------
    //  Private data members
    //
    //  fEnumeration
    //      we own it (or not, depending on state of fEnumerationInherited).
    //
    //  fMemberTypeValidators
    //      we own it (or not, depending on the state of fMemberTypesInherited).
    //
    // -----------------------------------------------------------------------

     bool                             fEnumerationInherited;
     bool                             fMemberTypesInherited;
     RefArrayVectorOf<XMLCh>*         fEnumeration;
     RefVectorOf<DatatypeValidator>*  fMemberTypeValidators;
};

inline DatatypeValidator* UnionDatatypeValidator::newInstance
(
      RefHashTableOf<KVStringPair>* const facets
    , RefArrayVectorOf<XMLCh>* const      enums
    , const int                           finalSet
    , MemoryManager* const                manager
)
{
    return (DatatypeValidator*) new (manager) UnionDatatypeValidator(this, facets, enums, finalSet, manager, fMemberTypeValidators, true);
}

inline void UnionDatatypeValidator::validate( const XMLCh*             const content
                                           ,        ValidationContext* const context
                                           ,        MemoryManager*     const manager)
{
    checkContent(content, context, false, manager);
}

inline void UnionDatatypeValidator::cleanUp()
{
    //~RefVectorOf will delete all adopted elements
    if ( !fEnumerationInherited && fEnumeration)
        delete fEnumeration;

    if (!fMemberTypesInherited && fMemberTypeValidators)
        delete fMemberTypeValidators;

}

inline RefArrayVectorOf<XMLCh>* UnionDatatypeValidator:: getEnumeration() const
{
    return fEnumeration;
}

inline void UnionDatatypeValidator::setEnumeration(RefArrayVectorOf<XMLCh>* enums
                                                 , bool                inherited)
{
    if (enums)
    {
        if (  !fEnumerationInherited && fEnumeration)
            delete fEnumeration;

        fEnumeration = enums;
        fEnumerationInherited = inherited;
        setFacetsDefined(DatatypeValidator::FACET_ENUMERATION);
    }
}

//
// get the native UnionDTV's fMemberTypeValidators
//
inline
RefVectorOf<DatatypeValidator>* UnionDatatypeValidator::getMemberTypeValidators() const
{
    return this->fMemberTypeValidators;
}

inline bool UnionDatatypeValidator::isAtomic() const {

    if (!fMemberTypeValidators) {
        return false;
    }

    unsigned int memberSize = fMemberTypeValidators->size();

    for (unsigned int i=0; i < memberSize; i++) {
        if (!fMemberTypeValidators->elementAt(i)->isAtomic()) {
            return false;
        }
    }

    return true;
}

inline bool UnionDatatypeValidator::isSubstitutableBy(const DatatypeValidator* const toCheck) {

    if (toCheck == this) {
        return true;
    }

    if (fMemberTypeValidators) {
        unsigned int memberSize = fMemberTypeValidators->size();

        for (unsigned int i=0; i < memberSize; i++) {

            if (fMemberTypeValidators->elementAt(i)->getType() == DatatypeValidator::Union)
                return false;
            if (fMemberTypeValidators->elementAt(i)->isSubstitutableBy(toCheck)) {
                return true;
            }
        }
    }
    return false;
}

XERCES_CPP_NAMESPACE_END

#endif

/**
  * End of file UnionDatatypeValidator.hpp
  */

<commit_msg>Schema fixes for union of union.<commit_after>/*
 * Copyright 2001,2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * $Id$
 */

#if !defined(UNION_DATATYPEVALIDATOR_HPP)
#define UNION_DATATYPEVALIDATOR_HPP

#include <xercesc/validators/datatype/DatatypeValidator.hpp>

XERCES_CPP_NAMESPACE_BEGIN

class VALIDATORS_EXPORT UnionDatatypeValidator : public DatatypeValidator
{
public:

    // -----------------------------------------------------------------------
    //  Public ctor/dtor
    // -----------------------------------------------------------------------
	/** @name Constructors and Destructor. */
    //@{

    UnionDatatypeValidator
    (
        MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
    );

    //
    // constructor for native Union datatype validator
    // <simpleType name="nativeUnion">
    //      <union   memberTypes="member1 member2 ...">
    // </simpleType>
    //
    UnionDatatypeValidator
    (
        RefVectorOf<DatatypeValidator>* const memberTypeValidators
        , const int finalSet
        , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
    );

    //
    // constructor for derived Union datatype validator
    // <simpleType name="derivedUnion">
    //      <restriction base="nativeUnion">
    //          <pattern     value="patter_value"/>
    //          <enumeration value="enum_value"/>
    //      </restriction>
    // </simpleType>
    //
    UnionDatatypeValidator
    (
        DatatypeValidator* const baseValidator
        , RefHashTableOf<KVStringPair>* const facets
        , RefArrayVectorOf<XMLCh>* const enums
        , const int finalSet
        , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
        , RefVectorOf<DatatypeValidator>* const memberTypeValidators = 0
        , const bool memberTypesInherited = true
    );

    virtual ~UnionDatatypeValidator();

	//@}

	virtual const RefArrayVectorOf<XMLCh>* getEnumString() const;

    // -----------------------------------------------------------------------
    // Getter methods
    // -----------------------------------------------------------------------
    /** @name Getter Functions */
    //@{
    /**
      * Returns whether the type is atomic or not
      */
    virtual bool isAtomic() const;

    virtual const XMLCh* getCanonicalRepresentation
                        (
                          const XMLCh*         const rawData
                        ,       MemoryManager* const memMgr = 0
                        ,       bool                 toValidate = false
                        ) const;

    //@}

    // -----------------------------------------------------------------------
    // Validation methods
    // -----------------------------------------------------------------------
    /** @name Validation Function */
    //@{

    /**
     * validate that a string matches the boolean datatype
     * @param content A string containing the content to be validated
     *
     * @exception throws InvalidDatatypeException if the content is
     * is not valid.
     */

	virtual void validate
                 (
                  const XMLCh*             const content
                ,       ValidationContext* const context = 0
                ,       MemoryManager*     const manager = XMLPlatformUtils::fgMemoryManager
                  );

    /**
      * Checks whether a given type can be used as a substitute
      *
      * @param  toCheck    A datatype validator of the type to be used as a
      *                    substitute
      *
      * To be redefined in UnionDatatypeValidator
      */

    virtual bool isSubstitutableBy(const DatatypeValidator* const toCheck);

    //@}

    // -----------------------------------------------------------------------
    // Compare methods
    // -----------------------------------------------------------------------
    /** @name Compare Function */
    //@{

    /**
     * Compare two boolean data types
     *
     * @param content1
     * @param content2
     * @return
     */
    int compare(const XMLCh* const, const XMLCh* const
        , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
        );

    //@}

    /**
      * Returns an instance of the base datatype validator class
	  * Used by the DatatypeValidatorFactory.
      */
    virtual DatatypeValidator* newInstance
    (
        RefHashTableOf<KVStringPair>* const facets
        , RefArrayVectorOf<XMLCh>* const enums
        , const int finalSet
        , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
    );

    /***
     * Support for Serialization/De-serialization
     ***/
    DECL_XSERIALIZABLE(UnionDatatypeValidator)

    RefVectorOf<DatatypeValidator>* getMemberTypeValidators() const;

private:
    // -----------------------------------------------------------------------
    //  Unimplemented constructors and operators
    // -----------------------------------------------------------------------
    UnionDatatypeValidator(const UnionDatatypeValidator&);
    UnionDatatypeValidator& operator=(const UnionDatatypeValidator&);

    virtual void checkContent(const XMLCh*             const content
                            ,       ValidationContext* const context
                            , bool                           asBase
                            ,       MemoryManager*     const manager);

    void init(DatatypeValidator*            const baseValidator
            , RefHashTableOf<KVStringPair>* const facets
            , RefArrayVectorOf<XMLCh>*      const enums
            , MemoryManager*                const manager);

    void cleanUp();

    RefArrayVectorOf<XMLCh>*  getEnumeration() const;

    void                 setEnumeration(RefArrayVectorOf<XMLCh>*, bool);

    // -----------------------------------------------------------------------
    //  Private data members
    //
    //  fEnumeration
    //      we own it (or not, depending on state of fEnumerationInherited).
    //
    //  fMemberTypeValidators
    //      we own it (or not, depending on the state of fMemberTypesInherited).
    //
    // -----------------------------------------------------------------------

     bool                             fEnumerationInherited;
     bool                             fMemberTypesInherited;
     RefArrayVectorOf<XMLCh>*         fEnumeration;
     RefVectorOf<DatatypeValidator>*  fMemberTypeValidators;
};

inline DatatypeValidator* UnionDatatypeValidator::newInstance
(
      RefHashTableOf<KVStringPair>* const facets
    , RefArrayVectorOf<XMLCh>* const      enums
    , const int                           finalSet
    , MemoryManager* const                manager
)
{
    return (DatatypeValidator*) new (manager) UnionDatatypeValidator(this, facets, enums, finalSet, manager, fMemberTypeValidators, true);
}

inline void UnionDatatypeValidator::validate( const XMLCh*             const content
                                           ,        ValidationContext* const context
                                           ,        MemoryManager*     const manager)
{
    checkContent(content, context, false, manager);
}

inline void UnionDatatypeValidator::cleanUp()
{
    //~RefVectorOf will delete all adopted elements
    if ( !fEnumerationInherited && fEnumeration)
        delete fEnumeration;

    if (!fMemberTypesInherited && fMemberTypeValidators)
        delete fMemberTypeValidators;

}

inline RefArrayVectorOf<XMLCh>* UnionDatatypeValidator:: getEnumeration() const
{
    return fEnumeration;
}

inline void UnionDatatypeValidator::setEnumeration(RefArrayVectorOf<XMLCh>* enums
                                                 , bool                inherited)
{
    if (enums)
    {
        if (  !fEnumerationInherited && fEnumeration)
            delete fEnumeration;

        fEnumeration = enums;
        fEnumerationInherited = inherited;
        setFacetsDefined(DatatypeValidator::FACET_ENUMERATION);
    }
}

//
// get the native UnionDTV's fMemberTypeValidators
//
inline
RefVectorOf<DatatypeValidator>* UnionDatatypeValidator::getMemberTypeValidators() const
{
    return this->fMemberTypeValidators;
}

inline bool UnionDatatypeValidator::isAtomic() const {

    if (!fMemberTypeValidators) {
        return false;
    }

    unsigned int memberSize = fMemberTypeValidators->size();

    for (unsigned int i=0; i < memberSize; i++) {
        if (!fMemberTypeValidators->elementAt(i)->isAtomic()) {
            return false;
        }
    }

    return true;
}

inline bool UnionDatatypeValidator::isSubstitutableBy(const DatatypeValidator* const toCheck) {

    if (toCheck == this) {
        return true;
    }

    if (fMemberTypeValidators) {
        unsigned int memberSize = fMemberTypeValidators->size();

        for (unsigned int i=0; i < memberSize; i++) {
            if ((fMemberTypeValidators->elementAt(i)->getType() == DatatypeValidator::Union) &&
                (fMemberTypeValidators->elementAt(i) == toCheck))
                return false;
            if (fMemberTypeValidators->elementAt(i)->isSubstitutableBy(toCheck)) {
                return true;
            }
        }
    }
    return false;
}

XERCES_CPP_NAMESPACE_END

#endif

/**
  * End of file UnionDatatypeValidator.hpp
  */

<|endoftext|>


<commit_before>// dear imgui, v1.50 WIP
// (demo code)

// Message to the person tempted to delete this file when integrating ImGui into their code base:
// Do NOT remove this file from your project! It is useful reference code that you and other users will want to refer to.
// Everything in this file will be stripped out by the linker if you don't call ImGui::ShowTestWindow().
// During development, you can call ImGui::ShowTestWindow() in your code to learn about various features of ImGui.
// Removing this file from your project is hindering your access to documentation, likely leading you to poorer usage of the library.

#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif

#include "imgui.h"
#include <ctype.h>          // toupper, isprint
#include <math.h>           // sqrtf, powf, cosf, sinf, floorf, ceilf
#include <stdio.h>          // vsnprintf, sscanf, printf
#include <stdlib.h>         // NULL, malloc, free, qsort, atoi
#include <windows.h>
#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
#include <stddef.h>         // intptr_t
#else
#include <stdint.h>         // intptr_t
#endif

#ifdef _MSC_VER
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
#define snprintf _snprintf
#endif
#ifdef __clang__
#pragma clang diagnostic ignored "-Wold-style-cast"             // warning : use of old-style cast                              // yes, they are more terse.
#pragma clang diagnostic ignored "-Wdeprecated-declarations"    // warning : 'xx' is deprecated: The POSIX name for this item.. // for strdup used in demo code (so user can copy & paste the code)
#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast"   // warning : cast to 'void *' from smaller integer type 'int'
#pragma clang diagnostic ignored "-Wformat-security"            // warning : warning: format string is not a string literal
#pragma clang diagnostic ignored "-Wexit-time-destructors"      // warning : declaration requires an exit-time destructor       // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals.
#if __has_warning("-Wreserved-id-macro")
#pragma clang diagnostic ignored "-Wreserved-id-macro"          // warning : macro name is a reserved identifier                //
#endif
#elif defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"          // warning: cast to pointer from integer of different size
#pragma GCC diagnostic ignored "-Wformat-security"              // warning : format string is not a string literal (potentially insecure)
#pragma GCC diagnostic ignored "-Wdouble-promotion"             // warning: implicit conversion from 'float' to 'double' when passing argument to function
#pragma GCC diagnostic ignored "-Wconversion"                   // warning: conversion to 'xxxx' from 'xxxx' may alter its value
#if (__GNUC__ >= 6)
#pragma GCC diagnostic ignored "-Wmisleading-indentation"       // warning: this 'if' clause does not guard this statement      // GCC 6.0+ only. See #883 on github.
#endif
#endif

// Play it nice with Windows users. Notepad in 2015 still doesn't display text data with Unix-style \n.
#ifdef _WIN32
#define IM_NEWLINE "\r\n"
#else
#define IM_NEWLINE "\n"
#endif

#define IM_ARRAYSIZE(_ARR)  ((int)(sizeof(_ARR)/sizeof(*_ARR)))
#define IM_MAX(_A,_B)       (((_A) >= (_B)) ? (_A) : (_B))

//-----------------------------------------------------------------------------
// DEMO CODE
//-----------------------------------------------------------------------------

#ifndef IMGUI_DISABLE_TEST_WINDOWS

//EJEMPLO
static int generarTiempoLLegada(float P);
static int generarTiempoLLamada(float A);
static int seleccionarMenor(int n1, int n2, int n3);
static int generarTipo();
static int menor = 0, reloj = 0, delta = 0, deltaAnt = 0, TSLL = 0, tipo = 0, TClientes = 0, Tllamadas = 0, cola = 0, llamadasP = 0, llamadasCont = 0, TCELL = 0, CELL = 0;
static bool LLA = false, CLA = false;
static float P = 0.0f;
//EJEMPLO

void ImGui::Simulacion(bool* p_open, int tiempoMax, int nFilas, int nServicio) {
	static int i = 0;
	static bool atendido = false;
	static int TLL = generarTiempoLLegada(P);
	static int estaciones[10][2] = { {0,0} ,{ 0,0 } ,{ 0,0 } ,{ 0,0 } ,{ 0,0 } ,{ 0,0 } ,{ 0,0 } ,{ 0,0 } ,{ 0,0 } ,{ 0,0 } };
	static int TS[10][2] = { { 0,0 } ,{ 0,0 } ,{ 0,0 } ,{ 0,0 } ,{ 0,0 } ,{ 0,0 } ,{ 0,0 } ,{ 0,0 } ,{ 0,0 } ,{ 0,0 } };
	ImGui::SetNextWindowSize(ImVec2(550, 300));
	if (!ImGui::Begin("Simulacion", p_open))
	{
		// Early out if the window is collapsed, as an optimization.
		ImGui::End();
		return;
	}

	if (reloj<tiempoMax)
	{
		Sleep(1000);
		menor = TLL;
		for (i = 0; i < nServicio; i++) {
			delta = seleccionarMenor(TS[i][0],TS[i][1],menor);//seleccionar el menor de 3 numeros
			menor = delta;

		}
		delta = 10;
		reloj = reloj + delta;

		//Pendiente formula tiempo de espera total

		//Revisar el tiempo de llegada
		TLL = TLL - delta;
		i = 0;

		if (TLL == 0)
		{
			tipo = generarTipo();
			while ((i < nServicio)&&(atendido == false))
			{
				printf("checar %i\n",i);
				if (tipo == 0) {
					TClientes++;
					cola++;
					atendido = true;
				}
				else {
					printf("estacion: %i estado: %i\n", i, estaciones[i][1]);
					if (estaciones[i][1] == 0)
					{

						estaciones[i][1] = 1;
						TS[i][1] = generarTiempoLLamada(1) + delta;

						llamadasCont++;
						printf("atencion: %i\n", i);
						atendido = true;
						if (estaciones[i][0] == 1) {
							TS[i][0] = TS[i][0] + TS[i][1];
							TCELL = TCELL + TS[i][1];
							CELL++;
						}

					}
				}
				i++;
			}
			printf("atendido\n");
			if (atendido == false) {
				llamadasP++;
			}
			TLL = generarTiempoLLegada(P);//obtener un tiempo de llegada

		}

		//Revisar el tiempo de servicio de llamada
		for (i = 0; i < nServicio; i++) {
			TS[i][1] = TS[i][1] - delta;
			if (TS[i][1] <= 0) {
				estaciones[i][1] = 0;
			}
		}

		//Revisar el tiempo de servicio del cliente
		for (i = 0; i < nServicio; i++) {
			TS[i][0] = TS[i][0] - delta;
			if (TS[i][0]<=0)
			{

			}

		}

		atendido = false;
		printf("\n");
	}
	//Impresion de estado
	Tllamadas = llamadasCont + llamadasP;
	ImGui::Text("Reloj: %i", reloj);
	ImGui::Text("Cola: %i \n", cola);
	ImGui::Text("Clientes: %i \n", TClientes);
	ImGui::Text("Llamadas: %i \n", Tllamadas);
	ImGui::Text("Llamadas Perdidas: %i \n", llamadasP);
	ImGui::Text("Llamadas Contestadas: %i \n", llamadasCont);
	//Calculo de promedios
	//Impresiones
	ImGui::End();
}

static int generarTiempoLLegada(float P) {
	static int tiempo = 0;
	tiempo = 10;
	return tiempo;
}
static int generarTiempoLLamada(float A) {
	static int tiempo = 0;
	tiempo = 20;
	return tiempo;
}
static int seleccionarMenor(int n1, int n2, int n3) {
	static int mayor;

	mayor = 10;
	return mayor;
}
static int generarTipo() {
	static int tipo;
	tipo = 1;
	return tipo;
}

#else

void ImGui::ShowTestWindow(bool*) {}
void ImGui::ShowUserGuide() {}
void ImGui::ShowStyleEditor(ImGuiStyle*) {}

#endif
<commit_msg>ejemplo de generacion de tiempos de llegada<commit_after>// dear imgui, v1.50 WIP
// (demo code)

// Message to the person tempted to delete this file when integrating ImGui into their code base:
// Do NOT remove this file from your project! It is useful reference code that you and other users will want to refer to.
// Everything in this file will be stripped out by the linker if you don't call ImGui::ShowTestWindow().
// During development, you can call ImGui::ShowTestWindow() in your code to learn about various features of ImGui.
// Removing this file from your project is hindering your access to documentation, likely leading you to poorer usage of the library.

#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif

#include "imgui.h"
#include <ctype.h>          // toupper, isprint
#include <math.h>           // sqrtf, powf, cosf, sinf, floorf, ceilf
#include <stdio.h>          // vsnprintf, sscanf, printf
#include <stdlib.h>         // NULL, malloc, free, qsort, atoi
//#include <windows.h>
#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
#include <stddef.h>         // intptr_t
#else
#include <stdint.h>         // intptr_t
#endif

#include<iostream>
#include <random>

#ifdef _MSC_VER
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
#define snprintf _snprintf
#endif
#ifdef __clang__
#pragma clang diagnostic ignored "-Wold-style-cast"             // warning : use of old-style cast                              // yes, they are more terse.
#pragma clang diagnostic ignored "-Wdeprecated-declarations"    // warning : 'xx' is deprecated: The POSIX name for this item.. // for strdup used in demo code (so user can copy & paste the code)
#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast"   // warning : cast to 'void *' from smaller integer type 'int'
#pragma clang diagnostic ignored "-Wformat-security"            // warning : warning: format string is not a string literal
#pragma clang diagnostic ignored "-Wexit-time-destructors"      // warning : declaration requires an exit-time destructor       // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals.
#if __has_warning("-Wreserved-id-macro")
#pragma clang diagnostic ignored "-Wreserved-id-macro"          // warning : macro name is a reserved identifier                //
#endif
#elif defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"          // warning: cast to pointer from integer of different size
#pragma GCC diagnostic ignored "-Wformat-security"              // warning : format string is not a string literal (potentially insecure)
#pragma GCC diagnostic ignored "-Wdouble-promotion"             // warning: implicit conversion from 'float' to 'double' when passing argument to function
#pragma GCC diagnostic ignored "-Wconversion"                   // warning: conversion to 'xxxx' from 'xxxx' may alter its value
#if (__GNUC__ >= 6)
#pragma GCC diagnostic ignored "-Wmisleading-indentation"       // warning: this 'if' clause does not guard this statement      // GCC 6.0+ only. See #883 on github.
#endif
#endif

// Play it nice with Windows users. Notepad in 2015 still doesn't display text data with Unix-style \n.
#ifdef _WIN32
#define IM_NEWLINE "\r\n"
#else
#define IM_NEWLINE "\n"
#endif

#define IM_ARRAYSIZE(_ARR)  ((int)(sizeof(_ARR)/sizeof(*_ARR)))
#define IM_MAX(_A,_B)       (((_A) >= (_B)) ? (_A) : (_B))

//-----------------------------------------------------------------------------
// DEMO CODE
//-----------------------------------------------------------------------------

#ifndef IMGUI_DISABLE_TEST_WINDOWS

//EJEMPLO
static int generarTiempoLLegada(float P);
static int generarTiempoLLamada(float A);
static int seleccionarMenor(int n1, int n2, int n3);
static int generarTipo();
static float getRandomNumber();
static int randomInteger();
static void geometrica();

static int menor = 0, reloj = 0, delta = 0, deltaAnt = 0, TSLL = 0, tipo = 0, TClientes = 0, Tllamadas = 0, cola = 0, llamadasP = 0, llamadasCont = 0, TCELL = 0, CELL = 0;
static bool LLA = false, CLA = false;
static float P = 0.0f;
enum { MIN = 0, MAX = 1000 };

using namespace std;

#define LEN 20
char times[LEN];

struct ExampleAppLog
{
    ImGuiTextBuffer     Buf;
    ImGuiTextFilter     Filter;
    ImVector<int>       LineOffsets;        // Index to lines offset
    bool                ScrollToBottom;

    void    Clear()     { Buf.clear(); LineOffsets.clear(); }

    void    AddLog(const char* fmt, ...) IM_PRINTFARGS(2)
    {
        int old_size = Buf.size();
        va_list args;
        va_start(args, fmt);
        Buf.appendv(fmt, args);
        va_end(args);
        for (int new_size = Buf.size(); old_size < new_size; old_size++)
            if (Buf[old_size] == '\n')
                LineOffsets.push_back(old_size);
        ScrollToBottom = true;
    }

    void    Draw(const char* title, bool* p_open = NULL)
    {
        ImGui::SetNextWindowSize(ImVec2(500,400), ImGuiSetCond_FirstUseEver);
        ImGui::Begin(title, p_open);
        if (ImGui::Button("Clear")) Clear();
        ImGui::SameLine();
        bool copy = ImGui::Button("Copy");
        ImGui::SameLine();
        Filter.Draw("Filter", -100.0f);
        ImGui::Separator();
        ImGui::BeginChild("scrolling", ImVec2(0,0), false, ImGuiWindowFlags_HorizontalScrollbar);
        if (copy) ImGui::LogToClipboard();

        if (Filter.IsActive())
        {
            const char* buf_begin = Buf.begin();
            const char* line = buf_begin;
            for (int line_no = 0; line != NULL; line_no++)
            {
                const char* line_end = (line_no < LineOffsets.Size) ? buf_begin + LineOffsets[line_no] : NULL;
                if (Filter.PassFilter(line, line_end))
                    ImGui::TextUnformatted(line, line_end);
                line = line_end && line_end[1] ? line_end + 1 : NULL;
            }
        }
        else
        {
            ImGui::TextUnformatted(Buf.begin());
        }

        if (ScrollToBottom)
            ImGui::SetScrollHere(1.0f);
        ScrollToBottom = false;
        ImGui::EndChild();
        ImGui::End();
    }
};

//EJEMPLO
void ImGui::Simulacion(bool* p_open, int tiempoMax, int nFilas, int nServicio) {

	static ExampleAppLog log;

	ImGui::Begin("Simulacion", p_open);

	if(ImGui::Button("Generate times"))
	  {
	    geometrica();
	    log.AddLog("\n\n \tNew Generation\n\n");
	    for(int i = 0; i < LEN; i++)
	      log.AddLog("%d\n", times[i]);
	  }

	 log.Draw("Numbers for time", p_open);

	ImGui::End();
}

static int generarTiempoLLegada(float P) {
	static int tiempo = 0;
	tiempo = 10;
	return tiempo;
}
static int generarTiempoLLamada(float A) {
	static int tiempo = 0;
	tiempo = 20;
	return tiempo;
}
static int seleccionarMenor(int n1, int n2, int n3) {
	static int mayor;

	mayor = 10;
	return mayor;
}
static int generarTipo() {
	static int tipo;
	tipo = 1;
	return tipo;
}

static int randomInteger()
{
  std::mt19937 rng;  // only used once to initialise (seed) engine
  rng.seed(std::random_device()());
  std::uniform_int_distribution<std::mt19937::result_type> dist(MIN,MAX); // distribution in range [MIN, MAX]

  auto random_integer = dist(rng);

  return random_integer;
}

//Metodo Congruencial Lineal
static float getRandomNumber()
{

    long int m = 97711 /* 97711 */;
    int c = 7, a = 7;
    double nrandom = 0.0f, temp = 0.0f;
    double uniforme = 0.0f;

    int random_stop = randomInteger();
    cout << "rs = " << random_stop << " ";

    for (long int i = 0; i < random_stop; ++i)
      {
	nrandom = ((int)(a*temp + c) % m);
	temp = nrandom;
      }

    uniforme = nrandom / m;

  return uniforme;
}

static void geometrica(){
  double p, suma, y = 0;
  double r;
  int x;

  p = 0.07203;

  for (int i = 0; i < LEN; ++i)
    {
      x = 0;
      suma = 0;
      r = getRandomNumber();
      //cout << "r = " << r << endl;

      while (suma < r) {
	x++;
	y = (pow((1-p), x-1))*p;
	suma += y;
      }
      times[i] = x;
      printf("X = %d\n", x);
    }
}
#else

void ImGui::ShowTestWindow(bool*) {}
void ImGui::ShowUserGuide() {}
void ImGui::ShowStyleEditor(ImGuiStyle*) {}

#endif
<|endoftext|>


<commit_before>/*
 * benchmark.cpp
 *
 *  Created on: 04.05.2015
 *      Author: gmueller
 */

#include <iostream>
#include <sstream>

#include <sys/stat.h>
#include <sys/time.h>
#include <omp.h>

#include <quimby/Database.h>
#include <quimby/Grid.h>
#include <quimby/HCube.h>
#include <quimby/tga.h>

using namespace quimby;
using namespace std;

bool check_file(const std::string filename) {
	struct stat s;
	int r = stat(filename.c_str(), &s);
	return ((r == 0) && S_ISREG(s.st_mode) && (s.st_size > 0));
}

class Timer {
	struct timeval start;
public:
	Timer() {
		reset();
	}

	void reset() {
		::gettimeofday(&start, NULL);
	}

	size_t microns() {
		struct timeval now;
		::gettimeofday(&now, NULL);
		size_t ms = (now.tv_sec - start.tv_sec) * 1000000;
		ms += (now.tv_usec - start.tv_usec);
		return ms;

	}

	size_t millisecods() {
		return microns() / 1000;
	}

	double seconds() {
		struct timeval now;
		::gettimeofday(&now, NULL);
		return double(now.tv_sec - start.tv_sec)
				+ double(now.tv_usec - start.tv_usec) / 1000000;
	}

};

class Accessor {
public:
	virtual Vector3f get(const Vector3f &pos) {
		return Vector3f(0, 0, 0);
	}
};

class GridAccessor: public Accessor {
	Vector3f origin;
	Grid<Vector3f> &grid;
public:
	GridAccessor(const Vector3f &origin, Grid<Vector3f> &grid) :
			origin(origin), grid(grid) {

	}

	Vector3f get(const Vector3f &pos) {
		Vector3f r = pos - origin;
		return grid.get(r.x, r.y, r.z);
	}
};

template<size_t N>
class HCubeAccessor: public Accessor {
	Vector3f origin;
	float size;
	const HCube<N> *hcube;
public:
	HCubeAccessor(const Vector3f &origin, float size, const HCube<N> *hcube) :
			origin(origin), size(size), hcube(hcube) {

	}

	Vector3f get(const Vector3f &pos) {
		Vector3f r = pos - origin;
		return hcube->getValue(r, size);
	}
};

class RandomAccessBenchmark {
	Vector3f origin;
	float size;
public:
	RandomAccessBenchmark(Vector3f origin, float size) :
			origin(origin), size(size) {

	}
	double run(Accessor &accessor, size_t threads = 1,
			size_t samples = 10000000) {
		Timer timer;

		omp_set_num_threads(threads);

#pragma omp parallel
		{
			int seed = 1202107158 + omp_get_thread_num() * 1999;
			struct drand48_data drand_buf;
			srand48_r(seed, &drand_buf);

			float s = size * (1 - 1e-6);
#pragma omp parallel for
			for (size_t i = 0; i < samples; i++) {
				double x, y, z;
				drand48_r(&drand_buf, &x);
				drand48_r(&drand_buf, &y);
				drand48_r(&drand_buf, &z);
				accessor.get(origin + Vector3f(x, y, z) * s);
			}

		}
		return timer.seconds();
	}

};

class RandomWalkBenchmark {
	Vector3f origin;
	float size;
public:
	RandomWalkBenchmark(Vector3f origin, float size) :
			origin(origin), size(size) {

	}
	double run(Accessor &accessor, size_t threads = 1,
			size_t samples = 10000000) {
		Timer timer;

		omp_set_num_threads(threads);

		float step = size / 1000.;
		Vector3f end = origin + Vector3f(size, size, size) * (1 - 1e-6);

#pragma omp parallel
		{
			int seed = 1202107158 + omp_get_thread_num() * 1999;
			struct drand48_data drand_buf;
			srand48_r(seed, &drand_buf);

			Vector3f pos = origin + Vector3f(size / 2., size / 2., size / 2.);

#pragma omp parallel for
			for (size_t i = 0; i < samples; i++) {
				double x, y, z;
				drand48_r(&drand_buf, &x);
				drand48_r(&drand_buf, &y);
				drand48_r(&drand_buf, &z);
				pos += Vector3f(x-0.5, y-0.5, z-0.5) * step;
				pos.setUpper(origin);
				pos.setLower(end);
				accessor.get(pos);
				//cout << pos << endl;
			}

		}
		return timer.seconds();
	}

};

void print_slice(Accessor &accessor, size_t bins, size_t z,
		const Vector3f &origin, float size, const string &filename) {
	const float rl = 1e-15;
	const float ru = 1e-5;
	ofstream tgafile(filename.c_str());
	tga_write_header(tgafile, bins, bins);
	for (size_t x = 0; x < bins; x++) {
		for (size_t y = 0; y < bins; y++) {
			float value = accessor.get(
					origin + Vector3f(x, y, z) * (size / bins)).length();
			// normalize
			value = (log10(value) - log10(rl)) / (log10(ru) - log10(rl));
			tga_write_float(tgafile, value);
		}
	}

}

int main(int argc, const char **argv) {
	if (argc < 3) {
		cout << "benchmark <comaprofile.db> <bins>" << endl;
		return 1;
	}

	size_t bins = atoi(argv[2]);

	cout << "load coma db" << endl;
	FileDatabase fdb;
	fdb.open(argv[1]);

	cout << "  particles: " << fdb.getCount() << endl;
	cout << "  lower: " << fdb.getLowerBounds() << endl;
	cout << "  upper: " << fdb.getUpperBounds() << endl;

	Vector3f origin = fdb.getLowerBounds();

	Vector3f size3 = fdb.getUpperBounds() - fdb.getLowerBounds();
	float size = std::min(std::min(size3.x, size3.y), size3.z);
	cout << "  size: " << size << endl;

	cout << "create sample" << endl;
	Grid<Vector3f> grid(bins, size);

	stringstream gridfilename;
	gridfilename << "benchmark-" << bins << "-grid.grid";

	if (check_file(gridfilename.str())) {
		grid.load(gridfilename.str());

	} else {
		grid.reset(Vector3f(0, 0, 0));

		cout << "create visitor" << endl;
		SimpleSamplingVisitor v(grid, fdb.getLowerBounds(), size);
		v.showProgress(true);
		cout << "start sampling" << endl;
		fdb.accept(v);
		cout << endl;

		grid.save(gridfilename.str());
	}

	GridAccessor gridaccessor(fdb.getLowerBounds(), grid);

	cout << "print slices" << endl;
	for (size_t z = 0; z < bins; z += bins / 16) {
		stringstream filename;
		filename << "benchmark-" << bins << "-slice-grid-" << z << ".tga";
		print_slice(gridaccessor, bins, z, origin, size, filename.str());
	}

	size_t maxdepth = 0;

	while (pow(4, maxdepth + 1) < bins)
		maxdepth++;

	stringstream hcubefilename;
	hcubefilename << "benchmark-" << bins << "-hcube.hc4";
	if (!check_file(hcubefilename.str())) {
		cout << "create hc4, maxdepth=" << maxdepth << endl;

		HCubeFile4::create(grid, Vector3f(0, 0, 0), size, 0.1, 1e-19, maxdepth,
				hcubefilename.str());
	}

	cout << "open hc4" << endl;
	HCubeFile4 hcf;
	hcf.open(hcubefilename.str());
	const HCube4 *hcube = hcf.hcube();

	HCubeAccessor<4> hcubeaccessor(origin, size, hcube);

	cout << "print hcube slices" << endl;
	for (size_t z = 0; z < bins; z += bins / 16) {
		stringstream filename;
		filename << "benchmark-" << bins << "-slice-hcube-" << z << ".tga";
		print_slice(hcubeaccessor, bins, z, origin, size, filename.str());
	}

	RandomAccessBenchmark rab(origin, size);
	RandomWalkBenchmark rwb(origin, size);
	Accessor nullaccessor;

//ToDo: THREADS
//ToDo: zorder
//ToDo: mmap grid
	size_t max_threads = omp_get_max_threads();
	for (size_t threads = 1; threads <= max_threads; threads++) {
		cout << "threads: " << threads << "/" << max_threads << endl;

		cout << "  run null benchmark" << endl;
		cout << "    " << rab.run(nullaccessor, threads) << endl;
		cout << "    " << rab.run(nullaccessor, threads) << endl;

		cout << "  run grid benchmark" << endl;
		cout << "    " << rab.run(gridaccessor, threads) << endl;
		cout << "    " << rab.run(gridaccessor, threads) << endl;

		cout << "  run hcube benchmark" << endl;
		cout << "    " << rab.run(hcubeaccessor, threads) << endl;
		cout << "    " << rab.run(hcubeaccessor, threads) << endl;

		cout << "random walk";

		cout << "  run null benchmark" << endl;
		cout << "    " << rwb.run(nullaccessor, threads) << endl;
		cout << "    " << rwb.run(nullaccessor, threads) << endl;

		cout << "  run grid benchmark" << endl;
		cout << "    " << rwb.run(gridaccessor, threads) << endl;
		cout << "    " << rwb.run(gridaccessor, threads) << endl;

		cout << "  run hcube benchmark" << endl;
		cout << "    " << rwb.run(hcubeaccessor, threads) << endl;
		cout << "    " << rwb.run(hcubeaccessor, threads) << endl;

	}

	cout << "done" << endl;
}
<commit_msg>improve benchmark<commit_after>/*
 * benchmark.cpp
 *
 *  Created on: 04.05.2015
 *      Author: gmueller
 */

#include <iostream>
#include <sstream>

#include <sys/stat.h>
#include <sys/time.h>
#include <omp.h>

#include <quimby/Database.h>
#include <quimby/Grid.h>
#include <quimby/HCube.h>
#include <quimby/tga.h>

using namespace quimby;
using namespace std;

bool check_file(const std::string filename) {
	struct stat s;
	int r = stat(filename.c_str(), &s);
	return ((r == 0) && S_ISREG(s.st_mode) && (s.st_size > 0));
}

class Timer {
	struct timeval start;
public:
	Timer() {
		reset();
	}

	void reset() {
		::gettimeofday(&start, NULL);
	}

	size_t microns() {
		struct timeval now;
		::gettimeofday(&now, NULL);
		size_t ms = (now.tv_sec - start.tv_sec) * 1000000;
		ms += (now.tv_usec - start.tv_usec);
		return ms;

	}

	size_t millisecods() {
		return microns() / 1000;
	}

	double seconds() {
		struct timeval now;
		::gettimeofday(&now, NULL);
		return double(now.tv_sec - start.tv_sec)
				+ double(now.tv_usec - start.tv_usec) / 1000000;
	}

};

class Accessor {
public:
	virtual Vector3f get(const Vector3f &pos) {
		return Vector3f(0, 0, 0);
	}
};

class GridAccessor: public Accessor {
	Vector3f origin;
	Grid<Vector3f> &grid;
public:
	GridAccessor(const Vector3f &origin, Grid<Vector3f> &grid) :
			origin(origin), grid(grid) {

	}

	Vector3f get(const Vector3f &pos) {
		Vector3f r = pos - origin;
		return grid.get(r.x, r.y, r.z);
	}
};

template<size_t N>
class HCubeAccessor: public Accessor {
	Vector3f origin;
	float size;
	const HCube<N> *hcube;
public:
	HCubeAccessor(const Vector3f &origin, float size, const HCube<N> *hcube) :
			origin(origin), size(size), hcube(hcube) {

	}

	Vector3f get(const Vector3f &pos) {
		Vector3f r = pos - origin;
		return hcube->getValue(r, size);
	}
};

class RandomAccessBenchmark {
	Vector3f origin;
	float size;
public:
	RandomAccessBenchmark(Vector3f origin, float size) :
			origin(origin), size(size) {

	}
	double run(Accessor &accessor, size_t threads = 1,
			size_t samples = 10000000) {
		Timer timer;

		omp_set_num_threads(threads);

#pragma omp parallel
		{
			int seed = 1202107158 + omp_get_thread_num() * 1999;
			struct drand48_data drand_buf;
			srand48_r(seed, &drand_buf);

			float s = size * (1 - 1e-6);
#pragma omp parallel for
			for (size_t i = 0; i < samples; i++) {
				double x, y, z;
				drand48_r(&drand_buf, &x);
				drand48_r(&drand_buf, &y);
				drand48_r(&drand_buf, &z);
				accessor.get(origin + Vector3f(x, y, z) * s);
			}

		}
		return timer.seconds();
	}

};

class RandomWalkBenchmark {
	Vector3f origin;
	float size;
public:
	RandomWalkBenchmark(Vector3f origin, float size) :
			origin(origin), size(size) {

	}
	double run(Accessor &accessor, size_t threads = 1,
			size_t samples = 10000000) {
		Timer timer;

		omp_set_num_threads(threads);

		float step = size / 1000.;
		Vector3f end = origin + Vector3f(size, size, size) * (1 - 1e-6);

#pragma omp parallel
		{
			int seed = 1202107158 + omp_get_thread_num() * 1999;
			struct drand48_data drand_buf;
			srand48_r(seed, &drand_buf);

			Vector3f pos = origin + Vector3f(size / 2., size / 2., size / 2.);

#pragma omp parallel for
			for (size_t i = 0; i < samples; i++) {
				double x, y, z;
				drand48_r(&drand_buf, &x);
				drand48_r(&drand_buf, &y);
				drand48_r(&drand_buf, &z);
				pos += Vector3f(x-0.5, y-0.5, z-0.5) * step;
				pos.setUpper(origin);
				pos.setLower(end);
				accessor.get(pos);
				//cout << pos << endl;
			}

		}
		return timer.seconds();
	}

};

void print_slice(Accessor &accessor, size_t bins, size_t z,
		const Vector3f &origin, float size, const string &filename) {
	const float rl = 1e-15;
	const float ru = 1e-5;
	ofstream tgafile(filename.c_str());
	tga_write_header(tgafile, bins, bins);
	for (size_t x = 0; x < bins; x++) {
		for (size_t y = 0; y < bins; y++) {
			float value = accessor.get(
					origin + Vector3f(x, y, z) * (size / bins)).length();
			// normalize
			value = (log10(value) - log10(rl)) / (log10(ru) - log10(rl));
			tga_write_float(tgafile, value);
		}
	}

}

int main(int argc, const char **argv) {
	if (argc < 3) {
		cout << "benchmark <comaprofile.db> <bins>" << endl;
		return 1;
	}

	size_t bins = atoi(argv[2]);

	cout << "load coma db" << endl;
	FileDatabase fdb;
	fdb.open(argv[1]);

	cout << "  particles: " << fdb.getCount() << endl;
	cout << "  lower: " << fdb.getLowerBounds() << endl;
	cout << "  upper: " << fdb.getUpperBounds() << endl;

	Vector3f origin = fdb.getLowerBounds();

	Vector3f size3 = fdb.getUpperBounds() - fdb.getLowerBounds();
	float size = std::min(std::min(size3.x, size3.y), size3.z);
	cout << "  size: " << size << endl;

	cout << "create sample" << endl;
	Grid<Vector3f> grid(bins, size);

	stringstream gridfilename;
	gridfilename << "benchmark-" << bins << "-grid.grid";

	if (check_file(gridfilename.str())) {
		grid.load(gridfilename.str());

	} else {
		grid.reset(Vector3f(0, 0, 0));

		cout << "create visitor" << endl;
		SimpleSamplingVisitor v(grid, fdb.getLowerBounds(), size);
		v.showProgress(true);
		cout << "start sampling" << endl;
		fdb.accept(v);
		cout << endl;

		grid.save(gridfilename.str());
	}

	GridAccessor gridaccessor(fdb.getLowerBounds(), grid);

	cout << "print slices" << endl;
	for (size_t z = 0; z < bins; z += bins / 16) {
		stringstream filename;
		filename << "benchmark-" << bins << "-slice-grid-" << z << ".tga";
		print_slice(gridaccessor, bins, z, origin, size, filename.str());
	}

	size_t maxdepth = 0;

	while (pow(4, maxdepth + 1) < bins)
		maxdepth++;

	stringstream hcubefilename;
	hcubefilename << "benchmark-" << bins << "-hcube.hc4";
	if (!check_file(hcubefilename.str())) {
		cout << "create hc4, maxdepth=" << maxdepth << endl;

		HCubeFile4::create(grid, Vector3f(0, 0, 0), size, 0.1, 1e-19, maxdepth,
				hcubefilename.str());
	}

	cout << "open hc4" << endl;
	HCubeFile4 hcf;
	hcf.open(hcubefilename.str());
	const HCube4 *hcube = hcf.hcube();

	HCubeAccessor<4> hcubeaccessor(origin, size, hcube);

	cout << "print hcube slices" << endl;
	for (size_t z = 0; z < bins; z += bins / 16) {
		stringstream filename;
		filename << "benchmark-" << bins << "-slice-hcube-" << z << ".tga";
		print_slice(hcubeaccessor, bins, z, origin, size, filename.str());
	}

	RandomAccessBenchmark rab(origin, size);
	RandomWalkBenchmark rwb(origin, size);
	Accessor nullaccessor;

//ToDo: zorder
//ToDo: mmap grid
	cout << "accessor benchmark threads time" << endl;
	const size_t samples = 3;
	size_t max_threads = omp_get_max_threads();
	for (size_t threads = 1; threads <= max_threads; threads++) {

		for (size_t i = 0; i < samples; i++)
			cout << "0 0 " << threads << " " << rab.run(nullaccessor, threads) << endl;

		for (size_t i = 0; i < samples; i++)
			cout << "1 0 " << threads << " " << rab.run(gridaccessor, threads) << endl;

		for (size_t i = 0; i < samples; i++)
			cout << "2 0 " << threads << " " << rab.run(hcubeaccessor, threads) << endl;

		for (size_t i = 0; i < samples; i++)
			cout << "0 1 " << threads << " " << rwb.run(nullaccessor, threads) << endl;

		for (size_t i = 0; i < samples; i++)
			cout << "1 1 " << threads << " " << rwb.run(gridaccessor, threads) << endl;

		for (size_t i = 0; i < samples; i++)
			cout << "2 1 " << threads << " " << rwb.run(hcubeaccessor, threads) << endl;

	}

	cout << "done" << endl;
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef WITHOUT_HSA_BACKEND

#include <string>
#include <sstream>
#include <fstream>
#include <iostream>

#include "os/os.hpp"
#include "rocdevice.hpp"
#include "rocprogram.hpp"
#if defined(WITH_LIGHTNING_COMPILER)
#include "opencl1.2-c.amdgcn.inc"
#include "opencl2.0-c.amdgcn.inc"
#else // !defined(WITH_LIGHTNING_COMPILER)
#include "roccompilerlib.hpp"
#endif // !defined(WITH_LIGHTNING_COMPILER)
#include "utils/options.hpp"
#include <cstdio>

#if defined(ATI_OS_LINUX)
#include <dlfcn.h>
#include <libgen.h>
#endif // defined(ATI_OS_LINUX)

#if defined(WITH_LIGHTNING_COMPILER)
static std::string llvmBin_(amd::Os::getEnvironment("LLVM_BIN"));
#endif // defined(WITH_LIGHTNING_COMPILER)

//CLC_IN_PROCESS_CHANGE
extern int openclFrontEnd(const char* cmdline, std::string*, std::string* typeInfo = NULL);

namespace roc {

/* Temporary log function for the compiler library */
static void
logFunction(const char* msg, size_t size)
{
    std::cout<< "Compiler Log: " << msg << std::endl;
}

static int programsCount = 0;

#if defined(WITH_LIGHTNING_COMPILER)
bool
HSAILProgram::compileImpl_LC(
    const std::string& sourceCode,
    const std::vector<const std::string*>& headers,
    const char** headerIncludeNames,
    amd::option::Options* options)
{
    using namespace amd::opencl_driver;
    std::auto_ptr<Compiler> C(newCompilerInstance());
    std::vector<Data*> inputs;

    Data* input = C->NewBufferReference(DT_CL,
        sourceCode.c_str(), sourceCode.length());
    if (input == NULL) {
        buildLog_ += "Error while creating data from source code";
        return false;
    }

    inputs.push_back(input);

    //Find the temp folder for the OS
    std::string tempFolder = amd::Os::getEnvironment("TEMP");
    if (tempFolder.empty()) {
        tempFolder = amd::Os::getEnvironment("TMP");
        if (tempFolder.empty()) {
            tempFolder = WINDOWS_SWITCH(".","/tmp");;
        }
    }
    //Iterate through each source code and dump it into tmp
    std::fstream f;
    std::vector<std::string> headerFileNames(headers.size());
    std::vector<std::string> newDirs;
    for (size_t i = 0; i < headers.size(); ++i) {
        std::string headerPath = tempFolder;
        std::string headerIncludeName(headerIncludeNames[i]);
        // replace / in path with current os's file separator
        if ( amd::Os::fileSeparator() != '/') {
            for (std::string::iterator it = headerIncludeName.begin(),
                end = headerIncludeName.end();
                it != end;
                ++it) {
                if (*it == '/') *it = amd::Os::fileSeparator();
            }
        }
        size_t pos = headerIncludeName.rfind(amd::Os::fileSeparator());
        if (pos != std::string::npos) {
            headerPath += amd::Os::fileSeparator();
            headerPath += headerIncludeName.substr(0, pos);
            headerIncludeName = headerIncludeName.substr(pos+1);
        }
        if (!amd::Os::pathExists(headerPath)) {
            bool ret = amd::Os::createPath(headerPath);
            assert(ret && "failed creating path!");
            newDirs.push_back(headerPath);
        }
        std::string headerFullName
        = headerPath + amd::Os::fileSeparator() + headerIncludeName;
        headerFileNames[i] = headerFullName;
        f.open(headerFullName.c_str(), std::fstream::out);
        //Should we allow asserts
        assert(!f.fail() && "failed creating header file!");
        f.write(headers[i]->c_str(), headers[i]->length());
        f.close();

        Data* inc = C->NewFileReference(DT_CL_HEADER, headerFileNames[i]);
        if (inc == NULL) {
            buildLog_ += "Error while creating data from headers";
            return false;
        }
        inputs.push_back(inc);
    }

    //Set the options for the compiler
    std::ostringstream ostrstr;
    std::copy(options->clangOptions.begin(), options->clangOptions.end(),
        std::ostream_iterator<std::string>(ostrstr, " "));
    std::string driverOptions(ostrstr.str());

    //Set the include path for the temp folder that contains the includes
    if(!headers.empty()) {
        driverOptions.append(" -I");
        driverOptions.append(tempFolder);
    }

    const char* xLang = options->oVariables->XLang;
    if (xLang != NULL && strcmp(xLang, "cl")) {
        buildLog_ += "Unsupported OpenCL language.\n";
    }

    //FIXME_Nikolay: the program manager should be setting the language
    //driverOptions.append(" -x cl");

    driverOptions.append(" -cl-std=").append(options->oVariables->CLStd);

    // Set the -O#
    std::ostringstream optLevel;
    optLevel << " -O" << options->oVariables->OptLevel;
    driverOptions.append(optLevel.str());

    //FIXME_lmoriche: has the CL option been validated?
    uint clcStd = (options->oVariables->CLStd[2] - '0') * 100
        + (options->oVariables->CLStd[4] - '0') * 10;

    driverOptions.append(preprocessorOptions(options));

    Buffer* output = C->NewBuffer(DT_LLVM_BC);
    if (output == NULL) {
        buildLog_ += "Error while creating buffer for the LLVM bitcode";
        return false;
    }

    driverOptions.append(options->llvmOptions);

    // Set fp32-denormals and fp64-denormals
    bool fp32Denormals = !options->oVariables->DenormsAreZero
        && dev().deviceInfo().gfxipVersion_ >= 900;

    driverOptions.append(" -Xclang -target-feature -Xclang ");
    driverOptions.append(fp32Denormals ? "+" : "-")
        .append("fp32-denormals,+fp64-denormals");

    if (options->isDumpFlagSet(amd::option::DUMP_CL)) {
        std::ofstream f(options->getDumpFileName(".cl").c_str(), std::ios::trunc);
        if(f.is_open()) {
            f << "/* Compiler options:\n" \
                   "-c -emit-llvm -target amdgcn-amd-amdhsa-opencl -x cl" \
                   " -include opencl-c.h " << driverOptions
                << "\n*/\n\n" << sourceCode;
        } else {
            buildLog_ +=
                "Warning: opening the file to dump the OpenCL source failed.\n";
        }
    }

    std::pair<const void*, size_t> hdr;
    switch(clcStd) {
    case 120:
        hdr = std::make_pair(opencl1_2_c_amdgcn, opencl1_2_c_amdgcn_size);
        break;
    case 200:
        hdr = std::make_pair(opencl2_0_c_amdgcn, opencl2_0_c_amdgcn_size);
        break;
    default:
        buildLog_ += "Unsupported requested OpenCL C version (-cl-std).\n";
        return false;
    }

    File* pch = C->NewTempFile(DT_CL_HEADER);
    if (pch == NULL || !pch->WriteData((const char*) hdr.first, hdr.second)) {
        buildLog_ += "Error while opening the opencl-c header ";
        return false;
    }

    driverOptions.append(" -include-pch " + pch->Name());
    driverOptions.append(" -Xclang -fno-validate-pch");

    // Tokenize the options string into a vector of strings
    std::istringstream istrstr(driverOptions);
    std::istream_iterator<std::string> sit(istrstr), end;
    std::vector<std::string> params(sit, end);

    // Compile source to IR
    bool ret = C->CompileToLLVMBitcode(inputs, output, params);
    buildLog_ += C->Output();
    if (!ret) {
        buildLog_ += "Error: Failed to compile opencl source (from CL to LLVM IR).\n";
        return false;
    }

    llvmBinary_.assign(output->Buf().data(), output->Size());
    elfSectionType_ = amd::OclElf::LLVMIR;

    if (options->isDumpFlagSet(amd::option::DUMP_BC_ORIGINAL)) {
        std::ofstream f(options->getDumpFileName("_original.bc").c_str(), std::ios::trunc);
        if(f.is_open()) {
            f.write(llvmBinary_.data(), llvmBinary_.size());
        } else {
            buildLog_ +=
                "Warning: opening the file to dump the compiled IR failed.\n";
        }
    }

    if (clBinary()->saveSOURCE()) {
        clBinary()->elfOut()->addSection(
            amd::OclElf::SOURCE, sourceCode.data(), sourceCode.size());
    }
    if (clBinary()->saveLLVMIR()) {
        clBinary()->elfOut()->addSection(
            amd::OclElf::LLVMIR, llvmBinary_.data(), llvmBinary_.size(), false);
        // store the original compile options
        clBinary()->storeCompileOptions(compileOptions_);
    }
    return true;
}
#endif // defined(WITH_LIGHTNING_COMPILER)

bool
HSAILProgram::compileImpl(
    const std::string& sourceCode,
    const std::vector<const std::string*>& headers,
    const char** headerIncludeNames,
    amd::option::Options* options)
{
#if defined(WITH_LIGHTNING_COMPILER)
    return compileImpl_LC(sourceCode, headers, headerIncludeNames, options);
#else // !defined(WITH_LIGHTNING_COMPILER)
    acl_error errorCode;
    aclTargetInfo target;

    target = g_complibApi._aclGetTargetInfo(LP64_SWITCH("hsail","hsail64"),
        dev().deviceInfo().complibTarget_, &errorCode);

    //end if asic info is ready
    // We dump the source code for each program (param: headers)
    // into their filenames (headerIncludeNames) into the TEMP
    // folder specific to the OS and add the include path while
    // compiling

    //Find the temp folder for the OS
    std::string tempFolder = amd::Os::getEnvironment("TEMP");
    if (tempFolder.empty()) {
        tempFolder = amd::Os::getEnvironment("TMP");
        if (tempFolder.empty()) {
            tempFolder = WINDOWS_SWITCH(".","/tmp");;
        }
    }
    //Iterate through each source code and dump it into tmp
    std::fstream f;
    std::vector<std::string> headerFileNames(headers.size());
    std::vector<std::string> newDirs;
    for (size_t i = 0; i < headers.size(); ++i) {
        std::string headerPath = tempFolder;
        std::string headerIncludeName(headerIncludeNames[i]);
        // replace / in path with current os's file separator
        if ( amd::Os::fileSeparator() != '/') {
            for (std::string::iterator it = headerIncludeName.begin(),
                end = headerIncludeName.end();
                it != end;
                ++it) {
                if (*it == '/') *it = amd::Os::fileSeparator();
            }
        }
        size_t pos = headerIncludeName.rfind(amd::Os::fileSeparator());
        if (pos != std::string::npos) {
            headerPath += amd::Os::fileSeparator();
            headerPath += headerIncludeName.substr(0, pos);
            headerIncludeName = headerIncludeName.substr(pos+1);
        }
        if (!amd::Os::pathExists(headerPath)) {
            bool ret = amd::Os::createPath(headerPath);
            assert(ret && "failed creating path!");
            newDirs.push_back(headerPath);
        }
        std::string headerFullName
        = headerPath + amd::Os::fileSeparator() + headerIncludeName;
        headerFileNames[i] = headerFullName;
        f.open(headerFullName.c_str(), std::fstream::out);
        //Should we allow asserts
        assert(!f.fail() && "failed creating header file!");
        f.write(headers[i]->c_str(), headers[i]->length());
        f.close();
    }

    //Create Binary
    binaryElf_ = g_complibApi._aclBinaryInit(sizeof(aclBinary),
        &target,
        &binOpts_,
        &errorCode);

    if( errorCode!=ACL_SUCCESS ) {
        buildLog_ += "Error while compiling opencl source:\
                     aclBinary init failure \n";
        LogWarning("aclBinaryInit failed");
        return false;
    }

    //Insert opencl into binary
    errorCode = g_complibApi._aclInsertSection(device().compiler(),
        binaryElf_,
        sourceCode.c_str(),
        strlen(sourceCode.c_str()),
        aclSOURCE);

    if ( errorCode != ACL_SUCCESS )    {
        buildLog_ += "Error while converting to BRIG: \
                     Inserting openCl Source \n";
    }

    //Set the options for the compiler
    //Set the include path for the temp folder that contains the includes
    if(!headers.empty()) {
        this->compileOptions_.append(" -I");
        this->compileOptions_.append(tempFolder);
    }

    //Add only for CL2.0 and later
    if (options->oVariables->CLStd[2] >= '2') {
        std::stringstream opts;
        opts << " -D" << "CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE="
            << device().info().maxGlobalVariableSize_;
        compileOptions_.append(opts.str());
    }

    //Compile source to IR
    this->compileOptions_.append(preprocessorOptions(options));
    this->compileOptions_.append(codegenOptions(options));

    errorCode = g_complibApi._aclCompile(device().compiler(),
        binaryElf_,
        //"-Wf,--support_all_extensions",
        this->compileOptions_.c_str(),
        ACL_TYPE_OPENCL,
        ACL_TYPE_LLVMIR_BINARY,
        logFunction);
    buildLog_ += g_complibApi._aclGetCompilerLog(device().compiler());
    if( errorCode!=ACL_SUCCESS ) {
        LogWarning("aclCompile failed");
        buildLog_ += "Error while compiling \
                     opencl source: Compiling CL to IR";
        return false;
    }
    // Save the binary in the interface class
    saveBinaryAndSetType(TYPE_COMPILED);
    return true;
#endif // !defined(WITH_LIGHTNING_COMPILER)
}

#if defined(WITH_LIGHTNING_COMPILER)
#if defined(ATI_OS_LINUX)
static pthread_once_t once = PTHREAD_ONCE_INIT;

static void
checkLLVM_BIN()
{
    if (llvmBin_.empty()) {
        Dl_info info;
        if (dladdr((const void*)&amd::Device::init, &info)) {
            llvmBin_ = dirname(strdup(info.dli_fname));
            size_t pos = llvmBin_.rfind("lib");
            if (pos != std::string::npos) {
                llvmBin_.replace(pos, 3, "bin");
            }
        }
    }
#if defined(DEBUG)
    std::string clangExe(llvmBin_ + "/clang");
    struct stat buf;
    if (stat(clangExe.c_str(), &buf)) {
        std::string msg("Could not find the Clang binary in " + llvmBin_);
        LogWarning(msg.c_str());
    }
#endif // defined(DEBUG)
}
#endif // defined(ATI_OS_LINUX)

std::auto_ptr<amd::opencl_driver::Compiler>
HSAILProgram::newCompilerInstance()
{
#if defined(ATI_OS_LINUX)
    pthread_once(&once, checkLLVM_BIN);
#endif // defined(ATI_OS_LINUX)
    return std::auto_ptr<amd::opencl_driver::Compiler>(
        amd::opencl_driver::CompilerFactory().CreateAMDGPUCompiler(llvmBin_));
}
#endif // defined(WITH_LIGHTNING_COMPILER)

} // namespace roc
#endif // WITHOUT_GPU_BACKEND
<commit_msg>P4 to Git Change 1323311 by lmoriche@lmoriche_opencl_dev on 2016/10/06 13:26:29<commit_after>//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef WITHOUT_HSA_BACKEND

#include <string>
#include <sstream>
#include <fstream>
#include <iostream>

#include "os/os.hpp"
#include "rocdevice.hpp"
#include "rocprogram.hpp"
#if defined(WITH_LIGHTNING_COMPILER)
#include "opencl1.2-c.amdgcn.inc"
#include "opencl2.0-c.amdgcn.inc"
#else // !defined(WITH_LIGHTNING_COMPILER)
#include "roccompilerlib.hpp"
#endif // !defined(WITH_LIGHTNING_COMPILER)
#include "utils/options.hpp"
#include <cstdio>

#if defined(ATI_OS_LINUX)
#include <dlfcn.h>
#include <libgen.h>
#endif // defined(ATI_OS_LINUX)

#if defined(WITH_LIGHTNING_COMPILER)
static std::string llvmBin_(amd::Os::getEnvironment("LLVM_BIN"));
#endif // defined(WITH_LIGHTNING_COMPILER)

//CLC_IN_PROCESS_CHANGE
extern int openclFrontEnd(const char* cmdline, std::string*, std::string* typeInfo = NULL);

namespace roc {

/* Temporary log function for the compiler library */
static void
logFunction(const char* msg, size_t size)
{
    std::cout<< "Compiler Log: " << msg << std::endl;
}

static int programsCount = 0;

#if defined(WITH_LIGHTNING_COMPILER)
bool
HSAILProgram::compileImpl_LC(
    const std::string& sourceCode,
    const std::vector<const std::string*>& headers,
    const char** headerIncludeNames,
    amd::option::Options* options)
{
    using namespace amd::opencl_driver;
    std::auto_ptr<Compiler> C(newCompilerInstance());
    std::vector<Data*> inputs;

    Data* input = C->NewBufferReference(DT_CL,
        sourceCode.c_str(), sourceCode.length());
    if (input == NULL) {
        buildLog_ += "Error while creating data from source code";
        return false;
    }

    inputs.push_back(input);

    Buffer* output = C->NewBuffer(DT_LLVM_BC);
    if (output == NULL) {
        buildLog_ += "Error while creating buffer for the LLVM bitcode";
        return false;
    }

    //Set the options for the compiler
    std::ostringstream ostrstr;
    std::copy(options->clangOptions.begin(), options->clangOptions.end(),
        std::ostream_iterator<std::string>(ostrstr, " "));

    ostrstr << " -m" << sizeof(void*) * 8;
    std::string driverOptions(ostrstr.str());

    const char* xLang = options->oVariables->XLang;
    if (xLang != NULL && strcmp(xLang, "cl")) {
        buildLog_ += "Unsupported OpenCL language.\n";
    }

    //FIXME_Nikolay: the program manager should be setting the language
    //driverOptions.append(" -x cl");

    driverOptions.append(" -cl-std=").append(options->oVariables->CLStd);

    // Set the -O#
    std::ostringstream optLevel;
    optLevel << " -O" << options->oVariables->OptLevel;
    driverOptions.append(optLevel.str());

    // Set the machine target
    driverOptions.append(" -mcpu=");
    driverOptions.append(dev().deviceInfo().machineTarget_);

    driverOptions.append(options->llvmOptions);

    driverOptions.append(preprocessorOptions(options));

    //Find the temp folder for the OS
    std::string tempFolder = amd::Os::getEnvironment("TEMP");
    if (tempFolder.empty()) {
        tempFolder = amd::Os::getEnvironment("TMP");
        if (tempFolder.empty()) {
            tempFolder = WINDOWS_SWITCH(".","/tmp");;
        }
    }
    //Iterate through each source code and dump it into tmp
    std::fstream f;
    std::vector<std::string> headerFileNames(headers.size());
    std::vector<std::string> newDirs;
    for (size_t i = 0; i < headers.size(); ++i) {
        std::string headerPath = tempFolder;
        std::string headerIncludeName(headerIncludeNames[i]);
        // replace / in path with current os's file separator
        if ( amd::Os::fileSeparator() != '/') {
            for (std::string::iterator it = headerIncludeName.begin(),
                end = headerIncludeName.end();
                it != end;
                ++it) {
                if (*it == '/') *it = amd::Os::fileSeparator();
            }
        }
        size_t pos = headerIncludeName.rfind(amd::Os::fileSeparator());
        if (pos != std::string::npos) {
            headerPath += amd::Os::fileSeparator();
            headerPath += headerIncludeName.substr(0, pos);
            headerIncludeName = headerIncludeName.substr(pos+1);
        }
        if (!amd::Os::pathExists(headerPath)) {
            bool ret = amd::Os::createPath(headerPath);
            assert(ret && "failed creating path!");
            newDirs.push_back(headerPath);
        }
        std::string headerFullName
        = headerPath + amd::Os::fileSeparator() + headerIncludeName;
        headerFileNames[i] = headerFullName;
        f.open(headerFullName.c_str(), std::fstream::out);
        //Should we allow asserts
        assert(!f.fail() && "failed creating header file!");
        f.write(headers[i]->c_str(), headers[i]->length());
        f.close();

        Data* inc = C->NewFileReference(DT_CL_HEADER, headerFileNames[i]);
        if (inc == NULL) {
            buildLog_ += "Error while creating data from headers";
            return false;
        }
        inputs.push_back(inc);
    }

    //Set the include path for the temp folder that contains the includes
    if(!headers.empty()) {
        driverOptions.append(" -I");
        driverOptions.append(tempFolder);
    }

    if (options->isDumpFlagSet(amd::option::DUMP_CL)) {
        std::ofstream f(options->getDumpFileName(".cl").c_str(), std::ios::trunc);
        if(f.is_open()) {
            f << "/* Compiler options:\n" \
                   "-c -emit-llvm -target amdgcn-amd-amdhsa-opencl -x cl "
                   << driverOptions << " -include opencl-c.h "
                << "\n*/\n\n" << sourceCode;
        } else {
            buildLog_ +=
                "Warning: opening the file to dump the OpenCL source failed.\n";
        }
    }

    //FIXME_lmoriche: has the CL option been validated?
    uint clcStd = (options->oVariables->CLStd[2] - '0') * 100
        + (options->oVariables->CLStd[4] - '0') * 10;

    std::pair<const void*, size_t> hdr;
    switch(clcStd) {
    case 120:
        hdr = std::make_pair(opencl1_2_c_amdgcn, opencl1_2_c_amdgcn_size);
        break;
    case 200:
        hdr = std::make_pair(opencl2_0_c_amdgcn, opencl2_0_c_amdgcn_size);
        break;
    default:
        buildLog_ += "Unsupported requested OpenCL C version (-cl-std).\n";
        return false;
    }

    File* pch = C->NewTempFile(DT_CL_HEADER);
    if (pch == NULL || !pch->WriteData((const char*) hdr.first, hdr.second)) {
        buildLog_ += "Error while opening the opencl-c header ";
        return false;
    }

    driverOptions.append(" -include-pch " + pch->Name());
    driverOptions.append(" -Xclang -fno-validate-pch");

    // Tokenize the options string into a vector of strings
    std::istringstream istrstr(driverOptions);
    std::istream_iterator<std::string> sit(istrstr), end;
    std::vector<std::string> params(sit, end);

    // Compile source to IR
    bool ret = C->CompileToLLVMBitcode(inputs, output, params);
    buildLog_ += C->Output();
    if (!ret) {
        buildLog_ += "Error: Failed to compile opencl source (from CL to LLVM IR).\n";
        return false;
    }

    llvmBinary_.assign(output->Buf().data(), output->Size());
    elfSectionType_ = amd::OclElf::LLVMIR;

    if (options->isDumpFlagSet(amd::option::DUMP_BC_ORIGINAL)) {
        std::ofstream f(options->getDumpFileName("_original.bc").c_str(), std::ios::trunc);
        if(f.is_open()) {
            f.write(llvmBinary_.data(), llvmBinary_.size());
        } else {
            buildLog_ +=
                "Warning: opening the file to dump the compiled IR failed.\n";
        }
    }

    if (clBinary()->saveSOURCE()) {
        clBinary()->elfOut()->addSection(
            amd::OclElf::SOURCE, sourceCode.data(), sourceCode.size());
    }
    if (clBinary()->saveLLVMIR()) {
        clBinary()->elfOut()->addSection(
            amd::OclElf::LLVMIR, llvmBinary_.data(), llvmBinary_.size(), false);
        // store the original compile options
        clBinary()->storeCompileOptions(compileOptions_);
    }
    return true;
}
#endif // defined(WITH_LIGHTNING_COMPILER)

bool
HSAILProgram::compileImpl(
    const std::string& sourceCode,
    const std::vector<const std::string*>& headers,
    const char** headerIncludeNames,
    amd::option::Options* options)
{
#if defined(WITH_LIGHTNING_COMPILER)
    return compileImpl_LC(sourceCode, headers, headerIncludeNames, options);
#else // !defined(WITH_LIGHTNING_COMPILER)
    acl_error errorCode;
    aclTargetInfo target;

    target = g_complibApi._aclGetTargetInfo(LP64_SWITCH("hsail","hsail64"),
        dev().deviceInfo().complibTarget_, &errorCode);

    //end if asic info is ready
    // We dump the source code for each program (param: headers)
    // into their filenames (headerIncludeNames) into the TEMP
    // folder specific to the OS and add the include path while
    // compiling

    //Find the temp folder for the OS
    std::string tempFolder = amd::Os::getEnvironment("TEMP");
    if (tempFolder.empty()) {
        tempFolder = amd::Os::getEnvironment("TMP");
        if (tempFolder.empty()) {
            tempFolder = WINDOWS_SWITCH(".","/tmp");;
        }
    }
    //Iterate through each source code and dump it into tmp
    std::fstream f;
    std::vector<std::string> headerFileNames(headers.size());
    std::vector<std::string> newDirs;
    for (size_t i = 0; i < headers.size(); ++i) {
        std::string headerPath = tempFolder;
        std::string headerIncludeName(headerIncludeNames[i]);
        // replace / in path with current os's file separator
        if ( amd::Os::fileSeparator() != '/') {
            for (std::string::iterator it = headerIncludeName.begin(),
                end = headerIncludeName.end();
                it != end;
                ++it) {
                if (*it == '/') *it = amd::Os::fileSeparator();
            }
        }
        size_t pos = headerIncludeName.rfind(amd::Os::fileSeparator());
        if (pos != std::string::npos) {
            headerPath += amd::Os::fileSeparator();
            headerPath += headerIncludeName.substr(0, pos);
            headerIncludeName = headerIncludeName.substr(pos+1);
        }
        if (!amd::Os::pathExists(headerPath)) {
            bool ret = amd::Os::createPath(headerPath);
            assert(ret && "failed creating path!");
            newDirs.push_back(headerPath);
        }
        std::string headerFullName
        = headerPath + amd::Os::fileSeparator() + headerIncludeName;
        headerFileNames[i] = headerFullName;
        f.open(headerFullName.c_str(), std::fstream::out);
        //Should we allow asserts
        assert(!f.fail() && "failed creating header file!");
        f.write(headers[i]->c_str(), headers[i]->length());
        f.close();
    }

    //Create Binary
    binaryElf_ = g_complibApi._aclBinaryInit(sizeof(aclBinary),
        &target,
        &binOpts_,
        &errorCode);

    if( errorCode!=ACL_SUCCESS ) {
        buildLog_ += "Error while compiling opencl source:\
                     aclBinary init failure \n";
        LogWarning("aclBinaryInit failed");
        return false;
    }

    //Insert opencl into binary
    errorCode = g_complibApi._aclInsertSection(device().compiler(),
        binaryElf_,
        sourceCode.c_str(),
        strlen(sourceCode.c_str()),
        aclSOURCE);

    if ( errorCode != ACL_SUCCESS )    {
        buildLog_ += "Error while converting to BRIG: \
                     Inserting openCl Source \n";
    }

    //Set the options for the compiler
    //Set the include path for the temp folder that contains the includes
    if(!headers.empty()) {
        this->compileOptions_.append(" -I");
        this->compileOptions_.append(tempFolder);
    }

    //Add only for CL2.0 and later
    if (options->oVariables->CLStd[2] >= '2') {
        std::stringstream opts;
        opts << " -D" << "CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE="
            << device().info().maxGlobalVariableSize_;
        compileOptions_.append(opts.str());
    }

    //Compile source to IR
    this->compileOptions_.append(preprocessorOptions(options));
    this->compileOptions_.append(codegenOptions(options));

    errorCode = g_complibApi._aclCompile(device().compiler(),
        binaryElf_,
        //"-Wf,--support_all_extensions",
        this->compileOptions_.c_str(),
        ACL_TYPE_OPENCL,
        ACL_TYPE_LLVMIR_BINARY,
        logFunction);
    buildLog_ += g_complibApi._aclGetCompilerLog(device().compiler());
    if( errorCode!=ACL_SUCCESS ) {
        LogWarning("aclCompile failed");
        buildLog_ += "Error while compiling \
                     opencl source: Compiling CL to IR";
        return false;
    }
    // Save the binary in the interface class
    saveBinaryAndSetType(TYPE_COMPILED);
    return true;
#endif // !defined(WITH_LIGHTNING_COMPILER)
}

#if defined(WITH_LIGHTNING_COMPILER)
#if defined(ATI_OS_LINUX)
static pthread_once_t once = PTHREAD_ONCE_INIT;

static void
checkLLVM_BIN()
{
    if (llvmBin_.empty()) {
        Dl_info info;
        if (dladdr((const void*)&amd::Device::init, &info)) {
            llvmBin_ = dirname(strdup(info.dli_fname));
            size_t pos = llvmBin_.rfind("lib");
            if (pos != std::string::npos) {
                llvmBin_.replace(pos, 3, "bin");
            }
        }
    }
#if defined(DEBUG)
    std::string clangExe(llvmBin_ + "/clang");
    struct stat buf;
    if (stat(clangExe.c_str(), &buf)) {
        std::string msg("Could not find the Clang binary in " + llvmBin_);
        LogWarning(msg.c_str());
    }
#endif // defined(DEBUG)
}
#endif // defined(ATI_OS_LINUX)

std::auto_ptr<amd::opencl_driver::Compiler>
HSAILProgram::newCompilerInstance()
{
#if defined(ATI_OS_LINUX)
    pthread_once(&once, checkLLVM_BIN);
#endif // defined(ATI_OS_LINUX)
    return std::auto_ptr<amd::opencl_driver::Compiler>(
        amd::opencl_driver::CompilerFactory().CreateAMDGPUCompiler(llvmBin_));
}
#endif // defined(WITH_LIGHTNING_COMPILER)

} // namespace roc
#endif // WITHOUT_GPU_BACKEND
<|endoftext|>