<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

////////////////////////////////////////////////////////////////////////////
//                                                                        //
// AliTRDCalibraVdriftLinearFit                                           //
//                                                                        //
// Does the Vdrift an ExB calibration by applying a linear fit            //
//                                                                        //
// Author:                                                                //
//   R. Bailhache (R.Bailhache@gsi.de)                                    //
//                                                                        //
////////////////////////////////////////////////////////////////////////////

//Root includes
#include <TObjArray.h>
#include <TH2F.h>
#include <TString.h>
#include <TVectorD.h>
#include <TAxis.h>
#include <TLinearFitter.h>
#include <TMath.h>
#include <TTreeStream.h>

//header file
#include "AliTRDCalibraVdriftLinearFit.h"

ClassImp(AliTRDCalibraVdriftLinearFit) /*FOLD00*/

//_____________________________________________________________________
AliTRDCalibraVdriftLinearFit::AliTRDCalibraVdriftLinearFit() : /*FOLD00*/
  TObject(),
  fVersion(0),
  fLinearFitterHistoArray(540),
  fLinearFitterPArray(540),
  fLinearFitterEArray(540)
{
  //
  // default constructor
  //
}
//_____________________________________________________________________
AliTRDCalibraVdriftLinearFit::AliTRDCalibraVdriftLinearFit(const AliTRDCalibraVdriftLinearFit &ped) : /*FOLD00*/
  TObject(ped),
  fVersion(ped.fVersion),
  fLinearFitterHistoArray(540),
  fLinearFitterPArray(540),
  fLinearFitterEArray(540)
{
    //
    // copy constructor
    //
  for (Int_t idet = 0; idet < 540; idet++){

    const TVectorD     *vectorE     = (TVectorD*)ped.fLinearFitterEArray.UncheckedAt(idet);
    const TVectorD     *vectorP     = (TVectorD*)ped.fLinearFitterPArray.UncheckedAt(idet);
    const TH2S         *hped        = (TH2S*)ped.fLinearFitterHistoArray.UncheckedAt(idet);

    if ( vectorE != 0x0 ) fLinearFitterEArray.AddAt(new TVectorD(*vectorE), idet);
    if ( vectorP != 0x0 ) fLinearFitterPArray.AddAt(new TVectorD(*vectorP), idet);
    if ( hped != 0x0 ){
      TH2S *hNew = (TH2S *)hped->Clone();
      //hNew->SetDirectory(0);
      fLinearFitterHistoArray.AddAt(hNew,idet);
    }
  }
}
//_____________________________________________________________________
AliTRDCalibraVdriftLinearFit::AliTRDCalibraVdriftLinearFit(const TObjArray &obja) : /*FOLD00*/
  TObject(),
  fVersion(0),
  fLinearFitterHistoArray(540),
  fLinearFitterPArray(540),
  fLinearFitterEArray(540)
{
  //
  // constructor from a TObjArray
  //
  for (Int_t idet = 0; idet < 540; idet++){
    const TH2S         *hped        = (TH2S*)obja.UncheckedAt(idet);
    if ( hped != 0x0 ){
      TH2S *hNew = (TH2S *)hped->Clone();
      //hNew->SetDirectory(0);
      fLinearFitterHistoArray.AddAt(hNew,idet);
    }
  }
}
//_____________________________________________________________________
AliTRDCalibraVdriftLinearFit& AliTRDCalibraVdriftLinearFit::operator = (const  AliTRDCalibraVdriftLinearFit &source)
{
  //
  // assignment operator
  //
  if (&source == this) return *this;
  new (this) AliTRDCalibraVdriftLinearFit(source);

  return *this;
}
//_____________________________________________________________________
AliTRDCalibraVdriftLinearFit::~AliTRDCalibraVdriftLinearFit() /*FOLD00*/
{
  //
  // destructor
  //
  fLinearFitterHistoArray.Delete();
  fLinearFitterPArray.Delete();
  fLinearFitterEArray.Delete();

}
//_____________________________________________________________________________
void AliTRDCalibraVdriftLinearFit::Copy(TObject &c) const
{
  //
  // Copy function
  //

  AliTRDCalibraVdriftLinearFit& target = (AliTRDCalibraVdriftLinearFit &) c;

  // Copy only the histos
  for (Int_t idet = 0; idet < 540; idet++){
    if(fLinearFitterHistoArray.UncheckedAt(idet)){
      TH2S *hped1 = (TH2S *)target.GetLinearFitterHisto(idet,kTRUE);
      //hped1->SetDirectory(0);
      hped1->Add((const TH2S *)fLinearFitterHistoArray.UncheckedAt(idet));
    }
  }

  TObject::Copy(c);

}
//_____________________________________________________________________________
Long64_t AliTRDCalibraVdriftLinearFit::Merge(const TCollection* list)
{
  // Merge list of objects (needed by PROOF)

  if (!list)
    return 0;

  if (list->IsEmpty())
    return 1;

  TIterator* iter = list->MakeIterator();
  TObject* obj = 0;

  // collection of generated histograms
  Int_t count=0;
  while((obj = iter->Next()) != 0)
    {
      AliTRDCalibraVdriftLinearFit* entry = dynamic_cast<AliTRDCalibraVdriftLinearFit*>(obj);
      if (entry == 0) continue;

      // Copy only the histos
      for (Int_t idet = 0; idet < 540; idet++){
	if(entry->GetLinearFitterHisto(idet)){
	  TH2S *hped1 = (TH2S *)GetLinearFitterHisto(idet,kTRUE);
	  Double_t entriesa = hped1->GetEntries();
	  Double_t entriesb = ((TH2S *)entry->GetLinearFitterHisto(idet))->GetEntries();
	  if((entriesa + entriesb) < 5*32767) hped1->Add(entry->GetLinearFitterHisto(idet));
	}
      }

      count++;
    }

  return count;
}
//_____________________________________________________________________
void AliTRDCalibraVdriftLinearFit::Add(AliTRDCalibraVdriftLinearFit *ped)
{
  //
  // Add histo
  //

  fVersion++;

  for (Int_t idet = 0; idet < 540; idet++){
    const TH2S         *hped        = (TH2S*)ped->GetLinearFitterHisto(idet);
    //printf("idet %d\n",idet);
    if ( hped != 0x0 ){
      //printf("add\n");
      TH2S *hped1 = (TH2S *)GetLinearFitterHisto(idet,kTRUE);
      Double_t entriesa = hped1->GetEntries();
      Double_t entriesb = hped->GetEntries();
      if((entriesa + entriesb) < 5*32767) hped1->Add(hped);
    }
  }
}
//______________________________________________________________________________________
TH2S* AliTRDCalibraVdriftLinearFit::GetLinearFitterHisto(Int_t detector, Bool_t force)
{
    //
    // return pointer to TH2F histo
    // if force is true create a new histo if it doesn't exist allready
    //
    if ( !force || fLinearFitterHistoArray.UncheckedAt(detector) )
	return (TH2S*)fLinearFitterHistoArray.UncheckedAt(detector);

    // if we are forced and TLinearFitter doesn't yes exist create it

    // new TH2F
    TString name("LFDV");
    name += detector;
    name += "version";
    name +=  fVersion;

    TH2S *lfdv = new TH2S((const Char_t *)name,(const Char_t *) name
    		  ,36,-0.9,0.9,48
    		  ,-1.2,1.2);
    lfdv->SetXTitle("tan(phi_{track})");
    lfdv->SetYTitle("dy/dt");
    lfdv->SetZTitle("Number of clusters");
    lfdv->SetStats(0);
    lfdv->SetDirectory(0);

    fLinearFitterHistoArray.AddAt(lfdv,detector);
    return lfdv;
}
//______________________________________________________________________________________
Bool_t AliTRDCalibraVdriftLinearFit::GetParam(Int_t detector, TVectorD *param)
{
    //
    // return param for this detector
    //
  if ( fLinearFitterPArray.UncheckedAt(detector) ){
    const TVectorD     *vectorP     = (TVectorD*)fLinearFitterPArray.UncheckedAt(detector);
    if(!param) param = new TVectorD(2);
    for(Int_t k = 0; k < 2; k++){
      (*param)[k] = (*vectorP)[k];
    }
    return kTRUE;
  }
  else return kFALSE;

}
//______________________________________________________________________________________
Bool_t AliTRDCalibraVdriftLinearFit::GetError(Int_t detector, TVectorD *error)
{
    //
    // return error for this detector
    //
  if ( fLinearFitterEArray.UncheckedAt(detector) ){
    const TVectorD     *vectorE     = (TVectorD*)fLinearFitterEArray.UncheckedAt(detector);
    if(!error) error = new TVectorD(3);
    for(Int_t k = 0; k < 3; k++){
      (*error)[k] = (*vectorE)[k];
    }
    return kTRUE;
  }
  else return kFALSE;

}
//______________________________________________________________________________________
void AliTRDCalibraVdriftLinearFit::Update(Int_t detector, Float_t tnp, Float_t pars1)
{
    //
    // Fill the 2D histos for debugging
    //

  TH2S *h = ((TH2S *) GetLinearFitterHisto(detector,kTRUE));
  Double_t nbentries = h->GetEntries();
  if(nbentries < 5*32767) h->Fill(tnp,pars1);

}
//____________Functions fit Online CH2d________________________________________
void AliTRDCalibraVdriftLinearFit::FillPEArray()
{
  //
  // Fill fLinearFitterPArray and fLinearFitterEArray from inside
  //

  Int_t *arrayI = new Int_t[540];
  for(Int_t k = 0; k< 540; k++){
    arrayI[k] = 0;
  }

  // Loop over histos
  for(Int_t cb = 0; cb < 540; cb++){
    const TH2S *linearfitterhisto = (TH2S*)fLinearFitterHistoArray.UncheckedAt(cb);
    //printf("Processing the detector cb %d we find %d\n",cb, (Bool_t) linearfitterhisto);

    if ( linearfitterhisto != 0 ){

      // Fill a linearfitter
      TAxis *xaxis = linearfitterhisto->GetXaxis();
      TAxis *yaxis = linearfitterhisto->GetYaxis();
      TLinearFitter linearfitter = TLinearFitter(2,"pol1");
      //printf("test\n");
      for(Int_t ibinx = 0; ibinx < linearfitterhisto->GetNbinsX(); ibinx++){
	for(Int_t ibiny = 0; ibiny < linearfitterhisto->GetNbinsY(); ibiny++){
	  if(linearfitterhisto->GetBinContent(ibinx+1,ibiny+1)>0){
	    Double_t x = xaxis->GetBinCenter(ibinx+1);
	    Double_t y = yaxis->GetBinCenter(ibiny+1);
	    for(Int_t k = 0; k < (Int_t)linearfitterhisto->GetBinContent(ibinx+1,ibiny+1); k++){
	      linearfitter.AddPoint(&x,y);
	      arrayI[cb]++;
	    }
	  }
	}
      }

      //printf("Find %d entries for the detector %d\n",arrayI[cb],cb);

      // Eval the linear fitter
      if(arrayI[cb]>10){
	TVectorD  *par  = new TVectorD(2);
	TVectorD   pare = TVectorD(2);
	TVectorD  *parE = new TVectorD(3);
	linearfitter.Eval();
	linearfitter.GetParameters(*par);
	linearfitter.GetErrors(pare);
	Float_t  ppointError =  TMath::Sqrt(TMath::Abs(linearfitter.GetChisquare())/arrayI[cb]);
	(*parE)[0] = pare[0]*ppointError;
	(*parE)[1] = pare[1]*ppointError;
	(*parE)[2] = (Double_t) arrayI[cb];
	fLinearFitterPArray.AddAt(par,cb);
	fLinearFitterEArray.AddAt(parE,cb);
	//par->Print();
	//parE->Print();
      }

      delete linearfitterhisto;

    }// if something
  }

}

<commit_msg>Bug fix by Raphaelle<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

////////////////////////////////////////////////////////////////////////////
//                                                                        //
// AliTRDCalibraVdriftLinearFit                                           //
//                                                                        //
// Does the Vdrift an ExB calibration by applying a linear fit            //
//                                                                        //
// Author:                                                                //
//   R. Bailhache (R.Bailhache@gsi.de)                                    //
//                                                                        //
////////////////////////////////////////////////////////////////////////////

//Root includes
#include <TObjArray.h>
#include <TH2F.h>
#include <TString.h>
#include <TVectorD.h>
#include <TAxis.h>
#include <TLinearFitter.h>
#include <TMath.h>
#include <TTreeStream.h>

//header file
#include "AliTRDCalibraVdriftLinearFit.h"

ClassImp(AliTRDCalibraVdriftLinearFit) /*FOLD00*/

