←Previous | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | Next→
  return isFinite (x) ? copysign (x - trunc (x), x) : x;
}

//------------------------------------------------------------------------
//z = frem (x, y)
//  floor除算の余り
function frem (x, y) {
  return x - floor (x / y) * y;
}

//------------------------------------------------------------------------
//y = fround (x)
//  最も近いfloat値に丸める
function builtin_fround (x) {
  return new Float32Array ([x]) [0];
}
let fround = Math.fround || builtin_fround;

//------------------------------------------------------------------------
//y = hypot2 (a, b)
//y = hypot3 (a, b, c)
//y = hypot4 (a, b, c, d)
//y = hypotn (n, ...)
//  斜辺 hypotenuse
function builtin_hypot2 (a, b) {
  return sqrt (a * a + b * b);
}
function builtin_hypot3 (a, b, c) {
  return sqrt (a * a + b * b + c * c);
}
function builtin_hypot4 (a, b, c, d) {
  return sqrt (a * a + b * b + c * c + d * d);
}
function builtin_hypotn () {
  let y = 0.0;
  for (let i = 0, n = arguments.length; i < n; i++) {
    let x = arguments[i];
    y += x * x;
  }
  return sqrt (y);
}
let hypot2 = Math.hypot || builtin_hypot2;
let hypot3 = Math.hypot || builtin_hypot3;
let hypot4 = Math.hypot || builtin_hypot4;
let hypotn = Math.hypot || builtin_hypotn;

//------------------------------------------------------------------------
//z = ieeerem (x, y)
//  剰余(round-to-nearest)
function ieeerem (x, y) {
  return !isFinite (x) || isNaN (y) ? NaN : !isFinite (y) ? x : x - roundn (x / y) * y;
}

//------------------------------------------------------------------------
//z = imul (x, y)
//  32bit符号あり整数乗算(下位)
//  64bit浮動小数点数を32bit符号あり整数に変換して掛け合わせ、
//  積の64bit符号あり整数の下位32bitを32bit符号あり整数として取り出して64bit浮動小数点数に変換して返す
//
//  64bit浮動小数点数から32bit符号なし整数を取り出すとき32bit符号あり整数を経由してはならない
//  同じ32bit整数への変換でもdouble→intのキャストは-0x80000000..0x7fffffffで飽和するので、
//  0x80000000..0xffffffffのビットパターンが保存されない
function builtin_imul (x, y) {
  let b = x & 65535, d = y & 65535;
  return ((x >> 16) * d + b * (y >> 16) << 16) + b * d >>> 0 >> 0;
}
let imul = Math.imul || builtin_imul;

//------------------------------------------------------------------------
//z = imulh (x, y)
//  32bit符号あり整数乗算(上位)
//  64bit浮動小数点数を32bit符号あり整数に変換して掛け合わせ、
//  積の64bit符号あり整数の上位32bitを32bit符号あり整数として取り出して64bit浮動小数点数に変換して返す
//
//  64bit浮動小数点数から32bit符号なし整数を取り出すとき32bit符号あり整数を経由してはならない
//  同じ32bit整数への変換でもdouble→intのキャストは-0x80000000..0x7fffffffで飽和するので、
//  0x80000000..0xffffffffのビットパターンが保存されない
function imulh (x, y) {
  let a = x >> 16, b = x & 65535, c = y >> 16, d = y & 65535;
  return a * c + ((a * d + b * c + (b * d >>> 16)) * 2 ** -16 >> 0) >> 0;  //0x1p-16  *0x1p-16>>0の部分は入力が33bitあるので>>16にしてはならない
}

//------------------------------------------------------------------------
//b = isFinite (x)
//  有限か

//------------------------------------------------------------------------
//b = isInfinity (x)
//  ±Infinityか
function isInfinity (x) {
  return !isNaN (x) && !isFinite (x);
}

//------------------------------------------------------------------------
//b =isNaN (x)
//  NaNか

//------------------------------------------------------------------------
//b = isalnum (x)
function isalnum (x) {
  return isdigit (x) || isalpha (x);
}

//------------------------------------------------------------------------
//b = isalpha (x)
function isalpha (x) {
  return isupper (x) || islower (x);
}

//------------------------------------------------------------------------
//b = isascii (x)
function isascii (x) {
  return 0x00 <= x && x <= 0x7f;
}

//------------------------------------------------------------------------
//b = isbdigit (x)
function isbdigit (x) {
  return 0x30 <= x && x <= 0x31;  //'0'..'1'
}

