<commit_before>#include "box.hpp"
#include <cmath>
#include <iostream>
#include <string>
#include "color.hpp"
#include "ray.hpp"
#include "material.hpp"
#include <glm/glm.hpp>

Box::Box() : Shape{}, min_{0.0f, 0.0f, 0.0f}, max_{0.0f, 0.0f, 0.0f} {}
Box::Box(glm::vec3 const& min, glm::vec3 const& max):Shape{}, min_{min}, max_{max} {}
// Box::Box(glm::vec3 const& min, glm::vec3 const& max, std::string name, Color const& color):Shape{name, color}, min_{min}, max_{max} {}
//Box::~Box(){std::cout << "Box Destructor" << std::endl;}

/*Box::Box(glm::vec3 const& min, glm::vec3 const& max, std::string name, Material const& mat):Shape{name, mat}, min_{min}, max_{max} {}
Box::Box(glm::vec3 const& min, glm::vec3 const& max, std::string name, std::string name_mat, Color const& ka, Color const& kd, Color const& ks,
float m):Shape{name, name_mat, ka, kd, ks, m}, min_{min}, max_{max} {}*/

Box::Box(std::string name, glm::vec3 const& min, glm::vec3 const& max, std::string material):Shape{name, material},
min_{min}, max_{max} {}

glm::vec3 const& Box::get_min()const{
	return min_;
}
glm::vec3 const& Box::get_max()const{
	return max_;
}

/*float Box::area() const{
	float depth = fabs(max_.x - min_.x);
	float width = fabs(max_.y - min_.y);
	float high = fabs(max_.z - min_.z);
	return (2 * high * width + 2 * width * depth + 2 * high * depth) ;
}
float Box::volume() const{
	float depth = fabs(max_.x - min_.x);
	float width = fabs(max_.y - min_.y);
	float high = fabs(max_.z - min_.z);
	return (high * width * depth);
}*/

std::ostream& Box::print(std::ostream& os) const{
	Shape::print(os);
	//os << "Name: " << get_name() << ", Color: " << get_color().r << " " << get_color().g << " " << get_color().b << "\n";
	os << "Min: " << min_.x << " " << min_.y << " " << min_.z << ", Max: "<< max_.x << " " << max_.y << " " << max_.z;
	return os;
}

bool Box::intersect(Ray const& ray, float& distance) const{
    double a = (get_min().x - ray.origin.x) * ray.inv_direction.x;
    double b = (get_max().x - ray.origin.x) * ray.inv_direction.x;
    double tmin = std::min(a, b);
    double tmax = std::max(a, b);

    a = (get_min().y - ray.origin.y) * ray.inv_direction.y;
    b = (get_max().y - ray.origin.y) * ray.inv_direction.y;
    tmin = std::max(tmin, std::min(a, b));
    tmax = std::min(tmax, std::max(a, b));

    a = (get_min().z - ray.origin.z) * ray.inv_direction.z;
    b = (get_max().z - ray.origin.z) * ray.inv_direction.z;
    tmin = std::max(tmin, std::min(a, b));
    tmax = std::min(tmax, std::max(a, b));

    if (tmax > std::max(0.0, tmin)) {
        distance = sqrt(tmin * tmin * (ray.direction.x * ray.direction.x + ray.direction.y * ray.direction.y + ray.direction.z * ray.direction.z));
        return true;
    }
    return false;
}

bool Box::intersect(Ray const& ray, float& distance, glm::vec3& intersection, glm::vec3& normal) const{
    double a = (min_.x - ray.origin.x) * ray.inv_direction.x;
    double b = (max_.x - ray.origin.x) * ray.inv_direction.x;
    double tmin = std::min(a, b);
    double tmax = std::max(a, b);

    a = (min_.y - ray.origin.y) * ray.inv_direction.y;
    b = (max_.y - ray.origin.y) * ray.inv_direction.y;
    tmin = std::max(tmin, std::min(a, b));
    tmax = std::min(tmax, std::max(a, b));

    a = (min_.z - ray.origin.z) * ray.inv_direction.z;
    b = (max_.z - ray.origin.z) * ray.inv_direction.z;
    tmin = std::max(tmin, std::min(a, b));
    tmax = std::min(tmax, std::max(a, b));

	//neu
    float t = tmin;
    if (t < 0){
    	t = tmax;
    	if (t < 0) return false;
    }

    //Intersectionpoint
    intersection = ray.origin + ray.direction * t;

    //normale
    //Ein Wert des Intersectionpoint muss mit min oder max übereinstimmen

    if (min_.x == intersection.x)
    {
        //vorne
        normal = normale_box(min_, intersection, glm::vec3(min_.x, max_.y, max_.z) );
    }
    else if (max_.x == intersection.x)
    {
        //hinten
        normal = normale_box(max_, intersection, glm::vec3(max_.x, min_.y, min_.z) );
    }
    else if (min_.y == intersection.y)
    {
        //links
        normal = normale_box(min_, intersection, glm::vec3(max_.x, min_.y, max_.z) );
    }
    else if (max_.y == intersection.y)
    {
        //rechts
        normal = normale_box(max_, intersection, glm::vec3(min_.x, max_.y, min_.z) );
    }
    else if (min_.z == intersection.z)
    {
        //unten
        normal = normale_box(min_, intersection, glm::vec3(max_.x, max_.y, min_.z) );
    }
    else if (max_.z == intersection.z)
    {
        //oben
        normal = normale_box(max_, intersection, glm::vec3(min_.x, min_.y, max_.z) );
    }

    //ende neu
    if (tmax > std::max(0.0, tmin)) {
        distance = sqrt(tmin * tmin * (ray.direction.x * ray.direction.x + ray.direction.y * ray.direction.y + ray.direction.z * ray.direction.z));
        return true;
    }
    return false;
}

glm::vec3 Box::normale_box(glm::vec3 const& p1, glm::vec3 const& p2, glm::vec3 const& p3)const{
    glm::vec3 normale(0.0,0.0,0.0);
    // überprüfen ob Ebene möglich
    float rx = (p3.x-p1.x)/(p2.x-p1.x);
    float ry = (p3.y-p1.y)/(p2.y-p1.y);
    float rz = (p3.z-p3.z)/(p2.z-p1.z);

    if(rx == ry && ry == rz){
        //Normale der Gerade berechnen (richtungsvektor*normalenvektor = 0)
        normale.x = (p2.y-p1.y) * -1;
        normale.y = (p2.x-p1.x);
    }
    else{
        //Kreuzprodukt der beiden Richtungsvektoren
        normale.x = (((p2.y-p1.y) * (p3.z-p1.z)) - ((p2.z-p1.z) * (p3.y-p1.y)));
        normale.y = (((p2.z-p1.z) * (p3.x-p1.x)) - ((p2.x-p1.x) * (p3.z-p1.z)));
        normale.z = (((p2.x-p1.x) * (p3.y-p1.y)) - ((p2.y-p1.y) * (p3.x-p1.x)));
    }
    normale = glm::normalize(normale);
    return normale;

}
<commit_msg>Probe mit anderer Intersect<commit_after>#include "box.hpp"
#include <cmath>
#include <iostream>
#include <string>
#include "color.hpp"
#include "ray.hpp"
#include "material.hpp"
#include <glm/glm.hpp>

Box::Box() : Shape{}, min_{0.0f, 0.0f, 0.0f}, max_{0.0f, 0.0f, 0.0f} {}
Box::Box(glm::vec3 const& min, glm::vec3 const& max):Shape{}, min_{min}, max_{max} {}
// Box::Box(glm::vec3 const& min, glm::vec3 const& max, std::string name, Color const& color):Shape{name, color}, min_{min}, max_{max} {}
//Box::~Box(){std::cout << "Box Destructor" << std::endl;}

/*Box::Box(glm::vec3 const& min, glm::vec3 const& max, std::string name, Material const& mat):Shape{name, mat}, min_{min}, max_{max} {}
Box::Box(glm::vec3 const& min, glm::vec3 const& max, std::string name, std::string name_mat, Color const& ka, Color const& kd, Color const& ks,
float m):Shape{name, name_mat, ka, kd, ks, m}, min_{min}, max_{max} {}*/

Box::Box(std::string name, glm::vec3 const& min, glm::vec3 const& max, std::string material):Shape{name, material},
min_{min}, max_{max} {}

glm::vec3 const& Box::get_min()const{
	return min_;
}
glm::vec3 const& Box::get_max()const{
	return max_;
}

/*float Box::area() const{
	float depth = fabs(max_.x - min_.x);
	float width = fabs(max_.y - min_.y);
	float high = fabs(max_.z - min_.z);
	return (2 * high * width + 2 * width * depth + 2 * high * depth) ;
}
float Box::volume() const{
	float depth = fabs(max_.x - min_.x);
	float width = fabs(max_.y - min_.y);
	float high = fabs(max_.z - min_.z);
	return (high * width * depth);
}*/

std::ostream& Box::print(std::ostream& os) const{
	Shape::print(os);
	//os << "Name: " << get_name() << ", Color: " << get_color().r << " " << get_color().g << " " << get_color().b << "\n";
	os << "Min: " << min_.x << " " << min_.y << " " << min_.z << ", Max: "<< max_.x << " " << max_.y << " " << max_.z;
	return os;
}

bool Box::intersect(Ray const& ray, float& distance) const{
    double a = (get_min().x - ray.origin.x) * ray.inv_direction.x;
    double b = (get_max().x - ray.origin.x) * ray.inv_direction.x;
    double tmin = std::min(a, b);
    double tmax = std::max(a, b);

    a = (get_min().y - ray.origin.y) * ray.inv_direction.y;
    b = (get_max().y - ray.origin.y) * ray.inv_direction.y;
    tmin = std::max(tmin, std::min(a, b));
    tmax = std::min(tmax, std::max(a, b));

    a = (get_min().z - ray.origin.z) * ray.inv_direction.z;
    b = (get_max().z - ray.origin.z) * ray.inv_direction.z;
    tmin = std::max(tmin, std::min(a, b));
    tmax = std::min(tmax, std::max(a, b));

    if (tmax > std::max(0.0, tmin)) {
        distance = sqrt(tmin * tmin * (ray.direction.x * ray.direction.x + ray.direction.y * ray.direction.y + ray.direction.z * ray.direction.z));
        return true;
    }
    return false;
}

bool Box::intersect(Ray const& ray, float& distance, glm::vec3& intersection, glm::vec3& normal) const{
    double a = (min_.x - ray.origin.x) * ray.inv_direction.x;
    double b = (max_.x - ray.origin.x) * ray.inv_direction.x;
    double tmin = std::min(a, b);
    double tmax = std::max(a, b);

    a = (min_.y - ray.origin.y) * ray.inv_direction.y;
    b = (max_.y - ray.origin.y) * ray.inv_direction.y;
    tmin = std::max(tmin, std::min(a, b));
    tmax = std::min(tmax, std::max(a, b));

    a = (min_.z - ray.origin.z) * ray.inv_direction.z;
    b = (max_.z - ray.origin.z) * ray.inv_direction.z;
    tmin = std::max(tmin, std::min(a, b));
    tmax = std::min(tmax, std::max(a, b));

	//neu
    float t = tmin;
    if (t < 0){
    	t = tmax;
    	if (t < 0) return false;
    }

    //Intersectionpoint
    intersection = ray.origin + ray.direction * t;

    //normale

    //Ein Wert des Intersectionpoint muss mit min oder max übereinstimmen

    if (min_.x == intersection.x)
    {
        //vorne
        normal = normale_box(min_, intersection, glm::vec3(min_.x, max_.y, max_.z) );
    }
    else if (max_.x == intersection.x)
    {
        //hinten
        normal = normale_box(max_, intersection, glm::vec3(max_.x, min_.y, min_.z) );
    }
    else if (min_.y == intersection.y)
    {
        //links
        normal = normale_box(min_, intersection, glm::vec3(max_.x, min_.y, max_.z) );
    }
    else if (max_.y == intersection.y)
    {
        //rechts
        normal = normale_box(max_, intersection, glm::vec3(min_.x, max_.y, min_.z) );
    }
    else if (min_.z == intersection.z)
    {
        //unten
        normal = normale_box(min_, intersection, glm::vec3(max_.x, max_.y, min_.z) );
    }
    else if (max_.z == intersection.z)
    {
        //oben
        normal = normale_box(max_, intersection, glm::vec3(min_.x, min_.y, max_.z) );
    }

    //normal = normale_box(intersection);

    //ende neu
    if (tmax > std::max(0.0, tmin)) {
        distance = sqrt(tmin * tmin * (ray.direction.x * ray.direction.x + ray.direction.y * ray.direction.y + ray.direction.z * ray.direction.z));
        return true;
    }
    return false;
}

glm::vec3 Box::normale_box(glm::vec3 const& p1, glm::vec3 const& p2, glm::vec3 const& p3)const{
    glm::vec3 normale(0.0,0.0,0.0);

    // überprüfen ob Ebene möglich
    float rx = (p3.x-p1.x)/(p2.x-p1.x);
    float ry = (p3.y-p1.y)/(p2.y-p1.y);
    float rz = (p3.z-p3.z)/(p2.z-p1.z);

    if(rx == ry && ry == rz){
        //Normale der Gerade berechnen (richtungsvektor*normalenvektor = 0)
        normale.x = (p2.y-p1.y) * -1;
        normale.y = (p2.x-p1.x);
    }
    else{
        //Kreuzprodukt der beiden Richtungsvektoren
        normale.x = (((p2.y-p1.y) * (p3.z-p1.z)) - ((p2.z-p1.z) * (p3.y-p1.y)));
        normale.y = (((p2.z-p1.z) * (p3.x-p1.x)) - ((p2.x-p1.x) * (p3.z-p1.z)));
        normale.z = (((p2.x-p1.x) * (p3.y-p1.y)) - ((p2.y-p1.y) * (p3.x-p1.x)));
    }
    /*
    if (max_.x < origin.x)
    {
        normale.x = 1;
    }
    else{
        normale.x = -1;
    }

    if (max_.y < origin.y)
    {
        normale.y = 1;
    }
    else{
        normale.y = -1;
    }

    if (max_.z < origin.z)
    {
        normale.z = 1;
    }
    else{
        normale.z = -1;
    }*/

    normale = glm::normalize(normale);
    return normale;

}
<|endoftext|>


