<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Paho Blog</title>
    <description>A blog by Paho.</description>
    <link>http://paholg.com/</link>
    <atom:link href="http://paholg.com/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Fri, 02 Aug 2024 05:52:26 +0000</pubDate>
    <lastBuildDate>Fri, 02 Aug 2024 05:52:26 +0000</lastBuildDate>
    <generator>Jekyll v3.9.5</generator>
    
      <item>
        <title>Specializing tests</title>
        <description>&lt;p&gt;I recently published a new version of &lt;a href=&quot;https://crates.io/crates/dimensioned/&quot;&gt;dimensioned&lt;/a&gt;, a Rust
library for compile-time dimensional analysis. In so doing, I found a neat little pattern coupling
&lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/1210/&quot;&gt;specialization&lt;/a&gt; with test generation.&lt;/p&gt;

&lt;h2 id=&quot;the-problem&quot;&gt;The Problem&lt;/h2&gt;

&lt;p&gt;Among other things, dimensioned defines various unit systems, and many constants in each unit
system. All of this is performed by a build script that creates documentation at the same time. For
example, from &lt;a href=&quot;https://github.com/paholg/dimensioned/blob/master/src/build/si.rs&quot;&gt;this code&lt;/a&gt;,
&lt;a href=&quot;http://paholg.com/dimensioned/dimensioned/unit_systems/si/index.html&quot;&gt;this documentation&lt;/a&gt; is
created.&lt;/p&gt;

&lt;p&gt;In addition to generating documentation, we would like to generate some tests. One such test is to
compare constants across unit systems. If the same constant is defined in two unit systems, then we
should ensure that, when converted, they have the same value. This ensures both that the conversion
does what it should and that we haven’t made a typo when defining one of the constants.&lt;/p&gt;

&lt;p&gt;Given unit systems &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt;, it should be as easy as&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;assert_ulps_eq!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CONST&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CONST&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.into&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;epsilon&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;max_ulps&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note: Due to the non-associativity of floating point math, we can’t use
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assert_eq!&lt;/code&gt;. Instead, we verify that the constants are within 2
&lt;a href=&quot;https://en.wikipedia.org/wiki/Unit_in_the_last_place&quot;&gt;ULPS&lt;/a&gt; using the
&lt;a href=&quot;https://github.com/brendanzab/approx&quot;&gt;approx&lt;/a&gt; crate.&lt;/p&gt;

&lt;p&gt;Unfortunately, this fails. We can’t always convert from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt;. Or, sometimes we can convert
from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt;, but we can’t go from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt;. For example, we can convert from SI to the
centimeter-gram-second (CGS) system, but only from a subset of SI. We can’t convert a candela to
CGS; there’s no unit to represent it. In addition, it makes no sense to convert from CGS to SI, as
CGS represents electricity and magnitism units in terms of centimeters, grams, and seconds, so such
a conversion would be ambiguous.&lt;/p&gt;

&lt;p&gt;What this means is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;From&lt;/code&gt; isn’t implemented for all possible constants from all possible constants,
so we’ll get &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unimplemented&lt;/code&gt; errors for some of those &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;into()&lt;/code&gt; calls.&lt;/p&gt;

&lt;p&gt;We could set up either a whitelist or blacklist of what constants to compare, but
that would be a pain and a maintainibility nightmare. Fortunately, there’s a better way.&lt;/p&gt;

&lt;h2 id=&quot;the-solution&quot;&gt;The Solution&lt;/h2&gt;

&lt;p&gt;First, let’s make a trait for performing these comparisons:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CmpConsts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_eq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then, let’s implement it for when we can perform the conversion:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CmpConsts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;where&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;From&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
       &lt;span class=&quot;nn&quot;&gt;fmt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Debug&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
       &lt;span class=&quot;n&quot;&gt;Dimensioned&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;f64&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
       &lt;span class=&quot;n&quot;&gt;ApproxEq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Epsilon&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_eq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;assert_ulps_eq!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.into&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;epsilon&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;max_ulps&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So, when we call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a.test_eq(b)&lt;/code&gt;, we perform the same test as before, with the same problems. So far
we have done nothing but added a useless layer of abstraction. Yay us!&lt;/p&gt;

&lt;p&gt;However, with a default &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl&lt;/code&gt;, it suddenly becomes useful:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CmpConsts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_eq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CmpConsts&lt;/code&gt; is implemented for &lt;em&gt;any&lt;/em&gt; two types &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;B&lt;/code&gt;. If we can convert from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;B&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt;,
then we perform the test. If not, then we do nothing and move on. No more compiler errors, and we
can generate all the comparison tests we want!&lt;/p&gt;