//------------------------------------------------------------------------
//b = isblank (x)
function isblank (x) {
  return x == 0x09 || x == 0x20;  //'\t'||' '
}

//------------------------------------------------------------------------
//b = iscntrl (x)
function iscntrl (x) {
  return isascii (x) && !isprint (x);
}

//------------------------------------------------------------------------
//b = iscsym (x)
function iscsym (x) {
  return isdigit (x) || iscsymf (x);
}

//------------------------------------------------------------------------
//b = iscsymf (x)
function iscsymf (x) {
  return isalpha (x) || x == 0x5f;  //||'_'
}

//------------------------------------------------------------------------
//b = isdigit (x)
function isdigit (x) {
  return 0x30 <= x && x <= 0x39;  //'0'..'9'
}

//------------------------------------------------------------------------
//b = isgraph (x)
function isgraph (x) {
  return 0x21 <= x && x <= 0x7e;  //'!'..'~'
}

//------------------------------------------------------------------------
//b = islower (x)
function islower (x) {
  return 0x61 <= x && x <= 0x7a;  //'a'..'z'
}

//------------------------------------------------------------------------
//b = isodigit (x)
function isodigit (x) {
  return 0x30 <= x && x <= 0x37;  //'0'..'7'
}

//------------------------------------------------------------------------
//b = isprint (x)
function isprint (x) {
  return 0x20 <= x && x <= 0x7e;  //' '..'~'
}

//------------------------------------------------------------------------
//b = ispunct (x)
function ispunct (x) {
  return isgraph (x) && !isalnum (x);
}

//------------------------------------------------------------------------
//b = isspace (x)
function isspace (x) {
  return (0x09 <= x && x <= 0x0d) || x == 0x20;  //'\t'..'\r'||' '
}

//------------------------------------------------------------------------
//b = isupper (x)
function isupper (x) {
  return 0x41 <= x && x <= 0x5a;  //'A'..'Z'
}

//------------------------------------------------------------------------
//b = isxdigit (x)
function isxdigit (x) {
  return isdigit (x) || (0x41 <= x && x <= 0x46) || (0x61 <= x && x <= 0x66);  //||'A'..'F'||'a'..'f'
}

//------------------------------------------------------------------------
//y = log (x)
//  自然対数 natural logarithm
let log = Math.log;

//------------------------------------------------------------------------
//y = log10 (x)
//  常用対数 common logarithm
function builtin_log10 (x) {
  return log (x) * LOG10E;
}
let log10 = Math.log10 || builtin_log10;

//------------------------------------------------------------------------
//y = log1p (x)
//  1に近い数の自然対数 natural logarithm of number being close to 1
function builtin_log1p (x) {
  return x == 0 ? x : log (1.0 + x);
}
let log1p = Math.log1p || builtin_log1p;

//------------------------------------------------------------------------
//y = log2 (x)
//  二進対数 binary logarithm
function builtin_log2 (x) {
  return log (x) * LOG2E;
}
let log2 = Math.log2 || builtin_log2;

//------------------------------------------------------------------------
//y = max2 (a, b)
//y = max3 (a, b, c)
//y = max4 (a, b, c, d)
//y = maxn (n, ...)
//  最大値
let max2 = Math.max;
let max3 = Math.max;
let max4 = Math.max;
let maxn = Math.max;

//------------------------------------------------------------------------
//y = min2 (a, b)
//y = min3 (a, b, c)
//y = min4 (a, b, c, d)
//y = minn (n, ...)
//  最小値
let min2 = Math.min;
let min3 = Math.min;
let min4 = Math.min;
let minn = Math.min;

//------------------------------------------------------------------------
//z = pow (x, y)
//  累乗
let pow = Math.pow;

//------------------------------------------------------------------------
//y = rad (x)
//  pi/180倍(ラジアン)
function rad (x) {
  return RAD_DEG * x;
}

//------------------------------------------------------------------------
//y = rounda (x)
//  丸め(away-from-zero)
function rounda (x) {
  return x == 0 ? x : 0.0 < x ? floor (x + 0.5) : ceil (x - 0.5);
}

//------------------------------------------------------------------------
//y = roundm (x)
//  丸め(toward-minus-infinity)
function roundm (x) {
  return !isFinite (x) ? x : 0.0 <= x && x <= 0.5 ? floor (x) : ceil (x - 0.5);
}

//------------------------------------------------------------------------
//y = roundn (x)
//  丸め(nearest-even)
function roundn (x) {
  let y = floor (x + 0.5), z = ceil (x - 0.5);
  return copysign (y == z ? y : floor (y * 0.5) * 2.0 == y ? y : z, x);
}