<commit_before>#ifndef RAY_HPP
#define RAY_HPP

#include <glm/vec3.hpp>
#include <glm/vec4.hpp>
#include <glm/glm.hpp>
struct Ray
{
	Ray():
	origin{0.0f,0.0f,0.0f},
	direction{0.0f,0.0f,0.0f}
	{}

	Ray(glm::vec3 const& ori, glm::vec3 const& dir):
	origin{ori},
	direction{dir}
	{}

	/*Ray(glm::vec4 const& transori, glm::vec4 const& transdir):
	transorigin{transori},
	transdirection{transdir}
	{}

	Ray(glm::vec4 const& scalori, glm::vec4 const& scaldir):
	scaorigin{scalori},
	scadirection{scaldir}
	{}*/

	glm::vec3 origin;
	glm::vec3 direction;
	/*glm::vec4 transorigin;
	glm::vec4 transdirection;
	glm::vec4 scaorigin;
	glm::vec4 scadirection;*/

	Ray transformRay(glm::mat4 const& mat)
{

    /*glm::vec4 origin4{origin, 1.0f};
    glm::vec4 direction4{direction, 0.0f};
    glm::vec4 origin_trans = mat * origin4;
    glm::vec4 direction_trans = mat * direction4;

    glm::vec3 origin3(origin_trans);
    glm::vec3 direction3(direction_trans);

    Ray ray{origin3, direction3};

    return ray;*/

	glm::vec4 origino{origin,1.0f};
	glm::vec4 directiono{direction,0.0f};

  //world_transformation_inv = glm::inverse(world_transformation);
  //world_transformation_inv_tp = glm::transpose(world_transformation_inv);

  //glm::vec4 newOrigin   {origin    * world_transformation_inv};
  //glm::vec4 newDirection{direction * world_transformation_inv};

	glm::vec4 origin_homogen = mat * origino;
	glm::vec4 direction_homogen = mat * directiono;

	glm::vec3 origini(origin_homogen);
	glm::vec3 directini(direction_homogen);

	Ray ray{origini, directini};

	//return Ray{glm::vec3{newOrigin.x, newOrigin.y, newOrigin.z }, glm::vec3{newDirection.x, newDirection.y, newDirection.z}};
	return ray;
}
};

#endif<commit_msg>Removed Comments at ray.hpp OK<commit_after>#ifndef RAY_HPP
#define RAY_HPP

#include <glm/vec3.hpp>
#include <glm/vec4.hpp>
#include <glm/glm.hpp>

struct Ray
{
	Ray():
	origin{0.0f,0.0f,0.0f},
	direction{0.0f,0.0f,0.0f}
	{}

	Ray(glm::vec3 const& ori, glm::vec3 const& dir):
	origin{ori},
	direction{dir}
	{}

	glm::vec3 origin;
	glm::vec3 direction;

	Ray transformRay(glm::mat4 const& mat)
	{
		glm::vec4 origino{origin,1.0f};
		glm::vec4 directiono{direction,0.0f};

		glm::vec4 origin_homogen = mat * origino;
		glm::vec4 direction_homogen = mat * directiono;

		glm::vec3 origini(origin_homogen);
		glm::vec3 directini(direction_homogen);

		return Ray {origini, directini};
	}
};

#endif<|endoftext|>


<commit_before>//
// Copyright (C) 2006-2011 SIPez LLC.  All rights reserved.
// Licensed to SIPfoundry under a Contributor Agreement.
//
// Copyright (C) 2004-2006 SIPfoundry Inc.
// Licensed by SIPfoundry under the LGPL license.
//
// Copyright (C) 2004-2006 Pingtel Corp.  All rights reserved.
// Licensed to SIPfoundry under a Contributor Agreement.
//
// $$
///////////////////////////////////////////////////////////////////////////////

#include "rtcp/RtcpConfig.h"

#undef WANT_RTCP_LOG_MESSAGES
#undef DROP_SOME_PACKETS

// SYSTEM INCLUDES
#include <assert.h>

#ifdef _VXWORKS /* [ */
#include <iosLib.h>
#include <netinet/in.h>
#endif /* _VXWORKS ] */

#ifdef WIN32 /* [ */
#include <winsock2.h>
#   ifndef WINCE
#       include <io.h>
#   endif
#endif /* WIN32 ] */

#ifdef __pingtel_on_posix__ /* [ */
#include "os/OsIntTypes.h"
#include <sys/types.h>
#include <netinet/in.h>
#endif /* __pingtel_on_posix__ ] */

// APPLICATION INCLUDES
#include "os/OsDefs.h"
#include "mp/MpMisc.h"
#include "mp/MpBuf.h"
#include "mp/MprToNet.h"
#include "mp/NetInTask.h"
#include "mp/MprFromNet.h"
#include "mp/dmaTask.h"

// EXTERNAL FUNCTIONS
// EXTERNAL VARIABLES
// CONSTANTS
// STATIC VARIABLE INITIALIZATIONS

#ifdef ENABLE_PACKET_HACKING /* [ */
int MprToNet::sDebug1 = 0;
int MprToNet::sDebug2 = 0;
int MprToNet::sDebug3 = 0;
int MprToNet::sDebug4 = 0;
int MprToNet::sDebug5 = 0;
#endif /* ENABLE_PACKET_HACKING ] */

static int doPadRtp = 1;

/* //////////////////////////// PUBLIC //////////////////////////////////// */

/* ============================ CREATORS ================================== */

// Constructor
MprToNet::MprToNet()
:  mpFromNetPal(NULL)
,  mRtcpPackets(0)
,  mRtcpFrameCount(0)
,  mRtcpFrameLimit(500)
#ifdef DEBUG /* [ */
,  mRtpSampleCounter(0)
#endif /* DEBUG ] */
,  mTimestampDelta(0)
,  mSeqNum(0)
,  mSSRC(0)
,  mpRtpSocket(NULL)
,  mpRtcpSocket(NULL)
,  mNumRtpWriteErrors(0)
,  mNumRtcpWriteErrors(0)
#ifdef INCLUDE_RTCP /* [ */
,  mpiRTPAccumulator(NULL)
#endif /* INCLUDE_RTCP ] */

{
}

// Destructor
MprToNet::~MprToNet()
{
#ifdef INCLUDE_RTCP /* [ */

//  Release the reference held to the RTP Accumulator interface used to
//  RTP outbound stream statistics
    if(mpiRTPAccumulator)
    {
        mpiRTPAccumulator->Release();
        mpiRTPAccumulator = NULL;
    }
#endif /* INCLUDE_RTCP ] */
    if (0 != mNumRtpWriteErrors) {
        osPrintf("MprToNet: %d network write errors on RTP socket!\n",
            mNumRtpWriteErrors);
    }
    if (0 != mNumRtcpWriteErrors) {
        osPrintf("MprToNet: %d network write errors on RTCP socket!\n",
            mNumRtcpWriteErrors);
    }
}

/* ============================ MANIPULATORS ============================== */

// Set the outbound RTP and RTCP sockets.
OsStatus MprToNet::setSockets(OsSocket& rRtpSocket, OsSocket& rRtcpSocket)
{
   mpRtpSocket  = &rRtpSocket;
   mpRtcpSocket = &rRtcpSocket;

   return OS_SUCCESS;
}

// Clear the outbound RTP and RTCP sockets.
OsStatus MprToNet::resetSockets(void)
{
   mpRtpSocket  = NULL;
   mpRtcpSocket = NULL;

   return OS_SUCCESS;
}

void MprToNet::setSSRC(int iSSRC)
{
   mSSRC = iSSRC;
   mSeqNum = rand_timer32() | 0xfc00;
   mTimestampDelta = rand_timer32();
}

#ifdef INCLUDE_RTCP /* [ */
void MprToNet::setRTPAccumulator(ISetSenderStatistics *piRTPAccumulator)
{
   mpiRTPAccumulator = piRTPAccumulator;
   if(mpiRTPAccumulator)
   {
       mpiRTPAccumulator->SetRTPTimestamp(mTimestampDelta);
   }
}

#endif /* INCLUDE_RTCP ] */

#ifdef DROP_SOME_PACKETS // [
static int dropLimit = 1<<30;
static int dropCount = 0;

extern "C" {
extern int dropEvery(int limit);
}

int dropEvery(int limit)
{
   int save = dropLimit;
   if (limit < 0) limit = 1<<30;
   if (limit > 0) {
      dropLimit = limit;
      dropCount = 0;
   }
   return save;
}
#endif // DROP_SOME_PACKETS ]

int MprToNet::writeRtp(int payloadType, UtlBoolean markerState,
                       const unsigned char* payloadData, int payloadOctets,
                       unsigned int timestamp, void* csrcList)
{
   MpRtpBufPtr pRtpPacket;
   char paddingLength;

   // Nothing to do when no socket specified.
   if (mpRtpSocket == NULL)
      return 0;

   // Allocate new RTP packet.
   pRtpPacket = MpMisc.RtpPool->getBuffer();

   // Get rid of packet sequence number.
   mSeqNum++;

   // Fill packet RTP header.
   pRtpPacket->setRtpVersion(2);
   pRtpPacket->setRtpPayloadType(payloadType);
   pRtpPacket->setPayloadSize(payloadOctets);
   if (markerState)
      pRtpPacket->enableRtpMarker();
   else
      pRtpPacket->disableRtpMarker();
   pRtpPacket->disableRtpExtension();
   pRtpPacket->setRtpSequenceNumber(mSeqNum);
   pRtpPacket->setRtpTimestamp(mTimestampDelta + timestamp);
   pRtpPacket->setRtpSSRC(mSSRC);
   pRtpPacket->setRtpCSRCCount(0);

#ifdef ENABLE_PACKET_HACKING /* [ */
   adjustRtpPacket(pRtpPacket->getRtpHeader());
#endif /* ENABLE_PACKET_HACKING ] */

   // Calculate number of padding bytes
   paddingLength = doPadRtp ? ((4 - (payloadOctets & 3))&3) : 0;

   if (paddingLength>0)
      pRtpPacket->enableRtpPadding();
   else
      pRtpPacket->disableRtpPadding();

   if (csrcList != NULL)
   {
      int csrcSize = pRtpPacket->getRtpCSRCCount() * sizeof(RtpSRC);
      // TODO:: implement CSRC list.
      assert(csrcSize == 0);
   }

   //////////////////////////////////////////////////////
   // Next part of code should separated from previous //
   //////////////////////////////////////////////////////

   char *pBuf;
   int numBytesSent;
   MpUdpBufPtr pUdpPacket;

   // Allocate UDP packet
   pUdpPacket = MpMisc.UdpPool->getBuffer();
   pBuf = pUdpPacket->getDataWritePtr();

   // Set size of data to send
   assert(pUdpPacket->getMaximumPacketSize() >= sizeof(RtpHeader)+payloadOctets+paddingLength);
   pUdpPacket->setPacketSize(sizeof(RtpHeader)+payloadOctets+paddingLength);

   // Copy RTP header to UDP packet
   memcpy(pBuf, &pRtpPacket->getRtpHeader(), sizeof(RtpHeader));
   pBuf += sizeof(RtpHeader);

   // TODO:: Copy CSRC list here.

   // Copy payload to UDP packet
   memcpy(pBuf, payloadData, payloadOctets);
   pBuf += payloadOctets;

   // Fill padding
   switch (paddingLength) {
   case 3:
      pBuf[1] = 0;           // fall through
   case 2:
      pBuf[0] = 0;           // fall through
   case 1:
      pBuf[paddingLength-1] = paddingLength;  // fall through
   case 0:
      break;
   }

#ifdef INCLUDE_RTCP /* [ */
   // Update the Accumulated statistics kept for an inbound RTP packet.
   // These statistics comprise a Sender Report that is sent out periodically
   // to the originating site
   if(mpiRTPAccumulator)
   {
       mpiRTPAccumulator->IncrementCounts(payloadOctets);
   }
#endif /* INCLUDE_RTCP ] */

#ifdef DROP_SOME_PACKETS /* [ */
   if (dropCount++ == dropLimit) {
      dropCount = 0;
      numBytesSent = pUdpPacket->getPacketSize();
   } else {
      numBytesSent = mpRtpSocket->write(pUdpPacket->getDataPtr(), pUdpPacket->getPacketSize());
   }
#else /* DROP_SOME_PACKETS ] [*/
   numBytesSent = mpRtpSocket->write(pUdpPacket->getDataPtr(), pUdpPacket->getPacketSize());
#endif /* DROP_SOME_PACKETS ] */

#ifdef TEST_PRINT
   UtlString remoteIp("null socket");
   int remotePort;
   if(mpRtpSocket)
   {
      mpRtpSocket->getRemoteHostIp(&remoteIp, &remotePort);
   }
   OsSysLog::add(FAC_MP, PRI_DEBUG, "MprToNet::writeRtp payload: %d send to address: %s port: %d numBytesSent: %d errno: %d",
      payloadType, remoteIp.data(), remotePort, numBytesSent, errno);
#endif

   if (numBytesSent != pUdpPacket->getPacketSize()) {
      switch (errno) {
         /* insert other benign errno values here */
            case 0:
            case 55: // Network disconnected, continue and hope it comes back
               break;
            default:
               // close(fd);  MAYBE: mpRtpSocket->close() ?
               // mpRtpSocket = NULL;
               break;
      }

   }
   return (pUdpPacket->getPacketSize() == numBytesSent) ? pUdpPacket->getPacketSize() : numBytesSent;
}

#ifdef ENABLE_PACKET_HACKING /* [ */
extern "C" {
extern int sTRA(int a, int b, int c);
extern int setToRtpAdjustment(int a, int b, int c);
};

