<commit_before>#pragma ident "$Id$"

//============================================================================
//
//  This file is part of GPSTk, the GPS Toolkit.
//
//  The GPSTk is free software; you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published
//  by the Free Software Foundation; either version 2.1 of the License, or
//  any later version.
//
//  The GPSTk is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with GPSTk; if not, write to the Free Software Foundation,
//  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Copyright 2004, The University of Texas at Austin
//
//============================================================================

//============================================================================
//
//This software developed by Applied Research Laboratories at the University of
//Texas at Austin, under contract to an agency or agencies within the U.S.
//Department of Defense. The U.S. Government retains all rights to use,
//duplicate, distribute, disclose, or release this software.
//
//Pursuant to DoD Directive 523024
//
// DISTRIBUTION STATEMENT A: This software has been approved for public
//                           release, distribution is unlimited.
//
//=============================================================================

/**
 * @file SP3Data.cpp
 * Encapsulate SP3 file data, including I/O
 */

#include "SP3Stream.hpp"
#include "SP3Header.hpp"
#include "SP3Data.hpp"
#include "StringUtils.hpp"
#include "DayTime.hpp"

using namespace gpstk::StringUtils;
using namespace std;

namespace gpstk
{
   void SP3Data::reallyPutRecord(FFStream& ffs) const
      throw(std::exception, FFStreamError, StringException)
   {
      SP3Stream& strm = dynamic_cast<SP3Stream&>(ffs);

      string line;
      if(flag == '*') {// output Epoch Header Record
         line = "* ";
         line += time.printf(" %4Y %2m %2d %2H %2M");
         line += " " + rightJustify(time.printf("%.8f"),11);
      }
      else {           // output Position and Clock OR Velocity and Clock Rate Record
         line = flag;
         if(version == 'c')
            line += SP3SatID(sat).toString();
         else
            line += rightJustify(asString(sat.id),3);
         line += rightJustify(asString(x[0],6),14);
         line += rightJustify(asString(x[1],6),14);
         line += rightJustify(asString(x[2],6),14);
         line += rightJustify(asString(clk,6),14);
         if(version == 'c') {
            line += rightJustify(asString(sig[0]),3);
            line += rightJustify(asString(sig[1]),3);
            line += rightJustify(asString(sig[2]),3);
            line += rightJustify(asString(sig[3]),4);
            if(flag == 'P') {
               line += string(" ");
               line += (clockEventFlag ? string("E") : string(" "));
               line += (clockPredFlag ? string("P") : string(" "));
               line += string("  ");
               line += (orbitManeuverFlag ? string("M") : string(" "));
               line += (orbitPredFlag ? string("P") : string(" "));
            }
            //else {
            //   line += string("       ");
            //}
         }

         // if version is 'c' and correlation flag is set,
         // output P|V Correlation Record
         if(version == 'c' && correlationFlag) {
            // first output the P|V record
            strm << line << endl;

            // now output the correlation record
            if(flag == 'P') line = "EP ";
            else line = "EV ";
            line += rightJustify(asString(sdev[0]),5);
            line += rightJustify(asString(sdev[1]),5);
            line += rightJustify(asString(sdev[2]),5);
            line += rightJustify(asString(sdev[3]),8);
            for(int i=0; i<6; i++)
               line += rightJustify(asString(correlation[i]),9);
         }
      }

      // write the line
      strm << line << endl;
   }

   void SP3Data::dump(ostream& s) const
   {
      s << flag << " " << sat
         << " " << time.printf("%Y/%02m/%02d %2H:%02M:%06.3f = %F/%10.3g");
      if(flag != '*') {
         s << fixed << setprecision(6)
           << " X=" << setw(14) << x[0]
           << " Y=" << setw(14) << x[1]
           << " Z=" << setw(14) << x[2]
           << " C=" << setw(14) << clk;

         if(version == 'c') {
            s << " sX=" << setw(2) << sig[0]
              << " sY=" << setw(2) << sig[1]
              << " sZ=" << setw(2) << sig[2]
              << " sC=" << setw(3) << sig[3];
            if(flag == 'P')
              s << " " << (clockEventFlag ? "clockEvent" : "-")
                << " " << (clockPredFlag ? "clockPrediction" : "-")
                << " " << (orbitManeuverFlag ? "orbitManeuver" : "-")
                << " " << (orbitPredFlag ? "orbitPrediction" : "-");
            if(correlationFlag)
               s << endl
                 << 'E' << flag
                 << " cXX=" << setw(4) << sdev[0]
                 << " cYY=" << setw(4) << sdev[1]
                 << " cZZ=" << setw(4) << sdev[2]
                 << " cCC=" << setw(7) << sdev[3]
                 << " cXY=" << setw(8) << correlation[0]
                 << " cXZ=" << setw(8) << correlation[1]
                 << " cXC=" << setw(8) << correlation[2]
                 << " cYZ=" << setw(8) << correlation[3]
                 << " cYC=" << setw(8) << correlation[4]
                 << " cZC=" << setw(8) << correlation[5];
         }
      }
      s << endl;
   };

   void SP3Data::reallyGetRecord(FFStream& ffs)
      throw(std::exception, FFStreamError, StringException)
   {
      SP3Stream& strm = dynamic_cast<SP3Stream&>(ffs);

      correlationFlag = false;
      int status = 0;                                          // initial status = 0
      while(1) {
         // set the time in the record
         time = strm.currentEpoch;

         // ---------------------------------------------------------
         // process the buffer containing the last line read
         if(strm.buffer.size() < 3) {
            // nothing in buffer - do nothing here, get another line
            ;
         }

         else if(strm.buffer.substr(0,3) == string("EOF")) {      // 'EOF' record
            // if a data record has been processed during this call, then
            // return and let the next call process this EOF.
            //if(status == 1) throw - found EOF right after an epoch record
            if(status > 1) break;

            // this next read had better fail - if it does, an exception will
            // be thrown, and the FFStreamError created next won't get thrown
            strm.formattedGetLine(strm.buffer, true);

            FFStreamError err("EOF text found but file didn't end");
            GPSTK_THROW(err);
         }

         else if(strm.buffer[0] == '*') {                         // Epoch record
            // if another record has been process during this call, quit now
            if(status > 0) break;
            status = 1;                                           // epoch status = 1

            // throw if the line is short
            if(strm.buffer.size() <= 30) {
               FFStreamError err("Invalid line length "+asString(strm.buffer.size()));
               GPSTK_THROW(err);
            }

            // parse the epoch line
            int year = asInt(strm.buffer.substr(3,4));
            int month = asInt(strm.buffer.substr(8,2));
            int dom = asInt(strm.buffer.substr(11,2));
            int hour = asInt(strm.buffer.substr(14,2));
            int minute = asInt(strm.buffer.substr(17,2));
            double second = asInt(strm.buffer.substr(20,10));
            DayTime t(year, month, dom, hour, minute, second);
            time = strm.currentEpoch = t;
         }

         else if(strm.buffer[0] == 'P' || strm.buffer[0] == 'V') {// P|V record
            // if nothing, or epoch record, was processed during this call,
            // process this P|V, otherwise (P|V or EP|V were processed), quit now
            if(status > 1) break;
            status = 2;                                           // P|V status = 2

            flag = strm.buffer[0];     // P or V

            // throw if the line is short
            if ((version == 'a' && strm.buffer.size() < 60) ||
               (version == 'c' && strm.buffer.size() < 73) ) {
               FFStreamError err("Invalid line length "+asString(strm.buffer.size()));
               GPSTK_THROW(err);
            }

            // parse the line
            if(version == 'a')
               sat = SatID(asInt(strm.buffer.substr(1, 3)), SP3SatID::systemGPS);
            else
               sat = SP3SatID(strm.buffer.substr(1,3));

            x[0] = asDouble(strm.buffer.substr(5,14));
            x[1] = asDouble(strm.buffer.substr(19,14));
            x[2] = asDouble(strm.buffer.substr(33,14));
            clk = asDouble(strm.buffer.substr(47,14));

            if(version == 'c') {
               // get sigmas from P|V record
               sig[0] = asInt(strm.buffer.substr(61,2));
               sig[1] = asInt(strm.buffer.substr(64,2));
               sig[2] = asInt(strm.buffer.substr(67,2));
               sig[3] = asInt(strm.buffer.substr(70,3));

               // get flags
               if(flag == 'P') {
                  clockEventFlag = clockPredFlag
                     = orbitManeuverFlag = orbitPredFlag = false;
                  if(strm.buffer.size() >= 75 && strm.buffer[74] == 'E')
                     clockEventFlag = true;
                  if(strm.buffer.size() >= 76 && strm.buffer[75] == 'P')
                     clockPredFlag = true;
                  if(strm.buffer.size() >= 79 && strm.buffer[78] == 'M')
                     orbitManeuverFlag = true;
                  if(strm.buffer.size() >= 80 && strm.buffer[79] == 'P')
                     orbitPredFlag = true;
               }
            }

         }
         else if(strm.buffer[0] == 'E' &&                      // EP|EV record
               (strm.buffer[1] == 'P' || strm.buffer[1] == 'V')) {

            // always process an EP|V immediately, since it must follow P|V
            status = 3;                                        // EP|V status = 3

            // throw if correlation record did not follow corresponding P|V record
            if(strm.buffer[1] != flag) {
               Exception e("SP3c correlation record mismatched with previous P|V");
               GPSTK_THROW(e);
            }

            // throw if line is short
            if(strm.buffer.size()<80) {
               FFStreamError err("Invalid SP3c correlation line length "
                  + asString(strm.buffer.size()));
               GPSTK_THROW(err);
            }

            sdev[0] = abs(asInt(strm.buffer.substr(4,4)));
            sdev[1] = abs(asInt(strm.buffer.substr(9,4)));
            sdev[2] = abs(asInt(strm.buffer.substr(14,4)));
            sdev[3] = abs(asInt(strm.buffer.substr(19,7)));
            correlation[0] = asInt(strm.buffer.substr(27,8));
            correlation[1] = asInt(strm.buffer.substr(36,8));
            correlation[2] = asInt(strm.buffer.substr(45,8));
            correlation[3] = asInt(strm.buffer.substr(54,8));
            correlation[4] = asInt(strm.buffer.substr(63,8));
            correlation[5] = asInt(strm.buffer.substr(72,8));

            // tell the caller that correlation data is now present
            correlationFlag = true;
         }

         else {                              // Unknown record
            FFStreamError err("Unknown line label " + strm.buffer.substr(0,2));
            GPSTK_THROW(err);
         }

         // ---------------------------------------------------------
         // read next line into the buffer
         strm.formattedGetLine(strm.buffer);

         // ---------------------------------------------------------
         // quit if EP|EV was processed
         if(status == 3) break;
         // go back if buffer was empty    (0)
         // go back if epoch was processed (1)
         // go back if P|V was processed   (2)
      }

   }   // end reallyGetRecord()

} // namespace
<commit_msg>Bug fix in reallyGetRecord, thanks Dagoberto<commit_after>#pragma ident "$Id$"

//============================================================================
//
//  This file is part of GPSTk, the GPS Toolkit.
//
//  The GPSTk is free software; you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published
//  by the Free Software Foundation; either version 2.1 of the License, or
//  any later version.
//
//  The GPSTk is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with GPSTk; if not, write to the Free Software Foundation,
//  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Copyright 2004, The University of Texas at Austin
//
//============================================================================

//============================================================================
//
//This software developed by Applied Research Laboratories at the University of
//Texas at Austin, under contract to an agency or agencies within the U.S.
//Department of Defense. The U.S. Government retains all rights to use,
//duplicate, distribute, disclose, or release this software.
//
//Pursuant to DoD Directive 523024
//
// DISTRIBUTION STATEMENT A: This software has been approved for public
//                           release, distribution is unlimited.
//
//=============================================================================

