Click here to Skip to main content
15,896,726 members
Articles / Web Development / HTML

Introducing Investigo: Using a Proxy DLL and embedded HTTP server for DirectX9 Performance Analysis, Debugging and Automated Performance Testing.

Rate me:
Please Sign up or sign in to vote.
4.90/5 (6 votes)
9 Nov 2012MIT48 min read 57.1K   1.4K   9  
Introducing Investigo: Using a Proxy DLL and embedded HTTP server for DirectX9 Performance Analysis, Debugging and Automated Performance Testing
#ifndef _DATE_TIME_INT_ADAPTER_HPP__
#define _DATE_TIME_INT_ADAPTER_HPP__

/* Copyright (c) 2002,2003 CrystalClear Software, Inc.
 * Use, modification and distribution is subject to the 
 * Boost Software License, Version 1.0. (See accompanying
 * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
 * Author: Jeff Garland, Bart Garst
 * $Date: 2008-11-12 14:37:53 -0500 (Wed, 12 Nov 2008) $
 */


#include "boost/config.hpp"
#include "boost/limits.hpp" //work around compilers without limits
#include "boost/date_time/special_defs.hpp"
#include "boost/date_time/locale_config.hpp"
#ifndef BOOST_DATE_TIME_NO_LOCALE
#  include <ostream>
#endif

namespace boost {
namespace date_time {


//! Adapter to create integer types with +-infinity, and not a value
/*! This class is used internally in counted date/time representations.
 *  It adds the floating point like features of infinities and
 *  not a number. It also provides mathmatical operations with
 *  consideration to special values following these rules:
 *@code
 *  +infinity  -  infinity  == Not A Number (NAN)
 *   infinity  *  non-zero  == infinity
 *   infinity  *  zero      == NAN
 *  +infinity  * -integer   == -infinity
 *   infinity  /  infinity  == NAN
 *   infinity  *  infinity  == infinity 
 *@endcode 
 */
template<typename int_type_>
class int_adapter {
public:
  typedef int_type_ int_type;
  int_adapter(int_type v) :
    value_(v)
  {}
  static bool has_infinity()
  {
    return  true;
  }
  static const int_adapter  pos_infinity()
  {
    return (::std::numeric_limits<int_type>::max)();
  }
  static const int_adapter  neg_infinity()
  {
    return (::std::numeric_limits<int_type>::min)();
  }
  static const int_adapter  not_a_number()
  {
    return (::std::numeric_limits<int_type>::max)()-1;
  }
  static  int_adapter max BOOST_PREVENT_MACRO_SUBSTITUTION ()
  {
    return (::std::numeric_limits<int_type>::max)()-2;
  }
  static  int_adapter min BOOST_PREVENT_MACRO_SUBSTITUTION ()
  {
    return (::std::numeric_limits<int_type>::min)()+1;
  }
  static int_adapter from_special(special_values sv)
  {
    switch (sv) {
    case not_a_date_time: return not_a_number();
    case neg_infin:       return neg_infinity();
    case pos_infin:       return pos_infinity();
    case max_date_time:   return (max)();
    case min_date_time:   return (min)();
    default:              return not_a_number();
    }
  }
  static bool is_inf(int_type v)
  {
    return (v == neg_infinity().as_number() ||
            v == pos_infinity().as_number());
  }
  static bool is_neg_inf(int_type v)
  {
    return (v == neg_infinity().as_number());
  }
  static bool is_pos_inf(int_type v)
  {
    return (v == pos_infinity().as_number());
  }
  static bool is_not_a_number(int_type v)
  {
    return (v == not_a_number().as_number());
  }
  //! Returns either special value type or is_not_special
  static special_values to_special(int_type v)
  {
    if (is_not_a_number(v)) return not_a_date_time;
    if (is_neg_inf(v)) return neg_infin;
    if (is_pos_inf(v)) return pos_infin;
    return not_special;
  }

