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,