/**
 * @file SP3Data.cpp
 * Encapsulate SP3 file data, including I/O
 */

#include "SP3Stream.hpp"
#include "SP3Header.hpp"
#include "SP3Data.hpp"
#include "StringUtils.hpp"
#include "DayTime.hpp"

using namespace gpstk::StringUtils;
using namespace std;

namespace gpstk
{
   void SP3Data::reallyPutRecord(FFStream& ffs) const
      throw(std::exception, FFStreamError, StringException)
   {
      SP3Stream& strm = dynamic_cast<SP3Stream&>(ffs);

      string line;
      if(flag == '*') {// output Epoch Header Record
         line = "* ";
         line += time.printf(" %4Y %2m %2d %2H %2M");
         line += " " + rightJustify(time.printf("%.8f"),11);
      }
      else {           // output Position and Clock OR Velocity and Clock Rate Record
         line = flag;
         if(version == 'c')
            line += SP3SatID(sat).toString();
         else
            line += rightJustify(asString(sat.id),3);
         line += rightJustify(asString(x[0],6),14);
         line += rightJustify(asString(x[1],6),14);
         line += rightJustify(asString(x[2],6),14);
         line += rightJustify(asString(clk,6),14);
         if(version == 'c') {
            line += rightJustify(asString(sig[0]),3);
            line += rightJustify(asString(sig[1]),3);
            line += rightJustify(asString(sig[2]),3);
            line += rightJustify(asString(sig[3]),4);
            if(flag == 'P') {
               line += string(" ");
               line += (clockEventFlag ? string("E") : string(" "));
               line += (clockPredFlag ? string("P") : string(" "));
               line += string("  ");
               line += (orbitManeuverFlag ? string("M") : string(" "));
               line += (orbitPredFlag ? string("P") : string(" "));
            }
            //else {
            //   line += string("       ");
            //}
         }

         // if version is 'c' and correlation flag is set,
         // output P|V Correlation Record
         if(version == 'c' && correlationFlag) {
            // first output the P|V record
            strm << line << endl;

            // now output the correlation record
            if(flag == 'P') line = "EP ";
            else line = "EV ";
            line += rightJustify(asString(sdev[0]),5);
            line += rightJustify(asString(sdev[1]),5);
            line += rightJustify(asString(sdev[2]),5);
            line += rightJustify(asString(sdev[3]),8);
            for(int i=0; i<6; i++)
               line += rightJustify(asString(correlation[i]),9);
         }
      }

      // write the line
      strm << line << endl;
   }

   void SP3Data::dump(ostream& s) const
   {
      s << flag << " " << sat
         << " " << time.printf("%Y/%02m/%02d %2H:%02M:%06.3f = %F/%10.3g");
      if(flag != '*') {
         s << fixed << setprecision(6)
           << " X=" << setw(14) << x[0]
           << " Y=" << setw(14) << x[1]
           << " Z=" << setw(14) << x[2]
           << " C=" << setw(14) << clk;

         if(version == 'c') {
            s << " sX=" << setw(2) << sig[0]
              << " sY=" << setw(2) << sig[1]
              << " sZ=" << setw(2) << sig[2]
              << " sC=" << setw(3) << sig[3];
            if(flag == 'P')
              s << " " << (clockEventFlag ? "clockEvent" : "-")
                << " " << (clockPredFlag ? "clockPrediction" : "-")
                << " " << (orbitManeuverFlag ? "orbitManeuver" : "-")
                << " " << (orbitPredFlag ? "orbitPrediction" : "-");
            if(correlationFlag)
               s << endl
                 << 'E' << flag
                 << " cXX=" << setw(4) << sdev[0]
                 << " cYY=" << setw(4) << sdev[1]
                 << " cZZ=" << setw(4) << sdev[2]
                 << " cCC=" << setw(7) << sdev[3]
                 << " cXY=" << setw(8) << correlation[0]
                 << " cXZ=" << setw(8) << correlation[1]
                 << " cXC=" << setw(8) << correlation[2]
                 << " cYZ=" << setw(8) << correlation[3]
                 << " cYC=" << setw(8) << correlation[4]
                 << " cZC=" << setw(8) << correlation[5];
         }
      }
      s << endl;
   };

   void SP3Data::reallyGetRecord(FFStream& ffs)
      throw(std::exception, FFStreamError, StringException)
   {
      SP3Stream& strm = dynamic_cast<SP3Stream&>(ffs);

      correlationFlag = false;
      int status = 0;                                          // initial status = 0
      while(1) {
         // set the time in the record
         time = strm.currentEpoch;

         // ---------------------------------------------------------
         // process the buffer containing the last line read
         if(strm.buffer.size() < 3) {
            // nothing in buffer - do nothing here, get another line
            ;
         }

         else if(strm.buffer.substr(0,3) == string("EOF")) {      // 'EOF' record
            // if a data record has been processed during this call, then
            // return and let the next call process this EOF.
            //if(status == 1) throw - found EOF right after an epoch record
            if(status > 1) break;

            // this next read had better fail - if it does, an exception will
            // be thrown, and the FFStreamError created next won't get thrown
            strm.formattedGetLine(strm.buffer, true);

            FFStreamError err("EOF text found but file didn't end");
            GPSTK_THROW(err);
         }

         else if(strm.buffer[0] == '*') {                         // Epoch record
            // if another record has been process during this call, quit now
            if(status > 0) break;
            status = 1;                                           // epoch status = 1

            // throw if the line is short
            if(strm.buffer.size() <= 30) {
               FFStreamError err("Invalid line length "+asString(strm.buffer.size()));
               GPSTK_THROW(err);
            }

            // parse the epoch line
            int year = asInt(strm.buffer.substr(3,4));
            int month = asInt(strm.buffer.substr(8,2));
            int dom = asInt(strm.buffer.substr(11,2));
            int hour = asInt(strm.buffer.substr(14,2));
            int minute = asInt(strm.buffer.substr(17,2));
            double second = asInt(strm.buffer.substr(20,10));
            DayTime t(year, month, dom, hour, minute, second);
            time = strm.currentEpoch = t;
         }

         else if(strm.buffer[0] == 'P' || strm.buffer[0] == 'V') {// P|V record
            // if nothing, or epoch record, was processed during this call,
            // process this P|V, otherwise (P|V or EP|V were processed), quit now
            if(status > 1) break;
            status = 2;                                           // P|V status = 2

            flag = strm.buffer[0];     // P or V

            // throw if the line is short
            if ((version == 'a' && strm.buffer.size() < 60) ||
               (version == 'c' && strm.buffer.size() < 73) ) {
               FFStreamError err("Invalid line length "+asString(strm.buffer.size()));
               GPSTK_THROW(err);
            }

            // parse the line
            if(version == 'a')
               sat = SatID(asInt(strm.buffer.substr(1, 3)), SP3SatID::systemGPS);
            else
               sat = SP3SatID(strm.buffer.substr(1,3));

            x[0] = asDouble(strm.buffer.substr(4,14));
            x[1] = asDouble(strm.buffer.substr(18,14));
            x[2] = asDouble(strm.buffer.substr(32,14));
            clk = asDouble(strm.buffer.substr(46,14));

            if(version == 'c') {
               // get sigmas from P|V record
               sig[0] = asInt(strm.buffer.substr(61,2));
               sig[1] = asInt(strm.buffer.substr(64,2));
               sig[2] = asInt(strm.buffer.substr(67,2));
               sig[3] = asInt(strm.buffer.substr(70,3));

               // get flags
               if(flag == 'P') {
                  clockEventFlag = clockPredFlag
                     = orbitManeuverFlag = orbitPredFlag = false;
                  if(strm.buffer.size() >= 75 && strm.buffer[74] == 'E')
                     clockEventFlag = true;
                  if(strm.buffer.size() >= 76 && strm.buffer[75] == 'P')
                     clockPredFlag = true;
                  if(strm.buffer.size() >= 79 && strm.buffer[78] == 'M')
                     orbitManeuverFlag = true;
                  if(strm.buffer.size() >= 80 && strm.buffer[79] == 'P')
                     orbitPredFlag = true;
               }
            }

         }
         else if(strm.buffer[0] == 'E' &&                      // EP|EV record
               (strm.buffer[1] == 'P' || strm.buffer[1] == 'V')) {

            // always process an EP|V immediately, since it must follow P|V
            status = 3;                                        // EP|V status = 3

            // throw if correlation record did not follow corresponding P|V record
            if(strm.buffer[1] != flag) {
               Exception e("SP3c correlation record mismatched with previous P|V");
               GPSTK_THROW(e);
            }

            // throw if line is short
            if(strm.buffer.size()<80) {
               FFStreamError err("Invalid SP3c correlation line length "
                  + asString(strm.buffer.size()));
               GPSTK_THROW(err);
            }

            sdev[0] = abs(asInt(strm.buffer.substr(4,4)));
            sdev[1] = abs(asInt(strm.buffer.substr(9,4)));
            sdev[2] = abs(asInt(strm.buffer.substr(14,4)));
            sdev[3] = abs(asInt(strm.buffer.substr(19,7)));
            correlation[0] = asInt(strm.buffer.substr(27,8));
            correlation[1] = asInt(strm.buffer.substr(36,8));
            correlation[2] = asInt(strm.buffer.substr(45,8));
            correlation[3] = asInt(strm.buffer.substr(54,8));
            correlation[4] = asInt(strm.buffer.substr(63,8));
            correlation[5] = asInt(strm.buffer.substr(72,8));

            // tell the caller that correlation data is now present
            correlationFlag = true;
         }

         else {                              // Unknown record
            FFStreamError err("Unknown line label " + strm.buffer.substr(0,2));
            GPSTK_THROW(err);
         }

         // ---------------------------------------------------------
         // read next line into the buffer
         strm.formattedGetLine(strm.buffer);

         // ---------------------------------------------------------
         // quit if EP|EV was processed
         if(status == 3) break;
         // go back if buffer was empty    (0)
         // go back if epoch was processed (1)
         // go back if P|V was processed   (2)
      }

   }   // end reallyGetRecord()

} // namespace
<|endoftext|>


<commit_before>
#pragma once

#include <deque>
#include <optional>

#include "quantities/named_quantities.hpp"
#include "quantities/quantities.hpp"

namespace principia {
namespace numerics {
namespace internal_pid {

using quantities::Inverse;
using quantities::Time;

template<typename Value, int horizon, int finite_difference_order>
class PID {
public:
  static_assert(finite_difference_order <= horizon);

  PID(double kp, Inverse<Time> const& ki, Time const& kd);

  // Clears the state of the PID.
  void Clear();

  // Adds the error between the process variable and the set-point to the state
  // of the PID and returns an updated process variable derived from the
  // set-point and the control variable.
  Value ComputeValue(Value const& process_variable,
                     Value const& set_point,
                     Time const& Δt);

private:
  double const kp_;
  Inverse<Time> const ki_;
  Time const kd_;

  // The PID is not prepared to receive inputs that are not equally spaced.
  std::optional<Time> previous_Δt_;

  // The front element is the oldest.
  std::deque<Value> errors_;
};

}  // namespace internal_pid

using internal_pid::PID;

}  // namespace numerics
}  // namespace principia

#include "numerics/pid_body.hpp"
<commit_msg>Lint.<commit_after>
#pragma once

#include <deque>
#include <optional>

#include "quantities/named_quantities.hpp"
#include "quantities/quantities.hpp"

namespace principia {
namespace numerics {
namespace internal_pid {

using quantities::Inverse;
using quantities::Time;

template<typename Value, int horizon, int finite_difference_order>
class PID {
 public:
  static_assert(finite_difference_order <= horizon);

  PID(double kp, Inverse<Time> const& ki, Time const& kd);

  // Clears the state of the PID.
  void Clear();