//------------------------------------------------------------------------
//y = roundp (x)
//  丸め(toward-plus-infinity)
function roundp (x) {
  return !isFinite (x) ? x : -0.5 <= x && x <= 0.0 ? ceil (x) : floor (x + 0.5);
}

//------------------------------------------------------------------------
//z = roundp2 (x, y)
//  丸め(toward-plus-infinity)
function roundp2 (x, y) {
  return roundp (x / y) * y;
}

//------------------------------------------------------------------------
//y = roundz (x)
//  丸め(toward-zero)
function roundz (x) {
  return !isFinite (x) || x == 0 ? x : (0.0 < x ?
                                        x <= 0.5 ? 0.0 : ceil (x - 0.5) :
                                        -0.5 <= x ? -0.0 : floor (x + 0.5));
}

//------------------------------------------------------------------------
//y = sec (x)
//  正割 secant セカント
function sec (x) {
  return 1.0 / cos (x);
}

//------------------------------------------------------------------------
//y = sech (x)
//  双曲線正割 hyperbolic secant ハイパボリックセカント
function sech (x) {
  return 1.0 / cosh (x);
}

//------------------------------------------------------------------------
//y = sgn (x)
//  符号
function builtin_sgn (x) {
  x = +x;
  return x === 0 || isNaN (x) ? x : 0.0 < x ? 1.0 : -1.0;
}
let sgn = Math.sign || builtin_sgn;

//------------------------------------------------------------------------
//y = sin (x)
//  正弦 sine サイン
let sin = Math.sin;

//------------------------------------------------------------------------
//y = sinh (x)
//  双曲線正弦 hyperbolic sine ハイパボリックサイン
function builtin_sinh (x) {
  return x == 0 ? x : x = exp (x), 0.5 * (x - 1.0 / x);
}
let sinh = Math.sinh || builtin_sinh;

//------------------------------------------------------------------------
//y = sqrt (x)
//  1/2乗(平方根)
let sqrt = Math.sqrt;

//------------------------------------------------------------------------
//y = squ (x)
//  2乗
function squ (x) {
  return x * x;
}

//------------------------------------------------------------------------
//y = tan (x)
//  正接 tangent タンジェント
let tan = Math.tan;

//------------------------------------------------------------------------
//y = tanh (x)
//  双曲線正接 hyperbolic tangent ハイパボリックタンジェント
function builtin_tanh (x) {
  return isNaN (x) || x == 0 ? x : isFinite (x) ? (x = exp (2.0 * x), (x - 1.0) / (x + 1.0)) : 0.0 <= x ? 1.0 : -1.0;
}
let tanh = Math.tanh || builtin_tanh;

//------------------------------------------------------------------------
//b = tolower (x)
function tolower (x) {
  return isupper (x) ? x | 0x20 : x;
}

//------------------------------------------------------------------------
//b = toupper (x)
function toupper (x) {
  return islower (x) ? x & ~0x20 : x;
}

//------------------------------------------------------------------------
//y = trunc (x)
//  切り落とし truncate
function builtin_trunc (x) {
  return isNaN (x) ? NaN : 0.0 <= x ? floor (x) : ceil (x);
}
let trunc = Math.trunc || builtin_trunc;

//------------------------------------------------------------------------
//z = umul (x, y)
//  32bit符号なし整数乗算(下位)
//  64bit浮動小数点数を32bit符号なし整数に変換して掛け合わせ、
//  積の64bit符号なし整数の下位32bitを32bit符号なし整数として取り出して64bit浮動小数点数に変換して返す
//
//  64bit浮動小数点数から32bit符号なし整数を取り出すとき32bit符号あり整数を経由してはならない
//  同じ32bit整数への変換でもdouble→intのキャストは-0x80000000..0x7fffffffで飽和するので、
//  0x80000000..0xffffffffのビットパターンが保存されない
function umul (x, y) {
  let b = x >>> 0 & 65535, d = y >>> 0 & 65535;
  return ((x >>> 16) * d + b * (y >>> 16) << 16) + b * d >>> 0;
}