//_____________________________________________________________________
AliTRDCalibraVdriftLinearFit::AliTRDCalibraVdriftLinearFit() : /*FOLD00*/
  TObject(),
  fVersion(0),
  fLinearFitterHistoArray(540),
  fLinearFitterPArray(540),
  fLinearFitterEArray(540)
{
  //
  // default constructor
  //
}
//_____________________________________________________________________
AliTRDCalibraVdriftLinearFit::AliTRDCalibraVdriftLinearFit(const AliTRDCalibraVdriftLinearFit &ped) : /*FOLD00*/
  TObject(ped),
  fVersion(ped.fVersion),
  fLinearFitterHistoArray(540),
  fLinearFitterPArray(540),
  fLinearFitterEArray(540)
{
    //
    // copy constructor
    //
  for (Int_t idet = 0; idet < 540; idet++){

    const TVectorD     *vectorE     = (TVectorD*)ped.fLinearFitterEArray.UncheckedAt(idet);
    const TVectorD     *vectorP     = (TVectorD*)ped.fLinearFitterPArray.UncheckedAt(idet);
    const TH2S         *hped        = (TH2S*)ped.fLinearFitterHistoArray.UncheckedAt(idet);

    if ( vectorE != 0x0 ) fLinearFitterEArray.AddAt(new TVectorD(*vectorE), idet);
    if ( vectorP != 0x0 ) fLinearFitterPArray.AddAt(new TVectorD(*vectorP), idet);
    if ( hped != 0x0 ){
      TH2S *hNew = (TH2S *)hped->Clone();
      //hNew->SetDirectory(0);
      fLinearFitterHistoArray.AddAt(hNew,idet);
    }
  }
}
//_____________________________________________________________________
AliTRDCalibraVdriftLinearFit::AliTRDCalibraVdriftLinearFit(const TObjArray &obja) : /*FOLD00*/
  TObject(),
  fVersion(0),
  fLinearFitterHistoArray(540),
  fLinearFitterPArray(540),
  fLinearFitterEArray(540)
{
  //
  // constructor from a TObjArray
  //
  for (Int_t idet = 0; idet < 540; idet++){
    const TH2S         *hped        = (TH2S*)obja.UncheckedAt(idet);
    if ( hped != 0x0 ){
      TH2S *hNew = (TH2S *)hped->Clone();
      //hNew->SetDirectory(0);
      fLinearFitterHistoArray.AddAt(hNew,idet);
    }
  }
}
//_____________________________________________________________________
AliTRDCalibraVdriftLinearFit& AliTRDCalibraVdriftLinearFit::operator = (const  AliTRDCalibraVdriftLinearFit &source)
{
  //
  // assignment operator
  //
  if (&source == this) return *this;
  new (this) AliTRDCalibraVdriftLinearFit(source);

  return *this;
}
//_____________________________________________________________________
AliTRDCalibraVdriftLinearFit::~AliTRDCalibraVdriftLinearFit() /*FOLD00*/
{
  //
  // destructor
  //
  fLinearFitterHistoArray.Delete();
  fLinearFitterPArray.Delete();
  fLinearFitterEArray.Delete();

}
//_____________________________________________________________________________
void AliTRDCalibraVdriftLinearFit::Copy(TObject &c) const
{
  //
  // Copy function
  //

  AliTRDCalibraVdriftLinearFit& target = (AliTRDCalibraVdriftLinearFit &) c;

  // Copy only the histos
  for (Int_t idet = 0; idet < 540; idet++){
    if(fLinearFitterHistoArray.UncheckedAt(idet)){
      TH2S *hped1 = (TH2S *)target.GetLinearFitterHisto(idet,kTRUE);
      //hped1->SetDirectory(0);
      hped1->Add((const TH2S *)fLinearFitterHistoArray.UncheckedAt(idet));
    }
  }

  TObject::Copy(c);

}
//_____________________________________________________________________________
Long64_t AliTRDCalibraVdriftLinearFit::Merge(const TCollection* list)
{
  // Merge list of objects (needed by PROOF)

  if (!list)
    return 0;

  if (list->IsEmpty())
    return 1;

  TIterator* iter = list->MakeIterator();
  TObject* obj = 0;

  // collection of generated histograms
  Int_t count=0;
  while((obj = iter->Next()) != 0)
    {
      AliTRDCalibraVdriftLinearFit* entry = dynamic_cast<AliTRDCalibraVdriftLinearFit*>(obj);
      if (entry == 0) continue;

      // Copy only the histos
      for (Int_t idet = 0; idet < 540; idet++){
	if(entry->GetLinearFitterHisto(idet)){
	  TH2S *hped1 = (TH2S *)GetLinearFitterHisto(idet,kTRUE);
	  Double_t entriesa = hped1->GetEntries();
	  Double_t entriesb = ((TH2S *)entry->GetLinearFitterHisto(idet))->GetEntries();
	  if((entriesa + entriesb) < 5*32767) hped1->Add(entry->GetLinearFitterHisto(idet));
	}
      }

      count++;
    }

  return count;
}
//_____________________________________________________________________
void AliTRDCalibraVdriftLinearFit::Add(AliTRDCalibraVdriftLinearFit *ped)
{
  //
  // Add histo
  //

  fVersion++;

  for (Int_t idet = 0; idet < 540; idet++){
    const TH2S         *hped        = (TH2S*)ped->GetLinearFitterHisto(idet);
    //printf("idet %d\n",idet);
    if ( hped != 0x0 ){
      //printf("add\n");
      TH2S *hped1 = (TH2S *)GetLinearFitterHisto(idet,kTRUE);
      Double_t entriesa = hped1->GetEntries();
      Double_t entriesb = hped->GetEntries();
      if((entriesa + entriesb) < 5*32767) hped1->Add(hped);
    }
  }
}
//______________________________________________________________________________________
TH2S* AliTRDCalibraVdriftLinearFit::GetLinearFitterHisto(Int_t detector, Bool_t force)
{
    //
    // return pointer to TH2F histo
    // if force is true create a new histo if it doesn't exist allready
    //
    if ( !force || fLinearFitterHistoArray.UncheckedAt(detector) )
	return (TH2S*)fLinearFitterHistoArray.UncheckedAt(detector);

    // if we are forced and TLinearFitter doesn't yes exist create it

    // new TH2F
    TString name("LFDV");
    name += detector;
    name += "version";
    name +=  fVersion;

    TH2S *lfdv = new TH2S((const Char_t *)name,(const Char_t *) name
    		  ,36,-0.9,0.9,48
    		  ,-1.2,1.2);
    lfdv->SetXTitle("tan(phi_{track})");
    lfdv->SetYTitle("dy/dt");
    lfdv->SetZTitle("Number of clusters");
    lfdv->SetStats(0);
    lfdv->SetDirectory(0);

    fLinearFitterHistoArray.AddAt(lfdv,detector);
    return lfdv;
}
//______________________________________________________________________________________
Bool_t AliTRDCalibraVdriftLinearFit::GetParam(Int_t detector, TVectorD *param)
{
    //
    // return param for this detector
    //
  if ( fLinearFitterPArray.UncheckedAt(detector) ){
    const TVectorD     *vectorP     = (TVectorD*)fLinearFitterPArray.UncheckedAt(detector);
    if(!param) param = new TVectorD(2);
    for(Int_t k = 0; k < 2; k++){
      (*param)[k] = (*vectorP)[k];
    }
    return kTRUE;
  }
  else return kFALSE;

}
//______________________________________________________________________________________
Bool_t AliTRDCalibraVdriftLinearFit::GetError(Int_t detector, TVectorD *error)
{
    //
    // return error for this detector
    //
  if ( fLinearFitterEArray.UncheckedAt(detector) ){
    const TVectorD     *vectorE     = (TVectorD*)fLinearFitterEArray.UncheckedAt(detector);
    if(!error) error = new TVectorD(3);
    for(Int_t k = 0; k < 3; k++){
      (*error)[k] = (*vectorE)[k];
    }
    return kTRUE;
  }
  else return kFALSE;

}
//______________________________________________________________________________________
void AliTRDCalibraVdriftLinearFit::Update(Int_t detector, Float_t tnp, Float_t pars1)
{
    //
    // Fill the 2D histos for debugging
    //

  TH2S *h = ((TH2S *) GetLinearFitterHisto(detector,kTRUE));
  Double_t nbentries = h->GetEntries();
  if(nbentries < 5*32767) h->Fill(tnp,pars1);

}
//____________Functions fit Online CH2d________________________________________
void AliTRDCalibraVdriftLinearFit::FillPEArray()
{
  //
  // Fill fLinearFitterPArray and fLinearFitterEArray from inside
  //

  Int_t *arrayI = new Int_t[540];
  for(Int_t k = 0; k< 540; k++){
    arrayI[k] = 0;
  }

  // Loop over histos
  for(Int_t cb = 0; cb < 540; cb++){
    const TH2S *linearfitterhisto = (TH2S*)fLinearFitterHistoArray.UncheckedAt(cb);
    //printf("Processing the detector cb %d we find %d\n",cb, (Bool_t) linearfitterhisto);

    if ( linearfitterhisto != 0 ){

      // Fill a linearfitter
      TAxis *xaxis = linearfitterhisto->GetXaxis();
      TAxis *yaxis = linearfitterhisto->GetYaxis();
      TLinearFitter linearfitter = TLinearFitter(2,"pol1");
      //printf("test\n");
      for(Int_t ibinx = 0; ibinx < linearfitterhisto->GetNbinsX(); ibinx++){
	for(Int_t ibiny = 0; ibiny < linearfitterhisto->GetNbinsY(); ibiny++){
	  if(linearfitterhisto->GetBinContent(ibinx+1,ibiny+1)>0){
	    Double_t x = xaxis->GetBinCenter(ibinx+1);
	    Double_t y = yaxis->GetBinCenter(ibiny+1);
	    for(Int_t k = 0; k < (Int_t)linearfitterhisto->GetBinContent(ibinx+1,ibiny+1); k++){
	      linearfitter.AddPoint(&x,y);
	      arrayI[cb]++;
	    }
	  }
	}
      }

      //printf("Find %d entries for the detector %d\n",arrayI[cb],cb);

      // Eval the linear fitter
      if(arrayI[cb]>10){
	TVectorD  *par  = new TVectorD(2);
	TVectorD   pare = TVectorD(2);
	TVectorD  *parE = new TVectorD(3);
	linearfitter.Eval();
	linearfitter.GetParameters(*par);
	linearfitter.GetErrors(pare);
	Float_t  ppointError =  TMath::Sqrt(TMath::Abs(linearfitter.GetChisquare())/arrayI[cb]);
	(*parE)[0] = pare[0]*ppointError;
	(*parE)[1] = pare[1]*ppointError;
	(*parE)[2] = (Double_t) arrayI[cb];
	fLinearFitterPArray.AddAt(par,cb);
	fLinearFitterEArray.AddAt(parE,cb);
	//par->Print();
	//parE->Print();
      }

      //delete linearfitterhisto;

    }// if something
  }

}
<|endoftext|>


<commit_before>/*=========================================================================

  Library   : Image Registration Toolkit (IRTK)
  Module    : $Id$
  Copyright : Imperial College, Department of Computing
              Visual Information Processing (VIP), 2008 onwards
  Date      : $Date$
  Version   : $Revision$
  Changes   : $Author$

=========================================================================*/

#include <irtkImage.h>

#include <irtkFileToImage.h>
#include <irtkNIFTI.h>

irtkBaseImage::irtkBaseImage()
{
  _matI2W = irtkMatrix(4, 4);
  _matW2I = irtkMatrix(4, 4);

  // Update transformation matrix
  this->UpdateMatrix();
}

irtkBaseImage::irtkBaseImage(const irtkBaseImage &image) : irtkObject(image)
{
  _attr   = image._attr;
  _matI2W = image._matI2W;
  _matW2I = image._matW2I;
}

irtkBaseImage::~irtkBaseImage()
{
	// Update image attributes
	_attr = irtkImageAttributes();

  // Update transformation matrix
  this->UpdateMatrix();
}

irtkBaseImage *irtkBaseImage::New(const char *filename)
{
  irtkBaseImage *image;

  irtkFileToImage *reader = irtkFileToImage::New(filename);
  image = reader->GetOutput();
  delete reader;

  return image;
}