int setToRtpAdjustment(int ssrc, int seq, int ts)
{
   MprToNet::sDebug1 = ssrc;
   MprToNet::sDebug2 = seq;
   MprToNet::sDebug3 = ts;
   return 0;
}

int sTRA(int a, int b, int c) {return setToRtpAdjustment(a,b,c);}
#endif /* ENABLE_PACKET_HACKING ] */

/* ============================ ACCESSORS ================================= */

OsStatus MprToNet::setRtpPal(MprFromNet* pal)
{
   mpFromNetPal = pal;
   return OS_SUCCESS;
}

/* ============================ INQUIRY =================================== */

/* //////////////////////////// PROTECTED ///////////////////////////////// */

/* //////////////////////////// PRIVATE /////////////////////////////////// */

#ifdef ENABLE_PACKET_HACKING /* [ */
void MprToNet::adjustRtpPacket(struct RtpHeader* rp)
{
   struct RtpHeader rh;

   memcpy((char *) &rh, (char *) rp, sizeof(struct RtpHeader));
   // rh.vpxcc = rh.vpxcc;
   // rh.mpt = rh.mpt;
   rh.ssrc = ntohl(rh.ssrc) - sDebug1;
   rh.seq = ntohs(rh.seq) - sDebug2;
   rh.timestamp = ntohl(rh.timestamp) - sDebug3;
   rh.ssrc = htonl(rh.ssrc);
   rh.seq = htons(rh.seq);
   rh.timestamp = htonl(rh.timestamp);
   memcpy((char *) rp, (char *) &rh, sizeof(struct RtpHeader));
}
#endif /* ENABLE_PACKET_HACKING ] */

/* ============================ FUNCTIONS ================================= */
<commit_msg>Check if RTP output soceket is NULL immediately before write as it can be set to NULL outside media task. This sometimes caused a crash in when many lines are active.<commit_after>//
// Copyright (C) 2006-2012 SIPez LLC.  All rights reserved.
//
// Copyright (C) 2004-2006 SIPfoundry Inc.
// Licensed by SIPfoundry under the LGPL license.
//
// Copyright (C) 2004-2006 Pingtel Corp.  All rights reserved.
// Licensed to SIPfoundry under a Contributor Agreement.
//
// $$
///////////////////////////////////////////////////////////////////////////////

#include "rtcp/RtcpConfig.h"

#undef WANT_RTCP_LOG_MESSAGES
#undef DROP_SOME_PACKETS

// SYSTEM INCLUDES
#include <assert.h>

#ifdef _VXWORKS /* [ */
#include <iosLib.h>
#include <netinet/in.h>
#endif /* _VXWORKS ] */

#ifdef WIN32 /* [ */
#include <winsock2.h>
#   ifndef WINCE
#       include <io.h>
#   endif
#endif /* WIN32 ] */

#ifdef __pingtel_on_posix__ /* [ */
#include "os/OsIntTypes.h"
#include <sys/types.h>
#include <netinet/in.h>
#endif /* __pingtel_on_posix__ ] */

// APPLICATION INCLUDES
#include "os/OsDefs.h"
#include "mp/MpMisc.h"
#include "mp/MpBuf.h"
#include "mp/MprToNet.h"
#include "mp/NetInTask.h"
#include "mp/MprFromNet.h"
#include "mp/dmaTask.h"

// EXTERNAL FUNCTIONS
// EXTERNAL VARIABLES
// CONSTANTS
// STATIC VARIABLE INITIALIZATIONS

#ifdef ENABLE_PACKET_HACKING /* [ */
int MprToNet::sDebug1 = 0;
int MprToNet::sDebug2 = 0;
int MprToNet::sDebug3 = 0;
int MprToNet::sDebug4 = 0;
int MprToNet::sDebug5 = 0;
#endif /* ENABLE_PACKET_HACKING ] */

static int doPadRtp = 1;

/* //////////////////////////// PUBLIC //////////////////////////////////// */

/* ============================ CREATORS ================================== */

// Constructor
MprToNet::MprToNet()
:  mpFromNetPal(NULL)
,  mRtcpPackets(0)
,  mRtcpFrameCount(0)
,  mRtcpFrameLimit(500)
#ifdef DEBUG /* [ */
,  mRtpSampleCounter(0)
#endif /* DEBUG ] */
,  mTimestampDelta(0)
,  mSeqNum(0)
,  mSSRC(0)
,  mpRtpSocket(NULL)
,  mpRtcpSocket(NULL)
,  mNumRtpWriteErrors(0)
,  mNumRtcpWriteErrors(0)
#ifdef INCLUDE_RTCP /* [ */
,  mpiRTPAccumulator(NULL)
#endif /* INCLUDE_RTCP ] */

{
}

// Destructor
MprToNet::~MprToNet()
{
#ifdef INCLUDE_RTCP /* [ */

//  Release the reference held to the RTP Accumulator interface used to
//  RTP outbound stream statistics
    if(mpiRTPAccumulator)
    {
        mpiRTPAccumulator->Release();
        mpiRTPAccumulator = NULL;
    }
#endif /* INCLUDE_RTCP ] */
    if (0 != mNumRtpWriteErrors) {
        osPrintf("MprToNet: %d network write errors on RTP socket!\n",
            mNumRtpWriteErrors);
    }
    if (0 != mNumRtcpWriteErrors) {
        osPrintf("MprToNet: %d network write errors on RTCP socket!\n",
            mNumRtcpWriteErrors);
    }
}

/* ============================ MANIPULATORS ============================== */

// Set the outbound RTP and RTCP sockets.
OsStatus MprToNet::setSockets(OsSocket& rRtpSocket, OsSocket& rRtcpSocket)
{
   mpRtpSocket  = &rRtpSocket;
   mpRtcpSocket = &rRtcpSocket;

   return OS_SUCCESS;
}

// Clear the outbound RTP and RTCP sockets.
OsStatus MprToNet::resetSockets(void)
{
   mpRtpSocket  = NULL;
   mpRtcpSocket = NULL;

   return OS_SUCCESS;
}

void MprToNet::setSSRC(int iSSRC)
{
   mSSRC = iSSRC;
   mSeqNum = rand_timer32() | 0xfc00;
   mTimestampDelta = rand_timer32();
}

#ifdef INCLUDE_RTCP /* [ */
void MprToNet::setRTPAccumulator(ISetSenderStatistics *piRTPAccumulator)
{
   mpiRTPAccumulator = piRTPAccumulator;
   if(mpiRTPAccumulator)
   {
       mpiRTPAccumulator->SetRTPTimestamp(mTimestampDelta);
   }
}

#endif /* INCLUDE_RTCP ] */

#ifdef DROP_SOME_PACKETS // [
static int dropLimit = 1<<30;
static int dropCount = 0;

extern "C" {
extern int dropEvery(int limit);
}

int dropEvery(int limit)
{
   int save = dropLimit;
   if (limit < 0) limit = 1<<30;
   if (limit > 0) {
      dropLimit = limit;
      dropCount = 0;
   }
   return save;
}
#endif // DROP_SOME_PACKETS ]

int MprToNet::writeRtp(int payloadType, UtlBoolean markerState,
                       const unsigned char* payloadData, int payloadOctets,
                       unsigned int timestamp, void* csrcList)
{
   MpRtpBufPtr pRtpPacket;
   char paddingLength;

   // Nothing to do when no socket specified.
   if (mpRtpSocket == NULL)
      return 0;

   // Allocate new RTP packet.
   pRtpPacket = MpMisc.RtpPool->getBuffer();

   // Get rid of packet sequence number.
   mSeqNum++;

   // Fill packet RTP header.
   pRtpPacket->setRtpVersion(2);
   pRtpPacket->setRtpPayloadType(payloadType);
   pRtpPacket->setPayloadSize(payloadOctets);
   if (markerState)
      pRtpPacket->enableRtpMarker();
   else
      pRtpPacket->disableRtpMarker();
   pRtpPacket->disableRtpExtension();
   pRtpPacket->setRtpSequenceNumber(mSeqNum);
   pRtpPacket->setRtpTimestamp(mTimestampDelta + timestamp);
   pRtpPacket->setRtpSSRC(mSSRC);
   pRtpPacket->setRtpCSRCCount(0);

#ifdef ENABLE_PACKET_HACKING /* [ */
   adjustRtpPacket(pRtpPacket->getRtpHeader());
#endif /* ENABLE_PACKET_HACKING ] */

   // Calculate number of padding bytes
   paddingLength = doPadRtp ? ((4 - (payloadOctets & 3))&3) : 0;

   if (paddingLength>0)
      pRtpPacket->enableRtpPadding();
   else
      pRtpPacket->disableRtpPadding();

   if (csrcList != NULL)
   {
      int csrcSize = pRtpPacket->getRtpCSRCCount() * sizeof(RtpSRC);
      // TODO:: implement CSRC list.
      assert(csrcSize == 0);
   }

   //////////////////////////////////////////////////////
   // Next part of code should separated from previous //
   //////////////////////////////////////////////////////

   char *pBuf;
   unsigned int numBytesSent;
   MpUdpBufPtr pUdpPacket;

   // Allocate UDP packet
   pUdpPacket = MpMisc.UdpPool->getBuffer();
   pBuf = pUdpPacket->getDataWritePtr();

   // Set size of data to send
   assert(pUdpPacket->getMaximumPacketSize() >= sizeof(RtpHeader)+payloadOctets+paddingLength);
   pUdpPacket->setPacketSize(sizeof(RtpHeader)+payloadOctets+paddingLength);

   // Copy RTP header to UDP packet
   memcpy(pBuf, &pRtpPacket->getRtpHeader(), sizeof(RtpHeader));
   pBuf += sizeof(RtpHeader);

   // TODO:: Copy CSRC list here.

   // Copy payload to UDP packet
   memcpy(pBuf, payloadData, payloadOctets);
   pBuf += payloadOctets;

   // Fill padding
   switch (paddingLength) {
   case 3:
      pBuf[1] = 0;           // fall through
   case 2:
      pBuf[0] = 0;           // fall through
   case 1:
      pBuf[paddingLength-1] = paddingLength;  // fall through
   case 0:
      break;
   }

#ifdef INCLUDE_RTCP /* [ */
   // Update the Accumulated statistics kept for an inbound RTP packet.
   // These statistics comprise a Sender Report that is sent out periodically
   // to the originating site
   if(mpiRTPAccumulator)
   {
       mpiRTPAccumulator->IncrementCounts(payloadOctets);
   }
#endif /* INCLUDE_RTCP ] */

   const char* writeBytes = pUdpPacket->getDataPtr();
   int packetSize = pUdpPacket->getPacketSize();

#ifdef DROP_SOME_PACKETS /* [ */
   if (dropCount++ == dropLimit) {
      dropCount = 0;
      numBytesSent = pUdpPacket->getPacketSize();
   }
   // Socket can get set asynchronously to NULL when RTP send is stopped.  So check immediately before accessing socket.
   else if(mpRtpSocket)
   {
      numBytesSent = mpRtpSocket->write(writeBytes, packetSize);
   }
   else
   {
       numBytesSent = 0;
   }
#else /* DROP_SOME_PACKETS ] [*/

   // Socket can get set asynchronously to NULL when RTP send is stopped.  So check immediately before accessing socket.
   if(mpRtpSocket)
   {
      numBytesSent = mpRtpSocket->write(writeBytes, packetSize);
   }
   else
   {
       numBytesSent = 0;
   }
#endif /* DROP_SOME_PACKETS ] */

#ifdef TEST_PRINT
   UtlString remoteIp("null socket");
   int remotePort;
   if(mpRtpSocket)
   {
      mpRtpSocket->getRemoteHostIp(&remoteIp, &remotePort);
   }
   OsSysLog::add(FAC_MP, PRI_DEBUG, "MprToNet::writeRtp payload: %d send to address: %s port: %d numBytesSent: %d errno: %d",
      payloadType, remoteIp.data(), remotePort, numBytesSent, errno);
#endif

   if (numBytesSent != pUdpPacket->getPacketSize()) {
      switch (errno) {
         /* insert other benign errno values here */
            case 0:
            case 55: // Network disconnected, continue and hope it comes back
               break;
            default:
               // close(fd);  MAYBE: mpRtpSocket->close() ?
               // mpRtpSocket = NULL;
               break;
      }

   }
   return (pUdpPacket->getPacketSize() == numBytesSent) ? pUdpPacket->getPacketSize() : numBytesSent;
}

#ifdef ENABLE_PACKET_HACKING /* [ */
extern "C" {
extern int sTRA(int a, int b, int c);
extern int setToRtpAdjustment(int a, int b, int c);
};

int setToRtpAdjustment(int ssrc, int seq, int ts)
{
   MprToNet::sDebug1 = ssrc;
   MprToNet::sDebug2 = seq;
   MprToNet::sDebug3 = ts;
   return 0;
}

int sTRA(int a, int b, int c) {return setToRtpAdjustment(a,b,c);}
#endif /* ENABLE_PACKET_HACKING ] */

/* ============================ ACCESSORS ================================= */

OsStatus MprToNet::setRtpPal(MprFromNet* pal)
{
   mpFromNetPal = pal;
   return OS_SUCCESS;
}

/* ============================ INQUIRY =================================== */

/* //////////////////////////// PROTECTED ///////////////////////////////// */

/* //////////////////////////// PRIVATE /////////////////////////////////// */

#ifdef ENABLE_PACKET_HACKING /* [ */
void MprToNet::adjustRtpPacket(struct RtpHeader* rp)
{
   struct RtpHeader rh;

   memcpy((char *) &rh, (char *) rp, sizeof(struct RtpHeader));
   // rh.vpxcc = rh.vpxcc;
   // rh.mpt = rh.mpt;
   rh.ssrc = ntohl(rh.ssrc) - sDebug1;
   rh.seq = ntohs(rh.seq) - sDebug2;
   rh.timestamp = ntohl(rh.timestamp) - sDebug3;
   rh.ssrc = htonl(rh.ssrc);
   rh.seq = htons(rh.seq);
   rh.timestamp = htonl(rh.timestamp);
   memcpy((char *) rp, (char *) &rh, sizeof(struct RtpHeader));
}
#endif /* ENABLE_PACKET_HACKING ] */

