<commit_before>#include "ofQtUtils.h"

static bool bQuicktimeInitialized = false;

//----------------------------------------
void initializeQuicktime(){
	if (bQuicktimeInitialized == false){

		//----------------------------------
		// do we have quicktime installed at all?
		// http://www.apple.com/quicktime/download/win.html
		// can gestalt help with versions, or is that only after init?

		OSErr myErr 	= noErr;
		#ifdef TARGET_WIN32
			myErr = InitializeQTML(0);
			if (myErr != noErr){
				printf("----------------------------------------------------- \n");
				printf("sorry, there is a problem with quicktime starting up \nplease check!");
                OF_EXIT_APP(0);
			}
		#endif
		myErr = EnterMovies ();
		if (myErr != noErr){
			printf("----------------------------------------------------- \n");
			printf("sorry, there is a problem with quicktime starting up  \nplease check!");
			OF_EXIT_APP(0);
		}

		bQuicktimeInitialized = true;
	}
}

//----------------------------------------
void closeQuicktime(){
	if (bQuicktimeInitialized == true){
		ExitMovies();
		#ifdef TARGET_WIN32
			TerminateQTML();
		#endif
		bQuicktimeInitialized = false;
	}
}

//----------------------------------------
void convertPixels(unsigned char * gWorldPixels, unsigned char * rgbPixels, int w, int h){

	// ok for macs?
	// ok for intel macs?

	int * rgbaPtr 			= (int *) gWorldPixels;
	pix24 * rgbPtr 			= (pix24 *) rgbPixels;
	int totalPixelCount 	= w * h;
	unsigned char * rgbaStart;

	//	putting in the boolean, so we can work on
	//	0,0 in top right...
	//	bool bFlipVertically 	= true;

	bool bFlipVertically 	= false;

	// -------------------------------------------
	// we flip vertically because the 0,0 position in OF
	// is the bottom left (not top left, like processing)
	// since the 0,0 of a picture is top left
	// if we upload and drawf the data as is
	// it will be upside-down....
	// -------------------------------------------

	if (!bFlipVertically){
		//----- argb->rgb
		for (int i = 0; i < h; i++){
			pix24 * rgbPtr 			= (pix24 *) rgbPixels + ((i) * w);
			for (int j = 0; j < w; j++){
				rgbaStart = (unsigned char *)rgbaPtr;
				memcpy (rgbPtr, rgbaStart+1, sizeof(pix24));
				rgbPtr++;
				rgbaPtr++;
			}
		}
	} else {
		//----- flip while argb->rgb
		for (int i = 0; i < h; i++){
			pix24 * rgbPtr 			= (pix24 *) rgbPixels + ((h-i-1) * w);
			for (int j = 0; j < w; j++){
				rgbaStart = (unsigned char *)rgbaPtr;
				memcpy (rgbPtr, rgbaStart+1, sizeof(pix24));
				rgbPtr++;
				rgbaPtr++;
			}
		}
	}
}

//----------------------------------------
// osx needs this for modal dialogs.
Boolean SeqGrabberModalFilterUPP (DialogPtr theDialog, const EventRecord *theEvent, short *itemHit, long refCon){
	#pragma unused(theDialog, itemHit)
  	Boolean  handled = false;
  	if ((theEvent->what == updateEvt) &&
    ((WindowPtr) theEvent->message == (WindowPtr) refCon))
  	{
    	BeginUpdate ((WindowPtr) refCon);
    	EndUpdate ((WindowPtr) refCon);
    	handled = true;
  	}
  	return (handled);
}

//----------------------------------------

#ifdef TARGET_OSX
// GetSettingsPreference
//    Returns a preference for a specified key as QuickTime UserData
// It is your responsibility to dispose of the returned UserData
OSErr GetSettingsPreference(CFStringRef inKey, UserData *outUserData)
{
  CFPropertyListRef theCFSettings;
  Handle            theHandle = NULL;
  UserData          theUserData = NULL;
  OSErr             err = paramErr;

  // read the new setttings from our preferences
  theCFSettings = CFPreferencesCopyAppValue(inKey,
                                         kCFPreferencesCurrentApplication);
  if (theCFSettings) {
    err = PtrToHand(CFDataGetBytePtr((CFDataRef)theCFSettings), &theHandle,
                    CFDataGetLength((CFDataRef)theCFSettings));

    CFRelease(theCFSettings);
    if (theHandle) {
      err = NewUserDataFromHandle(theHandle, &theUserData);
      if (theUserData) {
        *outUserData = theUserData;
      }
      DisposeHandle(theHandle);
    }
  }

  return err;
}

//----------------------------------------
// SaveSettingsPreference
//    Saves a preference for a specified key from QuickTime UserData
OSErr SaveSettingsPreference(CFStringRef inKey, UserData inUserData)
{
  CFDataRef theCFSettings;
  Handle    hSettings;
  OSErr     err;

  if (NULL == inUserData) return paramErr;

  hSettings = NewHandle(0);
  err = MemError();

  if (noErr == err) {
    err = PutUserDataIntoHandle(inUserData, hSettings);

    if (noErr == err) {
      HLock(hSettings);

      theCFSettings = CFDataCreate(kCFAllocatorDefault,
                                   (UInt8 *)*hSettings,
                                   GetHandleSize(hSettings));
      if (theCFSettings) {
        CFPreferencesSetAppValue(inKey, theCFSettings,
                                 kCFPreferencesCurrentApplication);
        CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
        CFRelease(theCFSettings);
      }
    }

    DisposeHandle(hSettings);
  }

  return err;
}

#define   kCharacteristicHasVideoFrameRate		FOUR_CHAR_CODE('vfrr')
#define   kCharacteristicIsAnMpegTrack			FOUR_CHAR_CODE('mpeg')

/*

Calculate the static frame rate for a given movie.

*/
void MovieGetStaticFrameRate(Movie inMovie, double *outStaticFrameRate)
{
  assert(inMovie != NULL);
  assert(outStaticFrameRate != NULL);

  *outStaticFrameRate = 0;

  Media movieMedia;
  MediaHandler movieMediaHandler;
  /* get the media identifier for the media that contains the first
    video track's sample data, and also get the media handler for
    this media. */
  MovieGetVideoMediaAndMediaHandler(inMovie, &movieMedia, &movieMediaHandler);
  if (movieMedia && movieMediaHandler)
  {
    Boolean isMPEG = false;
    /* is this the MPEG-1/MPEG-2 media handler? */
    OSErr err = IsMPEGMediaHandler(movieMediaHandler, &isMPEG);
    if (err == noErr)
    {
      if (isMPEG) /* working with MPEG-1/MPEG-2 media */
      {
        Fixed staticFrameRate;
        ComponentResult err = MPEGMediaGetStaticFrameRate(movieMediaHandler, &staticFrameRate);
        if (err == noErr)
        {
          /* convert Fixed data result to type double */
          *outStaticFrameRate = Fix2X(staticFrameRate);
        }
      }
      else  /* working with non-MPEG-1/MPEG-2 media */
      {
        OSErr err = MediaGetStaticFrameRate(movieMedia, outStaticFrameRate);
        assert(err == noErr);
      }
    }
  }
}

/*

Get the media identifier for the media that contains the first
video track's sample data, and also get the media handler for
this media.

*/
void MovieGetVideoMediaAndMediaHandler(Movie inMovie, Media *outMedia, MediaHandler *outMediaHandler)
{
  assert(inMovie != NULL);
  assert(outMedia != NULL);
  assert(outMediaHandler != NULL);

  *outMedia = NULL;
  *outMediaHandler = NULL;

  /* get first video track */
  Track videoTrack = GetMovieIndTrackType(inMovie, 1, kCharacteristicHasVideoFrameRate,
              movieTrackCharacteristic | movieTrackEnabledOnly);
  if (videoTrack != NULL)
  {
    /* get media ref. for track's sample data */
    *outMedia = GetTrackMedia(videoTrack);
    if (*outMedia)
    {
      /* get a reference to the media handler component */
      *outMediaHandler = GetMediaHandler(*outMedia);
    }
  }
}

/*

Return true if media handler reference is from the MPEG-1/MPEG-2 media handler.
Return false otherwise.

*/
OSErr IsMPEGMediaHandler(MediaHandler inMediaHandler, Boolean *outIsMPEG)
{
  assert(inMediaHandler != NULL);
  assert(outIsMPEG != NULL);

  /* is this the MPEG-1/MPEG-2 media handler? */
  return(MediaHasCharacteristic(inMediaHandler,
                  kCharacteristicIsAnMpegTrack,
                  outIsMPEG));
}

/*

Given a reference to the media handler used for media in a MPEG-1/MPEG-2
track, return the static frame rate.

*/
ComponentResult MPEGMediaGetStaticFrameRate(MediaHandler inMPEGMediaHandler, Fixed *outStaticFrameRate)
{
  assert(inMPEGMediaHandler != NULL);
  assert(outStaticFrameRate != NULL);

  *outStaticFrameRate = 0;

  MHInfoEncodedFrameRateRecord encodedFrameRate;
  Size encodedFrameRateSize = sizeof(encodedFrameRate);

    /* get the static frame rate */
  ComponentResult err = MediaGetPublicInfo(inMPEGMediaHandler,
                       kMHInfoEncodedFrameRate,
                       &encodedFrameRate,
                       &encodedFrameRateSize);
  if (err == noErr)
  {
    /* return frame rate at which the track was encoded */
    *outStaticFrameRate = encodedFrameRate.encodedFrameRate;
  }

  return err;
}

/*

Given a reference to the media that contains the sample data for a track,
calculate the static frame rate.

*/
OSErr MediaGetStaticFrameRate(Media inMovieMedia, double *outFPS)
{
  assert(inMovieMedia != NULL);
  assert(outFPS != NULL);

  *outFPS = 0;

    /* get the number of samples in the media */
  long sampleCount = GetMediaSampleCount(inMovieMedia);
  OSErr err = GetMoviesError();

  if (sampleCount && err == noErr)
  {
      /* find the media duration */
    TimeValue64 duration = GetMediaDisplayDuration(inMovieMedia);
    err = GetMoviesError();
    if (err == noErr)
    {
        /* get the media time scale */
      TimeValue64 timeScale = GetMediaTimeScale(inMovieMedia);
      err = GetMoviesError();
      if (err == noErr)
      {
        /* calculate the frame rate:
          frame rate = (sample count * media time scale) / media duration
          */
        *outFPS = (double)sampleCount * (double)timeScale / (double)duration;
      }
    }
  }

  return err;
}

#endif

<commit_msg>Redone overwritten changes for platform especific ifdefs<commit_after>#include "ofQtUtils.h"
#ifndef TARGET_LINUX
static bool bQuicktimeInitialized = false;

//----------------------------------------
void initializeQuicktime(){
	if (bQuicktimeInitialized == false){

		//----------------------------------
		// do we have quicktime installed at all?
		// http://www.apple.com/quicktime/download/win.html
		// can gestalt help with versions, or is that only after init?

		OSErr myErr 	= noErr;
		#ifdef TARGET_WIN32
			myErr = InitializeQTML(0);
			if (myErr != noErr){
				printf("----------------------------------------------------- \n");
				printf("sorry, there is a problem with quicktime starting up \nplease check!");
                OF_EXIT_APP(0);
			}
		#endif
		myErr = EnterMovies ();
		if (myErr != noErr){
			printf("----------------------------------------------------- \n");
			printf("sorry, there is a problem with quicktime starting up  \nplease check!");
			OF_EXIT_APP(0);
		}

		bQuicktimeInitialized = true;
	}
}

//----------------------------------------
void closeQuicktime(){
	if (bQuicktimeInitialized == true){
		ExitMovies();
		#ifdef TARGET_WIN32
			TerminateQTML();
		#endif
		bQuicktimeInitialized = false;
	}
}

//----------------------------------------
void convertPixels(unsigned char * gWorldPixels, unsigned char * rgbPixels, int w, int h){

	// ok for macs?
	// ok for intel macs?

	int * rgbaPtr 			= (int *) gWorldPixels;
	pix24 * rgbPtr 			= (pix24 *) rgbPixels;
	int totalPixelCount 	= w * h;
	unsigned char * rgbaStart;

	//	putting in the boolean, so we can work on
	//	0,0 in top right...
	//	bool bFlipVertically 	= true;

	bool bFlipVertically 	= false;

	// -------------------------------------------
	// we flip vertically because the 0,0 position in OF
	// is the bottom left (not top left, like processing)
	// since the 0,0 of a picture is top left
	// if we upload and drawf the data as is
	// it will be upside-down....
	// -------------------------------------------

	if (!bFlipVertically){
		//----- argb->rgb
		for (int i = 0; i < h; i++){
			pix24 * rgbPtr 			= (pix24 *) rgbPixels + ((i) * w);
			for (int j = 0; j < w; j++){
				rgbaStart = (unsigned char *)rgbaPtr;
				memcpy (rgbPtr, rgbaStart+1, sizeof(pix24));
				rgbPtr++;
				rgbaPtr++;
			}
		}
	} else {
		//----- flip while argb->rgb
		for (int i = 0; i < h; i++){
			pix24 * rgbPtr 			= (pix24 *) rgbPixels + ((h-i-1) * w);
			for (int j = 0; j < w; j++){
				rgbaStart = (unsigned char *)rgbaPtr;
				memcpy (rgbPtr, rgbaStart+1, sizeof(pix24));
				rgbPtr++;
				rgbaPtr++;
			}
		}
	}
}

//----------------------------------------
// osx needs this for modal dialogs.
Boolean SeqGrabberModalFilterUPP (DialogPtr theDialog, const EventRecord *theEvent, short *itemHit, long refCon){
	#pragma unused(theDialog, itemHit)
  	Boolean  handled = false;
  	if ((theEvent->what == updateEvt) &&
    ((WindowPtr) theEvent->message == (WindowPtr) refCon))
  	{
    	BeginUpdate ((WindowPtr) refCon);
    	EndUpdate ((WindowPtr) refCon);
    	handled = true;
  	}
  	return (handled);
}

//----------------------------------------