irtkBaseImage *irtkBaseImage::New(const irtkBaseImage *image)
{
  // Convert image
  if (dynamic_cast<const irtkGenericImage<char> *>(image) != NULL) {
    return new irtkGenericImage<char>(*(dynamic_cast<const irtkGenericImage<char> *>(image)));
  } else if (dynamic_cast<const irtkGenericImage<unsigned char> *>(image) != NULL) {
    return new irtkGenericImage<unsigned char>(*(dynamic_cast<const irtkGenericImage<unsigned char> *>(image)));
  } else if (dynamic_cast<const irtkGenericImage<short> *>(image) != NULL) {
    return new irtkGenericImage<short>(*(dynamic_cast<const irtkGenericImage<short> *>(image)));
  } else if (dynamic_cast<const irtkGenericImage<unsigned short> *>(image) != NULL) {
    return new irtkGenericImage<unsigned short>(*(dynamic_cast<const irtkGenericImage<unsigned short> *>(image)));
  } else if (dynamic_cast<const irtkGenericImage<float> *>(image) != NULL) {
    return new irtkGenericImage<float>(*(dynamic_cast<const irtkGenericImage<float> *>(image)));
  } else if (dynamic_cast<const irtkGenericImage<double> *>(image) != NULL) {
    return new irtkGenericImage<double>(*(dynamic_cast<const irtkGenericImage<double> *>(image)));
  } else {
  	cerr << "irtkBaseImage::New: Cannot allocate image of unknown type" << endl;
  	exit(1);
  }
}

void irtkBaseImage::UpdateMatrix()
{
  // Note that the update of zaxis is taken place in the
  // Initialize routines, in case a specific zaxis is passed.

  // Update image to world coordinate system matrix
  _matI2W.Ident();
  _matI2W(0, 0) = _attr._xaxis[0];
  _matI2W(1, 0) = _attr._xaxis[1];
  _matI2W(2, 0) = _attr._xaxis[2];
  _matI2W(0, 1) = _attr._yaxis[0];
  _matI2W(1, 1) = _attr._yaxis[1];
  _matI2W(2, 1) = _attr._yaxis[2];
  _matI2W(0, 2) = _attr._zaxis[0];
  _matI2W(1, 2) = _attr._zaxis[1];
  _matI2W(2, 2) = _attr._zaxis[2];

  irtkMatrix tmp1(4, 4);
  tmp1.Ident();
  tmp1(0, 3) = - (_attr._x - 1) / 2.0;
  tmp1(1, 3) = - (_attr._y - 1) / 2.0;
  tmp1(2, 3) = - (_attr._z - 1) / 2.0;

  irtkMatrix tmp2(4, 4);
  tmp2.Ident();
  tmp2(0, 0) = _attr._dx;
  tmp2(1, 1) = _attr._dy;
  tmp2(2, 2) = _attr._dz;

  irtkMatrix tmp3(4, 4);
  tmp3.Ident();
  tmp3(0, 3) = _attr._xorigin;
  tmp3(1, 3) = _attr._yorigin;
  tmp3(2, 3) = _attr._zorigin;

  _matI2W = tmp3 * (_matI2W * (tmp2 * tmp1));

  // Update world to image coordinate system matrix

  // _matW2I is the inverse of the above matrix _matI2W but we can calculate
  // it exactly because we know analytic expressions for the individual matrices
  // that form its product.  For example, the rotation part inverse below is
  // the transpose of the one above as they are orthogonal matrices.

  _matW2I.Ident();
  _matW2I(0, 0) = _attr._xaxis[0];
  _matW2I(0, 1) = _attr._xaxis[1];
  _matW2I(0, 2) = _attr._xaxis[2];
  _matW2I(1, 0) = _attr._yaxis[0];
  _matW2I(1, 1) = _attr._yaxis[1];
  _matW2I(1, 2) = _attr._yaxis[2];
  _matW2I(2, 0) = _attr._zaxis[0];
  _matW2I(2, 1) = _attr._zaxis[1];
  _matW2I(2, 2) = _attr._zaxis[2];

  tmp1.Ident();
  tmp1(0, 3) = (_attr._x - 1) / 2.0;
  tmp1(1, 3) = (_attr._y - 1) / 2.0;
  tmp1(2, 3) = (_attr._z - 1) / 2.0;

  tmp2.Ident();
  tmp2(0, 0) = 1.0 / _attr._dx;
  tmp2(1, 1) = 1.0 / _attr._dy;
  tmp2(2, 2) = 1.0 / _attr._dz;

  tmp3.Ident();
  tmp3(0, 3) = - _attr._xorigin;
  tmp3(1, 3) = - _attr._yorigin;
  tmp3(2, 3) = - _attr._zorigin;

  _matW2I = tmp1 * (tmp2 * (_matW2I * tmp3));
}

void irtkBaseImage::Update(const irtkImageAttributes &attr)
{
  _attr = attr;

  // Update transformation matrix
  this->UpdateMatrix();
}

void irtkBaseImage::Orientation(int &i, int &j, int &k) const
{

#ifdef HAS_NIFTI

  // Work out orientation of axis
  mat44 mat_44;
  for (i = 0; i < 4; ++i) {
    for (j = 0; j < 4; ++j) {
      mat_44.m[i][j] = this->GetImageToWorldMatrix()(i, j);
    }
  }
  nifti_mat44_to_orientation(mat_44, &i, &j, &k);

#else

  cerr << "irtkBaseImage::Orientation: Requires NIFTI support. Please recompile with NIFTI enabled" << endl;
  exit(1);

#endif
}

void irtkBaseImage::GetMinMaxAsDouble(double *min, double *max) const
{
  int x, y, z, t;

  *min = 0;
  *max = 0;

  if (this->GetNumberOfVoxels() > 0) {
    *min = this->GetAsDouble(0, 0, 0, 0);
    *max = this->GetAsDouble(0, 0, 0, 0);
  }

  for (t = 0; t < this->GetT(); t++) {
    for (z = 0; z < this->GetZ(); z++) {
      for (y = 0; y < this->GetY(); y++) {
        for (x = 0; x < this->GetX(); x++) {
          if (this->GetAsDouble(x, y, z, t) < *min) *min = this->GetAsDouble(x, y, z, t);
          if (this->GetAsDouble(x, y, z, t) > *max) *max = this->GetAsDouble(x, y, z, t);
        }
      }
    }
  }
}

void irtkBaseImage::PutMinMaxAsDouble(double min, double max)
{
  int x, y, z, t;
  double min_val, max_val;

  // Get lower and upper bound
  this->GetMinMaxAsDouble(&min_val, &max_val);

  for (t = 0; t < this->GetT(); t++) {
    for (z = 0; z < this->GetZ(); z++) {
      for (y = 0; y < this->GetY(); y++) {
        for (x = 0; x < this->GetX(); x++) {
          this->PutAsDouble(x, y, z, t, ((this->GetAsDouble(x, y, z, t) - min_val) / (max_val - min_val)) * (max - min) + min);
        }
      }
    }
  }
}

void irtkBaseImage::Print()
{
  // Print image dimensions
  cout << "Image size is " << _attr._x << " " << _attr._y << " " << _attr._z << " " << _attr._t << endl;
  // Print voxel dimensions
  cout << "Voxel size is " << _attr._dx << " " << _attr._dy << " "
  << _attr._dz << " " << _attr._dt << endl;
  // Print origin
  cout << "Image origin is " << _attr._xorigin << " " << _attr._yorigin << " " << _attr._zorigin << " " << _attr._torigin << endl;
  // Print x-axis
  printf("X-axis is % 0.2f % 0.2f % 0.2f\n", _attr._xaxis[0], _attr._xaxis[1], _attr._xaxis[2]);
  // Print y-axis
  printf("Y-axis is % 0.2f % 0.2f % 0.2f\n", _attr._yaxis[0], _attr._yaxis[1], _attr._yaxis[2]);
  // Print z-axis
  printf("Z-axis is % 0.2f % 0.2f % 0.2f\n", _attr._zaxis[0], _attr._zaxis[1], _attr._zaxis[2]);
}
<commit_msg>Modified Print() to direct all output to cout.<commit_after>/*=========================================================================

  Library   : Image Registration Toolkit (IRTK)
  Module    : $Id$
  Copyright : Imperial College, Department of Computing
              Visual Information Processing (VIP), 2008 onwards
  Date      : $Date$
  Version   : $Revision$
  Changes   : $Author$

=========================================================================*/

#include <irtkImage.h>

#include <irtkFileToImage.h>
#include <irtkNIFTI.h>

irtkBaseImage::irtkBaseImage()
{
  _matI2W = irtkMatrix(4, 4);
  _matW2I = irtkMatrix(4, 4);

  // Update transformation matrix
  this->UpdateMatrix();
}

irtkBaseImage::irtkBaseImage(const irtkBaseImage &image) : irtkObject(image)
{
  _attr   = image._attr;
  _matI2W = image._matI2W;
  _matW2I = image._matW2I;
}

irtkBaseImage::~irtkBaseImage()
{
	// Update image attributes
	_attr = irtkImageAttributes();

  // Update transformation matrix
  this->UpdateMatrix();
}

irtkBaseImage *irtkBaseImage::New(const char *filename)
{
  irtkBaseImage *image;

  irtkFileToImage *reader = irtkFileToImage::New(filename);
  image = reader->GetOutput();
  delete reader;

  return image;
}

irtkBaseImage *irtkBaseImage::New(const irtkBaseImage *image)
{
  // Convert image
  if (dynamic_cast<const irtkGenericImage<char> *>(image) != NULL) {
    return new irtkGenericImage<char>(*(dynamic_cast<const irtkGenericImage<char> *>(image)));
  } else if (dynamic_cast<const irtkGenericImage<unsigned char> *>(image) != NULL) {
    return new irtkGenericImage<unsigned char>(*(dynamic_cast<const irtkGenericImage<unsigned char> *>(image)));
  } else if (dynamic_cast<const irtkGenericImage<short> *>(image) != NULL) {
    return new irtkGenericImage<short>(*(dynamic_cast<const irtkGenericImage<short> *>(image)));
  } else if (dynamic_cast<const irtkGenericImage<unsigned short> *>(image) != NULL) {
    return new irtkGenericImage<unsigned short>(*(dynamic_cast<const irtkGenericImage<unsigned short> *>(image)));
  } else if (dynamic_cast<const irtkGenericImage<float> *>(image) != NULL) {
    return new irtkGenericImage<float>(*(dynamic_cast<const irtkGenericImage<float> *>(image)));
  } else if (dynamic_cast<const irtkGenericImage<double> *>(image) != NULL) {
    return new irtkGenericImage<double>(*(dynamic_cast<const irtkGenericImage<double> *>(image)));
  } else {
  	cerr << "irtkBaseImage::New: Cannot allocate image of unknown type" << endl;
  	exit(1);
  }
}

void irtkBaseImage::UpdateMatrix()
{
  // Note that the update of zaxis is taken place in the
  // Initialize routines, in case a specific zaxis is passed.

  // Update image to world coordinate system matrix
  _matI2W.Ident();
  _matI2W(0, 0) = _attr._xaxis[0];
  _matI2W(1, 0) = _attr._xaxis[1];
  _matI2W(2, 0) = _attr._xaxis[2];
  _matI2W(0, 1) = _attr._yaxis[0];
  _matI2W(1, 1) = _attr._yaxis[1];
  _matI2W(2, 1) = _attr._yaxis[2];
  _matI2W(0, 2) = _attr._zaxis[0];
  _matI2W(1, 2) = _attr._zaxis[1];
  _matI2W(2, 2) = _attr._zaxis[2];

  irtkMatrix tmp1(4, 4);
  tmp1.Ident();
  tmp1(0, 3) = - (_attr._x - 1) / 2.0;
  tmp1(1, 3) = - (_attr._y - 1) / 2.0;
  tmp1(2, 3) = - (_attr._z - 1) / 2.0;

  irtkMatrix tmp2(4, 4);
  tmp2.Ident();
  tmp2(0, 0) = _attr._dx;
  tmp2(1, 1) = _attr._dy;
  tmp2(2, 2) = _attr._dz;

  irtkMatrix tmp3(4, 4);
  tmp3.Ident();
  tmp3(0, 3) = _attr._xorigin;
  tmp3(1, 3) = _attr._yorigin;
  tmp3(2, 3) = _attr._zorigin;

  _matI2W = tmp3 * (_matI2W * (tmp2 * tmp1));

  // Update world to image coordinate system matrix

  // _matW2I is the inverse of the above matrix _matI2W but we can calculate
  // it exactly because we know analytic expressions for the individual matrices
  // that form its product.  For example, the rotation part inverse below is
  // the transpose of the one above as they are orthogonal matrices.

  _matW2I.Ident();
  _matW2I(0, 0) = _attr._xaxis[0];
  _matW2I(0, 1) = _attr._xaxis[1];
  _matW2I(0, 2) = _attr._xaxis[2];
  _matW2I(1, 0) = _attr._yaxis[0];
  _matW2I(1, 1) = _attr._yaxis[1];
  _matW2I(1, 2) = _attr._yaxis[2];
  _matW2I(2, 0) = _attr._zaxis[0];
  _matW2I(2, 1) = _attr._zaxis[1];
  _matW2I(2, 2) = _attr._zaxis[2];

  tmp1.Ident();
  tmp1(0, 3) = (_attr._x - 1) / 2.0;
  tmp1(1, 3) = (_attr._y - 1) / 2.0;
  tmp1(2, 3) = (_attr._z - 1) / 2.0;

  tmp2.Ident();
  tmp2(0, 0) = 1.0 / _attr._dx;
  tmp2(1, 1) = 1.0 / _attr._dy;
  tmp2(2, 2) = 1.0 / _attr._dz;

  tmp3.Ident();
  tmp3(0, 3) = - _attr._xorigin;
  tmp3(1, 3) = - _attr._yorigin;
  tmp3(2, 3) = - _attr._zorigin;

  _matW2I = tmp1 * (tmp2 * (_matW2I * tmp3));
}