  // Adds the error between the process variable and the set-point to the state
  // of the PID and returns an updated process variable derived from the
  // set-point and the control variable.
  Value ComputeValue(Value const& process_variable,
                     Value const& set_point,
                     Time const& Δt);

 private:
  double const kp_;
  Inverse<Time> const ki_;
  Time const kd_;

  // The PID is not prepared to receive inputs that are not equally spaced.
  std::optional<Time> previous_Δt_;

  // The front element is the oldest.
  std::deque<Value> errors_;
};

}  // namespace internal_pid

using internal_pid::PID;

}  // namespace numerics
}  // namespace principia

#include "numerics/pid_body.hpp"
<|endoftext|>


<commit_before>#include <iostream>
#include <string.h>
#include <istream>
#include <cstring>
#include <unistd.h>
using namespace std;
#include <cstdio>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string>
#include <errno.h>
#include <cstdlib>

int main()
{
    string input;
    //taking input as a c++ string; will convert to c_str later

    cout << "$ "; //command prompt
    getline (cin,input);
    cout << endl << "outputting input: " << endl << input << endl;

    //these will be the arguments to my shell after parsing
    int argc = 0; // no arguments (yet)
    char* argv[99999];
    argv[0] = new char[9999];

    char * tmp; //cstring to not deal with memory management for now
    char delims[] = " "; // connectors we are looking out for.
                                //FIXME: may not be exactly what we want since may have
                                //to be arguments too

    char input2[9999]; //will take copy of input from std::string input
    strcpy(input2, input.c_str() );

    cout << "about to run strtok 1st time" << endl;
    tmp = strtok(input2,delims) ;
    strcpy( argv[argc] , tmp ); //copying first token

    cout << "about to run strtok In while loop." << endl;
    while (tmp != NULL)
    {
        argc +=1; // argument count increases.
        printf ("%s\n",tmp) ;
        tmp = strtok (NULL,delims);
        argv[argc] = tmp; // copying tokens into argv one at a time

    }
    /* cerr << "copying tmp into argv..." << endl;
    strcpy(*argv,tmp );
    cout << "strcpy successful!! (maybe LOL)" << endl;
    */

    //checking everything was read in
    cout << "argc: " << argc << "   " <<  endl;
    cout << " argv:" << endl;

    for(unsigned i = 0; argv[i]!='\0'; ++i){
        cout << i << ": " << argv[i] << endl;
    }

    //need to figure out a way to read in commands with ';' in between
    //and white space in between

    //checking how execvp works (dummy variables)
    char * aargv[4];
    aargv[0] = new char[4];
    aargv[1] = new char[4];
    aargv[2] = new char[4];
    strcpy( aargv[0] , "pwd"); //copying first token
    cout << "first copy. \n" << endl;
    strcpy( aargv[1] , " ; " );
    cout << "about tho start third..." << endl;
    strcpy( aargv[2] , "ls");
    cout << "done copying... " << endl;

    //beginning fork, execpv processes
    //may need to creat multiple forks to run input with connectors
    int pid=fork();

    if(pid == -1)
    {
        perror("There was an error with fork(). " );
        exit(1);

    }
    //child process
    if (pid==0) {
        cout << "i'm a child" << endl;

        cout <<" before" << endl;
        if(-1 == execvp(argv[0], argv))
        {
            perror("Error: execvp didn't run as expected. Commands may not exist.");
        }
        exit(1); //avoid zombies

    }
    //pid now > 0 so we are in parent process.
    else{
        if( wait(NULL) == -1 ){
            perror("Error: wait() did not wait!! :o ");
    }

        cout << "I'm a parent." << endl;
        exit(1);
    }

    return 0;
}
<commit_msg>created at vector <char**> argv to handle different argumentsgit add rschell.cpp and sorta got the loop to get these arguments working. MUCH MORE WORK LEFTgit add rschell.cpp<commit_after>#include <iostream>
#include <string.h>
#include <istream>
#include <cstring>
#include <unistd.h>
using namespace std;
#include <cstdio>
#include <cstring>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string>
#include <errno.h>
#include <cstdlib>
#include <vector>

//Counts number of arguments
int count_args( const string & input ) {
	if (input.size() == 0 )
	{
		return 0;
	}

	int count = 1;

	for(unsigned i = 0; i < input.size(); ++i)
	{
		if ( input.at(i) == '&' || input.at(i) == '|' )
		{
			i+=1; // first '&' or '|' will be followed by another
			count +=1;
		}

		if ( input.at(i) == ';' && i+1 != input.size() )//can have command: pwd;
		{
			count +=1;
	//BUG: will give greater size than should be when have input: "ls ; pwd;   "
	//will count white space unfortunately.....
	//will say extra argument than there is..
		}
	}
	return count;
}

int main()
{
    string input;
	    //taking input as a c++ string; will convert to c_str later

    cout << "$ "; //command prompt
    getline (cin,input);
    cout << endl << "outputting input: " << endl << input << endl;
    cout << "input.size() (raw): " << input.size() << endl; // trying to see if space adds size

    //these will be the arguments to my shell after parsing
    	unsigned arg_count = count_args(input);
	vector <char**> argv;
	argv.resize( arg_count );

    char * tmp; //cstring to not deal with memory management for now
    char delims[] = " "; // connectors we are looking out for.
                                //FIXME: may not be exactly what we want since may have
                                //to be arguments too
	int inp_sz = input.size()+1;
    char* input2 = new char[inp_sz]; //will take copy of input from std::string input
    strcpy(input2, input.c_str() );
	cout << "input2 done. no seg fault here. " << endl;

	for(unsigned i = 0; i < arg_count; ++i)
	{
		int argc = 0 ; // no arguments (yet)
		tmp = strtok(input2,delims) ;
		cout << "strtok, i = " << i << endl;
		argv.at(i) = new char* [999];
		argv.at(i)[argc] = new char[strlen(tmp) +1];
    		strcpy( (argv.at(i)[argc] ) , tmp ); //copying first token
   		cout << "strcpy, i = " << i << endl;

		while (tmp != NULL)
		{
			argc +=1; // argument count increases.
			printf ("%s\n",tmp) ;
			tmp = strtok (NULL,delims);
			argv.at(i)[argc] = tmp; // copying tokens into argv one at a time

		}
		cout << "first while, i = " << i << endl;
	}
	    /* cerr << "copying tmp into argv..." << endl;
    strcpy(*argv,tmp );
    cout << "strcpy successful!! (maybe LOL)" << endl;
    */

    //checking everything was read in
    //cout << "argc: " << argc << "   " <<  endl;
    //cout << " argv:" << endl;

    for(unsigned i = 0; argv[i]!='\0'; ++i){
        cout << i << ": " << argv[i] << endl;
    }

    //need to figure out a way to read in commands with ';' in between
    //and white space in between

    //checking how execvp works (dummy variables)
    char * aargv[4];
    aargv[0] = new char[4];
    aargv[1] = new char[4];
    aargv[2] = new char[4];
    strcpy( aargv[0] , "pwd"); //copying first token
    cout << "first copy. \n" << endl;
    strcpy( aargv[1] , " ; " );
    cout << "about tho start third..." << endl;
    strcpy( aargv[2] , "ls");
    cout << "done copying... " << endl;

    //beginning fork, execpv processes
    //may need to creat multiple forks to run input with connectors

	//will now make major changes
	//execute multiple commands through for loop (similar to lab02)

	int pid=fork();
	if(pid == -1)
	{
		perror("There was an error with fork(). " );
		exit(1);

	}
	//child process
	if (pid==0) {
		cout << "i'm a child" << endl;

/*
		if(-1 == execvp(*argv.at(0)[0] ,  *argv.at(0) )
		{
			perror("Error: execvp didn't run as expected. Commands may not exist.");

			exit(1); //avoid zombies

		}*/
	}
	//pid now > 0 so we are in parent process.
	else{
		if( wait(NULL) == -1 ){
			perror("Error: wait() did not wait!! :o ");
		}

		cout << "I'm a parent." << endl;
		exit(1);
	}

	return 0;
}

<|endoftext|>


<commit_before>#pragma once

#include "h5file.hpp"

namespace mocc {
    /**
     * This simply specifies an interface for outputing "stuff" to and HDF5
     * file. Any class extending it must implement the output() method, which
     * adds its data to the H5File instance passed to it.
     */
    class HasOutput {
    public:
        // Perform final output to a data file. Most output is probably
        // delegated to supbordinate objects.
        virtual void output( H5Node &file ) const = 0;
    };
}
<commit_msg>Improve HasOutput docs<commit_after>#pragma once

#include "h5file.hpp"

namespace mocc {
    /**
     * This simply specifies an interface for outputing "stuff" to and HDF5
     * file. Any class extending it must implement the output() method, which
     * adds its data to the H5File instance passed to it.
     */
    class HasOutput {
    public:
        /**
         * \brief Output relevant data to an HDF5 file node.
         */
        virtual void output( H5Node &file ) const = 0;
    };
}
<|endoftext|>


<commit_before>/*
 * Texture.h
 *
 *  Created on: 16 Jun 2014
 *      Author: rick
 */

#ifndef TEXTURE_H_
#define TEXTURE_H_

#include "Vec3D.hpp"

typedef Vec3Df Texture;

#endif /* TEXTURE_H_ */
<commit_msg>Really fixed refactor.<commit_after>/*
 * Texture.hpp
 *
 *  Created on: 16 Jun 2014
 *      Author: rick
 */

#ifndef TEXTURE_H_
#define TEXTURE_H_

#include "Vec3D.hpp"

typedef Vec3Df Texture;

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


<commit_before>// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include "pal.h"
#include "utils.h"
#include "trace.h"

#include <dlfcn.h>
#include <dirent.h>
#include <sys/stat.h>

#if defined(__APPLE__)
#include <mach-o/dyld.h>
#endif

#if defined(__LINUX__)
#define symlinkEntrypointExecutable "/proc/self/exe"
#elif !defined(__APPLE__)
#define symlinkEntrypointExecutable "/proc/curproc/exe"
#endif

bool pal::find_coreclr(pal::string_t& recv)
{
    pal::string_t candidate;
    pal::string_t test;

    // Try /usr/share/dotnet and /usr/local/share/dotnet
    candidate.assign("/usr/share/dotnet/runtime/coreclr");
    if (coreclr_exists_in_dir(candidate)) {
        recv.assign(candidate);
        return true;
    }

    candidate.assign("/usr/local/share/dotnet/runtime/coreclr");
    if (coreclr_exists_in_dir(candidate)) {
        recv.assign(candidate);
        return true;
    }
    return false;
}

bool pal::load_library(const char_t* path, dll_t& dll)
{
    dll = dlopen(path, RTLD_LAZY);
    if (dll == nullptr)
    {
        trace::error(_X("failed to load %s, error: %s"), path, dlerror());
        return false;
    }
    return true;
}

pal::proc_t pal::get_symbol(dll_t library, const char* name)
{
    auto result = dlsym(library, name);
    if (result == nullptr)
    {
        trace::error(_X("failed to resolve library symbol %s, error: %s"), name, dlerror());
    }
    return result;
}

void pal::unload_library(dll_t library)
{
    if (dlclose(library) != 0)
    {
        trace::warning(_X("failed to unload library, error: %s"), dlerror());
    }
}

int pal::xtoi(const char_t* input)
{
    return atoi(input);
}

bool pal::is_path_rooted(const pal::string_t& path)
{
    return path.front() == '/';
}

bool pal::get_default_packages_directory(pal::string_t& recv)
{
    if (!pal::getenv("HOME", recv))
    {
        return false;
    }
    append_path(recv, _X(".dnx"));
    append_path(recv, _X("packages"));
    return true;
}