  //-3 leaves room for representations of infinity and not a date
  static  int_type maxcount()
  {
    return (::std::numeric_limits<int_type>::max)()-3;
  }
  bool is_infinity() const
  {
    return (value_ == neg_infinity().as_number() ||
            value_ == pos_infinity().as_number());
  }
  bool is_pos_infinity()const
  {
    return(value_ == pos_infinity().as_number());
  }
  bool is_neg_infinity()const
  {
    return(value_ == neg_infinity().as_number());
  }
  bool is_nan() const
  {
    return (value_ == not_a_number().as_number());
  }
  bool is_special() const
  {
    return(is_infinity() || is_nan()); 
  }
  bool operator==(const int_adapter& rhs) const
  {
    return (compare(rhs) == 0);
  }
  bool operator==(const int& rhs) const
  {
    // quiets compiler warnings
    bool is_signed = std::numeric_limits<int_type>::is_signed;
    if(!is_signed)
    {
      if(is_neg_inf(value_) && rhs == 0)
      {
        return false;
      }
    }
    return (compare(rhs) == 0);
  }
  bool operator!=(const int_adapter& rhs) const
  {
    return (compare(rhs) != 0);
  }
  bool operator!=(const int& rhs) const
  {
    // quiets compiler warnings
    bool is_signed = std::numeric_limits<int_type>::is_signed;
    if(!is_signed)
    {
      if(is_neg_inf(value_) && rhs == 0)
      {
        return true;
      }
    }
    return (compare(rhs) != 0);
  }
  bool operator<(const int_adapter& rhs) const
  {
    return (compare(rhs) == -1);
  }
  bool operator<(const int& rhs) const
  {
    // quiets compiler warnings
    bool is_signed = std::numeric_limits<int_type>::is_signed;
    if(!is_signed)
    {
      if(is_neg_inf(value_) && rhs == 0)
      {
        return true;
      }
    }
    return (compare(rhs) == -1);
  }
  bool operator>(const int_adapter& rhs) const
  {
    return (compare(rhs) == 1);
  }
  int_type as_number() const
  {
    return value_;
  }
  //! Returns either special value type or is_not_special
  special_values as_special() const
  {
    return int_adapter::to_special(value_);
  }
  //creates nasty ambiguities
//   operator int_type() const
//   {
//     return value_;
//   }

  /*! Operator allows for adding dissimilar int_adapter types.
   * The return type will match that of the the calling object's type */
  template<class rhs_type>
  inline
  int_adapter operator+(const int_adapter<rhs_type>& rhs) const
  {
    if(is_special() || rhs.is_special())
    {
      if (is_nan() || rhs.is_nan()) 
      {
        return int_adapter::not_a_number();
      }
      if((is_pos_inf(value_) && rhs.is_neg_inf(rhs.as_number())) ||
      (is_neg_inf(value_) && rhs.is_pos_inf(rhs.as_number())) )
      {
        return int_adapter::not_a_number();
      }
      if (is_infinity()) 
      {
        return *this;
      }
      if (rhs.is_pos_inf(rhs.as_number())) 
      {
        return int_adapter::pos_infinity();
      }
      if (rhs.is_neg_inf(rhs.as_number())) 
      {
        return int_adapter::neg_infinity();
      }
    }
    return int_adapter<int_type>(value_ + rhs.as_number());
  }

  int_adapter operator+(const int_type rhs) const
  {
    if(is_special())
    {
      if (is_nan()) 
      {
        return int_adapter<int_type>(not_a_number());
      }
      if (is_infinity()) 
      {
        return *this;
      }
    }
    return int_adapter<int_type>(value_ + rhs);
  }
  
  /*! Operator allows for subtracting dissimilar int_adapter types.
   * The return type will match that of the the calling object's type */
  template<class rhs_type>
  inline
  int_adapter operator-(const int_adapter<rhs_type>& rhs)const
  {
    if(is_special() || rhs.is_special())
    {
      if (is_nan() || rhs.is_nan()) 
      {
        return int_adapter::not_a_number();
      }
      if((is_pos_inf(value_) && rhs.is_pos_inf(rhs.as_number())) ||
         (is_neg_inf(value_) && rhs.is_neg_inf(rhs.as_number())) )
      {
        return int_adapter::not_a_number();
      }
      if (is_infinity()) 
      {
        return *this;
      }
      if (rhs.is_pos_inf(rhs.as_number())) 
      {
        return int_adapter::neg_infinity();
      }
      if (rhs.is_neg_inf(rhs.as_number())) 
      {
        return int_adapter::pos_infinity();
      }
    }
    return int_adapter<int_type>(value_ - rhs.as_number());
  }
  int_adapter operator-(const int_type rhs) const
  {
    if(is_special())
    {
      if (is_nan()) 
      {
        return int_adapter<int_type>(not_a_number());
      }
      if (is_infinity()) 
      {
        return *this;
      }
    }
    return int_adapter<int_type>(value_ - rhs);
  }