//------------------------------------------------------------------------
//z = umulh (x, y)
//  32bit符号なし整数乗算(上位)
//  64bit浮動小数点数を32bit符号なし整数に変換して掛け合わせ、
//  積の64bit符号なし整数の上位32bitを32bit符号なし整数として取り出して64bit浮動小数点数に変換して返す
//
//  64bit浮動小数点数から32bit符号なし整数を取り出すとき32bit符号あり整数を経由してはならない
//  同じ32bit整数への変換でもdouble→intのキャストは-0x80000000..0x7fffffffで飽和するので、
//  0x80000000..0xffffffffのビットパターンが保存されない
function umulh (x, y) {
  let a = x >>> 16, b = x >>> 0 & 65535, c = y >>> 16, d = y >>> 0 & 65535;
  return a * c + ((a * d + b * c + (b * d >>> 16)) * 2 ** -16 >>> 0) >>> 0;  //0x1p-16  *0x1p-16>>>0の部分は入力が33bitあるので>>>16にしてはならない
}





//========================================================================================
//
//  Event
//
//========================================================================================

//------------------------------------------------------------------------
//element = addEvent (element, type1, listener1, type2, listener2, ...)
//  Object element
//  Object element
//  String type
//  Function listener
//  DOM要素にイベントリスナーを追加する
function addEvent (element, ...typeListener) {
  for (let i = 0; i + 1 < typeListener.length; i += 2) {
    let type = typeListener[i];
    let listener = typeListener[i + 1];
    if (element.addEventListener) {
      element.addEventListener (type, listener, false);
    } else if (element.attachEvent) {
      //IE8まではaddEventListenerがないので代わりにattachEventを使う
      //attachEventはthisの値がwindowになってしまうのでFunction.prototype.applyを使ってthisにターゲットを入れてからリスナーを呼び出す
      element.attachEvent ("on" + type, function () {
        listener.apply (element, arguments);
      });
    } else {
      //attachEventもないときはelement.on~に入れるしかない
      //追加ではなく上書きになってしまうのでリスナーが存在する場合はそれと追加するリスナーの両方を呼び出す
      let prevListener = element["on" + type];  //Function
      element["on" + type] = typeof (prevListener) === "function" ? function () {
        prevListener.apply (element, arguments);
        listener.apply (element, arguments);
      } : listener;
    }
  }  //for i
  return element;
}

//------------------------------------------------------------------------
//b = consumeEvent (e)
//  boolean b
//  Error e
//  イベントを消費する
function consumeEvent (e) {
  if (e.preventDefault) {
    e.preventDefault ();
  }
  if (e.stopPropagation) {
    e.stopPropagation ();
  }
}





//========================================================================================
//
//  Debug
//
//========================================================================================

//------------------------------------------------------------------------
//cprint (s)
//  コンソールに出力する
function cprint (s) {
  //Chromeでなければ文字列にする
  //  ChromeはコンソールでObjectを展開できるので文字列にする必要がない
  if (!sincludes (navigator.userAgent, "Chrome")) {
    s += "";  //Stringにする。nullも文字列にできる
  }
  //コンソールに出力する
  if (console) {
    console.log (s);  //MSIEのconsole.logはapplyが使えない
  } else if (window.opera) {
    window.opera.postError (s);
  }
}

//------------------------------------------------------------------------
//cprintf (format, data...)
//  コンソールへのフォーマット出力
function cprintf () {
  cprint (sprintf.apply (this, arguments));
}

//------------------------------------------------------------------------
//s = otos (o)
//  オブジェクトのメンバをすべて文字列に変換する
function otos (o) {
  if (o === null) {
    return "" + o;
  }
  let a = [];
  for (let k in o) {
    a.push (k);
  }
  a.sort ();
  for (let i = 0; i < a.length; i++) {
    a[i] = a[i] + "=" + o[a[i]] + "\n";
  }
  return a.join ("");
}





//========================================================================================
//
//  File
//
//========================================================================================

//------------------------------------------------------------------------
//success = readBinaryFile (name, process)
//  boolean success
//  String name
//  Function process
//    process (data)
//    Uint8Array data
//  バイナリファイルを読み込む
//  読み終わるとprocess(data)が呼ばれる
//  Google Chromeでローカルでテストするときはコマンドラインに-allow-file-access-from-filesを指定する
function readBinaryFile (name, process) {
  let r = null;  //Object
  if (XMLHttpRequest) {
    try {
      r = new XMLHttpRequest ();
    } catch (e) {  //Error
    }
  }
/*
  if (!r && ActiveXObject) {
    let a = ["Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.3.0", "Msxml2.XMLHTTP", "Microsoft.XMLHTTP"];  //Array
    while (!r && a.length) {
      try {
        r = new ActiveXObject (a.shift ());
      } catch (e) {  //Error
      }
    }
  }
*/
  if (!r) {
    return false;
  }
  r.onload = function () {
    if (r.response instanceof ArrayBuffer) {
      process (new Uint8Array (r.response));
    }
  };
  r.open ("GET", name);
  r.responseType = "arraybuffer";
  r.send ();
  return true;
}





