class Sass::Value::Number

def coerce_or_convert_value(new_numerator_units, new_denominator_units,

def coerce_or_convert_value(new_numerator_units, new_denominator_units,
                            coerce_unitless:,
                            name: nil,
                            other: nil,
                            other_name: nil)
  if other && (other.numerator_units != new_denominator_units && other.denominator_units != new_denominator_units)
    raise Sass::ScriptError, "Expect #{other} to have units #{unit_string(new_numerator_units,
                                                                          new_denominator_units).inspect}"
  end
  return value if numerator_units == new_numerator_units && denominator_units == new_denominator_units
  return value if numerator_units == new_numerator_units && denominator_units == new_denominator_units
  other_unitless = new_numerator_units.empty? && new_denominator_units.empty?
  return value if coerce_unitless && (unitless? || other_unitless)
  compatibility_error = lambda {
    unless other.nil?
      message = "#{self} and"
      message << " $#{other_name}:" unless other_name.nil?
      message << " #{other} have incompatible units"
      message << " (one has units and the other doesn't)" if unitless? || other_unitless
      return Sass::ScriptError.new(message, name)
    end
    return Sass::ScriptError.new("Expected #{self} to have no units", name) unless other_unitless
    if new_numerator_units.length == 1 && new_denominator_units.empty?
      type = Unit::TYPES_BY_UNIT[new_numerator_units.first]
      return Sass::ScriptError.new(
        "Expected #{self} to have a #{type} unit (#{Unit::UNITS_BY_TYPE[type].join(', ')})", name
      )
    end
    unit_length = new_numerator_units.length + new_denominator_units.length
    units = unit_string(new_numerator_units, new_denominator_units)
    Sass::ScriptError.new("Expected #{self} to have unit#{unit_length > 1 ? 's' : ''} #{units}", name)
  }
  result = value
  old_numerator_units = numerator_units.dup
  new_numerator_units.each do |new_numerator_unit|
    index = old_numerator_units.find_index do |old_numerator_unit|
      factor = Unit.conversion_factor(new_numerator_unit, old_numerator_unit)
      if factor.nil?
        false
      else
        result *= factor
        true
      end
    end
    raise compatibility_error.call if index.nil?
    old_numerator_units.delete_at(index)
  end
  old_denominator_units = denominator_units.dup
  new_denominator_units.each do |new_denominator_unit|
    index = old_denominator_units.find_index do |old_denominator_unit|
      factor = Unit.conversion_factor(new_denominator_unit, old_denominator_unit)
      if factor.nil?
        false
      else
        result /= factor
        true
      end
    end
    raise compatibility_error.call if index.nil?
    old_denominator_units.delete_at(index)
  end
  raise compatibility_error.call unless old_numerator_units.empty? && old_denominator_units.empty?
  result
end