#ifdef TARGET_OSX
// GetSettingsPreference
//    Returns a preference for a specified key as QuickTime UserData
// It is your responsibility to dispose of the returned UserData
OSErr GetSettingsPreference(CFStringRef inKey, UserData *outUserData)
{
  CFPropertyListRef theCFSettings;
  Handle            theHandle = NULL;
  UserData          theUserData = NULL;
  OSErr             err = paramErr;

  // read the new setttings from our preferences
  theCFSettings = CFPreferencesCopyAppValue(inKey,
                                         kCFPreferencesCurrentApplication);
  if (theCFSettings) {
    err = PtrToHand(CFDataGetBytePtr((CFDataRef)theCFSettings), &theHandle,
                    CFDataGetLength((CFDataRef)theCFSettings));

    CFRelease(theCFSettings);
    if (theHandle) {
      err = NewUserDataFromHandle(theHandle, &theUserData);
      if (theUserData) {
        *outUserData = theUserData;
      }
      DisposeHandle(theHandle);
    }
  }

  return err;
}

//----------------------------------------
// SaveSettingsPreference
//    Saves a preference for a specified key from QuickTime UserData
OSErr SaveSettingsPreference(CFStringRef inKey, UserData inUserData)
{
  CFDataRef theCFSettings;
  Handle    hSettings;
  OSErr     err;

  if (NULL == inUserData) return paramErr;

  hSettings = NewHandle(0);
  err = MemError();

  if (noErr == err) {
    err = PutUserDataIntoHandle(inUserData, hSettings);

    if (noErr == err) {
      HLock(hSettings);

      theCFSettings = CFDataCreate(kCFAllocatorDefault,
                                   (UInt8 *)*hSettings,
                                   GetHandleSize(hSettings));
      if (theCFSettings) {
        CFPreferencesSetAppValue(inKey, theCFSettings,
                                 kCFPreferencesCurrentApplication);
        CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
        CFRelease(theCFSettings);
      }
    }

    DisposeHandle(hSettings);
  }

  return err;
}

#define   kCharacteristicHasVideoFrameRate		FOUR_CHAR_CODE('vfrr')
#define   kCharacteristicIsAnMpegTrack			FOUR_CHAR_CODE('mpeg')

/*

Calculate the static frame rate for a given movie.

*/
void MovieGetStaticFrameRate(Movie inMovie, double *outStaticFrameRate)
{
  assert(inMovie != NULL);
  assert(outStaticFrameRate != NULL);

  *outStaticFrameRate = 0;

  Media movieMedia;
  MediaHandler movieMediaHandler;
  /* get the media identifier for the media that contains the first
    video track's sample data, and also get the media handler for
    this media. */
  MovieGetVideoMediaAndMediaHandler(inMovie, &movieMedia, &movieMediaHandler);
  if (movieMedia && movieMediaHandler)
  {
    Boolean isMPEG = false;
    /* is this the MPEG-1/MPEG-2 media handler? */
    OSErr err = IsMPEGMediaHandler(movieMediaHandler, &isMPEG);
    if (err == noErr)
    {
      if (isMPEG) /* working with MPEG-1/MPEG-2 media */
      {
        Fixed staticFrameRate;
        ComponentResult err = MPEGMediaGetStaticFrameRate(movieMediaHandler, &staticFrameRate);
        if (err == noErr)
        {
          /* convert Fixed data result to type double */
          *outStaticFrameRate = Fix2X(staticFrameRate);
        }
      }
      else  /* working with non-MPEG-1/MPEG-2 media */
      {
        OSErr err = MediaGetStaticFrameRate(movieMedia, outStaticFrameRate);
        assert(err == noErr);
      }
    }
  }
}

/*

Get the media identifier for the media that contains the first
video track's sample data, and also get the media handler for
this media.

*/
void MovieGetVideoMediaAndMediaHandler(Movie inMovie, Media *outMedia, MediaHandler *outMediaHandler)
{
  assert(inMovie != NULL);
  assert(outMedia != NULL);
  assert(outMediaHandler != NULL);

  *outMedia = NULL;
  *outMediaHandler = NULL;

  /* get first video track */
  Track videoTrack = GetMovieIndTrackType(inMovie, 1, kCharacteristicHasVideoFrameRate,
              movieTrackCharacteristic | movieTrackEnabledOnly);
  if (videoTrack != NULL)
  {
    /* get media ref. for track's sample data */
    *outMedia = GetTrackMedia(videoTrack);
    if (*outMedia)
    {
      /* get a reference to the media handler component */
      *outMediaHandler = GetMediaHandler(*outMedia);
    }
  }
}

/*

Return true if media handler reference is from the MPEG-1/MPEG-2 media handler.
Return false otherwise.

*/
OSErr IsMPEGMediaHandler(MediaHandler inMediaHandler, Boolean *outIsMPEG)
{
  assert(inMediaHandler != NULL);
  assert(outIsMPEG != NULL);

  /* is this the MPEG-1/MPEG-2 media handler? */
  return(MediaHasCharacteristic(inMediaHandler,
                  kCharacteristicIsAnMpegTrack,
                  outIsMPEG));
}

/*

Given a reference to the media handler used for media in a MPEG-1/MPEG-2
track, return the static frame rate.

*/
ComponentResult MPEGMediaGetStaticFrameRate(MediaHandler inMPEGMediaHandler, Fixed *outStaticFrameRate)
{
  assert(inMPEGMediaHandler != NULL);
  assert(outStaticFrameRate != NULL);

  *outStaticFrameRate = 0;

  MHInfoEncodedFrameRateRecord encodedFrameRate;
  Size encodedFrameRateSize = sizeof(encodedFrameRate);

    /* get the static frame rate */
  ComponentResult err = MediaGetPublicInfo(inMPEGMediaHandler,
                       kMHInfoEncodedFrameRate,
                       &encodedFrameRate,
                       &encodedFrameRateSize);
  if (err == noErr)
  {
    /* return frame rate at which the track was encoded */
    *outStaticFrameRate = encodedFrameRate.encodedFrameRate;
  }

  return err;
}

/*

Given a reference to the media that contains the sample data for a track,
calculate the static frame rate.

*/
OSErr MediaGetStaticFrameRate(Media inMovieMedia, double *outFPS)
{
  assert(inMovieMedia != NULL);
  assert(outFPS != NULL);

  *outFPS = 0;

    /* get the number of samples in the media */
  long sampleCount = GetMediaSampleCount(inMovieMedia);
  OSErr err = GetMoviesError();

  if (sampleCount && err == noErr)
  {
      /* find the media duration */
    TimeValue64 duration = GetMediaDisplayDuration(inMovieMedia);
    err = GetMoviesError();
    if (err == noErr)
    {
        /* get the media time scale */
      TimeValue64 timeScale = GetMediaTimeScale(inMovieMedia);
      err = GetMoviesError();
      if (err == noErr)
      {
        /* calculate the frame rate:
          frame rate = (sample count * media time scale) / media duration
          */
        *outFPS = (double)sampleCount * (double)timeScale / (double)duration;
      }
    }
  }

  return err;
}

#endif
#endif
<|endoftext|>


<commit_before>/*
 * eos - A 3D Morphable Model fitting library written in modern C++11/14.
 *
 * File: python/pybind11_Image.hpp
 *
 * Copyright 2017 Patrik Huber
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma once

#ifndef EOS_PYBIND11_IMAGE_HPP_
#define EOS_PYBIND11_IMAGE_HPP_

#include "pybind11/numpy.h"

#include "Eigen/Core"

#include <cstddef>
#include <vector>

NAMESPACE_BEGIN(pybind11)
NAMESPACE_BEGIN(detail)

/**
 * @file python/pybind11_Image.hpp
 * @brief Transparent conversion to and from Python for eos::core::Image.
 *
 * Numpy uses row-major storage order by default.
 * eos::core::Image uses col-major storage (like Eigen).
 *
 * If given non-standard strides or something from numpy, probably doesn't work.
 * May need to .clone()? in numpy before passing to the C++ function.
 */

/**
 * @brief Transparent conversion for eos::core::Image3u to and from Python.
 *
 * Converts an eos::core::Image3u to and from Python. Can construct a eos::core::Image3u from numpy arrays,
 * as well as potentially other Python array types.
 *
 * Note: Not sure what happens if the given numpy array is not contiguous, not in default (row-major) storage
 *       order, or has non-standard strides. It may or may not work.
 */
template<>
struct type_caster<eos::core::Image3u>
{
	bool load(handle src, bool)
	{
		auto buf = pybind11::array::ensure(src);
		if (!buf)
			return false;

		// Todo: We should probably check that buf.strides(i) is "default", by dividing it by the Scalar type or something.

		if (!pybind11::isinstance<pybind11::array_t<std::uint8_t>>(buf))
		{
			return false; // we only convert uint8_t for now.
		}

		if (buf.ndim() != 3) {
			return false; // we expected a numpy array with 3 dimensions.
		}
		// We got something with 3 dimensions, i.e. an image with 2, 3 or 4 channels (or 'k' for that matter):
		if (buf.shape(2) != 3) {
			return false; // We expected a 3-channel image.
		}

		// Note: If our Image class had support for col/row major, we could just map buf.mutable_data().
		// Like with OpenCV: value = cv::Mat(buf.shape(0), buf.shape(1), opencv_type, buf.mutable_data());
		// But since it doesn't, we just copy the data for now:
		value = eos::core::Image3u(buf.shape(0), buf.shape(1));
		array_t<std::uint8_t> buf_as_array(buf);
		for (int r = 0; r < buf.shape(0); ++r) {
			for (int c = 0; c < buf.shape(1); ++c) {
				value(r, c)[0] = buf_as_array.at(r, c, 0);
				value(r, c)[1] = buf_as_array.at(r, c, 1);
				value(r, c)[2] = buf_as_array.at(r, c, 2);
			}
		}
		return true;
	};

    static handle cast(const eos::core::Image3u& src, return_value_policy /* policy */, handle /* parent */)
	{
		const std::size_t num_channels = 3;
		std::vector<std::size_t> shape = { static_cast<std::size_t>(src.height()), static_cast<std::size_t>(src.width()), num_channels };

		// (2048, 4, 1) is default which results in transposed image
		// Below line works now. In numpy the strides are (2048, 4, 1) though. I think a copy gets created nevertheless?
		std::vector<std::size_t> strides = { num_channels, num_channels * src.height(), 1 }; // might be cols or rows...? I think rows?
		// Note: I think with the change to the new Image class (July 2018), which is now row-major by default, the strides here might have changed. I didn't check.
		// Also, since the new Image stores a vector of Pixels, the question is whether there's any padding added by the compiler, but probably not, since all types that we use are 1 byte or a multiple thereof.
		// numpy: 'f' = fortran = col-major
		//        'c' = c = row-major = default I think.
		return array(pybind11::dtype::of<std::uint8_t>(), shape, strides, &src(0, 0).data()[0]).release();
	};

    PYBIND11_TYPE_CASTER(eos::core::Image3u, _("numpy.ndarray[uint8[m, n, 3]]"));
};

/**
 * @brief Transparent conversion for eos::core::Image4u to and from Python.
 *
 * Converts an eos::core::Image4u to and from Python. Can construct a eos::core::Image4u from numpy arrays,
 * as well as potentially other Python array types.
 *
 * Note: Not sure what happens if the given numpy array is not contiguous, not in default (row-major) storage
 *       order, or has non-standard strides. It may or may not work.
 */
template<>
struct type_caster<eos::core::Image4u>
{
	bool load(handle src, bool)
	{
		auto buf = pybind11::array::ensure(src);
		if (!buf)
			return false;

		// Todo: We should probably check that buf.strides(i) is "default", by dividing it by the Scalar type or something.

		if (!pybind11::isinstance<pybind11::array_t<std::uint8_t>>(buf))
		{
			return false; // we only convert uint8_t for now.
		}

		if (buf.ndim() != 3) {
			return false; // we expected a numpy array with 3 dimensions.
		}
		// We got something with 3 dimensions, i.e. an image with 2, 3 or 4 channels (or 'k' for that matter):
		if (buf.shape(2) != 4) {
			return false; // We expected a 4-channel image.
		}

		// Note: If our Image class had support for col/row major, we could just map buf.mutable_data().
		// Like with OpenCV: value = cv::Mat(buf.shape(0), buf.shape(1), opencv_type, buf.mutable_data());
		// But since it doesn't, we just copy the data for now:
		value = eos::core::Image4u(buf.shape(0), buf.shape(1));
		array_t<std::uint8_t> buf_as_array(buf);
		for (int r = 0; r < buf.shape(0); ++r) {
			for (int c = 0; c < buf.shape(1); ++c) {
				value(r, c)[0] = buf_as_array.at(r, c, 0);
				value(r, c)[1] = buf_as_array.at(r, c, 1);
				value(r, c)[2] = buf_as_array.at(r, c, 2);
				value(r, c)[3] = buf_as_array.at(r, c, 3);
			}
		}
		return true;
	};

    static handle cast(const eos::core::Image4u& src, return_value_policy /* policy */, handle /* parent */)
	{
		const std::size_t num_chanels = 4;
		std::vector<std::size_t> shape;
		shape = { static_cast<std::size_t>(src.height()), static_cast<std::size_t>(src.width()), num_chanels };

		// (2048, 4, 1) is default which results in transposed image
		// Below line works now. In numpy the strides are (2048, 4, 1) though. I think a copy gets created nevertheless?
		std::vector<size_t> strides = { num_chanels, num_chanels * src.height(), 1 }; // might be cols or rows...? I think rows?
		// Note: I think with the change to the new Image class (July 2018), which is now row-major by default, the strides here might have changed. I didn't check.
		// Also, since the new Image stores a vector of Pixels, the question is whether there's any padding added by the compiler, but probably not, since all types that we use are 1 byte or a multiple thereof.
		return array(pybind11::dtype::of<std::uint8_t>(), shape, strides, &src(0, 0).data()[0]).release();
	};

    PYBIND11_TYPE_CASTER(eos::core::Image4u, _("numpy.ndarray[uint8[m, n, 4]]"));
};

