<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Testing on NicoLabs</title>
		<link>http://blog.hellonico.info/ja/tags/testing/</link>
		<description>Recent content in Testing on NicoLabs</description>
		<generator>Hugo</generator>
		<language>ja</language>
		
		
		
		
			<lastBuildDate>Sun, 28 Jun 2026 11:30:00 +0900</lastBuildDate>
		
			<atom:link href="http://blog.hellonico.info/ja/tags/testing/index.xml" rel="self" type="application/rss+xml" />
			<item>
				<title>ConiのネイティブFloat32配列のためのハードコア・カオステスト</title>
				<link>http://blog.hellonico.info/ja/posts/coni/float32-chaos-testing/</link>
				<pubDate>Sun, 28 Jun 2026 11:30:00 +0900</pubDate>
				<guid>http://blog.hellonico.info/ja/posts/coni/float32-chaos-testing/</guid>
				<description>&lt;p&gt;ブラウザで高性能なアプリケーションを構築する場合、JavaScriptの汎用的な&lt;code&gt;Number&lt;/code&gt;型では不十分なことがよくあります。連続した生のメモリ配列が必要になるのです。Coni WASMでは、最も数学的に集約的なアプリケーションのために、ネイティブなWebAssemblyの&lt;code&gt;float32&lt;/code&gt;配列に大きく依存しています。&lt;/p&gt;&#xA;&lt;h3 id=&#34;float32は実際にconiのどこで使われているのか&#34;&gt;Float32は実際にConiのどこで使われているのか？&lt;/h3&gt;&#xA;&lt;p&gt;ネイティブの&lt;code&gt;float32&lt;/code&gt;配列（&lt;code&gt;make-float32-array&lt;/code&gt;、&lt;code&gt;f32-set!&lt;/code&gt;、&lt;code&gt;f32-get&lt;/code&gt;）は、Coniのパフォーマンス・レイヤーの絶対的なバックボーンです。これらは以下のような機能を駆動しています：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;WebGLジオメトリ:&lt;/strong&gt; &lt;a href=&#34;https://coni-lang.org/wasm-apps/apps/deep-focus-webgl/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreffer &#34;&gt;&lt;code&gt;deep-focus-webgl&lt;/code&gt;&lt;/a&gt;アプリでは、&lt;code&gt;float32&lt;/code&gt;配列を使用して80,000頂点のブレイン・マトリックス（240,000個の浮点数！）をネイティブに数学的に形成し、その後&lt;code&gt;js/float32-buffer&lt;/code&gt;を介して一撃でGPUに転送します。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;ゲームエンジンのパーティクルシステム:&lt;/strong&gt; &lt;code&gt;flappy-bird&lt;/code&gt;や&lt;code&gt;neon-boids&lt;/code&gt;のようなゲームでは、並行する&lt;code&gt;float32&lt;/code&gt;配列が数千のX/Y座標、速度、寿命を、ガベージコレクションの停止を発生させることなく追跡します。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;生（Raw）のDSPオーディオ:&lt;/strong&gt; 私たちの&lt;code&gt;sound-nodes&lt;/code&gt;シンセサイザーは、複雑なインパルス応答とノイズ波形をWebAudioチャンネルにマッピングする前に、&lt;code&gt;float32&lt;/code&gt;配列を使用してネイティブに計算します。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;バグ型強制とf64reinterpret_i64&#34;&gt;バグ：型強制と&lt;code&gt;f64.reinterpret_i64&lt;/code&gt;&lt;/h3&gt;&#xA;&lt;p&gt;これらの配列は非常に重要であるため、そこでのバグは壊滅的です。最近、正確な整数（例えば&lt;code&gt;150&lt;/code&gt;）を&lt;code&gt;f32-set!&lt;/code&gt;に渡すと、なぜか&lt;code&gt;0.0&lt;/code&gt;が返ってくるという問題を発見しました。&lt;/p&gt;&#xA;&lt;p&gt;何が起きていたのでしょうか？以前のバージョンのWASMコンパイラでは、整数を浮動小数点数のセッターに渡すと、コンパイラがビットを解釈するために誤って&lt;code&gt;f64.reinterpret_i64&lt;/code&gt;を使用し、基礎となる値を完全に文字化けさせていたのです。&lt;/p&gt;&#xA;&lt;h3 id=&#34;解決策float32カオステスト&#34;&gt;解決策：Float32カオステスト&lt;/h3&gt;&#xA;&lt;p&gt;私たちはコンパイラにパッチを当て、メモリへの挿入前に整数を正しく浮動小数点数に強制（コアーション）するようにしましたが、二度と退行（リグレッション）しないという保証が欲しかったのです。そこで&lt;strong&gt;カオステスト&lt;/strong&gt;の登場です。&lt;/p&gt;&#xA;&lt;p&gt;新しい&lt;code&gt;float32_coercion_test.coni&lt;/code&gt;スイートに、ハードコアなカオステストを構築しました。少数のハッピーパス（正常系）の数値をテストするだけでなく、巨大な配列を割り当て、決定論的な擬似ランダムループでそれを激しく叩きます。&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;deftest&lt;/span&gt; test-f32-chaos&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;float32配列の境界と型強制のためのハードコアなカオステスト&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#66d9ef&#34;&gt;let &lt;/span&gt;[size &lt;span style=&#34;color:#ae81ff&#34;&gt;1000&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        arr (&lt;span style=&#34;color:#a6e22e&#34;&gt;make-float32-array&lt;/span&gt; size)]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#66d9ef&#34;&gt;loop &lt;/span&gt;[i &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#66d9ef&#34;&gt;if &lt;/span&gt;(&amp;lt; i size)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#66d9ef&#34;&gt;let &lt;/span&gt;[&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#75715e&#34;&gt;;; 極端なエッジケースを混ぜて生成：&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          val (&lt;span style=&#34;color:#66d9ef&#34;&gt;if &lt;/span&gt;(= (&lt;span style=&#34;color:#a6e22e&#34;&gt;mod&lt;/span&gt; i &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;) &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;) (- &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; i)                   &lt;span style=&#34;color:#75715e&#34;&gt;;; 負の整数&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                (&lt;span style=&#34;color:#66d9ef&#34;&gt;if &lt;/span&gt;(= (&lt;span style=&#34;color:#a6e22e&#34;&gt;mod&lt;/span&gt; i &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;) &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;) (* i &lt;span style=&#34;color:#ae81ff&#34;&gt;10000&lt;/span&gt;)             &lt;span style=&#34;color:#75715e&#34;&gt;;; 大きな正の整数&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  (&lt;span style=&#34;color:#66d9ef&#34;&gt;if &lt;/span&gt;(= (&lt;span style=&#34;color:#a6e22e&#34;&gt;mod&lt;/span&gt; i &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;) &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;) (+ i &lt;span style=&#34;color:#ae81ff&#34;&gt;0.5&lt;/span&gt;)             &lt;span style=&#34;color:#75715e&#34;&gt;;; 正確なfloat32の分数&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;)))                                    &lt;span style=&#34;color:#75715e&#34;&gt;;; ゼロ（整数）&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#a6e22e&#34;&gt;f32-set!&lt;/span&gt; arr i val)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#a6e22e&#34;&gt;recur&lt;/span&gt; (+ i &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        nil))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;;; ... 検証ループ ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;極端な正の整数、負の境界値、純粋なゼロ、そして小数部を持つ浮動小数点数の残酷なミックスを意図的に1,000回&lt;code&gt;f32-set!&lt;/code&gt;関数に投げつけることで、WASMのトラップを回避し、型強制が防弾（完璧）であることを保証します。&lt;/p&gt;</description>
			</item>
	</channel>
</rss>
