function _rationalize (expr, scope = {}, detailed = false) {
    const setRules = rulesRationalize() // Rules for change polynomial in near canonical form
    const polyRet = polynomial(expr, scope, true, setRules.firstRules) // Check if expression is a rationalizable polynomial
    const nVars = polyRet.variables.length
    const noExactFractions = { exactFractions: false }
    const withExactFractions = { exactFractions: true }
    expr = polyRet.expression

    if (nVars >= 1) { // If expression in not a constant
      expr = expandPower(expr) // First expand power of polynomials (cannot be made from rules!)
      let sBefore // Previous expression
      let rules
      let eDistrDiv = true
      let redoInic = false
      // Apply the initial rules, including succ div rules:
      expr = simplify(expr, setRules.firstRules, {}, noExactFractions)
      let s
      while (true) {
        // Alternate applying successive division rules and distr.div.rules
        // until there are no more changes:
        rules = eDistrDiv ? setRules.distrDivRules : setRules.sucDivRules
        expr = simplify(expr, rules, {}, withExactFractions)
        eDistrDiv = !eDistrDiv // Swap between Distr.Div and Succ. Div. Rules

        s = expr.toString()
        if (s === sBefore) {
          break // No changes : end of the loop
        }

        redoInic = true
        sBefore = s
      }

      if (redoInic) { // Apply first rules again without succ div rules (if there are changes)
        expr = simplify(expr, setRules.firstRulesAgain, {}, noExactFractions)
      }
      // Apply final rules:
      expr = simplify(expr, setRules.finalRules, {}, noExactFractions)
    } // NVars >= 1

    const coefficients = []
    const retRationalize = {}

    if (expr.type === 'OperatorNode' && expr.isBinary() && expr.op === '/') { // Separate numerator from denominator
      if (nVars === 1) {
        expr.args[0] = polyToCanonical(expr.args[0], coefficients)
        expr.args[1] = polyToCanonical(expr.args[1])
      }
      if (detailed) {
        retRationalize.numerator = expr.args[0]
        retRationalize.denominator = expr.args[1]
      }
    } else {
      if (nVars === 1) {
        expr = polyToCanonical(expr, coefficients)
      }
      if (detailed) {
        retRationalize.numerator = expr
        retRationalize.denominator = null
      }
    }
    // nVars

    if (!detailed) return expr
    retRationalize.coefficients = coefficients
    retRationalize.variables = polyRet.variables
    retRationalize.expression = expr
    return retRationalize
  }
Transform a rationalizable expression in a rational fraction.
If rational fraction is one variable polynomial then converts
the numerator and denominator in canonical form, with decreasing
exponents, returning the coefficients of numerator.

Syntax:

    math.rationalize(expr)
    math.rationalize(expr, detailed)
    math.rationalize(expr, scope)
    math.rationalize(expr, scope, detailed)

Examples:

    math.rationalize('sin(x)+y')
                  //  Error: There is an unsolved function call
    math.rationalize('2x/y - y/(x+1)')
                  // (2*x^2-y^2+2*x)/(x*y+y)
    math.rationalize('(2x+1)^6')
                  // 64*x^6+192*x^5+240*x^4+160*x^3+60*x^2+12*x+1
    math.rationalize('2x/( (2x-1) / (3x+2) ) - 5x/ ( (3x+4) / (2x^2-5) ) + 3')
                  // -20*x^4+28*x^3+104*x^2+6*x-12)/(6*x^2+5*x-4)
    math.rationalize('x/(1-x)/(x-2)/(x-3)/(x-4) + 2x/ ( (1-2x)/(2-3x) )/ ((3-4x)/(4-5x) )') =
                  // (-30*x^7+344*x^6-1506*x^5+3200*x^4-3472*x^3+1846*x^2-381*x)/
                  //     (-8*x^6+90*x^5-383*x^4+780*x^3-797*x^2+390*x-72)

    math.rationalize('x+x+x+y',{y:1}) // 3*x+1
    math.rationalize('x+x+x+y',{})    // 3*x+y

    const ret = math.rationalize('x+x+x+y',{},true)
                  // ret.expression=3*x+y, ret.variables = ["x","y"]
    const ret = math.rationalize('-2+5x^2',{},true)
                  // ret.expression=5*x^2-2, ret.variables = ["x"], ret.coefficients=[-2,0,5]

See also:

    simplify

@param  {Node|string} expr    The expression to check if is a polynomial expression
@param  {Object|boolean}      optional scope of expression or true for already evaluated rational expression at input
@param  {Boolean}  detailed   optional True if return an object, false if return expression node (default)

@return {Object | Node}    The rational polynomial of `expr` or an object
           `{expression, numerator, denominator, variables, coefficients}`, where
             `expression` is a `Node` with the node simplified expression,
             `numerator` is a `Node` with the simplified numerator of expression,
             `denominator` is a `Node` or `boolean` with the simplified denominator or `false` (if there is no denominator),
             `variables` is an array with variable names,
             and `coefficients` is an array with coefficients of numerator sorted by increased exponent
          {Expression Node}  node simplified expression