NAMESPACE_END(detail)
NAMESPACE_END(pybind11)

#endif /* EOS_PYBIND11_IMAGE_HPP_ */
<commit_msg>Fix small typo in variable name<commit_after>/*
 * eos - A 3D Morphable Model fitting library written in modern C++11/14.
 *
 * File: python/pybind11_Image.hpp
 *
 * Copyright 2017 Patrik Huber
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma once

#ifndef EOS_PYBIND11_IMAGE_HPP_
#define EOS_PYBIND11_IMAGE_HPP_

#include "pybind11/numpy.h"

#include "Eigen/Core"

#include <cstddef>
#include <vector>

NAMESPACE_BEGIN(pybind11)
NAMESPACE_BEGIN(detail)

/**
 * @file python/pybind11_Image.hpp
 * @brief Transparent conversion to and from Python for eos::core::Image.
 *
 * Numpy uses row-major storage order by default.
 * eos::core::Image uses col-major storage (like Eigen).
 *
 * If given non-standard strides or something from numpy, probably doesn't work.
 * May need to .clone()? in numpy before passing to the C++ function.
 */

/**
 * @brief Transparent conversion for eos::core::Image3u to and from Python.
 *
 * Converts an eos::core::Image3u to and from Python. Can construct a eos::core::Image3u from numpy arrays,
 * as well as potentially other Python array types.
 *
 * Note: Not sure what happens if the given numpy array is not contiguous, not in default (row-major) storage
 *       order, or has non-standard strides. It may or may not work.
 */
template<>
struct type_caster<eos::core::Image3u>
{
	bool load(handle src, bool)
	{
		auto buf = pybind11::array::ensure(src);
		if (!buf)
			return false;

		// Todo: We should probably check that buf.strides(i) is "default", by dividing it by the Scalar type or something.

		if (!pybind11::isinstance<pybind11::array_t<std::uint8_t>>(buf))
		{
			return false; // we only convert uint8_t for now.
		}

		if (buf.ndim() != 3) {
			return false; // we expected a numpy array with 3 dimensions.
		}
		// We got something with 3 dimensions, i.e. an image with 2, 3 or 4 channels (or 'k' for that matter):
		if (buf.shape(2) != 3) {
			return false; // We expected a 3-channel image.
		}

		// Note: If our Image class had support for col/row major, we could just map buf.mutable_data().
		// Like with OpenCV: value = cv::Mat(buf.shape(0), buf.shape(1), opencv_type, buf.mutable_data());
		// But since it doesn't, we just copy the data for now:
		value = eos::core::Image3u(buf.shape(0), buf.shape(1));
		array_t<std::uint8_t> buf_as_array(buf);
		for (int r = 0; r < buf.shape(0); ++r) {
			for (int c = 0; c < buf.shape(1); ++c) {
				value(r, c)[0] = buf_as_array.at(r, c, 0);
				value(r, c)[1] = buf_as_array.at(r, c, 1);
				value(r, c)[2] = buf_as_array.at(r, c, 2);
			}
		}
		return true;
	};

    static handle cast(const eos::core::Image3u& src, return_value_policy /* policy */, handle /* parent */)
	{
		const std::size_t num_channels = 3;
		std::vector<std::size_t> shape = { static_cast<std::size_t>(src.height()), static_cast<std::size_t>(src.width()), num_channels };

		// (2048, 4, 1) is default which results in transposed image
		// Below line works now. In numpy the strides are (2048, 4, 1) though. I think a copy gets created nevertheless?
		std::vector<std::size_t> strides = { num_channels, num_channels * src.height(), 1 }; // might be cols or rows...? I think rows?
		// Note: I think with the change to the new Image class (July 2018), which is now row-major by default, the strides here might have changed. I didn't check.
		// Also, since the new Image stores a vector of Pixels, the question is whether there's any padding added by the compiler, but probably not, since all types that we use are 1 byte or a multiple thereof.
		// numpy: 'f' = fortran = col-major
		//        'c' = c = row-major = default I think.
		return array(pybind11::dtype::of<std::uint8_t>(), shape, strides, &src(0, 0).data()[0]).release();
	};

    PYBIND11_TYPE_CASTER(eos::core::Image3u, _("numpy.ndarray[uint8[m, n, 3]]"));
};

/**
 * @brief Transparent conversion for eos::core::Image4u to and from Python.
 *
 * Converts an eos::core::Image4u to and from Python. Can construct a eos::core::Image4u from numpy arrays,
 * as well as potentially other Python array types.
 *
 * Note: Not sure what happens if the given numpy array is not contiguous, not in default (row-major) storage
 *       order, or has non-standard strides. It may or may not work.
 */
template<>
struct type_caster<eos::core::Image4u>
{
	bool load(handle src, bool)
	{
		auto buf = pybind11::array::ensure(src);
		if (!buf)
			return false;

		// Todo: We should probably check that buf.strides(i) is "default", by dividing it by the Scalar type or something.

		if (!pybind11::isinstance<pybind11::array_t<std::uint8_t>>(buf))
		{
			return false; // we only convert uint8_t for now.
		}

		if (buf.ndim() != 3) {
			return false; // we expected a numpy array with 3 dimensions.
		}
		// We got something with 3 dimensions, i.e. an image with 2, 3 or 4 channels (or 'k' for that matter):
		if (buf.shape(2) != 4) {
			return false; // We expected a 4-channel image.
		}

		// Note: If our Image class had support for col/row major, we could just map buf.mutable_data().
		// Like with OpenCV: value = cv::Mat(buf.shape(0), buf.shape(1), opencv_type, buf.mutable_data());
		// But since it doesn't, we just copy the data for now:
		value = eos::core::Image4u(buf.shape(0), buf.shape(1));
		array_t<std::uint8_t> buf_as_array(buf);
		for (int r = 0; r < buf.shape(0); ++r) {
			for (int c = 0; c < buf.shape(1); ++c) {
				value(r, c)[0] = buf_as_array.at(r, c, 0);
				value(r, c)[1] = buf_as_array.at(r, c, 1);
				value(r, c)[2] = buf_as_array.at(r, c, 2);
				value(r, c)[3] = buf_as_array.at(r, c, 3);
			}
		}
		return true;
	};

    static handle cast(const eos::core::Image4u& src, return_value_policy /* policy */, handle /* parent */)
	{
		const std::size_t num_channels = 4;
		std::vector<std::size_t> shape;
		shape = { static_cast<std::size_t>(src.height()), static_cast<std::size_t>(src.width()), num_channels };

		// (2048, 4, 1) is default which results in transposed image
		// Below line works now. In numpy the strides are (2048, 4, 1) though. I think a copy gets created nevertheless?
		std::vector<size_t> strides = { num_channels, num_channels * src.height(), 1 }; // might be cols or rows...? I think rows?
		// Note: I think with the change to the new Image class (July 2018), which is now row-major by default, the strides here might have changed. I didn't check.
		// Also, since the new Image stores a vector of Pixels, the question is whether there's any padding added by the compiler, but probably not, since all types that we use are 1 byte or a multiple thereof.
		return array(pybind11::dtype::of<std::uint8_t>(), shape, strides, &src(0, 0).data()[0]).release();
	};

    PYBIND11_TYPE_CASTER(eos::core::Image4u, _("numpy.ndarray[uint8[m, n, 4]]"));
};

NAMESPACE_END(detail)
NAMESPACE_END(pybind11)

#endif /* EOS_PYBIND11_IMAGE_HPP_ */
<|endoftext|>


<commit_before>#include "material.h"
#include "simconf.h"

#include "functions.h"

#include <cmath>
#include <iostream>

void materialBase::prepare()
{
  double tt = 0.0;

  // get total stoichiometry
  for( int i = 0; i < element.size(); i++ )
  {
    if( element[i]->t < 0.0 ) element[i]->t = 0.0;
    tt += element[i]->t;
  }

  // normalize relative probabilities to 1
  for( int i = 0; i < element.size(); i++ ) element[i]->t /= tt;

  // average
  am = 0.0;
  az = 0.0;
  for( int i = 0; i < element.size(); i++ )
  {
    am += element[i]->m * element[i]->t;
    az += double( element[i]->z ) * element[i]->t;
  }

  arho = rho * 0.6022 / am; //[TRI00310] atoms/Ang^3
}

// make sure layers are prepare'd first!
void materialBase::average( const ionBase *pka )
{
  mu = pka->m1 / am;

  // universal or firsov screening length
  a = .5292 * .8853 / ( pow( double(pka->z1), 0.23 ) + pow( az, 0.23 ) );
  //a = .5292 * .8853 / pow( pow( double(pka.z1), 0.5 ) + pow( az, 0.5 ), 2.0/3.0 );

  // mean flight path0
  f = a * am / ( az * double(pka->z1) * 14.4 * ( pka->m1 + am ) );
  //eps0 = e0 * f;
  epsdg = simconf->tmin * f * pow( 1.0 + mu, 2.0 ) / ( 4.0 * mu );

  // fd and kd determine how much recoil energy goes into el. loss and vaccancies
  fd = pow( 0.01 * az, -7.0 / 3.0 );
  kd = pow( 0.1334 * az, 2.0 / 3.0 ) / sqrtf( am );

  for( int i = 0; i < element.size(); i++ )
  {
    element[i]->my = pka->m1 / element[i]->m;
    element[i]->ec = 4.0 * element[i]->my / pow( 1.0 + element[i]->my, 2.0 );
    element[i]->ai = .5292 * .8853 / ( pow( double(pka->z1), 0.23 ) + pow( element[i]->m, 0.23 ) );
    //ai = .5292 * .8853 / pow( pow( double(pka.z1), 0.5 ) + pow( element[i].m, 0.5 ), 2.0/3.0 );
    element[i]->fi = element[i]->ai * element[i]->m /
                     ( double(pka->z1) * double(element[i]->z) * 14.4 * ( pka->m1 + element[i]->m ) );
  }

  dirty = false;
}

// make sure layers are prepare'd and averaged first!
double materialBase::getrstop( const ionBase *pka )
{
  double se = 0.0;
  for( int i = 0; i < element.size(); i++ )
    se += rstop( pka, element[i]->z ) * element[i]->t * arho;

  return se;
}

double materialBase::rpstop( int z2p, double e )
{
  double pe, pe0, sl, sh, sp, velpwr;
  int z2 = z2p-1;
  // velocity proportional stopping below pe0
  pe0 = 25.0;
  pe = fmax( pe0, e );

  // pcoef indices are one less than in the fortran version!
  sl = ( simconf->pcoef[z2][0] * pow( pe, simconf->pcoef[z2][1] ) ) +
       ( simconf->pcoef[z2][2] * pow( pe, simconf->pcoef[z2][3] ) );
  sh = simconf->pcoef[z2][4] / pow( pe, simconf->pcoef[z2][5] ) *
       logf( simconf->pcoef[z2][6] / pe + simconf->pcoef[z2][7] * pe );
  sp = sl * sh / (sl + sh );
  if( e <= pe0 )
  {
    // velpwr is the power of velocity stopping below pe0
    if( z2p <= 6 )
      velpwr = 0.25;
    else
      velpwr = 0.45;
    sp *= pow( e/pe0, velpwr );
  }
  return sp;
}

double materialBase::rstop( const ionBase *ion, int z2 )
{
  double e, vrmin, yrmin, v, vr, yr, vmin, m1;
  double a, b, q, q1, l, l0, l1;
  double zeta;
  int z1 = ion->z1;
  double fz1 = double(z1), fz2 = double(z2);
  double eee, sp, power;
  double se;

  // scoeff
  double lfctr = simconf->scoef[z1-1].lfctr;
  double mm1 = simconf->scoef[z1-1].mm1;
  double vfermi = simconf->scoef[z2-1].vfermi;
  double atrho = simconf->scoef[z2-1].atrho;

  if( ion->m1 == 0.0 )
    m1 = mm1;
  else
    m1 = ion->m1;

  e = 0.001 * ion->e / m1;

  if( z1 == 1 )
  {
    cerr << "proton stopping not yet implemented!\n";
  }
  else if( z1 == 2 )
  {
    cerr << "alpha stopping not yet implemented!\n";
  }
  else
  {
    yrmin = 0.13;
    vrmin = 1.0;
    v = sqrtf( e / 25.0) / vfermi;

    if( v >= 1.0 )
      vr = v * vfermi * ( 1.0 + 1.0 / ( 5.0 * v*v ) );
    else
      vr = ( 3.0 * vfermi / 4.0 ) * ( 1.0 + ( 2.0 * v*v / 3.0 ) - pow( v, 4.0 ) / 15.0 );

    yr = fmax( yrmin, vr / pow(fz1,0.6667) );
    yr = fmax( yr, vrmin / pow(fz1,0.6667) );
    a = -0.803 * pow( yr, 0.3 ) + 1.3167 * pow( yr, 0.6 ) + 0.38157 * yr +  0.008983 * yr*yr;

    // ionization level of the ion at velocity yr
    q = fmin( 1.0, fmax( 0.0, 1.0 - exp( -fmin( a, 50.0 ) ) ) );

    b = ( fmin( 0.43, fmax( 0.32, 0.12 + 0.025 * fz1 ) ) ) / pow( fz1, 0.3333 );
    l0 = ( 0.8 - q * fmin( 1.2, 0.6 + fz1 / 30.0) ) / pow( fz1, 0.3333 );
    if( q < 0.2 )
      l1 = 0.0;
    else if( q < fmax( 0.0, 0.9 - 0.025 * fz1 ) )
    {//210
      q1 = 0.2;
      l1 = b * ( q - 0.2 ) / fabs( fmax( 0.0, 0.9 - 0.025 * fz1 ) - 0.2000001 );
    }
    else if( q < fmax( 0.0, 1.0 - 0.025 * fmin( 16.0, fz1 ) ) )
      l1 = b;
    else
      l1 = b * ( 1.0 - q ) / ( 0.025 * fmin( 16.0, fz1 ) );

    l = fmax( l1, l0 * lfctr );
    zeta = q + ( 1.0 / ( 2.0 * vfermi*vfermi ) ) * ( 1.0 - q ) * logf( 1.0 + sqr( 4.0 * l * vfermi / 1.919  ) );

    // add z1^3 effect
    a = -sqr( 7.6 - fmax( 0.0, logf( e ) ) );
    zeta *= 1.0 + ( 1.0 / (fz1*fz1) ) * ( 0.18 + 0.0015 * fz2 ) * expf( a );

    if( yr <= fmax( yrmin, vrmin / pow( fz1, 0.6667 ) ) )
    {
      // calculate velocity stopping for  yr < yrmin
      vrmin = fmax( vrmin, yrmin * pow( fz1, 0.6667 ) );
      vmin = 0.5 * ( vrmin + sqrtf( fmax( 0.0, vrmin*vrmin - 0.8 * vfermi*vfermi ) ) );
      eee = 25.0 * vmin*vmin;
      sp = rpstop( z2, eee );

      if( z2 == 6 || ( ( z2 == 14 || z2 == 32 ) && z1 <= 19 ) )
        power = 0.375;
      else
        power = 0.5;

      se = sp * sqr( zeta * fz1 ) * pow( e/eee, power );
    }
    else
    {
      sp = rpstop( z2, e );
      se = sp * sqr( zeta * fz1 );
    }
  } // END: heavy-ions

  return se * 10.0;
}
<commit_msg>fix m/z mix-up in screening length calculation (thanks Topher Matthews for spotting this)<commit_after>#include "material.h"
#include "simconf.h"