/* ============================ FUNCTIONS ================================= */
<|endoftext|>


<commit_before>#include "./../include/Camera.hpp"
#include <iostream>

#include <glm/gtc/type_precision.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

using namespace std;

Camera::Camera()
    : m_view{ glm::lookAt( glm::vec3{0, 0, -5}, glm::vec3{}, glm::vec3{0,1,0}) },
      m_fov{ 1.04f }, m_ratio{ 1.0f }, m_znear{ 1.0f }, m_zfar{ 500.0f },
      m_mouseBehavior{ ARCBALL_BEHAVIOR }
{}

Camera::~Camera()
{

}

void Camera::animate(float time)
{
}

const glm::mat4& Camera::viewMatrix() const
{
    return m_view;
}

void Camera::setViewMatrix(const glm::mat4& view)
{
    m_view = view;
}

glm::vec3 Camera::getPosition() const
{
    return -glm::vec3( m_view[3] ) * glm::mat3( m_view );
}

glm::vec3 Camera::getRight() const
{
    return glm::vec3( m_view[0][0], m_view[1][0], m_view[2][0] );
}

glm::vec3 Camera::getUp() const
{
    return glm::vec3( m_view[0][1], m_view[1][1], m_view[2][1] );
}

glm::vec3 Camera::getForward() const
{
    return glm::vec3( -m_view[0][2], -m_view[1][2], -m_view[2][2] );
}

void Camera::setPosition( const glm::vec3& pos )
{
    for( int i = 0; i < 3; ++ i )
    {
        m_view[3][i] = float(0);
        for( int j = 0; j < 3; ++ j )
        {
            m_view[3][i] -= m_view[j][i] * pos[j];
        }
    }
}

void Camera::setRight( const glm::vec3& right )
{
    glm::vec3 minus_pos = glm::vec3( m_view[3] ) * glm::mat3( m_view );
    m_view[0][0] = right.x;
    m_view[1][0] = right.y;
    m_view[2][0] = right.z;
    m_view[3][0] = dot( right, minus_pos );
}

void Camera::setUp( const glm::vec3& up )
{
  glm::vec3 minus_pos = glm::vec3( m_view[3] ) * glm::mat3( m_view );
  m_view[0][1] = up.x;
  m_view[1][1] = up.y;
  m_view[2][1] = up.z;
  m_view[3][1] = dot( up, minus_pos );
}

void Camera::setForward( const glm::vec3& forward )
{
  glm::vec3 pos = -glm::vec3( m_view[3] ) * glm::mat3( m_view );
  m_view[0][0] = -forward.x;
  m_view[1][0] = -forward.y;
  m_view[2][0] = -forward.z;
  m_view[3][0] = dot( forward, pos );
}

const glm::mat4& Camera::projectionMatrix() const
{
    return m_projection;
}

void Camera::setProjectionMatrix(const glm::mat4& projection)
{
    m_projection = projection;
}

float Camera::fov() const
{
    return m_fov;
}

float Camera::ratio() const
{
    return m_ratio;
}

float Camera::znear() const
{
    return m_znear;
}

float Camera::zfar() const
{
    return m_zfar;
}

void Camera::setFov( const float& v )
{
    m_fov = v;
    m_projection = glm::perspective( m_fov, m_ratio, m_znear, m_zfar );
}

void Camera::setRatio( const float& v )
{
    m_ratio = v;
    m_projection = glm::perspective( m_fov, m_ratio, m_znear, m_zfar );
}

void Camera::setZfar( const float& v )
{
    m_zfar = v;
    m_projection = glm::perspective( m_fov, m_ratio, m_znear, m_zfar );
}

void Camera::setZnear( const float& v )
{
    m_znear = v;
    m_projection = glm::perspective( m_fov, m_ratio, m_znear, m_zfar );
}

Camera::CAMERA_MOUSE_BEHAVIOR Camera::getMouseBehavior() const
{
    return m_mouseBehavior;
}

void Camera::setMouseBehavior( const CAMERA_MOUSE_BEHAVIOR& v )
{
    m_mouseBehavior = v;
    if( m_mouseBehavior == ARCBALL_BEHAVIOR )
      {
        glm::vec3 pos = getPosition();
        glm::vec3 up = getUp();
        m_view = glm::lookAt(
            getPosition(),
            glm::vec3{},
            getUp());
      }
}

void Camera::update( float dx, float dy )
{
    switch( m_mouseBehavior )
    {
    case ARCBALL_BEHAVIOR:
    {
        glm::mat4 rotation = glm::rotate( glm::mat4( glm::mat3(m_view) ), dx, getUp());
        rotation = glm::rotate( rotation, dy, getRight());

        m_view[0] = rotation[0];
        m_view[1] = rotation[1];
        m_view[2] = rotation[2];

        setPosition(-glm::vec3(m_view[3]) * glm::mat3(rotation));
    }
        break;

    case SPACESHIP_BEHAVIOR:
    {
        const float cx = float( std::cos( dx ) );
        const float sx = float( std::sin( dx ) );
        const float cy = float( std::cos( dy ) );
        const float sy = float( std::sin( dy ) );

        glm::mat3 rotation = glm::mat3( m_view );
        glm::vec3 minus_pos = glm::vec3( m_view[3] ) * rotation;
        // build a rotation matrix to apply to the current rotation:
        //
        rotation = glm::mat3(
                    glm::vec3( cx, sx*sy,-sx*cy),
                    glm::vec3(  0,    cy,    sy),
                    glm::vec3( sx,-cx*sy, cx*cy) ) *rotation;
        for( int col = 0; col < 3; ++ col )
            for( int lin = 0; lin < 3; ++ lin )
            {
                m_view[col][lin] = rotation[col][lin];
            }
        m_view[3][0] = dot( minus_pos, getRight() );
        m_view[3][1] = dot( minus_pos, getUp() );
        m_view[3][2] = dot( minus_pos, -getForward() );
    }
        break;

    default:
        assert(false);
    }
}
<commit_msg>[Map] Camera modified<commit_after>#include "./../include/Camera.hpp"
#include <iostream>

#include <glm/gtc/type_precision.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

using namespace std;

Camera::Camera()
    : m_view{ glm::lookAt( glm::vec3{0, 0, -5}, glm::vec3{}, glm::vec3{0,1,0}) },
      m_fov{ 1.04f }, m_ratio{ 1.0f }, m_znear{ 1.0f }, m_zfar{ 1500.0f },
      m_mouseBehavior{ ARCBALL_BEHAVIOR }
{}

Camera::~Camera()
{

}

void Camera::animate(float time)
{
}

const glm::mat4& Camera::viewMatrix() const
{
    return m_view;
}

void Camera::setViewMatrix(const glm::mat4& view)
{
    m_view = view;
}

glm::vec3 Camera::getPosition() const
{
    return -glm::vec3( m_view[3] ) * glm::mat3( m_view );
}

glm::vec3 Camera::getRight() const
{
    return glm::vec3( m_view[0][0], m_view[1][0], m_view[2][0] );
}

glm::vec3 Camera::getUp() const
{
    return glm::vec3( m_view[0][1], m_view[1][1], m_view[2][1] );
}

glm::vec3 Camera::getForward() const
{
    return glm::vec3( -m_view[0][2], -m_view[1][2], -m_view[2][2] );
}

void Camera::setPosition( const glm::vec3& pos )
{
    for( int i = 0; i < 3; ++ i )
    {
        m_view[3][i] = float(0);
        for( int j = 0; j < 3; ++ j )
        {
            m_view[3][i] -= m_view[j][i] * pos[j];
        }
    }
}

void Camera::setRight( const glm::vec3& right )
{
    glm::vec3 minus_pos = glm::vec3( m_view[3] ) * glm::mat3( m_view );
    m_view[0][0] = right.x;
    m_view[1][0] = right.y;
    m_view[2][0] = right.z;
    m_view[3][0] = dot( right, minus_pos );
}

void Camera::setUp( const glm::vec3& up )
{
  glm::vec3 minus_pos = glm::vec3( m_view[3] ) * glm::mat3( m_view );
  m_view[0][1] = up.x;
  m_view[1][1] = up.y;
  m_view[2][1] = up.z;
  m_view[3][1] = dot( up, minus_pos );
}

void Camera::setForward( const glm::vec3& forward )
{
  glm::vec3 pos = -glm::vec3( m_view[3] ) * glm::mat3( m_view );
  m_view[0][0] = -forward.x;
  m_view[1][0] = -forward.y;
  m_view[2][0] = -forward.z;
  m_view[3][0] = dot( forward, pos );
}

const glm::mat4& Camera::projectionMatrix() const
{
    return m_projection;
}

void Camera::setProjectionMatrix(const glm::mat4& projection)
{
    m_projection = projection;
}

float Camera::fov() const
{
    return m_fov;
}

float Camera::ratio() const
{
    return m_ratio;
}

float Camera::znear() const
{
    return m_znear;
}

float Camera::zfar() const
{
    return m_zfar;
}

void Camera::setFov( const float& v )
{
    m_fov = v;
    m_projection = glm::perspective( m_fov, m_ratio, m_znear, m_zfar );
}

void Camera::setRatio( const float& v )
{
    m_ratio = v;
    m_projection = glm::perspective( m_fov, m_ratio, m_znear, m_zfar );
}

void Camera::setZfar( const float& v )
{
    m_zfar = v;
    m_projection = glm::perspective( m_fov, m_ratio, m_znear, m_zfar );
}

void Camera::setZnear( const float& v )
{
    m_znear = v;
    m_projection = glm::perspective( m_fov, m_ratio, m_znear, m_zfar );
}

Camera::CAMERA_MOUSE_BEHAVIOR Camera::getMouseBehavior() const
{
    return m_mouseBehavior;
}

void Camera::setMouseBehavior( const CAMERA_MOUSE_BEHAVIOR& v )
{
    m_mouseBehavior = v;
    if( m_mouseBehavior == ARCBALL_BEHAVIOR )
      {
        glm::vec3 pos = getPosition();
        glm::vec3 up = getUp();
        m_view = glm::lookAt(
            getPosition(),
            glm::vec3{},
            getUp());
      }
}

void Camera::update( float dx, float dy )
{
    switch( m_mouseBehavior )
    {
    case ARCBALL_BEHAVIOR:
    {
        glm::mat4 rotation = glm::rotate( glm::mat4( glm::mat3(m_view) ), dx, getUp());
        rotation = glm::rotate( rotation, dy, getRight());

        m_view[0] = rotation[0];
        m_view[1] = rotation[1];
        m_view[2] = rotation[2];

        setPosition(-glm::vec3(m_view[3]) * glm::mat3(rotation));
    }
        break;

    case SPACESHIP_BEHAVIOR:
    {
        const float cx = float( std::cos( dx ) );
        const float sx = float( std::sin( dx ) );
        const float cy = float( std::cos( dy ) );
        const float sy = float( std::sin( dy ) );

        glm::mat3 rotation = glm::mat3( m_view );
        glm::vec3 minus_pos = glm::vec3( m_view[3] ) * rotation;
        // build a rotation matrix to apply to the current rotation:
        //
        rotation = glm::mat3(
                    glm::vec3( cx, sx*sy,-sx*cy),
                    glm::vec3(  0,    cy,    sy),
                    glm::vec3( sx,-cx*sy, cx*cy) ) *rotation;
        for( int col = 0; col < 3; ++ col )
            for( int lin = 0; lin < 3; ++ lin )
            {
                m_view[col][lin] = rotation[col][lin];
            }
        m_view[3][0] = dot( minus_pos, getRight() );
        m_view[3][1] = dot( minus_pos, getUp() );
        m_view[3][2] = dot( minus_pos, -getForward() );
    }
        break;

    default:
        assert(false);
    }
}
<|endoftext|>


<commit_before>#include "stdsneezy.h"
#include "database.h"

void updateStockHistory()
{
  TDatabase db(DB_SNEEZY);

  db.query("insert into stockhistory select max(sh.n)+1, si.ticker, si.price from stockinfo si, stockhistory sh group by si.ticker, si.price");

  db.query("insert into stockhistory select max(sh.n), 'INDX', sum(si.price*si.shares)/sum(si.shares) from stockinfo si, stockhistory sh where sh.ticker=si.ticker");
}

void stockSplit(sstring ticker, float pricechange)
{
  TDatabase db(DB_SNEEZY);

  db.query("update stockinfo set shares=shares*2, price=(price/2)+%f where ticker='%s'", pricechange, ticker.c_str());

  db.query("update stockhistory set price=price/2 where ticker='%s'",
  	   ticker.c_str());

  //  db.query("insert into stockhistory select max(n), ticker, max(price) from stockhistory where ticker='%s' group by ticker", ticker.c_str());
  //  db.query("insert into stockhistory select max(n), ticker, min(price) from stockhistory where ticker='%s' group by ticker", ticker.c_str());
}

void stockReverseSplit(sstring ticker, float pricechange)
{
  TDatabase db(DB_SNEEZY);

  db.query("update stockinfo set shares=shares/10, price=(price*2)+%f where ticker='%s'", pricechange, ticker.c_str());

  db.query("update stockhistory set price=price*10 where ticker='%s'",
	   ticker.c_str());

  //  db.query("insert into stockhistory select max(n), ticker, max(price) from stockhistory where ticker='%s' group by ticker", ticker.c_str());
  //  db.query("insert into stockhistory select max(n), ticker, min(price) from stockhistory where ticker='%s' group by ticker", ticker.c_str());
}

