<commit_before>using System;
using OpenTK;

namespace Bearded.Utilities.Math
{
    /// <summary>
    /// A typesafe representation of a direction in two dimensional space.
    /// </summary>
    public struct Direction2 : IEquatable<Direction2>
    {
        const float fromRadians = uint.MaxValue / GameMath.TwoPi;
        const float toRadians = GameMath.TwoPi / ushort.MaxValue;

        const float fromDegrees = uint.MaxValue / 360f;
        const float toDegrees = 360f / uint.MaxValue;

        private readonly uint data;

        #region Constructing

        private Direction2(uint data)
        {
            this.data = data;
        }

        /// <summary>
        /// Initialises a direction from an absolute angle value in radians.
        /// </summary>
        public static Direction2 FromRadians(float radians)
        {
            return new Direction2((uint)(radians * Direction2.fromRadians));
        }

        /// <summary>
        /// Initialises a direction from an absolute angle value in degrees.
        /// </summary>
        public static Direction2 FromDegrees(float degrees)
        {
            return new Direction2((uint)(degrees * Direction2.fromDegrees));
        }

        /// <summary>
        /// Initialises a direction along a vector.
        /// </summary>
        public static Direction2 Of(Vector2 vector)
        {
            return Direction2.FromRadians(GameMath.Atan2(vector.Y, vector.X));
        }

        /// <summary>
        /// Initialises the direction between two points.
        /// </summary>
        /// <param name="from">The base point.</param>
        /// <param name="to">The point the directions "points" towards.</param>
        public static Direction2 Between(Vector2 from, Vector2 to)
        {
            return Direction2.Of(to - from);
        }

        #endregion


        #region Static Fields

        /// <summary>
        /// Default base direction (along positive X axis).
        /// </summary>
        public static readonly Direction2 Zero = new Direction2(0);

        #endregion


        #region Properties

        /// <summary>
        /// Gets the absolute angle of the direction in radians between 0 and 2pi.
        /// </summary>
        public float Radians { get { return this.data * Direction2.toRadians; } }

        /// <summary>
        /// Gets the absolute angle of the direction in degrees between 0 and 360.
        /// </summary>
        public float Degrees { get { return this.data * Direction2.toDegrees; } }

        /// <summary>
        /// Gets the absolute angle of the direction in radians between -pi and pi.
        /// </summary>
        public float RadiansSigned { get { return ((int)this.data) * Direction2.toRadians; } }

        /// <summary>
        /// Gets the absolute angle of the direction in degrees between -180 and 180.
        /// </summary>
        public float DegreesSigned { get { return ((int)this.data) * Direction2.toDegrees; } }

        /// <summary>
        /// Gets the unit vector pointing in this direction.
        /// </summary>
        public Vector2 Vector
        {
            get
            {
                var radians = this.Radians;
                return new Vector2(GameMath.Cos(radians), GameMath.Sin(radians));
            }
        }

        #endregion


        #region Methods

        /// <summary>
        /// Returns this direction turnen towards a goal direction with a given maximum step length in radians.
        /// This will never overshoot the goal.
        /// </summary>
        /// <param name="goal">The goal direction.</param>
        /// <param name="maxStepInRadians">The maximum step length in radians. Negative values will return the original direction.</param>
        public Direction2 TurnedTowards(Direction2 goal, float maxStepInRadians)
        {
            if (maxStepInRadians <= 0)
                return this;

            var step = maxStepInRadians.Radians();

            var thisToGoal = goal - this;

            if (step > thisToGoal.Abs())
                return goal;
            
            step *= thisToGoal.Sign();

            return this + step;
        }

        #region Statics

        /// <summary>
        /// Linearly interpolates between two directions.
        /// This always interpolates along the shorter arc.
        /// </summary>
        /// <param name="d0">The first direction (at p == 0).</param>
        /// <param name="d1">The second direction (at p == 1).</param>
        /// <param name="p">The parameter.</param>
        public static Direction2 Lerp(Direction2 d0, Direction2 d1, float p)
        {
            return d0 + p * (d1 - d0);
        }