void irtkBaseImage::Update(const irtkImageAttributes &attr)
{
  _attr = attr;

  // Update transformation matrix
  this->UpdateMatrix();
}

void irtkBaseImage::Orientation(int &i, int &j, int &k) const
{

#ifdef HAS_NIFTI

  // Work out orientation of axis
  mat44 mat_44;
  for (i = 0; i < 4; ++i) {
    for (j = 0; j < 4; ++j) {
      mat_44.m[i][j] = this->GetImageToWorldMatrix()(i, j);
    }
  }
  nifti_mat44_to_orientation(mat_44, &i, &j, &k);

#else

  cerr << "irtkBaseImage::Orientation: Requires NIFTI support. Please recompile with NIFTI enabled" << endl;
  exit(1);

#endif
}

void irtkBaseImage::GetMinMaxAsDouble(double *min, double *max) const
{
  int x, y, z, t;

  *min = 0;
  *max = 0;

  if (this->GetNumberOfVoxels() > 0) {
    *min = this->GetAsDouble(0, 0, 0, 0);
    *max = this->GetAsDouble(0, 0, 0, 0);
  }

  for (t = 0; t < this->GetT(); t++) {
    for (z = 0; z < this->GetZ(); z++) {
      for (y = 0; y < this->GetY(); y++) {
        for (x = 0; x < this->GetX(); x++) {
          if (this->GetAsDouble(x, y, z, t) < *min) *min = this->GetAsDouble(x, y, z, t);
          if (this->GetAsDouble(x, y, z, t) > *max) *max = this->GetAsDouble(x, y, z, t);
        }
      }
    }
  }
}

void irtkBaseImage::PutMinMaxAsDouble(double min, double max)
{
  int x, y, z, t;
  double min_val, max_val;

  // Get lower and upper bound
  this->GetMinMaxAsDouble(&min_val, &max_val);

  for (t = 0; t < this->GetT(); t++) {
    for (z = 0; z < this->GetZ(); z++) {
      for (y = 0; y < this->GetY(); y++) {
        for (x = 0; x < this->GetX(); x++) {
          this->PutAsDouble(x, y, z, t, ((this->GetAsDouble(x, y, z, t) - min_val) / (max_val - min_val)) * (max - min) + min);
        }
      }
    }
  }
}

void irtkBaseImage::Print()
{
  char buffer[256];
  // Print image dimensions
  cout << "Image size is " << _attr._x << " " << _attr._y << " " << _attr._z << " " << _attr._t << endl;
  // Print voxel dimensions
  cout << "Voxel size is " << _attr._dx << " " << _attr._dy << " "
  << _attr._dz << " " << _attr._dt << endl;
  // Print origin
  cout << "Image origin is " << _attr._xorigin << " " << _attr._yorigin << " " << _attr._zorigin << " " << _attr._torigin << endl;
  // Print x-axis
  sprintf(buffer,"X-axis is % 0.2f % 0.2f % 0.2f\n", _attr._xaxis[0], _attr._xaxis[1], _attr._xaxis[2]);
  cout<<buffer;
  // Print y-axis
  sprintf(buffer,"Y-axis is % 0.2f % 0.2f % 0.2f\n", _attr._yaxis[0], _attr._yaxis[1], _attr._yaxis[2]);
  cout<<buffer;
  // Print z-axis
  sprintf(buffer,"Z-axis is % 0.2f % 0.2f % 0.2f\n", _attr._zaxis[0], _attr._zaxis[1], _attr._zaxis[2]);
  cout<<buffer;
}
<|endoftext|>


<commit_before>#include "text/textUtil.h"

#include "platform.h"