void updateStocks()
{
  TDatabase db(DB_SNEEZY), stocks(DB_SNEEZY);

  stocks.query("select ticker, shares, price, (((random() * volatility * 2) - volatility) / 1000) as pricechange from stockinfo");

  while(stocks.fetchRow()){
    float pricechange=convertTo<float>(stocks["pricechange"]);
    float price=convertTo<float>(stocks["price"]);
    sstring ticker=stocks["ticker"];
    int shares=convertTo<int>(stocks["shares"]);

    if(shares<=0)
      continue;

    if((price+pricechange) < ::number(1,5)){
      stockReverseSplit(ticker, pricechange);
    } else if(price+pricechange > ::number(100, 125)){
      stockSplit(ticker, pricechange);
    } else {
      db.query("update stockinfo set price=price+%f where ticker='%s'",
	       pricechange, ticker.c_str());
    }

  }

}

int stockBoard(TBeing *ch, cmdTypeT cmd, const char *arg, TObj *o1, TObj *o2)
{
  int found=0;
  TThing *o;
  TObj *to;
  TDatabase db(DB_SNEEZY);
  float price, pricediff;
  int shares;

  if(cmd != CMD_LOOK)
    return FALSE;

  for (o = ch->roomp->getStuff(); o; o = o->nextThing) {
    to = dynamic_cast<TObj *>(o);
    if (to && to->spec == SPEC_STOCK_BOARD &&
	isname(arg, to->name)){
      found=1;
      break;
    }
  }

  if(!found)
    return FALSE;

  ch->sendTo("You examine the board:\n\r");
  ch->sendTo("------------------------------------------------------------\n\r");
  db.query("select sum(sh.price*si.shares)/sum(si.shares) as dayprice, sum(si.price*si.shares)/sum(si.shares) as price from stockinfo si, stockhistory sh, (select ticker, max(n) as n from stockhistory group by ticker) sn where sh.n=sn.n and si.ticker=sh.ticker");

  if(db.fetchRow()){
    price=convertTo<float>(db["price"]);
    pricediff=price-convertTo<float>(db["dayprice"]);

    ch->sendTo(COLOR_BASIC, fmt("Market: <Y>%.2f  %s%+.2f<1>\n\r") %
	       price % (pricediff>0?"<G>":"<R>") %
	       (convertTo<float>(db["dayprice"]) - price));
  }

  ch->sendTo("------------------------------------------------------------\n\r");
  ch->sendTo("Ticker   Bid    Ask  Change  Market Cap                                \n\r");
  ch->sendTo("------------------------------------------------------------\n\r");

  db.query("select distinct si.ticker, si.price, sh.price as dayprice, si.shares from stockinfo si, stockhistory sh, (select ticker, max(n) as n from stockhistory group by ticker) sn where sh.n=sn.n and si.ticker=sh.ticker and sn.ticker=si.ticker");

  while(db.fetchRow()){
    price=convertTo<float>(db["price"]);
    shares=convertTo<int>(db["shares"]);
    pricediff=price-convertTo<float>(db["dayprice"]);

    ch->sendTo(COLOR_BASIC, fmt("%-6s  <Y>%.2f  %.2f<1>  %s%+.2f<1>   %s\n\r") %
	       db["ticker"] % (price*0.97) % (price * 1.03) %
	       (pricediff>0?"<G>":"<R>") % pricediff %
	       talenDisplay((int)(price*(float)shares)));
  }

  ch->sendTo("------------------------------------------------------------\n\r");
  ch->sendTo("Price charts can be seen at: http://sneezy.saw.net/peel/stocks/\n\r");
  ch->sendTo("------------------------------------------------------------\n\r");

  return TRUE;
}

<commit_msg>typo fix<commit_after>#include "stdsneezy.h"
#include "database.h"

void updateStockHistory()
{
  TDatabase db(DB_SNEEZY);

  db.query("insert into stockhistory select max(sh.n)+1, si.ticker, si.price from stockinfo si, stockhistory sh group by si.ticker, si.price");

  db.query("insert into stockhistory select max(sh.n), 'INDX', sum(si.price*si.shares)/sum(si.shares) from stockinfo si, stockhistory sh where sh.ticker=si.ticker");
}

void stockSplit(sstring ticker, float pricechange)
{
  TDatabase db(DB_SNEEZY);

  db.query("update stockinfo set shares=shares*2, price=(price/2)+%f where ticker='%s'", pricechange, ticker.c_str());

  db.query("update stockhistory set price=price/2 where ticker='%s'",
  	   ticker.c_str());

  //  db.query("insert into stockhistory select max(n), ticker, max(price) from stockhistory where ticker='%s' group by ticker", ticker.c_str());
  //  db.query("insert into stockhistory select max(n), ticker, min(price) from stockhistory where ticker='%s' group by ticker", ticker.c_str());
}

void stockReverseSplit(sstring ticker, float pricechange)
{
  TDatabase db(DB_SNEEZY);

  db.query("update stockinfo set shares=shares/10, price=(price*2)+%f where ticker='%s'", pricechange, ticker.c_str());

  db.query("update stockhistory set price=price*10 where ticker='%s'",
	   ticker.c_str());

  //  db.query("insert into stockhistory select max(n), ticker, max(price) from stockhistory where ticker='%s' group by ticker", ticker.c_str());
  //  db.query("insert into stockhistory select max(n), ticker, min(price) from stockhistory where ticker='%s' group by ticker", ticker.c_str());
}

void updateStocks()
{
  TDatabase db(DB_SNEEZY), stocks(DB_SNEEZY);

  stocks.query("select ticker, shares, price, (((random() * volatility * 2) - volatility) / 1000) as pricechange from stockinfo");

  while(stocks.fetchRow()){
    float pricechange=convertTo<float>(stocks["pricechange"]);
    float price=convertTo<float>(stocks["price"]);
    sstring ticker=stocks["ticker"];
    int shares=convertTo<int>(stocks["shares"]);

    if(shares<=0)
      continue;

    if((price+pricechange) < ::number(1,5)){
      stockReverseSplit(ticker, pricechange);
    } else if(price+pricechange > ::number(100, 125)){
      stockSplit(ticker, pricechange);
    } else {
      db.query("update stockinfo set price=price+%f where ticker='%s'",
	       pricechange, ticker.c_str());
    }

  }

}

int stockBoard(TBeing *ch, cmdTypeT cmd, const char *arg, TObj *o1, TObj *o2)
{
  int found=0;
  TThing *o;
  TObj *to;
  TDatabase db(DB_SNEEZY);
  float price, pricediff;
  int shares;

  if(cmd != CMD_LOOK)
    return FALSE;

  for (o = ch->roomp->getStuff(); o; o = o->nextThing) {
    to = dynamic_cast<TObj *>(o);
    if (to && to->spec == SPEC_STOCK_BOARD &&
	isname(arg, to->name)){
      found=1;
      break;
    }
  }

  if(!found)
    return FALSE;

  ch->sendTo("You examine the board:\n\r");
  ch->sendTo("------------------------------------------------------------\n\r");
  db.query("select sum(sh.price*si.shares)/sum(si.shares) as dayprice, sum(si.price*si.shares)/sum(si.shares) as price from stockinfo si, stockhistory sh, (select ticker, max(n) as n from stockhistory group by ticker) sn where sh.n=sn.n and si.ticker=sh.ticker");

  if(db.fetchRow()){
    price=convertTo<float>(db["price"]);
    pricediff=price-convertTo<float>(db["dayprice"]);

    ch->sendTo(COLOR_BASIC, fmt("Market: <Y>%.2f  %s%+.2f<1>\n\r") %
	       price % (pricediff>0?"<G>":"<R>") %
	       (price - convertTo<float>(db["dayprice"])));
  }

  ch->sendTo("------------------------------------------------------------\n\r");
  ch->sendTo("Ticker   Bid    Ask  Change  Market Cap                                \n\r");
  ch->sendTo("------------------------------------------------------------\n\r");

  db.query("select distinct si.ticker, si.price, sh.price as dayprice, si.shares from stockinfo si, stockhistory sh, (select ticker, max(n) as n from stockhistory group by ticker) sn where sh.n=sn.n and si.ticker=sh.ticker and sn.ticker=si.ticker");

  while(db.fetchRow()){
    price=convertTo<float>(db["price"]);
    shares=convertTo<int>(db["shares"]);
    pricediff=price-convertTo<float>(db["dayprice"]);

    ch->sendTo(COLOR_BASIC, fmt("%-6s  <Y>%.2f  %.2f<1>  %s%+.2f<1>   %s\n\r") %
	       db["ticker"] % (price*0.97) % (price * 1.03) %
	       (pricediff>0?"<G>":"<R>") % pricediff %
	       talenDisplay((int)(price*(float)shares)));
  }

  ch->sendTo("------------------------------------------------------------\n\r");
  ch->sendTo("Price charts can be seen at: http://sneezy.saw.net/peel/stocks/\n\r");
  ch->sendTo("------------------------------------------------------------\n\r");

  return TRUE;
}

<|endoftext|>


<commit_before>#include <gtest/gtest.h>

#include "mcc/gas/gas.h"

#include "mcc/tac/float_literal.h"
#include "mcc/tac/helper/ast_converters.h"
#include "mcc/tac/int_literal.h"
#include "parser.h"
#include "test_utils.h"

#include <iostream>
#include <regex>

using namespace mcc::gas;

namespace mcc {
namespace gas {
TEST(Gas, FunctionStackSpace) {
  auto tree = parser::parse(
      R"(
         void bar(int arg1);

         void foo(int arg1) {
            if(arg1 < 0) return;
            bar(arg1 - 1);
         }

         void bar(int arg1) {
            if(arg1 < 0) return;
            foo(arg1 - 1);
            bar(arg1 - 1);
         }

          int main() {
             foo(10);
             return 0;
          }
        )");

  Tac tac = Tac(tree);
  Gas gas = Gas(tac);

  function_stack_space_map_type expected;

  auto l1 = std::make_shared<Label>("foo");
  auto l2 = std::make_shared<Label>("bar");
  auto l3 = std::make_shared<Label>("main");

  expected[l1] = 4;
  expected[l2] = 8;
  expected[l3] = 0;

  for (auto const e : expected) {
    auto result = gas.getRegisterManager()->lookupFunctionStackSpace(e.first);

    EXPECT_EQ(e.second, result);
  }
}

TEST(Gas, VariableStackOffset) {
  auto tree = parser::parse(
      R"(
         void bar(int arg1);

         void foo(int arg1, int arg2) {
            if(arg1 < 0) return;
            bar(arg1 - 1);
         }

         void bar(int arg1) {
            if(arg1 < 0) return;
            foo(arg1 - 1, arg1);
            bar(arg1 - 1);
         }

          int main() {
             foo(10, 10);
             return 0;
          }
        )");

  Tac tac = Tac(tree);
  Gas gas = Gas(tac);

  auto regMan = gas.getRegisterManager();

  Label::ptr_t currentFunction;
  int varCounter = 0;
  signed expectedOffsets[] = {8, 12, -4, -4, -8, 8, -4, -4, -8, -8, -12, -4};
  for (auto codeLine : tac.codeLines) {
    if (helper::isType<Label>(codeLine)) {
      auto label = std::static_pointer_cast<Label>(codeLine);
      if (label->isFunctionEntry()) {
        currentFunction = label;
      }
    }

    if (codeLine->containsTargetVar()) {
      auto targetVar = codeLine->getTargetVariable();
      auto targetVarOffset =
          regMan->lookupVariableStackOffset(currentFunction, targetVar);

      EXPECT_EQ(expectedOffsets[varCounter++], targetVarOffset);
    }
  }
}

/* Gas Conversion */
TEST(Gas, GasConversion) {
  auto tree = parser::parse(
      R"(
            void print_int(int out);
            int read_int();

            int fibonacci(int n) {
                if ( n == 0 )
                    return 0;
                else if ( n == 1 )
                    return 1;
                else
                    return (fibonacci(n-1) + fibonacci(n-2));
            }

            int main(void) {
                int i = read_int();
                int fib = fibonacci(i);
                print_int(fib);

                return 0;
            }
        )");

  auto tac = Tac(tree);
  Gas gas = Gas(tac);

  // get labels from tac
  auto labels = std::vector<std::string>();
  for (auto triple : tac.codeLines) {
    switch (triple->getOperator().getName()) {
      case OperatorName::LABEL: {
        auto label = std::static_pointer_cast<Label>(triple);
        if (!label->isFunctionEntry()) {
          labels.push_back(label->getValue());
        }
      } break;
      case OperatorName::JUMP: {
        auto label = std::static_pointer_cast<Label>(triple->getArg1());
        if (!label->isFunctionEntry()) {
          labels.push_back(label->getValue());
        }
      } break;
      case OperatorName::JUMPFALSE: {
        auto label = std::static_pointer_cast<Label>(triple->getArg2());
        if (!label->isFunctionEntry()) {
          labels.push_back(label->getValue());
        }
      } break;
      default:
        // ignore
        break;
    }
  }

  auto curLabel = labels.begin();

  auto expected = R"(.intel_syntax noprefix
.global main

fibonacci:
	push ebp
	mov ebp, esp
	sub esp, 20
	push ebx
	push edi
	push esi
	mov ecx, DWORD PTR [ebp + 8]
	cmp ecx, 0
	jne )" + *curLabel++ +
                  R"(
	mov eax, 0
	pop esi
	pop edi
	pop ebx
	add esp, 20
	mov esp, ebp
	pop ebp
	ret
	jmp )" + *curLabel++ +
                  R"(

)" + *curLabel++ +
                  R"(:
	cmp ecx, 1
	jne )" + *curLabel++ +
                  R"(
	mov eax, 1
	pop esi
	pop edi
	pop ebx
	add esp, 20
	mov esp, ebp
	pop ebp
	ret
	jmp )" + *curLabel++ +
                  R"(

)" + *curLabel++ +
                  R"(:
	mov eax, ecx
	sub eax, 1
	mov ebx, eax
	push ecx
	push edx
	push ebx
	call fibonacci
	add esp, 4
	pop edx
	pop ecx
	mov edx, eax
	mov eax, ecx
	sub eax, 2
	mov ebx, eax
	push ecx
	push edx
	push ebx
	call fibonacci
	add esp, 4
	pop edx
	pop ecx
	mov ebx, eax
	mov eax, edx
	add eax, ebx
	mov ecx, eax
	mov eax, ecx
	pop esi
	pop edi
	pop ebx
	add esp, 20
	mov esp, ebp
	pop ebp
	ret

)" + *curLabel++ +
                  R"(:

)" + *curLabel++ +
                  R"(:
	pop esi
	pop edi
	pop ebx
	add esp, 20
	mov esp, ebp
	pop ebp