#if defined(__APPLE__)
bool pal::get_own_executable_path(pal::string_t& recv)
{
    uint32_t path_length = 0;
    if (_NSGetExecutablePath(nullptr, &path_length) == -1)
    {
        char path_buf[path_length];
        if (_NSGetExecutablePath(path_buf, &path_length) == 0)
        {
            recv.assign(path_buf);
            return true;
        }
    }
    return false;
}
#else
bool pal::get_own_executable_path(pal::string_t& recv)
{
    // Just return the symlink to the exe from /proc
    // We'll call realpath on it later
    recv.assign(symlinkEntrypointExecutable);
    return true;
}
#endif

bool pal::getenv(const pal::char_t* name, pal::string_t& recv)
{
    auto result = ::getenv(name);
    if (result != nullptr)
    {
        recv.assign(result);
    }

    // We don't return false. Windows does have a concept of an error reading the variable,
    // but Unix just returns null, which we treat as the variable not existing.
    return true;
}

bool pal::realpath(pal::string_t& path)
{
    pal::char_t buf[PATH_MAX];
    auto resolved = ::realpath(path.c_str(), buf);
    if (resolved == nullptr)
    {
        if (errno == ENOENT)
        {
            return false;
        }
        perror("realpath()");
        return false;
    }
    path.assign(resolved);
    return true;
}

bool pal::file_exists(const pal::string_t& path)
{
    struct stat buffer;
    return (::stat(path.c_str(), &buffer) == 0);
}

std::vector<pal::string_t> pal::readdir(const pal::string_t& path)
{
    std::vector<pal::string_t> files;

    auto dir = opendir(path.c_str());
    if (dir != nullptr)
    {
        struct dirent* entry = nullptr;
        while((entry = readdir(dir)) != nullptr)
        {
            // We are interested in files only
            switch (entry->d_type)
            {
            case DT_REG:
                break;

            // Handle symlinks and file systems that do not support d_type
            case DT_LNK:
            case DT_UNKNOWN:
                {
                    std::string fullFilename;

                    fullFilename.append(path);
                    fullFilename.push_back(DIR_SEPARATOR);
                    fullFilename.append(entry->d_name);

                    struct stat sb;
                    if (stat(fullFilename.c_str(), &sb) == -1)
                    {
                        continue;
                    }

                    if (!S_ISREG(sb.st_mode))
                    {
                        continue;
                    }
                }
                break;

            default:
                continue;
            }

            files.push_back(pal::string_t(entry->d_name));
        }
    }

    return files;
}
<commit_msg>Changes for corehost default path resolution on mac<commit_after>// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include "pal.h"
#include "utils.h"
#include "trace.h"

#include <dlfcn.h>
#include <dirent.h>
#include <sys/stat.h>

#if defined(__APPLE__)
#include <mach-o/dyld.h>
#endif

#if defined(__LINUX__)
#define symlinkEntrypointExecutable "/proc/self/exe"
#elif !defined(__APPLE__)
#define symlinkEntrypointExecutable "/proc/curproc/exe"
#endif

bool pal::find_coreclr(pal::string_t& recv)
{
    pal::string_t candidate;
    pal::string_t test;

    // Try /usr/share/dotnet and /usr/local/share/dotnet/cli
    // TODO: These paths should be consistent
    candidate.assign("/usr/share/dotnet/runtime/coreclr");
    if (coreclr_exists_in_dir(candidate)) {
        recv.assign(candidate);
        return true;
    }

    candidate.assign("/usr/local/share/dotnet/cli/runtime/coreclr");
    if (coreclr_exists_in_dir(candidate)) {
        recv.assign(candidate);
        return true;
    }
    return false;
}

bool pal::load_library(const char_t* path, dll_t& dll)
{
    dll = dlopen(path, RTLD_LAZY);
    if (dll == nullptr)
    {
        trace::error(_X("failed to load %s, error: %s"), path, dlerror());
        return false;
    }
    return true;
}

pal::proc_t pal::get_symbol(dll_t library, const char* name)
{
    auto result = dlsym(library, name);
    if (result == nullptr)
    {
        trace::error(_X("failed to resolve library symbol %s, error: %s"), name, dlerror());
    }
    return result;
}

void pal::unload_library(dll_t library)
{
    if (dlclose(library) != 0)
    {
        trace::warning(_X("failed to unload library, error: %s"), dlerror());
    }
}

int pal::xtoi(const char_t* input)
{
    return atoi(input);
}

bool pal::is_path_rooted(const pal::string_t& path)
{
    return path.front() == '/';
}

bool pal::get_default_packages_directory(pal::string_t& recv)
{
    if (!pal::getenv("HOME", recv))
    {
        return false;
    }
    append_path(recv, _X(".dnx"));
    append_path(recv, _X("packages"));
    return true;
}

#if defined(__APPLE__)
bool pal::get_own_executable_path(pal::string_t& recv)
{
    uint32_t path_length = 0;
    if (_NSGetExecutablePath(nullptr, &path_length) == -1)
    {
        char path_buf[path_length];
        if (_NSGetExecutablePath(path_buf, &path_length) == 0)
        {
            recv.assign(path_buf);
            return true;
        }
    }
    return false;
}
#else
bool pal::get_own_executable_path(pal::string_t& recv)
{
    // Just return the symlink to the exe from /proc
    // We'll call realpath on it later
    recv.assign(symlinkEntrypointExecutable);
    return true;
}
#endif

bool pal::getenv(const pal::char_t* name, pal::string_t& recv)
{
    auto result = ::getenv(name);
    if (result != nullptr)
    {
        recv.assign(result);
    }

    // We don't return false. Windows does have a concept of an error reading the variable,
    // but Unix just returns null, which we treat as the variable not existing.
    return true;
}

bool pal::realpath(pal::string_t& path)
{
    pal::char_t buf[PATH_MAX];
    auto resolved = ::realpath(path.c_str(), buf);
    if (resolved == nullptr)
    {
        if (errno == ENOENT)
        {
            return false;
        }
        perror("realpath()");
        return false;
    }
    path.assign(resolved);
    return true;
}

bool pal::file_exists(const pal::string_t& path)
{
    struct stat buffer;
    return (::stat(path.c_str(), &buffer) == 0);
}

std::vector<pal::string_t> pal::readdir(const pal::string_t& path)
{
    std::vector<pal::string_t> files;

    auto dir = opendir(path.c_str());
    if (dir != nullptr)
    {
        struct dirent* entry = nullptr;
        while((entry = readdir(dir)) != nullptr)
        {
            // We are interested in files only
            switch (entry->d_type)
            {
            case DT_REG:
                break;

            // Handle symlinks and file systems that do not support d_type
            case DT_LNK:
            case DT_UNKNOWN:
                {
                    std::string fullFilename;

                    fullFilename.append(path);
                    fullFilename.push_back(DIR_SEPARATOR);
                    fullFilename.append(entry->d_name);

                    struct stat sb;
                    if (stat(fullFilename.c_str(), &sb) == -1)
                    {
                        continue;
                    }

                    if (!S_ISREG(sb.st_mode))
                    {
                        continue;
                    }
                }
                break;

            default:
                continue;
            }

            files.push_back(pal::string_t(entry->d_name));
        }
    }

    return files;
}
<|endoftext|>


