<story><title>Writing a small ray tracer in Rust and Zig</title><url>https://nelari.us/post/raytracer_with_rust_and_zig/</url></story><parent_chain><item><author>skrebbel</author><text>This is an awesome post.&lt;p&gt;At the risk of shedding it to bikes, one point that the author makes is that Zig&amp;#x27;s lack of operator overloading makes him write vector math like this:&lt;p&gt;&lt;pre&gt;&lt;code&gt;    if (discriminant &amp;gt; 0.0) {
        &amp;#x2F;&amp;#x2F; I stared at this monster for a while to ensure I got it right
        return uv.sub(n.mul(dt)).mul(ni_over_nt).sub(n.mul(math.sqrt(discriminant)));
    }
&lt;/code&gt;&lt;/pre&gt;
He signs off with:&lt;p&gt;&amp;gt; &lt;i&gt;How do C programmers manage?&lt;/i&gt;&lt;p&gt;The answer is simple: we assign names to intermediate results. Now, I have absolutely no idea what that expression computes, because I suck at graphics programming and math in general. Please pretend that these are proper mathy terms:&lt;p&gt;&lt;pre&gt;&lt;code&gt;    if (discriminant &amp;gt; 0.0) {
        const banana = uv.sub(n.mul(dt))
        const apple = banana.mul(ni_over_nt)
        const pear = n.mul(math.sqrt(discriminant)
        return apple.sub(pear)
    }
&lt;/code&gt;&lt;/pre&gt;
I&amp;#x27;m convinced that there&amp;#x27;s a proper mathy&amp;#x2F;lighting-y word for each component in that expression. Of course this approach totally breaks down if you&amp;#x27;re copying expressions from papers or articles without understanding why they are correct (which is how I do all my graphics programming). I do find that naming variables is often a great way to force myself to grok what&amp;#x27;s going on.</text></item></parent_chain><comment><author>dahart</author><text>&amp;gt; I’m convinced that there’s a proper mathy &amp;#x2F; lighting-y word for each component in that expression.&lt;p&gt;Sometimes yes, but often no. Frequently this kind of expression is the result of solving an equation, so it’s just an expression.&lt;p&gt;Graphics people often use two approaches for sub-expressions:&lt;p&gt;- You can name them with the same letters that are in the expression, just with the punctuation &amp;amp; operators removed, for example:&lt;p&gt;&lt;pre&gt;&lt;code&gt;    const uvMinusNTimesDt = uv.sub(n.mul(dt))
&lt;/code&gt;&lt;/pre&gt;
- Alternatively, just like with equations, math people often freely assign single letter names to variables without worrying about semantic meaning.&lt;p&gt;&lt;pre&gt;&lt;code&gt;    const q = uv.sub(n.mul(dt))
&lt;/code&gt;&lt;/pre&gt;
Nothing really wrong with naming sub-expressions after fruits, or single letters, or spelling them out explicitly.&lt;p&gt;It might be worth reflecting on what the goals are with your naming, and whether it matters what they’re named. As software engineers, our biases lean toward making choices that improve readability and maintainability. But for a specific equation that will never change once it works correctly, our preconceived notions about good software design and best practices might not actually apply to this situation. It might be more important to document the source of the equation than to make the implementation readable.</text></comment>
<story><title>Writing a small ray tracer in Rust and Zig</title><url>https://nelari.us/post/raytracer_with_rust_and_zig/</url></story><parent_chain><item><author>skrebbel</author><text>This is an awesome post.&lt;p&gt;At the risk of shedding it to bikes, one point that the author makes is that Zig&amp;#x27;s lack of operator overloading makes him write vector math like this:&lt;p&gt;&lt;pre&gt;&lt;code&gt;    if (discriminant &amp;gt; 0.0) {
        &amp;#x2F;&amp;#x2F; I stared at this monster for a while to ensure I got it right
        return uv.sub(n.mul(dt)).mul(ni_over_nt).sub(n.mul(math.sqrt(discriminant)));
    }
&lt;/code&gt;&lt;/pre&gt;
He signs off with:&lt;p&gt;&amp;gt; &lt;i&gt;How do C programmers manage?&lt;/i&gt;&lt;p&gt;The answer is simple: we assign names to intermediate results. Now, I have absolutely no idea what that expression computes, because I suck at graphics programming and math in general. Please pretend that these are proper mathy terms:&lt;p&gt;&lt;pre&gt;&lt;code&gt;    if (discriminant &amp;gt; 0.0) {
        const banana = uv.sub(n.mul(dt))
        const apple = banana.mul(ni_over_nt)
        const pear = n.mul(math.sqrt(discriminant)
        return apple.sub(pear)
    }
&lt;/code&gt;&lt;/pre&gt;
I&amp;#x27;m convinced that there&amp;#x27;s a proper mathy&amp;#x2F;lighting-y word for each component in that expression. Of course this approach totally breaks down if you&amp;#x27;re copying expressions from papers or articles without understanding why they are correct (which is how I do all my graphics programming). I do find that naming variables is often a great way to force myself to grok what&amp;#x27;s going on.</text></item></parent_chain><comment><author>geokon</author><text>In my experience writing math code the intermediary values get quite goofy Ex: orthogonal-vector-to-plane-bisecting-input-vector-and-first-column-vector&lt;p&gt;But I rather use crazy descriptive names than hiding it away. Otherwise it gets quite incomprehensible when you reread it 3 months later&lt;p&gt;Anyone else hit this problem? I suspect most people just reference a paper or book and use the letters to match the source ( x&amp;#x2F;y&amp;#x2F;n&amp;#x2F;m&amp;#x2F;etc. )</text></comment>