main:
	push ebp
	mov ebp, esp
	sub esp, 8
	push ebx
	push edi
	push esi
	push ecx
	push edx
	call read_int
	pop edx
	pop ecx
	mov ebx, eax
	push ecx
	push edx
	push ebx
	call fibonacci
	add esp, 4
	pop edx
	pop ecx
	mov ebx, eax
	push ecx
	push edx
	push ebx
	call print_int
	add esp, 4
	pop edx
	pop ecx
	mov eax, 0
	pop esi
	pop edi
	pop ebx
	add esp, 8
	mov esp, ebp
	pop ebp
	ret

.att_syntax noprefix
)";

  EXPECT_EQ(expected, gas.toString());
}

TEST(Gas, GasAddIntegerConversion) {
  auto tree = parser::parse(
      R"(
        void main() {

        }
        )");

  Tac tac = Tac(tree);
  IntLiteral::ptr_t operandOne = std::make_shared<IntLiteral>(10);
  IntLiteral::ptr_t operandTwo = std::make_shared<IntLiteral>(15);
  Operator op = Operator(OperatorName::ADD);

  Triple::ptr_t addTriple =
      std::make_shared<Triple>(op, operandOne, operandTwo);
  tac.addLine(addTriple);

  Gas gas = Gas(tac);
  auto expected = R"(.intel_syntax noprefix
.global main

main:
	push ebp
	mov ebp, esp
	sub esp, 4
	push ebx
	push edi
	push esi
	mov eax, 10
	add eax, 15
	mov ebx, eax

.att_syntax noprefix
)";

  EXPECT_EQ(expected, gas.toString());
}

TEST(Gas, GasSubIntegerConversion) {
  auto tree = parser::parse(
      R"(
        void main() {

        }
        )");

  Tac tac = Tac(tree);
  IntLiteral::ptr_t operandOne = std::make_shared<IntLiteral>(10);
  IntLiteral::ptr_t operandTwo = std::make_shared<IntLiteral>(15);
  Operator op = Operator(OperatorName::SUB);

  Triple::ptr_t subTriple =
      std::make_shared<Triple>(op, operandOne, operandTwo);
  tac.addLine(subTriple);

  Gas gas = Gas(tac);
  auto expected = R"(.intel_syntax noprefix
.global main

main:
	push ebp
	mov ebp, esp
	sub esp, 4
	push ebx
	push edi
	push esi
	mov eax, 10
	sub eax, 15
	mov ebx, eax

.att_syntax noprefix
)";

  EXPECT_EQ(expected, gas.toString());
}

TEST(Gas, GasMulIntegerConversion) {
  auto tree = parser::parse(
      R"(
        void main() {

        }
        )");

  Tac tac = Tac(tree);
  IntLiteral::ptr_t operandOne = std::make_shared<IntLiteral>(10);
  IntLiteral::ptr_t operandTwo = std::make_shared<IntLiteral>(15);
  Operator op = Operator(OperatorName::MUL);

  Triple::ptr_t triple = std::make_shared<Triple>(op, operandOne, operandTwo);
  tac.addLine(triple);

  Gas gas = Gas(tac);

  auto expected = R"(.intel_syntax noprefix
.global main

main:
	push ebp
	mov ebp, esp
	sub esp, 4
	push ebx
	push edi
	push esi
	mov eax, 10
	imul eax, 15
	mov ebx, eax

.att_syntax noprefix
)";

  EXPECT_EQ(expected, gas.toString());
}

TEST(Gas, GasAddFloatConversion) {
  auto tree = parser::parse(
      R"(
        void main() {

        }
        )");

  Tac tac = Tac(tree);
  FloatLiteral::ptr_t operandOne = std::make_shared<FloatLiteral>(10.0);
  FloatLiteral::ptr_t operandTwo = std::make_shared<FloatLiteral>(15.0);
  Operator op = Operator(OperatorName::ADD);

  Triple::ptr_t triple = std::make_shared<Triple>(op, operandOne, operandTwo);
  tac.addLine(triple);

  Gas gas = Gas(tac);

  auto expected = R"(.intel_syntax noprefix
.global main

main:
	push ebp
	mov ebp, esp
	sub esp, 4
	push ebx
	push edi
	push esi
	fld DWORD PTR .FC0
	fld DWORD PTR .FC1
	faddp st(1), st
	fstp DWORD PTR [ebp - 4]
	mov ebx, DWORD PTR [ebp - 4]

.FC0: .float 10.000000
.FC1: .float 15.000000

.att_syntax noprefix
)";

  EXPECT_EQ(expected, gas.toString());
}

TEST(Gas, GasSubFloatConversion) {
  auto tree = parser::parse(
      R"(
        void main() {

        }
        )");

  Tac tac = Tac(tree);
  FloatLiteral::ptr_t operandOne = std::make_shared<FloatLiteral>(10.0);
  FloatLiteral::ptr_t operandTwo = std::make_shared<FloatLiteral>(15.0);
  Operator op = Operator(OperatorName::SUB);

  Triple::ptr_t triple = std::make_shared<Triple>(op, operandOne, operandTwo);
  tac.addLine(triple);

  Gas gas = Gas(tac);

  auto expected = R"(.intel_syntax noprefix
.global main

main:
	push ebp
	mov ebp, esp
	sub esp, 4
	push ebx
	push edi
	push esi
	fld DWORD PTR .FC0
	fld DWORD PTR .FC1
	fsubp st(1), st
	fstp DWORD PTR [ebp - 4]
	mov ebx, DWORD PTR [ebp - 4]

.FC0: .float 10.000000
.FC1: .float 15.000000

.att_syntax noprefix
)";

  EXPECT_EQ(expected, gas.toString());
}

TEST(Gas, GasMulFloatConversion) {
  auto tree = parser::parse(
      R"(
        void main() {

        }
        )");

  Tac tac = Tac(tree);
  FloatLiteral::ptr_t operandOne = std::make_shared<FloatLiteral>(10.0);
  FloatLiteral::ptr_t operandTwo = std::make_shared<FloatLiteral>(15.0);
  Operator op = Operator(OperatorName::MUL);

  Triple::ptr_t triple = std::make_shared<Triple>(op, operandOne, operandTwo);
  tac.addLine(triple);

  Gas gas = Gas(tac);

  auto expected = R"(.intel_syntax noprefix
.global main

main:
	push ebp
	mov ebp, esp
	sub esp, 4
	push ebx
	push edi
	push esi
	fld DWORD PTR .FC0
	fld DWORD PTR .FC1
	fmulp st(1), st
	fstp DWORD PTR [ebp - 4]
	mov ebx, DWORD PTR [ebp - 4]

.FC0: .float 10.000000
.FC1: .float 15.000000

.att_syntax noprefix
)";

  EXPECT_EQ(expected, gas.toString());
}

TEST(Gas, GasDivFloatConversion) {
  auto tree = parser::parse(
      R"(
        void main() {

        }
        )");

  Tac tac = Tac(tree);
  FloatLiteral::ptr_t operandOne = std::make_shared<FloatLiteral>(10.0);
  FloatLiteral::ptr_t operandTwo = std::make_shared<FloatLiteral>(15.0);
  Operator op = Operator(OperatorName::DIV);

  Triple::ptr_t triple = std::make_shared<Triple>(op, operandOne, operandTwo);
  tac.addLine(triple);

  Gas gas = Gas(tac);

  auto expected = R"(.intel_syntax noprefix
.global main

main:
	push ebp
	mov ebp, esp
	sub esp, 4
	push ebx
	push edi
	push esi
	fld DWORD PTR .FC0
	fld DWORD PTR .FC1
	fdivp st(1), st
	fstp DWORD PTR [ebp - 4]
	mov ebx, DWORD PTR [ebp - 4]

.FC0: .float 10.000000
.FC1: .float 15.000000

.att_syntax noprefix
)";

  EXPECT_EQ(expected, gas.toString());
}
}
}
<commit_msg>temporarily fixed tests<commit_after>#include <gtest/gtest.h>

#include "mcc/gas/gas.h"

#include "mcc/tac/float_literal.h"
#include "mcc/tac/helper/ast_converters.h"
#include "mcc/tac/int_literal.h"
#include "parser.h"
#include "test_utils.h"

#include <iostream>
#include <regex>

using namespace mcc::gas;

namespace mcc {
namespace gas {
TEST(Gas, FunctionStackSpace) {
  auto tree = parser::parse(
      R"(
         void bar(int arg1);

         void foo(int arg1) {
            if(arg1 < 0) return;
            bar(arg1 - 1);
         }

         void bar(int arg1) {
            if(arg1 < 0) return;
            foo(arg1 - 1);
            bar(arg1 - 1);
         }

          int main() {
             foo(10);
             return 0;
          }
        )");

  Tac tac = Tac(tree);
  Gas gas = Gas(tac);

  function_stack_space_map_type expected;

  auto l1 = std::make_shared<Label>("foo");
  auto l2 = std::make_shared<Label>("bar");
  auto l3 = std::make_shared<Label>("main");

  expected[l1] = 4;
  expected[l2] = 8;
  expected[l3] = 0;

  for (auto const e : expected) {
    auto result = gas.getRegisterManager()->lookupFunctionStackSpace(e.first);

    EXPECT_EQ(e.second, result);
  }
}

TEST(Gas, VariableStackOffset) {
  auto tree = parser::parse(
      R"(
         void bar(int arg1);

         void foo(int arg1, int arg2) {
            if(arg1 < 0) return;
            bar(arg1 - 1);
         }

         void bar(int arg1) {
            if(arg1 < 0) return;
            foo(arg1 - 1, arg1);
            bar(arg1 - 1);
         }

          int main() {
             foo(10, 10);
             return 0;
          }
        )");

  Tac tac = Tac(tree);
  Gas gas = Gas(tac);

  auto regMan = gas.getRegisterManager();

  Label::ptr_t currentFunction;
  int varCounter = 0;
  signed expectedOffsets[] = {8, 12, -4, -4, -8, 8, -4, -4, -8, -8, -12, -4};
  for (auto codeLine : tac.codeLines) {
    if (helper::isType<Label>(codeLine)) {
      auto label = std::static_pointer_cast<Label>(codeLine);
      if (label->isFunctionEntry()) {
        currentFunction = label;
      }
    }

    if (codeLine->containsTargetVar()) {
      auto targetVar = codeLine->getTargetVariable();
      auto targetVarOffset =
          regMan->lookupVariableStackOffset(currentFunction, targetVar);

      EXPECT_EQ(expectedOffsets[varCounter++], targetVarOffset);
    }
  }
}

/* Gas Conversion */
TEST(Gas, GasConversion) {
  auto tree = parser::parse(
      R"(
            void print_int(int out);
            int read_int();

            int fibonacci(int n) {
                if ( n == 0 )
                    return 0;
                else if ( n == 1 )
                    return 1;
                else
                    return (fibonacci(n-1) + fibonacci(n-2));
            }

            int main(void) {
                int i = read_int();
                int fib = fibonacci(i);
                print_int(fib);

                return 0;
            }
        )");

  auto tac = Tac(tree);
  Gas gas = Gas(tac);

  // get labels from tac
  auto labels = std::vector<std::string>();
  for (auto triple : tac.codeLines) {
    switch (triple->getOperator().getName()) {
      case OperatorName::LABEL: {
        auto label = std::static_pointer_cast<Label>(triple);
        if (!label->isFunctionEntry()) {
          labels.push_back(label->getValue());
        }
      } break;
      case OperatorName::JUMP: {
        auto label = std::static_pointer_cast<Label>(triple->getArg1());
        if (!label->isFunctionEntry()) {
          labels.push_back(label->getValue());
        }
      } break;
      case OperatorName::JUMPFALSE: {
        auto label = std::static_pointer_cast<Label>(triple->getArg2());
        if (!label->isFunctionEntry()) {
          labels.push_back(label->getValue());
        }
      } break;
      default:
        // ignore
        break;
    }
  }

  auto curLabel = labels.begin();

  auto expected = R"(.intel_syntax noprefix
.global main

fibonacci:
	push ebp
	mov ebp, esp
	sub esp, 20
	push ebx
	push edi
	push esi
	mov edx, DWORD PTR [ebp + 8]
	cmp edx, 0
	jne )" + *curLabel++ +
                  R"(
	mov eax, 0
	pop esi
	pop edi
	pop ebx
	add esp, 20
	mov esp, ebp
	pop ebp
	ret
	jmp )" + *curLabel++ +
                  R"(

)" + *curLabel++ +
                  R"(:
	cmp edx, 1
	jne )" + *curLabel++ +
                  R"(
	mov eax, 1
	pop esi
	pop edi
	pop ebx
	add esp, 20
	mov esp, ebp
	pop ebp
	ret
	jmp )" + *curLabel++ +
                  R"(

)" + *curLabel++ +
                  R"(:
	mov eax, edx
	sub eax, 1
	mov ecx, eax
	push ecx
	push edx
	push ecx
	call fibonacci
	add esp, 4
	pop edx
	pop ecx
	mov esi, eax
	mov ebx, edx
	sub ebx, 2
	mov ecx, ebx
	push ecx
	push edx
	push ecx
	call fibonacci
	add esp, 4
	pop edx
	pop ecx
	mov ecx, eax
	mov eax, esi
	add eax, ecx
	mov edx, eax
	mov eax, edx
	pop esi
	pop edi
	pop ebx
	add esp, 20
	mov esp, ebp
	pop ebp
	ret

)" + *curLabel++ +
                  R"(:

)" + *curLabel++ +
                  R"(:
	pop esi
	pop edi
	pop ebx
	add esp, 20
	mov esp, ebp
	pop ebp

