docs: function Sort_nat(source,       // @arg StringArray     - source. ["abc100", "abc1", "abc10"]
                    ignoreCase) { // @arg Boolean = false - true is case-insensitive
                                  // @ret StringArray     - sorted array. ["abc1", "abc10", "abc100"]
                                  // @desc nat sort
  //{@dev
      _if(!Array.isArray(source), "Sort.nat(source)");
      _if(ignoreCase !== undefined &&
          typeof ignoreCase !== "boolean", "Sort.nat(,ignoreCase)");
  //}@dev
  
      function toNumberArray(str) {
          return str.split(/(\d+)/).reduce(function(prev, next) {
                      if (next !== "") {
                          if (isNaN(next)) {
                              next.split("").forEach(function(v) {
                                  prev.push( v.charCodeAt(0) );
                              });
                          } else {
                              prev.push(+next);
                          }
                      }
                      return prev;
                  }, []);
      }
  
      var cache = {}; // { keyword: [number, ...], ... }
  
      return source.sort(function(a, b) {
          var aa, bb;
  
          if (a in cache) {
              aa = cache[a];
          } else {
              cache[a] = aa = toNumberArray( ignoreCase ? a.toLowerCase() : a );
          }
          if (b in cache) {
              bb = cache[b];
          } else {
              cache[b] = bb = toNumberArray( ignoreCase ? b.toLowerCase() : b );
          }
          var x = 0, y = 0, i = 0, iz = aa.length;
  
          for (; i < iz; ++i) {
              x = aa[i] || 0;
              y = bb[i] || 0;
              if (x !== y) {
                  return x - y;
              }
          }
          return a.length - b.length;
      });
  }