#include "functions.h"

#include <cmath>
#include <iostream>

void materialBase::prepare()
{
  double tt = 0.0;

  // get total stoichiometry
  for( int i = 0; i < element.size(); i++ )
  {
    if( element[i]->t < 0.0 ) element[i]->t = 0.0;
    tt += element[i]->t;
  }

  // normalize relative probabilities to 1
  for( int i = 0; i < element.size(); i++ ) element[i]->t /= tt;

  // average
  am = 0.0;
  az = 0.0;
  for( int i = 0; i < element.size(); i++ )
  {
    am += element[i]->m * element[i]->t;
    az += double( element[i]->z ) * element[i]->t;
  }

  arho = rho * 0.6022 / am; //[TRI00310] atoms/Ang^3
}

// make sure layers are prepare'd first!
void materialBase::average( const ionBase *pka )
{
  mu = pka->m1 / am;

  // universal or firsov screening length
  a = .5292 * .8853 / ( pow( double(pka->z1), 0.23 ) + pow( az, 0.23 ) );
  //a = .5292 * .8853 / pow( pow( double(pka.z1), 0.5 ) + pow( az, 0.5 ), 2.0/3.0 );

  // mean flight path0
  f = a * am / ( az * double(pka->z1) * 14.4 * ( pka->m1 + am ) );
  //eps0 = e0 * f;
  epsdg = simconf->tmin * f * pow( 1.0 + mu, 2.0 ) / ( 4.0 * mu );

  // fd and kd determine how much recoil energy goes into el. loss and vaccancies
  fd = pow( 0.01 * az, -7.0 / 3.0 );
  kd = pow( 0.1334 * az, 2.0 / 3.0 ) / sqrtf( am );

  for( int i = 0; i < element.size(); i++ )
  {
    element[i]->my = pka->m1 / element[i]->m;
    element[i]->ec = 4.0 * element[i]->my / pow( 1.0 + element[i]->my, 2.0 );
    element[i]->ai = .5292 * .8853 / ( pow( double(pka->z1), 0.23 ) + pow( element[i]->z, 0.23 ) );
    //ai = .5292 * .8853 / pow( pow( double(pka.z1), 0.5 ) + pow( element[i].z, 0.5 ), 2.0/3.0 );
    element[i]->fi = element[i]->ai * element[i]->m /
                     ( double(pka->z1) * double(element[i]->z) * 14.4 * ( pka->m1 + element[i]->m ) );
  }

  dirty = false;
}

// make sure layers are prepare'd and averaged first!
double materialBase::getrstop( const ionBase *pka )
{
  double se = 0.0;
  for( int i = 0; i < element.size(); i++ )
    se += rstop( pka, element[i]->z ) * element[i]->t * arho;

  return se;
}

double materialBase::rpstop( int z2p, double e )
{
  double pe, pe0, sl, sh, sp, velpwr;
  int z2 = z2p-1;
  // velocity proportional stopping below pe0
  pe0 = 25.0;
  pe = fmax( pe0, e );

  // pcoef indices are one less than in the fortran version!
  sl = ( simconf->pcoef[z2][0] * pow( pe, simconf->pcoef[z2][1] ) ) +
       ( simconf->pcoef[z2][2] * pow( pe, simconf->pcoef[z2][3] ) );
  sh = simconf->pcoef[z2][4] / pow( pe, simconf->pcoef[z2][5] ) *
       logf( simconf->pcoef[z2][6] / pe + simconf->pcoef[z2][7] * pe );
  sp = sl * sh / (sl + sh );
  if( e <= pe0 )
  {
    // velpwr is the power of velocity stopping below pe0
    if( z2p <= 6 )
      velpwr = 0.25;
    else
      velpwr = 0.45;
    sp *= pow( e/pe0, velpwr );
  }
  return sp;
}

double materialBase::rstop( const ionBase *ion, int z2 )
{
  double e, vrmin, yrmin, v, vr, yr, vmin, m1;
  double a, b, q, q1, l, l0, l1;
  double zeta;
  int z1 = ion->z1;
  double fz1 = double(z1), fz2 = double(z2);
  double eee, sp, power;
  double se;

  // scoeff
  double lfctr = simconf->scoef[z1-1].lfctr;
  double mm1 = simconf->scoef[z1-1].mm1;
  double vfermi = simconf->scoef[z2-1].vfermi;
  double atrho = simconf->scoef[z2-1].atrho;

  if( ion->m1 == 0.0 )
    m1 = mm1;
  else
    m1 = ion->m1;

  e = 0.001 * ion->e / m1;

  if( z1 == 1 )
  {
    cerr << "proton stopping not yet implemented!\n";
  }
  else if( z1 == 2 )
  {
    cerr << "alpha stopping not yet implemented!\n";
  }
  else
  {
    yrmin = 0.13;
    vrmin = 1.0;
    v = sqrtf( e / 25.0) / vfermi;

    if( v >= 1.0 )
      vr = v * vfermi * ( 1.0 + 1.0 / ( 5.0 * v*v ) );
    else
      vr = ( 3.0 * vfermi / 4.0 ) * ( 1.0 + ( 2.0 * v*v / 3.0 ) - pow( v, 4.0 ) / 15.0 );

    yr = fmax( yrmin, vr / pow(fz1,0.6667) );
    yr = fmax( yr, vrmin / pow(fz1,0.6667) );
    a = -0.803 * pow( yr, 0.3 ) + 1.3167 * pow( yr, 0.6 ) + 0.38157 * yr +  0.008983 * yr*yr;

    // ionization level of the ion at velocity yr
    q = fmin( 1.0, fmax( 0.0, 1.0 - exp( -fmin( a, 50.0 ) ) ) );

    b = ( fmin( 0.43, fmax( 0.32, 0.12 + 0.025 * fz1 ) ) ) / pow( fz1, 0.3333 );
    l0 = ( 0.8 - q * fmin( 1.2, 0.6 + fz1 / 30.0) ) / pow( fz1, 0.3333 );
    if( q < 0.2 )
      l1 = 0.0;
    else if( q < fmax( 0.0, 0.9 - 0.025 * fz1 ) )
    {//210
      q1 = 0.2;
      l1 = b * ( q - 0.2 ) / fabs( fmax( 0.0, 0.9 - 0.025 * fz1 ) - 0.2000001 );
    }
    else if( q < fmax( 0.0, 1.0 - 0.025 * fmin( 16.0, fz1 ) ) )
      l1 = b;
    else
      l1 = b * ( 1.0 - q ) / ( 0.025 * fmin( 16.0, fz1 ) );

    l = fmax( l1, l0 * lfctr );
    zeta = q + ( 1.0 / ( 2.0 * vfermi*vfermi ) ) * ( 1.0 - q ) * logf( 1.0 + sqr( 4.0 * l * vfermi / 1.919  ) );

    // add z1^3 effect
    a = -sqr( 7.6 - fmax( 0.0, logf( e ) ) );
    zeta *= 1.0 + ( 1.0 / (fz1*fz1) ) * ( 0.18 + 0.0015 * fz2 ) * expf( a );

    if( yr <= fmax( yrmin, vrmin / pow( fz1, 0.6667 ) ) )
    {
      // calculate velocity stopping for  yr < yrmin
      vrmin = fmax( vrmin, yrmin * pow( fz1, 0.6667 ) );
      vmin = 0.5 * ( vrmin + sqrtf( fmax( 0.0, vrmin*vrmin - 0.8 * vfermi*vfermi ) ) );
      eee = 25.0 * vmin*vmin;
      sp = rpstop( z2, eee );

      if( z2 == 6 || ( ( z2 == 14 || z2 == 32 ) && z1 <= 19 ) )
        power = 0.375;
      else
        power = 0.5;

      se = sp * sqr( zeta * fz1 ) * pow( e/eee, power );
    }
    else
    {
      sp = rpstop( z2, e );
      se = sp * sqr( zeta * fz1 );
    }
  } // END: heavy-ions

  return se * 10.0;
}
<|endoftext|>


<commit_before>#include "SingleElimination.hpp"

std::vector<std::shared_ptr<lionheart::Player>> lionheart::SingleElimination::run()
{
  std::vector<std::shared_ptr<Player>> winners;
  auto fortMap = lionheart::makeMap("forts.in");
  auto infantryPaths = std::make_shared<lionheart::Paths>(fortMap, 1);
  auto mountedPaths = std::make_shared<lionheart::Paths>(fortMap, 5);
  auto round = 0;
  while (players.size() > 1)
  {
    winners.clear();
    while (players.size() > 1)
    {
      auto p1 = players.back();
      players.pop_back();
      auto p2 = players.back();
      players.pop_back();

      lionheart::Game game(p1, p2, fortMap, infantryPaths, mountedPaths);
      game.start();

      std::cout << p1->getBlazon().name << " vs. " << p2->getBlazon().name
                << ": ";
      if (display) {
        display->setOutput(std::string("se") + p1->getBlazon().name + "-" +
                           p2->getBlazon().name);

        display->show(game.getReport(), p1->getBlazon(), p2->getBlazon());
      }
      for (auto i = 0; i < 200; ++i)
      {
        game.doTurn(nullptr);
        if (display) {
          display->show(game.getReport(), p1->getBlazon(), p2->getBlazon());
        }
        if (!game.canContinue()) break;
      }
      auto winner = game.winner();
      if (winner) {
        winners.push_back(winner);
        std::cout << winner->getBlazon().name << " wins!" << std::endl;
      }
      else
      {
        auto tie = game.tiebreaker();
        if (tie) {
        std::cout << winner->getBlazon().name << " wins by tie break!" << std::endl;
          winners.push_back(tie);
        }
        else
        {
          winners.push_back(p1);
          std::cout << p1->getBlazon().name << " moves on." << std::endl;
        }
      }
    }

    std::swap(players, winners);
    ++round;
    std::cout << "Single Elimination Round " << round << std::endl;
    for(auto&& p:players)
    {
      std::cout << "     " << p->getBlazon().name << std::endl;
    }
  }
  return players;
}
<commit_msg>Fix null pointer error on tie with tiebreaks<commit_after>#include "SingleElimination.hpp"

std::vector<std::shared_ptr<lionheart::Player>> lionheart::SingleElimination::run()
{
  std::vector<std::shared_ptr<Player>> winners;
  auto fortMap = lionheart::makeMap("forts.in");
  auto infantryPaths = std::make_shared<lionheart::Paths>(fortMap, 1);
  auto mountedPaths = std::make_shared<lionheart::Paths>(fortMap, 5);
  auto round = 0;
  while (players.size() > 1)
  {
    winners.clear();
    while (players.size() > 1)
    {
      auto p1 = players.back();
      players.pop_back();
      auto p2 = players.back();
      players.pop_back();

      lionheart::Game game(p1, p2, fortMap, infantryPaths, mountedPaths);
      game.start();

      std::cout << p1->getBlazon().name << " vs. " << p2->getBlazon().name
                << ": ";
      if (display) {
        display->setOutput(std::string("se") + p1->getBlazon().name + "-" +
                           p2->getBlazon().name);

        display->show(game.getReport(), p1->getBlazon(), p2->getBlazon());
      }
      for (auto i = 0; i < 200; ++i)
      {
        game.doTurn(nullptr);
        if (display) {
          display->show(game.getReport(), p1->getBlazon(), p2->getBlazon());
        }
        if (!game.canContinue()) break;
      }
      auto winner = game.winner();
      if (winner) {
        winners.push_back(winner);
        std::cout << winner->getBlazon().name << " wins!" << std::endl;
      }
      else
      {
        auto tie = game.tiebreaker();
        if (tie) {
        std::cout << tie->getBlazon().name << " wins by tie break!" << std::endl;
          winners.push_back(tie);
        }
        else
        {
          winners.push_back(p1);
          std::cout << p1->getBlazon().name << " moves on." << std::endl;
        }
      }
    }

    std::swap(players, winners);
    ++round;
    std::cout << "Single Elimination Round " << round << std::endl;
    for(auto&& p:players)
    {
      std::cout << "     " << p->getBlazon().name << std::endl;
    }
  }
  return players;
}
<|endoftext|>


<commit_before><commit_msg>08/07/2017<commit_after><|endoftext|>


<commit_before>/****************************************************************
 * Copyright (c) 2014, The Pennsylvania State University
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms,
 * with or without modification, are permitted for
 * personal and commercial purposes provided that the
 * following conditions are met:
 *
 * 1. Redistribution of source code must retain the
 *    above copyright notice, this list of conditions
 *    and the following Disclaimer.
 *
 * 2. Redistribution in binary form must reproduce the
 *    above copyright notice, this list of conditions
 *    and the following disclaimer
 *
 * 3. Neither the name of The Pennsylvania State University
 *    nor the names of its contributors may be used to
 *    endorse or promote products derived from this software
 *    without the specific prior written permission of The
 *    Pennsylvania State University
 *
 * THIS SOFTWARE IS PROVIDED BY THE PENNSYLVANIA STATE UNIVERSITY
 * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT OF
 * INTELLECTUAL PROPERTY ARE EXPRESSLY DISCLAIMED. IN NO EVENT
 * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGE.
 ****************************************************************/