main:
	push ebp
	mov ebp, esp
	sub esp, 8
	push ebx
	push edi
	push esi
	push ecx
	push edx
	call read_int
	pop edx
	pop ecx
	mov ecx, eax
	push ecx
	push edx
	push ecx
	call fibonacci
	add esp, 4
	pop edx
	pop ecx
	mov ecx, eax
	push ecx
	push edx
	push ecx
	call print_int
	add esp, 4
	pop edx
	pop ecx
	mov eax, 0
	pop esi
	pop edi
	pop ebx
	add esp, 8
	mov esp, ebp
	pop ebp
	ret

.att_syntax noprefix
)";

  EXPECT_EQ(expected, gas.toString());
}

TEST(Gas, GasAddIntegerConversion) {
  auto tree = parser::parse(
      R"(
        void main() {

        }
        )");

  Tac tac = Tac(tree);
  IntLiteral::ptr_t operandOne = std::make_shared<IntLiteral>(10);
  IntLiteral::ptr_t operandTwo = std::make_shared<IntLiteral>(15);
  Operator op = Operator(OperatorName::ADD);

  Triple::ptr_t addTriple =
      std::make_shared<Triple>(op, operandOne, operandTwo);
  tac.addLine(addTriple);

  Gas gas = Gas(tac);
  auto expected = R"(.intel_syntax noprefix
.global main

main:
	push ebp
	mov ebp, esp
	sub esp, 4
	push ebx
	push edi
	push esi
	mov eax, 10
	add eax, 15
	mov ecx, eax

.att_syntax noprefix
)";

  EXPECT_EQ(expected, gas.toString());
}

TEST(Gas, GasSubIntegerConversion) {
  auto tree = parser::parse(
      R"(
        void main() {

        }
        )");

  Tac tac = Tac(tree);
  IntLiteral::ptr_t operandOne = std::make_shared<IntLiteral>(10);
  IntLiteral::ptr_t operandTwo = std::make_shared<IntLiteral>(15);
  Operator op = Operator(OperatorName::SUB);

  Triple::ptr_t subTriple =
      std::make_shared<Triple>(op, operandOne, operandTwo);
  tac.addLine(subTriple);

  Gas gas = Gas(tac);
  auto expected = R"(.intel_syntax noprefix
.global main

main:
	push ebp
	mov ebp, esp
	sub esp, 4
	push ebx
	push edi
	push esi
	mov eax, 10
	sub eax, 15
	mov ecx, eax

.att_syntax noprefix
)";

  EXPECT_EQ(expected, gas.toString());
}

TEST(Gas, GasMulIntegerConversion) {
  auto tree = parser::parse(
      R"(
        void main() {

        }
        )");

  Tac tac = Tac(tree);
  IntLiteral::ptr_t operandOne = std::make_shared<IntLiteral>(10);
  IntLiteral::ptr_t operandTwo = std::make_shared<IntLiteral>(15);
  Operator op = Operator(OperatorName::MUL);

  Triple::ptr_t triple = std::make_shared<Triple>(op, operandOne, operandTwo);
  tac.addLine(triple);

  Gas gas = Gas(tac);

  auto expected = R"(.intel_syntax noprefix
.global main

main:
	push ebp
	mov ebp, esp
	sub esp, 4
	push ebx
	push edi
	push esi
	mov ebx, 10
	imul ebx, 15
	mov ecx, ebx

.att_syntax noprefix
)";

  EXPECT_EQ(expected, gas.toString());
}

TEST(Gas, GasAddFloatConversion) {
  auto tree = parser::parse(
      R"(
        void main() {

        }
        )");

  Tac tac = Tac(tree);
  FloatLiteral::ptr_t operandOne = std::make_shared<FloatLiteral>(10.0);
  FloatLiteral::ptr_t operandTwo = std::make_shared<FloatLiteral>(15.0);
  Operator op = Operator(OperatorName::ADD);

  Triple::ptr_t triple = std::make_shared<Triple>(op, operandOne, operandTwo);
  tac.addLine(triple);

  Gas gas = Gas(tac);

  auto expected = R"(.intel_syntax noprefix
.global main

main:
	push ebp
	mov ebp, esp
	sub esp, 4
	push ebx
	push edi
	push esi
	fld DWORD PTR .FC0
	fld DWORD PTR .FC1
	faddp st(1), st
	fstp DWORD PTR [ebp - 4]
	mov ecx, DWORD PTR [ebp - 4]

.FC0: .float 10.000000
.FC1: .float 15.000000

.att_syntax noprefix
)";

  EXPECT_EQ(expected, gas.toString());
}

TEST(Gas, GasSubFloatConversion) {
  auto tree = parser::parse(
      R"(
        void main() {

        }
        )");

  Tac tac = Tac(tree);
  FloatLiteral::ptr_t operandOne = std::make_shared<FloatLiteral>(10.0);
  FloatLiteral::ptr_t operandTwo = std::make_shared<FloatLiteral>(15.0);
  Operator op = Operator(OperatorName::SUB);

  Triple::ptr_t triple = std::make_shared<Triple>(op, operandOne, operandTwo);
  tac.addLine(triple);

  Gas gas = Gas(tac);

  auto expected = R"(.intel_syntax noprefix
.global main

main:
	push ebp
	mov ebp, esp
	sub esp, 4
	push ebx
	push edi
	push esi
	fld DWORD PTR .FC0
	fld DWORD PTR .FC1
	fsubp st(1), st
	fstp DWORD PTR [ebp - 4]
	mov ecx, DWORD PTR [ebp - 4]

.FC0: .float 10.000000
.FC1: .float 15.000000

.att_syntax noprefix
)";

  EXPECT_EQ(expected, gas.toString());
}

TEST(Gas, GasMulFloatConversion) {
  auto tree = parser::parse(
      R"(
        void main() {

        }
        )");

  Tac tac = Tac(tree);
  FloatLiteral::ptr_t operandOne = std::make_shared<FloatLiteral>(10.0);
  FloatLiteral::ptr_t operandTwo = std::make_shared<FloatLiteral>(15.0);
  Operator op = Operator(OperatorName::MUL);

  Triple::ptr_t triple = std::make_shared<Triple>(op, operandOne, operandTwo);
  tac.addLine(triple);

  Gas gas = Gas(tac);

  auto expected = R"(.intel_syntax noprefix
.global main

main:
	push ebp
	mov ebp, esp
	sub esp, 4
	push ebx
	push edi
	push esi
	fld DWORD PTR .FC0
	fld DWORD PTR .FC1
	fmulp st(1), st
	fstp DWORD PTR [ebp - 4]
	mov ecx, DWORD PTR [ebp - 4]

.FC0: .float 10.000000
.FC1: .float 15.000000

.att_syntax noprefix
)";

  EXPECT_EQ(expected, gas.toString());
}

TEST(Gas, GasDivFloatConversion) {
  auto tree = parser::parse(
      R"(
        void main() {

        }
        )");

  Tac tac = Tac(tree);
  FloatLiteral::ptr_t operandOne = std::make_shared<FloatLiteral>(10.0);
  FloatLiteral::ptr_t operandTwo = std::make_shared<FloatLiteral>(15.0);
  Operator op = Operator(OperatorName::DIV);

  Triple::ptr_t triple = std::make_shared<Triple>(op, operandOne, operandTwo);
  tac.addLine(triple);

  Gas gas = Gas(tac);

  auto expected = R"(.intel_syntax noprefix
.global main

main:
	push ebp
	mov ebp, esp
	sub esp, 4
	push ebx
	push edi
	push esi
	fld DWORD PTR .FC0
	fld DWORD PTR .FC1
	fdivp st(1), st
	fstp DWORD PTR [ebp - 4]
	mov ecx, DWORD PTR [ebp - 4]

.FC0: .float 10.000000
.FC1: .float 15.000000

.att_syntax noprefix
)";

  EXPECT_EQ(expected, gas.toString());
}
}
}
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>

// optimize stack size
class Stack
{
    public:
        Stack() { head = 0; }

        void Push(char val) { body[head++] = val; }
        char Pop() { return body[--head]; }
        char Peek() { return body[head-1]; }
        bool isEmpty() { return head == 0; }
    private:
        char body[100];
        int head;
};

enum class InputType
{
    Console,
    File,
    Constructor
};

class CalculationNotDoneException: public std::exception
{
    virtual const char* what() const throw()
    {
        return "The Input() method should be executed before Output()";
    }
} calc_not_done;

class Calculator
{
    public:
        std::string InputFileName;
        std::string OutputFileName;

        Calculator() :
            InputFileName("Input.txt"),
            OutputFileName("Output.txt"),
            result(0),
            calculationDone(false)
        {
            // empty constructor, totally legit
        }

        Calculator(const InputType& inputFrom)
        {
            Calculator();

            Input(inputFrom);
        }

        Calculator(const InputType& inputFrom, const std::string& expression)
        {
            Calculator();

            Input(inputFrom, expression);
        }

        Calculator(const InputType& inputFrom, const std::string& inputFileName, const std::string& outputFileName)
        {
            Calculator();

            InputFileName = inputFileName;
            OutputFileName = outputFileName;

            Input(inputFrom);
        }

        void Input(const InputType& inputFrom, const std::string& expression = "")
        {
            if (InputType::Console == inputFrom)
            {
                std::getline(std::cin, input);
            }
            else if (InputType::File == inputFrom)
            {
                std::ifstream inputFile(InputFileName);

                if (inputFile.is_open())
                {
                    std::getline(inputFile, input);

                    inputFile.close();
                }
                else
                {
                    std::cout << "Can't open a file named " << InputFileName << std::endl;

                    return;
                }
            }
            else if (InputType::Constructor == inputFrom)
            {
                input = expression;
            }

            processInput();
        }

        double Output()
        {
            if (!calculationDone) throw calc_not_done;

            if (InputType::Console == inputType)
            {
                std::cout << result << std::endl;
            }
            else if (InputType::File == inputType)
            {
                std::ofstream outputFile(OutputFileName);

                if (outputFile.is_open())
                {
                    outputFile << result << std::endl;

                    outputFile.close();
                }
                else
                {
                    std::cout << "Can't read a file named " << OutputFileName << std::endl;

                    return result;
                }
            }
            else if (InputType::Constructor == inputType)
            {
                // nothing specific, just return the result
            }

            calculationDone = false;

            return result;
        }

    private:
        double result;
        bool calculationDone;
        InputType inputType;
        std::string input;

        void processInput()
        {
            Stack st;
            std::string out;

            for (int i = 0; i < input.length(); ++i)
            {
                char c = input[i];

                if (c == ')')
                {
                    while (st.Peek() != '(')
                    {
                        out += st.Pop();
                    }

                    st.Pop();
                }

                if (c >= '0' && c <= '9')
                {
                    out += c;
                }

                if (c == '(')
                {
                    st.Push(c);
                }

                if(c == '+' || c == '-' || c == '/' || c == '*')
                {
                    if (st.isEmpty())
                    {
                        st.Push(c);
                    }
                    else
                    {
                        if (priority(st.Peek()) < priority(c))
                        {
                            st.Push(c);
                        }
                        else
                        {
                            while (!st.isEmpty() && (priority(st.Peek()) >= priority(c)))
                            {
                                out += st.Pop();
                            }

                            st.Push(c);
                        }
                    }
                }
            }

            while (!st.isEmpty())
            {
                out += st.Pop();
            }

            std::cout << "Polish notation: " << out << std::endl;
        }

        int priority(char sign)
        {
            switch(sign)
            {
                case '*':
                case '/':
                    return 3;

                case '-':
                case '+':
                    return 2;

                case '(':
                    return 1;
            }
        }

        double calculate()
        {
            // calculate

            calculationDone = true;
        }
};

// add an option to use command line arguments
// int argc, char* argv[]
int main()
{
    // Use case #1 - expression comes from console
    auto calc1 = new Calculator(InputType::Console); // Input() method called automatically
    calc1->Output();

    // Use case #2 - expression comes from file
    auto calc2 = new Calculator(InputType::File, "test.in", "test.out"); // custom filenames
    calc2->Output();

    // Use case #3 - expression in a constructor
    auto calc3 = new Calculator(InputType::Constructor, "2 * 5 - 7 / 3 + (2 - 1 / 2)"); // brackets supported
    calc3->Output();
}
<commit_msg>Finished implementation of calculation using polish notation<commit_after>#include <iostream>
#include <fstream>
#include <string>
#include <stack>

enum class InputType
{
    Console,
    File,
    Constructor
};

class CalculationNotDoneException: public std::exception
{
    virtual const char* what() const throw()
    {
        return "The Input() method should be executed before Output()";
    }
} calc_not_done;

class Calculator
{
    public:
        std::string InputFileName;
        std::string OutputFileName;

        Calculator() :
            InputFileName("Input.txt"),
            OutputFileName("Output.txt"),
            result(0),
            calculationDone(false)
        {
            // empty constructor, totally legit
        }

        Calculator(const InputType& inputFrom)
        {
            Calculator();

            Input(inputFrom);
        }

        Calculator(const InputType& inputFrom, const std::string& expression)
        {
            Calculator();

            Input(inputFrom, expression);
        }

        Calculator(const InputType& inputFrom, const std::string& inputFileName, const std::string& outputFileName)
        {
            Calculator();

            InputFileName = inputFileName;
            OutputFileName = outputFileName;

            Input(inputFrom);
        }

