<commit_before>//------------------------------------------------------------------------------
// Copyright (c) 2016 John D. Haughton
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//------------------------------------------------------------------------------

// Kindle3 Linux event

#include <assert.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>

// C++11 threads would be nicer but don't seem to be able to link
// against any libs that actually work at runtime
#include <pthread.h>

#include "PLT/Event.h"
#include "STB/Fifo.h"

// ALT    ?

static const uint8_t DEL = PLT::BACKSPACE;
static const uint8_t RET = PLT::RETURN;
static const uint8_t LSH = PLT::LSHIFT;
static const uint8_t UP  = PLT::UP;        // Cursor up
static const uint8_t DWN = PLT::DOWN;      // Cursor down
static const uint8_t LFT = PLT::LEFT;      // Cursor left
static const uint8_t RGT = PLT::RIGHT;     // Cursor ritgh
static const uint8_t HME = PLT::ESCAPE;    // Home
static const uint8_t LPR = PLT::HOME;      // Left previous
static const uint8_t LNX = PLT::END;       // Left next
static const uint8_t RPR = PLT::PAGE_UP;   // Right previous
static const uint8_t RNX = PLT::PAGE_DOWN; // Right next
static const uint8_t SEL = PLT::SELECT;    // Select (center of cursor keys)
static const uint8_t MNU = PLT::MENU;      // Menu
static const uint8_t BAK = PLT::BACK;      // Back
static const uint8_t AA  = PLT::CAPSLOCK;  // Aa
static const uint8_t SYM = PLT::RALT;      // Sym
static const uint8_t VLD = PLT::VOL_DOWN;  // Volume -
static const uint8_t VLU = PLT::VOL_UP;    // Volume +

static const uint8_t event_decode[0xD0] =
{
//  x0   x1   x2   x3   x4   x5   x6   x7   x8   x9   xA   xB   xC   xD   xE   xF
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, DEL,   0,  // 0x
   'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p',   0,   0, RET,   0, 'a', 's',  // 1x
   'd', 'f', 'g', 'h', 'j', 'k', 'l',   0,   0,   0, LSH,   0, 'z', 'x', 'c', 'v',  // 2x
   'b', 'n', 'm',   0, '.',   0,   0,   0,   0, ' ',   0,   0,   0,   0,   0,   0,  // 3x
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  // 4x
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  // 5x
     0,   0,   0,   0,   0,   0, HME,  UP, LNX, LFT, RGT,   0, DWN, RPR,   0,   0,  // 6x
     0,   0, VLD, VLU,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, SYM,   0,  // 7x
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, MNU,   0,   0,   0,   0,  // 8x
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, BAK,   0,  // 9x
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  // Ax
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  AA, RNX,  // Bx
     0, LPR, SEL,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0   // Cx
};

class EventImpl
{
private:
   static const uint16_t TIMER_EV = 0xFF00;

   pthread_t             key_td;
   pthread_t             tmr_td;
   volatile uint32_t     tmr_period_ms;
   pthread_mutex_t       fifo_mutex;
   pthread_cond_t        fifo_cv;
   STB::Fifo<uint16_t,4> fifo;

   //! Push an event in a thread safe manner
   void pushEvent(PLT::Event::Type type, uint8_t code = 0)
   {
      uint16_t ev = (uint16_t(type) << 8) | code;

      pthread_mutex_lock(&fifo_mutex);

      if (!fifo.full()) fifo.push(ev);
      pthread_cond_signal(&fifo_cv);

      pthread_mutex_unlock(&fifo_mutex);
   }

   //! Get next event in a thread safe manner
   bool popEvent(bool block, PLT::Event::Type& type, uint8_t& code)
   {
      bool new_event;

      pthread_mutex_lock(&fifo_mutex);

      if (block)
      {
         while(fifo.empty())
         {
            pthread_cond_wait(&fifo_cv, &fifo_mutex);
         }

         new_event = true;
      }
      else
      {
         new_event = !fifo.empty();
      }

      if (new_event)
      {
         uint16_t ev = fifo.back();
         fifo.pop();
         type = PLT::Event::Type(ev >> 8);
         code = uint8_t(ev);
      }

      pthread_mutex_unlock(&fifo_mutex);

      return new_event;
   }

   //! Loop to wait for key events
   void keyEventLoop()
   {
      static const unsigned NUM_FD = 3;

      int fd[NUM_FD];

      fd[0] = open("/dev/input/event0", O_RDONLY | O_NONBLOCK);
      fd[1] = open("/dev/input/event1", O_RDONLY | O_NONBLOCK);
      fd[2] = open("/dev/input/event2", O_RDONLY | O_NONBLOCK);

      int nfds = 0;
      for(unsigned i = 0; i < NUM_FD; ++i)
      {
         if(fd[i] > nfds) nfds = fd[i];
      }
      nfds++;

      while(true)
      {
         fd_set read_fds;

         FD_ZERO(&read_fds);

         for(unsigned i = 0; i < NUM_FD; ++i)
         {
            FD_SET(fd[i], &read_fds);
         }

         if(select(nfds, &read_fds, NULL, NULL, NULL) < 0) break;

         for(unsigned i = 0; i < NUM_FD; ++i)
         {
            if(FD_ISSET(fd[i], &read_fds))
            {
               uint8_t buffer[16];

               if(read(fd[i], buffer, 16) != 16) break;

               if(buffer[10] < 0xD0)
               {
                  switch(buffer[12])
                  {
                  case 0: pushEvent(PLT::Event::KEY_UP,   event_decode[buffer[10]]); break;
                  case 1: pushEvent(PLT::Event::KEY_DOWN, event_decode[buffer[10]]); break;
                  default: break;
                  }
               }
            }
         }
      }

      for(unsigned i = 0; i < NUM_FD; ++i)
      {
         close(fd[i]);
      }
   }

   static void* thunkKeyEventLoop(void* ptr)
   {
      EventImpl* impl = (EventImpl*)ptr;
      impl->keyEventLoop();
      return 0;
   }

   //! Loop to wait for periodic timer events
   void tmrEventLoop()
   {
      while(true)
      {
         usleep(tmr_period_ms * 1000);
         pushEvent(PLT::Event::TIMER);
      }
   }

   static void* thunkTmrEventLoop(void* ptr)
   {
      EventImpl* impl = (EventImpl*)ptr;
      impl->tmrEventLoop();
      return 0;
   }

public:
   EventImpl()
      : key_td(0)
      , tmr_td(0)
      , tmr_period_ms(0)
   {
      pthread_mutex_init(&fifo_mutex, 0);

      pthread_attr_t attr;
      pthread_attr_init(&attr);
      pthread_create(&key_td, &attr, thunkKeyEventLoop, this);
   }

   ~EventImpl()
   {
      pthread_cancel(key_td);
      pthread_cancel(tmr_td);
   }

   void setTimer(uint32_t period_ms)
   {
      tmr_period_ms = period_ms;

      if(tmr_td == 0)
      {
         pthread_attr_t attr;
         pthread_attr_init(&attr);
         pthread_create(&tmr_td, &attr, thunkTmrEventLoop, this);
      }
   }

   PLT::Event::Type getEvent(PLT::Event::Message& event, bool block)
   {
      event.type = PLT::Event::NONE;
      event.x    = 0;
      event.y    = 0;

      if(popEvent(block, event.type, event.code))
      {
         // printf("getEvent() => EV %x:%02x\n", event.type, event.code);
      }

      return PLT::Event::Type(event.type);
   }
};

static EventImpl impl;

static PLT::Event::Type getEvent(PLT::Event::Message& event, bool wait)
{
   return impl.getEvent(event, wait);
}

namespace PLT {

namespace Event {

Type poll(Message& event)
{
   return getEvent(event, /* block */ false);
}

Type wait(Message& event)
{
   return getEvent(event, /* block */ true);
}

int mainLoop(bool (*callback)(void*), void* user_data)
{
   while(true)
   {
      Message event;
      Type    type = wait(event);

      if(callback != nullptr) (*callback)(user_data);

      if(type == QUIT) return 0;
   }
}

int eventLoop(void (*callback)(const Message&, void*), void* user_data)
{
   while(true)
   {
      Message event;
      Type    type = wait(event);

      if(callback != nullptr) (*callback)(event, user_data);

      if(type == QUIT) return 0;
   }
}

void setTimer(unsigned period_ms)
{
   impl.setTimer(period_ms);
}

} // namespace Event

} // namespace PLT
<commit_msg>Avoid timer deadlock in Kindle3 events handling<commit_after>//------------------------------------------------------------------------------
// Copyright (c) 2016 John D. Haughton
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//------------------------------------------------------------------------------

// Kindle3 Linux event

#include <assert.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>

// C++11 threads would be nicer but don't seem to be able to link
// against any libs that actually work at runtime
#include <pthread.h>

#include "PLT/Event.h"
#include "STB/Fifo.h"

// ALT    ?

static const uint8_t DEL = PLT::BACKSPACE;
static const uint8_t RET = PLT::RETURN;
static const uint8_t LSH = PLT::LSHIFT;
static const uint8_t UP  = PLT::UP;        // Cursor up
static const uint8_t DWN = PLT::DOWN;      // Cursor down
static const uint8_t LFT = PLT::LEFT;      // Cursor left
static const uint8_t RGT = PLT::RIGHT;     // Cursor ritgh
static const uint8_t HME = PLT::ESCAPE;    // Home
static const uint8_t LPR = PLT::HOME;      // Left previous
static const uint8_t LNX = PLT::END;       // Left next
static const uint8_t RPR = PLT::PAGE_UP;   // Right previous
static const uint8_t RNX = PLT::PAGE_DOWN; // Right next
static const uint8_t SEL = PLT::SELECT;    // Select (center of cursor keys)
static const uint8_t MNU = PLT::MENU;      // Menu
static const uint8_t BAK = PLT::BACK;      // Back
static const uint8_t AA  = PLT::CAPSLOCK;  // Aa
static const uint8_t SYM = PLT::RALT;      // Sym
static const uint8_t VLD = PLT::VOL_DOWN;  // Volume -
static const uint8_t VLU = PLT::VOL_UP;    // Volume +

static const uint8_t event_decode[0xD0] =
{
//  x0   x1   x2   x3   x4   x5   x6   x7   x8   x9   xA   xB   xC   xD   xE   xF
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, DEL,   0,  // 0x
   'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p',   0,   0, RET,   0, 'a', 's',  // 1x
   'd', 'f', 'g', 'h', 'j', 'k', 'l',   0,   0,   0, LSH,   0, 'z', 'x', 'c', 'v',  // 2x
   'b', 'n', 'm',   0, '.',   0,   0,   0,   0, ' ',   0,   0,   0,   0,   0,   0,  // 3x
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  // 4x
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  // 5x
     0,   0,   0,   0,   0,   0, HME,  UP, LNX, LFT, RGT,   0, DWN, RPR,   0,   0,  // 6x
     0,   0, VLD, VLU,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, SYM,   0,  // 7x
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, MNU,   0,   0,   0,   0,  // 8x
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, BAK,   0,  // 9x
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  // Ax
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  AA, RNX,  // Bx
     0, LPR, SEL,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0   // Cx
};

class EventImpl
{
private:
   static const uint16_t TIMER_EV = 0xFF00;

   pthread_t             key_td{0};
   pthread_mutex_t       fifo_mutex;
   pthread_cond_t        fifo_cv;
   STB::Fifo<uint16_t,4> fifo;

   pthread_t             timer_td{0};
   volatile uint32_t     timer_period_ms{0};
   pthread_mutex_t       timer_mutex;
   pthread_cond_t        timer_cv;

   //! Push an event in a thread safe manner
   void pushEvent(PLT::Event::Type type, uint8_t code = 0)
   {
      uint16_t ev = (uint16_t(type) << 8) | code;

      pthread_mutex_lock(&fifo_mutex);

      if (!fifo.full()) fifo.push(ev);
      pthread_cond_signal(&fifo_cv);

      pthread_mutex_unlock(&fifo_mutex);
   }