<commit_before>/*
 * Message.cpp
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include <core/http/Message.hpp>

#include <algorithm>

#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/function.hpp>
#include <boost/asio/buffer.hpp>

#include <core/SafeConvert.hpp>

namespace rstudio {
namespace core {
namespace http {

// encodings
const char * const kGzipEncoding = "gzip";

void Message::setHttpVersion(int httpVersionMajor, int httpVersionMinor)
{
   httpVersionMajor_ = httpVersionMajor ;
   httpVersionMinor_ = httpVersionMinor ;
}

void Message::setContentType(const std::string& contentType)
{
   setHeader("Content-Type", contentType) ;
}

std::string Message::contentType() const
{
   return headerValue("Content-Type") ;
}

std::size_t Message::contentLength() const
{
   return safe_convert::stringTo<std::size_t>(headerValue("Content-Length"), 0);
}

void Message::setContentLength(int contentLength)
{
   setHeader("Content-Length", contentLength);
}

void Message::addHeader(const std::string& name, const std::string& value)
{
   Header header ;
   header.name = name ;
   header.value = value ;
   addHeader(header);
}

void Message::addHeader(const Header& header)
{
   headers_.push_back(header);
}

void Message::addHeaders(const std::vector<Header>& headers)
{
   std::copy(headers.begin(), headers.end(), std::back_inserter(headers_));
}

std::string Message::headerValue(const std::string& name) const
{
   return http::headerValue(headers_, name);
}

bool Message::containsHeader(const std::string& name) const
{
   return http::containsHeader(headers_, name);
}

void Message::setHeaderLine(const std::string& line)
{
   Header header;
   if (http::parseHeader(line, &header))
      setHeader(header);
}

void Message::setHeader(const Header& header)
{
   setHeader(header.name, header.value);
}

void Message::setHeader(const std::string& name, const std::string& value)
{
   Headers::iterator it = std::find_if(headers_.begin(),
                                       headers_.end(),
                                       HeaderNamePredicate(name));
   if ( it != headers_.end() )
   {
      Header hdr ;
      hdr.name = name ;
      hdr.value = value ;
      *it = hdr ;
   }
   else
   {
      addHeader(name, value) ;
   }
}

void Message::setHeader(const std::string& name, int value)
{
   setHeader(name, safe_convert::numberToString(value));
}

void Message::replaceHeader(const std::string& name, const std::string& value)
{
   Header hdr ;
   hdr.name = name ;
   hdr.value = value ;
   std::replace_if(headers_.begin(),
                   headers_.end(),
                   HeaderNamePredicate(name),
                   hdr) ;
}

void Message::removeHeader(const std::string& name)
{
   headers_.erase(std::remove_if(headers_.begin(),
                                 headers_.end(),
                                 HeaderNamePredicate(name)),
                  headers_.end())  ;
}

void Message::reset()
{
   setHttpVersion(1,1) ;
   httpVersion_.clear() ;
   headers_.clear() ;
   body_.clear() ;

   // allow additional reseting by subclasses
   resetMembers() ;
}

namespace {
const char Space[] = { ' ' } ;
const char HeaderSeparator[] = { ':', ' ' } ;
const char CrLf[] = { '\r', '\n' } ;

void appendHeader(const Header& header,
                  std::vector<boost::asio::const_buffer>* pBuffers)
{
   pBuffers->push_back(boost::asio::buffer(header.name)) ;
   pBuffers->push_back(boost::asio::buffer(HeaderSeparator)) ;
   pBuffers->push_back(boost::asio::buffer(header.value)) ;
   pBuffers->push_back(boost::asio::buffer(CrLf)) ;
}

}

std::vector<boost::asio::const_buffer> Message::toBuffers(
                                          const Header& overrideHeader) const
{
   // buffers to return
   std::vector<boost::asio::const_buffer> buffers ;

   // call subclass to append first line
   appendFirstLineBuffers(buffers) ;
   buffers.push_back(boost::asio::buffer(CrLf)) ;

   // copy override header (for stable storage)
   overrideHeader_ = overrideHeader;

   // headers
   for (Headers::const_iterator
        it = headers_.begin(); it != headers_.end(); ++it)
   {
      // add the header if it isn't being overriden
      if (it->name != overrideHeader_.name)
         appendHeader(*it, &buffers);
   }

   // add override header
   if (!overrideHeader_.empty())
      appendHeader(overrideHeader_, &buffers);

   // empty line
   buffers.push_back(boost::asio::buffer(CrLf)) ;

   // body
   buffers.push_back(boost::asio::buffer(body_)) ;

   // return the buffers
   return buffers ;
}

void Message::appendSpaceBuffer(
                     std::vector<boost::asio::const_buffer>& buffers) const
{
   buffers.push_back(boost::asio::buffer(Space)) ;
}

void Message::appendHttpVersionBuffers(
      std::vector<boost::asio::const_buffer>& buffers) const
{
   std::ostringstream httpVersionStream;
   httpVersionStream << "HTTP/" << httpVersionMajor_ << "." << httpVersionMinor_ ;
   httpVersion_ = httpVersionStream.str() ;
   buffers.push_back(boost::asio::buffer(httpVersion_)) ;
}

std::ostream& operator << (std::ostream& stream, const Message& m)
{
   // headers
   for (Headers::const_iterator it =
         m.headers().begin(); it != m.headers().end(); ++ it)
   {
      stream << it->name << ": " << it->value << std::endl ;
   }

   // empty line
   stream << std::endl ;

   // body
   stream << m.body() << std::endl ;

   return stream ;
}

} // namespace http
} // namespace core
} // namespace rstudio

<commit_msg>work around RStudio crash (toolchain issue?)<commit_after>/*
 * Message.cpp
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include <core/http/Message.hpp>

#include <algorithm>

#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/function.hpp>
#include <boost/asio/buffer.hpp>

#include <core/SafeConvert.hpp>

namespace rstudio {
namespace core {
namespace http {

// encodings
const char * const kGzipEncoding = "gzip";

void Message::setHttpVersion(int httpVersionMajor, int httpVersionMinor)
{
   httpVersionMajor_ = httpVersionMajor ;
   httpVersionMinor_ = httpVersionMinor ;
}

void Message::setContentType(const std::string& contentType)
{
   setHeader("Content-Type", contentType) ;
}

std::string Message::contentType() const
{
   return headerValue("Content-Type") ;
}

std::size_t Message::contentLength() const
{
   std::string value = headerValue("Content-Length");
   if (value.empty())
      return 0;

   return safe_convert::stringTo<std::size_t>(value, 0);
}

void Message::setContentLength(int contentLength)
{
   setHeader("Content-Length", contentLength);
}

void Message::addHeader(const std::string& name, const std::string& value)
{
   Header header ;
   header.name = name ;
   header.value = value ;
   addHeader(header);
}

void Message::addHeader(const Header& header)
{
   headers_.push_back(header);
}

void Message::addHeaders(const std::vector<Header>& headers)
{
   std::copy(headers.begin(), headers.end(), std::back_inserter(headers_));
}

std::string Message::headerValue(const std::string& name) const
{
   return http::headerValue(headers_, name);
}

bool Message::containsHeader(const std::string& name) const
{
   return http::containsHeader(headers_, name);
}

void Message::setHeaderLine(const std::string& line)
{
   Header header;
   if (http::parseHeader(line, &header))
      setHeader(header);
}

void Message::setHeader(const Header& header)
{
   setHeader(header.name, header.value);
}

void Message::setHeader(const std::string& name, const std::string& value)
{
   Headers::iterator it = std::find_if(headers_.begin(),
                                       headers_.end(),
                                       HeaderNamePredicate(name));
   if ( it != headers_.end() )
   {
      Header hdr ;
      hdr.name = name ;
      hdr.value = value ;
      *it = hdr ;
   }
   else
   {
      addHeader(name, value) ;
   }
}

void Message::setHeader(const std::string& name, int value)
{
   setHeader(name, safe_convert::numberToString(value));
}

void Message::replaceHeader(const std::string& name, const std::string& value)
{
   Header hdr ;
   hdr.name = name ;
   hdr.value = value ;
   std::replace_if(headers_.begin(),
                   headers_.end(),
                   HeaderNamePredicate(name),
                   hdr) ;
}

void Message::removeHeader(const std::string& name)
{
   headers_.erase(std::remove_if(headers_.begin(),
                                 headers_.end(),
                                 HeaderNamePredicate(name)),
                  headers_.end())  ;
}

void Message::reset()
{
   setHttpVersion(1,1) ;
   httpVersion_.clear() ;
   headers_.clear() ;
   body_.clear() ;

   // allow additional reseting by subclasses
   resetMembers() ;
}

namespace {
const char Space[] = { ' ' } ;
const char HeaderSeparator[] = { ':', ' ' } ;
const char CrLf[] = { '\r', '\n' } ;

void appendHeader(const Header& header,
                  std::vector<boost::asio::const_buffer>* pBuffers)
{
   pBuffers->push_back(boost::asio::buffer(header.name)) ;
   pBuffers->push_back(boost::asio::buffer(HeaderSeparator)) ;
   pBuffers->push_back(boost::asio::buffer(header.value)) ;
   pBuffers->push_back(boost::asio::buffer(CrLf)) ;
}

}

std::vector<boost::asio::const_buffer> Message::toBuffers(
                                          const Header& overrideHeader) const
{
   // buffers to return
   std::vector<boost::asio::const_buffer> buffers ;

   // call subclass to append first line
   appendFirstLineBuffers(buffers) ;
   buffers.push_back(boost::asio::buffer(CrLf)) ;

   // copy override header (for stable storage)
   overrideHeader_ = overrideHeader;

   // headers
   for (Headers::const_iterator
        it = headers_.begin(); it != headers_.end(); ++it)
   {
      // add the header if it isn't being overriden
      if (it->name != overrideHeader_.name)
         appendHeader(*it, &buffers);
   }

   // add override header
   if (!overrideHeader_.empty())
      appendHeader(overrideHeader_, &buffers);

   // empty line
   buffers.push_back(boost::asio::buffer(CrLf)) ;

   // body
   buffers.push_back(boost::asio::buffer(body_)) ;

   // return the buffers
   return buffers ;
}

void Message::appendSpaceBuffer(
                     std::vector<boost::asio::const_buffer>& buffers) const
{
   buffers.push_back(boost::asio::buffer(Space)) ;
}

void Message::appendHttpVersionBuffers(
      std::vector<boost::asio::const_buffer>& buffers) const
{
   std::ostringstream httpVersionStream;
   httpVersionStream << "HTTP/" << httpVersionMajor_ << "." << httpVersionMinor_ ;
   httpVersion_ = httpVersionStream.str() ;
   buffers.push_back(boost::asio::buffer(httpVersion_)) ;
}

std::ostream& operator << (std::ostream& stream, const Message& m)
{
   // headers
   for (Headers::const_iterator it =
         m.headers().begin(); it != m.headers().end(); ++ it)
   {
      stream << it->name << ": " << it->value << std::endl ;
   }

   // empty line
   stream << std::endl ;

   // body
   stream << m.body() << std::endl ;

   return stream ;
}

} // namespace http
} // namespace core
} // namespace rstudio

<|endoftext|>


<commit_before>#include "alara.h"
#include "Matrix.h"

/* this is used to determine how many terms are needed in the expansion */
#define MAXEXPTOL 1e-15

/* This is the maximum number of terms allowed for the expansion method
 * If more are needed, the inversion method is used */
#define MAXNUMEXPTERMS 15

/* This is used to determine if poles are degenerate.  Loops should
 * generate poles which are exactly the same, but poles with small
 * relative differences may act as degeneracies anyway */
#define SMALL_REL_DIFF 1e-8

/* routine for to calculate factorial */
double fact(int i)
{
  double result=1;

  while (i>1) result *= i--;

  return result;
}

double bateman(int row, int col, double* P, double* d, double t)
{
  if (row == col)
    /* if this is on the diagonal,
     * simple exponential decay */
    return exp(-d[col]*t);

  if (d[col] == 0)
    /* if the isotope at this rank=col has no destruction,
     * the whole column is empty ! (except the diagonal)
     * Note: this is only possible when calling from a decay matrix sol'n
     */
      return 0;

  double result, sum, sumInc, den;
  int term, denTerm;

  result = 1;
  sum = 0;
  sumInc = 0;

  for (term=col;term<row;term++)
    {
      /* multiplicative increment of normalization */
      result *= P[term+1];

      if (result == 0)
	/* if there is no production path between the isotopes at
	 * row and col, this element is empty
	 * Note: this is only possible when calling from a decay matrix sol'n
	 */
	return 0;

      /* set denominator element based on Laplace root: d[term]
       * (traditional analytic inverse Laplace transform) */
      den = 1;

      for (denTerm=col;denTerm<term;denTerm++)
	den *= (d[denTerm]-d[term]);

      for (denTerm++;denTerm<=row;denTerm++)
	den *= (d[denTerm]-d[term]);

      /* set numerator element based on Laplace root: d[term] */
      sumInc = expm1(-d[term]*t)-expm1(-d[row]*t);

      /* add element based on Laplace root: d[term] */
      sum += sumInc/den;
    }

  /* multiply normalization by sum of Laplace inverse terms */
  result *= sum;

  return result;

};

double dGn(int idx, double *pole, int *mult, int numPoles, int termNum)
{
  int pNum, pwr;
  double invPwrSum,result = 0;

  if (termNum==0)   /* End Condition - 0th derivative */
    /* return inverse product of pole-otherPoles */
    {
      result = 1;

      /* all poles before the current pole */
      for (pNum=0; pNum<idx; pNum++)
	result /= pow( pole[pNum] - pole[idx] , mult[pNum] );

      /* all poles after the current pole */
      for (pNum++; pNum<numPoles; pNum++)
	result /= pow( pole[pNum] - pole[idx] , mult[pNum] );
    }
  else
    for (pwr=termNum;pwr>0;pwr--)
      {
	invPwrSum = 0;

	/* all poles before the current pole */
	for (pNum=0; pNum<idx; pNum++)
	  invPwrSum += mult[pNum] * pow( pole[pNum]-pole[idx] , -pwr );

	/* all poles after the current pole */
	for (pNum++; pNum<numPoles; pNum++)
	  invPwrSum += mult[pNum] * pow( pole[pNum]-pole[idx] , -pwr );

	/* recursively add terms */
	result += -2*(pwr%2 -.5) * (fact(termNum-1)/fact(termNum-pwr))
	  * invPwrSum * dGn(idx,pole,mult,numPoles,termNum-pwr);
      }

  return result;

}

double laplaceInverse(int row, int col, double *d, double t)
{
  int idx, checkIdx, multCnt;
  int numPoles = 0;
  int *mult = new int[row-col+1];
  double *pole = new double[row-col+1];
  double poleResult, result;

  if (row == col)
    /* if this is on the diagonal,
     * simple exponential decay */
    return exp(-d[col]*t);

  /* index all the poles with the multiplicities */
  for (idx = col;idx<=row;idx++)
    {
      for (checkIdx=0;checkIdx<numPoles;checkIdx++)
	if ( fabs((d[idx]-pole[checkIdx]))<SMALL_REL_DIFF*d[idx] )
	  {
	    mult[checkIdx]++;
	    break;
	  }
      if (checkIdx == numPoles)
	{
	  pole[checkIdx] = d[idx];
	  mult[checkIdx] = 1;
	  numPoles++;
	}
    }

  /* perform recursive analytic Laplace inversion */
  for (idx=0;idx<numPoles;idx++)
    {
      poleResult = 0;

      for (multCnt=mult[idx];multCnt>0;multCnt--)
	poleResult += dGn(idx, pole, mult, numPoles, mult[idx] - multCnt)
	  * pow(t,multCnt-1)
	  / fact(multCnt-1)
	  / fact(mult[idx]-multCnt) ;

      result += poleResult * exp(-pole[idx]*t);
    }

  return result;

}

double laplaceExpansion(int row, int col, double *d, double t, int numTerms)
{

  int sz = row-col;
  double result;

  if (row == col)
    /* if this is on the diagonal,
     * simple exponential decay */
    return exp(-d[col]*t);

  /* initialize matrix with destruction rates */
  Matrix poleMat = Matrix::Triangle(d,sz+1);
  Matrix powPoleMat = Matrix::Identity(sz+1);

  /* zeroth term is simply the correct power of t/n!  */
  result = pow(t,sz)/fact(sz);

  /* for each successive term */
  for (int termNum=1;termNum<numTerms;termNum++)
    {
      /* multiply the power matrix by the non-power matrix */
      powPoleMat *= poleMat;

      /* power of t/n! times coefficient, with alternating sign!! */
      result += powPoleMat.rowSum(sz) * ( 1-2*(termNum%2) )
              * pow(t,termNum+sz)/fact(termNum+sz);
    }

  return result;
}