namespace Tangram {

float TextWrapper::getShapeRangeWidth(const alfons::LineLayout& _line) {
    float maxWidth = 0;

    float lineWidth = 0;
    size_t charCount = 0;
    size_t shapeCount = 0;

    float lastWidth = 0;
    size_t lastShape = 0;
    size_t lastChar = 0;

    for (auto it = _line.shapes().begin(), end = _line.shapes().end(); it != end; it++) {

        auto &shape = *it;

        charCount++;
        shapeCount++;
        lineWidth += _line.advance(shape);

        if (shape.mustBreak) {
            lastShape = shapeCount;
            lastChar = charCount;
            lastWidth = lineWidth;

            // Append shapes of current glyph cluster
            while ((it+1 != end) && !(it+1)->cluster) {
                it++;
                lineWidth += _line.advance(*it);
                shapeCount++;
            }

            auto& endShape = _line.shapes()[lastShape-1];

            if (endShape.isSpace) {
                lineWidth -= _line.advance(endShape);
                lastWidth -= _line.advance(endShape);
            }

            m_lineWraps.emplace_back(lastShape, lastWidth);
            maxWidth = std::max(maxWidth, lastWidth);

            lineWidth -= lastWidth;
            charCount -= lastChar;
            lastShape = 0;
        }
    }

    if (charCount > 0) {
        m_lineWraps.emplace_back(shapeCount, lineWidth);
        maxWidth = std::max(maxWidth, lineWidth);
    }

    return maxWidth;
}

void TextWrapper::clearWraps() {
    m_lineWraps.clear();
}

int TextWrapper::draw(alfons::TextBatch& _batch, float _maxWidth, const alfons::LineLayout& _line,
                      TextLabelProperty::Align _alignment, float _lineSpacing,
                      alfons::LineMetrics& _layoutMetrics) {
    size_t shapeStart = 0;
    glm::vec2 position;

    for (auto wrap : m_lineWraps) {
        alfons::LineMetrics lineMetrics;

        switch(_alignment) {
            case TextLabelProperty::Align::center:
            case TextLabelProperty::Align::none:
                position.x = (_maxWidth - wrap.second) * 0.5;
                break;
            case TextLabelProperty::Align::right:
                position.x = (_maxWidth - wrap.second);
                break;
            default:
                position.x = 0;
        }

        size_t shapeEnd = wrap.first;

        // Draw line quads
        _batch.drawShapeRange(_line, shapeStart, shapeEnd, position, lineMetrics);

        shapeStart = shapeEnd;

        // FIXME hardcoded value for SDF radius 6
        float height = lineMetrics.height();
        height -= (2 * 6) * _line.scale(); // substract glyph padding
        height += _lineSpacing; // add some custom line offset

        position.y += height;

        _layoutMetrics.addExtents(lineMetrics.aabb);
    }

    return int(m_lineWraps.size());
}

}
<commit_msg>Include all shaped glyph from the last cluster (#1637)<commit_after>#include "text/textUtil.h"

#include "platform.h"

namespace Tangram {

float TextWrapper::getShapeRangeWidth(const alfons::LineLayout& _line) {
    float maxWidth = 0;

    float lineWidth = 0;
    size_t charCount = 0;
    size_t shapeCount = 0;

    float lastWidth = 0;
    size_t lastShape = 0;
    size_t lastChar = 0;

    for (auto it = _line.shapes().begin(), end = _line.shapes().end(); it != end; it++) {

        auto &shape = *it;

        charCount++;
        shapeCount++;
        lineWidth += _line.advance(shape);

        if (shape.mustBreak) {
            lastWidth = lineWidth;

            // Append shapes of current glyph cluster
            while ((it+1 != end) && !(it+1)->cluster) {
                it++;
                lineWidth += _line.advance(*it);
                shapeCount++;
            }

            lastChar = charCount;
            lastShape = shapeCount;

            auto& endShape = _line.shapes()[lastShape-1];

            if (endShape.isSpace) {
                lineWidth -= _line.advance(endShape);
                lastWidth -= _line.advance(endShape);
            }

            m_lineWraps.emplace_back(lastShape, lastWidth);
            maxWidth = std::max(maxWidth, lastWidth);

            lineWidth -= lastWidth;
            charCount -= lastChar;
            lastShape = 0;
        }
    }

    if (charCount > 0) {
        m_lineWraps.emplace_back(shapeCount, lineWidth);
        maxWidth = std::max(maxWidth, lineWidth);
    }

    return maxWidth;
}

void TextWrapper::clearWraps() {
    m_lineWraps.clear();
}

int TextWrapper::draw(alfons::TextBatch& _batch, float _maxWidth, const alfons::LineLayout& _line,
                      TextLabelProperty::Align _alignment, float _lineSpacing,
                      alfons::LineMetrics& _layoutMetrics) {
    size_t shapeStart = 0;
    glm::vec2 position;

    for (auto wrap : m_lineWraps) {
        alfons::LineMetrics lineMetrics;

        switch(_alignment) {
            case TextLabelProperty::Align::center:
            case TextLabelProperty::Align::none:
                position.x = (_maxWidth - wrap.second) * 0.5;
                break;
            case TextLabelProperty::Align::right:
                position.x = (_maxWidth - wrap.second);
                break;
            default:
                position.x = 0;
        }

        size_t shapeEnd = wrap.first;

        // Draw line quads
        _batch.drawShapeRange(_line, shapeStart, shapeEnd, position, lineMetrics);

        shapeStart = shapeEnd;

        // FIXME hardcoded value for SDF radius 6
        float height = lineMetrics.height();
        height -= (2 * 6) * _line.scale(); // substract glyph padding
        height += _lineSpacing; // add some custom line offset

        position.y += height;

        _layoutMetrics.addExtents(lineMetrics.aabb);
    }

    return int(m_lineWraps.size());
}

}
<|endoftext|>


<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  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.
 */
/*
 * Copyright (C) 2016 ScyllaDB
 */

#pragma once

#include <chrono>
#include <atomic>
#include "timer.hh"

class lowres_clock {
public:
    typedef int64_t rep;
    // The lowres_clock's resolution is 10ms. However, to make it is easier to
    // do calcuations with std::chrono::milliseconds, we make the clock's
    // period to 1ms instead of 10ms.
    typedef std::ratio<1, 1000> period;
    typedef std::chrono::duration<rep, period> duration;
    typedef std::chrono::time_point<lowres_clock, duration> time_point;
    lowres_clock();
    static time_point now() {
        auto nr = _now.load(std::memory_order_relaxed);
        return time_point(duration(nr));
    }
private:
    static void update();
    // _now is updated by cpu0 and read by other cpus. Make _now on its own
    // cache line to avoid false sharing.
    static std::atomic<rep> _now [[gnu::aligned(64)]];
    // High resolution timer to drive this low resolution clock
    timer<> _timer [[gnu::aligned(64)]];
    // High resolution timer expires every 10 milliseconds
    static constexpr std::chrono::milliseconds _granularity{10};
};
<commit_msg>lowres_clock: drop cache-line alignment for _timer<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  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.
 */
/*
 * Copyright (C) 2016 ScyllaDB
 */

#pragma once

#include <chrono>
#include <atomic>
#include "timer.hh"

class lowres_clock {
public:
    typedef int64_t rep;
    // The lowres_clock's resolution is 10ms. However, to make it is easier to
    // do calcuations with std::chrono::milliseconds, we make the clock's
    // period to 1ms instead of 10ms.
    typedef std::ratio<1, 1000> period;
    typedef std::chrono::duration<rep, period> duration;
    typedef std::chrono::time_point<lowres_clock, duration> time_point;
    lowres_clock();
    static time_point now() {
        auto nr = _now.load(std::memory_order_relaxed);
        return time_point(duration(nr));
    }
private:
    static void update();
    // _now is updated by cpu0 and read by other cpus. Make _now on its own
    // cache line to avoid false sharing.
    static std::atomic<rep> _now [[gnu::aligned(64)]];
    // High resolution timer to drive this low resolution clock
    timer<> _timer;
    // High resolution timer expires every 10 milliseconds
    static constexpr std::chrono::milliseconds _granularity{10};
};
<|endoftext|>


<commit_before>#include <windows.h>
#include <winsock.h>
#include <string>
using std::string;
#include <iostream>
using std::cout; using std::endl; using std::cin;

namespace as3
{
    class Socket
    {
    public:
        explicit Socket(SOCKET s)
            : socket_{ s }
        {}
        Socket(int address_family, int type, int protocol)
            : socket_{ ::socket(address_family, type, protocol) }
        {}

        /*auto operator=(Socket && other) -> Socket& */

        auto get() const ->  SOCKET { return socket_; }
        auto is_failed() const -> bool { return socket_ < 0; }
        ~Socket(){ ::closesocket(socket_); cout << "from class Socket : clearing socket\n"; }
    private:
        const SOCKET socket_;
    };

    const int WSVERS = MAKEWORD(2, 0);

    auto make_remote_address(char* arr[]) -> sockaddr_in
    {
        struct sockaddr_in address;
        memset(&address, 0, sizeof(address));
        address.sin_addr.s_addr = inet_addr(arr[1]);    //IP address
        address.sin_port = htons((u_short)atoi(arr[2]));//Port number
        address.sin_family = AF_INET;
        return address;
    }

    auto handle_user_input(int arguments_count) -> void
    {
        if (arguments_count != 3)
        {
            cout << "USAGE: client IP-address port" << endl;
            exit(1);
        }
    }

    auto setup_win_sock_api(WORD version_required) -> WSADATA
    {
        WSADATA wsadata;
        if (WSAStartup(WSVERS, &wsadata) != 0)
        {
            WSACleanup();
            cout << "WSAStartup failed\n";
            exit(1);
        }
        return wsadata;
    }

    //return the string received
    auto receive(SOCKET s) -> string
    {
        auto received = string();
        //receive char by char, end on an LF, ignore CR's
        for (auto ch = char(0); true; /* */)
        {
            if (0 >= recv(s, &ch, 1, 0)) { cout << "recv failed\n"; exit(1); }
            if (ch == '\n') break; else if (ch == '\r') continue; else received.push_back(ch);
        }
        return received;
    }

    auto send(SOCKET sock, string const& send_buffer) -> void
    {
        auto bytes_sent = ::send(sock, send_buffer.c_str(), send_buffer.size(), 0);
        if (bytes_sent < 0) { cout << "send failed\n"; exit(1); }
    }
}//namespace rsa

auto main(int argc, char *argv[]) -> int
{
    {
        as3::handle_user_input(argc);
        auto wsa_data = as3::setup_win_sock_api(as3::WSVERS);
        auto remoteaddr = as3::make_remote_address(argv);

        //CREATE CLIENT'S SOCKET
        auto sock = as3::Socket{ AF_INET, SOCK_STREAM, 0 };
        //auto s = socket(AF_INET, SOCK_STREAM, 0);
        //if (s < 0)
        //{
        //    cout << "socket failed\n";
        //    exit(1);
        //}

        //CONNECT
        if (connect(sock.get(), (struct sockaddr *)&remoteaddr, sizeof(remoteaddr)) != 0)
        {
            cout << "connect failed\n";
            exit(1);
        }

        for (auto send_buffer = string{}; cin >> send_buffer && send_buffer != "."; cout << as3::receive(sock.get()) << endl)
        {
            as3::send(sock.get(), send_buffer + "\r\n");
        }
    }
    //closesocket(s);
    return 0;
}<commit_msg>	modified:   src/2015a3/rsa/client/client.cpp<commit_after>#include <windows.h>
#include <winsock.h>
#include <string>
using std::string;
#include <iostream>
using std::cout; using std::endl; using std::cin;

namespace as3
{
    class Socket
    {
    public:
        explicit Socket(SOCKET s)
            : socket_{ s }
        {}
        Socket(int address_family, int type, int protocol)
            : socket_{ ::socket(address_family, type, protocol) }
        {}

        auto get() const ->  SOCKET { return socket_; }
        auto is_failed() const -> bool { return socket_ < 0; }
        ~Socket(){ ::closesocket(socket_); cout << "clearing socket\n"; }

    private:
        const SOCKET socket_;
    };

    const int WSVERS = MAKEWORD(2, 0);

    auto make_remote_address(char* arr[]) -> sockaddr_in
    {
        struct sockaddr_in address;
        memset(&address, 0, sizeof(address));
        address.sin_addr.s_addr = inet_addr(arr[1]);    //IP address
        address.sin_port = htons((u_short)atoi(arr[2]));//Port number
        address.sin_family = AF_INET;
        return address;
    }

    auto handle_user_input(int arguments_count) -> void
    {
        if (arguments_count != 3)
        {
            cout << "USAGE: client IP-address port" << endl;
            exit(1);
        }
    }

    auto setup_win_sock_api(WORD version_required) -> WSADATA
    {
        WSADATA wsadata;
        if (WSAStartup(WSVERS, &wsadata) != 0)
        {
            WSACleanup();
            cout << "WSAStartup failed\n";
            exit(1);
        }
        return wsadata;
    }

    //return the string received
    auto receive(SOCKET s) -> string
    {
        auto received = string();
        //receive char by char, end on an LF, ignore CR's
        for (auto ch = char(0); true; /* */)
        {
            if (0 >= recv(s, &ch, 1, 0)) { cout << "recv failed\n"; exit(1); }
            if (ch == '\n') break; else if (ch == '\r') continue; else received.push_back(ch);
        }
        return received;
    }

    auto send(SOCKET sock, string const& send_buffer) -> void
    {
        auto bytes_sent = ::send(sock, send_buffer.c_str(), send_buffer.size(), 0);
        if (bytes_sent < 0) { cout << "send failed\n"; exit(1); }
    }
}//namespace rsa

auto main(int argc, char *argv[]) -> int
{
    {
        as3::handle_user_input(argc);
        auto wsa_data = as3::setup_win_sock_api(as3::WSVERS);
        auto remoteaddr = as3::make_remote_address(argv);

        //CREATE CLIENT'S SOCKET
        auto sock = as3::Socket{ AF_INET, SOCK_STREAM, 0 };

        //CONNECT
        if (connect(sock.get(), (struct sockaddr *)&remoteaddr, sizeof(remoteaddr)) != 0)
        {
            cout << "connect failed\n";
            exit(1);
        }

        for (auto send_buffer = string{}; cin >> send_buffer && send_buffer != "."; cout << as3::receive(sock.get()) << endl)
        {
            as3::send(sock.get(), send_buffer + "\r\n");
        }
    }
    return 0;
}<|endoftext|>


<commit_before>#include <map>

#include <llvm/IR/Value.h>
#include <llvm/IR/Instruction.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/Constants.h>
#include <llvm/IR/GlobalVariable.h>
#include <llvm/IR/Module.h>
#include <llvm/Support/raw_ostream.h>

#include "LLVMNode.h"
#include "LLVMDependenceGraph.h"
#include "DefUse.h"
#include "AnalysisGeneric.h"

#include "analysis/DFS.h"

using namespace llvm;

namespace dg {
namespace analysis {

LLVMDefUseAnalysis::LLVMDefUseAnalysis(LLVMDependenceGraph *dg)
    : DataFlowAnalysis<LLVMNode>(dg->getEntryBB(), DATAFLOW_INTERPROCEDURAL),
      dg(dg)
{
    Module *m = dg->getModule();
    // set data layout
    DL = m->getDataLayout();
}

Pointer LLVMDefUseAnalysis::getConstantExprPointer(const ConstantExpr *CE)
{
    return dg::analysis::getConstantExprPointer(CE, dg, DL);
}

DefMap::DefMap(const DefMap& o)
{
    merge(&o);
}

bool DefMap::merge(const DefMap *oth, PointsToSetT *without)
{
    bool changed = false;

    if (this == oth)
        return false;

    for (auto it : oth->defs) {
        const Pointer& ptr = it.first;

        // should we skip this pointer
        if (without && without->count(ptr) != 0)
            continue;

        // our values that we have for
        // this pointer
        ValuesSetT& our_vals = defs[ptr];

        // copy values that have map oth for the
        // pointer to our values
        for (LLVMNode *defnode : it.second) {
            changed |= our_vals.insert(defnode).second;
        }
    }

    return changed;
}

bool DefMap::add(const Pointer& p, LLVMNode *n)
{
    return defs[p].insert(n).second;
}

bool DefMap::update(const Pointer& p, LLVMNode *n)
{
    bool ret;
    ValuesSetT& dfs = defs[p];

    ret = dfs.count(n) == 0 || dfs.size() > 1;
    dfs.clear();
    dfs.insert(n);

    return ret;
}

static DefMap *getDefMap(LLVMNode *n)
{
    DefMap *r = n->getData<DefMap>();
    if (!r) {
        r = new DefMap();
        n->setData(r);
    }

    // must always have
    assert(r);

    return r;
}

/// --------------------------------------------------
//   Reaching definitions analysis
/// --------------------------------------------------

static bool handleStoreInst(const StoreInst *Inst, LLVMNode *node,
                            PointsToSetT *&strong_update)
{
    bool changed = false;
    LLVMNode *ptrNode = node->getOperand(0);
    assert(ptrNode && "No pointer operand");

    (void) Inst;

    // update definitions
    DefMap *df = getDefMap(node);
    PointsToSetT& S = ptrNode->getPointsTo();

    if (S.size() == 1) {// strong update
        changed |= df->update(*S.begin(), node);
        strong_update = &S;
    } else { // weak update
        for (const Pointer& ptr : ptrNode->getPointsTo())
            changed |= df->add(ptr, node);
    }

    return changed;
}

bool LLVMDefUseAnalysis::runOnNode(LLVMNode *node)
{
    bool changed = false;
    const Value *val = node->getKey();
    // pointers that should not be updated
    // because they were updated strongly
    PointsToSetT *strong_update = nullptr;

    if (const StoreInst *Inst = dyn_cast<StoreInst>(val)) {
        changed |= dg::analysis::handleStoreInst(Inst, node, strong_update);
    }

    // update states according to predcessors
    DefMap *df = getDefMap(node);
    LLVMNode *pred = node->getPredcessor();
    if (pred) {
        changed |= df->merge(getDefMap(pred), strong_update);
    } else { // BB predcessors
        LLVMBBlock *BB = node->getBasicBlock();
        assert(BB && "Node has no BB");

        for (auto predBB : BB->predcessors()) {
            pred = predBB->getLastNode();
            assert(pred && "BB has no last node");

            df->merge(getDefMap(pred), strong_update);
        }
    }

    return changed;
}

} // namespace analysis
} // namespace dg

/// --------------------------------------------------
//   Add def-use edges
/// --------------------------------------------------
namespace dg {
namespace analysis {

static void addIndirectDefUsePtr(const Pointer& ptr, LLVMNode *to, DefMap *df)
{
    ValuesSetT& defs = df->get(ptr);
    // do we have any reaching definition at all?
    if (defs.empty()) {
        // we do not add initial def to global variables because not all
        // global variables could be used in the code and we'd redundantly
        // iterate through the defintions. Do it lazily here.
        LLVMNode *ptrnode = ptr.obj->node;
        if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(ptrnode->getKey())) {
            if (GV->hasInitializer()) {
                // ok, so the GV was defined in initialization phase,
                // so the reaching definition for the ptr is there
                defs.insert(ptrnode);
            }
        } else {
            errs() << "WARN: no reaching definition for " << *ptr.obj->node->getKey()
                   << " + " << *ptr.offset << "\n";
            return;
        }
    }

    // we read ptrNode memory that is defined on these locations
    assert(!defs.empty());
    for (LLVMNode *n : defs)
        n->addDataDependence(to);
}

static void addIndirectDefUse(LLVMNode *ptrNode, LLVMNode *to, DefMap *df)
{
    // iterate over all memory locations that this
    // store can define and check where they are defined
    for (const Pointer& ptr : ptrNode->getPointsTo())
        addIndirectDefUsePtr(ptr, to, df);
}

void LLVMDefUseAnalysis::handleStoreInst(const StoreInst *Inst, LLVMNode *node)
{
    // we have only top-level dependencies here

    LLVMNode *valNode = node->getOperand(1);
    // this node uses what is defined on valNode
    if (!valNode) {
        if (const ConstantExpr *CE
                = dyn_cast<ConstantExpr>(Inst->getValueOperand())) {
            const Pointer ptr = getConstantExprPointer(CE);
            addIndirectDefUsePtr(ptr, node, getDefMap(node));
        } else
            errs() << "ERR: unhandled StoreInst value " << *Inst << "\n";
    } else
        valNode->addDataDependence(node);

    // and also uses what is defined on ptrNode
    LLVMNode *ptrNode = node->getOperand(0);
    ptrNode->addDataDependence(node);
}

void LLVMDefUseAnalysis::handleLoadInst(const LoadInst *Inst, LLVMNode *node)
{
    DefMap *df = getDefMap(node);
    LLVMNode *ptrNode = node->getOperand(0);
    const Value *valOp = Inst->getPointerOperand();

    // handle ConstantExpr
    if (!ptrNode) {
        if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(valOp)) {
            const Pointer ptr = getConstantExprPointer(CE);
            addIndirectDefUsePtr(ptr, node, df);
        } else {
            errs() << "ERR: Unhandled LoadInst operand " << *Inst << "\n";
            abort();
        }
    } else {
        // we use the top-level value that is defined
        // on ptrNode
        ptrNode->addDataDependence(node);

        addIndirectDefUse(ptrNode, node, df);
    }
}

static void handleCallInst(LLVMNode *node)
{
    DefMap *df = getDefMap(node);
    LLVMNode **operands = node->getOperands();
    LLVMDGParameters *params = node->getParameters();

    if (!params) // function has no arguments
        return;

    for (int i = 0, e = node->getOperandsNum(); i < e; ++i) {
        LLVMNode *op = operands[i];
        if (!op)
            continue;

        LLVMDGParameter *p = params->find(op->getKey());
        if (!p) {
            errs() << "ERR: no actual parameter for " << *op->getKey() << "\n";
            continue;
        }

        if (op->isPointerTy()) {
            // add data dependencies to in parameters
            addIndirectDefUse(op, p->in, df);

            // FIXME
            // look for reaching definitions inside the procedure
            // because since this is a pointer, we can change things
        } else
            op->addDataDependence(p->in);
    }

    // if the called function returns a value,
    // make this node data dependent on that
    if (!node->isVoidTy()) {
        for (auto sub : node->getSubgraphs())
            sub->getExit()->addDataDependence(node);
    }
}

static void handleInstruction(const Instruction *Inst, LLVMNode *node)
{
    LLVMDependenceGraph *dg = node->getDG();

    for (auto I = Inst->op_begin(), E = Inst->op_end(); I != E; ++I) {
        LLVMNode *op = dg->getNode(*I);
        if (op)
            op->addDataDependence(node);
        else if (!isa<ConstantInt>(*I) && !isa<BranchInst>(Inst))
            errs() << "WARN: no node for operand " << **I
                   << "in " << *Inst << "\n";
    }
}

void LLVMDefUseAnalysis::handleNode(LLVMNode *node)
{
    const Value *val = node->getKey();

    if (const StoreInst *Inst = dyn_cast<StoreInst>(val)) {
        handleStoreInst(Inst, node);
    } else if (const LoadInst *Inst = dyn_cast<LoadInst>(val)) {
        handleLoadInst(Inst, node);
    } else if (isa<CallInst>(val)) {
        handleCallInst(node);
    } else if (const Instruction *Inst = dyn_cast<Instruction>(val)) {
        handleInstruction(Inst, node); // handle rest of Insts
    }
}

void handleBlock(LLVMBBlock *BB, LLVMDefUseAnalysis *analysis)
{
    LLVMNode *n = BB->getFirstNode();
    while (n) {
        analysis->handleNode(n);
        n = n->getSuccessor();
    }
}

void LLVMDefUseAnalysis::addDefUseEdges()
{
    // it doesn't matter how we'll go through the nodes
    BBlockDFS<LLVMNode> runner(DFS_INTERPROCEDURAL);
    runner.run(dg->getEntryBB(), handleBlock, this);
}

} // namespace analysis
} // namespace dg
<commit_msg>def-use: handle global variables better<commit_after>#include <map>