//========================================================================================
//
//  String
//
//========================================================================================

//------------------------------------------------------------------------
//s = fromCharCode (code, ...)
let fromCharCode = String.fromCharCode;

//------------------------------------------------------------------------
//n = parseNum (s)
//  double n
//  String s
//  文字列を数値に変換する
//  数値として解釈できないときは0を返す
//  NaNを返すことはない
function parseNum (s) {
  let n = parseFloat (s || "0");  //double
  return isNaN (n) ? 0 : n;
}

//------------------------------------------------------------------------
//n = parseDec (s)
//  double n
//  String s
//  文字列を10進数の整数とみなして数値に変換する
//  10進数の整数として解釈できないときは0を返す
//  NaNを返すことはない
function parseDec (s) {
  let n = parseInt (s || "0", 10);  //double
  return isNaN (n) ? 0 : n;
}

//------------------------------------------------------------------------
//n = parseHex (s)
//  double n
//  String s
//  文字列を16進数とみなして数値に変換する
//  16進数として解釈できないときは0を返す
//  NaNを返すことはない
function parseHex (s) {
  let n = parseInt (s || "0", 16);  //double
  return isNaN (n) ? 0 : n;
}

//------------------------------------------------------------------------
//b = sincludes (s, t, i)
//  文字列sのインデックスi(省略時0)以降に文字列tが含まれるかどうか
let sincludes = (
  String.prototype.includes ?
  function (s, t, i) {
    return s.includes (t, i);
  } :
  function (s, t, i) {
    return 0 <= s.indexOf (t, i);
  });