int small(double *d, double t, int rank)
{
  double max=0;

  /* for each pole in the problem */
  for (int poleNum=0;poleNum<rank;poleNum++)
    /* determine the larges pole */
    max = d[poleNum]>max?d[poleNum]:max;

  int n=MAXNUMEXPTERMS;
  /* using a defined maximum number of terms, if the last term results
   * in a correction which is too large */
  if (pow(rank*max*t,n)*fact(rank-1)/(n*fact(n+rank-1)) > MAXEXPTOL)
    /* return the maximum number of terms + 1
     * to be used to indicate that a series expansion will not work */
    return MAXNUMEXPTERMS+1;

  /* arrive at a VERY rough approximation for number of terms by splitting
   * guess in half */
  /* for each guess at the number of terms */
  for (;n>0;n/=2)
    {
      /* if the correction is too large */
      if (pow(rank*max*t,n)*fact(rank-1)/(n*fact(n+rank-1))>MAXEXPTOL)
	/* return the previous guess */
	return 2*n;
    }

  /* return the last guess (must be 1 ... VERY unlikely ) */
  return n;
}

double loopSoln(int row, int col, double *P, double *d, double t)
{

  double result = 1;
  int idx;

  for (idx=col;idx<row;idx++)
    result *= P[idx+1];

  int numExpansionTerms = small(d,t,row-col+1);

  if (numExpansionTerms>MAXNUMEXPTERMS)
    result *= laplaceInverse(row, col, d, t);
  else
    result *= laplaceExpansion(row, col, d, t, numExpansionTerms);

  return result;

}
<commit_msg>Make sure that small() compares correct poles [col..row] rather than first (row-col+1) poles.<commit_after>#include "alara.h"
#include "Matrix.h"

/* this is used to determine how many terms are needed in the expansion */
#define MAXEXPTOL 1e-15

/* This is the maximum number of terms allowed for the expansion method
 * If more are needed, the inversion method is used */
#define MAXNUMEXPTERMS 15

/* This is used to determine if poles are degenerate.  Loops should
 * generate poles which are exactly the same, but poles with small
 * relative differences may act as degeneracies anyway */
#define SMALL_REL_DIFF 1e-8

/* routine for to calculate factorial */
double fact(int i)
{
  double result=1;

  while (i>1) result *= i--;

  return result;
}

double bateman(int row, int col, double* P, double* d, double t)
{
  if (row == col)
    /* if this is on the diagonal,
     * simple exponential decay */
    return exp(-d[col]*t);

  if (d[col] == 0)
    /* if the isotope at this rank=col has no destruction,
     * the whole column is empty ! (except the diagonal)
     * Note: this is only possible when calling from a decay matrix sol'n
     */
      return 0;

  double result, sum, sumInc, den;
  int term, denTerm;

  result = 1;
  sum = 0;
  sumInc = 0;

  for (term=col;term<row;term++)
    {
      /* multiplicative increment of normalization */
      result *= P[term+1];

      if (result == 0)
	/* if there is no production path between the isotopes at
	 * row and col, this element is empty
	 * Note: this is only possible when calling from a decay matrix sol'n
	 */
	return 0;

      /* set denominator element based on Laplace root: d[term]
       * (traditional analytic inverse Laplace transform) */
      den = 1;

      for (denTerm=col;denTerm<term;denTerm++)
	den *= (d[denTerm]-d[term]);

      for (denTerm++;denTerm<=row;denTerm++)
	den *= (d[denTerm]-d[term]);

      /* set numerator element based on Laplace root: d[term] */
      sumInc = expm1(-d[term]*t)-expm1(-d[row]*t);

      /* add element based on Laplace root: d[term] */
      sum += sumInc/den;
    }

  /* multiply normalization by sum of Laplace inverse terms */
  result *= sum;

  return result;

};

double dGn(int idx, double *pole, int *mult, int numPoles, int termNum)
{
  int pNum, pwr;
  double invPwrSum,result = 0;

  if (termNum==0)   /* End Condition - 0th derivative */
    /* return inverse product of pole-otherPoles */
    {
      result = 1;

      /* all poles before the current pole */
      for (pNum=0; pNum<idx; pNum++)
	result /= pow( pole[pNum] - pole[idx] , mult[pNum] );

      /* all poles after the current pole */
      for (pNum++; pNum<numPoles; pNum++)
	result /= pow( pole[pNum] - pole[idx] , mult[pNum] );
    }
  else
    for (pwr=termNum;pwr>0;pwr--)
      {
	invPwrSum = 0;

	/* all poles before the current pole */
	for (pNum=0; pNum<idx; pNum++)
	  invPwrSum += mult[pNum] * pow( pole[pNum]-pole[idx] , -pwr );

	/* all poles after the current pole */
	for (pNum++; pNum<numPoles; pNum++)
	  invPwrSum += mult[pNum] * pow( pole[pNum]-pole[idx] , -pwr );

	/* recursively add terms */
	result += -2*(pwr%2 -.5) * (fact(termNum-1)/fact(termNum-pwr))
	  * invPwrSum * dGn(idx,pole,mult,numPoles,termNum-pwr);
      }

  return result;

}

double laplaceInverse(int row, int col, double *d, double t)
{
  int idx, checkIdx, multCnt;
  int numPoles = 0;
  int *mult = new int[row-col+1];
  double *pole = new double[row-col+1];
  double poleResult, result;

  if (row == col)
    /* if this is on the diagonal,
     * simple exponential decay */
    return exp(-d[col]*t);

  /* index all the poles with the multiplicities */
  for (idx = col;idx<=row;idx++)
    {
      for (checkIdx=0;checkIdx<numPoles;checkIdx++)
	if ( fabs((d[idx]-pole[checkIdx]))<SMALL_REL_DIFF*d[idx] )
	  {
	    mult[checkIdx]++;
	    break;
	  }
      if (checkIdx == numPoles)
	{
	  pole[checkIdx] = d[idx];
	  mult[checkIdx] = 1;
	  numPoles++;
	}
    }

  /* perform recursive analytic Laplace inversion */
  for (idx=0;idx<numPoles;idx++)
    {
      poleResult = 0;

      for (multCnt=mult[idx];multCnt>0;multCnt--)
	poleResult += dGn(idx, pole, mult, numPoles, mult[idx] - multCnt)
	  * pow(t,multCnt-1)
	  / fact(multCnt-1)
	  / fact(mult[idx]-multCnt) ;

      result += poleResult * exp(-pole[idx]*t);
    }

  return result;

}

double laplaceExpansion(int row, int col, double *d, double t, int numTerms)
{

  int sz = row-col;
  double result;

  if (row == col)
    /* if this is on the diagonal,
     * simple exponential decay */
    return exp(-d[col]*t);

  /* initialize matrix with destruction rates */
  Matrix poleMat = Matrix::Triangle(d,sz+1);
  Matrix powPoleMat = Matrix::Identity(sz+1);

  /* zeroth term is simply the correct power of t/n!  */
  result = pow(t,sz)/fact(sz);

  /* for each successive term */
  for (int termNum=1;termNum<numTerms;termNum++)
    {
      /* multiply the power matrix by the non-power matrix */
      powPoleMat *= poleMat;

      /* power of t/n! times coefficient, with alternating sign!! */
      result += powPoleMat.rowSum(sz) * ( 1-2*(termNum%2) )
              * pow(t,termNum+sz)/fact(termNum+sz);
    }

  return result;
}

int small(double *d, double t, int col, int row)
{

  int rank = row-col+1;
  double max=0;

  /* for each pole in the problem */
  for (int poleNum=col;poleNum<=row;poleNum++)
    /* determine the larges pole */
    max = d[poleNum]>max?d[poleNum]:max;

  int n=MAXNUMEXPTERMS;
  /* using a defined maximum number of terms, if the last term results
   * in a correction which is too large */
  if (pow(rank*max*t,n)*fact(rank-1)/(n*fact(n+rank-1)) > MAXEXPTOL)
    /* return the maximum number of terms + 1
     * to be used to indicate that a series expansion will not work */
    return MAXNUMEXPTERMS+1;

  /* arrive at a VERY rough approximation for number of terms by splitting
   * guess in half */
  /* for each guess at the number of terms */
  for (;n>0;n/=2)
    {
      /* if the correction is too large */
      if (pow(rank*max*t,n)*fact(rank-1)/(n*fact(n+rank-1))>MAXEXPTOL)
	/* return the previous guess */
	return 2*n;
    }

  /* return the last guess (must be 1 ... VERY unlikely ) */
  return n;
}

double loopSoln(int row, int col, double *P, double *d, double t)
{

  double result = 1;
  int idx;

  for (idx=col;idx<row;idx++)
    result *= P[idx+1];

  int numExpansionTerms = small(d,t,col,row);

  if (numExpansionTerms>MAXNUMEXPTERMS)
    result *= laplaceInverse(row, col, d, t);
  else
    result *= laplaceExpansion(row, col, d, t, numExpansionTerms);

  return result;

}
<|endoftext|>


<commit_before>#include "Utility.h"

#include <vector>
#include <random>
#include <chrono>
#include <fstream>
#include <algorithm>
#include <string>
#include <cctype>
#include <iostream>

namespace String
{
    namespace
    {
        const auto whitespace = " \t\n";
    }
}

std::vector<std::string> String::split(const std::string& s, const std::string& delim, size_t count)
{
    std::vector<std::string> result;
    size_t start_index = 0;
    size_t end_index = 0;
    size_t split_count = 0;
    while(end_index < s.size() && split_count < count)
    {
        end_index = (delim.empty() ?
                     s.find_first_of(" \t\n", start_index) :
                     s.find(delim, start_index));
        result.push_back(s.substr(start_index, end_index-start_index));
        if(end_index == std::string::npos)
        {
            start_index = std::string::npos;
        }
        else
        {
            start_index = end_index + (delim.empty() ? 1 : delim.size());
        }
        ++split_count;
    }

    if(start_index < s.size())
    {
        result.push_back(s.substr(start_index));
    }

    if(delim.empty())
    {
        auto it = result.begin();
        while(it != result.end())
        {
            if((*it).empty())
            {
                it = result.erase(it);
            }
            else
            {
                (*it) = String::trim_outer_whitespace(*it);
                ++it;
            }
        }
    }

    return result;
}

bool String::starts_with(const std::string& s, const std::string& beginning)
{
    if(beginning.size() > s.size())
    {
        return false;
    }

    return std::equal(beginning.begin(), beginning.end(), s.begin());
}

bool String::starts_with(const std::string& s, char beginning)
{
    return s[0] == beginning;
}

std::string String::consolidate_inner_whitespace(const std::string& s)
{
    size_t start = s.find_first_not_of(whitespace);
    auto initial_whitespace = s.substr(0, start);

    size_t last_non_whitespace = s.find_last_not_of(whitespace);
    std::string final_whitespace;
    if(last_non_whitespace != std::string::npos)
    {
        final_whitespace = s.substr(last_non_whitespace + 1);
    }

    std::string result;

    while(true)
    {
        auto end = s.find_first_of(whitespace, start);

        // [start, end) is all non-whitespace
        if( ! result.empty())
        {
            result += " ";
        }
        result += s.substr(start, end - start);
        start = s.find_first_not_of(whitespace, end);
        if(start == std::string::npos)
        {
            start = end; // only whitespace left
            break;
        }
    }

    return initial_whitespace + result + final_whitespace;
}

std::string String::trim_outer_whitespace(const std::string& s)
{
    auto text_start = s.find_first_not_of(whitespace);
    if(text_start == std::string::npos)
    {
        return std::string{};
    }

    auto text_end = s.find_last_not_of(whitespace);
    if(text_end == std::string::npos)
    {
        return s.substr(text_start);
    }

    return s.substr(text_start, text_end - text_start + 1);
}

