<commit_before>require 'flt/dec_num'

module Flt

  # Trigonometry functions. The angular units used by these functions can be specified
  # with the +angle+ attribute of the context. The accepted values are:
  # * :rad for radians
  # * :deg for degrees
  # * :grad for gradians
  #
  # These functions are injected in Context objects.
  module Trigonometry

    # Cosine of an angle given in the units specified by the context +angle+ attribute.
    def cos(x)
      cos_base(num_class[x])
    end

    # Sine of an angle given in the units specified by the context +angle+ attribute.
    def sin(x)
      sin_base(num_class[x])
    end

    # Tangent of an angle given in the units specified by the context +angle+ attribute.
    def tan(x)
      tan_base(num_class[x])
    end

    # Arc-tangent. The result is in the units specified by the context +angle+ attribute.
    # If the angular units are radians the result is in [-pi/2, pi/2]; it is in [-90,90] in degrees.
    def atan(x)
      atan_base(num_class[x])
    end

    # Arc-tangent with two arguments (principal value of the argument of the complex number x+i*y).
    # The result is in the units specified by the context +angle+ attribute.
    # If the angular units are radians the result is in [-pi, pi]; it is in [-180,180] in degrees.
    def atan2(y, x)
      atan2_base(num_class[y], num_class[x])
    end

    # Arc-sine. The result is in the units specified by the context +angle+ attribute.
    # If the angular units are radians the result is in [-pi/2, pi/2]; it is in [-90,90] in degrees.
    def asin(x)
      asin_base(num_class[x])
    end

    # Arc-cosine. The result is in the units specified by the context +angle+ attribute.
    # If the angular units are radians the result is in [-pi/2, pi/2]; it is in [-90,90] in degrees.
    def acos(x)
      acos_base(num_class[x])
    end

    # Length of the hypotenuse of a right-angle triangle (modulus or absolute value of the complex x+i*y).
    def hypot(x, y)
      hypot_base(num_class[x], num_class[y])
    end

    # Pi
    def pi(round_digits=nil)
      unless defined?(@pi_cache)
        @pi_value = nil
        @pi_digits = 0
      end
      round_digits ||= self.precision
      if @pi_digits < round_digits
        # provisional implementation (very slow)
        lasts = 0
        t, s, n, na, d, da = [num_class[3], 3, 1, 0, 0, 24]
        num_class.context(self) do |local_context|
          local_context.precision = round_digits + 6
          while s != lasts
            lasts = s
            n, na = n+na, na+8
            d, da = d+da, da+32
            t = (t * n) / d
            s += t
          end
        end
        @pi_value = s
        @pi_digits = round_digits
      end
      num_class.context(self, :precision=>round_digits){+@pi_value}
    end

    def e(digits=nil)
      num_class.context(self) do |local_context|
        local_context.precision = digits if digits
        num_class.Num(1).exp
      end
    end

    def half
      num_class['0.5']
    end

    protected

    def cos_base(x)
      x = x.copy_sign(+1) # note that abs rounds; copy_sign does not.
      rev_sign = false
      s = nil
      num_class.context(self) do |local_context|
        local_context.precision += 3 # extra digits for intermediate steps
        x,k,pi_2 = local_context.reduce_angle2(x,2)<commit_msg>The generic pi cache wasn't being used (for double reason: it was reset for each call and caching was done in the Context object which could change too often).<commit_after>require 'flt/dec_num'

module Flt

  # Trigonometry functions. The angular units used by these functions can be specified
  # with the +angle+ attribute of the context. The accepted values are:
  # * :rad for radians
  # * :deg for degrees
  # * :grad for gradians
  #
  # These functions are injected in Context objects.
  module Trigonometry

    # Cosine of an angle given in the units specified by the context +angle+ attribute.
    def cos(x)
      cos_base(num_class[x])
    end

    # Sine of an angle given in the units specified by the context +angle+ attribute.
    def sin(x)
      sin_base(num_class[x])
    end

    # Tangent of an angle given in the units specified by the context +angle+ attribute.
    def tan(x)
      tan_base(num_class[x])
    end

    # Arc-tangent. The result is in the units specified by the context +angle+ attribute.
    # If the angular units are radians the result is in [-pi/2, pi/2]; it is in [-90,90] in degrees.
    def atan(x)
      atan_base(num_class[x])
    end

    # Arc-tangent with two arguments (principal value of the argument of the complex number x+i*y).
    # The result is in the units specified by the context +angle+ attribute.
    # If the angular units are radians the result is in [-pi, pi]; it is in [-180,180] in degrees.
    def atan2(y, x)
      atan2_base(num_class[y], num_class[x])
    end

    # Arc-sine. The result is in the units specified by the context +angle+ attribute.
    # If the angular units are radians the result is in [-pi/2, pi/2]; it is in [-90,90] in degrees.
    def asin(x)
      asin_base(num_class[x])
    end

    # Arc-cosine. The result is in the units specified by the context +angle+ attribute.
    # If the angular units are radians the result is in [-pi/2, pi/2]; it is in [-90,90] in degrees.
    def acos(x)
      acos_base(num_class[x])
    end

    # Length of the hypotenuse of a right-angle triangle (modulus or absolute value of the complex x+i*y).
    def hypot(x, y)
      hypot_base(num_class[x], num_class[y])
    end

    # Pi
    def pi(round_digits=nil)
      round_digits ||= self.precision
      if Trigonometry.pi_digits < round_digits
        # provisional implementation (very slow)
        lasts = 0
        t, s, n, na, d, da = [num_class[3], 3, 1, 0, 0, 24]
        num_class.context(self) do |local_context|
          local_context.precision = round_digits + 6
          while s != lasts
            lasts = s
            n, na = n+na, na+8
            d, da = d+da, da+32
            t = (t * n) / d
            s += t
          end
        end
        Trigonometry.pi_value = s
        Trigonometry.pi_digits = round_digits
      end
      num_class.context(self, :precision=>round_digits){+Trigonometry.pi_value}
    end

    def e(digits=nil)
      num_class.context(self) do |local_context|
        local_context.precision = digits if digits
        num_class.Num(1).exp
      end
    end

    def half
      num_class['0.5']
    end

    protected

    @pi_value = nil
    @pi_digits = 0
    class <<self
      attr_accessor :pi_value, :pi_digits
    end

    def cos_base(x)
      x = x.copy_sign(+1) # note that abs rounds; copy_sign does not.
      rev_sign = false
      s = nil
      num_class.context(self) do |local_context|
        local_context.precision += 3 # extra digits for intermediate steps
        x,k,pi_2 = local_context.reduce_angle2(x,2)
{'fraction_non_alphanumeric': 0.08939678865904817, 'fraction_numerical': 0.013597569796036452, 'mean_word_length': 2.4193867457962415, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, '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': '1645391', 'n_tokens_mistral': 2323, 'n_tokens_neox': 2204, 'n_words': 806}