#include "filepath.h"
#include "functions.h"
#include "gtest/gtest.h"
#include <string>
#include <fstream>
//This is to put a delay in the test...hopefully
#include <unistd.h>

#ifdef _MSC_VER
#define UNLINK _unlink
#else
#define UNLINK unlink
#endif

TEST(FilePathTests, Directory)
{
    std::string testString;
#ifdef _WIN32
    testString = "C:\\Windows";
#else
    testString = "/usr";
#endif
    stadic::FilePath dir(testString);
    EXPECT_TRUE(dir.exists());
    EXPECT_TRUE(dir.isDir());
    EXPECT_FALSE(dir.isFile());
    EXPECT_FALSE(dir.isUpdated());

#ifdef _WIN32
    testString = "C:\\Windows\\";
#else
    testString = "/usr/";
#endif
    stadic::FilePath dir1(testString);
    EXPECT_TRUE(dir1.exists());
    EXPECT_TRUE(dir1.isDir());
    EXPECT_FALSE(dir1.isFile());
    EXPECT_FALSE(dir1.isUpdated());

    stadic::FilePath dir2("DOESNOTEXIST");
    EXPECT_FALSE(dir2.exists());
}

TEST(FilePathTests, File)
{
    std::string testString = "testfile.txt";
    UNLINK(testString.c_str());

    stadic::FilePath file(testString);
    EXPECT_FALSE(file.exists());

    std::ofstream testOut(testString);
    testOut << "This is a test file";
    testOut.close();

    EXPECT_TRUE(file.exists());
    EXPECT_TRUE(file.isFile());
    EXPECT_FALSE(file.isDir());
    EXPECT_FALSE(file.isUpdated());
    sleep(3);
    //There may need to be a delay inserted here so the updated time actually changes
    std::ofstream reWrite(testString);
    reWrite << "I'm doing this as hard as I can";
    reWrite.close();

    EXPECT_TRUE(file.exists());
    EXPECT_TRUE(file.isFile());
    EXPECT_FALSE(file.isDir());
    EXPECT_TRUE(file.isUpdated());

}
<commit_msg>Reduced delay in filepathtest to 1 second from 3<commit_after>/****************************************************************
 * Copyright (c) 2014, The Pennsylvania State University
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms,
 * with or without modification, are permitted for
 * personal and commercial purposes provided that the
 * following conditions are met:
 *
 * 1. Redistribution of source code must retain the
 *    above copyright notice, this list of conditions
 *    and the following Disclaimer.
 *
 * 2. Redistribution in binary form must reproduce the
 *    above copyright notice, this list of conditions
 *    and the following disclaimer
 *
 * 3. Neither the name of The Pennsylvania State University
 *    nor the names of its contributors may be used to
 *    endorse or promote products derived from this software
 *    without the specific prior written permission of The
 *    Pennsylvania State University
 *
 * THIS SOFTWARE IS PROVIDED BY THE PENNSYLVANIA STATE UNIVERSITY
 * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT OF
 * INTELLECTUAL PROPERTY ARE EXPRESSLY DISCLAIMED. IN NO EVENT
 * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGE.
 ****************************************************************/

#include "filepath.h"
#include "functions.h"
#include "gtest/gtest.h"
#include <string>
#include <fstream>
//This is to put a delay in the test...hopefully
#include <unistd.h>

#ifdef _MSC_VER
#define UNLINK _unlink
#else
#define UNLINK unlink
#endif

TEST(FilePathTests, Directory)
{
    std::string testString;
#ifdef _WIN32
    testString = "C:\\Windows";
#else
    testString = "/usr";
#endif
    stadic::FilePath dir(testString);
    EXPECT_TRUE(dir.exists());
    EXPECT_TRUE(dir.isDir());
    EXPECT_FALSE(dir.isFile());
    EXPECT_FALSE(dir.isUpdated());

#ifdef _WIN32
    testString = "C:\\Windows\\";
#else
    testString = "/usr/";
#endif
    stadic::FilePath dir1(testString);
    EXPECT_TRUE(dir1.exists());
    EXPECT_TRUE(dir1.isDir());
    EXPECT_FALSE(dir1.isFile());
    EXPECT_FALSE(dir1.isUpdated());

    stadic::FilePath dir2("DOESNOTEXIST");
    EXPECT_FALSE(dir2.exists());
}

TEST(FilePathTests, File)
{
    std::string testString = "testfile.txt";
    UNLINK(testString.c_str());

    stadic::FilePath file(testString);
    EXPECT_FALSE(file.exists());

    std::ofstream testOut(testString);
    testOut << "This is a test file";
    testOut.close();

    EXPECT_TRUE(file.exists());
    EXPECT_TRUE(file.isFile());
    EXPECT_FALSE(file.isDir());
    EXPECT_FALSE(file.isUpdated());
    sleep(1);
    //There may need to be a delay inserted here so the updated time actually changes
    std::ofstream reWrite(testString);
    reWrite << "I'm doing this as hard as I can";
    reWrite.close();

    EXPECT_TRUE(file.exists());
    EXPECT_TRUE(file.isFile());
    EXPECT_FALSE(file.isDir());
    EXPECT_TRUE(file.isUpdated());

}
<|endoftext|>


<commit_before>#include "svgpath.h"
#include "svgutils.h"
#include "graphicscontext.h"

SvgPath::SvgPath(const std::string &str)
{
	setPath(str);
}

void SvgPath::setPath(const std::string &str)
{
	data.commands.clear();
	data.coords.clear();

	ok = true;
	lastError = "";

	if (str.empty())
	{
		ok = false;
		return;
	}

	pathString = str;

	auto it = str.begin();

	try
	{
		SvgUtils::readSvgPath(it, str.end(), std::back_inserter(data.commands), std::back_inserter(data.coords));
	}
	catch (std::exception &e)
	{
		lastError = e.what();
		ok = false;
	}
}

const std::string &SvgPath::getPath() const
{
	return pathString;
}

const SvgPath::PathData &SvgPath::getPathData() const
{
	return data;
}

bool SvgPath::isOk() const
{
	return ok;
}

std::string SvgPath::getLastError() const
{
	return lastError;
}

void SvgPath::draw(GraphicsContext *g) const
{
	if (!ok) return;

	std::vector<PathElement>::const_iterator commandIt = data.commands.begin();
	std::vector<double>::const_iterator coordsIt = data.coords.begin();

	PathElement prevCommand = PathElement::ClosePath;
	double x = 0, y = 0;
	double x1 = 0, y1 = 0;
	double x2 = 0, y2 = 0;
	double cx = 0, cy = 0;
	double prevX = 0, prevY = 0;
	double prevX1 = 0, prevY1 = 0;
	double prevX2 = 0, prevY2 = 0;

	while (commandIt != data.commands.end())
	{
		if (*commandIt == PathElement::MoveTo ||
			*commandIt == PathElement::MoveToRel ||
			*commandIt == PathElement::LineTo ||
			*commandIt == PathElement::LineToRel)
		{
			x = *(coordsIt + 0);
			y = *(coordsIt + 1);

			std::advance(coordsIt, 2);
		}
		else if (*commandIt == PathElement::LineToHorizontal || *commandIt == PathElement::LineToHorizontalRel)
		{
			x = *coordsIt;
			coordsIt++;
		}
		else if(*commandIt == PathElement::LineToVertical || *commandIt == PathElement::LineToVerticalRel)
		{
			y = *coordsIt;
			coordsIt++;
		}
		else if(*commandIt == PathElement::CurveToCubic || *commandIt == PathElement::CurveToCubicRel)
		{
			x1 = *(coordsIt + 0);
			y1 = *(coordsIt + 1);
			x2 = *(coordsIt + 2);
			y2 = *(coordsIt + 3);
			x = *(coordsIt + 4);
			y = *(coordsIt + 5);

			std::advance(coordsIt, 6);
		}
		else if(*commandIt == PathElement::CurveToCubicSmooth || *commandIt == PathElement::CurveToCubicSmoothRel)
		{
			x2 = *(coordsIt + 0);
			y2 = *(coordsIt + 1);
			x = *(coordsIt + 2);
			y = *(coordsIt + 3);

			std::advance(coordsIt, 4);
		}
		else if(*commandIt == PathElement::CurveToQuadratic || *commandIt == PathElement::CurveToQuadraticRel)
		{
			x1 = *(coordsIt + 0);
			y1 = *(coordsIt + 1);
			x = *(coordsIt + 2);
			y = *(coordsIt + 3);

			std::advance(coordsIt, 4);
		}
		else if(*commandIt == PathElement::CurveToQuadraticSmooth || *commandIt == PathElement::CurveToQuadraticSmoothRel)
		{
			x = *(coordsIt + 0);
			y = *(coordsIt + 1);

			std::advance(coordsIt, 2);
		}

		g->getCurrentPoint(cx, cy);

		if (*commandIt == PathElement::MoveTo || *commandIt == PathElement::MoveToRel)
		{
			if (prevCommand != PathElement::ClosePath && std::distance(commandIt, data.commands.begin()) != 0)
				g->closePath();

			if (SvgUtils::isCommandRelative(*commandIt))
			{
				x += cx;
				y += cy;
			}

			g->moveTo(x, y);
		}
		else if (*commandIt == PathElement::LineTo || *commandIt == PathElement::LineToRel)
		{
			if (SvgUtils::isCommandRelative(*commandIt))
			{
				x += cx;
				y += cy;
			}

			g->lineTo(x, y);
		}
		else if (*commandIt == PathElement::LineToHorizontal || *commandIt == PathElement::LineToHorizontalRel)
		{
			if (SvgUtils::isCommandRelative(*commandIt))
				x += cx;

			g->lineTo(x, cy);
		}
		else if (*commandIt == PathElement::LineToVertical || *commandIt == PathElement::LineToVerticalRel)
		{
			if (SvgUtils::isCommandRelative(*commandIt))
				y += cy;

			g->lineTo(cx, y);
		}
		else if (*commandIt == PathElement::CurveToCubic || *commandIt == PathElement::CurveToCubicRel)
		{
			if (SvgUtils::isCommandRelative(*commandIt))
			{
				x += cx;
				y += cy;
				x1 += cx;
				y1 += cy;
				x2 += cx;
				y2 += cy;
			}

			g->curveTo(x1, y1, x2, y2, x, y);
		}
		else if (*commandIt == PathElement::CurveToCubicSmooth || *commandIt == PathElement::CurveToCubicSmoothRel)
		{
			if (SvgUtils::isCurveToCubic(prevCommand))
			{
				x1 = 2 * prevX - prevX2;
				y1 = 2 * prevY - prevY2;
			}
			else
			{
				x1 = cx;
				y1 = cy;
			}

			if (SvgUtils::isCommandRelative(*commandIt))
			{
				x += cx;
				y += cy;
				x2 += cx;
				y2 += cy;
			}

			g->curveTo(x1, y1, x2, y2, x, y);
		}
		else if (*commandIt == PathElement::CurveToQuadratic || *commandIt == PathElement::CurveToQuadraticRel)
		{
			if (SvgUtils::isCommandRelative(*commandIt))
			{
				x += cx;
				y += cy;
				x1 += cx;
				y1 += cy;
			}

			double qx1 = x1;
			double qy1 = y1;

			x1 = cx + 2.0 / 3.0 * (qx1 - cx);
			y1 = cy + 2.0 / 3.0 * (qy1 - cy);

			x2 = x + 2.0 / 3.0 * (qx1 - x);
			y2 = y + 2.0 / 3.0 * (qy1 - y);

			g->curveTo(x1, y1, x2, y2, x, y);

			// restore control point coordinate
			x1 = qx1;
			y1 = qy1;
		}
		else if (*commandIt == PathElement::CurveToQuadraticSmooth || *commandIt == PathElement::CurveToQuadraticSmoothRel)
		{
			if (SvgUtils::isCommandRelative(*commandIt))
			{
				x += cx;
				y += cy;
			}

			if (SvgUtils::isCurveToQuadratic(prevCommand))
			{
				x1 = 2 * prevX - prevX1;
				y1 = 2 * prevY - prevY1;
			}
			else
			{
				x1 = cx;
				y1 = cy;
			}

			double qx1 = x1;
			double qy1 = y1;

			x1 = cx + 2.0 / 3.0 * (qx1 - cx);
			y1 = cy + 2.0 / 3.0 * (qy1 - cy);

			x2 = x + 2.0 / 3.0 * (qx1 - x);
			y2 = y + 2.0 / 3.0 * (qy1 - y);

			g->curveTo(x1, y1, x2, y2, x, y);

			// restore control point coordinate
			x1 = qx1;
			y1 = qy1;
		}
		else if (*commandIt == PathElement::ClosePath)
		{
			g->closePath();
		}

		prevX = x;
		prevY = y;
		prevX1 = x1;
		prevY1 = y1;
		prevX2 = x2;
		prevY2 = y2;
		prevCommand = *commandIt++;
	}
}<commit_msg>don't explicit close path for moveTo command<commit_after>#include "svgpath.h"
#include "svgutils.h"
#include "graphicscontext.h"

SvgPath::SvgPath(const std::string &str)
{
	setPath(str);
}

void SvgPath::setPath(const std::string &str)
{
	data.commands.clear();
	data.coords.clear();

	ok = true;
	lastError = "";

	if (str.empty())
	{
		ok = false;
		return;
	}

	pathString = str;

	auto it = str.begin();

	try
	{
		SvgUtils::readSvgPath(it, str.end(), std::back_inserter(data.commands), std::back_inserter(data.coords));
	}
	catch (std::exception &e)
	{
		lastError = e.what();
		ok = false;
	}
}

const std::string &SvgPath::getPath() const
{
	return pathString;
}

