text:   var Dictionary = (function () {
  
      var primes = [1, 3, 7, 13, 31, 61, 127, 251, 509, 1021, 2039, 4093, 8191, 16381, 32749, 65521, 131071, 262139, 524287, 1048573, 2097143, 4194301, 8388593, 16777213, 33554393, 67108859, 134217689, 268435399, 536870909, 1073741789, 2147483647],
        noSuchkey = "no such key",
        duplicatekey = "duplicate key";
  
      function isPrime(candidate) {
        if ((candidate & 1) === 0) { return candidate === 2; }
        var num1 = Math.sqrt(candidate),
          num2 = 3;
        while (num2 <= num1) {
          if (candidate % num2 === 0) { return false; }
          num2 += 2;
        }
        return true;
      }
  
      function getPrime(min) {
        var index, num, candidate;
        for (index = 0; index < primes.length; ++index) {
          num = primes[index];
          if (num >= min) { return num; }
        }
        candidate = min | 1;
        while (candidate < primes[primes.length - 1]) {
          if (isPrime(candidate)) { return candidate; }
          candidate += 2;
        }
        return min;
      }
  
      function stringHashFn(str) {
        var hash = 757602046;
        if (!str.length) { return hash; }
        for (var i = 0, len = str.length; i < len; i++) {
          var character = str.charCodeAt(i);
          hash = ((hash << 5) - hash) + character;
          hash = hash & hash;
        }
        return hash;
      }
  
      function numberHashFn(key) {
        var c2 = 0x27d4eb2d;
        key = (key ^ 61) ^ (key >>> 16);
        key = key + (key << 3);
        key = key ^ (key >>> 4);
        key = key * c2;
        key = key ^ (key >>> 15);
        return key;
      }
  
      var getHashCode = (function () {
        var uniqueIdCounter = 0;
  
        return function (obj) {
          if (obj == null) { throw new Error(noSuchkey); }
  
          // Check for built-ins before tacking on our own for any object
          if (typeof obj === 'string') { return stringHashFn(obj); }
          if (typeof obj === 'number') { return numberHashFn(obj); }
          if (typeof obj === 'boolean') { return obj === true ? 1 : 0; }
          if (obj instanceof Date) { return numberHashFn(obj.valueOf()); }
          if (obj instanceof RegExp) { return stringHashFn(obj.toString()); }
          if (typeof obj.valueOf === 'function') {
            // Hack check for valueOf
            var valueOf = obj.valueOf();
            if (typeof valueOf === 'number') { return numberHashFn(valueOf); }
            if (typeof valueOf === 'string') { return stringHashFn(valueOf); }
          }
          if (obj.hashCode) { return obj.hashCode(); }
  
          var id = 17 * uniqueIdCounter++;
          obj.hashCode = function () { return id; };
          return id;
        };
      }());
  
      function newEntry() {
        return { key: null, value: null, next: 0, hashCode: 0 };
      }
  
      function Dictionary(capacity, comparer) {
        if (capacity < 0) { throw new ArgumentOutOfRangeError(); }
        if (capacity > 0) { this._initialize(capacity); }
  
        this.comparer = comparer || defaultComparer;
        this.freeCount = 0;
        this.size = 0;
        this.freeList = -1;
      }
  
      var dictionaryProto = Dictionary.prototype;
  
      dictionaryProto._initialize = function (capacity) {
        var prime = getPrime(capacity), i;
        this.buckets = new Array(prime);
        this.entries = new Array(prime);
        for (i = 0; i < prime; i++) {
          this.buckets[i] = -1;
          this.entries[i] = newEntry();
        }
        this.freeList = -1;
      };
  
      dictionaryProto.add = function (key, value) {
        this._insert(key, value, true);
      };
  
      dictionaryProto._insert = function (key, value, add) {
        if (!this.buckets) { this._initialize(0); }
        var index3,
          num = getHashCode(key) & 2147483647,
          index1 = num % this.buckets.length;
        for (var index2 = this.buckets[index1]; index2 >= 0; index2 = this.entries[index2].next) {
          if (this.entries[index2].hashCode === num && this.comparer(this.entries[index2].key, key)) {
            if (add) { throw new Error(duplicatekey); }
            this.entries[index2].value = value;
            return;
          }
        }
        if (this.freeCount > 0) {
          index3 = this.freeList;
          this.freeList = this.entries[index3].next;
          --this.freeCount;
        } else {
          if (this.size === this.entries.length) {
            this._resize();
            index1 = num % this.buckets.length;
          }
          index3 = this.size;
          ++this.size;
        }
        this.entries[index3].hashCode = num;
        this.entries[index3].next = this.buckets[index1];
        this.entries[index3].key = key;
        this.entries[index3].value = value;
        this.buckets[index1] = index3;
      };
  
      dictionaryProto._resize = function () {
        var prime = getPrime(this.size * 2),
          numArray = new Array(prime);
        for (index = 0; index < numArray.length; ++index) {  numArray[index] = -1; }
        var entryArray = new Array(prime);
        for (index = 0; index < this.size; ++index) { entryArray[index] = this.entries[index]; }
        for (var index = this.size; index < prime; ++index) { entryArray[index] = newEntry(); }
        for (var index1 = 0; index1 < this.size; ++index1) {
          var index2 = entryArray[index1].hashCode % prime;
          entryArray[index1].next = numArray[index2];
          numArray[index2] = index1;
        }
        this.buckets = numArray;
        this.entries = entryArray;
      };
  
      dictionaryProto.remove = function (key) {
        if (this.buckets) {
          var num = getHashCode(key) & 2147483647,
            index1 = num % this.buckets.length,
            index2 = -1;
          for (var index3 = this.buckets[index1]; index3 >= 0; index3 = this.entries[index3].next) {
            if (this.entries[index3].hashCode === num && this.comparer(this.entries[index3].key, key)) {
              if (index2 < 0) {
                this.buckets[index1] = this.entries[index3].next;
              } else {
                this.entries[index2].next = this.entries[index3].next;
              }
              this.entries[index3].hashCode = -1;
              this.entries[index3].next = this.freeList;
              this.entries[index3].key = null;
              this.entries[index3].value = null;
              this.freeList = index3;
              ++this.freeCount;
              return true;
            } else {
              index2 = index3;
            }
          }
        }
        return false;
      };
  
      dictionaryProto.clear = function () {
        var index, len;
        if (this.size <= 0) { return; }
        for (index = 0, len = this.buckets.length; index < len; ++index) {
          this.buckets[index] = -1;
        }
        for (index = 0; index < this.size; ++index) {
          this.entries[index] = newEntry();
        }
        this.freeList = -1;
        this.size = 0;
      };
  
      dictionaryProto._findEntry = function (key) {
        if (this.buckets) {
          var num = getHashCode(key) & 2147483647;
          for (var index = this.buckets[num % this.buckets.length]; index >= 0; index = this.entries[index].next) {
            if (this.entries[index].hashCode === num && this.comparer(this.entries[index].key, key)) {
              return index;
            }
          }
        }
        return -1;
      };
  
      dictionaryProto.count = function () {
        return this.size - this.freeCount;
      };
  
      dictionaryProto.tryGetValue = function (key) {
        var entry = this._findEntry(key);
        return entry >= 0 ?
          this.entries[entry].value :
          undefined;
      };
  
      dictionaryProto.getValues = function () {
        var index = 0, results = [];
        if (this.entries) {
          for (var index1 = 0; index1 < this.size; index1++) {
            if (this.entries[index1].hashCode >= 0) {
              results[index++] = this.entries[index1].value;
            }
          }
        }
        return results;
      };
  
      dictionaryProto.get = function (key) {
        var entry = this._findEntry(key);
        if (entry >= 0) { return this.entries[entry].value; }
        throw new Error(noSuchkey);
      };
  
      dictionaryProto.set = function (key, value) {
        this._insert(key, value, false);
      };
  
      dictionaryProto.containskey = function (key) {
        return this._findEntry(key) >= 0;
      };
  
      return Dictionary;
    }());
  