   //! Get next event in a thread safe manner
   bool popEvent(bool block, PLT::Event::Type& type, uint8_t& code)
   {
      bool new_event;

      pthread_mutex_lock(&fifo_mutex);

      if (block)
      {
         while(fifo.empty())
         {
            pthread_cond_wait(&fifo_cv, &fifo_mutex);
         }

         new_event = true;
      }
      else
      {
         new_event = !fifo.empty();
      }

      if (new_event)
      {
         uint16_t ev = fifo.back();
         fifo.pop();
         type = PLT::Event::Type(ev >> 8);
         code = uint8_t(ev);
      }

      pthread_mutex_unlock(&fifo_mutex);

      return new_event;
   }

   //! Loop to wait for key events
   void keyEventLoop()
   {
      static const unsigned NUM_FD = 3;

      int fd[NUM_FD];

      fd[0] = open("/dev/input/event0", O_RDONLY | O_NONBLOCK);
      fd[1] = open("/dev/input/event1", O_RDONLY | O_NONBLOCK);
      fd[2] = open("/dev/input/event2", O_RDONLY | O_NONBLOCK);

      int nfds = 0;
      for(unsigned i = 0; i < NUM_FD; ++i)
      {
         if(fd[i] > nfds) nfds = fd[i];
      }
      nfds++;

      while(true)
      {
         fd_set read_fds;

         FD_ZERO(&read_fds);

         for(unsigned i = 0; i < NUM_FD; ++i)
         {
            FD_SET(fd[i], &read_fds);
         }

         if(select(nfds, &read_fds, NULL, NULL, NULL) < 0) break;

         for(unsigned i = 0; i < NUM_FD; ++i)
         {
            if(FD_ISSET(fd[i], &read_fds))
            {
               uint8_t buffer[16];

               if(read(fd[i], buffer, 16) != 16) break;

               if(buffer[10] < 0xD0)
               {
                  switch(buffer[12])
                  {
                  case 0: pushEvent(PLT::Event::KEY_UP,   event_decode[buffer[10]]); break;
                  case 1: pushEvent(PLT::Event::KEY_DOWN, event_decode[buffer[10]]); break;
                  default: break;
                  }
               }
            }
         }
      }

      for(unsigned i = 0; i < NUM_FD; ++i)
      {
         close(fd[i]);
      }
   }

   static void* thunkKeyEventLoop(void* ptr)
   {
      EventImpl* impl = (EventImpl*)ptr;
      impl->keyEventLoop();
      return nullptr;
   }

   //! Loop to wait for periodic timer events
   void timerEventLoop()
   {
      while(true)
      {
         pthread_mutex_lock(&timer_mutex);

         while(timer_period_ms == 0)
         {
            pthread_cond_wait(&timer_cv, &timer_mutex);
         }

         unsigned period_ms = timer_period_ms;

         pthread_mutex_unlock(&timer_mutex);

         usleep(period_ms * 1000);
         pushEvent(PLT::Event::TIMER);
      }
   }

   static void* thunkTimerEventLoop(void* ptr)
   {
      EventImpl* impl = (EventImpl*)ptr;
      impl->timerEventLoop();
      return nullptr;
   }

public:
   EventImpl()
   {
      pthread_mutex_init(&fifo_mutex, 0);

      pthread_attr_t attr;
      pthread_attr_init(&attr);
      pthread_create(&key_td, &attr, thunkKeyEventLoop, this);
   }

   ~EventImpl()
   {
      pthread_cancel(key_td);
      pthread_cancel(timer_td);
   }

   void setTimer(uint32_t period_ms)
   {
      if(period_ms == timer_period_ms) return;

      if(timer_td == 0)
      {
         pthread_attr_t attr;
         pthread_attr_init(&attr);
         pthread_create(&timer_td, &attr, thunkTimerEventLoop, this);
      }

      pthread_mutex_lock(&timer_mutex);

      timer_period_ms = period_ms;
      pthread_cond_signal(&timer_cv);

      pthread_mutex_unlock(&timer_mutex);
   }

   PLT::Event::Type getEvent(PLT::Event::Message& event, bool block)
   {
      event.type = PLT::Event::NONE;
      event.x    = 0;
      event.y    = 0;

      if(popEvent(block, event.type, event.code))
      {
         // printf("getEvent() => EV %x:%02x\n", event.type, event.code);
      }

      return PLT::Event::Type(event.type);
   }
};

static EventImpl impl;

static PLT::Event::Type getEvent(PLT::Event::Message& event, bool wait)
{
   return impl.getEvent(event, wait);
}

namespace PLT {

namespace Event {

Type poll(Message& event)
{
   return getEvent(event, /* block */ false);
}

Type wait(Message& event)
{
   return getEvent(event, /* block */ true);
}

int mainLoop(bool (*callback)(void*), void* user_data)
{
   while(true)
   {
      Message event;
      Type    type = wait(event);

      if(callback != nullptr) (*callback)(user_data);

      if(type == QUIT) return 0;
   }
}

int eventLoop(void (*callback)(const Message&, void*), void* user_data)
{
   while(true)
   {
      Message event;
      Type    type = wait(event);

      if(callback != nullptr) (*callback)(event, user_data);

      if(type == QUIT) return 0;
   }
}

void setTimer(unsigned period_ms)
{
   impl.setTimer(period_ms);
}

} // namespace Event

} // namespace PLT
<|endoftext|>


<commit_before>/*****************************************************************************
 * Project: RooFit                                                           *
 * Package: RooFitCore                                                       *
 *    File: $Id: RooProdGenContext.cc,v 1.7 2002/09/30 00:57:29 verkerke Exp $
 * Authors:                                                                  *
 *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu       *
 *   DK, David Kirkby,    UC Irvine,         dkirkby@uci.edu                 *
 *                                                                           *
 * Copyright (c) 2000-2002, Regents of the University of California          *
 *                          and Stanford University. All rights reserved.    *
 *                                                                           *
 * Redistribution and use in source and binary forms,                        *
 * with or without modification, are permitted according to the terms        *
 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
 *****************************************************************************/

// -- CLASS DESCRIPTION [AUX} --
// RooProdGenContext is an efficient implementation of the generator context
// specific for RooProdPdf PDFs. The sim-context owns a list of
// component generator contexts that are used to generate the dependents
// for each component PDF sequentially.

#include "RooFitCore/RooProdGenContext.hh"
#include "RooFitCore/RooProdPdf.hh"
#include "RooFitCore/RooDataSet.hh"

ClassImp(RooProdGenContext)
;

RooProdGenContext::RooProdGenContext(const RooProdPdf &model, const RooArgSet &vars,
				   const RooDataSet *prototype, Bool_t verbose) :
  RooAbsGenContext(model,vars,prototype,verbose), _pdf(&model)
{
  // Constructor. Build an array of generator contexts for each product component PDF

  // Make full list of dependents (generated & proto)
  RooArgSet deps(vars) ;
  if (prototype) {
    RooArgSet* protoDeps = model.getDependents(*prototype->get()) ;
    deps.add(*protoDeps) ;
    delete protoDeps ;
  }

  // Factorize product in irreducible terms
  TList* termList = model.factorizeProduct(deps) ;
  TIterator* termIter = termList->MakeIterator() ;

  RooAbsPdf* pdf ;
  RooArgSet* term ;
  while(term=(RooArgSet*)termIter->Next()) {
    TIterator* pdfIter = term->createIterator() ;

    if (term->getSize()==1) {
      // Simple term

      pdf = (RooAbsPdf*) pdfIter->Next() ;
      RooArgSet* pdfDep = pdf->getDependents(&vars) ;
      if (pdfDep->getSize()>0) {
	RooAbsGenContext* cx = pdf->genContext(*pdfDep,prototype,verbose) ;
	_gcList.Add(cx) ;
      }
      delete pdfDep ;

    } else {

      // Composite term
      RooArgSet termDeps ;
      while(pdf=(RooAbsPdf*) pdfIter->Next()) {
	RooArgSet* pdfDep = pdf->getDependents(&vars) ;
	termDeps.add(*pdfDep,kFALSE) ;
	delete pdfDep ;
      }
      if (termDeps.getSize()>0) {
	const char* name = model.makeRGPPName("PRODGEN_",*term,RooArgSet(),RooArgSet()) ;

	RooProdPdf* multiPdf = new RooProdPdf(name,name,*term) ;
	multiPdf->useDefaultGen(kTRUE) ;
	_ownedMultiProds.addOwned(*multiPdf) ;

	RooAbsGenContext* cx = multiPdf->genContext(termDeps,prototype,verbose) ;
	_gcList.Add(cx) ;
      }
    }

    delete pdfIter ;
  }
  _gcIter = _gcList.MakeIterator() ;
}

RooProdGenContext::~RooProdGenContext()
{
  // Destructor. Delete all owned subgenerator contexts
  delete _gcIter ;
  _gcList.Delete() ;
}

void RooProdGenContext::initGenerator(const RooArgSet &theEvent)
{
  // Forward initGenerator call to all components
  RooAbsGenContext* gc ;
  _gcIter->Reset() ;
  while(gc=(RooAbsGenContext*)_gcIter->Next()){
    gc->initGenerator(theEvent) ;
  }
}

void RooProdGenContext::generateEvent(RooArgSet &theEvent, Int_t remaining)
{
  // Generate a single event of the product by generating the components
  // of the products sequentially

  // Loop over the component generators
  TList compData ;
  RooAbsGenContext* gc ;
  _gcIter->Reset() ;
  while(gc=(RooAbsGenContext*)_gcIter->Next()) {

    // Generate component
    gc->generateEvent(theEvent,remaining) ;
  }
}

void RooProdGenContext::printToStream(ostream &os, PrintOption opt, TString indent) const
{
  RooAbsGenContext::printToStream(os,opt,indent) ;
  TString indent2(indent) ;
  indent2.Append("    ") ;
  RooAbsGenContext* gc ;
  _gcIter->Reset() ;
  while(gc=(RooAbsGenContext*)_gcIter->Next()) {
    gc->printToStream(os,opt,indent2) ;
  }
}
<commit_msg><commit_after>/*****************************************************************************
 * Project: RooFit                                                           *
 * Package: RooFitCore                                                       *
 *    File: $Id: RooProdGenContext.cc,v 1.8 2003/04/28 20:42:39 wverkerke Exp $
 * Authors:                                                                  *
 *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu       *
 *   DK, David Kirkby,    UC Irvine,         dkirkby@uci.edu                 *
 *                                                                           *
 * Copyright (c) 2000-2002, Regents of the University of California          *
 *                          and Stanford University. All rights reserved.    *
 *                                                                           *
 * Redistribution and use in source and binary forms,                        *
 * with or without modification, are permitted according to the terms        *
 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
 *****************************************************************************/

// -- CLASS DESCRIPTION [AUX} --
// RooProdGenContext is an efficient implementation of the generator context
// specific for RooProdPdf PDFs. The sim-context owns a list of
// component generator contexts that are used to generate the dependents
// for each component PDF sequentially.

#include "RooFitCore/RooProdGenContext.hh"
#include "RooFitCore/RooProdPdf.hh"
#include "RooFitCore/RooDataSet.hh"

ClassImp(RooProdGenContext)
;

