d3.scale.ordinal = function() {
  var domain = [],
      index = {},
      range = [],
      rangeBand = 0;

  function scale(x) {
    var i = x in index ? index[x] : (index[x] = domain.push(x) - 1);
    return range[i % range.length];
  }

  scale.domain = function(x) {
    if (!arguments.length) return domain;
    domain = x;
    index = {};
    var i = -1, j = -1, n = domain.length; while (++i < n) {
      x = domain[i];
      if (!(x in index)) index[x] = ++j;
    }
    return scale;
  };

  scale.range = function(x) {
    if (!arguments.length) return range;
    range = x;
    return scale;
  };

  scale.rangePoints = function(x, padding) {
    if (arguments.length < 2) padding = 0;
    var start = x[0],
        stop = x[1],
        step = (stop - start) / (domain.length - 1 + padding);
    range = domain.length == 1
        ? [(start + stop) / 2]
        : d3.range(start + step * padding / 2, stop + step / 2, step);
    rangeBand = 0;
    return scale;
  };

  scale.rangeBands = function(x, padding) {
    if (arguments.length < 2) padding = 0;
    var start = x[0],
        stop = x[1],
        step = (stop - start) / (domain.length + padding);
    range = d3.range(start + step * padding, stop, step);
    rangeBand = step * (1 - padding);
    return scale;
  };

  scale.rangeRoundBands = function(x, padding) {
    if (arguments.length < 2) padding = 0;
    var start = x[0],
        stop = x[1],
        diff = stop - start,
        step = Math.floor(diff / (domain.length + padding)),
        err = diff - (domain.length - padding) * step;
    range = d3.range(start + Math.round(err / 2), stop, step);
    rangeBand = Math.round(step * (1 - padding));
    return scale;
  };

  scale.rangeBand = function() {
    return rangeBand;
  };

  return scale;
};