//------------------------------------------------------------------------
//s = sprintf (s, format, data, ...)
//  フォーマット出力
//  format  フォーマット
//    %%
//    %[index$][flags][minimum width][.precision or maximum width]mode
//  %%    %を出力する
//  index$  インデックスで指定された引数を使う
//  flags  フラグ
//    空白  正数の先頭に+を出力しないとき空白を出力する
//    #     16進数などの先頭にプレフィックスを付ける
//    +     正数の先頭に+を出力する
//    -     左詰めにする
//    0     右詰めのときゼロ充填する
//  minimum width  フィールド幅。*のとき引数を参照する
//  precision or maximum width  精度または最大幅。*のとき引数を参照する
//  mode
//    Aa  浮動小数点数  16進数
//    Bb  整数          2進数
//    Ee  浮動小数点数  浮動小数点
//    Ff  浮動小数点数  固定小数点
//    Gg  浮動小数点数  有効桁数
//    Xx  整数          16進数
//    c   整数          文字
//    d   整数          10進数
//    o   整数          8進数
//    s   文字列        文字列
function sprintf () {
  let f = arguments[0];  //String  format フォーマット
  let n = 0;  //int  最後に使用したパラメータの番号。index$は反映しない
  let o = "";  //String  出力する文字列
  let r = new RegExp (
    "%" +
    "(?:" + ("(%)" +  //$1 %
             "|" +
             "(?:([1-9]\\d*)\\$)?" +  //$2 index
             "([- #+0]*)" +  //$3 flags
             "(?:" + ("(\\*)" +  //$4 dynamic minimum width mode
                      "(?:([1-9]\\d*)\\$)?" +  //$5 index of minimum width
                      "|" +
                      "([1-9]\\d*)") +  //$6 minimum width
             ")?" +
             "(?:" + ("\\." +
                      "(?:" + ("(\\*)" +  //$7 dynamic precision or maximum width mode
                               "(?:([1-9]\\d*)\\$)?" +  //$8 index of precision or maximum width
                               "|" +
                               "(\\d+)") +  //$9 precision or maximum width
                      ")") +
             ")?" +
             "([ABEFGXabcdefgosx])") +  //$10 mode
    ")", "g");  //RegExp  フォーマットの正規表現
  let i = 0;  //int  %を探し始める位置
  r.lastIndex = 0;
  let t;
  while (t = r.exec (f)) {  //Array
    o += f.substring (i, t.index);  //見つかった%の手前までそのままコピー
    i = r.lastIndex;  //次回%を探し始める位置
    if (t[1]) {  //%
      o += "%";
      continue;
    }
    let b, p, s, l, z;  //boolean
    if (t[3]) {  //フラグ
      b = sincludes (t[3], " ");  //正数の先頭に+を出力しないとき空白を出力する
      p = sincludes (t[3], "#");  //16進数などの先頭にプレフィックスを付ける
      s = sincludes (t[3], "+");  //正数の先頭に+を出力する
      l = sincludes (t[3], "-");  //左詰めにする
      z = sincludes (t[3], "0");  //右詰めのときゼロ充填する
    } else {
      b = p = s = l = z = false;
    }
    let w = (t[4] ? arguments[t[5] ? parseInt (t[5], 10) : ++n] :
             t[6] ? parseInt (t[6], 10) :
             -1);  //int  フィールド幅。$5,$6の先頭は[1-9]なのでNaNにはならない
    let e = (t[7] ? arguments[t[8] ? parseInt (t[8], 10) : ++n] :
             t[9] ? parseInt (t[9], 10) :
             -1);  //int  精度または最大幅。$8,$9の先頭は[1-9]なのでNaNにはならない
    let d = arguments[t[2] ? parseInt (t[2], 10) : ++n];  //Object  インデックスの位置のデータ。$2の先頭は[1-9]なのでNaNにはならない
    let m = t[10];  //String  モード
    let k;  //int
    if (m === "c" || m === "s") {  //文字モード
      p = "";
      d = m === "c" ? fromCharCode (d >> 0) : d + "";  //明示的に文字列にする
      if (0 <= e && e < d.length) {  //最大幅を超えているとき
        d = d.substring (0, e);  //末尾を切り捨てる
      }
    } else {  //数値モード
      d -= 0;  //明示的に数値にする。"033"は10進数、""は0、"0h"はNaN
      if (sincludes ("BXbdox", m)) {  //整数モード
        d = trunc (d);  //明示的に整数にする。32bitに収まらない場合があるので>>0は不可
        if (m === "d") {  //10進数
          if (d < 0) {  //負数。0<=dだとNaNのときfalseなので-NaNと表示されてしまう。整数なので-0は存在しない
            p = "-";
            d = -d;
          } else {  //正数
            p = s ? "+" : b ? " " : "";
          }
          d = d.toString (10);
        } else {  //10進数以外
          if (d < 0) {  //負数のとき
            //32bit符号なし整数にする
            //&で下位32bitを符号あり整数として切り出してから>>>0を使って符号なし整数にする
            //toStringは10進数でなくても符号が付くので、bit31が立っている数も正数にしておかなければならない
            d = (d & 0xffffffff) >>> 0;
          }
          if (m === "x") {  //16進数小文字
            p = p ? "0x" : "";
            d = d.toString (16).toLowerCase ();
          } else if (m === "X") {  //16進数大文字
            p = p ? "0X" : "";
            d = d.toString (16).toUpperCase ();
          } else if (m === "o") {  //8進数
            p = p ? "0" : "";  //8進数のプレフィックスは0のみ
            d = d.toString (8);
          } else {  //2進数
            p = p ? "0" + m : "";
            d = d.toString (2);
          }
        }  //if 10進数/10進数以外
        if (0 <= e && 0 < (k = e - d.length)) {  //有効桁数に満たないとき
          d = srepeat ("0", k) + d;  //有効桁数までゼロ充填する
          z = 0;  //フィールド幅までのゼロ充填を解除する
        }
        if (m === "o" && d.charAt (0) === "0") {  //先頭が0のとき8進数のプレフィックスは不要
          p = "";
        }
      } else {  //浮動小数点数モード
        if (d < 0 || (d === 0 && 1 / d < 0)) {  //負数。0<=dだとNaNのときfalseなので-NaNと表示されてしまう。1/d<0は-0の判別
          p = "-";
          d = -d;
        } else {  //正数
          p = s ? "+" : b ? " " : "";
        }
        if (m === "a" || m === "A") {  //16進数
          if (!isFinite (d)) {  //NaNまたはInfinity
            d = d.toString ();  //NaNとInfinityは0xXXXp+XXXの形で書けない
          } else if (d === 0) {  //0
            p += "a" <= m ? "0x" : "0X";
            d = "0" + ("a" <= m ? "p+0" : "P+0");
          } else {  //非正規化数または正規化数
            p += "a" <= m ? "0x" : "0X";
            let a = new Uint32Array (new Float64Array ([d]).buffer);
            let e0, m0, m1;
            let bigEndian = new Uint32Array (new Float64Array ([1]).buffer)[0] == 0x3ff00000;  //true=big endian,false=little endian
            if (bigEndian) {
              e0 = a[0] >>> 20;  //指数部
              m0 = a[0] & 0xfffff;  //Uint32 仮数部の上位20bit
              m1 = a[1];  //Uint32 仮数部の下位32bit
            } else {
              e0 = a[1] >>> 20;  //指数部
              m0 = a[1] & 0xfffff;  //Uint32 仮数部の上位20bit
              m1 = a[0];  //Uint32 仮数部の下位32bit
            }
            if (e0 == 0) {  //非正規化数
              let i0 = m0 ? clz32 (m0) - 11 : clz32 (m1) + 21;  //左にずらすbit数
              e0 -= i0 - 1;
              if (i0 < 32) {
                m0 = m0 << i0 | m1 >>> -i0;  //Uint32 整数部を付けたまま正規化する
                m1 = (m1 << i0) >>> 0;  //Uint32
              } else if (i0 == 32) {
                m0 = m1;  //Uint32
                m1 = 0;  //Uint32
              } else {
                m0 = m1 << i0;  //Uint32
                m1 = 0;  //Uint32
              }
            } else {  //正規化数
              m0 |= 0x100000;  //Uint32 整数部を付ける
            }
            e0 -= 1023;
            if (e < 0) {
              e = m1 ? 13 - (ctz32 (m1) >> 2) : 5 - (ctz32 (m0) >> 2);  //正確に表現するのに必要な小数部の桁数
            }
            if (e < 5) {
              m0 += 0x80000 >>> (e << 2);  //Uint32
              m0 &= -1 << ((5 - e) << 2);  //Uint32
              m1 = 0;  //Uint32
            } else if (e == 5) {
              if (m1 >> 0 < 0) {
                m0++;  //Uint32
              }
              m1 = 0;  //Uint32
            } else if (e < 13) {
              m1 += 0x80000000 >>> ((e - 5) << 2);  //33bitになる場合がある。演算子に注意
              if (m1 >>> 0 != m1) {
                m0++;  //Uint32
                m1 >>>= 0;  //Uint32
              }
              m1 = (m1 & -1 << ((13 - e) << 2)) >>> 0;  //Uint32
            }
            d = (m0 * 0x100000000 + m1).toString (16);  //整数部1桁と小数部13桁。JavaScriptは16進数の整数をdoubleの範囲で入出力できる
            if (e == 0) {  //小数部が0桁のとき
              d = d.substring (0, 1);  //小数点を省略する
            } else {
              if (e <= 13) {
                d = d.substring (0, 1 + e);
              } else {
                d += srepeat ("0", e - 13);
              }
              d = d.substring (0, 1) + "." + d.substring (1);
            }
            d += ("a" <= m ? "p" : "P") + (e0 < 0 ? "" : "+") + e0;
          }
        } else {  //10進数
          if (e < 0) {  //有効桁数のデフォルトは6桁
            e = 6;
          }
          if (m === "e" || m === "E") {  //浮動小数点
            d = d.toExponential (e <= 20 ? e : 20);  //toExponentialは0から20まで
          } else if (m === "f" || m === "F") {  //固定小数点
            d = d.toFixed (e <= 20 ? e : 20);  //toFixedは0から20まで
          } else {  //有効桁数
            let e1 = !e ? 1 : e <= 21 ? e : 21;  //toPrecisionは1から21まで
            let d1 = d.toPrecision (e1);
            let r1 = d1.match (/\.(?:[1-9]|0+[1-9])*(0+)(?=[eE]|$)/);
            if (r1) {
              e1 -= r1[1].length;  //末尾の0の並びの長さ
              d1 = d.toPrecision (e1);  //末尾の0の並びを取り除く
            }
            d = d1;
          }
          if (0 <= (k = d.indexOf ("e")) || 0 <= (k = d.indexOf ("E"))) {  //指数部分があるとき
            if (k === d.length - 3) {  //指数部分が1桁しかないときは2桁にする
              d = d.substring (0, d.length - 1) + "0" + d.substring (d.length - 1);
            }
            d = d.substring (0, k) + ("e" <= m ? "e" : "E") + d.substring (k + 1);  //eまたはEの小文字/大文字を合わせる
          }
        }  //if 16進数/10進数
      }  //if 整数モード/浮動小数点数モード
    }  //if 文字モード/数値モード
    o += (w < 0 || (k = w - (p + d).length) <= 0 ? p + d :  //プレフィックスのみ
          l ? p + d + srepeat (" ", k) :  //左詰め
          z ? p + srepeat ("0", k) + d :  //ゼロ充填右詰め
          srepeat (" ", k) + p + d);  //空白充填右詰め
  }  //while t
  return o + f.substring (i);  //%を含まない残りの文字列を連結してから返す
}