  // should templatize this to be consistant with op +-
  int_adapter operator*(const int_adapter& rhs)const
  {
    if(this->is_special() || rhs.is_special())
    {
      return mult_div_specials(rhs);
    }
    return int_adapter<int_type>(value_ * rhs.value_);
  }
  /*! Provided for cases when automatic conversion from 
   * 'int' to 'int_adapter' causes incorrect results. */
  int_adapter operator*(const int rhs) const
  {
    if(is_special())
    {
      return mult_div_specials(rhs);
    }
    return int_adapter<int_type>(value_ * rhs);
  }

  // should templatize this to be consistant with op +-
  int_adapter operator/(const int_adapter& rhs)const
  {
    if(this->is_special() || rhs.is_special())
    {
      if(is_infinity() && rhs.is_infinity())
      {
        return int_adapter<int_type>(not_a_number());
      }
      if(rhs != 0)
      {
        return mult_div_specials(rhs);
      }
      else { // let divide by zero blow itself up
        return int_adapter<int_type>(value_ / rhs.value_);
      }
    }
    return int_adapter<int_type>(value_ / rhs.value_);
  }
  /*! Provided for cases when automatic conversion from 
   * 'int' to 'int_adapter' causes incorrect results. */
  int_adapter operator/(const int rhs) const
  {
    if(is_special() && rhs != 0)
    {
      return mult_div_specials(rhs);
    }
    return int_adapter<int_type>(value_ / rhs);
  }

  // should templatize this to be consistant with op +-
  int_adapter operator%(const int_adapter& rhs)const
  {
    if(this->is_special() || rhs.is_special())
    {
      if(is_infinity() && rhs.is_infinity())
      {
        return int_adapter<int_type>(not_a_number());
      }
      if(rhs != 0)
      {
        return mult_div_specials(rhs);
      }
      else { // let divide by zero blow itself up
        return int_adapter<int_type>(value_ % rhs.value_);
      }
    }
    return int_adapter<int_type>(value_ % rhs.value_);
  }
  /*! Provided for cases when automatic conversion from 
   * 'int' to 'int_adapter' causes incorrect results. */
  int_adapter operator%(const int rhs) const
  {
    if(is_special() && rhs != 0)
    {
      return mult_div_specials(rhs);
    }
    return int_adapter<int_type>(value_ % rhs);
  }
private:
  int_type value_;
  