RooProdGenContext::RooProdGenContext(const RooProdPdf &model, const RooArgSet &vars,
				   const RooDataSet *prototype, Bool_t verbose) :
  RooAbsGenContext(model,vars,prototype,verbose), _pdf(&model)
{
  // Constructor. Build an array of generator contexts for each product component PDF

  // Make full list of dependents (generated & proto)
  RooArgSet deps(vars) ;
  if (prototype) {
    RooArgSet* protoDeps = model.getDependents(*prototype->get()) ;
    deps.add(*protoDeps) ;
    delete protoDeps ;
  }

  // Factorize product in irreducible terms
  TList* termList = model.factorizeProduct(vars) ;
  TIterator* termIter = termList->MakeIterator() ;

  RooAbsPdf* pdf ;
  RooArgSet* term ;
  while(term=(RooArgSet*)termIter->Next()) {
    TIterator* pdfIter = term->createIterator() ;

    if (term->getSize()==1) {
      // Simple term

      pdf = (RooAbsPdf*) pdfIter->Next() ;
      RooArgSet* pdfDep = pdf->getDependents(&vars) ;
      if (pdfDep->getSize()>0) {
	RooAbsGenContext* cx = pdf->genContext(*pdfDep,prototype,verbose) ;
	_gcList.Add(cx) ;
      }
      delete pdfDep ;

    } else {

      // Composite term
      RooArgSet termDeps ;
      while(pdf=(RooAbsPdf*) pdfIter->Next()) {
	RooArgSet* pdfDep = pdf->getDependents(&vars) ;
	termDeps.add(*pdfDep,kFALSE) ;
	delete pdfDep ;
      }
      if (termDeps.getSize()>0) {
	const char* name = model.makeRGPPName("PRODGEN_",*term,RooArgSet(),RooArgSet()) ;

	RooProdPdf* multiPdf = new RooProdPdf(name,name,*term) ;
	multiPdf->useDefaultGen(kTRUE) ;
	_ownedMultiProds.addOwned(*multiPdf) ;

	RooAbsGenContext* cx = multiPdf->genContext(termDeps,prototype,verbose) ;
	_gcList.Add(cx) ;
      }
    }

    delete pdfIter ;
  }
  _gcIter = _gcList.MakeIterator() ;
}

RooProdGenContext::~RooProdGenContext()
{
  // Destructor. Delete all owned subgenerator contexts
  delete _gcIter ;
  _gcList.Delete() ;
}

void RooProdGenContext::initGenerator(const RooArgSet &theEvent)
{
  // Forward initGenerator call to all components
  RooAbsGenContext* gc ;
  _gcIter->Reset() ;
  while(gc=(RooAbsGenContext*)_gcIter->Next()){
    gc->initGenerator(theEvent) ;
  }
}

void RooProdGenContext::generateEvent(RooArgSet &theEvent, Int_t remaining)
{
  // Generate a single event of the product by generating the components
  // of the products sequentially

  // Loop over the component generators
  TList compData ;
  RooAbsGenContext* gc ;
  _gcIter->Reset() ;
  while(gc=(RooAbsGenContext*)_gcIter->Next()) {

    // Generate component
    gc->generateEvent(theEvent,remaining) ;
  }
}

void RooProdGenContext::printToStream(ostream &os, PrintOption opt, TString indent) const
{
  RooAbsGenContext::printToStream(os,opt,indent) ;
  TString indent2(indent) ;
  indent2.Append("    ") ;
  RooAbsGenContext* gc ;
  _gcIter->Reset() ;
  while(gc=(RooAbsGenContext*)_gcIter->Next()) {
    gc->printToStream(os,opt,indent2) ;
  }
}
<|endoftext|>


<commit_before>#include "ride/wx.h"
#include "ride/filepropertiesdlg.h"
#include "ride/fileedit.h"

#include <map>
#include <vector>

class StringIntConverter {
private:
  typedef std::vector<int> Ints;
  typedef std::map<int, wxString> IntsToStrings;
public:
  StringIntConverter& operator()(int i, const wxString& str) {
    strings_.Add(str);
    ints_.push_back(i);
    intstostrings_.insert(IntsToStrings::value_type(i, str));
    return *this;
  }

  const wxArrayString& strings() const {
    return strings_;
  }

  int GetInt(int index) const {
    return ints_[index];
  }

  int GetIndex(int i) const {
    for (int index = 0; index < ints_.size(); ++index) {
      if (ints_[index] == i) return index;
    }
    return 0;
  }

  wxString ToString(int i) const {
    IntsToStrings::const_iterator ret = intstostrings_.find(i);
    if (ret == intstostrings_.end()) return "Unknown";
    else return ret->second;
  }

private:
  wxArrayString strings_;
  Ints ints_;
  IntsToStrings intstostrings_;
};

const StringIntConverter& EOLString() {
  static StringIntConverter sic = StringIntConverter()
    (wxSTC_EOL_CR, wxT("CR (Unix)"))
    (wxSTC_EOL_CRLF, wxT("CRLF (Windows)"))
    (wxSTC_EOL_LF, wxT("CR (Macintosh)"));
  return sic;
}

const StringIntConverter& CodePageString() {
  static StringIntConverter sic = StringIntConverter()
    (wxSTC_CP_UTF8, "UTF-8")
    (wxSTC_CHARSET_ANSI, "Ansi")
    (wxSTC_CHARSET_DEFAULT, "Default")
    (wxSTC_CHARSET_BALTIC, "Baltic")
    (wxSTC_CHARSET_CHINESEBIG5, "Chinesebig5")
    (wxSTC_CHARSET_EASTEUROPE, "Easteurope")
    (wxSTC_CHARSET_GB2312, "Gb2312")
    (wxSTC_CHARSET_GREEK, "Greek")
    (wxSTC_CHARSET_HANGUL, "Hangul")
    (wxSTC_CHARSET_MAC, "Mac")
    (wxSTC_CHARSET_OEM, "Oem")
    (wxSTC_CHARSET_RUSSIAN, "Russian")
    (wxSTC_CHARSET_CYRILLIC, "Cyrillic")
    (wxSTC_CHARSET_SHIFTJIS, "Shiftjis")
    (wxSTC_CHARSET_SYMBOL, "Symbol")
    (wxSTC_CHARSET_TURKISH, "Turkish")
    (wxSTC_CHARSET_JOHAB, "Johab")
    (wxSTC_CHARSET_HEBREW, "Hebrew")
    (wxSTC_CHARSET_ARABIC, "Arabic")
    (wxSTC_CHARSET_VIETNAMESE, "Vietnamese")
    (wxSTC_CHARSET_THAI, "Thai")
    (wxSTC_CHARSET_8859_15, "8859_15");
  return sic;
}

FilePropertiesDlg::FilePropertiesDlg(FileEdit* parent, wxStyledTextCtrl* ctrl) : ::ui::FileProperties(parent, wxID_ANY), ctrl_(ctrl) {
  uiFileName->SetLabel(parent->filename());
  uiLanguage->SetLabelText(parent->GetLanguageName());
  UpdateGui();
}

void FilePropertiesDlg::UpdateGui() {
  uiEncoding->SetLabelText(CodePageString().ToString(ctrl_->GetCodePage()));
  uiLineEndings->SetLabelText(EOLString().ToString(ctrl_->GetEOLMode()));
}

// remove the encoding part?
void FilePropertiesDlg::OnChangeEncoding(wxCommandEvent& event) {
#ifdef wxUSE_UNICODE
  wxMessageBox("Unable to change encoding in unicode build", "Unicode only", wxICON_INFORMATION);
#else
  wxSingleChoiceDialog dlg(this, "Select new text encoding", "Text encoding", CodePageString().strings());
  if (dlg.ShowModal() != wxID_OK) return;
  const int selected = dlg.GetSelection();
  const int new_encoding = CodePageString().GetInt(selected);

  ctrl_->SetCodePage(new_encoding);
  UpdateGui();
#endif
}

void FilePropertiesDlg::OnChangeLineEnding(wxCommandEvent& event) {
  wxSingleChoiceDialog dlg(this, "Select new line ending", "Line ending?", EOLString().strings());
  dlg.SetSelection(EOLString().GetIndex(ctrl_->GetEOLMode()));
  if (dlg.ShowModal() != wxID_OK) return;
  const int selected = dlg.GetSelection();
  const int new_ending = EOLString().GetInt(selected);

  ctrl_->SetEOLMode(new_ending);
  ctrl_->ConvertEOLs(new_ending);
  UpdateGui();
}
<commit_msg>Fixed warning<commit_after>#include "ride/wx.h"
#include "ride/filepropertiesdlg.h"
#include "ride/fileedit.h"

#include <map>
#include <vector>

class StringIntConverter {
private:
  typedef std::vector<int> Ints;
  typedef std::map<int, wxString> IntsToStrings;
public:
  StringIntConverter& operator()(int i, const wxString& str) {
    strings_.Add(str);
    ints_.push_back(i);
    intstostrings_.insert(IntsToStrings::value_type(i, str));
    return *this;
  }

  const wxArrayString& strings() const {
    return strings_;
  }

  int GetInt(int index) const {
    return ints_[index];
  }

  size_t GetIndex(size_t i) const {
    for (size_t index = 0; index < ints_.size(); ++index) {
      if (ints_[index] == i) return index;
    }
    return 0;
  }

  wxString ToString(int i) const {
    IntsToStrings::const_iterator ret = intstostrings_.find(i);
    if (ret == intstostrings_.end()) return "Unknown";
    else return ret->second;
  }

private:
  wxArrayString strings_;
  Ints ints_;
  IntsToStrings intstostrings_;
};

const StringIntConverter& EOLString() {
  static StringIntConverter sic = StringIntConverter()
    (wxSTC_EOL_CR, wxT("CR (Unix)"))
    (wxSTC_EOL_CRLF, wxT("CRLF (Windows)"))
    (wxSTC_EOL_LF, wxT("CR (Macintosh)"));
  return sic;
}

const StringIntConverter& CodePageString() {
  static StringIntConverter sic = StringIntConverter()
    (wxSTC_CP_UTF8, "UTF-8")
    (wxSTC_CHARSET_ANSI, "Ansi")
    (wxSTC_CHARSET_DEFAULT, "Default")
    (wxSTC_CHARSET_BALTIC, "Baltic")
    (wxSTC_CHARSET_CHINESEBIG5, "Chinesebig5")
    (wxSTC_CHARSET_EASTEUROPE, "Easteurope")
    (wxSTC_CHARSET_GB2312, "Gb2312")
    (wxSTC_CHARSET_GREEK, "Greek")
    (wxSTC_CHARSET_HANGUL, "Hangul")
    (wxSTC_CHARSET_MAC, "Mac")
    (wxSTC_CHARSET_OEM, "Oem")
    (wxSTC_CHARSET_RUSSIAN, "Russian")
    (wxSTC_CHARSET_CYRILLIC, "Cyrillic")
    (wxSTC_CHARSET_SHIFTJIS, "Shiftjis")
    (wxSTC_CHARSET_SYMBOL, "Symbol")
    (wxSTC_CHARSET_TURKISH, "Turkish")
    (wxSTC_CHARSET_JOHAB, "Johab")
    (wxSTC_CHARSET_HEBREW, "Hebrew")
    (wxSTC_CHARSET_ARABIC, "Arabic")
    (wxSTC_CHARSET_VIETNAMESE, "Vietnamese")
    (wxSTC_CHARSET_THAI, "Thai")
    (wxSTC_CHARSET_8859_15, "8859_15");
  return sic;
}

FilePropertiesDlg::FilePropertiesDlg(FileEdit* parent, wxStyledTextCtrl* ctrl) : ::ui::FileProperties(parent, wxID_ANY), ctrl_(ctrl) {
  uiFileName->SetLabel(parent->filename());
  uiLanguage->SetLabelText(parent->GetLanguageName());
  UpdateGui();
}

void FilePropertiesDlg::UpdateGui() {
  uiEncoding->SetLabelText(CodePageString().ToString(ctrl_->GetCodePage()));
  uiLineEndings->SetLabelText(EOLString().ToString(ctrl_->GetEOLMode()));
}

// remove the encoding part?
void FilePropertiesDlg::OnChangeEncoding(wxCommandEvent& event) {
#ifdef wxUSE_UNICODE
  wxMessageBox("Unable to change encoding in unicode build", "Unicode only", wxICON_INFORMATION);
#else
  wxSingleChoiceDialog dlg(this, "Select new text encoding", "Text encoding", CodePageString().strings());
  if (dlg.ShowModal() != wxID_OK) return;
  const int selected = dlg.GetSelection();
  const int new_encoding = CodePageString().GetInt(selected);

  ctrl_->SetCodePage(new_encoding);
  UpdateGui();
#endif
}