std::string String::remove_extra_whitespace(const std::string& s)
{
    return trim_outer_whitespace(consolidate_inner_whitespace(s));
}

std::string String::strip_comments(const std::string& str, char comment)
{
    return trim_outer_whitespace(str.substr(0, str.find(comment)));
}

std::string String::strip_block_comment(const std::string& str, char start, char end)
{
    auto start_comment_index = str.find(start);
    auto end_comment_index = str.find(end);
    if(start_comment_index == std::string::npos || end_comment_index == std::string::npos)
    {
        return consolidate_inner_whitespace(trim_outer_whitespace(str));
    }

    auto first_part = str.substr(0, start_comment_index);
    auto last_part = str.substr(end_comment_index + 1);
    return strip_block_comment(first_part + " " + last_part, start, end);
}

std::string String::lowercase(std::string s)
{
    std::transform(s.begin(), s.end(), s.begin(), [](char c) -> char { return std::tolower(c); });
    return s;
}

int Random::random_integer(int min, int max)
{
    thread_local static std::mt19937_64 generator(std::random_device{}());
    using uid = std::uniform_int_distribution<int>;
    thread_local static auto dist = uid{};
    return dist(generator, uid::param_type{min, max});
}

double Random::random_normal(double standard_deviation)
{
    thread_local static std::mt19937_64 generator(std::random_device{}());
    using nd = std::normal_distribution<double>;
    thread_local static auto dist = nd{};
    return dist(generator, nd::param_type{0.0, standard_deviation});
}

double Random::random_real(double min, double max)
{
    thread_local static std::mt19937_64 generator(std::random_device{}());
    using urd = std::uniform_real_distribution<double>;
    thread_local static auto dist = urd{};
    return dist(generator, urd::param_type{min, max});
}

bool Random::coin_flip()
{
    return success_probability(0.5);
}

bool Random::success_probability(double probability)
{
    return random_real(0.0, 1.0) < probability;
}

// Mean moves left in game given that a number of moves have been made already.
double Math::average_moves_left(double mean_moves, double width, size_t moves_so_far)
{
    // Assumes the number of moves in a game has a log-normal distribution.
    //
    // A = Sum(x = moves_so_far + 1 to infinity) P(x)*x = average number of moves
    //                                                    given game has already progressed
    //                                                    moves_so_far
    //
    // B = Sum(x = moves_so_far + 1 to infinity) P(x) = renormalization of P(x) for a
    //                                                  truncated range

    auto M = std::log(mean_moves);
    auto S = width;
    auto S2 = std::pow(S, 2);
    auto Sr2 = S*std::sqrt(2);
    auto ln_x = std::log(moves_so_far);

    auto A = std::exp(M + S2/2)*(1 + std::erf((M + S2 - ln_x)/Sr2));
    auto B = 1 + std::erf((M-ln_x)/Sr2);

    auto expected_mean = A/B;
    return expected_mean - moves_so_far;
}

Configuration_File::Configuration_File(const std::string& file_name)
{
    std::ifstream ifs(file_name);
    std::string line;
    while(std::getline(ifs, line))
    {
        line = String::strip_comments(line, '#');
        if(line.empty())
        {
            continue;
        }
        if( ! String::contains(line, '='))
        {
            throw std::runtime_error("Configuration file lines must be of form \"Name = Value\"\n" + line);
        }
        auto line_split = String::split(line, "=", 1);
        auto parameter = String::lowercase(String::remove_extra_whitespace(line_split[0]));
        parameters[parameter] = String::trim_outer_whitespace(line_split[1]);
    }
}

std::string Configuration_File::get_text(const std::string& parameter) const
{
    try
    {
        return parameters.at(parameter);
    }
    catch(const std::out_of_range&)
    {
        for(const auto& key_value : parameters)
        {
            std::cerr << "\"" << key_value.first << "\" --> \"" << key_value.second << "\"" << std::endl;
        }
        throw std::runtime_error("Configuration parameter not found: " + parameter);
    }
}

double Configuration_File::get_number(const std::string& parameter) const
{
    try
    {
        return std::stod(get_text(parameter));
    }
    catch(const std::invalid_argument&)
    {
        throw std::runtime_error("Invalid number for \"" + parameter + "\" : " + get_text(parameter));
    }
}

std::ofstream Scoped_Stopwatch::out_file;
std::mutex Scoped_Stopwatch::write_lock;

Scoped_Stopwatch::Scoped_Stopwatch(const std::string& name) :
    place_name(name),
    start_time(std::chrono::steady_clock::now()),
    stopped(false)
{
}

Scoped_Stopwatch::~Scoped_Stopwatch()
{
    stop();
}

void Scoped_Stopwatch::stop()
{
    auto end_time = std::chrono::steady_clock::now();

    if(stopped)
    {
        return;
    }

    std::lock_guard<std::mutex> write_lock_guard(write_lock);

    if( ! out_file.is_open())
    {
        out_file.open("timings.txt");
    }

    out_file << place_name << "|"
             << std::chrono::duration_cast<std::chrono::duration<double>>
                (end_time - start_time).count()
             << '\n';

    stopped = true;
}

void Scoped_Stopwatch::add_info(const std::string& info)
{
    place_name += info;
}
<commit_msg>Minor fixes to Utility.cpp<commit_after>#include "Utility.h"

#include <vector>
#include <random>
#include <chrono>
#include <fstream>
#include <algorithm>
#include <string>
#include <cctype>
#include <iostream>
#include <cmath>

namespace String
{
    namespace
    {
        const auto whitespace = " \t\n";
    }
}

std::vector<std::string> String::split(const std::string& s, const std::string& delim, size_t count)
{
    std::vector<std::string> result;
    size_t start_index = 0;
    size_t end_index = 0;
    size_t split_count = 0;
    while(end_index < s.size() && split_count < count)
    {
        end_index = (delim.empty() ?
                     s.find_first_of(" \t\n", start_index) :
                     s.find(delim, start_index));
        result.push_back(s.substr(start_index, end_index-start_index));
        if(end_index == std::string::npos)
        {
            start_index = std::string::npos;
        }
        else
        {
            start_index = end_index + (delim.empty() ? 1 : delim.size());
        }
        ++split_count;
    }

    if(start_index < s.size())
    {
        result.push_back(s.substr(start_index));
    }

    if(delim.empty())
    {
        auto it = result.begin();
        while(it != result.end())
        {
            if((*it).empty())
            {
                it = result.erase(it);
            }
            else
            {
                (*it) = String::trim_outer_whitespace(*it);
                ++it;
            }
        }
    }

    return result;
}

bool String::starts_with(const std::string& s, const std::string& beginning)
{
    if(beginning.size() > s.size())
    {
        return false;
    }

    return std::equal(beginning.begin(), beginning.end(), s.begin());
}

bool String::starts_with(const std::string& s, char beginning)
{
    return s[0] == beginning;
}

std::string String::consolidate_inner_whitespace(const std::string& s)
{
    size_t start = s.find_first_not_of(whitespace);
    auto initial_whitespace = s.substr(0, start);

    size_t last_non_whitespace = s.find_last_not_of(whitespace);
    std::string final_whitespace;
    if(last_non_whitespace != std::string::npos)
    {
        final_whitespace = s.substr(last_non_whitespace + 1);
    }

    std::string result;

    while(true)
    {
        auto end = s.find_first_of(whitespace, start);

        // [start, end) is all non-whitespace
        if( ! result.empty())
        {
            result += " ";
        }
        result += s.substr(start, end - start);
        start = s.find_first_not_of(whitespace, end);
        if(start == std::string::npos)
        {
            start = end; // only whitespace left
            break;
        }
    }

    return initial_whitespace + result + final_whitespace;
}

std::string String::trim_outer_whitespace(const std::string& s)
{
    auto text_start = s.find_first_not_of(whitespace);
    if(text_start == std::string::npos)
    {
        return std::string{};
    }

    auto text_end = s.find_last_not_of(whitespace);
    if(text_end == std::string::npos)
    {
        return s.substr(text_start);
    }

    return s.substr(text_start, text_end - text_start + 1);
}

std::string String::remove_extra_whitespace(const std::string& s)
{
    return trim_outer_whitespace(consolidate_inner_whitespace(s));
}

std::string String::strip_comments(const std::string& str, char comment)
{
    return trim_outer_whitespace(str.substr(0, str.find(comment)));
}

std::string String::strip_block_comment(const std::string& str, char start, char end)
{
    auto start_comment_index = str.find(start);
    auto end_comment_index = str.find(end);
    if(start_comment_index == std::string::npos || end_comment_index == std::string::npos)
    {
        return consolidate_inner_whitespace(trim_outer_whitespace(str));
    }

    auto first_part = str.substr(0, start_comment_index);
    auto last_part = str.substr(end_comment_index + 1);
    return strip_block_comment(first_part + " " + last_part, start, end);
}

std::string String::lowercase(std::string s)
{
    std::transform(s.begin(), s.end(), s.begin(), [](char c) -> char { return std::tolower(c); });
    return s;
}

int Random::random_integer(int min, int max)
{
    thread_local static std::mt19937_64 generator(std::random_device{}());
    using uid = std::uniform_int_distribution<int>;
    thread_local static auto dist = uid{};
    return dist(generator, uid::param_type{min, max});
}

double Random::random_normal(double standard_deviation)
{
    thread_local static std::mt19937_64 generator(std::random_device{}());
    using nd = std::normal_distribution<double>;
    thread_local static auto dist = nd{};
    return dist(generator, nd::param_type{0.0, standard_deviation});
}

double Random::random_real(double min, double max)
{
    thread_local static std::mt19937_64 generator(std::random_device{}());
    using urd = std::uniform_real_distribution<double>;
    thread_local static auto dist = urd{};
    return dist(generator, urd::param_type{min, max});
}

bool Random::coin_flip()
{
    return success_probability(0.5);
}

bool Random::success_probability(double probability)
{
    return random_real(0.0, 1.0) < probability;
}

// Mean moves left in game given that a number of moves have been made already.
double Math::average_moves_left(double mean_moves, double width, size_t moves_so_far)
{
    // Assumes the number of moves in a game has a log-normal distribution.
    //
    // A = Sum(x = moves_so_far + 1 to infinity) P(x)*x = average number of moves
    //                                                    given game has already progressed
    //                                                    moves_so_far
    //
    // B = Sum(x = moves_so_far + 1 to infinity) P(x) = renormalization of P(x) for a
    //                                                  truncated range
    //
    // The calculations below for A and B use integrals on continuous functions as a
    // faster approximation.

    auto M = std::log(mean_moves);
    auto S = width;
    auto S2 = std::pow(S, 2);
    auto Sr2 = S*std::sqrt(2);
    auto ln_x = std::log(moves_so_far);

    auto A = std::exp(M + S2/2)*(1 + std::erf((M + S2 - ln_x)/Sr2));
    auto B = 1 + std::erf((M-ln_x)/Sr2);

    auto expected_mean = A/B;
    return expected_mean - moves_so_far;
}

Configuration_File::Configuration_File(const std::string& file_name)
{
    std::ifstream ifs(file_name);
    std::string line;
    while(std::getline(ifs, line))
    {
        line = String::strip_comments(line, '#');
        if(line.empty())
        {
            continue;
        }
        if( ! String::contains(line, '='))
        {
            throw std::runtime_error("Configuration file lines must be of form \"Name = Value\"\n" + line);
        }
        auto line_split = String::split(line, "=", 1);
        auto parameter = String::lowercase(String::remove_extra_whitespace(line_split[0]));
        parameters[parameter] = String::trim_outer_whitespace(line_split[1]);
    }
}