//------------------------------------------------------------------------
//t = srepeat (s, n)
//  文字列sをn回繰り返した文字列
let srepeat = (
  String.prototype.repeat ?
  function (s, n) {
    return s.repeat (n);
  } :
  function (s, n) {
    s += "";  //文字列にする
    n >>= 0;  //32bit符号あり整数にする。32bitを超える可能性は考えない
    if (s.length && 0 < n) {  //文字列が""ではなくて回数が1以上かつNaNではないとき
      let t = n & 1 ? s : "";
      while (n >>= 1) {
        s += s;
        if (n & 1) {
          t += s;
        }
      }
      return t;
    } else {
      return "";
    }
  });





//========================================================================================
//
//  SVG
//
//========================================================================================

let SVGNS = "http://www.w3.org/2000/svg";  //String

//o = createRootSvg (width, height, viewX, viewY, viewWidth, viewHeight)
//  Object o
//  int width
//  int height
//  double viewX
//  double viewY
//  double viewWidth
//  double viewHeight
function createRootSvg (width, height, viewX, viewY, viewWidth, viewHeight) {
  if (document.createElementNS === undefined) {  //document.createElementNSがないのでsvgが使えない
    return null;
  }
  let svgElement = nsCreateNode (SVGNS, "svg");  //Object
  if (!(typeof (svgElement) == "object" &&
        (typeof (svgElement.SVG_ZOOMANDPAN_UNKNOWN) == "number" ||
         typeof (svgElement.ownerSVGElement) == "object"))) {  //IE9PPのsvgはSVG_ZOOMANDPAN_UNKNOWNがない
    return null;
  }
  return setViewBox (resizeRootSvg (svgElement, width, height), viewX, viewY, viewWidth, viewHeight);
}