void FilePropertiesDlg::OnChangeLineEnding(wxCommandEvent& event) {
  wxSingleChoiceDialog dlg(this, "Select new line ending", "Line ending?", EOLString().strings());
  dlg.SetSelection(EOLString().GetIndex(ctrl_->GetEOLMode()));
  if (dlg.ShowModal() != wxID_OK) return;
  const int selected = dlg.GetSelection();
  const int new_ending = EOLString().GetInt(selected);

  ctrl_->SetEOLMode(new_ending);
  ctrl_->ConvertEOLs(new_ending);
  UpdateGui();
}
<|endoftext|>


<commit_before>namespace treap {
    mt19937 rnd = []() {
        random_device rd;
        return mt19937(rd());
    }();

    template <typename T>
    struct Node {
        Node* l;
        Node* r;
        uint32_t y;
        size_t sz;

        T data;

        Node(): l(nullptr), r(nullptr), y(rnd()), sz(1), data() {}
        Node(const T& data): l(nullptr), r(nullptr), y(rnd()), sz(1), data(data) {}
        Node(T&& data): l(nullptr), r(nullptr), y(rnd()), sz(1), data(data) {}

        Node* update() {
            sz = size(l) + 1 + size(r);
            return this;
        }

        Node* setL(Node* l) {
            this->l = l;
            return update();
        }

        Node* setR(Node* r) {
            this->r = r;
            return update();
        }
    };

    template <typename T>
    size_t size(T* t) {
        if (!t) return 0;
        return t->sz;
    }

    template <typename T>
    T* merge(T* l, T* r) {
        if (!l || !r) return l ? l : r;
        if (l->y > r->y) return l->setR(merge(l->r, r));
        else return r->setL(merge(l, r->l));
    }

    template <typename T>
    pair<T*, T*> split(T* t, size_t sz) {
        if (!t) return make_pair(t, t);
        if (size(t->l) < sz) {
            auto tmp = split(t->r, sz - 1 - size(t->l));
            return make_pair(t->setR(tmp.first), tmp.second);
        } else {
            auto tmp = split(t->l, sz);
            return make_pair(tmp.first, t->setL(tmp.second));
        }
    }

    template <typename T>
    tuple<T*, T*, T*> cut(T* t, size_t l, size_t r) {
        T *a, *b, *c;
        tie(a, b) = split(t, l);
        tie(b, c) = split(b, r - l);
        return make_tuple(a, b, c);
    }

    template <typename T, typename C>
    void walk(T* t, const C& callback) {
        if (!t) return;
        walk(t->l, callback);
        callback(*t);
        walk(t->r, callback);
    }

    const auto printData = [](const node& n) {
        cout << n.data << " ";
    };
}

using namespace treap;
using node = Node<int>;
<commit_msg>treap fix<commit_after>namespace treap {
    mt19937 rnd = []() {
        random_device rd;
        return mt19937(rd());
    }();

    template <typename T>
    struct Node {
        Node* l;
        Node* r;
        uint32_t y;
        size_t sz;

        T data;

        Node(): l(nullptr), r(nullptr), y(rnd()), sz(1), data() {}
        Node(const T& data): l(nullptr), r(nullptr), y(rnd()), sz(1), data(data) {}
        Node(T&& data): l(nullptr), r(nullptr), y(rnd()), sz(1), data(data) {}

        Node* update() {
            sz = size(l) + 1 + size(r);
            return this;
        }

        Node* setL(Node* l) {
            this->l = l;
            return update();
        }

        Node* setR(Node* r) {
            this->r = r;
            return update();
        }
    };

    template <typename T>
    size_t size(T* t) {
        if (!t) return 0;
        return t->sz;
    }

    template <typename T>
    T* merge(T* l, T* r) {
        if (!l || !r) return l ? l : r;
        if (l->y > r->y) return l->setR(merge(l->r, r));
        else return r->setL(merge(l, r->l));
    }

    template <typename T>
    pair<T*, T*> split(T* t, size_t sz) {
        if (!t) return make_pair(t, t);
        if (size(t->l) < sz) {
            auto tmp = split(t->r, sz - 1 - size(t->l));
            return make_pair(t->setR(tmp.first), tmp.second);
        } else {
            auto tmp = split(t->l, sz);
            return make_pair(tmp.first, t->setL(tmp.second));
        }
    }

    template <typename T>
    tuple<T*, T*, T*> cut(T* t, size_t l, size_t r) {
        T *a, *b, *c;
        tie(a, b) = split(t, l);
        tie(b, c) = split(b, r - l);
        return make_tuple(a, b, c);
    }

    template <typename T, typename C>
    void walk(T* t, const C& callback) {
        if (!t) return;
        walk(t->l, callback);
        callback(*t);
        walk(t->r, callback);
    }
}

using namespace treap;
using node = Node<int>;

const auto printData = [](const node& n) {
    cout << n.data << " ";
};
<|endoftext|>


<commit_before>/**
 ** \file object/float-class.cc
 ** \brief Creation of the URBI object float.
 */

#include <cmath>

#include "sdk/config.h"
#ifndef HAVE_ROUND
#  include "libport/ufloat.h"
#endif

#include "object/float-class.hh"
#include "object/object.hh"
#include "object/atom.hh"
#include "object/urbi-exception.hh"

namespace object
{
  rObject float_class;

  /*-----------------------------------------.
  | Routines to implement float primitives.  |
  `-----------------------------------------*/