#include <llvm/IR/Value.h>
#include <llvm/IR/Instruction.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/Constants.h>
#include <llvm/IR/GlobalVariable.h>
#include <llvm/IR/Module.h>
#include <llvm/Support/raw_ostream.h>

#include "LLVMNode.h"
#include "LLVMDependenceGraph.h"
#include "DefUse.h"
#include "AnalysisGeneric.h"

#include "analysis/DFS.h"

using namespace llvm;

namespace dg {
namespace analysis {

LLVMDefUseAnalysis::LLVMDefUseAnalysis(LLVMDependenceGraph *dg)
    : DataFlowAnalysis<LLVMNode>(dg->getEntryBB(), DATAFLOW_INTERPROCEDURAL),
      dg(dg)
{
    Module *m = dg->getModule();
    // set data layout
    DL = m->getDataLayout();
}

Pointer LLVMDefUseAnalysis::getConstantExprPointer(const ConstantExpr *CE)
{
    return dg::analysis::getConstantExprPointer(CE, dg, DL);
}

DefMap::DefMap(const DefMap& o)
{
    merge(&o);
}

bool DefMap::merge(const DefMap *oth, PointsToSetT *without)
{
    bool changed = false;

    if (this == oth)
        return false;

    for (auto it : oth->defs) {
        const Pointer& ptr = it.first;

        // should we skip this pointer
        if (without && without->count(ptr) != 0)
            continue;

        // our values that we have for
        // this pointer
        ValuesSetT& our_vals = defs[ptr];

        // copy values that have map oth for the
        // pointer to our values
        for (LLVMNode *defnode : it.second) {
            changed |= our_vals.insert(defnode).second;
        }
    }

    return changed;
}

bool DefMap::add(const Pointer& p, LLVMNode *n)
{
    return defs[p].insert(n).second;
}

bool DefMap::update(const Pointer& p, LLVMNode *n)
{
    bool ret;
    ValuesSetT& dfs = defs[p];

    ret = dfs.count(n) == 0 || dfs.size() > 1;
    dfs.clear();
    dfs.insert(n);

    return ret;
}

static DefMap *getDefMap(LLVMNode *n)
{
    DefMap *r = n->getData<DefMap>();
    if (!r) {
        r = new DefMap();
        n->setData(r);
    }

    // must always have
    assert(r);

    return r;
}

/// --------------------------------------------------
//   Reaching definitions analysis
/// --------------------------------------------------

static bool handleStoreInst(const StoreInst *Inst, LLVMNode *node,
                            PointsToSetT *&strong_update)
{
    bool changed = false;
    LLVMNode *ptrNode = node->getOperand(0);
    assert(ptrNode && "No pointer operand");

    (void) Inst;

    // update definitions
    DefMap *df = getDefMap(node);
    PointsToSetT& S = ptrNode->getPointsTo();

    if (S.size() == 1) {// strong update
        changed |= df->update(*S.begin(), node);
        strong_update = &S;
    } else { // weak update
        for (const Pointer& ptr : ptrNode->getPointsTo())
            changed |= df->add(ptr, node);
    }

    return changed;
}

bool LLVMDefUseAnalysis::runOnNode(LLVMNode *node)
{
    bool changed = false;
    const Value *val = node->getKey();
    // pointers that should not be updated
    // because they were updated strongly
    PointsToSetT *strong_update = nullptr;

    if (const StoreInst *Inst = dyn_cast<StoreInst>(val)) {
        changed |= dg::analysis::handleStoreInst(Inst, node, strong_update);
    }

    // update states according to predcessors
    DefMap *df = getDefMap(node);
    LLVMNode *pred = node->getPredcessor();
    if (pred) {
        changed |= df->merge(getDefMap(pred), strong_update);
    } else { // BB predcessors
        LLVMBBlock *BB = node->getBasicBlock();
        assert(BB && "Node has no BB");

        for (auto predBB : BB->predcessors()) {
            pred = predBB->getLastNode();
            assert(pred && "BB has no last node");

            df->merge(getDefMap(pred), strong_update);
        }
    }

    return changed;
}

} // namespace analysis
} // namespace dg

/// --------------------------------------------------
//   Add def-use edges
/// --------------------------------------------------
namespace dg {
namespace analysis {

static void addIndirectDefUsePtr(const Pointer& ptr, LLVMNode *to, DefMap *df)
{
    ValuesSetT& defs = df->get(ptr);
    // do we have any reaching definition at all?
    if (defs.empty()) {
        // we do not add initial def to global variables because not all
        // global variables could be used in the code and we'd redundantly
        // iterate through the defintions. Do it lazily here.
        LLVMNode *ptrnode = ptr.obj->node;
        if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(ptrnode->getKey())) {
            if (GV->hasInitializer()) {
                // ok, so the GV was defined in initialization phase,
                // so the reaching definition for the ptr is there
                defs.insert(ptrnode);
            }
        } else {
            errs() << "WARN: no reaching definition for " << *ptr.obj->node->getKey()
                   << " + " << *ptr.offset << "\n";
            return;
        }
    }

    // we read ptrNode memory that is defined on these locations
    assert(!defs.empty());
    for (LLVMNode *n : defs)
        n->addDataDependence(to);
}

static void addIndirectDefUse(LLVMNode *ptrNode, LLVMNode *to, DefMap *df)
{
    // iterate over all memory locations that this
    // store can define and check where they are defined
    for (const Pointer& ptr : ptrNode->getPointsTo())
        addIndirectDefUsePtr(ptr, to, df);
}

// return Value used on operand LLVMNode
// It is either the operand itself or
// global value used in ConstantExpr if the
// operand is ConstantExpr
static void addStoreInstDefUse(LLVMNode *storeNode, LLVMNode *op, DefMap *df)
{
    const Value *val = op->getKey();
    if (isa<ConstantExpr>(val)) {
        // it should be one ptr
        PointsToSetT& PS = op->getPointsTo();
        assert(PS.size() == 1);

        const Pointer& ptr = *PS.begin();
        addIndirectDefUsePtr(ptr, storeNode,  df);
    } else {
        op->addDataDependence(storeNode);
    }
}

void LLVMDefUseAnalysis::handleStoreInst(const StoreInst *Inst, LLVMNode *node)
{
    DefMap *df = getDefMap(node);
    LLVMNode *valNode = node->getOperand(1);

    // this node uses what is defined on valNode
    if (valNode) {
        addStoreInstDefUse(node, valNode, df);
    } else {
        if (!isa<ConstantInt>(Inst->getValueOperand()))
            errs() << "ERR def-use: Unhandled value operand for " << *Inst << "\n";
    }

    LLVMNode *ptrNode = node->getOperand(0);
    assert(ptrNode);

    // and also uses what is defined on ptrNode
    addStoreInstDefUse(node, ptrNode, df);
}

void LLVMDefUseAnalysis::handleLoadInst(const LoadInst *Inst, LLVMNode *node)
{
    DefMap *df = getDefMap(node);
    LLVMNode *ptrNode = node->getOperand(0);
    const Value *valOp = Inst->getPointerOperand();

    // handle ConstantExpr
    if (!ptrNode) {
        if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(valOp)) {
            const Pointer ptr = getConstantExprPointer(CE);
            addIndirectDefUsePtr(ptr, node, df);
        } else {
            errs() << "ERR: Unhandled LoadInst operand " << *Inst << "\n";
            abort();
        }
    } else {
        // we use the top-level value that is defined
        // on ptrNode
        ptrNode->addDataDependence(node);

        addIndirectDefUse(ptrNode, node, df);
    }
}

static void handleCallInst(LLVMNode *node)
{
    DefMap *df = getDefMap(node);
    LLVMNode **operands = node->getOperands();
    LLVMDGParameters *params = node->getParameters();

    if (!params) // function has no arguments
        return;

    for (int i = 0, e = node->getOperandsNum(); i < e; ++i) {
        LLVMNode *op = operands[i];
        if (!op)
            continue;

        LLVMDGParameter *p = params->find(op->getKey());
        if (!p) {
            errs() << "ERR: no actual parameter for " << *op->getKey() << "\n";
            continue;
        }

        if (op->isPointerTy()) {
            // add data dependencies to in parameters
            addIndirectDefUse(op, p->in, df);

            // FIXME
            // look for reaching definitions inside the procedure
            // because since this is a pointer, we can change things
        } else
            op->addDataDependence(p->in);
    }

    // if the called function returns a value,
    // make this node data dependent on that
    if (!node->isVoidTy()) {
        for (auto sub : node->getSubgraphs())
            sub->getExit()->addDataDependence(node);
    }
}

static void handleInstruction(const Instruction *Inst, LLVMNode *node)
{
    LLVMDependenceGraph *dg = node->getDG();

    for (auto I = Inst->op_begin(), E = Inst->op_end(); I != E; ++I) {
        LLVMNode *op = dg->getNode(*I);
        if (op)
            op->addDataDependence(node);
        else if (!isa<ConstantInt>(*I) && !isa<BranchInst>(Inst))
            errs() << "WARN: no node for operand " << **I
                   << "in " << *Inst << "\n";
    }
}

void LLVMDefUseAnalysis::handleNode(LLVMNode *node)
{
    const Value *val = node->getKey();

    if (const StoreInst *Inst = dyn_cast<StoreInst>(val)) {
        handleStoreInst(Inst, node);
    } else if (const LoadInst *Inst = dyn_cast<LoadInst>(val)) {
        handleLoadInst(Inst, node);
    } else if (isa<CallInst>(val)) {
        handleCallInst(node);
    } else if (const Instruction *Inst = dyn_cast<Instruction>(val)) {
        handleInstruction(Inst, node); // handle rest of Insts
    }
}

void handleBlock(LLVMBBlock *BB, LLVMDefUseAnalysis *analysis)
{
    LLVMNode *n = BB->getFirstNode();
    while (n) {
        analysis->handleNode(n);
        n = n->getSuccessor();
    }
}

void LLVMDefUseAnalysis::addDefUseEdges()
{
    // it doesn't matter how we'll go through the nodes
    BBlockDFS<LLVMNode> runner(DFS_INTERPROCEDURAL);
    runner.run(dg->getEntryBB(), handleBlock, this);
}

} // namespace analysis
} // namespace dg
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: std_outp.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: np $ $Date: 2002-11-01 12:18:50 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef CSV_STD_OUTP_HXX
#define CSV_STD_OUTP_HXX