        void Input(const InputType& inputFrom, const std::string& expression = "")
        {
            inputType = inputFrom;

            if (InputType::Console == inputType)
            {
                std::getline(std::cin, input);
            }
            else if (InputType::File == inputType)
            {
                std::ifstream inputFile(InputFileName);

                if (inputFile.is_open())
                {
                    std::getline(inputFile, input);

                    inputFile.close();
                }
                else
                {
                    std::cout << "Can't read from file named " << InputFileName << std::endl;

                    return;
                }
            }
            else if (InputType::Constructor == inputType)
            {
                input = expression;
            }

            processInput();
        }

        long Output()
        {
            if (!calculationDone) throw calc_not_done;

            if (InputType::Console == inputType)
            {
                std::cout << result << std::endl;
            }
            else if (InputType::File == inputType)
            {
                std::ofstream outputFile(OutputFileName);

                if (outputFile.is_open())
                {
                    outputFile << result << std::endl;

                    outputFile.close();
                }
                else
                {
                    std::cout << "Can't create a file named " << OutputFileName << std::endl;

                    return result;
                }
            }
            else if (InputType::Constructor == inputType)
            {
                // nothing specific, just return the result
            }

            calculationDone = false;

            return result;
        }

    private:
        long result;
        bool calculationDone;
        InputType inputType;
        std::string input;

        // add ^ operator
        void processInput()
        {
            std::stack<char> st;
            std::string out;

            for (int i = 0; i < input.length(); ++i)
            {
                char c = input[i];

                if (c == ')')
                {
                    while (st.top() != '(')
                    {
                        out += st.top();
                        st.pop();
                    }
                    st.pop();
                }

                if (c >= '0' && c <= '9')
                {
                    out += c;
                }

                if (c == '(')
                {
                    st.push(c);
                }

                if(c == '+' || c == '-' || c == '/' || c == '*')
                {
                    if (st.empty())
                    {
                        st.push(c);
                    }
                    else
                    {
                        if (operationPriority(st.top()) < operationPriority(c))
                        {
                            st.push(c);
                        }
                        else
                        {
                            while (!st.empty() && (operationPriority(st.top()) >= operationPriority(c)))
                            {
                                out += st.top();
                                st.pop();
                            }

                            st.push(c);
                        }
                    }
                }
            }

            while (!st.empty())
            {
                out += st.top();
                st.pop();
            }

            input = out;

            calculateOutput();
        }

        // add ^ operator
        int operationPriority(char sign)
        {
            switch(sign)
            {
                case '*':
                case '/':
                    return 3;

                case '-':
                case '+':
                    return 2;

                case '(':
                    return 1;
            }
        }

        // add ^ operator
        long calculateOutput()
        {
            std::stack<std::string> st;

            for (int i = 0; i < input.length(); ++i)
            {
                char c = input[i];

                if(c == '+' || c == '-' || c == '*' || c == '/')
                {
                    long a = std::stol(st.top());
                    st.pop();
                    long b = std::stol(st.top());
                    st.pop();

                    switch(c)
                    {
                        case '+':
                            st.push(std::to_string(a + b));
                            break;

                        case '-':
                            st.push(std::to_string(a - b));
                            break;

                        case '*':
                            st.push(std::to_string(a * b));
                            break;

                        case '/':
                            st.push(std::to_string(a / b));
                            break;
                    }
                }
                else
                {
                    st.push(std::to_string(c));
                }
            }

            result = std::stol(st.top());

            calculationDone = true;
        }
};

// add an option to use command line arguments
// int argc, char* argv[]
int main()
{
    // Use case #1 - expression comes from console
    auto calc1 = new Calculator(InputType::Console); // Input() method called automatically
    calc1->Output();

    // Use case #2 - expression comes from file
    auto calc2 = new Calculator(InputType::File, "test.in", "test.out"); // custom filenames
    calc2->Output();

    // Use case #3 - expression in a constructor
    auto calc3 = new Calculator(InputType::Constructor, "2 * 5 - 7 / 3 + (2 - 1 / 2)"); // brackets supported
    calc3->Output();
}
<|endoftext|>


<commit_before>#include "xchainer/memory.h"

#include <cassert>

#ifdef XCHAINER_ENABLE_CUDA
#include <cuda.h>
#include <cuda_runtime.h>
#endif  // XCHAINER_ENABLE_CUDA

#include "xchainer/backend.h"
#ifdef XCHAINER_ENABLE_CUDA
#include "xchainer/cuda/cuda_runtime.h"
#endif  // XCHAINER_ENABLE_CUDA
#include "xchainer/device_id.h"
#include "xchainer/error.h"

#include <iostream>

namespace xchainer {
namespace internal {

bool IsPointerCudaMemory(const void* ptr) {
#ifdef XCHAINER_ENABLE_CUDA
    cudaPointerAttributes attr = {};
    cudaError_t status = cudaPointerGetAttributes(&attr, ptr);
    switch (status) {
        case cudaSuccess:
            if (attr.isManaged) {
                return true;
            } else {
                throw XchainerError("Non-managed GPU memory is not supported");
            }
        case cudaErrorInvalidValue:
            return false;
        default:
            cuda::CheckError(status);
            break;
    }
    assert(false);  // should never be reached
#else
    (void)ptr;  // unused
    return false;
#endif  // XCHAINER_ENABLE_CUDA
}

std::shared_ptr<void> Allocate(const DeviceId& device_id, size_t bytesize) {
    // TODO(sonots): Use device_id.backend->Allocate()
    if (device_id.backend()->GetName() == "native") {
        return std::make_unique<uint8_t[]>(bytesize);
#ifdef XCHAINER_ENABLE_CUDA
    } else if (device_id.backend()->GetName() == "cuda") {
        void* raw_ptr = nullptr;
        // Be careful to be exception-safe, i.e., do not throw before creating shared_ptr
        cudaError_t status = cudaMallocManaged(&raw_ptr, bytesize, cudaMemAttachGlobal);
        if (status == cudaSuccess) {
            return std::shared_ptr<void>{raw_ptr, cudaFree};
        } else {
            cuda::Throw(status);
        }
        assert(false);  // should never be reached
#endif                  // XCHAINER_ENABLE_CUDA
    } else {
        throw DeviceError("invalid device_id");
    }
}

void MemoryCopy(void* dst_ptr, const void* src_ptr, size_t bytesize) {
#ifdef XCHAINER_ENABLE_CUDA
    bool is_dst_cuda_memory = IsPointerCudaMemory(dst_ptr);
    bool is_src_cuda_memory = IsPointerCudaMemory(src_ptr);
    if (is_dst_cuda_memory) {
        if (is_src_cuda_memory) {
            // Copy from device_id to device_id is faster even in unified memory
            cuda::CheckError(cudaMemcpy(dst_ptr, src_ptr, bytesize, cudaMemcpyDeviceToDevice));
        } else {
            // For pre-6.x GPU architecture, we encountered SEGV with std::memcpy
            // ref. https://github.com/pfnet/xchainer/pull/74
            cuda::CheckError(cudaMemcpy(dst_ptr, src_ptr, bytesize, cudaMemcpyHostToDevice));
        }
    } else {
        if (is_src_cuda_memory) {
            // For pre-6.x GPU architecture, we encountered SEGV with std::memcpy
            // ref. https://github.com/pfnet/xchainer/pull/74
            cuda::CheckError(cudaMemcpy(dst_ptr, src_ptr, bytesize, cudaMemcpyDeviceToHost));
        } else {
            std::memcpy(dst_ptr, src_ptr, bytesize);
        }
    }
#else
    std::memcpy(dst_ptr, src_ptr, bytesize);
#endif  // XCHAINER_ENABLE_CUDA
}

std::shared_ptr<void> MemoryFromBuffer(const DeviceId& device_id, const std::shared_ptr<void>& src_ptr, size_t bytesize) {
// TODO(sonots): Use device_id.backend->FromBuffer()
#ifdef XCHAINER_ENABLE_CUDA
    if (device_id.backend()->GetName() == "native") {
        if (IsPointerCudaMemory(src_ptr.get())) {
            std::shared_ptr<void> dst_ptr = Allocate(device_id, bytesize);
            cuda::CheckError(cudaMemcpy(dst_ptr.get(), src_ptr.get(), bytesize, cudaMemcpyDeviceToHost));
            return dst_ptr;
        } else {
            return src_ptr;
        }
    } else if (device_id.backend()->GetName() == "cuda") {
        if (IsPointerCudaMemory(src_ptr.get())) {
            return src_ptr;
        } else {
            std::shared_ptr<void> dst_ptr = Allocate(device_id, bytesize);
            cuda::CheckError(cudaMemcpy(dst_ptr.get(), src_ptr.get(), bytesize, cudaMemcpyHostToDevice));
            return dst_ptr;
        }
    } else {
        throw DeviceError("invalid device_id");
    }
#else
    (void)bytesize;  // unused
    if (device_id.backend()->GetName() == "native") {
        return src_ptr;
    } else {
        throw DeviceError("invalid device_id");
    }
#endif  // XCHAINER_ENABLE_CUDA
}

}  // namespace internal
}  // namespace xchainer
<commit_msg>trivial: fix comments<commit_after>#include "xchainer/memory.h"

#include <cassert>

#ifdef XCHAINER_ENABLE_CUDA
#include <cuda.h>
#include <cuda_runtime.h>
#endif  // XCHAINER_ENABLE_CUDA

#include "xchainer/backend.h"
#ifdef XCHAINER_ENABLE_CUDA
#include "xchainer/cuda/cuda_runtime.h"
#endif  // XCHAINER_ENABLE_CUDA
#include "xchainer/device_id.h"
#include "xchainer/error.h"

#include <iostream>

namespace xchainer {
namespace internal {

bool IsPointerCudaMemory(const void* ptr) {
#ifdef XCHAINER_ENABLE_CUDA
    cudaPointerAttributes attr = {};
    cudaError_t status = cudaPointerGetAttributes(&attr, ptr);
    switch (status) {
        case cudaSuccess:
            if (attr.isManaged) {
                return true;
            } else {
                throw XchainerError("Non-managed GPU memory is not supported");
            }
        case cudaErrorInvalidValue:
            return false;
        default:
            cuda::CheckError(status);
            break;
    }
    assert(false);  // should never be reached
#else
    (void)ptr;  // unused
    return false;
#endif  // XCHAINER_ENABLE_CUDA
}

std::shared_ptr<void> Allocate(const DeviceId& device_id, size_t bytesize) {
    // TODO(sonots): Use device_id.backend->Allocate()
    if (device_id.backend()->GetName() == "native") {
        return std::make_unique<uint8_t[]>(bytesize);
#ifdef XCHAINER_ENABLE_CUDA
    } else if (device_id.backend()->GetName() == "cuda") {
        void* raw_ptr = nullptr;
        // Be careful to be exception-safe, i.e., do not throw before creating shared_ptr
        cudaError_t status = cudaMallocManaged(&raw_ptr, bytesize, cudaMemAttachGlobal);
        if (status == cudaSuccess) {
            return std::shared_ptr<void>{raw_ptr, cudaFree};
        } else {
            cuda::Throw(status);
        }
        assert(false);  // should never be reached
#endif                  // XCHAINER_ENABLE_CUDA
    } else {
        throw DeviceError("invalid device_id");
    }
}

void MemoryCopy(void* dst_ptr, const void* src_ptr, size_t bytesize) {
#ifdef XCHAINER_ENABLE_CUDA
    bool is_dst_cuda_memory = IsPointerCudaMemory(dst_ptr);
    bool is_src_cuda_memory = IsPointerCudaMemory(src_ptr);
    if (is_dst_cuda_memory) {
        if (is_src_cuda_memory) {
            // Copy from device to device is faster even in unified memory
            cuda::CheckError(cudaMemcpy(dst_ptr, src_ptr, bytesize, cudaMemcpyDeviceToDevice));
        } else {
            // For pre-6.x GPU architecture, we encountered SEGV with std::memcpy
            // ref. https://github.com/pfnet/xchainer/pull/74
            cuda::CheckError(cudaMemcpy(dst_ptr, src_ptr, bytesize, cudaMemcpyHostToDevice));
        }
    } else {
        if (is_src_cuda_memory) {
            // For pre-6.x GPU architecture, we encountered SEGV with std::memcpy
            // ref. https://github.com/pfnet/xchainer/pull/74
            cuda::CheckError(cudaMemcpy(dst_ptr, src_ptr, bytesize, cudaMemcpyDeviceToHost));
        } else {
            std::memcpy(dst_ptr, src_ptr, bytesize);
        }
    }
#else
    std::memcpy(dst_ptr, src_ptr, bytesize);
#endif  // XCHAINER_ENABLE_CUDA
}

std::shared_ptr<void> MemoryFromBuffer(const DeviceId& device_id, const std::shared_ptr<void>& src_ptr, size_t bytesize) {
// TODO(sonots): Use device_id.backend->FromBuffer()
#ifdef XCHAINER_ENABLE_CUDA
    if (device_id.backend()->GetName() == "native") {
        if (IsPointerCudaMemory(src_ptr.get())) {
            std::shared_ptr<void> dst_ptr = Allocate(device_id, bytesize);
            cuda::CheckError(cudaMemcpy(dst_ptr.get(), src_ptr.get(), bytesize, cudaMemcpyDeviceToHost));
            return dst_ptr;
        } else {
            return src_ptr;
        }
    } else if (device_id.backend()->GetName() == "cuda") {
        if (IsPointerCudaMemory(src_ptr.get())) {
            return src_ptr;
        } else {
            std::shared_ptr<void> dst_ptr = Allocate(device_id, bytesize);
            cuda::CheckError(cudaMemcpy(dst_ptr.get(), src_ptr.get(), bytesize, cudaMemcpyHostToDevice));
            return dst_ptr;
        }
    } else {
        throw DeviceError("invalid device_id");
    }
#else
    (void)bytesize;  // unused
    if (device_id.backend()->GetName() == "native") {
        return src_ptr;
    } else {
        throw DeviceError("invalid device_id");
    }
#endif  // XCHAINER_ENABLE_CUDA
}

}  // namespace internal
}  // namespace xchainer
<|endoftext|>