  // This macro is used to generate modulo
  // and division functions.
#define FCT_OP_PROTECTED(Name, Operator, ErrorMessage)                  \
  static                                                                \
  libport::ufloat                                                       \
  float_##Name (libport::ufloat l, libport::ufloat r)                   \
  {                                                                     \
    if (!r)								\
      throw PrimitiveError("Operator " #Operator,                       \
			   ErrorMessage);                               \
    return l Operator r;                                                \
  }

#define FCT_M_PROTECTED(Name, Method, ErrorMessage)                     \
  static                                                                \
  libport::ufloat                                                       \
  float_##Name (libport::ufloat l, libport::ufloat r)                   \
  {                                                                     \
    if (!r)								\
      throw PrimitiveError(#Method, ErrorMessage);                      \
    return Method(l, r);                                                \
  }

  FCT_OP_PROTECTED(div, /, "division by 0")
  FCT_M_PROTECTED(mod, fmod, "modulo by 0")

#undef FCT_M_PROTECTED
#undef FCT_OP_PROTECTED

  static libport::ufloat
  float_req (libport::ufloat l, libport::ufloat r)
  {
    // FIXME: get epsilontilde from environment

    // ENSURE_COMPARISON ("Approximate", l, r);
    // UVariable *epsilontilde =
    //   ::urbiserver->getVariable(MAINDEVICE, "epsilontilde");
    // if (epsilontilde)
    //   $EXEC$
    // else
    //   return 0;

#define epsilontilde 0.0001
    return fabs(l - r) <= epsilontilde;
#undef epsilontilde
  }

  static float
  float_deq (libport::ufloat l, libport::ufloat r)
  {
    // FIXME: get deltas for l and r

    // ENSURE_COMPARISON ("Approximate", l, r);
    libport::ufloat dl = 0.f;
    libport::ufloat dr = 0.f;
    // dl = 0, get l->delta
    // dr = 0, get r->delta

    return fabs(l - r) <= dl + dr;
  }

  static float
  float_peq (libport::ufloat l, libport::ufloat r)
  {
    // FIXME: get epsilonpercent from environment
    // FIXME: return error on div by 0

    // ENSURE_COMPARISON ("Approximate", l, r);
    // UVariable *epsilonpercent =
    //   ::urbiserver->getVariable(MAINDEVICE, "epsilonpercent");
    // if (epsilonpercent)
    //   $EXEC$
    // else
    //   return 0;

    if (r == 0)
      // FIXME: error
      return 0;

# define epsilonpercent 0.0001
    return fabs(1.f - l / r) < epsilonpercent;
# undef epsilonpercent
  }

  static float
  float_sgn (libport::ufloat x)
  {
    return
      0 < x ?  1 :
      x < 0 ? -1 :
      0;
  }

  static float
  float_random (libport::ufloat x)
  {
    float res = 0.f;
    const long long range = libport::to_long_long (x);
    if (range)
      res = rand () % range;
    return res;
  }

  // This is quite hideous, to be cleaned once we have integers.
# define INTEGER_BIN_OP(Name, Op)					\
  static float								\
  float_ ## Name (libport::ufloat lhs, libport::ufloat rhs)		\
  {									\
    return libport::to_long_long (lhs) Op libport::to_long_long (rhs);	\
  }

  INTEGER_BIN_OP(lshift, <<)
  INTEGER_BIN_OP(rshift, >>)
  INTEGER_BIN_OP(xor,    ^)

# undef INTEGER_BIN_OP

/*-------------------------------------------------------------------.
| Float Primitives.                                                  |
|                                                                    |
| I.e., the signature is runner::Runner& x objects_type -> rObject.  |
`--------------------------------------------------------------------*/

  /// Clone.
  static rObject
  float_class_clone(runner::Runner&, objects_type args)
  {
    CHECK_ARG_COUNT(1);
    FETCH_ARG(0, Float);
    return clone(arg0);
  }

  /// Change the value.
  static rObject
  float_class_set(runner::Runner&, objects_type args)
  {
    CHECK_ARG_COUNT(2);
    FETCH_ARG(0, Float);
    FETCH_ARG(1, Float);
    arg0->value_set (arg1->value_get());
    return arg0;
  }

  /// Unary or binary minus.
  static rObject
  float_class_sub(runner::Runner&, objects_type args)
  {
    // FIXME: The error message requires 2 although 1 is ok.
    if (args.size () != 1 && args.size() != 2)
      throw WrongArgumentCount(2, args.size (), __PRETTY_FUNCTION__);
    FETCH_ARG(0, Float);
    if (args.size() == 1)
      return new Float(- arg0->value_get());
    else
    {
      FETCH_ARG(1, Float);
      return new Float(arg0->value_get() - arg1->value_get());
    }
  }

  /// Internal macro used to define a primitive for float numbers.
  /// \param Name primitive's name
  /// \param Call C++ code executed when primitive is called.
  /// \param Pre C++ code executed before call (typically to check args)
#define PRIMITIVE_0_FLOAT_(Name, Call, Pre)             \
  static rObject					\
  float_class_ ## Name (runner::Runner&, objects_type args)	\
  {                                                     \
    CHECK_ARG_COUNT(1);                                 \
    FETCH_ARG(0, Float);                                \
    Pre;                                                \
    return new Float(Call(arg0->value_get()));          \
  }

  /// Define a primitive for float numbers.
  /// \param Call Name primitive's name
#define PRIMITIVE_0_FLOAT(Name, Call)                   \
  PRIMITIVE_0_FLOAT_(Name, Call, )

#define PRIMITIVE_0_FLOAT_CHECK_POSITIVE(Name, Call)            \
  PRIMITIVE_0_FLOAT_(Name, Call,                                \
     if (VALUE(args[0], Float) < 0)                             \
       throw PrimitiveError(#Name,                              \
			    "argument has to be positive"))

#define PRIMITIVE_0_FLOAT_CHECK_RANGE(Name, Call, Min, Max)		\
  PRIMITIVE_0_FLOAT_(Name, Call,					\
     if (VALUE(args[0], Float) < Min || Max < VALUE(args[0], Float))	\
      throw PrimitiveError(#Name, "invalid range"))

#define PRIMITIVE_2_FLOAT(Name, Call)                   \
  PRIMITIVE_2_V(float, Name, Call, Float, Float, Float)

#define PRIMITIVE_OP_FLOAT(Name, Op)                    \
  PRIMITIVE_OP_V(float, Name, Op, Float, Float, Float)

  // Binary arithmetics operators.
  PRIMITIVE_OP_FLOAT(PLUS, +)
  PRIMITIVE_2_FLOAT(SLASH, float_div)
  PRIMITIVE_OP_FLOAT(STAR, *)
  PRIMITIVE_2_FLOAT(PERCENT, float_mod)
  PRIMITIVE_2_FLOAT(STAR_STAR, powf)

  PRIMITIVE_2_FLOAT(LT_LT, float_lshift) // <<
  PRIMITIVE_2_FLOAT(GT_GT, float_rshift) // >>
  PRIMITIVE_2_FLOAT(CARET,    float_xor)    // ^

  PRIMITIVE_OP_FLOAT(AMPSERSAND_AMPSERSAND, &&)
  PRIMITIVE_OP_FLOAT(PIPE_PIPE, ||)

  PRIMITIVE_OP_FLOAT(EQ_EQ, ==)
  PRIMITIVE_2_FLOAT(TILDA_EQ, float_req) //REQ ~=
  PRIMITIVE_2_FLOAT(EQ_TILDA_EQ, float_deq) //DEQ =~=
  PRIMITIVE_2_FLOAT(PERCENT_EQ, float_peq) //PEQ %=

  PRIMITIVE_OP_FLOAT(LT, <)

  PRIMITIVE_0_FLOAT(sin, sin)
  PRIMITIVE_0_FLOAT_CHECK_RANGE(asin, asin, -1, 1)
  PRIMITIVE_0_FLOAT(cos, cos)
  PRIMITIVE_0_FLOAT_CHECK_RANGE(acos, acos, -1, 1)
  PRIMITIVE_0_FLOAT(tan, tan)
  PRIMITIVE_0_FLOAT(atan, atan)
  PRIMITIVE_0_FLOAT(sgn, float_sgn)
  PRIMITIVE_0_FLOAT(abs, fabs)
  PRIMITIVE_0_FLOAT(exp, exp)
  PRIMITIVE_0_FLOAT_CHECK_POSITIVE(log, log)
  PRIMITIVE_0_FLOAT(round, round)
  PRIMITIVE_0_FLOAT(random, float_random)
  PRIMITIVE_0_FLOAT(trunc, trunc)
  PRIMITIVE_0_FLOAT_CHECK_POSITIVE(sqrt, sqrt)

#undef PRIMITIVE_2_FLOAT
#undef PRIMITIVE_0_FLOAT_CHECK_RANGE
#undef PRIMITIVE_0_FLOAT_CHECK_POSITIVE
#undef PRIMITIVE_0_FLOAT
#undef PRIMITIVE_0_FLOAT_
#undef PRIMITIVE_OP_FLOAT

  /// Initialize the Float class.
  void
  float_class_initialize ()
  {
    /// \a Call gives the name of the C++ function, and \a Name that in Urbi.
#define DECLARE(Name)                      \
    DECLARE_PRIMITIVE(float, Name, Name)

    DECLARE(PLUS);
    DECLARE(SLASH);
    DECLARE(STAR);
    DECLARE(MINUS);
    DECLARE(STAR_STAR);
    DECLARE(PERCENT);

    DECLARE(LT_LT);
    DECLARE(GT_GT);
    DECLARE(CARET);

    DECLARE(AMPERSAND_AMPERSAND);
    DECLARE(PIPE_PIPE);

    DECLARE(EQ_EQ);
    DECLARE(TILDA_EQ);
    DECLARE(EQ_TILDA_EQ);
    DECLARE(PERCENT_EQ);

    DECLARE(LT);

    DECLARE(clone);
    DECLARE(set);

    DECLARE(sin);
    DECLARE(asin);
    DECLARE(cos);
    DECLARE(acos);
    DECLARE(tan);
    DECLARE(atan);
    DECLARE(sgn);
    DECLARE(abs);
    DECLARE(exp);
    DECLARE(log);
    DECLARE(round);
    DECLARE(random);
    DECLARE(trunc);
    DECLARE(sqrt);
#undef DECLARE

  }

}; // namespace object
<commit_msg>More symbols.<commit_after>/**
 ** \file object/float-class.cc
 ** \brief Creation of the URBI object float.
 */

#include <cmath>

#include "sdk/config.h"
#ifndef HAVE_ROUND
#  include "libport/ufloat.h"
#endif

#include "object/float-class.hh"
#include "object/object.hh"
#include "object/atom.hh"
#include "object/urbi-exception.hh"

namespace object
{
  rObject float_class;

  /*-----------------------------------------.
  | Routines to implement float primitives.  |
  `-----------------------------------------*/

  // This macro is used to generate modulo
  // and division functions.
#define FCT_OP_PROTECTED(Name, Operator, ErrorMessage)                  \
  static                                                                \
  libport::ufloat                                                       \
  float_##Name (libport::ufloat l, libport::ufloat r)                   \
  {                                                                     \
    if (!r)								\
      throw PrimitiveError("Operator " #Operator,                       \
			   ErrorMessage);                               \
    return l Operator r;                                                \
  }

#define FCT_M_PROTECTED(Name, Method, ErrorMessage)                     \
  static                                                                \
  libport::ufloat                                                       \
  float_##Name (libport::ufloat l, libport::ufloat r)                   \
  {                                                                     \
    if (!r)								\
      throw PrimitiveError(#Method, ErrorMessage);                      \
    return Method(l, r);                                                \
  }

  FCT_OP_PROTECTED(div, /, "division by 0")
  FCT_M_PROTECTED(mod, fmod, "modulo by 0")

#undef FCT_M_PROTECTED
#undef FCT_OP_PROTECTED

  static libport::ufloat
  float_req (libport::ufloat l, libport::ufloat r)
  {
    // FIXME: get epsilontilde from environment

    // ENSURE_COMPARISON ("Approximate", l, r);
    // UVariable *epsilontilde =
    //   ::urbiserver->getVariable(MAINDEVICE, "epsilontilde");
    // if (epsilontilde)
    //   $EXEC$
    // else
    //   return 0;

#define epsilontilde 0.0001
    return fabs(l - r) <= epsilontilde;
#undef epsilontilde
  }

  static float
  float_deq (libport::ufloat l, libport::ufloat r)
  {
    // FIXME: get deltas for l and r

    // ENSURE_COMPARISON ("Approximate", l, r);
    libport::ufloat dl = 0.f;
    libport::ufloat dr = 0.f;
    // dl = 0, get l->delta
    // dr = 0, get r->delta

    return fabs(l - r) <= dl + dr;
  }

  static float
  float_peq (libport::ufloat l, libport::ufloat r)
  {
    // FIXME: get epsilonpercent from environment
    // FIXME: return error on div by 0

    // ENSURE_COMPARISON ("Approximate", l, r);
    // UVariable *epsilonpercent =
    //   ::urbiserver->getVariable(MAINDEVICE, "epsilonpercent");
    // if (epsilonpercent)
    //   $EXEC$
    // else
    //   return 0;

    if (r == 0)
      // FIXME: error
      return 0;

# define epsilonpercent 0.0001
    return fabs(1.f - l / r) < epsilonpercent;
# undef epsilonpercent
  }

  static float
  float_sgn (libport::ufloat x)
  {
    return
      0 < x ?  1 :
      x < 0 ? -1 :
      0;
  }

  static float
  float_random (libport::ufloat x)
  {
    float res = 0.f;
    const long long range = libport::to_long_long (x);
    if (range)
      res = rand () % range;
    return res;
  }

  // This is quite hideous, to be cleaned once we have integers.
# define INTEGER_BIN_OP(Name, Op)					\
  static float								\
  float_ ## Name (libport::ufloat lhs, libport::ufloat rhs)		\
  {									\
    return libport::to_long_long (lhs) Op libport::to_long_long (rhs);	\
  }

  INTEGER_BIN_OP(lshift, <<)
  INTEGER_BIN_OP(rshift, >>)
  INTEGER_BIN_OP(xor,    ^)

# undef INTEGER_BIN_OP

/*-------------------------------------------------------------------.
| Float Primitives.                                                  |
|                                                                    |
| I.e., the signature is runner::Runner& x objects_type -> rObject.  |
`--------------------------------------------------------------------*/

  /// Clone.
  static rObject
  float_class_clone(runner::Runner&, objects_type args)
  {
    CHECK_ARG_COUNT(1);
    FETCH_ARG(0, Float);
    return clone(arg0);
  }

  /// Change the value.
  static rObject
  float_class_set(runner::Runner&, objects_type args)
  {
    CHECK_ARG_COUNT(2);
    FETCH_ARG(0, Float);
    FETCH_ARG(1, Float);
    arg0->value_set (arg1->value_get());
    return arg0;
  }

  /// Unary or binary minus.
  static rObject
  float_class_MINUS(runner::Runner&, objects_type args)
  {
    // FIXME: The error message requires 2 although 1 is ok.
    if (args.size () != 1 && args.size() != 2)
      throw WrongArgumentCount(2, args.size (), __PRETTY_FUNCTION__);
    FETCH_ARG(0, Float);
    if (args.size() == 1)
      return new Float(- arg0->value_get());
    else
    {
      FETCH_ARG(1, Float);
      return new Float(arg0->value_get() - arg1->value_get());
    }
  }

  /// Internal macro used to define a primitive for float numbers.
  /// \param Name primitive's name
  /// \param Call C++ code executed when primitive is called.
  /// \param Pre C++ code executed before call (typically to check args)
#define PRIMITIVE_0_FLOAT_(Name, Call, Pre)             \
  static rObject					\
  float_class_ ## Name (runner::Runner&, objects_type args)	\
  {                                                     \
    CHECK_ARG_COUNT(1);                                 \
    FETCH_ARG(0, Float);                                \
    Pre;                                                \
    return new Float(Call(arg0->value_get()));          \
  }

  /// Define a primitive for float numbers.
  /// \param Call Name primitive's name
#define PRIMITIVE_0_FLOAT(Name, Call)                   \
  PRIMITIVE_0_FLOAT_(Name, Call, )

#define PRIMITIVE_0_FLOAT_CHECK_POSITIVE(Name, Call)            \
  PRIMITIVE_0_FLOAT_(Name, Call,                                \
     if (VALUE(args[0], Float) < 0)                             \
       throw PrimitiveError(#Name,                              \
			    "argument has to be positive"))

#define PRIMITIVE_0_FLOAT_CHECK_RANGE(Name, Call, Min, Max)		\
  PRIMITIVE_0_FLOAT_(Name, Call,					\
     if (VALUE(args[0], Float) < Min || Max < VALUE(args[0], Float))	\
      throw PrimitiveError(#Name, "invalid range"))

#define PRIMITIVE_2_FLOAT(Name, Call)                   \
  PRIMITIVE_2_V(float, Name, Call, Float, Float, Float)

#define PRIMITIVE_OP_FLOAT(Name, Op)                    \
  PRIMITIVE_OP_V(float, Name, Op, Float, Float, Float)

  // Binary arithmetics operators.
  PRIMITIVE_OP_FLOAT(PLUS, +)
  PRIMITIVE_2_FLOAT(SLASH, float_div)
  PRIMITIVE_OP_FLOAT(STAR, *)
  PRIMITIVE_2_FLOAT(PERCENT, float_mod)
  PRIMITIVE_2_FLOAT(STAR_STAR, powf)

  PRIMITIVE_2_FLOAT(LT_LT, float_lshift) // <<
  PRIMITIVE_2_FLOAT(GT_GT, float_rshift) // >>
  PRIMITIVE_2_FLOAT(CARET,    float_xor) // ^

  PRIMITIVE_OP_FLOAT(AMPERSAND_AMPERSAND, &&)
  PRIMITIVE_OP_FLOAT(PIPE_PIPE, ||)

  PRIMITIVE_OP_FLOAT(EQ_EQ, ==)
  PRIMITIVE_2_FLOAT(TILDA_EQ, float_req)    //REQ ~=
  PRIMITIVE_2_FLOAT(EQ_TILDA_EQ, float_deq) //DEQ =~=
  PRIMITIVE_2_FLOAT(PERCENT_EQ, float_peq)  //PEQ %=

  PRIMITIVE_OP_FLOAT(LT, <)

  PRIMITIVE_0_FLOAT(sin, sin)
  PRIMITIVE_0_FLOAT_CHECK_RANGE(asin, asin, -1, 1)
  PRIMITIVE_0_FLOAT(cos, cos)
  PRIMITIVE_0_FLOAT_CHECK_RANGE(acos, acos, -1, 1)
  PRIMITIVE_0_FLOAT(tan, tan)
  PRIMITIVE_0_FLOAT(atan, atan)
  PRIMITIVE_0_FLOAT(sgn, float_sgn)
  PRIMITIVE_0_FLOAT(abs, fabs)
  PRIMITIVE_0_FLOAT(exp, exp)
  PRIMITIVE_0_FLOAT_CHECK_POSITIVE(log, log)
  PRIMITIVE_0_FLOAT(round, round)
  PRIMITIVE_0_FLOAT(random, float_random)
  PRIMITIVE_0_FLOAT(trunc, trunc)
  PRIMITIVE_0_FLOAT_CHECK_POSITIVE(sqrt, sqrt)

#undef PRIMITIVE_2_FLOAT
#undef PRIMITIVE_0_FLOAT_CHECK_RANGE
#undef PRIMITIVE_0_FLOAT_CHECK_POSITIVE
#undef PRIMITIVE_0_FLOAT
#undef PRIMITIVE_0_FLOAT_
#undef PRIMITIVE_OP_FLOAT

  /// Initialize the Float class.
  void
  float_class_initialize ()
  {
    /// \a Call gives the name of the C++ function, and \a Name that in Urbi.
#define DECLARE(Name)                      \
    DECLARE_PRIMITIVE(float, Name, Name)

    DECLARE(PLUS);
    DECLARE(SLASH);
    DECLARE(STAR);
    DECLARE(MINUS);
    DECLARE(STAR_STAR);
    DECLARE(PERCENT);

    DECLARE(LT_LT);
    DECLARE(GT_GT);
    DECLARE(CARET);

    DECLARE(AMPERSAND_AMPERSAND);
    DECLARE(PIPE_PIPE);

    DECLARE(EQ_EQ);
    DECLARE(TILDA_EQ);
    DECLARE(EQ_TILDA_EQ);
    DECLARE(PERCENT_EQ);

    DECLARE(LT);

    DECLARE(clone);
    DECLARE(set);

    DECLARE(sin);
    DECLARE(asin);
    DECLARE(cos);
    DECLARE(acos);
    DECLARE(tan);
    DECLARE(atan);
    DECLARE(sgn);
    DECLARE(abs);
    DECLARE(exp);
    DECLARE(log);
    DECLARE(round);
    DECLARE(random);
    DECLARE(trunc);
    DECLARE(sqrt);
#undef DECLARE

  }

}; // namespace object
<|endoftext|>


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

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.txt for details.

    This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE,  See the above copyright notices for more information.

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

#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#ifdef __BORLANDC__
#define ITK_LEAN_AND_MEAN
#endif

#include "otbImage.h"
#include "otbVectorImage.h"
#include "otbImageFileReader.h"
#include "otbStreamingImageFileWriter.h"
#include "otbVectorRescaleIntensityImageFilter.h"
#include "otbCommandLineArgumentParser.h"
#include "itkCastImageFilter.h"
#include "otbStandardFilterWatcher.h"
#include "otbStandardWriterWatcher.h"

template<typename OutputPixelType>
int generic_main_convert(otb::CommandLineArgumentParseResult* parseResult)
{

  typedef otb::VectorImage<double, 2> InputImageType;
  typedef otb::VectorImage<OutputPixelType, 2> OutputImageType;

  typedef otb::StreamingImageFileWriter<OutputImageType> WriterType;

  typename WriterType::Pointer writer=WriterType::New();

  writer->SetFileName(parseResult->GetOutputImage().c_str());

  if (parseResult->IsOptionPresent("--UseRescale"))
  {
    typedef otb::ImageFileReader<InputImageType> ReaderType;
    typename ReaderType::Pointer reader=ReaderType::New();
    reader->SetFileName(parseResult->GetInputImage().c_str());
    reader->UpdateOutputInformation();

    typedef otb::VectorRescaleIntensityImageFilter<InputImageType, OutputImageType> RescalerType;
    typename OutputImageType::PixelType minimum;
    typename OutputImageType::PixelType maximum;
    minimum.SetSize(reader->GetOutput()->GetNumberOfComponentsPerPixel());
    maximum.SetSize(reader->GetOutput()->GetNumberOfComponentsPerPixel());
    minimum.Fill(itk::NumericTraits<OutputPixelType>::min());
    maximum.Fill(itk::NumericTraits<OutputPixelType>::max());

    typename RescalerType::Pointer rescaler=RescalerType::New();

    rescaler->SetOutputMinimum(minimum);
    rescaler->SetOutputMaximum(maximum);

    rescaler->SetInput(reader->GetOutput());
    writer->SetInput(rescaler->GetOutput());

    otb::StandardWriterWatcher watcher(writer,rescaler,"Conversion");

    writer->Update();
  }
  else
  {
    typedef otb::ImageFileReader<OutputImageType> ReaderType;
    typename ReaderType::Pointer reader=ReaderType::New();
    reader->SetFileName(parseResult->GetInputImage().c_str());
    otb::StandardFilterWatcher watcher(writer,"Conversion");
    writer->SetInput(reader->GetOutput());
    writer->Update();
  }

  return EXIT_SUCCESS;
}

int main(int argc, char * argv[])
{
  try
  {
    // Parse command line parameters
    typedef otb::CommandLineArgumentParser ParserType;
    ParserType::Pointer parser = ParserType::New();

    parser->SetProgramDescription("Convert an image to a different format, eventually rescaling the data and/or changing the pixel type");
    parser->AddInputImage();
    parser->AddOutputImage();
    parser->AddOption("--OutputPixelType","OutputPixelType: unsigned char (1), short int (2), int (3), float (4), double (5), unsigned short int (12), unsigned int (13); default 1","-t", 1, false);
    parser->AddOption("--UseRescale", "Rescale value between output type min and max","-r", 0, false);

    typedef otb::CommandLineArgumentParseResult ParserResultType;
    ParserResultType::Pointer  parseResult = ParserResultType::New();

    try
    {
      parser->ParseCommandLine(argc,argv,parseResult);
    }
    catch ( itk::ExceptionObject & err )
    {
      std::string descriptionException = err.GetDescription();
      if (descriptionException.find("ParseCommandLine(): Help Parser") != std::string::npos)
      {
        std::cout << "WARNING : output file pixels are converted in 'unsigned char'" << std::endl;
        return EXIT_SUCCESS;
      }
      if (descriptionException.find("ParseCommandLine(): Version Parser") != std::string::npos)
      {
        return EXIT_SUCCESS;
      }
      return EXIT_FAILURE;
    }

    unsigned int type=1;
    if (parseResult->IsOptionPresent("--OutputPixelType"))
    {
      type=parseResult->GetParameterUInt("--OutputPixelType");
    }

    switch (type)
    {
    case 1:
      generic_main_convert<unsigned char>(parseResult);
      break;
    case 2:
      generic_main_convert<short int>(parseResult);
      break;
    case 3:
      generic_main_convert<int>(parseResult);
      break;
    case 4:
      generic_main_convert<float>(parseResult);
      break;
    case 5:
      generic_main_convert<double>(parseResult);
      break;
    case 12:
      generic_main_convert<unsigned short int>(parseResult);
      break;
    case 13:
      generic_main_convert<unsigned int>(parseResult);
      break;
    default:
      generic_main_convert<unsigned char>(parseResult);
      break;
    }

  }
  catch ( itk::ExceptionObject & err )
  {
    std::cout << "Exception itk::ExceptionObject raised !" << std::endl;
    std::cout << err << std::endl;
    return EXIT_FAILURE;
  }
  catch ( std::bad_alloc & err )
  {
    std::cout << "Exception bad_alloc : "<<(char*)err.what()<< std::endl;
    return EXIT_FAILURE;
  }
  catch ( ... )
  {
    std::cout << "Unknow exception raised !" << std::endl;
    return EXIT_FAILURE;
  }
  return EXIT_SUCCESS;
}
<commit_msg>DOC: fix copyright and doc<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

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

#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#ifdef __BORLANDC__
#define ITK_LEAN_AND_MEAN
#endif

#include "otbImage.h"
#include "otbVectorImage.h"
#include "otbImageFileReader.h"
#include "otbStreamingImageFileWriter.h"
#include "otbVectorRescaleIntensityImageFilter.h"
#include "otbCommandLineArgumentParser.h"
#include "itkCastImageFilter.h"
#include "otbStandardFilterWatcher.h"
#include "otbStandardWriterWatcher.h"

template<typename OutputPixelType>
int generic_main_convert(otb::CommandLineArgumentParseResult* parseResult)
{

  typedef otb::VectorImage<double, 2> InputImageType;
  typedef otb::VectorImage<OutputPixelType, 2> OutputImageType;

  typedef otb::StreamingImageFileWriter<OutputImageType> WriterType;

  typename WriterType::Pointer writer=WriterType::New();

  writer->SetFileName(parseResult->GetOutputImage().c_str());

  if (parseResult->IsOptionPresent("--UseRescale"))
  {
    typedef otb::ImageFileReader<InputImageType> ReaderType;
    typename ReaderType::Pointer reader=ReaderType::New();
    reader->SetFileName(parseResult->GetInputImage().c_str());
    reader->UpdateOutputInformation();

    typedef otb::VectorRescaleIntensityImageFilter<InputImageType, OutputImageType> RescalerType;
    typename OutputImageType::PixelType minimum;
    typename OutputImageType::PixelType maximum;
    minimum.SetSize(reader->GetOutput()->GetNumberOfComponentsPerPixel());
    maximum.SetSize(reader->GetOutput()->GetNumberOfComponentsPerPixel());
    minimum.Fill(itk::NumericTraits<OutputPixelType>::min());
    maximum.Fill(itk::NumericTraits<OutputPixelType>::max());

    typename RescalerType::Pointer rescaler=RescalerType::New();

    rescaler->SetOutputMinimum(minimum);
    rescaler->SetOutputMaximum(maximum);

    rescaler->SetInput(reader->GetOutput());
    writer->SetInput(rescaler->GetOutput());

    otb::StandardWriterWatcher watcher(writer,rescaler,"Conversion");

    writer->Update();
  }
  else
  {
    typedef otb::ImageFileReader<OutputImageType> ReaderType;
    typename ReaderType::Pointer reader=ReaderType::New();
    reader->SetFileName(parseResult->GetInputImage().c_str());
    otb::StandardFilterWatcher watcher(writer,"Conversion");
    writer->SetInput(reader->GetOutput());
    writer->Update();
  }

  return EXIT_SUCCESS;
}

int main(int argc, char * argv[])
{
  try
  {
    // Parse command line parameters
    typedef otb::CommandLineArgumentParser ParserType;
    ParserType::Pointer parser = ParserType::New();

    parser->SetProgramDescription("Convert an image to a different format, eventually rescaling the data and/or changing the pixel type");
    parser->AddInputImage();
    parser->AddOutputImage();
    parser->AddOption("--OutputPixelType","OutputPixelType: unsigned char (1), short int (2), int (3), float (4), double (5), unsigned short int (12), unsigned int (13); default 1","-t", 1, false);
    parser->AddOption("--UseRescale", "Rescale value between output type min and max","-r", 0, false);

    typedef otb::CommandLineArgumentParseResult ParserResultType;
    ParserResultType::Pointer  parseResult = ParserResultType::New();

    try
    {
      parser->ParseCommandLine(argc,argv,parseResult);
    }
    catch ( itk::ExceptionObject & err )
    {
      std::string descriptionException = err.GetDescription();
      if (descriptionException.find("ParseCommandLine(): Help Parser") != std::string::npos)
      {
        std::cout << "WARNING : output file pixels are converted in 'unsigned char'" << std::endl;
        return EXIT_SUCCESS;
      }
      if (descriptionException.find("ParseCommandLine(): Version Parser") != std::string::npos)
      {
        return EXIT_SUCCESS;
      }
      return EXIT_FAILURE;
    }

    unsigned int type=1;
    if (parseResult->IsOptionPresent("--OutputPixelType"))
    {
      type=parseResult->GetParameterUInt("--OutputPixelType");
    }

    switch (type)
    {
    case 1:
      generic_main_convert<unsigned char>(parseResult);
      break;
    case 2:
      generic_main_convert<short int>(parseResult);
      break;
    case 3:
      generic_main_convert<int>(parseResult);
      break;
    case 4:
      generic_main_convert<float>(parseResult);
      break;
    case 5:
      generic_main_convert<double>(parseResult);
      break;
    case 12:
      generic_main_convert<unsigned short int>(parseResult);
      break;
    case 13:
      generic_main_convert<unsigned int>(parseResult);
      break;
    default:
      generic_main_convert<unsigned char>(parseResult);
      break;
    }

  }
  catch ( itk::ExceptionObject & err )
  {
    std::cout << "Exception itk::ExceptionObject raised !" << std::endl;
    std::cout << err << std::endl;
    return EXIT_FAILURE;
  }
  catch ( std::bad_alloc & err )
  {
    std::cout << "Exception bad_alloc : "<<(char*)err.what()<< std::endl;
    return EXIT_FAILURE;
  }
  catch ( ... )
  {
    std::cout << "Unknow exception raised !" << std::endl;
    return EXIT_FAILURE;
  }
  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/**
 * Simple Image Processing Library
 * Copyright Erik Smistad 2012
 * See LICENSE file for information on use
 */

#ifndef SIPL_TYPES
#define SIPL_TYPES

#include <math.h>

namespace SIPL {
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef struct color_float { float red, blue, green;} color_float ;
typedef struct color_uchar { unsigned char red, blue, green;} color_uchar ;
enum slice_plane {X,Y,Z};

class int2;
// Vector classes
class float2 {
    public:
        float x,y;
        float2() {
            this->x = 0.0f;
            this->y = 0.0f;
        };
        float2(float x, float y) {
            this->x = x;
            this->y = y;
        };
        float length() const {
            return sqrt((float)(x*x+y*y));
        };
        float2 normalize() const {
            float l = this->length();
            return float2(x/l,y/l);
        };
        float distance(float2 &other) const ;
        float dot(float2 &other) const ;
        float distance(int2 &other) const ;
        float dot(int2 &other) const ;
        template <class T>
        float2 operator+(T v) const {
            float2 n;
            n.x = this->x + v;
            n.y = this->y + v;
            return n;
        };
        template <class T>
        float2 operator-(T v) const {
            float2 n;
            n.x = this->x - v;
            n.y = this->y - v;
            return n;
        };
        template <class T>
        float2 operator*(T v) const {
            float2 n;
            n.x = this->x * v;
            n.y = this->y * v;
            return n;
        };
        template <class T>
        float2 operator/(T v) const {
            float2 n;
            n.x = this->x / v;
            n.y = this->y / v;
            return n;
        };

 };

class int3;

class float3 {
    public:
        float x,y,z;
        float3() {
            this->x = 0.0f;
            this->y = 0.0f;
            this->z = 0.0f;
        };
        float3(float x, float y, float z) {
            this->x = x;
            this->y = y;
            this->z = z;
        };
        float length() const {
            return sqrt((float)(x*x+y*y+z*z));
        };
        float3 normalize() {
            float l = this->length();
            return float3(x / l, y / l, z / l);
        };
        float distance(float3 &other) const ;
        float distance(int3 &other) const ;
        float dot(float3 &other) const ;
        float dot(int3 &other) const ;
        template <class T>
        float3 operator+(T v) const {
            float3 n;
            n.x = this->x + v;
            n.y = this->y + v;
            n.z = this->z + v;
            return n;
        };
        template <class T>
        float3 operator-(T v) const {
            float3 n;
            n.x = this->x - v;
            n.y = this->y - v;
            n.z = this->z - v;
            return n;
        };
        template <class T>
        float3 operator*(T v) const {
            float3 n;
            n.x = this->x * v;
            n.y = this->y * v;
            n.z = this->z * v;
            return n;
        };
        template <class T>
        float3 operator/(T v) const {
            float3 n;
            n.x = this->x / v;
            n.y = this->y / v;
            n.z = this->z / v;
            return n;
        };
};

// These are not for images/volumes
class int2 {
    public:
        int x,y;
        int2() {
            this->x = 0;
            this->y = 0;
        };
        int2(float x, float y) {
            this->x = x;
            this->y = y;
        };
        float length() const {
            return sqrt((float)(x*x+y*y));
        };
        float2 normalize() const {
            float l = this->length();
            return float2(x / l, y / l);
        };
        float distance(float2 &other) const ;
        float dot(float2 &other) const ;
        float distance(int2 &other) const ;
        float dot(int2 &other) const ;
        template <class T>
        int2 operator+(T v) const {
            int2 n;
            n.x = this->x + v;
            n.y = this->y + v;
            return n;
        };
        template <class T>
        int2 operator-(T v) const {
            int2 n;
            n.x = this->x - v;
            n.y = this->y - v;
            return n;
        };
        template <class T>
        int2 operator*(T v) const {
            int2 n;
            n.x = this->x * v;
            n.y = this->y * v;
            return n;
        };
        template <class T>
        int2 operator/(T v) const {
            int2 n;
            n.x = this->x / v;
            n.y = this->y / v;
            return n;
        };
};

class int3 {
    public:
        int x,y,z;
        int3() {
            this->x = 0;
            this->y = 0;
            this->z = 0;
        };
        int3(int x, int y, int z) {
            this->x = x;
            this->y = y;
            this->z = z;
        };
        float length() const {
            return sqrt((float)(x*x+y*y+z*z));
        };
        float3 normalize() const {
            float l = this->length();
            return float3(x / l, y / l, z / l);
        };
        float distance(float3 &other) const ;
        float distance(int3 &other) const ;
        float dot(float3 &other) const ;
        float dot(int3 &other) const ;
        template <class T>
        int3 operator+(T v) const {
            int3 n;
            n.x = this->x + v;
            n.y = this->y + v;
            n.z = this->z + v;
            return n;
        };
        template <class T>
        int3 operator-(T v) const {
            int3 n;
            n.x = this->x - v;
            n.y = this->y - v;
            n.z = this->z - v;
            return n;
        };
        template <class T>
        int3 operator*(T v) const {
            int3 n;
            n.x = this->x * v;
            n.y = this->y * v;
            n.z = this->z * v;
            return n;
        };
        template <class T>
        int3 operator/(T v) const {
            int3 n;
            n.x = this->x / v;
            n.y = this->y / v;
            n.z = this->z / v;
            return n;
        };
};

// float2
template <> inline
float2 float2::operator+(float2 other) const {
    float2 v;
    v.x = this->x + other.x;
    v.y = this->y + other.y;
    return v;
}
template <> inline
float2 float2::operator+(int2 other) const {
    float2 v;
    v.x = this->x + other.x;
    v.y = this->y + other.y;
    return v;
}
template <> inline
float2 float2::operator-(float2 other) const {
    float2 v;
    v.x = this->x - other.x;
    v.y = this->y - other.y;
    return v;
}
template <> inline
float2 float2::operator-(int2 other) const {
    float2 v;
    v.x = this->x - other.x;
    v.y = this->y - other.y;
    return v;
}
template <> inline
float2 float2::operator*(float2 other) const {
    float2 v;
    v.x = this->x * other.x;
    v.y = this->y * other.y;
    return v;
}
template <> inline
float2 float2::operator*(int2 other) const {
    float2 v;
    v.x = this->x * other.x;
    v.y = this->y * other.y;
    return v;
}

template <class T>
float2 operator+(T scalar, float2 other) {
    return other.operator+(scalar);
}
template <class T>
float2 operator-(T scalar, float2 other) {
    return other.operator-(scalar);
}
template <class T>
float2 operator*(T scalar, float2 other) {
    return other.operator*(scalar);
}

// float3
template <> inline
float3 float3::operator+(float3 other) const {
    float3 v;
    v.x = this->x + other.x;
    v.y = this->y + other.y;
    v.z = this->z + other.z;
    return v;
}
template <> inline
float3 float3::operator+(int3 other) const {
    float3 v;
    v.x = this->x + other.x;
    v.y = this->y + other.y;
    v.z = this->z + other.z;
    return v;
}
template <> inline
float3 float3::operator-(float3 other) const {
    float3 v;
    v.x = this->x - other.x;
    v.y = this->y - other.y;
    v.z = this->z - other.z;
    return v;
}
template <> inline
float3 float3::operator-(int3 other) const {
    float3 v;
    v.x = this->x - other.x;
    v.y = this->y - other.y;
    v.z = this->z - other.z;
    return v;
}
template <> inline
float3 float3::operator*(float3 other) const {
    float3 v;
    v.x = this->x * other.x;
    v.y = this->y * other.y;
    v.z = this->z * other.z;
    return v;
}
template <> inline
float3 float3::operator*(int3 other) const {
    float3 v;
    v.x = this->x * other.x;
    v.y = this->y * other.y;
    v.z = this->z * other.z;
    return v;
}

template <class T>
float3 operator+(T scalar, float3 other) {
    return other.operator+(scalar);
}
template <class T>
float3 operator-(T scalar, float3 other) {
    return other.operator-(scalar);
}
template <class T>
float3 operator*(T scalar, float3 other) {
    return other.operator*(scalar);
}

// int2
template <> inline
int2 int2::operator+(float2 other) const {
    int2 v;
    v.x = this->x + other.x;
    v.y = this->y + other.y;
    return v;
}
template <> inline
int2 int2::operator+(int2 other) const {
    int2 v;
    v.x = this->x + other.x;
    v.y = this->y + other.y;
    return v;
}
template <> inline
int2 int2::operator-(float2 other) const {
    int2 v;
    v.x = this->x - other.x;
    v.y = this->y - other.y;
    return v;
}
template <> inline
int2 int2::operator-(int2 other) const {
    int2 v;
    v.x = this->x - other.x;
    v.y = this->y - other.y;
    return v;
}
template <> inline
int2 int2::operator*(float2 other) const {
    int2 v;
    v.x = this->x * other.x;
    v.y = this->y * other.y;
    return v;
}
template <> inline
int2 int2::operator*(int2 other) const {
    int2 v;
    v.x = this->x * other.x;
    v.y = this->y * other.y;
    return v;
}

template <class T>
int2 operator+(T scalar, int2 other) {
    return other.operator+(scalar);
}
template <class T>
int2 operator-(T scalar, int2 other) {
    return other.operator-(scalar);
}
template <class T>
int2 operator*(T scalar, int2 other) {
    return other.operator*(scalar);
}

// float3
template <> inline
int3 int3::operator+(float3 other) const {
    int3 v;
    v.x = this->x + other.x;
    v.y = this->y + other.y;
    v.z = this->z + other.z;
    return v;
}
template <> inline
int3 int3::operator+(int3 other) const {
    int3 v;
    v.x = this->x + other.x;
    v.y = this->y + other.y;
    v.z = this->z + other.z;
    return v;
}
template <> inline
int3 int3::operator-(float3 other) const {
    int3 v;
    v.x = this->x - other.x;
    v.y = this->y - other.y;
    v.z = this->z - other.z;
    return v;
}
template <> inline
int3 int3::operator-(int3 other) const {
    int3 v;
    v.x = this->x - other.x;
    v.y = this->y - other.y;
    v.z = this->z - other.z;
    return v;
}
template <> inline
int3 int3::operator*(float3 other) const {
    int3 v;
    v.x = this->x * other.x;
    v.y = this->y * other.y;
    v.z = this->z * other.z;
    return v;
}
template <> inline
int3 int3::operator*(int3 other) const {
    int3 v;
    v.x = this->x * other.x;
    v.y = this->y * other.y;
    v.z = this->z * other.z;
    return v;
}

template <class T>
int3 operator+(T scalar, int3 other) {
    return other.operator+(scalar);
}
template <class T>
int3 operator-(T scalar, int3 other) {
    return other.operator-(scalar);
}
template <class T>
int3 operator*(T scalar, int3 other) {
    return other.operator*(scalar);
}

}; // end SIPL namespace
#endif
<commit_msg>added region class<commit_after>/**
 * Simple Image Processing Library
 * Copyright Erik Smistad 2012
 * See LICENSE file for information on use
 */

#ifndef SIPL_TYPES
#define SIPL_TYPES

#include <math.h>

namespace SIPL {
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef struct color_float { float red, blue, green;} color_float ;
typedef struct color_uchar { unsigned char red, blue, green;} color_uchar ;
enum slice_plane {X,Y,Z};

class int2;
// Vector classes
class float2 {
    public:
        float x,y;
        float2() {
            this->x = 0.0f;
            this->y = 0.0f;
        };
        float2(float x, float y) {
            this->x = x;
            this->y = y;
        };
        float length() const {
            return sqrt((float)(x*x+y*y));
        };
        float2 normalize() const {
            float l = this->length();
            return float2(x/l,y/l);
        };
        float distance(float2 &other) const ;
        float dot(float2 &other) const ;
        float distance(int2 &other) const ;
        float dot(int2 &other) const ;
        template <class T>
        float2 operator+(T v) const {
            float2 n;
            n.x = this->x + v;
            n.y = this->y + v;
            return n;
        };
        template <class T>
        float2 operator-(T v) const {
            float2 n;
            n.x = this->x - v;
            n.y = this->y - v;
            return n;
        };
        template <class T>
        float2 operator*(T v) const {
            float2 n;
            n.x = this->x * v;
            n.y = this->y * v;
            return n;
        };
        template <class T>
        float2 operator/(T v) const {
            float2 n;
            n.x = this->x / v;
            n.y = this->y / v;
            return n;
        };

 };

class int3;

class float3 {
    public:
        float x,y,z;
        float3() {
            this->x = 0.0f;
            this->y = 0.0f;
            this->z = 0.0f;
        };
        float3(float x, float y, float z) {
            this->x = x;
            this->y = y;
            this->z = z;
        };
        float length() const {
            return sqrt((float)(x*x+y*y+z*z));
        };
        float3 normalize() {
            float l = this->length();
            return float3(x / l, y / l, z / l);
        };
        float distance(float3 &other) const ;
        float distance(int3 &other) const ;
        float dot(float3 &other) const ;
        float dot(int3 &other) const ;
        template <class T>
        float3 operator+(T v) const {
            float3 n;
            n.x = this->x + v;
            n.y = this->y + v;
            n.z = this->z + v;
            return n;
        };
        template <class T>
        float3 operator-(T v) const {
            float3 n;
            n.x = this->x - v;
            n.y = this->y - v;
            n.z = this->z - v;
            return n;
        };
        template <class T>
        float3 operator*(T v) const {
            float3 n;
            n.x = this->x * v;
            n.y = this->y * v;
            n.z = this->z * v;
            return n;
        };
        template <class T>
        float3 operator/(T v) const {
            float3 n;
            n.x = this->x / v;
            n.y = this->y / v;
            n.z = this->z / v;
            return n;
        };
};

// These are not for images/volumes
class int2 {
    public:
        int x,y;
        int2() {
            this->x = 0;
            this->y = 0;
        };
        int2(float x, float y) {
            this->x = x;
            this->y = y;
        };
        float length() const {
            return sqrt((float)(x*x+y*y));
        };
        float2 normalize() const {
            float l = this->length();
            return float2(x / l, y / l);
        };
        float distance(float2 &other) const ;
        float dot(float2 &other) const ;
        float distance(int2 &other) const ;
        float dot(int2 &other) const ;
        template <class T>
        int2 operator+(T v) const {
            int2 n;
            n.x = this->x + v;
            n.y = this->y + v;
            return n;
        };
        template <class T>
        int2 operator-(T v) const {
            int2 n;
            n.x = this->x - v;
            n.y = this->y - v;
            return n;
        };
        template <class T>
        int2 operator*(T v) const {
            int2 n;
            n.x = this->x * v;
            n.y = this->y * v;
            return n;
        };
        template <class T>
        int2 operator/(T v) const {
            int2 n;
            n.x = this->x / v;
            n.y = this->y / v;
            return n;
        };
};

class int3 {
    public:
        int x,y,z;
        int3() {
            this->x = 0;
            this->y = 0;
            this->z = 0;
        };
        int3(int x, int y, int z) {
            this->x = x;
            this->y = y;
            this->z = z;
        };
        float length() const {
            return sqrt((float)(x*x+y*y+z*z));
        };
        float3 normalize() const {
            float l = this->length();
            return float3(x / l, y / l, z / l);
        };
        float distance(float3 &other) const ;
        float distance(int3 &other) const ;
        float dot(float3 &other) const ;
        float dot(int3 &other) const ;
        template <class T>
        int3 operator+(T v) const {
            int3 n;
            n.x = this->x + v;
            n.y = this->y + v;
            n.z = this->z + v;
            return n;
        };
        template <class T>
        int3 operator-(T v) const {
            int3 n;
            n.x = this->x - v;
            n.y = this->y - v;
            n.z = this->z - v;
            return n;
        };
        template <class T>
        int3 operator*(T v) const {
            int3 n;
            n.x = this->x * v;
            n.y = this->y * v;
            n.z = this->z * v;
            return n;
        };
        template <class T>
        int3 operator/(T v) const {
            int3 n;
            n.x = this->x / v;
            n.y = this->y / v;
            n.z = this->z / v;
            return n;
        };
};

class Region {
    public:
        int3 offset;
        int3 size;
        Region(int x_size, int y_size);
        Region(int x_offset, int y_offset, int x_size, int y_size);
        Region(int x_size, int y_size, int z_size);
        Region(int x_offset, int y_offset, int z_offset, int x_size, int y_size, int z_size);
};

// float2
template <> inline
float2 float2::operator+(float2 other) const {
    float2 v;
    v.x = this->x + other.x;
    v.y = this->y + other.y;
    return v;
}
template <> inline
float2 float2::operator+(int2 other) const {
    float2 v;
    v.x = this->x + other.x;
    v.y = this->y + other.y;
    return v;
}
template <> inline
float2 float2::operator-(float2 other) const {
    float2 v;
    v.x = this->x - other.x;
    v.y = this->y - other.y;
    return v;
}
template <> inline
float2 float2::operator-(int2 other) const {
    float2 v;
    v.x = this->x - other.x;
    v.y = this->y - other.y;
    return v;
}
template <> inline
float2 float2::operator*(float2 other) const {
    float2 v;
    v.x = this->x * other.x;
    v.y = this->y * other.y;
    return v;
}
template <> inline
float2 float2::operator*(int2 other) const {
    float2 v;
    v.x = this->x * other.x;
    v.y = this->y * other.y;
    return v;
}

template <class T>
float2 operator+(T scalar, float2 other) {
    return other.operator+(scalar);
}
template <class T>
float2 operator-(T scalar, float2 other) {
    return other.operator-(scalar);
}
template <class T>
float2 operator*(T scalar, float2 other) {
    return other.operator*(scalar);
}

// float3
template <> inline
float3 float3::operator+(float3 other) const {
    float3 v;
    v.x = this->x + other.x;
    v.y = this->y + other.y;
    v.z = this->z + other.z;
    return v;
}
template <> inline
float3 float3::operator+(int3 other) const {
    float3 v;
    v.x = this->x + other.x;
    v.y = this->y + other.y;
    v.z = this->z + other.z;
    return v;
}
template <> inline
float3 float3::operator-(float3 other) const {
    float3 v;
    v.x = this->x - other.x;
    v.y = this->y - other.y;
    v.z = this->z - other.z;
    return v;
}
template <> inline
float3 float3::operator-(int3 other) const {
    float3 v;
    v.x = this->x - other.x;
    v.y = this->y - other.y;
    v.z = this->z - other.z;
    return v;
}
template <> inline
float3 float3::operator*(float3 other) const {
    float3 v;
    v.x = this->x * other.x;
    v.y = this->y * other.y;
    v.z = this->z * other.z;
    return v;
}
template <> inline
float3 float3::operator*(int3 other) const {
    float3 v;
    v.x = this->x * other.x;
    v.y = this->y * other.y;
    v.z = this->z * other.z;
    return v;
}

template <class T>
float3 operator+(T scalar, float3 other) {
    return other.operator+(scalar);
}
template <class T>
float3 operator-(T scalar, float3 other) {
    return other.operator-(scalar);
}
template <class T>
float3 operator*(T scalar, float3 other) {
    return other.operator*(scalar);
}

// int2
template <> inline
int2 int2::operator+(float2 other) const {
    int2 v;
    v.x = this->x + other.x;
    v.y = this->y + other.y;
    return v;
}
template <> inline
int2 int2::operator+(int2 other) const {
    int2 v;
    v.x = this->x + other.x;
    v.y = this->y + other.y;
    return v;
}
template <> inline
int2 int2::operator-(float2 other) const {
    int2 v;
    v.x = this->x - other.x;
    v.y = this->y - other.y;
    return v;
}
template <> inline
int2 int2::operator-(int2 other) const {
    int2 v;
    v.x = this->x - other.x;
    v.y = this->y - other.y;
    return v;
}
template <> inline
int2 int2::operator*(float2 other) const {
    int2 v;
    v.x = this->x * other.x;
    v.y = this->y * other.y;
    return v;
}
template <> inline
int2 int2::operator*(int2 other) const {
    int2 v;
    v.x = this->x * other.x;
    v.y = this->y * other.y;
    return v;
}

template <class T>
int2 operator+(T scalar, int2 other) {
    return other.operator+(scalar);
}
template <class T>
int2 operator-(T scalar, int2 other) {
    return other.operator-(scalar);
}
template <class T>
int2 operator*(T scalar, int2 other) {
    return other.operator*(scalar);
}

// float3
template <> inline
int3 int3::operator+(float3 other) const {
    int3 v;
    v.x = this->x + other.x;
    v.y = this->y + other.y;
    v.z = this->z + other.z;
    return v;
}
template <> inline
int3 int3::operator+(int3 other) const {
    int3 v;
    v.x = this->x + other.x;
    v.y = this->y + other.y;
    v.z = this->z + other.z;
    return v;
}
template <> inline
int3 int3::operator-(float3 other) const {
    int3 v;
    v.x = this->x - other.x;
    v.y = this->y - other.y;
    v.z = this->z - other.z;
    return v;
}
template <> inline
int3 int3::operator-(int3 other) const {
    int3 v;
    v.x = this->x - other.x;
    v.y = this->y - other.y;
    v.z = this->z - other.z;
    return v;
}
template <> inline
int3 int3::operator*(float3 other) const {
    int3 v;
    v.x = this->x * other.x;
    v.y = this->y * other.y;
    v.z = this->z * other.z;
    return v;
}
template <> inline
int3 int3::operator*(int3 other) const {
    int3 v;
    v.x = this->x * other.x;
    v.y = this->y * other.y;
    v.z = this->z * other.z;
    return v;
}

template <class T>
int3 operator+(T scalar, int3 other) {
    return other.operator+(scalar);
}
template <class T>
int3 operator-(T scalar, int3 other) {
    return other.operator-(scalar);
}
template <class T>
int3 operator*(T scalar, int3 other) {
    return other.operator*(scalar);
}

}; // end SIPL namespace
#endif
<|endoftext|>