  //! returns -1, 0, 1, or 2 if 'this' is <, ==, >, or 'nan comparison' rhs
  int compare(const int_adapter& rhs)const
  {
    if(this->is_special() || rhs.is_special())
    {
      if(this->is_nan() || rhs.is_nan()) {
        if(this->is_nan() && rhs.is_nan()) {
          return 0; // equal
        }
        else {
          return 2; // nan
        }
      }
      if((is_neg_inf(value_) && !is_neg_inf(rhs.value_)) ||
         (is_pos_inf(rhs.value_) && !is_pos_inf(value_)) )
        {
          return -1; // less than
        }
      if((is_pos_inf(value_) && !is_pos_inf(rhs.value_)) ||
         (is_neg_inf(rhs.value_) && !is_neg_inf(value_)) ) {
        return 1; // greater than
      }
    }
    if(value_ < rhs.value_) return -1;
    if(value_ > rhs.value_) return 1;
    // implied-> if(value_ == rhs.value_) 
    return 0;
  }
  /* When multiplying and dividing with at least 1 special value
   * very simmilar rules apply. In those cases where the rules
   * are different, they are handled in the respective operator 
   * function. */
  //! Assumes at least 'this' or 'rhs' is a special value
  int_adapter mult_div_specials(const int_adapter& rhs)const
  {
    int min_value; 
    // quiets compiler warnings
    bool is_signed = std::numeric_limits<int_type>::is_signed;
    if(is_signed) {
      min_value = 0;
    }
    else {
      min_value = 1;// there is no zero with unsigned
    }
    if(this->is_nan() || rhs.is_nan()) {
      return int_adapter<int_type>(not_a_number());
    }
    if((*this > 0 && rhs > 0) || (*this < min_value && rhs < min_value)) {
        return int_adapter<int_type>(pos_infinity());
    }
    if((*this > 0 && rhs < min_value) || (*this < min_value && rhs > 0)) {
        return int_adapter<int_type>(neg_infinity());
    }
    //implied -> if(this->value_ == 0 || rhs.value_ == 0)
    return int_adapter<int_type>(not_a_number());
  }
  /* Overloaded function necessary because of special
   * situation where int_adapter is instantiated with 
   * 'unsigned' and func is called with negative int.
   * It would produce incorrect results since 'unsigned'
   * wraps around when initialized with a negative value */
  //! Assumes 'this' is a special value
  int_adapter mult_div_specials(const int& rhs) const
  {
    int min_value; 
    // quiets compiler warnings
    bool is_signed = std::numeric_limits<int_type>::is_signed;
    if(is_signed) {
      min_value = 0;
    }
    else {
      min_value = 1;// there is no zero with unsigned
    }
    if(this->is_nan()) {
      return int_adapter<int_type>(not_a_number());
    }
    if((*this > 0 && rhs > 0) || (*this < min_value && rhs < 0)) {
        return int_adapter<int_type>(pos_infinity());
    }
    if((*this > 0 && rhs < 0) || (*this < min_value && rhs > 0)) {
        return int_adapter<int_type>(neg_infinity());
    }
    //implied -> if(this->value_ == 0 || rhs.value_ == 0)
    return int_adapter<int_type>(not_a_number());
  }
  
};

#ifndef BOOST_DATE_TIME_NO_LOCALE
  /*! Expected output is either a numeric representation 
   * or a special values representation.<BR> 
   * Ex. "12", "+infinity", "not-a-number", etc. */
  //template<class charT = char, class traits = std::traits<charT>, typename int_type>
  template<class charT, class traits, typename int_type>
  inline
  std::basic_ostream<charT, traits>& 
  operator<<(std::basic_ostream<charT, traits>& os, const int_adapter<int_type>& ia)
  {
    if(ia.is_special()) {
      // switch copied from date_names_put.hpp
      switch(ia.as_special())
        {
      case not_a_date_time:
        os << "not-a-number";
        break;
      case pos_infin:
        os << "+infinity";
        break;
      case neg_infin:
        os << "-infinity";
        break;
      default:
        os << "";
      }
    }
    else {
      os << ia.as_number(); 
    }
    return os;
  }
#endif


} } //namespace date_time



#endif

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
Chief Technology Officer
Australia Australia
Software craftsman | Author | Writing rapidfullstackdevelopment.com - Posting about how to survive and flourish as a software developer

Follow on Twitter for news and updates: https://twitter.com/codecapers

I'm writing a new book: Rapid Fullstack Development. Learn from my years of experience and become a better developer.

My second book, Bootstrapping Microservices, is a practical and project-based guide to building distributed applications with microservices.

My first book Data Wrangling with JavaScript is a comprehensive overview of working with data in JavaScript.

Data-Forge Notebook is my notebook-style application for data transformation, analysis and transformation in JavaScript.

I have a long history in software development with many years in apps, web apps, backends, serious games, simulations and VR. Making technology work for business is what I do: building bespoke software solutions that span multiple platforms.

I have years of experience managing development teams, preparing technical strategies and creation of software products. I can explain complicated technology to senior management. I have delivered cutting-edge products in fast-paced and high-pressure environments. I know how to focus and prioritize to get the important things done.

Author

- Rapid Fullstack Development
- Bootstrapping Microservices
- Data Wrangling with JavaScript

Creator of Market Wizard

- https://www.market-wizard.com.au/

Creator of Data-Forge and Data-Forge Notebook

- http://www.data-forge-js.com
- http://www.data-forge-notebook.com

Web

- www.codecapers.com.au

Open source

- https://github.com/ashleydavis
- https://github.com/data-forge
- https://github.com/data-forge-notebook


Skills

- Quickly building MVPs for startups
- Understanding how to get the most out of technology for business
- Developing technical strategies
- Management and coaching of teams & projects
- Microservices, devops, mobile and fullstack software development

Comments and Discussions