<commit_before>/*

    Copyright <NAME> and <NAME>, 2011, 2012
    
    This file is part of Lasercake.

    Lasercake is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Lasercake 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Lasercake.  If not, see <http://www.gnu.org/licenses/>.

*/

#ifndef LASERCAKE_UTILS_HPP__
#define LASERCAKE_UTILS_HPP__


#include <array>
#include <unordered_set>
#include <unordered_map>
#include <vector>
#include <memory>
#include <cmath>
#include <boost/functional/hash.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/taus88.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/random/random_number_generator.hpp>
#if defined(LASERCAKE_USE_GLIB)
#include <glib.h>
#endif

#include "config.hpp"
#include "data_structures/numbers.hpp"
#include "data_structures/bounds_checked_int.hpp"

template<typename Int> struct lasercake_int {
  typedef typename maybe_bounds_checked_int<Int>::type type;
};

template<typename Map>
typename Map::mapped_type* find_as_pointer(Map& m, typename Map::key_type const& k) {
  auto i = m.find(k);
  if(i == m.end()) return nullptr;
  else return &(i->second);
}

template<typename Map>
typename Map::mapped_type const* find_as_pointer(Map const& m, typename Map::key_type const& k) {
  auto i = m.find(k);
  if(i == m.end()) return nullptr;
  else return &(i->second);
}


// TODO think more about what RNGs go where, and so forth
// (e.g. for increased determinacy, maintained speed, and
// if networked then cryptographic-secureness could be nice too).
// The larger RNG here takes up a few kilobytes (RAM/cache) but produces nicer random numbers.
typedef boost::random::mt19937 large_fast_noncrypto_rng;
typedef boost::random::taus88 small_fast_noncrypto_rng;

template<typename RandomAccessRange, typename RNG> inline typename
RandomAccessRange::const_iterator random_element_of_sequence(RandomAccessRange const& c, RNG& rng) {
  caller_error_if(c.size() == 0, "random_element_of_sequence() on empty sequence");
  const boost::random::uniform_int_distribution<size_t> random_index(0, c.size()-1);
  return c.begin() + random_index(rng);
}
template<typename RandomAccessRange, typename RNG> inline typename
RandomAccessRange::iterator random_element_of_sequence(RandomAccessRange& c, RNG& rng) {
  caller_error_if(c.size() == 0, "random_element_of_sequence() on empty sequence");
  const boost::random::uniform_int_distribution<size_t> random_index(0, c.size()-1);
  return c.begin() + random_index(rng);
}

// If you need to pass around a dimension for use as an index to
// a vector3, you can optionally use these names.
enum {
  X = 0, Y = 1, Z = 2, num_dimensions = 3
};
typedef int which_dimension_type;