const SvgPath::PathData &SvgPath::getPathData() const
{
	return data;
}

bool SvgPath::isOk() const
{
	return ok;
}

std::string SvgPath::getLastError() const
{
	return lastError;
}

void SvgPath::draw(GraphicsContext *g) const
{
	if (!ok) return;

	std::vector<PathElement>::const_iterator commandIt = data.commands.begin();
	std::vector<double>::const_iterator coordsIt = data.coords.begin();

	PathElement prevCommand = PathElement::ClosePath;
	double x = 0, y = 0;
	double x1 = 0, y1 = 0;
	double x2 = 0, y2 = 0;
	double cx = 0, cy = 0;
	double prevX = 0, prevY = 0;
	double prevX1 = 0, prevY1 = 0;
	double prevX2 = 0, prevY2 = 0;

	while (commandIt != data.commands.end())
	{
		if (*commandIt == PathElement::MoveTo ||
			*commandIt == PathElement::MoveToRel ||
			*commandIt == PathElement::LineTo ||
			*commandIt == PathElement::LineToRel)
		{
			x = *(coordsIt + 0);
			y = *(coordsIt + 1);

			std::advance(coordsIt, 2);
		}
		else if (*commandIt == PathElement::LineToHorizontal || *commandIt == PathElement::LineToHorizontalRel)
		{
			x = *coordsIt;
			coordsIt++;
		}
		else if(*commandIt == PathElement::LineToVertical || *commandIt == PathElement::LineToVerticalRel)
		{
			y = *coordsIt;
			coordsIt++;
		}
		else if(*commandIt == PathElement::CurveToCubic || *commandIt == PathElement::CurveToCubicRel)
		{
			x1 = *(coordsIt + 0);
			y1 = *(coordsIt + 1);
			x2 = *(coordsIt + 2);
			y2 = *(coordsIt + 3);
			x = *(coordsIt + 4);
			y = *(coordsIt + 5);

			std::advance(coordsIt, 6);
		}
		else if(*commandIt == PathElement::CurveToCubicSmooth || *commandIt == PathElement::CurveToCubicSmoothRel)
		{
			x2 = *(coordsIt + 0);
			y2 = *(coordsIt + 1);
			x = *(coordsIt + 2);
			y = *(coordsIt + 3);

			std::advance(coordsIt, 4);
		}
		else if(*commandIt == PathElement::CurveToQuadratic || *commandIt == PathElement::CurveToQuadraticRel)
		{
			x1 = *(coordsIt + 0);
			y1 = *(coordsIt + 1);
			x = *(coordsIt + 2);
			y = *(coordsIt + 3);

			std::advance(coordsIt, 4);
		}
		else if(*commandIt == PathElement::CurveToQuadraticSmooth || *commandIt == PathElement::CurveToQuadraticSmoothRel)
		{
			x = *(coordsIt + 0);
			y = *(coordsIt + 1);

			std::advance(coordsIt, 2);
		}

		g->getCurrentPoint(cx, cy);

		if (*commandIt == PathElement::MoveTo || *commandIt == PathElement::MoveToRel)
		{
			if (SvgUtils::isCommandRelative(*commandIt))
			{
				x += cx;
				y += cy;
			}

			g->moveTo(x, y);
		}
		else if (*commandIt == PathElement::LineTo || *commandIt == PathElement::LineToRel)
		{
			if (SvgUtils::isCommandRelative(*commandIt))
			{
				x += cx;
				y += cy;
			}

			g->lineTo(x, y);
		}
		else if (*commandIt == PathElement::LineToHorizontal || *commandIt == PathElement::LineToHorizontalRel)
		{
			if (SvgUtils::isCommandRelative(*commandIt))
				x += cx;

			g->lineTo(x, cy);
		}
		else if (*commandIt == PathElement::LineToVertical || *commandIt == PathElement::LineToVerticalRel)
		{
			if (SvgUtils::isCommandRelative(*commandIt))
				y += cy;

			g->lineTo(cx, y);
		}
		else if (*commandIt == PathElement::CurveToCubic || *commandIt == PathElement::CurveToCubicRel)
		{
			if (SvgUtils::isCommandRelative(*commandIt))
			{
				x += cx;
				y += cy;
				x1 += cx;
				y1 += cy;
				x2 += cx;
				y2 += cy;
			}

			g->curveTo(x1, y1, x2, y2, x, y);
		}
		else if (*commandIt == PathElement::CurveToCubicSmooth || *commandIt == PathElement::CurveToCubicSmoothRel)
		{
			if (SvgUtils::isCurveToCubic(prevCommand))
			{
				x1 = 2 * prevX - prevX2;
				y1 = 2 * prevY - prevY2;
			}
			else
			{
				x1 = cx;
				y1 = cy;
			}

			if (SvgUtils::isCommandRelative(*commandIt))
			{
				x += cx;
				y += cy;
				x2 += cx;
				y2 += cy;
			}

			g->curveTo(x1, y1, x2, y2, x, y);
		}
		else if (*commandIt == PathElement::CurveToQuadratic || *commandIt == PathElement::CurveToQuadraticRel)
		{
			if (SvgUtils::isCommandRelative(*commandIt))
			{
				x += cx;
				y += cy;
				x1 += cx;
				y1 += cy;
			}

			double qx1 = x1;
			double qy1 = y1;

			x1 = cx + 2.0 / 3.0 * (qx1 - cx);
			y1 = cy + 2.0 / 3.0 * (qy1 - cy);

			x2 = x + 2.0 / 3.0 * (qx1 - x);
			y2 = y + 2.0 / 3.0 * (qy1 - y);

			g->curveTo(x1, y1, x2, y2, x, y);

			// restore control point coordinate
			x1 = qx1;
			y1 = qy1;
		}
		else if (*commandIt == PathElement::CurveToQuadraticSmooth || *commandIt == PathElement::CurveToQuadraticSmoothRel)
		{
			if (SvgUtils::isCommandRelative(*commandIt))
			{
				x += cx;
				y += cy;
			}

			if (SvgUtils::isCurveToQuadratic(prevCommand))
			{
				x1 = 2 * prevX - prevX1;
				y1 = 2 * prevY - prevY1;
			}
			else
			{
				x1 = cx;
				y1 = cy;
			}

			double qx1 = x1;
			double qy1 = y1;

			x1 = cx + 2.0 / 3.0 * (qx1 - cx);
			y1 = cy + 2.0 / 3.0 * (qy1 - cy);

			x2 = x + 2.0 / 3.0 * (qx1 - x);
			y2 = y + 2.0 / 3.0 * (qy1 - y);

			g->curveTo(x1, y1, x2, y2, x, y);

			// restore control point coordinate
			x1 = qx1;
			y1 = qy1;
		}
		else if (*commandIt == PathElement::ClosePath)
		{
			g->closePath();
		}

		prevX = x;
		prevY = y;
		prevX1 = x1;
		prevY1 = y1;
		prevX2 = x2;
		prevY2 = y2;
		prevCommand = *commandIt++;
	}
}<|endoftext|>


<commit_before>#include <iostream>
#include <chrono>

#include <infra/config/config.h>

#include <mips/mips_memory.h>
#include <mips/mips_rf.h>

#include "perf_sim.h"

static const uint32 PORT_LATENCY = 1;
static const uint32 PORT_FANOUT = 1;
static const uint32 PORT_BW = 1;
static const uint32 FLUSHED_STAGES_NUM = 4;

namespace config {
    static Value<std::string> bp_mode = { "bp-mode", "dynamic_two_bit", "branch prediction mode"};
    static Value<uint32> bp_size = { "bp-size", 128, "BTB size in entries"};
    static Value<uint32> bp_ways = { "bp-ways", 16, "number of ways in BTB"};
} // namespace config

PerfMIPS::PerfMIPS(bool log) : Log( log), rf( new RF), checker( false)
{
    executed_instrs = 0;

    wp_fetch_2_decode = make_write_port<IfIdData>("FETCH_2_DECODE", PORT_BW, PORT_FANOUT);
    rp_fetch_2_decode = make_read_port<IfIdData>("FETCH_2_DECODE", PORT_LATENCY);
    wp_decode_2_fetch_stall = make_write_port<bool>("DECODE_2_FETCH_STALL", PORT_BW, PORT_FANOUT);
    rp_decode_2_fetch_stall = make_read_port<bool>("DECODE_2_FETCH_STALL", PORT_LATENCY);

    wp_decode_2_decode = make_write_port<FuncInstr>("DECODE_2_DECODE", PORT_BW, PORT_FANOUT);
    rp_decode_2_decode = make_read_port<FuncInstr>("DECODE_2_DECODE", PORT_LATENCY);

    wp_decode_2_execute = make_write_port<FuncInstr>("DECODE_2_EXECUTE", PORT_BW, PORT_FANOUT);
    rp_decode_2_execute = make_read_port<FuncInstr>("DECODE_2_EXECUTE", PORT_LATENCY);

    wp_execute_2_memory = make_write_port<FuncInstr>("EXECUTE_2_MEMORY", PORT_BW, PORT_FANOUT);
    rp_execute_2_memory = make_read_port<FuncInstr>("EXECUTE_2_MEMORY", PORT_LATENCY);

    wp_memory_2_writeback = make_write_port<FuncInstr>("MEMORY_2_WRITEBACK", PORT_BW, PORT_FANOUT);
    rp_memory_2_writeback = make_read_port<FuncInstr>("MEMORY_2_WRITEBACK", PORT_LATENCY);

    /* branch misprediction unit ports */
    wp_memory_2_all_flush = make_write_port<bool>("MEMORY_2_ALL_FLUSH", PORT_BW, FLUSHED_STAGES_NUM);
    rp_fetch_flush = make_read_port<bool>("MEMORY_2_ALL_FLUSH", PORT_LATENCY);
    rp_decode_flush = make_read_port<bool>("MEMORY_2_ALL_FLUSH", PORT_LATENCY);
    rp_execute_flush = make_read_port<bool>("MEMORY_2_ALL_FLUSH", PORT_LATENCY);
    rp_memory_flush = make_read_port<bool>("MEMORY_2_ALL_FLUSH", PORT_LATENCY);

    wp_memory_2_fetch_target = make_write_port<Addr>("MEMORY_2_FETCH_TARGET", PORT_BW, PORT_FANOUT);
    rp_memory_2_fetch_target = make_read_port<Addr>("MEMORY_2_FETCH_TARGET", PORT_LATENCY);

    BPFactory bp_factory;
    bp = bp_factory.create( config::bp_mode, config::bp_size, config::bp_ways);

    init_ports();
}

FuncInstr PerfMIPS::read_instr(uint64 cycle)
{
    if (rp_decode_2_decode->is_ready( cycle))
    {
        rp_fetch_2_decode->ignore( cycle);
        return rp_decode_2_decode->read( cycle);
    }
    const auto& _data = rp_fetch_2_decode->read( cycle);
    FuncInstr instr( _data.raw,
        _data.PC,
        _data.predicted_taken,
        _data.predicted_target);
    return instr;

}

void PerfMIPS::run( const std::string& tr,
                    uint64 instrs_to_run)
{
    assert( instrs_to_run < MAX_VAL32);
    Cycles cycle = 0;

    memory = new MIPSMemory( tr);

    checker.init( tr);

    new_PC = memory->startPC();

    auto t_start = std::chrono::high_resolution_clock::now();

    while (executed_instrs < instrs_to_run)
    {
        clock_writeback( cycle);
        clock_fetch( cycle);
        clock_decode( cycle);
        clock_execute( cycle);
        clock_memory( cycle);
        ++cycle;

        sout << "Executed instructions: " << executed_instrs
             << std::endl << std::endl;

        check_ports( cycle);
    }

    auto t_end = std::chrono::high_resolution_clock::now();

    auto time = std::chrono::duration<double, std::milli>(t_end - t_start).count();
    auto frequency = cycle / time; // cycles per millisecond = kHz
    auto ipc = 1.0 * executed_instrs / cycle;
    auto simips = executed_instrs / time;

    std::cout << std::endl << "****************************"
              << std::endl << "instrs:   " << executed_instrs
              << std::endl << "cycles:   " << cycle
              << std::endl << "IPC:      " << ipc
              << std::endl << "sim freq: " << frequency << " kHz"
              << std::endl << "sim IPS:  " << simips    << " kips"
              << std::endl << "****************************"
              << std::endl;
}

void PerfMIPS::clock_fetch( int cycle)
{
    /* receive flush and stall signals */
    const bool is_flush = rp_fetch_flush->is_ready( cycle) && rp_fetch_flush->read( cycle);
    const bool is_stall = rp_decode_2_fetch_stall->is_ready( cycle) && rp_decode_2_fetch_stall->read( cycle);

    /* updating PC */
    if ( is_flush)
        PC = rp_memory_2_fetch_target->read( cycle); // fixing PC
    else if ( !is_stall)
        PC = new_PC;

    /* creating structure to be sent to decode stage */
    IfIdData data;

    /* fetching instruction */
    data.raw = memory->fetch( PC);

    /* saving predictions and updating PC according to them */
    data.PC = PC;
    data.predicted_taken = bp->is_taken( PC);
    data.predicted_target = bp->get_target( PC);

    /* updating PC according to prediction */
    new_PC = data.predicted_target;

    /* sending to decode */
    wp_fetch_2_decode->write( data, cycle);

    /* log */
    sout << "fetch   cycle " << std::dec << cycle << ": 0x"
         << std::hex << PC << ": 0x" << data.raw << std::endl;
}