        #endregion

        #endregion


        #region Operators

        #region Arithmetic

        /// <summary>
        /// Adds an angle to a direction.
        /// </summary>
        public static Direction2 operator +(Direction2 direction, Angle angle)
        {
            return new Direction2((uint)(direction.data + angle.Radians * fromRadians));
        }

        /// <summary>
        /// Substracts an angle from a direction.
        /// </summary>
        public static Direction2 operator -(Direction2 direction, Angle angle)
        {
            return new Direction2((uint)(direction.data - angle.Radians * fromRadians));
        }

        /// <summary>
        /// Gets the signed difference between two directions.
        /// Always returns the angle of the shorter arc.
        /// </summary>
        public static Angle operator -(Direction2 direction1, Direction2 direction2)
        {
            return Angle.FromRadians((direction1.data - direction2.data) * toRadians);
        }

        /// <summary>
        /// Gets the inverse direction to a direction.
        /// </summary>
        public static Direction2 operator -(Direction2 direction)
        {
            return new Direction2(direction.data + uint.MaxValue / 2);
        }

        #endregion

        #region Boolean

        /// <summary>
        /// Indicates whether the current object is equal to another object of the same type.
        /// </summary>
        /// <param name="other">An object to compare with this object.</param>
        /// <returns>
        /// true if the current object is equal to the <paramref name="other" /> parameter; otherwise, false.
        /// </returns>
        public bool Equals(Direction2 other)
        {
            return this.data == other.data;
        }

        /// <summary>
        /// Determines whether the specified <see cref="System.Object" />, is equal to this instance.
        /// </summary>
        /// <param name="obj">The <see cref="System.Object" /> to compare with this instance.</param>
        /// <returns>
        ///   <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.<commit_msg>fixed direction2 operator-(direction2), resolving #24<commit_after>using System;
using OpenTK;

namespace Bearded.Utilities.Math
{
    /// <summary>
    /// A typesafe representation of a direction in two dimensional space.
    /// </summary>
    public struct Direction2 : IEquatable<Direction2>
    {
        const float fromRadians = uint.MaxValue / GameMath.TwoPi;
        const float toRadians = GameMath.TwoPi / ushort.MaxValue;

        const float fromDegrees = uint.MaxValue / 360f;
        const float toDegrees = 360f / uint.MaxValue;

        private readonly uint data;

        #region Constructing

        private Direction2(uint data)
        {
            this.data = data;
        }

        /// <summary>
        /// Initialises a direction from an absolute angle value in radians.
        /// </summary>
        public static Direction2 FromRadians(float radians)
        {
            return new Direction2((uint)(radians * Direction2.fromRadians));
        }

        /// <summary>
        /// Initialises a direction from an absolute angle value in degrees.
        /// </summary>
        public static Direction2 FromDegrees(float degrees)
        {
            return new Direction2((uint)(degrees * Direction2.fromDegrees));
        }

        /// <summary>
        /// Initialises a direction along a vector.
        /// </summary>
        public static Direction2 Of(Vector2 vector)
        {
            return Direction2.FromRadians(GameMath.Atan2(vector.Y, vector.X));
        }

        /// <summary>
        /// Initialises the direction between two points.
        /// </summary>
        /// <param name="from">The base point.</param>
        /// <param name="to">The point the directions "points" towards.</param>
        public static Direction2 Between(Vector2 from, Vector2 to)
        {
            return Direction2.Of(to - from);
        }

        #endregion


        #region Static Fields

        /// <summary>
        /// Default base direction (along positive X axis).
        /// </summary>
        public static readonly Direction2 Zero = new Direction2(0);

        #endregion


        #region Properties

        /// <summary>
        /// Gets the absolute angle of the direction in radians between 0 and 2pi.
        /// </summary>
        public float Radians { get { return this.data * Direction2.toRadians; } }

        /// <summary>
        /// Gets the absolute angle of the direction in degrees between 0 and 360.
        /// </summary>
        public float Degrees { get { return this.data * Direction2.toDegrees; } }