//o = resizeRootSvg (o, width, height)
//  Object o
//  int width
//  int height
function resizeRootSvg (o, width, height) {
  return setStyle (nsSetAttr (o, null, "width", width + "px", "height", height + "px"),
                   "height", height + "px", "width", width + "px");
}

//o = createSvg (x, y, width, height, viewX, viewY, viewWidth, viewHeight)
//  Object o;
//  int x
//  int y
//  int width
//  int height
//  double viewX
//  double viewY
//  double viewWidth
//  double viewHeight
function createSvg (x, y, width, height, viewX, viewY, viewWidth, viewHeight) {
  return setViewBox (moveSvg (nsCreateNode (SVGNS, "svg"), x, y, width, height), viewX, viewY, viewWidth, viewHeight);
}

//o = moveSvg (o, x, y, width, height)
//  Object o
//  int x
//  int y
//  int width
//  int height
function moveSvg (o, x, y, width, height) {
  return nsSetAttr (o, null, "x", x, "y", y, "width", width, "height", height);
}

//o = setViewBox (o, viewX, viewY, viewWidth, viewHeight)
//  Object o
//  double viewX
//  double viewY
//  double viewWidth
//  double viewHeight
function setViewBox (o, viewX, viewY, viewWidth, viewHeight) {
  return nsSetAttr (o, null, "viewBox", viewX + " " + viewY + " " + viewWidth + " " + viewHeight);
}

//--------------------------------------------------------------------------------
//default

let defaultAlignmentBaseline = null;  //String  auto | baseline | before-edge | text-before-edge | middle | central | after-edge | text-after-edge | ideographic | alphabetic | hanging | mathematical | inherit
let defaultDisplay = null;  //String
let defaultFill = null;  //String
let defaultFontFamily = "Meiryo,メイリオ,sans-serif";  //String
let defaultFontSize = NaN;  //double
let defaultFontStyle = null;  //String  normal | italic | oblique | inherit
let defaultFontWeight = null;  //String  normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit
let defaultOpacity = NaN;  //double
let defaultStroke = null;  //String
let defaultStrokeLinecap = null;  //String  butt | round | square | inherit
let defaultStrokeLinejoin = null;  //String  miter | round | bevel | inherit
let defaultStrokeWidth = NaN;  //double
let defaultTextAnchor = null;  //String  start | middle | end | inherit
let defaultStack = [];  //Array

//pushDefault ()
function pushDefault () {
  defaultStack.push ({
  _alignmentBaseline: defaultAlignmentBaseline,
←Previous | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | Next→