std::string Configuration_File::get_text(const std::string& parameter) const
{
    try
    {
        return parameters.at(parameter);
    }
    catch(const std::out_of_range&)
    {
        for(const auto& key_value : parameters)
        {
            std::cerr << "\"" << key_value.first << "\" --> \"" << key_value.second << "\"" << std::endl;
        }
        throw std::runtime_error("Configuration parameter not found: " + parameter);
    }
}

double Configuration_File::get_number(const std::string& parameter) const
{
    try
    {
        return std::stod(get_text(parameter));
    }
    catch(const std::invalid_argument&)
    {
        throw std::runtime_error("Invalid number for \"" + parameter + "\" : " + get_text(parameter));
    }
}

std::ofstream Scoped_Stopwatch::out_file;
std::mutex Scoped_Stopwatch::write_lock;

Scoped_Stopwatch::Scoped_Stopwatch(const std::string& name) :
    place_name(name),
    start_time(std::chrono::steady_clock::now()),
    stopped(false)
{
}

Scoped_Stopwatch::~Scoped_Stopwatch()
{
    stop();
}

void Scoped_Stopwatch::stop()
{
    auto end_time = std::chrono::steady_clock::now();

    if(stopped)
    {
        return;
    }

    std::lock_guard<std::mutex> write_lock_guard(write_lock);

    if( ! out_file.is_open())
    {
        out_file.open("timings.txt");
    }

    out_file << place_name << "|"
             << std::chrono::duration_cast<std::chrono::duration<double>>
                (end_time - start_time).count()
             << '\n';

    stopped = true;
}

void Scoped_Stopwatch::add_info(const std::string& info)
{
    place_name += info;
}
<|endoftext|>


<commit_before>// For faster build
#include "marisa/trie.cc"

#include "marisa/agent.cc"

#include "marisa/grimoire/io/reader.cc"
#include "marisa/grimoire/io/writer.cc"

#include "marisa/grimoire/io/mapper.cc"
#include "marisa/grimoire/trie/louds-trie.cc"
#include "marisa/grimoire/trie/tail.cc"
#include "marisa/grimoire/vector/bit-vector.cc"
#include "marisa/keyset.cc"
<commit_msg>Add comments to marisa.cc for node.<commit_after>// For faster build
// Keep include order for VS compatibility.
#include "marisa/trie.cc"
// 1
#include "marisa/agent.cc"
// 2
#include "marisa/grimoire/io/reader.cc"
#include "marisa/grimoire/io/writer.cc"
// 3
#include "marisa/grimoire/io/mapper.cc"
#include "marisa/grimoire/trie/louds-trie.cc"
#include "marisa/grimoire/trie/tail.cc"
#include "marisa/grimoire/vector/bit-vector.cc"
#include "marisa/keyset.cc"
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014, Julien Bernard
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
#include "Rules.h"

#include <cassert>
#include <cstdio>

Rules::Rules(const Racket& lft, const Racket& rgt, Ball& ball)
  : l(&lft), r(&rgt), b(&ball)
  , m_l_points(0), m_r_points(0) {
  assert(lft.isOnLeft() && rgt.isOnRight());
}

int Rules::priority() const {
  return 1;
}

static bool isTouchingX(const Ball& ball, const Racket& racket) {
  float dx = std::abs(ball.getPosition().x - racket.getPosition().x);
  return dx < Ball::RADIUS + Racket::WIDTH / 2;
}

static bool isTouchingY(const Ball& ball, const Racket& racket) {
  float dy = std::abs(ball.getPosition().y - racket.getPosition().y);
  return dy < Racket::HEIGHT / 2;
}

static constexpr float PI = 3.14159265358979323846f;

static float computeNewAngle(const Ball& ball, const Racket& racket) {
  float dy = ball.getPosition().y - racket.getPosition().y;
  return 0.7 * dy / Racket::HEIGHT * PI;
}

void Rules::update(float dt) {
  static constexpr float X_LIMIT = Ground::WIDTH / 2 - Ball::RADIUS;

  sf::Vector2f velocity = b->getVelocity();
  auto position = b->getPosition();

  if (velocity.x > 0) {
    if (position.x < r->getPosition().x && isTouchingX(*b, *r) && isTouchingY(*b, *r)) {
      float angle = computeNewAngle(*b, *r);
      velocity.x = std::cos(PI - angle) * Ball::VELOCITY;
      velocity.y = std::sin(PI - angle) * Ball::VELOCITY;
//       velocity.x = -velocity.x;
    }

    if (position.x > X_LIMIT) {
      m_l_points++;
      velocity.x = -velocity.x;
      b->resetPosition();
    }
  } else {
    if (position.x > l->getPosition().x && isTouchingX(*b, *l) && isTouchingY(*b, *l)) {
      float angle = computeNewAngle(*b, *l);
      velocity.x = std::cos(angle) * Ball::VELOCITY;
      velocity.y = std::sin(angle) * Ball::VELOCITY;
//       velocity.x = -velocity.x;
    }

    if (position.x < - X_LIMIT) {
      m_r_points++;
      velocity.x = -velocity.x;
      b->resetPosition();
    }
  }

  b->setVelocity(velocity);
}

static const char digits[10][5][4] = {
  {
    " ##",
    "# #",
    "# #",
    "# #",
    "## ",
  },
  {
    " # ",
    " # ",
    " # ",
    " # ",
    " # ",
  },
  {
    "## ",
    "  #",
    " # ",
    "#  ",
    "###",
  },
  {
    "###",
    "  #",
    " ##",
    "  #",
    "###",
  },
  {
    "#  ",
    "#  ",
    "# #",
    "###",
    "  #",
  },
  {
    "###",
    "#  ",
    "###",
    "  #",
    "## ",
  },
  {
    "#  ",
    "#  ",
    "###",
    "# #",
    "###",
  },
  {
    "###",
    "  #",
    "  #",
    "  #",
    "  #",
  },
  {
    "###",
    "# #",
    "###",
    "# #",
    "###",
  },
  {
    "###",
    "# #",
    "###",
    "  #",
    "  #",
  },
};

static void displayDigit(unsigned d, const sf::Vector2f& position, sf::RenderWindow& window) {
  assert(0 <= d && d <= 9);

  static constexpr float WIDTH = 1.3f;
  static constexpr float HEIGHT = 2.0f;

  sf::RectangleShape shape({ WIDTH, HEIGHT });
  shape.setOrigin(WIDTH / 2, HEIGHT / 2);
  shape.setFillColor(sf::Color::White);

  for (int i = 0; i < 5; ++i) {
    for (int j = 0; j < 3; ++j) {
      if (digits[d][i][j] == '#') {
        shape.setPosition(position.x + (j - 1) * WIDTH, position.y + (i - 2) * HEIGHT);
        window.draw(shape);
      }
    }
  }
}

void Rules::render(sf::RenderWindow& window) {
  static constexpr float HI_X = 85.0f;
  static constexpr float LO_X = 90.0f;
  static constexpr float Y = 40.0f;

  displayDigit((m_r_points / 10) % 10, { HI_X, -Y }, window);
  displayDigit(m_r_points % 10, { LO_X, -Y }, window);

  displayDigit((m_l_points / 10) % 10, { -LO_X, -Y }, window);
  displayDigit(m_l_points % 10, { - HI_X, -Y }, window);
}
<commit_msg>remove unnecessary header<commit_after>/*
 * Copyright (c) 2014, Julien Bernard
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
#include "Rules.h"

#include <cassert>

Rules::Rules(const Racket& lft, const Racket& rgt, Ball& ball)
  : l(&lft), r(&rgt), b(&ball)
  , m_l_points(0), m_r_points(0) {
  assert(lft.isOnLeft() && rgt.isOnRight());
}

int Rules::priority() const {
  return 1;
}

static bool isTouchingX(const Ball& ball, const Racket& racket) {
  float dx = std::abs(ball.getPosition().x - racket.getPosition().x);
  return dx < Ball::RADIUS + Racket::WIDTH / 2;
}

static bool isTouchingY(const Ball& ball, const Racket& racket) {
  float dy = std::abs(ball.getPosition().y - racket.getPosition().y);
  return dy < Racket::HEIGHT / 2;
}

static constexpr float PI = 3.14159265358979323846f;

static float computeNewAngle(const Ball& ball, const Racket& racket) {
  float dy = ball.getPosition().y - racket.getPosition().y;
  return 0.7 * dy / Racket::HEIGHT * PI;
}

void Rules::update(float dt) {
  static constexpr float X_LIMIT = Ground::WIDTH / 2 - Ball::RADIUS;

  sf::Vector2f velocity = b->getVelocity();
  auto position = b->getPosition();

  if (velocity.x > 0) {
    if (position.x < r->getPosition().x && isTouchingX(*b, *r) && isTouchingY(*b, *r)) {
      float angle = computeNewAngle(*b, *r);
      velocity.x = std::cos(PI - angle) * Ball::VELOCITY;
      velocity.y = std::sin(PI - angle) * Ball::VELOCITY;
//       velocity.x = -velocity.x;
    }

    if (position.x > X_LIMIT) {
      m_l_points++;
      velocity.x = -velocity.x;
      b->resetPosition();
    }
  } else {
    if (position.x > l->getPosition().x && isTouchingX(*b, *l) && isTouchingY(*b, *l)) {
      float angle = computeNewAngle(*b, *l);
      velocity.x = std::cos(angle) * Ball::VELOCITY;
      velocity.y = std::sin(angle) * Ball::VELOCITY;
//       velocity.x = -velocity.x;
    }

    if (position.x < - X_LIMIT) {
      m_r_points++;
      velocity.x = -velocity.x;
      b->resetPosition();
    }
  }

  b->setVelocity(velocity);
}

static const char digits[10][5][4] = {
  {
    " ##",
    "# #",
    "# #",
    "# #",
    "## ",
  },
  {
    " # ",
    " # ",
    " # ",
    " # ",
    " # ",
  },
  {
    "## ",
    "  #",
    " # ",
    "#  ",
    "###",
  },
  {
    "###",
    "  #",
    " ##",
    "  #",
    "###",
  },
  {
    "#  ",
    "#  ",
    "# #",
    "###",
    "  #",
  },
  {
    "###",
    "#  ",
    "###",
    "  #",
    "## ",
  },
  {
    "#  ",
    "#  ",
    "###",
    "# #",
    "###",
  },
  {
    "###",
    "  #",
    "  #",
    "  #",
    "  #",
  },
  {
    "###",
    "# #",
    "###",
    "# #",
    "###",
  },
  {
    "###",
    "# #",
    "###",
    "  #",
    "  #",
  },
};

static void displayDigit(unsigned d, const sf::Vector2f& position, sf::RenderWindow& window) {
  assert(0 <= d && d <= 9);

  static constexpr float WIDTH = 1.3f;
  static constexpr float HEIGHT = 2.0f;

  sf::RectangleShape shape({ WIDTH, HEIGHT });
  shape.setOrigin(WIDTH / 2, HEIGHT / 2);
  shape.setFillColor(sf::Color::White);

  for (int i = 0; i < 5; ++i) {
    for (int j = 0; j < 3; ++j) {
      if (digits[d][i][j] == '#') {
        shape.setPosition(position.x + (j - 1) * WIDTH, position.y + (i - 2) * HEIGHT);
        window.draw(shape);
      }
    }
  }
}

void Rules::render(sf::RenderWindow& window) {
  static constexpr float HI_X = 85.0f;
  static constexpr float LO_X = 90.0f;
  static constexpr float Y = 40.0f;

  displayDigit((m_r_points / 10) % 10, { HI_X, -Y }, window);
  displayDigit(m_r_points % 10, { LO_X, -Y }, window);

  displayDigit((m_l_points / 10) % 10, { -LO_X, -Y }, window);
  displayDigit(m_l_points % 10, { - HI_X, -Y }, window);
}
<|endoftext|>