        /// <summary>
        /// Gets the absolute angle of the direction in radians between -pi and pi.
        /// </summary>
        public float RadiansSigned { get { return ((int)this.data) * Direction2.toRadians; } }

        /// <summary>
        /// Gets the absolute angle of the direction in degrees between -180 and 180.
        /// </summary>
        public float DegreesSigned { get { return ((int)this.data) * Direction2.toDegrees; } }

        /// <summary>
        /// Gets the unit vector pointing in this direction.
        /// </summary>
        public Vector2 Vector
        {
            get
            {
                var radians = this.Radians;
                return new Vector2(GameMath.Cos(radians), GameMath.Sin(radians));
            }
        }

        #endregion


        #region Methods

        /// <summary>
        /// Returns this direction turnen towards a goal direction with a given maximum step length in radians.
        /// This will never overshoot the goal.
        /// </summary>
        /// <param name="goal">The goal direction.</param>
        /// <param name="maxStepInRadians">The maximum step length in radians. Negative values will return the original direction.</param>
        public Direction2 TurnedTowards(Direction2 goal, float maxStepInRadians)
        {
            if (maxStepInRadians <= 0)
                return this;

            var step = maxStepInRadians.Radians();

            var thisToGoal = goal - this;

            if (step > thisToGoal.Abs())
                return goal;
            
            step *= thisToGoal.Sign();

            return this + step;
        }

        #region Statics

        /// <summary>
        /// Linearly interpolates between two directions.
        /// This always interpolates along the shorter arc.
        /// </summary>
        /// <param name="d0">The first direction (at p == 0).</param>
        /// <param name="d1">The second direction (at p == 1).</param>
        /// <param name="p">The parameter.</param>
        public static Direction2 Lerp(Direction2 d0, Direction2 d1, float p)
        {
            return d0 + p * (d1 - d0);
        }

        #endregion

        #endregion


        #region Operators

        #region Arithmetic

        /// <summary>
        /// Adds an angle to a direction.
        /// </summary>
        public static Direction2 operator +(Direction2 direction, Angle angle)
        {
            return new Direction2((uint)(direction.data + angle.Radians * fromRadians));
        }

        /// <summary>
        /// Substracts an angle from a direction.
        /// </summary>
        public static Direction2 operator -(Direction2 direction, Angle angle)
        {
            return new Direction2((uint)(direction.data - angle.Radians * fromRadians));
        }

        /// <summary>
        /// Gets the signed difference between two directions.
        /// Always returns the angle of the shorter arc.
        /// </summary>
        public static Angle operator -(Direction2 direction1, Direction2 direction2)
        {
            return Angle.FromRadians((direction1.data - direction2.data) * toRadians);
        }

        /// <summary>
        /// Gets the inverse direction to a direction.
        /// </summary>
        public static Direction2 operator -(Direction2 direction)
        {
            return new Direction2(direction.data + (uint.MaxValue / 2 + 1));
        }

        #endregion

        #region Boolean

        /// <summary>
        /// Indicates whether the current object is equal to another object of the same type.
        /// </summary>
        /// <param name="other">An object to compare with this object.</param>
        /// <returns>
        /// true if the current object is equal to the <paramref name="other" /> parameter; otherwise, false.
        /// </returns>
        public bool Equals(Direction2 other)
        {
            return this.data == other.data;
        }

        /// <summary>
        /// Determines whether the specified <see cref="System.Object" />, is equal to this instance.
        /// </summary>
        /// <param name="obj">The <see cref="System.Object" /> to compare with this instance.</param>
        /// <returns>
        ///   <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.
{'fraction_non_alphanumeric': 0.1110790119890221, 'fraction_numerical': 0.011339014877943088, 'mean_word_length': 1.7182960345504514, 'pattern_counts': {'":': 0, '<': 141, '<?xml version=': 0, '>': 141, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '733908', 'n_tokens_mistral': 3685, 'n_tokens_neox': 3509, 'n_words': 1154}