function Range (start, end, step) {
    if (!(this instanceof Range)) {
      throw new SyntaxError('Constructor must be called with the new operator')
    }

    const hasStart = start !== null && start !== undefined
    const hasEnd = end !== null && end !== undefined
    const hasStep = step !== null && step !== undefined

    if (hasStart) {
      if (isBigNumber(start)) {
        start = start.toNumber()
      } else if (typeof start !== 'number' && !isBigInt(start)) {
        throw new TypeError('Parameter start must be a number or bigint')
      }
    }
    if (hasEnd) {
      if (isBigNumber(end)) {
        end = end.toNumber()
      } else if (typeof end !== 'number' && !isBigInt(end)) {
        throw new TypeError('Parameter end must be a number or bigint')
      }
    }
    if (hasStep) {
      if (isBigNumber(step)) {
        step = step.toNumber()
      } else if (typeof step !== 'number' && !isBigInt(step)) {
        throw new TypeError('Parameter step must be a number or bigint')
      }
    }

    this.start = hasStart ? parseFloat(start) : 0
    this.end = hasEnd ? parseFloat(end) : 0
    this.step = hasStep ? parseFloat(step) : 1
  }
Create a range of numbers. A range has a start, step, and end,
and contains functions to iterate over the range.

A range can be constructed as:

    const range = new Range(start, end)
    const range = new Range(start, end, step)

Note that the endpoints and step may be specified with other numeric
types such as bigint or BigNumber, but they will be demoted to the
built-in `number` type and the Range will only contain numbers. The
rationale for this demotion is that Range objects are primarily used
for indexing Matrix objects, and Matrix objects may only be indexed
with `number`s.

To get the result of the range:
    range.forEach(function (x) {
        console.log(x)
    })
    range.map(function (x) {
        return math.sin(x)
    })
    range.toArray()

Example usage:

    const c = new Range(2, 6)       // 2:1:5
    c.toArray()                     // [2, 3, 4, 5]
    const d = new Range(2, -3, -1)  // 2:-1:-2
    d.toArray()                     // [2, 1, 0, -1, -2]

@class Range
@constructor Range
@param {number} start  included lower bound
@param {number} end    excluded upper bound
@param {number} [step] step size, default value is 1