&lt;p&gt;Feel free to discuss this on
&lt;a href=&quot;https://www.reddit.com/r/rust/comments/64u6kp/specializing_tests_a_pattern_for_generating_tests/&quot;&gt;reddit&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Tue, 11 Apr 2017 00:00:00 +0000</pubDate>
        <link>http://paholg.com/2017/04/11/spec-tests/</link>
        <guid isPermaLink="true">http://paholg.com/2017/04/11/spec-tests/</guid>
        
        
      </item>
    
      <item>
        <title>Dimensioned 0.6.0</title>
        <description>&lt;p&gt;Dimensioned, the Rust library that I have written for compile-time dimensional analysis, has just
reached version 0.6.0! This version change indicates a full rewrite of the library, and I think
that it has made it much more usable.&lt;/p&gt;

&lt;p&gt;I first started this crate before Rust had hit 1.0, and I fairly quickly realized that what I
wanted was not possible. With the advent of associated types, it became possible, and two years ago
I first announced its existence. It was really a proof of concept at that point; it was lacking in
ergonomics and some pretty important features.&lt;/p&gt;

&lt;p&gt;Today, I am excited to report that I believe it is more than a proof of concept, and is ready to be
used.&lt;/p&gt;

&lt;p&gt;Here are some notable changes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;No longer do we need a nightly compiler! Dimensioned now works fine on Rust stable, so long as it
is at least version 1.15.&lt;/li&gt;
  &lt;li&gt;Before, units were expressed by parametrizing a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dim&lt;/code&gt; struct. That struct is gone, which brings a
couple benefits. The first is ergonomics; a meter was expressed as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dim&amp;lt;Meter, V&amp;gt;&lt;/code&gt; in past
verions, and now it is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Meter&amp;lt;V&amp;gt;&lt;/code&gt;. The second benefit is in Rust’s orphan rules; if you create a
unit system, you now create the outermost struct, and so have full control over what you can
implement for it.&lt;/li&gt;
  &lt;li&gt;We no longer depend on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt;! Use dimensioned wherever you desire!&lt;/li&gt;
  &lt;li&gt;Thanks to type macros, derived units can now be defined without a build script or the &lt;em&gt;extremely&lt;/em&gt;
clunky syntax that was necessary before.&lt;/li&gt;
  &lt;li&gt;Unit systems! We have added unit systems and definitions for many derived units and
constants. They are still incomplete, though, and an area where dimensioned should improve on
soon.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have some time, check out the
&lt;a href=&quot;http://paholg.com/dimensioned/dimensioned/index.html&quot;&gt;documentation&lt;/a&gt;, or the
&lt;a href=&quot;https://github.com/paholg/dimensioned&quot;&gt;readme&lt;/a&gt;. I have tried to make these documents as clear and
comprehensive as possible, but I am sure that I have failed in at least some ways.&lt;/p&gt;

&lt;p&gt;Please feel free to submit an &lt;a href=&quot;https://github.com/paholg/dimensioned/issues&quot;&gt;issue on GitHub&lt;/a&gt; or
leave a comment on &lt;a href=&quot;https://www.reddit.com/r/rust/comments/5x9jgq/dimensioned_06_compiletime_dimensional_analysis/&quot;&gt;reddit&lt;/a&gt; or on the &lt;a href=&quot;https://users.rust-lang.org/t/dimensioned-0-6-compile-time-dimensional-analysis-much-nicer-than-before/9759&quot;&gt;Rust user’s forum&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Fri, 03 Mar 2017 00:00:00 +0000</pubDate>
        <link>http://paholg.com/2017/03/03/dimensioned_0.6/</link>
        <guid isPermaLink="true">http://paholg.com/2017/03/03/dimensioned_0.6/</guid>
        
        
      </item>
    
      <item>
        <title>Hello, Internet</title>
        <description>&lt;p&gt;Hello, I am Paho and this is my blog.&lt;/p&gt;

&lt;p&gt;I don’t have much to say here right now, so I’ll just leave you with a quotation:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;On two occasions I have been asked, “Pray, Mr. Babbage, if you put into the machine
  wrong figures, will the right answers come out?” … I am not able rightly to
  apprehend the kind of confusion of ideas that could provoke such a question.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;      - Charles Babbage&lt;/p&gt;
</description>
        <pubDate>Sun, 15 Feb 2015 00:00:00 +0000</pubDate>
        <link>http://paholg.com/2015/02/15/hello/</link>
        <guid isPermaLink="true">http://paholg.com/2015/02/15/hello/</guid>
        
        
      </item>
    
  </channel>
</rss>