template<typename ScalarType> class vector3 {
public:
  ScalarType x, y, z;
  vector3():x(0),y(0),z(0){}
  vector3(ScalarType x, ScalarType y, ScalarType z):x(x),y(y),z(z){}
  template<typename OtherType> explicit vector3(vector3<OtherType> const& other):
    x(other.x),y(other.y),z(other.z){}

  // implicit conversions to/from array:
  BOOST_FORCEINLINE operator std::array<ScalarType, 3>()const {
    std::array<ScalarType, 3> result = {{ x, y, z }};
    return result;
  }
  BOOST_FORCEINLINE vector3(std::array<ScalarType, 3> const& arr)
    : x(arr[0]), y(arr[1]), z(arr[2]) {}
  
  BOOST_FORCEINLINE ScalarType& operator[](which_dimension_type index) {
    switch(index) {
      case 0: return x;
      case 1: return y;
      case 2: return z;
      default: caller_error("Trying to index a vector3 with an out-of-bounds index!");
    }
  }
  BOOST_FORCEINLINE ScalarType operator[](which_dimension_type index)const {
    switch(index) {
      case 0: return x;
      case 1: return y;
      case 2: return z;
      default: caller_error("Trying to index a vector3 with an out-of-bounds index!");
    }
  }
  BOOST_FORCEINLINE ScalarType operator()(which_dimension_type index)const { return (*this)[index]; }
  BOOST_FORCEINLINE void set(which_dimension_type index, ScalarType value) { (*this)[index] = value; }

  // Note: The operators are biased towards the type of the left operand (e.g. vector3<int> + vector3<int64_t> = vector3<int>)
  template<typename OtherType> vector3 operator+(vector3<OtherType> const& other)const {
    return vector3(x + other.x, y + other.y, z + other.z);
  }
  template<typename OtherType> vector3& operator+=(vector3<OtherType> const& other) {
    x += other.x; y += other.y; z += other.z; return *this;
  }
  template<typename OtherType> vector3 operator-(vector3<OtherType> const& other)const {
    return vector3(x - other.x, y - other.y, z - other.z);
  }
  template<typename OtherType> vector3& operator-=(vector3<OtherType> const& other) {
    x -= other.x; y -= other.y; z -= other.z; return *this;
  }
  vector3 operator*(ScalarType other)const {
    return vector3(x * other, y * other, z * other);
  }
  vector3& operator*=(ScalarType other) {
    x *= other; y *= other; z *= other; return *this;
  }
  vector3 operator/(ScalarType other)const {
    return vector3(divide_rounding_towards_zero(x, other), divide_rounding_towards_zero(y, other), divide_rounding_towards_zero(z, other));
  }
  vector3& operator/=(ScalarType other) {
    x = divide_rounding_towards_zero(x, other); y = divide_rounding_towards_zero(y, other); z = divide_rounding_towards_zero(z, other); return *this;
  }
  // Multiplying two vectors is usually a type-error mistake, so
  // you have to say you're doing it in words:
  template<typename OtherType> vector3 multiply_piecewise_by(vector3<OtherType> const& other)const {
    return vector3(x * other.x, y * other.y, z * other.z);
  }
  template<typename OtherType> vector3 divide_piecewise_by(vector3<OtherType> const& other)const {
    return vector3(x / other.x, y / other.y, z / other.z);
  }
  // Careful, shift operators on builtin types (ScalarType?) are only
  // defined for shift >= 0 && shift < bits_in_type
  vector3 operator<<(int shift)const {
    return vector3(x << shift, y << shift, z << shift);
  }
  vector3& operator<<=(int shift) {
    x <<= shift; y <<= shift; z <<= shift; return *this;
  }
  vector3 operator>>(int shift)const {
    return vector3(x >> shift, y >> shift, z >> shift);
  }
  vector3& operator>>=(int shift) {
    x >>= shift; y >>= shift; z >>= shift; return *this;
  }
  vector3 operator^(ScalarType other)const {
    return vector3(x ^ other, y ^ other, z ^ other);
  }
  vector3 operator|(ScalarType other)const {
    return vector3(x | other, y | other, z | other);
  }
  vector3 operator&(ScalarType other)const {
    return vector3(x & other, y & other, z & other);
  }
  vector3 operator~()const {<commit_msg>fix vector3 divide_piecewise_by to round towards zero<commit_after>/*

    Copyright <NAME> and <NAME>, 2011, 2012
    
    This file is part of Lasercake.

    Lasercake is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Lasercake 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Lasercake.  If not, see <http://www.gnu.org/licenses/>.

*/

#ifndef LASERCAKE_UTILS_HPP__
#define LASERCAKE_UTILS_HPP__


#include <array>
#include <unordered_set>
#include <unordered_map>
#include <vector>
#include <memory>
#include <cmath>
#include <boost/functional/hash.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/taus88.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/random/random_number_generator.hpp>
#if defined(LASERCAKE_USE_GLIB)
#include <glib.h>
#endif

#include "config.hpp"
#include "data_structures/numbers.hpp"
#include "data_structures/bounds_checked_int.hpp"

template<typename Int> struct lasercake_int {
  typedef typename maybe_bounds_checked_int<Int>::type type;
};

template<typename Map>
typename Map::mapped_type* find_as_pointer(Map& m, typename Map::key_type const& k) {
  auto i = m.find(k);
  if(i == m.end()) return nullptr;
  else return &(i->second);
}

template<typename Map>
typename Map::mapped_type const* find_as_pointer(Map const& m, typename Map::key_type const& k) {
  auto i = m.find(k);
  if(i == m.end()) return nullptr;
  else return &(i->second);
}


// TODO think more about what RNGs go where, and so forth
// (e.g. for increased determinacy, maintained speed, and
// if networked then cryptographic-secureness could be nice too).
// The larger RNG here takes up a few kilobytes (RAM/cache) but produces nicer random numbers.
typedef boost::random::mt19937 large_fast_noncrypto_rng;
typedef boost::random::taus88 small_fast_noncrypto_rng;

template<typename RandomAccessRange, typename RNG> inline typename
RandomAccessRange::const_iterator random_element_of_sequence(RandomAccessRange const& c, RNG& rng) {
  caller_error_if(c.size() == 0, "random_element_of_sequence() on empty sequence");
  const boost::random::uniform_int_distribution<size_t> random_index(0, c.size()-1);
  return c.begin() + random_index(rng);
}
template<typename RandomAccessRange, typename RNG> inline typename
RandomAccessRange::iterator random_element_of_sequence(RandomAccessRange& c, RNG& rng) {
  caller_error_if(c.size() == 0, "random_element_of_sequence() on empty sequence");
  const boost::random::uniform_int_distribution<size_t> random_index(0, c.size()-1);
  return c.begin() + random_index(rng);
}

// If you need to pass around a dimension for use as an index to
// a vector3, you can optionally use these names.
enum {
  X = 0, Y = 1, Z = 2, num_dimensions = 3
};
typedef int which_dimension_type;

template<typename ScalarType> class vector3 {
public:
  ScalarType x, y, z;
  vector3():x(0),y(0),z(0){}
  vector3(ScalarType x, ScalarType y, ScalarType z):x(x),y(y),z(z){}
  template<typename OtherType> explicit vector3(vector3<OtherType> const& other):
    x(other.x),y(other.y),z(other.z){}

  // implicit conversions to/from array:
  BOOST_FORCEINLINE operator std::array<ScalarType, 3>()const {
    std::array<ScalarType, 3> result = {{ x, y, z }};
    return result;
  }
  BOOST_FORCEINLINE vector3(std::array<ScalarType, 3> const& arr)
    : x(arr[0]), y(arr[1]), z(arr[2]) {}
  
  BOOST_FORCEINLINE ScalarType& operator[](which_dimension_type index) {
    switch(index) {
      case 0: return x;
      case 1: return y;
      case 2: return z;
      default: caller_error("Trying to index a vector3 with an out-of-bounds index!");
    }
  }
  BOOST_FORCEINLINE ScalarType operator[](which_dimension_type index)const {
    switch(index) {
      case 0: return x;
      case 1: return y;
      case 2: return z;
      default: caller_error("Trying to index a vector3 with an out-of-bounds index!");
    }
  }
  BOOST_FORCEINLINE ScalarType operator()(which_dimension_type index)const { return (*this)[index]; }
  BOOST_FORCEINLINE void set(which_dimension_type index, ScalarType value) { (*this)[index] = value; }

  // Note: The operators are biased towards the type of the left operand (e.g. vector3<int> + vector3<int64_t> = vector3<int>)
  template<typename OtherType> vector3 operator+(vector3<OtherType> const& other)const {
    return vector3(x + other.x, y + other.y, z + other.z);
  }
  template<typename OtherType> vector3& operator+=(vector3<OtherType> const& other) {
    x += other.x; y += other.y; z += other.z; return *this;
  }
  template<typename OtherType> vector3 operator-(vector3<OtherType> const& other)const {
    return vector3(x - other.x, y - other.y, z - other.z);
  }
  template<typename OtherType> vector3& operator-=(vector3<OtherType> const& other) {
    x -= other.x; y -= other.y; z -= other.z; return *this;
  }
  vector3 operator*(ScalarType other)const {
    return vector3(x * other, y * other, z * other);
  }
  vector3& operator*=(ScalarType other) {
    x *= other; y *= other; z *= other; return *this;
  }
  vector3 operator/(ScalarType other)const {
    return vector3(divide_rounding_towards_zero(x, other), divide_rounding_towards_zero(y, other), divide_rounding_towards_zero(z, other));
  }
  vector3& operator/=(ScalarType other) {
    x = divide_rounding_towards_zero(x, other); y = divide_rounding_towards_zero(y, other); z = divide_rounding_towards_zero(z, other); return *this;
  }
  // Multiplying two vectors is usually a type-error mistake, so
  // you have to say you're doing it in words:
  template<typename OtherType> vector3 multiply_piecewise_by(vector3<OtherType> const& other)const {
    return vector3(x * other.x, y * other.y, z * other.z);
  }
  template<typename OtherType> vector3 divide_piecewise_by(vector3<OtherType> const& other)const {
    return vector3(
      divide_rounding_towards_zero(x, other.x),
      divide_rounding_towards_zero(y, other.y),
      divide_rounding_towards_zero(z, other.z));
  }
  // Careful, shift operators on builtin types (ScalarType?) are only
  // defined for shift >= 0 && shift < bits_in_type
  vector3 operator<<(int shift)const {
    return vector3(x << shift, y << shift, z << shift);
  }
  vector3& operator<<=(int shift) {
    x <<= shift; y <<= shift; z <<= shift; return *this;
  }
  vector3 operator>>(int shift)const {
    return vector3(x >> shift, y >> shift, z >> shift);
  }
  vector3& operator>>=(int shift) {
    x >>= shift; y >>= shift; z >>= shift; return *this;
  }
  vector3 operator^(ScalarType other)const {
    return vector3(x ^ other, y ^ other, z ^ other);
  }
  vector3 operator|(ScalarType other)const {
    return vector3(x | other, y | other, z | other);
  }
  vector3 operator&(ScalarType other)const {
    return vector3(x & other, y & other, z & other);
  }
  vector3 operator~()const {
{'fraction_non_alphanumeric': 0.1217342968315731, 'fraction_numerical': 0.012993329627570873, 'mean_word_length': 4.419051204819277, 'pattern_counts': {'":': 0, '<': 125, '<?xml version=': 0, '>': 129, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3970896', 'n_tokens_mistral': 4870, 'n_tokens_neox': 4693, 'n_words': 1385}