void PerfMIPS::clock_decode( int cycle)
{
    sout << "decode  cycle " << std::dec << cycle << ": ";

    /* receive flush signal */
    const bool is_flush = rp_decode_flush->is_ready( cycle) && rp_decode_flush->read( cycle);

    /* branch misprediction */
    if ( is_flush)
    {
        /* ignoring the upcoming instruction as it is invalid */
        rp_fetch_2_decode->ignore( cycle);
        rp_decode_2_decode->ignore( cycle);

        sout << "flush\n";
        return;
    }
    /* check if there is something to process */
    if ( !rp_fetch_2_decode->is_ready( cycle) && !rp_decode_2_decode->is_ready( cycle))
    {
        sout << "bubble\n";
        return;
    }

    auto instr = read_instr( cycle);

    /* TODO: replace all this code by introducing Forwarding unit */
    if( rf->check_sources( instr))
    {
        rf->read_sources( &instr);

        wp_decode_2_execute->write( instr, cycle);

        /* log */
        sout << instr << std::endl;
    }
    else // data hazard, stalling pipeline
    {
        wp_decode_2_fetch_stall->write( true, cycle);
        wp_decode_2_decode->write( instr, cycle);
        sout << instr << " (data hazard)\n";
    }
}

void PerfMIPS::clock_execute( int cycle)
{
    sout << "execute cycle " << std::dec << cycle << ": ";

    /* receive flush signal */
    const bool is_flush = rp_execute_flush->is_ready( cycle) && rp_execute_flush->read( cycle);

    /* branch misprediction */
    if ( is_flush)
    {
        /* ignoring the upcoming instruction as it is invalid */
        if ( rp_decode_2_execute->is_ready( cycle))
        {
            const auto& instr = rp_decode_2_execute->read( cycle);
            rf->cancel( instr);
        }
        sout << "flush\n";
        return;
    }

    /* check if there is something to process */
    if ( !rp_decode_2_execute->is_ready( cycle))
    {
        sout << "bubble\n";
        return;
    }

    auto instr = rp_decode_2_execute->read( cycle);

    /* preform execution */
    instr.execute();

    wp_execute_2_memory->write( instr, cycle);

    /* log */
    sout << instr << std::endl;
}

void PerfMIPS::clock_memory( int cycle)
{
    sout << "memory  cycle " << std::dec << cycle << ": ";

    /* receieve flush signal */
    const bool is_flush = rp_memory_flush->is_ready( cycle) && rp_memory_flush->read( cycle);

    /* branch misprediction */
    if ( is_flush)
    {
        /* drop instruction as it is invalid */
        if ( rp_execute_2_memory->is_ready( cycle))
        {
            const auto& instr = rp_execute_2_memory->read( cycle);
            rf->cancel( instr);
        }
        sout << "flush\n";
        return;
    }

    /* check if there is something to process */
    if ( !rp_execute_2_memory->is_ready( cycle))
    {
        sout << "bubble\n";
        return;
    }

    auto instr = rp_execute_2_memory->read( cycle);

    if (instr.is_jump()) {
        /* acquiring real information for BPU */
        bool actually_taken = instr.is_jump_taken();
        Addr real_target = instr.get_new_PC();
        bp->update( actually_taken, instr.get_PC(), real_target);

        /* handle misprediction */
        if ( instr.is_misprediction())
        {
            /* flushing the pipeline */
            wp_memory_2_all_flush->write( true, cycle);

            /* sending valid PC to fetch stage */
            wp_memory_2_fetch_target->write( real_target, cycle);

            sout << "misprediction on ";
        }
    }

    /* perform required loads and stores */
    memory->load_store( &instr);

    wp_memory_2_writeback->write( instr, cycle);

    /* log */
    sout << instr << std::endl;
}

void PerfMIPS::clock_writeback( int cycle)
{
    sout << "wb      cycle " << std::dec << cycle << ": ";

    /* check if there is something to process */
    if ( !rp_memory_2_writeback->is_ready( cycle))
    {
        sout << "bubble\n";
        if ( cycle - last_writeback_cycle >= 10)
        {
            serr << "Deadlock was detected. The process will be aborted."
                 << std::endl << std::endl << critical;
        }
        return;
    }

    FuncInstr instr = rp_memory_2_writeback->read( cycle);

    /* perform writeback */
    rf->write_dst( instr);

    /* check for traps */
    instr.check_trap();

    /* log */
    sout << instr << std::endl;

    /* perform checks */
    check( instr);

    /* update simulator cycles info */
    ++executed_instrs;
    last_writeback_cycle = cycle;
}

void PerfMIPS::check( const FuncInstr& instr)
{
    const auto func_dump = checker.step();

    if ( func_dump.Dump() != instr.Dump())
        serr << "****************************" << std::endl
             << "Mismatch: " << std::endl
             << "Checker output: " << func_dump    << std::endl
             << "PerfSim output: " << instr.Dump() << std::endl
             << critical;
}

<commit_msg>Dump sizeof(FuncInstr) in PerfSim<commit_after>#include <iostream>
#include <chrono>

#include <infra/config/config.h>

#include <mips/mips_memory.h>
#include <mips/mips_rf.h>

#include "perf_sim.h"

static const uint32 PORT_LATENCY = 1;
static const uint32 PORT_FANOUT = 1;
static const uint32 PORT_BW = 1;
static const uint32 FLUSHED_STAGES_NUM = 4;

namespace config {
    static Value<std::string> bp_mode = { "bp-mode", "dynamic_two_bit", "branch prediction mode"};
    static Value<uint32> bp_size = { "bp-size", 128, "BTB size in entries"};
    static Value<uint32> bp_ways = { "bp-ways", 16, "number of ways in BTB"};
} // namespace config

PerfMIPS::PerfMIPS(bool log) : Log( log), rf( new RF), checker( false)
{
    executed_instrs = 0;

    wp_fetch_2_decode = make_write_port<IfIdData>("FETCH_2_DECODE", PORT_BW, PORT_FANOUT);
    rp_fetch_2_decode = make_read_port<IfIdData>("FETCH_2_DECODE", PORT_LATENCY);
    wp_decode_2_fetch_stall = make_write_port<bool>("DECODE_2_FETCH_STALL", PORT_BW, PORT_FANOUT);
    rp_decode_2_fetch_stall = make_read_port<bool>("DECODE_2_FETCH_STALL", PORT_LATENCY);

    wp_decode_2_decode = make_write_port<FuncInstr>("DECODE_2_DECODE", PORT_BW, PORT_FANOUT);
    rp_decode_2_decode = make_read_port<FuncInstr>("DECODE_2_DECODE", PORT_LATENCY);

    wp_decode_2_execute = make_write_port<FuncInstr>("DECODE_2_EXECUTE", PORT_BW, PORT_FANOUT);
    rp_decode_2_execute = make_read_port<FuncInstr>("DECODE_2_EXECUTE", PORT_LATENCY);

    wp_execute_2_memory = make_write_port<FuncInstr>("EXECUTE_2_MEMORY", PORT_BW, PORT_FANOUT);
    rp_execute_2_memory = make_read_port<FuncInstr>("EXECUTE_2_MEMORY", PORT_LATENCY);

    wp_memory_2_writeback = make_write_port<FuncInstr>("MEMORY_2_WRITEBACK", PORT_BW, PORT_FANOUT);
    rp_memory_2_writeback = make_read_port<FuncInstr>("MEMORY_2_WRITEBACK", PORT_LATENCY);

    /* branch misprediction unit ports */
    wp_memory_2_all_flush = make_write_port<bool>("MEMORY_2_ALL_FLUSH", PORT_BW, FLUSHED_STAGES_NUM);
    rp_fetch_flush = make_read_port<bool>("MEMORY_2_ALL_FLUSH", PORT_LATENCY);
    rp_decode_flush = make_read_port<bool>("MEMORY_2_ALL_FLUSH", PORT_LATENCY);
    rp_execute_flush = make_read_port<bool>("MEMORY_2_ALL_FLUSH", PORT_LATENCY);
    rp_memory_flush = make_read_port<bool>("MEMORY_2_ALL_FLUSH", PORT_LATENCY);

    wp_memory_2_fetch_target = make_write_port<Addr>("MEMORY_2_FETCH_TARGET", PORT_BW, PORT_FANOUT);
    rp_memory_2_fetch_target = make_read_port<Addr>("MEMORY_2_FETCH_TARGET", PORT_LATENCY);

    BPFactory bp_factory;
    bp = bp_factory.create( config::bp_mode, config::bp_size, config::bp_ways);

    init_ports();
}

FuncInstr PerfMIPS::read_instr(uint64 cycle)
{
    if (rp_decode_2_decode->is_ready( cycle))
    {
        rp_fetch_2_decode->ignore( cycle);
        return rp_decode_2_decode->read( cycle);
    }
    const auto& _data = rp_fetch_2_decode->read( cycle);
    FuncInstr instr( _data.raw,
        _data.PC,
        _data.predicted_taken,
        _data.predicted_target);
    return instr;

}

void PerfMIPS::run( const std::string& tr,
                    uint64 instrs_to_run)
{
    assert( instrs_to_run < MAX_VAL32);
    Cycles cycle = 0;

    memory = new MIPSMemory( tr);

    checker.init( tr);

    new_PC = memory->startPC();

    auto t_start = std::chrono::high_resolution_clock::now();

    while (executed_instrs < instrs_to_run)
    {
        clock_writeback( cycle);
        clock_fetch( cycle);
        clock_decode( cycle);
        clock_execute( cycle);
        clock_memory( cycle);
        ++cycle;

        sout << "Executed instructions: " << executed_instrs
             << std::endl << std::endl;

        check_ports( cycle);
    }

    auto t_end = std::chrono::high_resolution_clock::now();

    auto time = std::chrono::duration<double, std::milli>(t_end - t_start).count();
    auto frequency = cycle / time; // cycles per millisecond = kHz
    auto ipc = 1.0 * executed_instrs / cycle;
    auto simips = executed_instrs / time;

    std::cout << std::endl << "****************************"
              << std::endl << "instrs:     " << executed_instrs
              << std::endl << "cycles:     " << cycle
              << std::endl << "IPC:        " << ipc
              << std::endl << "sim freq:   " << frequency << " kHz"
              << std::endl << "sim IPS:    " << simips    << " kips"
              << std::endl << "instr size: " << sizeof(FuncInstr) << " bytes"
              << std::endl << "****************************"
              << std::endl;
}

void PerfMIPS::clock_fetch( int cycle)
{
    /* receive flush and stall signals */
    const bool is_flush = rp_fetch_flush->is_ready( cycle) && rp_fetch_flush->read( cycle);
    const bool is_stall = rp_decode_2_fetch_stall->is_ready( cycle) && rp_decode_2_fetch_stall->read( cycle);

    /* updating PC */
    if ( is_flush)
        PC = rp_memory_2_fetch_target->read( cycle); // fixing PC
    else if ( !is_stall)
        PC = new_PC;

    /* creating structure to be sent to decode stage */
    IfIdData data;

    /* fetching instruction */
    data.raw = memory->fetch( PC);

    /* saving predictions and updating PC according to them */
    data.PC = PC;
    data.predicted_taken = bp->is_taken( PC);
    data.predicted_target = bp->get_target( PC);

    /* updating PC according to prediction */
    new_PC = data.predicted_target;

    /* sending to decode */
    wp_fetch_2_decode->write( data, cycle);

    /* log */
    sout << "fetch   cycle " << std::dec << cycle << ": 0x"
         << std::hex << PC << ": 0x" << data.raw << std::endl;
}

void PerfMIPS::clock_decode( int cycle)
{
    sout << "decode  cycle " << std::dec << cycle << ": ";

    /* receive flush signal */
    const bool is_flush = rp_decode_flush->is_ready( cycle) && rp_decode_flush->read( cycle);

    /* branch misprediction */
    if ( is_flush)
    {
        /* ignoring the upcoming instruction as it is invalid */
        rp_fetch_2_decode->ignore( cycle);
        rp_decode_2_decode->ignore( cycle);

        sout << "flush\n";
        return;
    }
    /* check if there is something to process */
    if ( !rp_fetch_2_decode->is_ready( cycle) && !rp_decode_2_decode->is_ready( cycle))
    {
        sout << "bubble\n";
        return;
    }

    auto instr = read_instr( cycle);

    /* TODO: replace all this code by introducing Forwarding unit */
    if( rf->check_sources( instr))
    {
        rf->read_sources( &instr);

        wp_decode_2_execute->write( instr, cycle);

        /* log */
        sout << instr << std::endl;
    }
    else // data hazard, stalling pipeline
    {
        wp_decode_2_fetch_stall->write( true, cycle);
        wp_decode_2_decode->write( instr, cycle);
        sout << instr << " (data hazard)\n";
    }
}

void PerfMIPS::clock_execute( int cycle)
{
    sout << "execute cycle " << std::dec << cycle << ": ";

    /* receive flush signal */
    const bool is_flush = rp_execute_flush->is_ready( cycle) && rp_execute_flush->read( cycle);

    /* branch misprediction */
    if ( is_flush)
    {
        /* ignoring the upcoming instruction as it is invalid */
        if ( rp_decode_2_execute->is_ready( cycle))
        {
            const auto& instr = rp_decode_2_execute->read( cycle);
            rf->cancel( instr);
        }
        sout << "flush\n";
        return;
    }

    /* check if there is something to process */
    if ( !rp_decode_2_execute->is_ready( cycle))
    {
        sout << "bubble\n";
        return;
    }

    auto instr = rp_decode_2_execute->read( cycle);

    /* preform execution */
    instr.execute();

    wp_execute_2_memory->write( instr, cycle);

    /* log */
    sout << instr << std::endl;
}

void PerfMIPS::clock_memory( int cycle)
{
    sout << "memory  cycle " << std::dec << cycle << ": ";

    /* receieve flush signal */
    const bool is_flush = rp_memory_flush->is_ready( cycle) && rp_memory_flush->read( cycle);

    /* branch misprediction */
    if ( is_flush)
    {
        /* drop instruction as it is invalid */
        if ( rp_execute_2_memory->is_ready( cycle))
        {
            const auto& instr = rp_execute_2_memory->read( cycle);
            rf->cancel( instr);
        }
        sout << "flush\n";
        return;
    }

    /* check if there is something to process */
    if ( !rp_execute_2_memory->is_ready( cycle))
    {
        sout << "bubble\n";
        return;
    }

    auto instr = rp_execute_2_memory->read( cycle);

    if (instr.is_jump()) {
        /* acquiring real information for BPU */
        bool actually_taken = instr.is_jump_taken();
        Addr real_target = instr.get_new_PC();
        bp->update( actually_taken, instr.get_PC(), real_target);

        /* handle misprediction */
        if ( instr.is_misprediction())
        {
            /* flushing the pipeline */
            wp_memory_2_all_flush->write( true, cycle);

            /* sending valid PC to fetch stage */
            wp_memory_2_fetch_target->write( real_target, cycle);

            sout << "misprediction on ";
        }
    }

    /* perform required loads and stores */
    memory->load_store( &instr);

    wp_memory_2_writeback->write( instr, cycle);

    /* log */
    sout << instr << std::endl;
}

