<commit_before>'use strict'

// TODO this could be improved by simplifying seperated constants under associative and commutative operators
function factory (type, config, load, typed, math) {
  const util = load(require('./util'))
  const isCommutative = util.isCommutative
  const isAssociative = util.isAssociative
  const allChildren = util.allChildren
  const createMakeNodeFunction = util.createMakeNodeFunction
  const ConstantNode = math.expression.node.ConstantNode
  const OperatorNode = math.expression.node.OperatorNode
  const FunctionNode = math.expression.node.FunctionNode

  function simplifyConstant (expr, options) {
    const res = foldFraction(expr, options)
    return type.isNode(res) ? res : _toNode(res)
  }

  function _eval (fnname, args, options) {
    try {
      return _toNumber(math[fnname].apply(null, args), options)
    } catch (ignore) {
      // sometimes the implicit type conversion causes the evaluation to fail, so we'll try again after removing Fractions
      args = args.map(function (x) {
        if (type.isFraction(x)) {
          return x.valueOf()
        }
        return x
      })
      return _toNumber(math[fnname].apply(null, args), options)
    }
  }

  const _toNode = typed({
    'Fraction': _fractionToNode,
    'number': function (n) {
      if (n < 0) {
        return unaryMinusNode(new ConstantNode(-n))
      }
      return new ConstantNode(n)
    },
    'BigNumber': function (n) {
      if (n < 0) {
        return unaryMinusNode(new ConstantNode(-n))
      }
      return new ConstantNode(n) // old parameters: (n.toString(), 'number')
    },
    'Complex': function (s) {
      throw new Error('Cannot convert Complex number to Node')
    }
  })

  // convert a number to a fraction only if it can be expressed exactly
  function _exactFraction (n, options) {
    const exactFractions = (options && options.exactFractions !== false)
    if (exactFractions && isFinite(n)) {
      const f = math.fraction(n)
      if (f.valueOf() === n) {
        return f
      }
    }
    return n
  }

  // Convert numbers to a preferred number type in preference order: Fraction, number, Complex
  // BigNumbers are left alone
  const _toNumber = typed({
    'string, Object': function (s, options) {
      if (config.number === 'BigNumber') {
        return math.bignumber(s)
      } else if (config.number === 'Fraction') {
        return math.fraction(s)
      } else {
        const n = parseFloat(s)
        return _exactFraction(n, options)
      }
    },

    'Fraction, Object': function (s, options) { return s }, // we don't need options here

    'BigNumber, Object': function (s, options) { return s },// we don't need options here

    'number, Object': function (s, options) {
      return _exactFraction(s, options)
    },
<commit_msg>Refactored `globalOptions` into passing argument `options` everywhere (see #1173)<commit_after>'use strict'

// TODO this could be improved by simplifying seperated constants under associative and commutative operators
function factory (type, config, load, typed, math) {
  const util = load(require('./util'))
  const isCommutative = util.isCommutative
  const isAssociative = util.isAssociative
  const allChildren = util.allChildren
  const createMakeNodeFunction = util.createMakeNodeFunction
  const ConstantNode = math.expression.node.ConstantNode
  const OperatorNode = math.expression.node.OperatorNode
  const FunctionNode = math.expression.node.FunctionNode

  function simplifyConstant (expr, options) {
    const res = foldFraction(expr, options)
    return type.isNode(res) ? res : _toNode(res)
  }

  function _eval (fnname, args, options) {
    try {
      return _toNumber(math[fnname].apply(null, args), options)
    } catch (ignore) {
      // sometimes the implicit type conversion causes the evaluation to fail, so we'll try again after removing Fractions
      args = args.map(function (x) {
        if (type.isFraction(x)) {
          return x.valueOf()
        }
        return x
      })
      return _toNumber(math[fnname].apply(null, args), options)
    }
  }

  const _toNode = typed({
    'Fraction': _fractionToNode,
    'number': function (n) {
      if (n < 0) {
        return unaryMinusNode(new ConstantNode(-n))
      }
      return new ConstantNode(n)
    },
    'BigNumber': function (n) {
      if (n < 0) {
        return unaryMinusNode(new ConstantNode(-n))
      }
      return new ConstantNode(n) // old parameters: (n.toString(), 'number')
    },
    'Complex': function (s) {
      throw new Error('Cannot convert Complex number to Node')
    }
  })

  // convert a number to a fraction only if it can be expressed exactly
  function _exactFraction (n, options) {
    const exactFractions = (options && options.exactFractions !== false)
    if (exactFractions && isFinite(n)) {
      const f = math.fraction(n)
      if (f.valueOf() === n) {
        return f
      }
    }
    return n
  }

  // Convert numbers to a preferred number type in preference order: Fraction, number, Complex
  // BigNumbers are left alone
  const _toNumber = typed({
    'string, Object': function (s, options) {
      if (config.number === 'BigNumber') {
        return math.bignumber(s)
      } else if (config.number === 'Fraction') {
        return math.fraction(s)
      } else {
        const n = parseFloat(s)
        return _exactFraction(n, options)
      }
    },

    'Fraction, Object': function (s, options) { return s }, // we don't need options here

    'BigNumber, Object': function (s, options) { return s }, // we don't need options here

    'number, Object': function (s, options) {
      return _exactFraction(s, options)
    },

{'fraction_non_alphanumeric': 0.11154185022026432, 'fraction_numerical': 0.0014096916299559472, 'mean_word_length': 2.8876712328767122, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 3, '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': '2973806', 'n_tokens_mistral': 1694, 'n_tokens_neox': 1634, 'n_words': 518}