ã¡ãã£ãšåã«ãçŽ ã®JSã䜿çšããŠãã³ãã«ããéåãæç»ãããµã€ããGitHubäžã«å ¬éããŸãããããã®ãŽããšã¯æ¯ã«ãªããªãã»ã©ãºãŒã ãã¹ã ãŒãºã«è¡ãããµã€ããèŠã€ããã®ã§ç޹ä»ããŸãã
以äžã®ãµã€ãã«ãªããŸã â
JavaScriptã¯éåžžãå粟床浮åå°æ°ç¹æ°ã§èšç®ããã®ã§ãããã10^16çšåºŠã®åçã§èšç®èª€å·®ã蚱容ç¯å²å€ã«ãªãããããã¯ã»ã«åããŠããŸããŸã(å³å¯ã«æ£ç¢ºãªæŒç®ãã§ããã®ã¯10^14çšåºŠ)ãç§ãäœæãããµã€ãã¯å®éãã®èšç®æ¹æ³ã§å®è£ ããŠãããããå²ãšããã«ãºãŒã ã®éçã«å°éããŸãã
ããããäžèšã®ãµã€ãã¯æåæ³ãšããèšç®æ¹æ³ãå©çšããããšã§ã10^300çšåºŠãŸã§æ£ç¢ºãªãºãŒã ãå¯èœã«ããŠããŸããæŽã«ãWebWorkerã«ãã䞊ååãGPUã¢ã¯ã»ã©ã¬ãŒã·ã§ã³ãå®è£ ããŠãããéåžžã«æ·±ããºãŒã ã§ãã£ãŠãé«éã«èšç®ã§ããããã§ãã
ããããå ã¯ãæåæ³ã®èšç®æ¹æ³ã«ã€ããŠãããã®ãµã€ãã®å®è£ æŠèŠãåå¿è ã®ç®¡ç人ãã§ããçšåºŠã«è§£èª¬ããŠãããŸãã
ãŸãã¯ãã³ãã«ããéåã«ã€ããŠ
詳ãã解説ãããšã¡ãã£ãšé·ãã®ã§è»œã説æãããšã
æ¬¡ã®æŒžååŒ
ã§ãå®çŸ©ãããè€çŽ æ°åã® ã«ãããšãã«ãçºæ£ããªããšããç¹å šäœã®éåãã¬ã³ããªã³ã°ãããã®ã§ãããã®å³åœ¢ã¯ããããæ¡å€§ããŠãåããããªæ§é ãçŸãããã©ã¯ã¿ã«å³åœ¢ãšèšããããã®ã§ãã
æåæ³ã«ã€ããŠ
å ã»ã©ã説æããŸããããéåžžã®JavaScriptã§ã¯å粟床浮åå°æ°ç¹æ°ã§æŽæ°ãå°æ°ã«é¢ãããæ°å€ãæ±ãã®ã§ãããæ¥µç«¯ã«ãºãŒã ããããšã座æšã®å°æ°ç¹ä»¥äžã®æ¡æ°ãfloat64ã®ä»®æ°éšãè¶ ããŠããŸããä»è¿ã§ã¯èšç®èª€å·®ãããããã倧ãããšèšç®ãäžå¯èœã«ãªããŸãã
ããããåœç¶ãªãããããã倧ããªå€ãæ±ãããã®BigIntãšãããã®ããããããã¯ã¡ã¢ãªãèš±ãéãã®æ¡æ°ãå®è³ªã»ãŒç¡éã«å€§ããª(å°ããª)å€ã衚çŸããããšãå¯èœã§ããããéåžžã®numberåã§èšç®ããããé¥ãã«é
ããªããŸã(æ°å~æ°åå)ãããšããéåžžã®numberåã§è¡šããflaot64ã®éçå€(900京ããã)以å
ã§ãã£ãŠãã§ãã
ã€ãŸããéåžžã®èšç®æ¹æ³ã§ãã1ãã¯ã»ã«ããšã«ç¬ç«ããŠèšç®ãããæ¹æ³ã§ã¯ãBigIntã§è¡ãããšãããšçŸå®çãªæéã§èšç®ããããšãã§ããŸããã1æã¬ã³ããªã³ã°ãããã³ã«æ°åç§ããæ°åããã£ãšæ¡å€§ããŠæ¡æ°ãå¢ããŠãããšæ°æéæããå¯èœæ§ãããã®ã§ãã
ããã§äœ¿çšãããã¢ã«ãŽãªãºã ãæåæ³ãšããèšç®æ¹æ³ã§ãã
以äžãwikipediaããåŒçš
æ°åŠçã«å³å¯ã«è§£ãããšã®ã§ããªãåé¡ã®è¿äŒŒè§£ãæ±ããææ³ã®1ã€ã«ãæåè«ïŒãã€ã©ãããã è±èª: perturbation theoryïŒããããå ·äœçã«ã¯ã次ã®ãããªæé ã§è¿äŒŒè§£ãæ±ããã
- èããŠããåé¡Aããå³å¯ã«è§£ããåé¡Bã«å°ããªå€æŽïŒæåïŒãå ããããåé¡ã§ãããšã¿ãªãã
- åé¡Aã®è¿äŒŒè§£ã¯ãåé¡Bã®å³å¯è§£ã«ãæåãå ãã£ãããšã«ãã£ãŠçããå°ããªè£æ£ïŒæåé ïŒãå ãããã®ã§ãããšèããã
- ããã§æ±ããã¹ãæåé ã¯ãåé¡Bã®å³å¯è§£ã®çµã¿åãããããªãã¡äžæ¬¡çµåã®åœ¢ã§è¡šçŸåºæ¥ããšèãããã®ä¿æ°ãäžããããæ¡ä»¶ããé æ¬¡æ±ããã
äœãèšã£ãŠãããã¡ãã£ãšåããã¥ããã§ãããããããã³ãã«ããéåã®æç»ã«é©çšããŸãã
æ°åŠçã«å³å¯ã«è§£ãããšã®åºæ¥ãªãåé¡ã§ã¯ãããŸããããè¿äŒŒè§£ãæ±ããéšåã䜿çšããŸãã
- æç»é åã®äžã€ã®ç¹ã代衚ã®ç¹(åç §ç¹)ãšããŠBigIntã䜿çšããŠé«ç²ŸåºŠã«èšç®ãè¡ãããã®ãšããèšç®çµæãå šãŠä¿æããŠããã
- ä»ã®ç¹ã¯ããã®åç
§ç¹ããã®å·®åã§è¿äŒŒå埩èšç®ãè¡ãããã®ãšãã誀差å¢çãè¶
ããŠããŸãç¹ãçŸããå Žåãæ°ããåç
§ç¹ãšããŠèšç®ãè¡ãã
ãã®ãšãã®åç §ç¹ãšã®å·®åããéåžžã®numberåã§ã®ç¯å²å ã«åãŸããšæåŸ ããããšã§ãBigIntã®äœ¿çšãæå°éã«ãã€ã€ãé«éã§é«ç²ŸåºŠãªã¬ã³ããªã³ã°ãå¯èœã«ãªããŸãã
èŠèŠçã«çè§£ããããªãã3Blue1BrownJapanæ§ã®ä»¥äžã®åç»ã®4:10ã»ã©ã®éšåããèŠããã¢ãã¡ãŒã·ã§ã³ãèŠãŠã¿ãŠãã ããã
ãã®è»è·¡ã§ãããæ¡å€§ããŠãããšãé£ãåããã¯ã»ã«ã®æ°å€ã®å·®ããšãŠãå°ããªå€ã«ãªããé ç®ã«ã¿ããã»ãŒåãè»è·¡ã蟿ãããã«ãªããŸãããã®è»è·¡ã®èª€å·®ãnumberåã§é«éã«èšç®ã§ãããšèãããšåãããããããšæããŸãã
ãããŠããã®è»è·¡ã®å·®ãäžå®ä»¥äžã«ãªã£ããšãã¯æ£ç¢ºãªèšç®ã®ããã«æ°ããåç
§ç¹ãäœæããåãæ§ã«å
šãŠã®ãã¯ã»ã«ã§èšç®ããã®ã§ãã
ããããããã§ãå·®åãnumberåã®ç¯å²å ã«åãŸããšæåŸ ãããã®ãããããã10^300ããããšèšãããŠããã®ã§ããã以äžã®ãºãŒã ãè¡ãå Žåã¯ãææ°éšããŸãå¥ã«ä¿æãããšãããããªé«è² è·ãªèšç®æ¹æ³ã«ãªããŸãã
å®è£ æŠèŠ
ããããã¯ãå®éã®å®è£ ã«ã€ããŠè»œãã«è§£èª¬ããŠãããŸãã
ãã®ãµã€ãã®å®è£ ã§ç¹ã«æ³šç®ãã¹ãç¹ã¯ã段éçãªã¢ã«ãŽãªãºã åãæ¿ããšå¹ççãªäžŠååŠçã§ãã
JavaScriptå®è£ ã®ç¹åŸŽ
JavaScriptã§å®è£ ãããŠããã«ãé¢ãããããã®ãµã€ããé«éã«åäœããçç±ã¯ã以äžã®å·¥å€«ã«ãããŸãã
粟床ã«å¿ããã¢ã«ãŽãªãºã åãæ¿ã
ãºãŒã ã¬ãã«ã«å¿ããŠãèªåçã«æé©ãªã¢ã«ãŽãªãºã ãéžæããŸãã- 10^13åãŸã§: éåžžã®JavaScriptæ°å€ïŒfloat64ïŒã䜿ã£ãåºæ¬çãªãã³ãã«ããèšç®
- 10^300åãŸã§: BigIntã䜿ã£ãé«ç²ŸåºŠåç §ç¹èšç®ïŒfloat64ã§ã®æåæ³
- 10^300å以äž: BigInt + æ¡åŒµæµ®åå°æ°ç¹ã䜿ã£ãè¶ æ·±åºŠæåæ³
Web Workersã«ãã䞊ååŠç
ç»é¢ãå°ããªã¿ã€ã«ïŒéåžž32Ã32ãã¯ã»ã«ïŒã«åå²ããCPUã®å šã³ã¢æ°ã«åãããŠè€æ°ã®ã¯ãŒã«ãŒã§äžŠåèšç®ãè¡ããŸããããã«ãããã¡ã€ã³ã¹ã¬ãããåºãŸãããšãªããã¹ã ãŒãºãªãŠãŒã¶ãŒæäœãç¶æã§ããŸããæ®µéçãªæç»
æåã¯16x16ãã¯ã»ã«ã®äœè§£å床ã§çŽ æ©ãå šäœåã衚瀺ãããã®åŸåŸã ã«è§£å床ãäžããŠè©³çްãæã蟌ã¿ãŸããããã«ãããèšç®å®äºãåŸ ããã«å³åº§ã«ãã£ãŒãããã¯ãåŸãããŸãã
WebGPUå®è£ ã®åšå
å®éšçãªæ©èœãšããŠæäŸãããŠããWebGPUå®è£ ã§ãããWebWorkerã®ã¿ã®äžŠååãšã¯æ¯ã¹ç©ã«ãªããªãã»ã©é«éãªã¬ã³ããªã³ã°ãå®çŸããŠããŸãã管ç人ã®ãã¹ã¯ãããç°å¢ã§ã¯ãæå€§ã§10åè¿ãã®é«éåããããŠããå Žé¢ããããŸããã
åºå®å°æ°ç¹æŒç®ã®æŽ»çš
æ·±ããºãŒã ã§ã¯åº§æšã®ç²ŸåºŠã極ããŠéèŠã«ãªããŸãããã®ãµã€ãã§ã¯BigIntãåºç€ãšããåºå®å°æ°ç¹æŒç®ã©ã€ãã©ãªãç¬èªå®è£
ããå¿
èŠãªç²ŸåºŠãåçã«èª¿æŽããŠããŸãã
// 座æšå€æã®äŸïŒæŠå¿µçïŒ
canvas2complex(x, y) {
// ãã£ã³ãã¹åº§æšãé«ç²ŸåºŠãªè€çŽ æ°åº§æšã«å€æ
const scale = this.zoom.multiply(width).divide(4)
const r = fxp.fromNumber(x).subtract(width/2).divide(scale)
const i = fxp.fromNumber(y).subtract(height/2).divide(scale)
return [r.add(center[0]), i.add(center[1])]
} æè¡çãªå·¥å€«ã®è©³çް
ã¹ã ãŒãºçè²ïŒé£ç¶çè²ïŒæè¡
éåžžã®ãã³ãã«ããæç»ã§ã¯ãåæããªãç¹ã®ååŸ©åæ°ã«ãã£ãŠè²ã決ãããããåãè²ã®åž¯ç¶ãã¿ãŒã³ãçŸããŠçŸãããããŸããããã®ãµã€ãã§ã¯Smooth Coloringãšããæè¡ã䜿çšããŠãæ»ãããªã°ã©ããŒã·ã§ã³ãå®çŸããŠããŸãã
åºæ¬çãªèãæ¹ã¯ãååŸ©åæ°ãæŽæ°ã§ã¯ãªã宿°ãšããŠæ±ãããšã§ãã
// ã¹ã ãŒãºçè²ã®èšç®ïŒç°¡ç¥çïŒ
if (iter > 3) {
let log_zn = Math.log(zq) / 2; // |z|ã®å¯Ÿæ°
let nu = Math.log(log_zn / Math.log(2)) / Math.log(2);
iter = Math.floor(iter + 1 - nu); // 宿°ã®ååŸ©åæ°
} ããã«ããã飿¥ãããã¯ã»ã«éã§æ»ããã«è²ãå€åããçŸããã°ã©ããŒã·ã§ã³ãçãŸããŸãã
ã«ã©ãŒãã¬ããã·ã¹ãã
è²åœ©è±ããªè¡šçŸãå¯èœã«ãããããè€æ°ã®ã«ã©ãŒãã¬ãããåãæ¿ããããä»çµã¿ãå®è£ ããŠããŸãã
- ãã¬ããå¯åºŠ: è²ã®å€åé床ã調æŽ
- ãã¬ããå転: è²çžãå転ãããŠç°ãªãé°å²æ°ãæŒåº
- åèª¿äžæ¬¡è£é: è²ã®å¢çãæ»ããã«æ¥ç¶
ãã£ã³ã»ã«å¶åŸ¡ãšUIå¿çæ§
é·æéã®èšç®ã§ãæäœæ§ãä¿ã€ãããç¬ç¹ãªãã£ã³ã»ã«å¶åŸ¡ã·ã¹ãã ãå®è£ ããŠããŸãã
- ãžã§ãããŒã¯ã³æ¹åŒ: èšç®éå§æã«äžæã®ããŒã¯ã³ïŒBlob URLïŒãçæ
- éåæãã£ã³ã»ã«: ã¡ã€ã³ã¹ã¬ãããããŒã¯ã³ãç¡å¹åïŒ
revokeObjectURLïŒ - ã¯ãŒã«ãŒåŽæ€ç¥: 宿çã«ããŒã¯ã³ã®æå¹æ§ããã§ãã¯ããç¡å¹ãªãèšç®åæ¢
// ã¯ãŒã«ãŒåŽã§ã®ãã£ã³ã»ã«æ€ç¥ïŒæŠå¿µïŒ
function shouldStop(jobToken) {
if (!jobToken) return false;
try {
// åæXHRã§ããŒã¯ã³ã®æå¹æ§ããã§ãã¯
let xhr = new XMLHttpRequest();
xhr.open("GET", jobToken, false);
xhr.send(null);
return false; // æå¹
} catch (e) {
return true; // ç¡å¹ = ãã£ã³ã»ã«èŠæ±
}
} 段éçæç»ã®ä»çµã¿
å³åº§ã®ãã£ãŒãããã¯ãæäŸãããããè€æ°æ®µéã®æç»ãè¡ããŸãã
- 第1ãã¹: ç²ãè§£å床ïŒ4Ã4ãã¯ã»ã«ãªã©ïŒã§å šäœåãçŽ æ©ã衚瀺(æå€§ã§16x16ãã¯ã»ã«)
- 第2ãã¹: äžéè§£å床ã§è©³çްã远å
- æçµãã¹: ãã«è§£å床ã§å®å šãªç»åã宿
åãã¹ã¯åã®ãã¹ã®çµæã®äžã«éããŠæç»ããããŠãŒã¶ãŒã¯èšç®ã®é²è¡ç¶æ³ããªã¢ã«ã¿ã€ã ã§ç¢ºèªã§ããŸãã
å®éã«äœ¿ã£ãŠã¿ãã
åºæ¬æäœ
- ãºãŒã : ããŠã¹ãã€ãŒã«ãŸãã¯2æ¬æãã³ã
- ç§»å: ãã©ãã°æäœ
- èšå®å€æŽ: ç»é¢å³åŽã®ããã«ãã
- ãã©ã¡ãŒã¿ç¢ºèª: å°ãå°ããã§ãã
infoãšæžããŠãããã¿ã³ãã
é¢çœããã€ã³ããæ¢ããŠã¿ãã
ãã³ãã«ããéåã®å¢çç·ã¯ãã©ã¯ã¿ã«å³åœ¢ãªã®ã§ããã¡ããã¡ãè€éã§çŸããæ§é ãæã£ãŠããŸãããŸããæ¢çŽ¢ããŠãããšãå°ããªãã³ãã«ããéåã®è€è£œãç¡æ°ã«ååšããŸã(å³å¯ã«ã¯åã圢ã§ã¯ãªãããã§ãã)ãé¢çœã圢ãèŠã€ãã£ãããã«ã©ãŒãã¬ããã調æŽãããããŠæŽã«é åçãªæ¢çŽ¢ãé²ããŠã¿ãŸãããã
ãµã€ãã«ã¯ãI feel luckyããã¿ã³ãããã6ã€ã®è峿·±ããã€ã³ãã«ã©ã³ãã ã§ãžã£ã³ãã§ããŸãã
WebGPUæ©èœã詊ããŠã¿ã
察å¿ãã©ãŠã¶ïŒChrome/Edgeææ°çïŒã§ã¯ããGPU (exp.)ãããªã³ã«ããŠWebGPUæ©èœãäœéšã§ããŸããç¹ã«æ·±ããºãŒã ã¬ãã«(~10^300)ã§ãCPUå®è£ ãšã®é床差ã宿ã§ããã§ãããã
ãŸãšã
玹ä»ãããŠããã£ããã®ãµã€ãã¯ãåãªããã³ãã«ããéåãã¥ãŒã¢ãŒãè¶ ããŠãçŸä»£ã®ãã©ãŠã¶æè¡ãæå€§éã«æŽ»çšããæè¡çåäœã ãšæããŸããæåæ³ã«ããèšç®å¹çåãWeb WorkersãšWebGPUã«ãã䞊ååŠçãBigIntã䜿ã£ãé«ç²ŸåºŠæŒç®ãªã©ãå€ãã®å é²çãªæè¡ãçµã¿åããããŠããŸãã
髿 ¡æ°åŠã¬ãã«ã®ç¥èãããã°çè«ãçè§£ã§ããããã°ã©ãã³ã°ã®åºç€ãããã°å®è£ ã®è©³çްã远跡ã§ãããåŠç¿ææãšããŠãéåžžã«åªç§ãªãããžã§ã¯ãã ãšæããŸããçŸããæ°åŠãšææ°æè¡ã®èåãããã²å®éã«è§Šã£ãŠäœéšããŠã¿ãŠãã ããã
玹ä»ãããµã€ãã®GitHubãªããžããªâ