void PerfMIPS::clock_writeback( int cycle)
{
    sout << "wb      cycle " << std::dec << cycle << ": ";

    /* check if there is something to process */
    if ( !rp_memory_2_writeback->is_ready( cycle))
    {
        sout << "bubble\n";
        if ( cycle - last_writeback_cycle >= 10)
        {
            serr << "Deadlock was detected. The process will be aborted."
                 << std::endl << std::endl << critical;
        }
        return;
    }

    FuncInstr instr = rp_memory_2_writeback->read( cycle);

    /* perform writeback */
    rf->write_dst( instr);

    /* check for traps */
    instr.check_trap();

    /* log */
    sout << instr << std::endl;

    /* perform checks */
    check( instr);

    /* update simulator cycles info */
    ++executed_instrs;
    last_writeback_cycle = cycle;
}

void PerfMIPS::check( const FuncInstr& instr)
{
    const auto func_dump = checker.step();

    if ( func_dump.Dump() != instr.Dump())
        serr << "****************************" << std::endl
             << "Mismatch: " << std::endl
             << "Checker output: " << func_dump    << std::endl
             << "PerfSim output: " << instr.Dump() << std::endl
             << critical;
}

<|endoftext|>


<commit_before>#include "builtin/data.hpp"
#include "builtin/class.hpp"
#include "objectmemory.hpp"
#include "object_utils.hpp"

#include "gc/gc.hpp"

#include "capi/capi.hpp"

#include "ontology.hpp"

namespace rubinius {

  void Data::init(STATE) {
    GO(data).set(ontology::new_class(state, "Data", G(object)));
    G(data)->set_object_type(state, DataType);
  }

  Data* Data::create(STATE, void* data_ptr, Data::MarkFunctor mark, Data::FreeFunctor free) {
    Data* data;

    data = state->new_object<Data>(G(data));

    // Data is just a heap alias for the handle, so go ahead and create
    // the handle and populate it as an RData now.
    capi::Handle* handle = data->handle(state);

    assert(!handle && "can't already have a handle, it's brand new!");

    handle = state->shared().add_global_handle(state, data);

    // Don't call ->ref() on handle! We don't want the handle to keep the object
    // alive by default. The handle needs to have the lifetime of the object.

    RDataShadow* rdata = reinterpret_cast<RDataShadow*>(handle->as_rdata(0));

    rdata->data = data_ptr;
    rdata->dmark = mark;
    rdata->dfree = free;

    data->internal_ = rdata;
    data->freed_    = false;

    // If this Data requires a free function, register this object
    // as needing finalization.
    if(free) {
      state->memory()->needs_finalization(data, (FinalizerFunction)&Data::finalize);
    }

    return data;
  }

  RDataShadow* Data::slow_rdata(STATE) {
    capi::Handle* handle = this->handle(state);

    assert(handle && handle->is_rdata() && "invalid initialized Data object");

    return reinterpret_cast<RDataShadow*>(handle->as_rdata(0));
  }

  void* Data::data(STATE) {
    return rdata(state)->data;
  }

  Data::FreeFunctor Data::free(STATE) {
    return rdata(state)->dfree;
  }

  Data::MarkFunctor Data::mark(STATE) {
    return rdata(state)->dmark;
  }

  void Data::finalize(STATE, Data* data) {
    // MRI only calls free if the data_ptr is not NULL.
    void* data_ptr = data->data(state);

    if(data_ptr && !data->freed_p()) {
      Data::FreeFunctor f = data->free(state);
      if(f) {
        // If the user specifies -1, then we call free. We check here rather
        // than when Data_Make_Struct is called because the user is allowed to
        // change dfree.
        if(reinterpret_cast<intptr_t>(f) == -1) {
          ::free(data_ptr);
        } else {
          f(data_ptr);
        }
      }
      data->set_freed();
    }
  }

  void Data::Info::mark(Object* t, ObjectMark& mark) {
    auto_mark(t, mark);

    Data* data = force_as<Data>(t);

    if(data->freed_p()) return;

    RDataShadow* rdata = data->rdata();

    if(rdata->dmark) {
      ObjectMark* cur = capi::current_mark();
      capi::set_current_mark(&mark);

      (*rdata->dmark)(rdata->data);

      capi::set_current_mark(cur);
    }
  }

}
<commit_msg>Always enable finalizers for Data objects<commit_after>#include "builtin/data.hpp"
#include "builtin/class.hpp"
#include "objectmemory.hpp"
#include "object_utils.hpp"

#include "gc/gc.hpp"

#include "capi/capi.hpp"

#include "ontology.hpp"

namespace rubinius {

  void Data::init(STATE) {
    GO(data).set(ontology::new_class(state, "Data", G(object)));
    G(data)->set_object_type(state, DataType);
  }

  Data* Data::create(STATE, void* data_ptr, Data::MarkFunctor mark, Data::FreeFunctor free) {
    Data* data;

    data = state->new_object<Data>(G(data));

    // Data is just a heap alias for the handle, so go ahead and create
    // the handle and populate it as an RData now.
    capi::Handle* handle = data->handle(state);

    assert(!handle && "can't already have a handle, it's brand new!");

    handle = state->shared().add_global_handle(state, data);

    // Don't call ->ref() on handle! We don't want the handle to keep the object
    // alive by default. The handle needs to have the lifetime of the object.

    RDataShadow* rdata = reinterpret_cast<RDataShadow*>(handle->as_rdata(0));

    rdata->data = data_ptr;
    rdata->dmark = mark;
    rdata->dfree = free;

    data->internal_ = rdata;
    data->freed_    = false;

    if(mark || free) {
      state->memory()->needs_finalization(data, (FinalizerFunction)&Data::finalize);
    }

    return data;
  }

  RDataShadow* Data::slow_rdata(STATE) {
    capi::Handle* handle = this->handle(state);

    assert(handle && handle->is_rdata() && "invalid initialized Data object");

    return reinterpret_cast<RDataShadow*>(handle->as_rdata(0));
  }

  void* Data::data(STATE) {
    return rdata(state)->data;
  }

  Data::FreeFunctor Data::free(STATE) {
    return rdata(state)->dfree;
  }

  Data::MarkFunctor Data::mark(STATE) {
    return rdata(state)->dmark;
  }

  void Data::finalize(STATE, Data* data) {
    // MRI only calls free if the data_ptr is not NULL.
    void* data_ptr = data->data(state);

    if(data_ptr && !data->freed_p()) {
      Data::FreeFunctor f = data->free(state);
      if(f) {
        // If the user specifies -1, then we call free. We check here rather
        // than when Data_Make_Struct is called because the user is allowed to
        // change dfree.
        if(reinterpret_cast<intptr_t>(f) == -1) {
          ::free(data_ptr);
        } else {
          f(data_ptr);
        }
      }
      data->set_freed();
    }
  }

  void Data::Info::mark(Object* t, ObjectMark& mark) {
    auto_mark(t, mark);

    Data* data = force_as<Data>(t);

    if(data->freed_p()) return;

    RDataShadow* rdata = data->rdata();

    if(rdata->dmark) {
      ObjectMark* cur = capi::current_mark();
      capi::set_current_mark(&mark);

      (*rdata->dmark)(rdata->data);

      capi::set_current_mark(cur);
    }
  }

}
<|endoftext|>


<commit_before>#include "PlatformEntity.h"
PlatformEntity::PlatformEntity(){}
PlatformEntity::~PlatformEntity()
{
	this->Shutdown();
}
int PlatformEntity::Initialize(int entityID, PhysicsComponent * pComp, GraphicsComponent * gComp, AIComponent * aiComp)
{
	int result = 0;
	this->InitializeBase(entityID, pComp, gComp, nullptr, aiComp);
	return result;
}
int PlatformEntity::Shutdown()
{
	int result = 0;
	if (this->m_ActiveSound != nullptr)
		this->m_ActiveSound->drop();
	return result;
}

int PlatformEntity::Update(float deltaTime, InputHandler * inputHandler)
{
	int result = 0;
	this->SyncComponents();

	// Adjust misplaced graphics component - hack...
	this->m_gComp->worldMatrix = DirectX::XMMatrixMultiply(this->m_pComp->PC_OBB.ort,
		DirectX::XMMatrixTranslationFromVector(
		DirectX::XMVectorSubtract(this->m_pComp->PC_pos,
			DirectX::XMVECTOR{
		m_gComp->modelPtr->GetOBBData().position.x,
			m_gComp->modelPtr->GetOBBData().position.y,
			m_gComp->modelPtr->GetOBBData().position.z, 0})));

	if (this->GetAIComponent()->AC_triggered)
	{
		if (this->m_ActiveSound == nullptr)
		{
			DirectX::XMFLOAT3 pos;
			DirectX::XMStoreFloat3(&pos, this->GetPhysicsComponent()->PC_pos);
			this->m_ActiveSound = SoundHandler::instance().PlaySound3D(Sounds3D::GENERAL_LIFT, pos, true, true);
		}
		else
		{
			if (this->m_ActiveSound->getIsPaused())
			{
				this->m_ActiveSound->setIsPaused(false);
			}
		}
	}
	else
	{
		if (this->m_ActiveSound != nullptr && !this->m_ActiveSound->getIsPaused())
		{
			this->m_ActiveSound->setPlayPosition(0);
			this->m_ActiveSound->setIsPaused(true);	//Pause the walking sound
		}
	}
	return result;
}

int PlatformEntity::React(int entityID, EVENT reactEvent)
{
	switch (reactEvent)
	{
	//case FIELD_CONTAINS:
	//	break;
	//case FIELD_ENTERED:
	//	break;
	//case FIELD_EXITED:
	//	break;
	//case FIELD_CONDITIONS_MET:
	//	break;
	//case FIELD_ENABLED:
	//	break;
	//case FIELD_DISABLED:
	//	break;
	case BUTTON_DEACTIVE:
		this->GetAIComponent()->AC_triggered = false;
		break;
	case BUTTON_ACTIVE:
		this->GetAIComponent()->AC_triggered = true;
		break;
	case LEVER_DEACTIVE:
		this->GetAIComponent()->AC_triggered = false;
		break;
	case LEVER_ACTIVE:
		this->GetAIComponent()->AC_triggered = true;
		break;
	//case LEVER_ENABLED:
	//	break;
	//case LEVER_DISABLED:
	//	break;
	default:
		break;
	}
	return 1;
}<commit_msg>ADD basic wheel reaction<commit_after>#include "PlatformEntity.h"
PlatformEntity::PlatformEntity() {}
PlatformEntity::~PlatformEntity()
{
	this->Shutdown();
}
int PlatformEntity::Initialize(int entityID, PhysicsComponent * pComp, GraphicsComponent * gComp, AIComponent * aiComp)
{
	int result = 0;
	this->InitializeBase(entityID, pComp, gComp, nullptr, aiComp);
	return result;
}
int PlatformEntity::Shutdown()
{
	int result = 0;
	if (this->m_ActiveSound != nullptr)
		this->m_ActiveSound->drop();
	return result;
}

int PlatformEntity::Update(float deltaTime, InputHandler * inputHandler)
{
	int result = 0;
	this->SyncComponents();

	// Adjust misplaced graphics component - hack...
	this->m_gComp->worldMatrix = DirectX::XMMatrixMultiply(this->m_pComp->PC_OBB.ort,
		DirectX::XMMatrixTranslationFromVector(
			DirectX::XMVectorSubtract(this->m_pComp->PC_pos,
				DirectX::XMVECTOR{
		m_gComp->modelPtr->GetOBBData().position.x,
			m_gComp->modelPtr->GetOBBData().position.y,
			m_gComp->modelPtr->GetOBBData().position.z, 0})));

	if (this->GetAIComponent()->AC_triggered)
	{
		if (this->m_ActiveSound == nullptr)
		{
			DirectX::XMFLOAT3 pos;
			DirectX::XMStoreFloat3(&pos, this->GetPhysicsComponent()->PC_pos);
			this->m_ActiveSound = SoundHandler::instance().PlaySound3D(Sounds3D::GENERAL_LIFT, pos, true, true);
		}
		else
		{
			if (this->m_ActiveSound->getIsPaused())
			{
				this->m_ActiveSound->setIsPaused(false);
			}
		}
	}
	else
	{
		if (this->m_ActiveSound != nullptr && !this->m_ActiveSound->getIsPaused())
		{
			this->m_ActiveSound->setPlayPosition(0);
			this->m_ActiveSound->setIsPaused(true);	//Pause the walking sound
		}
	}
	return result;
}

int PlatformEntity::React(int entityID, EVENT reactEvent)
{
	switch (reactEvent)
	{
	//case FIELD_CONTAINS:
	//	break;
	//case FIELD_ENTERED:
	//	break;
	//case FIELD_EXITED:
	//	break;
	//case FIELD_CONDITIONS_MET:
	//	break;
	//case FIELD_ENABLED:
	//	break;
	//case FIELD_DISABLED:
	//	break;
	case BUTTON_DEACTIVE:
		this->GetAIComponent()->AC_triggered = false;
		break;
	case BUTTON_ACTIVE:
		this->GetAIComponent()->AC_triggered = true;
		break;
	case LEVER_DEACTIVE:
		this->GetAIComponent()->AC_triggered = false;
		break;
	case LEVER_ACTIVE:
		this->GetAIComponent()->AC_triggered = true;
		break;
	case WHEEL_INCREASING:
		this->GetAIComponent()->AC_triggered = true;
		break;
	case WHEEL_RESET:
		this->GetAIComponent()->AC_triggered = false;
		break;
	default:
		break;
	}
	return 1;
}<|endoftext|>