// USED SERVICES
    // BASE CLASSES
    // COMPONENTS
#include <cosv/csv_ostream.hxx>
    // PARAMETERS

namespace csv
{

#ifdef CSV_NO_IOSTREAMS
class redirect_out : public ostream
{
  public:
    virtual             ~redirect_out() {}

    void                re_endl()               { do_re_endl(); }
    void                re_flush()              { do_re_flush(); }

    static void         set_(
                            redirect_out &      o_rStdOut,
                            redirect_out &      o_rStdErr )
                                                { pStdOut_ = &o_rStdOut;
                                                  pStdErr_ = &o_rStdErr; }

    static redirect_out &
                        std_()                  { return *pStdOut_; }
    static redirect_out &
                        err_()                  { return *pStdErr_; }
    static bool         useme_()                { return pStdOut_ != 0; }

  private:
    virtual void        do_re_endl() = 0;
    virtual void        do_re_flush() = 0;

    // DATA
    static redirect_out *
                        pStdOut_;
    static redirect_out *
                        pStdErr_;
};
#endif // defined(CSV_NO_IOSTREAMS)

inline ostream &
Cout()
{

#ifndef CSV_NO_IOSTREAMS
//    return redirect_out::useme_()
//            ?   (ostream&)( redirect_out::std_() )
//            :   (ostream&)( std::cout );
    return (ostream&)( std::cout );
#else
    csv_assert( redirect_out::useme_() );
    return redirect_out::std_();
#endif
}

inline ostream &
Cerr()
{
#ifndef CSV_NO_IOSTREAMS
//    return redirect_out::useme_()
//            ?   (ostream&)( redirect_out::err_() )
//            :   (ostream&)( std::cerr );
    return (ostream&)( std::cerr );
#else
    csv_assert( redirect_out::useme_() );
    return redirect_out::err_();
#endif
}

typedef void (*F_FLUSHING_FUNC)(ostream&, bool, int*);

void                Endl( ostream&, bool, int* );

void                Flush( ostream&, bool, int* );

}   // namespace csv

inline csv::ostream &
operator<<( csv::ostream &          io_rStream,
            csv::F_FLUSHING_FUNC    i_fFlushingFunc )
{
#ifndef CSV_NO_IOSTREAMS
//    (*i_fFlushingFunc)( io_rStream, csv::redirect_out::useme_(), 0 );
    (*i_fFlushingFunc)( io_rStream, false, 0 );
#else
    csv_assert( csv::redirect_out::useme_() );
    (*i_fFlushingFunc)( io_rStream, true, 0 );
#endif
    return io_rStream;
}

#endif

<commit_msg>INTEGRATION: CWS ooo19126 (1.2.102); FILE MERGED 2005/09/05 14:08:52 rt 1.2.102.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: std_outp.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 07:57:13 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef CSV_STD_OUTP_HXX
#define CSV_STD_OUTP_HXX

// USED SERVICES
    // BASE CLASSES
    // COMPONENTS
#include <cosv/csv_ostream.hxx>
    // PARAMETERS

namespace csv
{

#ifdef CSV_NO_IOSTREAMS
class redirect_out : public ostream
{
  public:
    virtual             ~redirect_out() {}

    void                re_endl()               { do_re_endl(); }
    void                re_flush()              { do_re_flush(); }

    static void         set_(
                            redirect_out &      o_rStdOut,
                            redirect_out &      o_rStdErr )
                                                { pStdOut_ = &o_rStdOut;
                                                  pStdErr_ = &o_rStdErr; }

    static redirect_out &
                        std_()                  { return *pStdOut_; }
    static redirect_out &
                        err_()                  { return *pStdErr_; }
    static bool         useme_()                { return pStdOut_ != 0; }

  private:
    virtual void        do_re_endl() = 0;
    virtual void        do_re_flush() = 0;

    // DATA
    static redirect_out *
                        pStdOut_;
    static redirect_out *
                        pStdErr_;
};
#endif // defined(CSV_NO_IOSTREAMS)

inline ostream &
Cout()
{

#ifndef CSV_NO_IOSTREAMS
//    return redirect_out::useme_()
//            ?   (ostream&)( redirect_out::std_() )
//            :   (ostream&)( std::cout );
    return (ostream&)( std::cout );
#else
    csv_assert( redirect_out::useme_() );
    return redirect_out::std_();
#endif
}

inline ostream &
Cerr()
{
#ifndef CSV_NO_IOSTREAMS
//    return redirect_out::useme_()
//            ?   (ostream&)( redirect_out::err_() )
//            :   (ostream&)( std::cerr );
    return (ostream&)( std::cerr );
#else
    csv_assert( redirect_out::useme_() );
    return redirect_out::err_();
#endif
}

typedef void (*F_FLUSHING_FUNC)(ostream&, bool, int*);

void                Endl( ostream&, bool, int* );

void                Flush( ostream&, bool, int* );

}   // namespace csv

inline csv::ostream &
operator<<( csv::ostream &          io_rStream,
            csv::F_FLUSHING_FUNC    i_fFlushingFunc )
{
#ifndef CSV_NO_IOSTREAMS
//    (*i_fFlushingFunc)( io_rStream, csv::redirect_out::useme_(), 0 );
    (*i_fFlushingFunc)( io_rStream, false, 0 );
#else
    csv_assert( csv::redirect_out::useme_() );
    (*i_fFlushingFunc)( io_rStream, true, 0 );
#endif
    return io_rStream;
}

#endif

<|endoftext|>


<commit_before>///
/// @file  pi_lmo3.cpp
/// @brief Simple implementation of the Lagarias-Miller-Odlyzko
///        prime counting algorithm. This implementation uses
///        the segmented sieve of Eratosthenes to calculate S2(x).
///
/// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primecount-internal.hpp>
#include <imath.hpp>
#include <generate.hpp>
#include <PhiTiny.hpp>
#include <S1.hpp>

#include <stdint.h>
#include <algorithm>
#include <vector>

#ifdef _OPENMP
  #include <omp.h>
#endif

using namespace std;
using namespace primecount;

namespace {

/// Calculate the contribution of the special leaves.
/// This implementation uses segmentation which reduces the
/// algorithm's space complexity to O(x^(1/3) * log^2 x).
///
int64_t S2(int64_t x,
           int64_t y,
           int64_t c,
           vector<int32_t>& primes,
           vector<int32_t>& lpf,
           vector<int32_t>& mu)
{
  int64_t limit = x / y + 1;
  int64_t segment_size = isqrt(limit);
  int64_t pi_y = pi_bsearch(primes, y);
  int64_t S2_result = 0;

  vector<char> sieve(segment_size);
  vector<int64_t> next(primes.begin(), primes.end());
  vector<int64_t> phi(primes.size(), 0);

  // segmented sieve of Eratosthenes
  for (int64_t low = 1; low < limit; low += segment_size)
  {
    fill(sieve.begin(), sieve.end(), 1);

    // current segment [low, high[
    int64_t high = min(low + segment_size, limit);

    // phi(y, b) nodes with b <= c do not contribute to S2, so
    // we sieve out the multiples of the first c primes
    for (int64_t b = 1; b <= c; b++)
    {
      int64_t k = next[b];
      for (int64_t prime = primes[b]; k < high; k += prime)
        sieve[k - low] = 0;
      next[b] = k;
    }

    for (int64_t b = c + 1; b < pi_y; b++)
    {
      int64_t prime = primes[b];
      int64_t min_m = max(x / (prime * high), y / prime);
      int64_t max_m = min(x / (prime * low), y);
      int64_t i = 0;

      // obviously if (prime >= max_m) then (prime >= lpf[max_m])
      // hence (prime < lpf[m]) will always evaluate to false
      // and no special leaves are possible
      if (prime >= max_m)
        break;

      for (int64_t m = max_m; m > min_m; m--)
      {
        if (mu[m] != 0 && prime < lpf[m])
        {
          // we have found a special leaf, compute it's contribution
          // phi(x / (primes[b] * m), b - 1) by counting the number
          // of unsieved elements <= x / (primes[b] * m) after having
          // removed the multiples of the first b - 1 primes
          //
          for (int64_t xn = x / (prime * m); i <= xn - low; i++)
            phi[b] += sieve[i];

          S2_result -= mu[m] * phi[b];
        }
      }

      // count the remaining unsieved elements in this segment,
      // we need their count in the next segment
      for (; i < high - low; i++)
        phi[b] += sieve[i];

      // remove the multiples of the b-th prime
      int64_t k = next[b];
      for (; k < high; k += prime * 2)
        sieve[k - low] = 0;
      next[b] = k;
    }
  }

  return S2_result;
}

} // namespace

namespace primecount {

/// Calculate the number of primes below x using the
/// Lagarias-Miller-Odlyzko algorithm.
/// Run time: O(x^(2/3))
/// Memory usage: O(x^(1/3) * (log x)^2)
///
int64_t pi_lmo3(int64_t x)
{
  if (x < 2)
    return 0;

  double alpha = get_alpha_lmo(x);
  int64_t x13 = iroot<3>(x);
  int64_t y = (int64_t) (x13 * alpha);
  int64_t c = PhiTiny::get_c(y);
  int64_t p2 = P2(x, y, 1);

  auto primes = generate_primes<int32_t>(y);
  auto lpf = generate_lpf(y);
  auto mu = generate_moebius(y);

  int64_t pi_y = primes.size() - 1;
  int64_t s1 = S1(x, y, c, 1);
  int64_t s2 = S2(x, y, c, primes, lpf, mu);
  int64_t phi = s1 + s2;
  int64_t sum = phi + pi_y - 1 - p2;

  return sum;
}

} // namespace
<commit_msg>Refactor<commit_after>///
/// @file  pi_lmo3.cpp
/// @brief Simple implementation of the Lagarias-Miller-Odlyzko
///        prime counting algorithm. This implementation uses
///        the segmented sieve of Eratosthenes to calculate S2(x).
///
/// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primecount-internal.hpp>
#include <imath.hpp>
#include <generate.hpp>
#include <PhiTiny.hpp>
#include <S1.hpp>

#include <stdint.h>
#include <algorithm>
#include <vector>

#ifdef _OPENMP
  #include <omp.h>
#endif

using namespace std;
using namespace primecount;

namespace {

/// Calculate the contribution of the special leaves.
/// This implementation uses segmentation which reduces the
/// algorithm's space complexity to O(x^(1/3) * log^2 x).
///
int64_t S2(int64_t x,
           int64_t y,
           int64_t c,
           vector<int32_t>& primes,
           vector<int32_t>& lpf,
           vector<int32_t>& mu)
{
  int64_t limit = x / y + 1;
  int64_t segment_size = isqrt(limit);
  int64_t pi_y = pi_bsearch(primes, y);
  int64_t S2_result = 0;

  vector<char> sieve(segment_size);
  vector<int64_t> next(primes.begin(), primes.end());
  vector<int64_t> phi(primes.size(), 0);

  // segmented sieve of Eratosthenes
  for (int64_t low = 1; low < limit; low += segment_size)
  {
    // current segment [low, high[
    int64_t high = min(low + segment_size, limit);

    fill(sieve.begin(), sieve.end(), 1);

    // phi(y, b) nodes with b <= c do not contribute to S2, so
    // we sieve out the multiples of the first c primes
    for (int64_t b = 1; b <= c; b++)
    {
      int64_t k = next[b];
      for (int64_t prime = primes[b]; k < high; k += prime)
        sieve[k - low] = 0;
      next[b] = k;
    }

    for (int64_t b = c + 1; b < pi_y; b++)
    {
      int64_t prime = primes[b];
      int64_t min_m = max(x / (prime * high), y / prime);
      int64_t max_m = min(x / (prime * low), y);
      int64_t i = 0;

      // obviously if (prime >= max_m) then (prime >= lpf[max_m])
      // hence (prime < lpf[m]) will always evaluate to false
      // and no special leaves are possible
      if (prime >= max_m)
        break;

      for (int64_t m = max_m; m > min_m; m--)
      {
        if (mu[m] != 0 && prime < lpf[m])
        {
          // we have found a special leaf, compute it's contribution
          // phi(x / (primes[b] * m), b - 1) by counting the number
          // of unsieved elements <= x / (primes[b] * m) after having
          // removed the multiples of the first b - 1 primes
          //
          for (int64_t xn = x / (prime * m); i <= xn - low; i++)
            phi[b] += sieve[i];

          S2_result -= mu[m] * phi[b];
        }
      }

      // count the remaining unsieved elements in this segment,
      // we need their count in the next segment
      for (; i < high - low; i++)
        phi[b] += sieve[i];

      // remove the multiples of the b-th prime
      int64_t k = next[b];
      for (; k < high; k += prime * 2)
        sieve[k - low] = 0;
      next[b] = k;
    }
  }

  return S2_result;
}

} // namespace

namespace primecount {

/// Calculate the number of primes below x using the
/// Lagarias-Miller-Odlyzko algorithm.
/// Run time: O(x^(2/3))
/// Memory usage: O(x^(1/3) * (log x)^2)
///
int64_t pi_lmo3(int64_t x)
{
  if (x < 2)
    return 0;

  double alpha = get_alpha_lmo(x);
  int64_t x13 = iroot<3>(x);
  int64_t y = (int64_t) (x13 * alpha);
  int64_t c = PhiTiny::get_c(y);
  int64_t p2 = P2(x, y, 1);

  auto primes = generate_primes<int32_t>(y);
  auto lpf = generate_lpf(y);
  auto mu = generate_moebius(y);

  int64_t pi_y = primes.size() - 1;
  int64_t s1 = S1(x, y, c, 1);
  int64_t s2 = S2(x, y, c, primes, lpf, mu);
  int64_t phi = s1 + s2;
  int64_t sum = phi + pi_y - 1 - p2;

  return sum;
}

} // namespace
<|endoftext|>


<commit_before>#ifdef _MSC_VER
#pragma warning(push, 0)
#endif
#include <SDL2/SDL.h>
#ifdef _MSC_VER
#pragma warning(pop)
#endif

/*  #include "Bitmap.hpp"  */
#include "Camera.hpp"
#include "CanvasDef.hpp"
#include "Mat.hpp"
#include "Mesh.hpp"
#include "PredicateQuicksort.hpp"
#include "Quat.hpp"
#include "Render.hpp"
#include "UI.hpp"
#include "canvas8.hpp"
#include "Triangle.hpp"
#include <cstdio>
#include <vector>

bool paused = false;
const int framerateLock = 60;
const int screenTicksPerFrame = 1000 / framerateLock;

Palette make_db32_Palette();

#undef main // fuck off, SDL

int main(int argc, char* argv[])
{
    const Bitmap cursorpic(16, 16, "cursor.data");
    Camera camera(CANVAS_WIDTH, CANVAS_HEIGHT,
        Vec3(3.0f, 1.0f, 0.0f),
        Vec3(0.0f, 0.0f, 1.0f),
        Vec3(0.0f, 0.0f, 0.0f),
        90.0f,
        1.0f, // near
        80.0f); // far

    Triangle2 testTri { {16, 64}, {CANVAS_WIDTH/2,CANVAS_HEIGHT - 64}, {384, 8} };

    std::string meshname = "";
    if (argc == 2)
        meshname = argv[1];
    if (meshname == "")
        meshname = "obelisk";

    const Mesh mesh = Mesh::loadMesh(meshname);

    Palette db32 = make_db32_Palette();
    Canvas canvas(db32, CANVAS_WIDTH, CANVAS_HEIGHT);
    UI ui(canvas);

    SDL_Init(SDL_INIT_EVERYTHING);
    atexit(SDL_Quit);

    const int windowWidth = CANVAS_WIDTH * canvasToWindowScale,
              windowHeight = CANVAS_HEIGHT * canvasToWindowScale;

    SDL_Window* const window = SDL_CreateWindow("cpp-learn3d",
        SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        windowWidth,
        windowHeight,
        SDL_WINDOW_SHOWN //| SDL_WINDOW_FULLSCREEN_DESKTOP
    );

    SDL_Renderer* const renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    SDL_RendererInfo info;
    SDL_GetRendererInfo(renderer, &info);

    printf("Renderer name: %s\n", info.name);
    printf("Texture formats: \n");
    for (Uint32 i = 0; i < info.num_texture_formats; i++) {
        printf("    %s\n", SDL_GetPixelFormatName(info.texture_formats[i]));
    }

    SDL_Texture* const texture = SDL_CreateTexture(renderer,
        SDL_PIXELFORMAT_ARGB8888,
        SDL_TEXTUREACCESS_STREAMING,
        CANVAS_WIDTH,
        CANVAS_HEIGHT);

    SDL_Event event;
    bool running = true;
    unsigned int frame = 0;

    while (running) {
        const unsigned int ticksBeforeRender = SDL_GetTicks();

        int mouse_x, mouse_y;
        SDL_PumpEvents();
        SDL_GetMouseState(&mouse_x, &mouse_y);

        while (SDL_PollEvent(&event)) {
            if ((SDL_QUIT == event.type) || (SDL_KEYDOWN == event.type && SDL_SCANCODE_ESCAPE == event.key.keysym.scancode)) {
                running = false;
                break;
            }

            if ((SDL_KEYDOWN == event.type) && (SDL_SCANCODE_SPACE == event.key.keysym.scancode))
                paused = !paused;
        }

        // DO ALL THE DRAWING TO CANVAS HERE
        canvas.clear();

        /* const Point canvasMousePos = ui.windowCoordinatesToCanvasCoordinates(Point(mouse_x, mouse_y),
            windowWidth,
            windowHeight,
            CANVAS_WIDTH,
            CANVAS_HEIGHT);
        const int cx = canvasMousePos.first,
                  cy = canvasMousePos.second; */

        {
            static float eyedelta = 0.0f;
            eyedelta += 0.01f;

            const float h = 0.5f+(0.2f*sin(eyedelta/4.0f));
            const float eyex = 24 * sin(eyedelta),
                        eyey = 24 * cos(eyedelta),
                        eyez = 16.0f + h;

            camera.lookAt(Vec3(eyex, eyey, eyez),
                Vec3(0.0f, 0.0f, h),
                Vec3(0.0f, 0.0f, 1.0f));
            camera.setPerspectiveProjection(30.0f, 0.1f, 10.0f);
        }

        // determine mouse cursor position in canvas
        const Vec2 mcurpos = { static_cast<float>(mouse_x / canvasToWindowScale),
                               static_cast<float>(mouse_y / canvasToWindowScale) };

        // determine barycentric coords of debug triangle
        const Vec3 bary = testTri.barycentricCoordinates(mcurpos);

        canvas.blitBitmap(*mesh.getTexture(), 4, 16);
        canvas.drawFlatTriangle(testTri, bary.allGTE(0.0f) ? 12 : 4);
        //Render::drawMeshFlat(canvas, camera, mesh);
        for (int i = 0; i < 32; i++)
            Render::drawMeshTextured(canvas, camera, mesh);

        canvas.blitBitmap(cursorpic, mcurpos.x, mcurpos.y);

        // present to user
        canvas.updateSDLTexture(texture); // present 8bit AxB --into--> 32bit NxM
        SDL_RenderCopy(renderer, texture, nullptr, nullptr);
        SDL_RenderPresent(renderer);

        const unsigned int ticksAfterRender = SDL_GetTicks();
        const unsigned int tickDiff = ticksAfterRender - ticksBeforeRender;

        if (tickDiff < screenTicksPerFrame) {
            SDL_Delay(screenTicksPerFrame - tickDiff);
        }

        frame++;
    }

    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
}
<commit_msg>Remove silly poor-mans-performance-testing loop in main.cpp<commit_after>#ifdef _MSC_VER
#pragma warning(push, 0)
#endif
#include <SDL2/SDL.h>
#ifdef _MSC_VER
#pragma warning(pop)
#endif

/*  #include "Bitmap.hpp"  */
#include "Camera.hpp"
#include "CanvasDef.hpp"
#include "Mat.hpp"
#include "Mesh.hpp"
#include "PredicateQuicksort.hpp"
#include "Quat.hpp"
#include "Render.hpp"
#include "UI.hpp"
#include "canvas8.hpp"
#include "Triangle.hpp"
#include <cstdio>
#include <vector>

bool paused = false;
const int framerateLock = 60;
const int screenTicksPerFrame = 1000 / framerateLock;

Palette make_db32_Palette();

#undef main // fuck off, SDL

int main(int argc, char* argv[])
{
    const Bitmap cursorpic(16, 16, "cursor.data");
    Camera camera(CANVAS_WIDTH, CANVAS_HEIGHT,
        Vec3(3.0f, 1.0f, 0.0f),
        Vec3(0.0f, 0.0f, 1.0f),
        Vec3(0.0f, 0.0f, 0.0f),
        90.0f,
        1.0f, // near
        80.0f); // far

    Triangle2 testTri { {16, 64}, {CANVAS_WIDTH/2,CANVAS_HEIGHT - 64}, {384, 8} };

    std::string meshname = "";
    if (argc == 2)
        meshname = argv[1];
    if (meshname == "")
        meshname = "obelisk";

    const Mesh mesh = Mesh::loadMesh(meshname);

    Palette db32 = make_db32_Palette();
    Canvas canvas(db32, CANVAS_WIDTH, CANVAS_HEIGHT);
    UI ui(canvas);

    SDL_Init(SDL_INIT_EVERYTHING);
    atexit(SDL_Quit);

    const int windowWidth = CANVAS_WIDTH * canvasToWindowScale,
              windowHeight = CANVAS_HEIGHT * canvasToWindowScale;

    SDL_Window* const window = SDL_CreateWindow("cpp-learn3d",
        SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        windowWidth,
        windowHeight,
        SDL_WINDOW_SHOWN //| SDL_WINDOW_FULLSCREEN_DESKTOP
    );

    SDL_Renderer* const renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    SDL_RendererInfo info;
    SDL_GetRendererInfo(renderer, &info);

    printf("Renderer name: %s\n", info.name);
    printf("Texture formats: \n");
    for (Uint32 i = 0; i < info.num_texture_formats; i++) {
        printf("    %s\n", SDL_GetPixelFormatName(info.texture_formats[i]));
    }

    SDL_Texture* const texture = SDL_CreateTexture(renderer,
        SDL_PIXELFORMAT_ARGB8888,
        SDL_TEXTUREACCESS_STREAMING,
        CANVAS_WIDTH,
        CANVAS_HEIGHT);

    SDL_Event event;
    bool running = true;
    unsigned int frame = 0;

    while (running) {
        const unsigned int ticksBeforeRender = SDL_GetTicks();

        int mouse_x, mouse_y;
        SDL_PumpEvents();
        SDL_GetMouseState(&mouse_x, &mouse_y);

        while (SDL_PollEvent(&event)) {
            if ((SDL_QUIT == event.type) || (SDL_KEYDOWN == event.type && SDL_SCANCODE_ESCAPE == event.key.keysym.scancode)) {
                running = false;
                break;
            }

            if ((SDL_KEYDOWN == event.type) && (SDL_SCANCODE_SPACE == event.key.keysym.scancode))
                paused = !paused;
        }

        // DO ALL THE DRAWING TO CANVAS HERE
        canvas.clear();

        /* const Point canvasMousePos = ui.windowCoordinatesToCanvasCoordinates(Point(mouse_x, mouse_y),
            windowWidth,
            windowHeight,
            CANVAS_WIDTH,
            CANVAS_HEIGHT);
        const int cx = canvasMousePos.first,
                  cy = canvasMousePos.second; */

        {
            static float eyedelta = 0.0f;
            eyedelta += 0.01f;

            const float h = 0.5f+(0.2f*sin(eyedelta/4.0f));
            const float eyex = 24 * sin(eyedelta),
                        eyey = 24 * cos(eyedelta),
                        eyez = 16.0f + h;

            camera.lookAt(Vec3(eyex, eyey, eyez),
                Vec3(0.0f, 0.0f, h),
                Vec3(0.0f, 0.0f, 1.0f));
            camera.setPerspectiveProjection(30.0f, 0.1f, 10.0f);
        }

        // determine mouse cursor position in canvas
        const Vec2 mcurpos = { static_cast<float>(mouse_x / canvasToWindowScale),
                               static_cast<float>(mouse_y / canvasToWindowScale) };

        // determine barycentric coords of debug triangle
        const Vec3 bary = testTri.barycentricCoordinates(mcurpos);

        canvas.blitBitmap(*mesh.getTexture(), 4, 16);
        canvas.drawFlatTriangle(testTri, bary.allGTE(0.0f) ? 12 : 4);
        //Render::drawMeshFlat(canvas, camera, mesh);
        Render::drawMeshTextured(canvas, camera, mesh);

        canvas.blitBitmap(cursorpic, mcurpos.x, mcurpos.y);

        // present to user
        canvas.updateSDLTexture(texture); // present 8bit AxB --into--> 32bit NxM
        SDL_RenderCopy(renderer, texture, nullptr, nullptr);
        SDL_RenderPresent(renderer);

        const unsigned int ticksAfterRender = SDL_GetTicks();
        const unsigned int tickDiff = ticksAfterRender - ticksBeforeRender;

        if (tickDiff < screenTicksPerFrame) {
            SDL_Delay(screenTicksPerFrame - tickDiff);
        }

        frame++;
    }

    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
}
<|endoftext|>