<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Azavea Labs &#187; Math</title>
	<atom:link href="http://www.azavea.com/blogs/labs/tag/math/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.azavea.com/blogs/labs</link>
	<description>Insight on what our engineers are doing</description>
	<lastBuildDate>Mon, 06 Feb 2012 22:32:15 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>Restricting Zoom with Multiple OL Basemaps</title>
		<link>http://www.azavea.com/blogs/labs/2011/09/restricting-zoom-with-multiple-ol-basemap/</link>
		<comments>http://www.azavea.com/blogs/labs/2011/09/restricting-zoom-with-multiple-ol-basemap/#comments</comments>
		<pubDate>Thu, 01 Sep 2011 18:41:42 +0000</pubDate>
		<dc:creator>Kenny Shepard</dc:creator>
				<category><![CDATA[Posts]]></category>
		<category><![CDATA[Bing]]></category>
		<category><![CDATA[DistrictBuilder]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Math]]></category>
		<category><![CDATA[openlayers]]></category>
		<category><![CDATA[openstreetmap]]></category>

		<guid isPermaLink="false">http://www.azavea.com/blogs/labs/?p=1595</guid>
		<description><![CDATA[As David recently posted, our team has been hard at work implementing DistrictBuilder, where we&#8217;ve been investing a great deal of effort on both performance and usability. One feature we added in the spring was the addition of basemaps to the user interface. Before this addition, users labored over drawing the perfect district configurations without a whole [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.azavea.com/districtbuilder"><img class="alignleft size-full wp-image-1783" style="border: 0px;" title="DistrictBuilder_logo" src="http://www.azavea.com/blogs/labs/wp-content/uploads/2011/07/DistrictBuilder_logo.png" alt="DistrictBuilder logo" width="206" height="66" align="left" hspace="4" vspace="4" /></a>As David <a title="Building Districts in Web-Time" href="http://www.azavea.com/blogs/labs/2011/08/building-districts-in-web-time/">recently posted</a>, our team has been hard at work implementing <a title="DistrictBuilder on GitHub" href="https://github.com/PublicMapping/DistrictBuilder">DistrictBuilder</a>, where we&#8217;ve been investing a great deal of effort on both performance and usability. One feature we added in the spring was the addition of basemaps to the user interface. Before this addition, users labored over drawing the perfect district configurations without a whole lot of context of the surrounding environment (e.g. roads, water boundaries, etc.). When the time came to add a basemap to the application, it didn&#8217;t feel right restricting it to a single type of map, or even a single provider. We wanted to allow for users to have the choice to select the best map for the task at hand. Could an application promoting democracy really have it any other way?</p>
<p>We set out to support several base map options as well as any combination of options, including:</p>
<ul>
<li>Bing Maps (satellite, roads and hybrid)</li>
<li>GoogleMaps (satellite, roads and hybrid)</li>
<li>ArcGIS Online (any of several maps)</li>
<li>OpenStreetMap</li>
</ul>
<p>Since DistrictBuilder needs to be flexible enough to meet the needs of users and administrators in a variety of situations, we decided on a two step approach to basemap configuration. First, the administrator specifies, in the configuration file, which of the combinations of map providers and map types are allowed to be selected. Then DistrictBuilder presents all of the configured options to the user, where they can be toggled among at any time while a plan is being viewed or edited.</p>
<p>Here&#8217;s an example of an instance configured with an <a title="OpenStreetMap" href="http://www.openstreetmap.org/" target="_blank">OpenStreetMap</a> road layer, a <a title="Bing Maps" href="http://www.bing.com/maps/">Bing</a> hybrid layer, and a <a title="Google Maps" href="http://lmgtfy.com/?q=google+maps">Google</a> satellite layer:</p>
<p style="text-align: center;"><img class="size-full wp-image-1629 aligncenter" title="Road, Hybrid, and Satellite" src="http://www.azavea.com/blogs/labs/wp-content/uploads/2011/07/rhs.png" alt="Road, Hybrid, and Satellite" width="253" height="216" /></p>
<p>Here&#8217;s another example with only road layers &#8212; one for each of the three configured providers:</p>
<p style="text-align: center;"><img class="size-full wp-image-1632 aligncenter" title="Roads for three vendors" src="http://www.azavea.com/blogs/labs/wp-content/uploads/2011/07/rrr.png" alt="Roads for three vendors" width="302" height="202" /></p>
<p>DistrictBuilder currently allows the configuration of basemaps using permutations of each of the three vendors and three map types described above. Adding more options is a relatively easy task, however. With the launch of <a title="Fix Philly Districts" href="http://fixphillydistricts.com">Fix Philly Districts</a>, we wanted the basemap colors to be slightly more muted than the above options, and ended up adding support for the <a title="ArcGIS Online" href="http://www.azavea.com/blogs/labs/2011/02/openlayers-and-arcgis-com/" target="_blank">ArcGIS Online</a> World Topographic Map. We also experimented with the Google Maps V3 custom <a title="Google Styled Maps " href="http://code.google.com/apis/maps/documentation/javascript/styling.html">styling API</a>, which looked great, but introduced performance problems when panning and zooming (animations).</p>
<p>There were, of course, some hoops that needed to be jumped through in order to get all of these basemaps behaving correctly on the same map, which will be discussed below. I&#8217;ve extracted the logic required to do so into a small demo that can be viewed/downloaded <a href="http://s3.azavea.com.s3.amazonaws.com/com.azavea.www/blogs/multiple_base_layers/demo.html">here</a>. The demo has also been embedded into this post, and can be interacted with without going anywhere:</p>
<p><iframe src="http://s3.azavea.com.s3.amazonaws.com/com.azavea.www/blogs/multiple_base_layers/demo.html" frameborder="0" width="100%" height="370"></iframe></p>
<h1></h1>
<h1>Zoom Levels</h1>
<p>Many of the challenges that needed to be overcome to get this working correctly were brought about because we needed to restrict the zoom levels to the area at hand. We wanted to eliminate superfluous zoom levels to ensure the user was always operating within the appropriate boundaries (note: it is not done in this demo, but in DistrictBuilder we also restrict the extent with the &#8216;restrictedExtent&#8217; map parameter, so users can&#8217;t even pan outside of the area).</p>
<p>One difficulty with setting zoom levels on the different layers is that the layers don&#8217;t use zoom parameters consistently. In Bing (the VirtualEarth layer), minZoomLevel and maxZoomLevel are needed. In Google, minZoomLevel is needed, but it requires numZoomLevels instead of maxZoomLevel. And in OpenStreetMap (the OSM layer), well&#8230;no combination of those seem to work &#8212; we needed to slightly modify the XYZ layer (OSM&#8217;s base class) to allow maxResolution to be changed based on the minZoomLevel. To see how this is done, view the demo source. With that change in place, the list of required layer parameters is as follows:</p>
<ul>
<li><strong>Bing</strong> &#8211; minZoomLevel, maxZoomLevel, projection, sphericalMercator, maxExtent</li>
<li><strong>Google</strong> &#8211; numZoomLevel, minZoomLevel, projection, sphericalMercator, maxExtent</li>
<li><strong>OpenStreetMap</strong> - numZoomLevel, minZoomLevel, projection</li>
</ul>
<h1>Coordinate Systems</h1>
<p>We also faced some problems related to coordinate systems. DistrictBuilder uses <a title="GeoServer" href="http://geoserver.org">GeoServer</a> and <a title="GeoWebCache" href="http://geowebcache.org/">GeoWebCache</a> to serve up WMS layers. The coordinate system of our data is one version of the the <a title="GIS Standards gone crazy" href="http://viswaug.wordpress.com/2009/04/01/gis-standards-gone-crazy-epsg-especially/">ever-changing</a> &#8220;Popular Visualization CRS / Mercator&#8221; projection. We needed to match up the OpenLayers projection to the one used on our data, or else we were seeing slight offsets on our overlays. Unfortunately, the &#8216;projection&#8217; layer parameter isn&#8217;t always used within the layers correctly. For example, any layer using the SphericalMercator class gets its projection automatically hardcoded to 900913. We needed to make a slight modification to the SphericalMercator class to allow the &#8216;projection&#8217; parameter to carry through. This can be seen by viewing the demo source.</p>
<h1>Bonus: Math Time!</h1>
<p>One interesting part about implementing zoom restriction was that we needed it to work in any instance of DistrictBuilder &#8212; from large states to small towns, which may have vastly different extents. Instead of having an administrator figure out the proper minimum zoom level, we calculate it automatically based on the extent, which requires a little bit of basic algebra.</p>
<p>For Philadelphia, the extent of our area is:</p>
<pre>[-8397913.926216, 4842467.609439, -8329120.600772, 4895973.529229]</pre>
<p>In DistrictBuilder, we calculate this dynamically on the server side (using Django) by filtering all of the geounits in the database and calling the &#8216;extent&#8217; function on the query set. For the demo, this is hardcoded. Here&#8217;s how to transform this extent into a Spherical Mercator minZoomLevel:</p>
<ul>
<li>Find the width of the area in meters.</li>
</ul>
<pre>var studyWidthMeters = extent[2] - extent[0];</pre>
<ul>
<li>Find the width of the map in pixels. In the demo, this is hardcoded, because we are setting the div size of the map. In DistrictBuilder, the map takes up the whole screen, and this value is calculated on the fly based on the size of the div in which the map occupies.</li>
</ul>
<pre>var mapWidthPixels = 450;</pre>
<ul>
<li>Find the map resolution, or meters per pixel.</li>
</ul>
<pre>var resolution = studyWidthMeters / mapWidthPixels;</pre>
<ul>
<li>Find the maximum map resolution. In Spherical Mercator, the maximum resolution is one 256&#215;256 tile taking up the entire circumference Earth. So dividing the circumference of the earth (~40,000km) by 256 gives us the maximum meters per pixel, which is a constant.</li>
</ul>
<pre>var maxResolution = 156543.033928;</pre>
<ul>
<li>Spherical Mercator zoom levels work like a pyramid. Each zoom breaks the current tile up into a 2&#215;2 group of 256&#215;256 tiles, essentially halving the resolution each time. Therefore, finding the resolution at a given zoom level looks like this:</li>
</ul>
<pre>maxresolution / 2^zoom = resolution</pre>
<ul>
<li>We know the resolution and max resolution already, and need to find the zoom:</li>
</ul>
<pre>zoom = log(maxresolution/resolution)/log(2)</pre>
<ul>
<li>Or in javascript:</li>
</ul>
<pre>var minZoom = Math.log(maxResolution / resolution) / Math.LN2;</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.azavea.com/blogs/labs/2011/09/restricting-zoom-with-multiple-ol-basemap/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Scala&#8217;s Numeric type class (Pt. 2)</title>
		<link>http://www.azavea.com/blogs/labs/2011/06/scalas-numeric-type-class-pt-2/</link>
		<comments>http://www.azavea.com/blogs/labs/2011/06/scalas-numeric-type-class-pt-2/#comments</comments>
		<pubDate>Fri, 24 Jun 2011 18:53:38 +0000</pubDate>
		<dc:creator>Erik Osheim</dc:creator>
				<category><![CDATA[Posts]]></category>
		<category><![CDATA[benchmark]]></category>
		<category><![CDATA[fractional]]></category>
		<category><![CDATA[generics]]></category>
		<category><![CDATA[integral]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Math]]></category>
		<category><![CDATA[numeric]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[scala]]></category>
		<category><![CDATA[specialization]]></category>
		<category><![CDATA[type class]]></category>

		<guid isPermaLink="false">http://www.azavea.com/blogs/labs/?p=1513</guid>
		<description><![CDATA[In my last blog post I introduced the idea of type classes (and scala.math.Numeric in particular). I demonstrated basic usage but also alluded to some problems. In this blog post I will explain the problems, talk about specialization, and introduce a version of Numeric that solves many of the problems (com.azavea.math.Numeric). I will also present [...]]]></description>
			<content:encoded><![CDATA[<p>In my <a href="http://www.azavea.com/blogs/labs/2011/06/scalas-numeric-type-class-pt-1/">last blog post</a> I introduced the idea of type classes (and <tt>scala.math.Numeric</tt> in particular). I demonstrated basic usage but also alluded to some problems. In this blog post I will explain the problems, talk about specialization, and introduce a version of Numeric that solves many of the problems (<a href="https://github.com/azavea/numeric"><tt>com.azavea.math.Numeric</tt></a>). I will also present some benchmarking numbers.</p>
<h1>Icky Syntax</h1>
<p>The most noticeable problem when using Numeric (at least in 2.8) is the syntax. As Kevin Wright alluded to in a comment on the last post, you can include the Numeric type class in two ways: via a context bound on your type parameter (<tt>A</tt>) or as an implicit argument.</p>
<p>In my earlier examples I used the implicit argument because I thought it was easier to follow (especially for those who are new to implicits) and it bound the instance of the type class to a named variable (<tt>n</tt>). But you can also use the type bound syntax, which makes the function declaration a bit cleaner looking.</p>

<div class="wp_syntax"><div class="code"><pre class="scala" style="font-family:monospace;"><span style="color: #008000; font-style: italic;">// this makes it obvious that n is an instance of Numeric[A]</span>
<span style="color: #008000; font-style: italic;">// and gives us a reference to use.</span>
<span style="color: #0000ff; font-weight: bold;">def</span> square<span style="color: #F78811;">&#91;</span>A<span style="color: #F78811;">&#93;</span><span style="color: #F78811;">&#40;</span>a<span style="color: #000080;">:</span>A<span style="color: #F78811;">&#41;</span><span style="color: #F78811;">&#40;</span><span style="color: #0000ff; font-weight: bold;">implicit</span> n<span style="color: #000080;">:</span>Numeric<span style="color: #F78811;">&#91;</span>A<span style="color: #F78811;">&#93;</span><span style="color: #F78811;">&#41;</span> <span style="color: #000080;">=</span> <span style="color: #F78811;">&#123;</span>
  n.<span style="color: #000000;">times</span><span style="color: #F78811;">&#40;</span>a, a<span style="color: #F78811;">&#41;</span>
<span style="color: #F78811;">&#125;</span>
&nbsp;
<span style="color: #008000; font-style: italic;">// this definition is a bit cleaner looking.</span>
<span style="color: #008000; font-style: italic;">// implicitly[] searches for an implicit Numeric[A] instance.</span>
<span style="color: #008000; font-style: italic;">// unfortunately the body of the function is less clean.</span>
<span style="color: #0000ff; font-weight: bold;">def</span> square<span style="color: #F78811;">&#91;</span>A<span style="color: #000080;">:</span>Numeric<span style="color: #F78811;">&#93;</span><span style="color: #F78811;">&#40;</span>a<span style="color: #000080;">:</span>A<span style="color: #F78811;">&#41;</span> <span style="color: #000080;">=</span> <span style="color: #F78811;">&#123;</span>
  implicitly<span style="color: #F78811;">&#91;</span>Numeric<span style="color: #F78811;">&#91;</span>A<span style="color: #F78811;">&#93;</span><span style="color: #F78811;">&#93;</span>.<span style="color: #000000;">times</span><span style="color: #F78811;">&#40;</span>a, a<span style="color: #F78811;">&#41;</span>
<span style="color: #F78811;">&#125;</span></pre></div></div>

<p>Either way, you&#8217;re still writing things like <tt>n.times(a, a)</tt> rather than <tt>a * a</tt>. Fortunately, Scala 2.9 introduced some nice new implicit parameters that allow us to use infix operators:</p>

<div class="wp_syntax"><div class="code"><pre class="scala" style="font-family:monospace;"><span style="color: #0000ff; font-weight: bold;">import</span> Numeric.<span style="color: #000000;">Implicits</span>.<span style="color: #000080;">_</span>
<span style="color: #0000ff; font-weight: bold;">def</span> square<span style="color: #F78811;">&#91;</span>A<span style="color: #000080;">:</span>Numeric<span style="color: #F78811;">&#93;</span><span style="color: #F78811;">&#40;</span>a<span style="color: #000080;">:</span>A<span style="color: #F78811;">&#41;</span> <span style="color: #000080;">=</span> a <span style="color: #000080;">*</span> a</pre></div></div>

<h1>Confusing Conversions</h1>
<p>The implicits providing infix operators are definitely a big improvement! But while they are nice for simple cases like the previous one they can end up confusing the issue a little bit:</p>

<div class="wp_syntax"><div class="code"><pre class="scala" style="font-family:monospace;"><span style="color: #0000ff; font-weight: bold;">def</span> twice<span style="color: #F78811;">&#91;</span>A<span style="color: #000080;">:</span>Numeric<span style="color: #F78811;">&#93;</span><span style="color: #F78811;">&#40;</span>a<span style="color: #000080;">:</span>A<span style="color: #F78811;">&#41;</span> <span style="color: #000080;">=</span> a <span style="color: #000080;">*</span> <span style="color: #F78811;">2</span>
<span style="color: #008000; font-style: italic;">//error: could not find implicit value for parameter num:</span>
<span style="color: #008000; font-style: italic;">// scala.math.Numeric[Any]</span></pre></div></div>

<p>What&#8217;s going on here? The problem is that <tt>*</tt> is mapped to <tt>Numeric.times(a:A, b:A)</tt> but the second argument we provided isn&#8217;t an <tt>A</tt>, it&#8217;s an <tt>Int</tt>. In Java (and Scala) we are used to being able to mix numeric types like <tt>double</tt> and <tt>int</tt> without worrying: the result will be promoted to <tt>double</tt> (the type with the widest range). Unfortunately, as written Numeric isn&#8217;t able to do these kinds of things and instead types must be converted explicitly. Numeric does provide two special methods, <tt>zero</tt> and <tt>one</tt> which allow you to get those values for all its types.</p>

<div class="wp_syntax"><div class="code"><pre class="scala" style="font-family:monospace;"><span style="color: #008000; font-style: italic;">// use Numeric.one to get the correct type</span>
<span style="color: #0000ff; font-weight: bold;">def</span> once<span style="color: #F78811;">&#91;</span>A<span style="color: #000080;">:</span>Numeric<span style="color: #F78811;">&#93;</span><span style="color: #F78811;">&#40;</span>a<span style="color: #000080;">:</span>A<span style="color: #F78811;">&#41;</span><span style="color: #000080;">:</span>A <span style="color: #000080;">=</span> a <span style="color: #000080;">*</span> implicitly<span style="color: #F78811;">&#91;</span>Numeric<span style="color: #F78811;">&#91;</span>A<span style="color: #F78811;">&#93;</span><span style="color: #F78811;">&#93;</span>.<span style="color: #000000;">one</span>
&nbsp;
<span style="color: #008000; font-style: italic;">// convert 2 to be the correct type</span>
<span style="color: #0000ff; font-weight: bold;">def</span> twice<span style="color: #F78811;">&#91;</span>A<span style="color: #000080;">:</span>Numeric<span style="color: #F78811;">&#93;</span><span style="color: #F78811;">&#40;</span>a<span style="color: #000080;">:</span>A<span style="color: #F78811;">&#41;</span><span style="color: #000080;">:</span>A <span style="color: #000080;">=</span> a <span style="color: #000080;">*</span> implicitly<span style="color: #F78811;">&#91;</span>Numeric<span style="color: #F78811;">&#91;</span>A<span style="color: #F78811;">&#93;</span><span style="color: #F78811;">&#93;</span>.<span style="color: #000000;">fromInt</span><span style="color: #F78811;">&#40;</span><span style="color: #F78811;">2</span><span style="color: #F78811;">&#41;</span>
&nbsp;
<span style="color: #008000; font-style: italic;">// convert a to be an Int</span>
<span style="color: #0000ff; font-weight: bold;">def</span> thrice<span style="color: #F78811;">&#91;</span>A<span style="color: #000080;">:</span>Numeric<span style="color: #F78811;">&#93;</span><span style="color: #F78811;">&#40;</span>a<span style="color: #000080;">:</span>A<span style="color: #F78811;">&#41;</span><span style="color: #000080;">:</span>Int <span style="color: #000080;">=</span> a.<span style="color: #000000;">toInt</span> <span style="color: #000080;">*</span> <span style="color: #F78811;">3</span></pre></div></div>

<p>There&#8217;s also no good way to combine two different generic Numeric types, other than converting to a common concrete type (e.g. <tt>Double</tt>). You could imagine Numeric providing something like <tt>fromType[B]</tt> (as well as things like <tt>fromDouble</tt>) but currently it doesn&#8217;t.</p>

<div class="wp_syntax"><div class="code"><pre class="scala" style="font-family:monospace;"><span style="color: #0000ff; font-weight: bold;">def</span> combine<span style="color: #F78811;">&#91;</span>A<span style="color: #000080;">:</span>Numeric, B<span style="color: #000080;">:</span>Numeric<span style="color: #F78811;">&#93;</span><span style="color: #F78811;">&#40;</span>a<span style="color: #000080;">:</span>A, b<span style="color: #000080;">:</span>B<span style="color: #F78811;">&#41;</span> <span style="color: #000080;">=</span> a + b
<span style="color: #008000; font-style: italic;">//error: could not find implicit value for parameter num:</span>
<span style="color: #008000; font-style: italic;">// scala.math.Numeric[Any]</span>
&nbsp;
<span style="color: #008000; font-style: italic;">// this works</span>
<span style="color: #0000ff; font-weight: bold;">def</span> combine<span style="color: #F78811;">&#91;</span>A<span style="color: #000080;">:</span>Numeric, B<span style="color: #000080;">:</span>Numeric<span style="color: #F78811;">&#93;</span><span style="color: #F78811;">&#40;</span>a<span style="color: #000080;">:</span>A, b<span style="color: #000080;">:</span>B<span style="color: #F78811;">&#41;</span> <span style="color: #000080;">=</span> a.<span style="color: #000000;">toDouble</span> + b.<span style="color: #000000;">toDouble</span>
&nbsp;
<span style="color: #008000; font-style: italic;">// this would be nice (for some definition of nice)</span>
<span style="color: #008000; font-style: italic;">// but it doesn't work</span>
<span style="color: #0000ff; font-weight: bold;">def</span> combine<span style="color: #F78811;">&#91;</span>A<span style="color: #000080;">:</span>Numeric, B<span style="color: #000080;">:</span>Numeric<span style="color: #F78811;">&#93;</span><span style="color: #F78811;">&#40;</span>a<span style="color: #000080;">:</span>A, b<span style="color: #000080;">:</span>B<span style="color: #F78811;">&#41;</span><span style="color: #000080;">:</span>A <span style="color: #000080;">=</span> <span style="color: #F78811;">&#123;</span>
  a + implicitly<span style="color: #F78811;">&#91;</span>Numeric<span style="color: #F78811;">&#91;</span>A<span style="color: #F78811;">&#93;</span><span style="color: #F78811;">&#93;</span>.<span style="color: #000000;">fromType</span><span style="color: #F78811;">&#91;</span>B<span style="color: #F78811;">&#93;</span><span style="color: #F78811;">&#40;</span>b<span style="color: #F78811;">&#41;</span>
<span style="color: #F78811;">&#125;</span></pre></div></div>

<h1>Performance</h1>
<p>The most disappointing thing (in my opinion) about using <tt>scala.math.Numeric</tt> is its performance. In some cases it performs adequately, but in most cases it is very slow: actual algorithms written with Numeric tend to be 6-30 times slower than their direct counterparts (depending on what exactly they do). Some rough observations are that the comparison operators (e.g. <tt>&gt;</tt>) seem to be slower than the math operators (e.g. <tt>*</tt>), and performance does depend on which type you end up using: <tt>Numeric[Double]</tt> does relatively well (compared to the same code written for <tt>Double</tt>). <tt>Numeric[Int]</tt> does very badly compared to code written for <tt>Int</tt>.</p>
<h1>Specialization to the Rescue!</h1>
<p>Fortunately, Scala itself contains the tool to fix Numeric&#8217;s performance problems: specialization. Specialization was first described in the paper <a href="http://lamp.epfl.ch/~dragos/files/scala-spec.pdf">Compiling Generics Through User-Directed Type Specialization</a> by Iulian Dragos and Martin Odersky and was introduced in Scala 2.8 via the <tt>@specialized</tt> annotation. <a href="http://www.scala-notes.org/2011/04/specializing-for-primitive-types/">Other articles</a> have been written explaining specialization, but I will give another brief one here.</p>
<p>When writing generic functions in Scala (as well as Java), the compiler generates one implementation that supports all possible argument types (e.g. <tt>java.lang.Object</tt>). This fine for Java [1] since all the valid types you could use with your generic function are guaranteed to be subclasses of java.lang.Object. If you remember my first post, you&#8217;ll recall how we had to create boxed instances of <tt>java.lang.Integer</tt> to hold <tt>int</tt> values when using generics.</p>
<p>Unfortunately for Scala it means that using generic functions with value-types (e.g.<tt>Int</tt>) is much slower than functions implemented directly in terms of the value-type itself, since there is a single implementation which requires its arguments to be objects (e.g. boxed).</p>
<p>The <tt>@specialized</tt> annotation allows the Scala compiler to generate separate implementations of the generic function: one for all the reference types (inheriting from<tt>AnyRef</tt>) and one for each of the value types we choose to specialize over (e.g. <tt>Char</tt>, <tt>Double</tt>, <tt>Int</tt>). So if we have a generic function <tt>foo[A](a:A): A</tt> the compiler will generate other functions on primitive types, for instance <tt>fooInt(a:Int): Int</tt>, <tt>fooDouble(a:Double): Double</tt>, etc. And when we write <tt>foo(33)</tt> the compiler will translate that code into <tt>fooInt(33)</tt>.</p>
<p>Since Scala hides boxing/unboxing, specialization doesn&#8217;t make the code look nicer. But it makes a huge difference in performance: Dragos and Odersky report a 22-40x speed up in micro-benchmarks!</p>
<h1>Specializing Numeric</h1>
<p>Soon after specialization was added to Scala 2.8, people began discussing specializing Numeric. Searching Google I find names like Jason Zaugg, Iulian Dragos, and others talking about it. Andreas Flierl emailed the scala-language mailing list on January 3, 2011 with some early tests which got me interested in working on this. So I don&#8217;t want to claim any credit for the amazing work done on implementing <tt>@specialized</tt> or even the idea of specializing Numeric.</p>
<p>Starting with Andreas&#8217; code I began working on building a specialized Numeric, with the goal of making all its operations as fast as direct implementations. There were a bunch of ways that the code needed to be restructured (which I may discuss in a later article) and I learned a ton about implicits, typeclasses, and profiling Scala code. The code is available at: https://github.com/azavea/numeric along with the tests I&#8217;m running. The results follow, but the short story is that with the exception of implicit infix operators all <tt>com.azavea.math.Numeric</tt> code runs just as fast as the direct implementations.</p>
<h1>The Numbers</h1>
<style type="text/css">
    td { text-align: right; padding: 4px; }
    td { border: 1px solid black; padding: 4px; }
    thead { background-color: lightgrey; }
    .na { border: 0px; }
    .base { border: 0px; }
    .sep { border: 0px; colspan="6" }
    .name { background-color: lightgrey; }
    .great { background-color: #99ccff; }
    .good { background-color: #99ff99; }
    .ok { background-color: #ccff99; }
    .poor { background-color: #ffff99; }
    .bad { background-color: #ffcc99; }
    .awful { background-color: #ff9999; }
  </style>
<table>
<thead>
<tr>
<td>test</td>
<td>direct (ms)</td>
<td colspan="2">new (ms)</td>
<td colspan="2">old (ms)</td>
</tr>
</thead>
<tr>
<td class='sep' /></tr>
<tr>
<td class='name'>from-int-to-int</td>
<td class='base'>22.3</td>
<td class='good'>22.0</td>
<td class='good'> 0.99x</td>
<td class='bad'>169.1</td>
<td class='bad'> 7.60x</td>
</tr>
<tr>
<td class='name'>from-int-to-long</td>
<td class='base'>38.0</td>
<td class='good'>37.3</td>
<td class='good'> 0.98x</td>
<td class='bad'>244.5</td>
<td class='bad'> 6.43x</td>
</tr>
<tr>
<td class='name'>from-int-to-float</td>
<td class='base'>23.1</td>
<td class='good'>23.0</td>
<td class='good'> 0.99x</td>
<td class='bad'>202.5</td>
<td class='bad'> 8.76x</td>
</tr>
<tr>
<td class='name'>from-int-to-double</td>
<td class='base'>40.0</td>
<td class='good'>37.9</td>
<td class='good'> 0.95x</td>
<td class='bad'>271.4</td>
<td class='bad'> 6.78x</td>
</tr>
<tr>
<td class='sep' /></tr>
<tr>
<td class='name'>adder-int</td>
<td class='base'>12.6</td>
<td class='good'>13.5</td>
<td class='good'> 1.07x</td>
<td class='awful'>145.3</td>
<td class='awful'>11.50x</td>
</tr>
<tr>
<td class='name'>adder-long</td>
<td class='base'>21.1</td>
<td class='good'>21.4</td>
<td class='good'> 1.01x</td>
<td class='bad'>153.8</td>
<td class='bad'> 7.28x</td>
</tr>
<tr>
<td class='name'>adder-float</td>
<td class='base'>27.5</td>
<td class='good'>27.8</td>
<td class='good'> 1.01x</td>
<td class='good'>27.5</td>
<td class='good'> 1.00x</td>
</tr>
<tr>
<td class='name'>adder-double</td>
<td class='base'>27.3</td>
<td class='good'>26.0</td>
<td class='good'> 0.95x</td>
<td class='good'>27.5</td>
<td class='good'> 1.01x</td>
</tr>
<tr>
<td class='sep' /></tr>
<tr>
<td class='name'>array-total-int</td>
<td class='base'>8.3</td>
<td class='good'>8.3</td>
<td class='good'> 1.00x</td>
<td class='awful'>246.4</td>
<td class='awful'>29.86x</td>
</tr>
<tr>
<td class='name'>array-total-long</td>
<td class='base'>11.5</td>
<td class='good'>11.1</td>
<td class='good'> 0.97x</td>
<td class='awful'>310.8</td>
<td class='awful'>27.02x</td>
</tr>
<tr>
<td class='name'>array-total-float</td>
<td class='base'>16.1</td>
<td class='good'>16.6</td>
<td class='good'> 1.03x</td>
<td class='awful'>217.1</td>
<td class='awful'>13.47x</td>
</tr>
<tr>
<td class='name'>array-total-double</td>
<td class='base'>17.3</td>
<td class='good'>16.8</td>
<td class='good'> 0.97x</td>
<td class='awful'>216.8</td>
<td class='awful'>12.57x</td>
</tr>
<tr>
<td class='sep' /></tr>
<tr>
<td class='name'>array-rescale-int</td>
<td class='base'>27.1</td>
<td class='good'>26.8</td>
<td class='good'> 0.99x</td>
<td class='awful'>357.8</td>
<td class='awful'>13.19x</td>
</tr>
<tr>
<td class='name'>array-rescale-long</td>
<td class='base'>24.6</td>
<td class='good'>24.6</td>
<td class='good'> 1.00x</td>
<td class='awful'>540.6</td>
<td class='awful'>21.95x</td>
</tr>
<tr>
<td class='name'>array-rescale-float</td>
<td class='base'>59.3</td>
<td class='good'>59.6</td>
<td class='good'> 1.01x</td>
<td class='bad'>366.9</td>
<td class='bad'> 6.19x</td>
</tr>
<tr>
<td class='name'>array-rescale-double</td>
<td class='base'>91.4</td>
<td class='good'>91.1</td>
<td class='good'> 1.00x</td>
<td class='poor'>394.3</td>
<td class='poor'> 4.31x</td>
</tr>
<tr>
<td class='sep' /></tr>
<tr>
<td class='name'>find-max-int</td>
<td class='base'>16.6</td>
<td class='good'>16.9</td>
<td class='good'> 1.02x</td>
<td class='awful'>166.0</td>
<td class='awful'> 9.98x</td>
</tr>
<tr>
<td class='name'>find-max-long</td>
<td class='base'>12.1</td>
<td class='good'>12.1</td>
<td class='good'> 1.00x</td>
<td class='awful'>199.6</td>
<td class='awful'>16.46x</td>
</tr>
<tr>
<td class='name'>find-max-float</td>
<td class='base'>22.6</td>
<td class='good'>22.4</td>
<td class='good'> 0.99x</td>
<td class='bad'>187.8</td>
<td class='bad'> 8.30x</td>
</tr>
<tr>
<td class='name'>find-max-double</td>
<td class='base'>23.9</td>
<td class='good'>23.5</td>
<td class='good'> 0.98x</td>
<td class='bad'>195.6</td>
<td class='bad'> 8.19x</td>
</tr>
<tr>
<td class='sep' /></tr>
<tr>
<td class='name'>quicksort-int</td>
<td class='base'>155.9</td>
<td class='bad'>820.1</td>
<td class='bad'> 5.26x</td>
<td class='bad'>929.0</td>
<td class='bad'> 5.96x</td>
</tr>
<tr>
<td class='name'>quicksort-long</td>
<td class='base'>1105.0</td>
<td class='ok'>1326.4</td>
<td class='ok'> 1.20x</td>
<td class='ok'>1238.6</td>
<td class='ok'> 1.12x</td>
</tr>
<tr>
<td class='name'>quicksort-float</td>
<td class='base'>228.6</td>
<td class='bad'>1493.0</td>
<td class='bad'> 6.53x</td>
<td class='bad'>1364.5</td>
<td class='bad'> 5.97x</td>
</tr>
<tr>
<td class='name'>quicksort-double</td>
<td class='base'>251.0</td>
<td class='bad'>1470.3</td>
<td class='bad'> 5.86x</td>
<td class='bad'>1306.3</td>
<td class='bad'> 5.20x</td>
</tr>
<tr>
<td class='sep' /></tr>
<tr>
<td class='name'>array-allocator-int</td>
<td class='base'>68.4</td>
<td class='good'>73.3</td>
<td class='good'> 1.07x</td>
<td class='great'>42.6</td>
<td class='great'> 0.62x</td>
</tr>
<tr>
<td class='name'>array-allocator-long</td>
<td class='base'>101.9</td>
<td class='good'>102.4</td>
<td class='good'> 1.00x</td>
<td class='ok'>143.3</td>
<td class='ok'> 1.41x</td>
</tr>
<tr>
<td class='name'>array-allocator-float</td>
<td class='base'>87.4</td>
<td class='good'>82.5</td>
<td class='good'> 0.94x</td>
<td class='ok'>146.8</td>
<td class='ok'> 1.68x</td>
</tr>
<tr>
<td class='name'>array-allocator-double</td>
<td class='base'>82.9</td>
<td class='good'>83.0</td>
<td class='good'> 1.00x</td>
<td class='ok'>162.4</td>
<td class='ok'> 1.96x</td>
</tr>
<tr>
<td class='sep' /></tr>
<tr>
<td class='name'>insertion-sort-int</td>
<td class='base'>47.5</td>
<td class='good'>48.6</td>
<td class='good'> 1.02x</td>
<td class='awful'>1463.0</td>
<td class='awful'>30.80x</td>
</tr>
<tr>
<td class='name'>insertion-sort-long</td>
<td class='base'>49.9</td>
<td class='good'>50.3</td>
<td class='good'> 1.01x</td>
<td class='awful'>1440.6</td>
<td class='awful'>28.88x</td>
</tr>
<tr>
<td class='name'>insertion-sort-float</td>
<td class='base'>50.0</td>
<td class='good'>50.9</td>
<td class='good'> 1.02x</td>
<td class='awful'>1658.6</td>
<td class='awful'>33.17x</td>
</tr>
<tr>
<td class='name'>insertion-sort-double</td>
<td class='base'>49.3</td>
<td class='good'>49.9</td>
<td class='good'> 1.01x</td>
<td class='awful'>1850.5</td>
<td class='awful'>37.57x</td>
</tr>
<tr>
<td class='sep' /></tr>
<tr>
<td class='name'>merge-sort-int</td>
<td class='base'>275.6</td>
<td class='good'>293.0</td>
<td class='good'> 1.06x</td>
<td class='poor'>870.9</td>
<td class='poor'> 3.16x</td>
</tr>
<tr>
<td class='name'>merge-sort-long</td>
<td class='base'>288.3</td>
<td class='great'>215.0</td>
<td class='great'> 0.75x</td>
<td class='poor'>842.9</td>
<td class='poor'> 2.92x</td>
</tr>
<tr>
<td class='name'>merge-sort-float</td>
<td class='base'>186.8</td>
<td class='ok'>206.5</td>
<td class='ok'> 1.11x</td>
<td class='bad'>901.3</td>
<td class='bad'> 4.83x</td>
</tr>
<tr>
<td class='name'>merge-sort-double</td>
<td class='base'>197.6</td>
<td class='ok'>218.8</td>
<td class='ok'> 1.11x</td>
<td class='bad'>895.5</td>
<td class='bad'> 4.53x</td>
</tr>
<tr>
<td class='sep' /></tr>
<tr>
<td class='name'>infix-adder-int</td>
<td class='base'>20.5</td>
<td class='poor'>57.1</td>
<td class='poor'> 2.79x</td>
<td class='bad'>125.9</td>
<td class='bad'> 6.14x</td>
</tr>
<tr>
<td class='name'>infix-adder-long</td>
<td class='base'>20.8</td>
<td class='poor'>62.3</td>
<td class='poor'> 3.00x</td>
<td class='awful'>250.6</td>
<td class='awful'>12.08x</td>
</tr>
<tr>
<td class='name'>infix-adder-float</td>
<td class='base'>20.9</td>
<td class='ok'>33.9</td>
<td class='ok'> 1.62x</td>
<td class='bad'>176.4</td>
<td class='bad'> 8.45x</td>
</tr>
<tr>
<td class='name'>infix-adder-double</td>
<td class='base'>28.8</td>
<td class='ok'>32.9</td>
<td class='ok'> 1.14x</td>
<td class='bad'>189.0</td>
<td class='bad'> 6.57x</td>
</tr>
</table>
<p><br/></p>
<h1>Discussion</h1>
<p>Profiling this was a little bit annoying&#8211;I had to write 4 direct implementations (one for each of the types I was interested in) plus two generic implementations (one using the old <tt>scala.math.Numeric</tt> and one using the new <tt>com.azavea.math.Numeric</tt>). I used <tt>scala.testing.Benchmark</tt> although <a href="">Yuvi Masory</a> recently suggested using <a href="Caliper" class="broken_link" rel="nofollow">https://github.com/sirthias/scala-benchmarking-template</a> (which I still need to go check out).</p>
<p>Some things to note:</p>
<ol>
<li>Old Numeric does much better on floating-point numbers than on integral ones. Why?</li>
<li>For some reason old Numeric is able to beat the direct implementation of the <i>array-allocator</i> test.</li>
<li>Since <tt>scala.util.Sorting[T]</tt> uses <tt>scala.math.Ordering[T]</tt> (which isn&#8217;t specialized) it&#8217;s not possible to make Numeric any faster in this test.</li>
<li><tt>scala.util.Sorting[Long]</tt> is over 4x slower than <tt>Int</tt>, <tt>Float</tt> and <tt>Double</tt> in the direct implementation.</li>
<li>Infix operators are still slow enough that I still have mixed feelings endorsing them.</li>
</ol>
<p>One additional gotcha which I haven&#8217;t discussed at length is what writing your own specialized numeric code (currently) looks like. Unfortunately, there&#8217;s a lot of boiler-plate. While users of your library will just say <tt>doSomethingComplicated(Array(0, 1, 2), 18, 99)</tt> you will be stuck writing:</p>

<div class="wp_syntax"><div class="code"><pre class="scala" style="font-family:monospace;"><span style="color: #0000ff; font-weight: bold;">def</span> doSomethingComplicated<span style="color: #F78811;">&#91;</span><span style="color: #000080;">@</span>specialized A<span style="color: #000080;">:</span>Numeric<span style="color: #000080;">:</span>Manifest<span style="color: #F78811;">&#93;</span>
<span style="color: #F78811;">&#40;</span>ns<span style="color: #000080;">:</span>Array<span style="color: #F78811;">&#91;</span>A<span style="color: #F78811;">&#93;</span>, x<span style="color: #000080;">:</span>A, y<span style="color: #000080;">:</span>A<span style="color: #F78811;">&#41;</span> <span style="color: #000080;">=</span> <span style="color: #F78811;">&#123;</span>
  <span style="color: #008000; font-style: italic;">// implementation here</span>
<span style="color: #F78811;">&#125;</span></pre></div></div>

<p>And that&#8217;s only one type parameter; God forbid you want A and B to both be Numeric!</p>
<p>I don&#8217;t know of any easy way around this. You have to say <tt>@specialized</tt> if you want your code to be specialized. If you fail to do this anywhere in the call chain you will use generic implementations from that point down, losing any benefit to specialization. You need to specify <tt>Numeric</tt> because that&#8217;s the point, right? And when writing code that needs to use the type parameter <tt>A</tt> to allocate arrays (among other things) you have to provide a <tt>Manifest</tt>. This gets ugly really fast.</p>
<p>Given my ignorance of the Scala compiler, I can imagine various magical things that might fix this. For instance, I could imagine some kind of synthetic type bound that combines others, e.g. <tt>FastNumeric = @specialized Numeric:Manifest</tt> or something. Is this possible (or even a good idea)? I don&#8217;t know.</p>
<h1>Changes</h1>
<p>This section is a bit rushed&#8211;I may expand it into another post later, but I just wanted to get the information out there.</p>
<p>One of the biggest changes I made to Numeric was tearing out <tt>scala.math.Ordering</tt>&#8211;I didn&#8217;t want to try to specialize &#8220;everything at once&#8221; but <tt>scala.math.Numeric</tt> inherits all of its (incredibly slow) comparison methods from Ordering. Specializing Ordering would solve this problem.</p>
<p>I also created a specialized typeclass with the humorous name &#8220;Convertable&#8221; which applies to all the value types which represent numbers (<tt>Byte</tt>, <tt>Short</tt>, <tt>Int</tt>, <tt>Long</tt>, <tt>Float</tt> and <tt>Double</tt>). The great thing about this is that you can avoid doing boxing/unboxing during conversion between types. It also allows you to implement the <tt>fromType[T]</tt> method I discussed earlier.</p>
<p>I left out <tt>Short</tt> and <tt>Byte</tt> after Paul Phillips pointed out that neither classes operations behave as the direct implementations do. In Scala (as in Java) <tt>Byte + Byte -> Int</tt>, whereas in Numeric <tt>A + A -> A</tt> (so <tt>Byte + Byte -> Byte</tt>). This causes all kinds of bugs. Since <tt>Short</tt> and <tt>Byte</tt> (and <tt>Char</tt>) are converted to <tt>Int</tt> when you actually do things with them, I decided it was unlikely users wanted to be able to use them in generic numeric functions.</p>
<p>A (potentially) controversial change I made was not including <tt>scala.math.Integral</tt> and <tt>scala.math.Fractional</tt>, and unifying support for the division and mod operators. Coming from dynamically-typed languages, I expected to be able to do the following:</p>

<div class="wp_syntax"><div class="code"><pre class="scala" style="font-family:monospace;"><span style="color: #008000; font-style: italic;">// this does not work with the built-in Numeric</span>
<span style="color: #0000ff; font-weight: bold;">import</span> Numeric.<span style="color: #000000;">Implicits</span>.<span style="color: #000080;">_</span>
<span style="color: #0000ff; font-weight: bold;">def</span> scale<span style="color: #F78811;">&#91;</span>A<span style="color: #000080;">:</span>Numeric<span style="color: #F78811;">&#93;</span><span style="color: #F78811;">&#40;</span>n<span style="color: #000080;">:</span>A, num<span style="color: #000080;">:</span>A, denom<span style="color: #000080;">:</span>A<span style="color: #F78811;">&#41;</span> <span style="color: #000080;">=</span> <span style="color: #F78811;">&#40;</span>n <span style="color: #000080;">*</span> num<span style="color: #F78811;">&#41;</span> / denom
&nbsp;
<span style="color: #008000; font-style: italic;">// this *does* work</span>
<span style="color: #0000ff; font-weight: bold;">import</span> scala.<span style="color: #000000;">math</span>.<span style="color: #000000;">Integral</span>.<span style="color: #000000;">Implicits</span>.<span style="color: #000080;">_</span>
<span style="color: #0000ff; font-weight: bold;">def</span> scale<span style="color: #F78811;">&#91;</span>A<span style="color: #000080;">:</span>Integral<span style="color: #F78811;">&#93;</span><span style="color: #F78811;">&#40;</span>n<span style="color: #000080;">:</span>A, num<span style="color: #000080;">:</span>A, denom<span style="color: #000080;">:</span>A<span style="color: #F78811;">&#41;</span> <span style="color: #000080;">=</span> <span style="color: #F78811;">&#40;</span>n <span style="color: #000080;">*</span> num<span style="color: #F78811;">&#41;</span> / denom</pre></div></div>

<p>I understand that for someone who&#8217;s excited about creating user-defined numeric types this split isn&#8217;t a big deal. But from my perspective I want a generic numeric type that abstracts across all the useful value-types in Scala. I&#8217;m not opposed to having Integral and Fractional, but I would rather that Numeric not be defined in terms of them.</p>
<p>Finally I did some restructuring to avoid using inner traits and classes, since I had heard that those don&#8217;t specialize well.</p>
<h1>Conclusion</h1>
<p>While I still think there&#8217;s some room to make Numeric better, at this point it&#8217;s possible to write fast generic Numeric code in Scala. Stepping back, I think it&#8217;s incredibly exciting that I can avoid code duplication *and* maintain the speed that I&#8217;m used to from direct implementations.</p>
<p>I&#8217;m not sure what the best path is to add this capability to <tt>scala.math.Numeric</tt>. I think the trait lacks some important features (more type conversions, division, etc) and some of the restructuring is currently necessary to get these numbers. Since binary compatibility is important moving forward for Scala and the Typesafe team it&#8217;s not entirely clear what the best plan is. Hopefully some discussion and work at <a href="http://scalathon.org/">Scalathon</a> can clarify things a bit.</p>
<p>Please respond with any questions or comments. Do let me know if you find problems in the profiling, or try it yourself and get dramatically different numbers. I spent some time trying not to fall into obvious micro-benchmark pitfalls, but there&#8217;s still a lot I don&#8217;t know about the JVM. Thanks for reading!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.azavea.com/blogs/labs/2011/06/scalas-numeric-type-class-pt-2/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Truncating Floats in OpenLayers and SQLServer</title>
		<link>http://www.azavea.com/blogs/labs/2010/02/truncating-floats-in-openlayers-and-sqlserver/</link>
		<comments>http://www.azavea.com/blogs/labs/2010/02/truncating-floats-in-openlayers-and-sqlserver/#comments</comments>
		<pubDate>Fri, 26 Feb 2010 16:19:48 +0000</pubDate>
		<dc:creator>Carissa Brittain</dc:creator>
				<category><![CDATA[Posts]]></category>
		<category><![CDATA[Math]]></category>
		<category><![CDATA[openlayers]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://www.azavea.com/blogs/labs/?p=442</guid>
		<description><![CDATA[A perfectly valid question when dealing with map coordinates is &#8220;How accurate do we need to be?&#8221; For some applications, a tenth of a degree is more than accurate enough while for others, several more decimal places are needed. Sometimes this question is answered for you: if your data source only stores four decimal places, [...]]]></description>
			<content:encoded><![CDATA[<p>A perfectly valid question when dealing with map coordinates is &#8220;<a title="There's even a govt study" href="http://egsc.usgs.gov/isb/pubs/factsheets/fs17199.html" target="_blank">How accurate do we need to be?</a>&#8221; For some applications, a tenth of a degree is more than accurate enough while for others, several more decimal places are needed. Sometimes this question is answered for you: if your <a title="Some good free gis data" href="http://data.geocomm.com/" target="_blank">data source</a> only stores four decimal places, then that&#8217;s all the precision you&#8217;re going to have. If you&#8217;re in the <a title="4-leaves?" href="http://en.wikipedia.org/wiki/Shamrock" target="_blank">lucky</a> (unlucky?) position of generating your own coordinates, one common answer to the &#8220;how accurate&#8221; debate is &#8220;store it all&#8221;. This is the path Sajara chose, mostly because we didn&#8217;t have a good reason to choose a less precise solution over a more precise one. It just so happens that SQLServer&#8217;s <a title="Almost too much info" href="http://en.wikipedia.org/wiki/Floating_point" target="_blank">floating data type</a> precision limit is not tied so much to the number of decimal places, as to the number of numeric digits to be stored. They allow up to <a title="or 53 bits" href="http://en.wikipedia.org/wiki/Double_precision" target="_blank">16 numeric digits</a>, plus a <a title="We didn't always use one" href="http://en.wikipedia.org/wiki/Decimal_separator" target="_blank">period character</a> and a <a title="We didn't always use one either" href="http://en.wikipedia.org/wiki/Negative_number#History" target="_blank">negative character</a> as needed. Sajara works with coordinate systems in both meters and degrees, so depending on which system we&#8217;re using for a given implementation, we could be storing a value far more precise than is even visible to the <a title="half a millimeter or so" href="http://en.wikipedia.org/wiki/Naked_eye#Small_objects_and_maps" target="_blank">naked eye</a>.</p>
<p>Fast forward a few years and bring OpenLayers into the mix. We rewrote the asset editing portion of the software to allow data managers to move asset coordinates using an OpenLayers map. These coordinates were saved with still considerably more precision than we needed, but remember, we&#8217;re storing whatever precision we get. So far so good.</p>
<p>Now back to the present and we&#8217;re working on a comparison tool for our data managers. Suddenly values in the database are not matching the values coming out of our OpenLayers map. Almost, but not quite. In fact, only the last degrees of precision are different. After a bit of digging, we discovered that OpenLayers was returning numbers with between 1 and 3 fewer decimal places than our stored coordinates. Remember that we&#8217;re talking about distance differences smaller than <a title="Don't fall" href="http://images.google.com/images?hl=en&amp;client=firefox-a&amp;hs=ltN&amp;rls=org.mozilla:en-US:official&amp;resnum=0&amp;q=crack+in+the+sidewalk&amp;um=1&amp;ie=UTF-8&amp;ei=8PCHS4mEPI7U8Qakr8G8Dw&amp;sa=X&amp;oi=image_result_group&amp;ct=title&amp;resnum=4&amp;ved=0CCkQsAQwAw" target="_blank">a crack in the sidewalk</a> here, but programing languages don&#8217;t know anything about &#8220;close enough&#8221;. Either two numbers are the same or they aren&#8217;t and -39.6827663878 is not the same as -39.682766387 no matter how small the physical difference is. So we started <a title="Not quite this deep though" href="http://listverse.com/2008/09/21/top-10-amazing-holes-in-the-earth/" target="_blank">digging</a> for the reason.</p>
<p>OpenLayers has a value tucked away in its utility files that sets the default precision of a floating point number to 14 characters. This limit was added when a user noticed that the edges of certain coordinate systems were not behaving correctly due to some floating-point math precision errors. While the OpenLayers community recognizes that most systems allow floats to have 16 digits,  &#8220;<a title="Line 830-something or so" href="http://trac.openlayers.org/browser/trunk/openlayers/lib/OpenLayers/Util.js#L838">14 significant digits are sufficient to represent sub-millimeter accuracy in any coordinate system that anyone is likely to use with OpenLayers</a>&#8220;. So OpenLayers&#8217; answer to the accuracy question is to save everything that will fit in a standard float, with a few decimal places pared off just in case.</p>
<p>So the next question is: &#8220;So what?&#8221; The difference between 14 and 16 decimal places in a meter-based coordinate system is microscopic, and in a degrees-based one it&#8217;s not much bigger. So far as storing a saved coordinate in Sajara, we didn&#8217;t really care if we had 16 digits or 14 digits; the result wouldn&#8217;t look any different to our audience. However, since our initial coordinates had 16 digits and OpenLayers only preserved 14 of them, any programmatic comparison <a title="Though not quite this epic-ly" href="http://www.themadhat.com/images/fail_20at_20failing.jpg" target="_blank">fails!</a> No one likes to deal with false positives, but a 100% false positive rate was unacceptable.</p>
<p>We had a few choices here. First we could reset the default precision value in OpenLayers to zero, which would tell the library to never truncate anything. That&#8217;s a fairly simple change but we weren&#8217;t sure it wouldn&#8217;t have unforeseen data effects. Also, there&#8217;s a somewhat vague warning about problems with the <a title="The official definition." href="http://spatialreference.org/ref/sr-org/45/">Web Mercator</a> projection when this value is zero, which is one of the projections Sajara can use. So that option was out.</p>
<p>Second, we could have told SQLServer to alter the precision of coordinate values to 14, which is a fairly major change. This option was ruled out because of a difference in the definition of &#8220;precision&#8221; between SQLServer and OpenLayers. I mentioned earlier that SQLServer will store a maximum of 16 numeric digits plus a decimal and a negative sign, so a total of 18 characters. OpenLayers, however, considers the default precision of 14 to mean 14 characters instead of 14 numeric digits. So if a number has a decimal and a negative sign, we&#8217;re down to 12 numeric digits.  This little difference reintroduces the possibility of <a title="Wrong and right at the same time?" href="http://en.wikipedia.org/wiki/Type_I_and_type_II_errors#False_positive_rate">false positives</a>, so it isn&#8217;t really a change for the better.</p>
<p>The solution we finally decided to use was to change the OpenLayers default precision value to 18. Why 18? That&#8217;s the maximum amount of characters that SQLServer will store for a float, so OpenLayers will always be able to deal with any stored coordinates without having to truncate. Now, if we compare our stored coordinates with OpenLayer coordinates, we only get a change notice when an asset has actually been moved. Which is exactly what we wanted.</p>
<p>Here are some technical details for those interested:</p>
<p>The full variable name is OpenLayers.Util.DEFAULT_PRECISION and can be found in the Util.js file. There are a few good comments preceding the variable in the code, but more background can be found in the OpenLayers <a href="http://trac.openlayers.org/ticket/1951" target="_self">ticket #1951</a>. SQLServer information can be found in <a title="Very Technical" href="http://msdn.microsoft.com/en-us/library/ms173773.aspx" target="_blank">mdsn</a>. Note that if you wind up changing the OpenLayers precision value, you should do it as soon as possible after loading the library, so you don&#8217;t have the possibility of code using different precision values.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.azavea.com/blogs/labs/2010/02/truncating-floats-in-openlayers-and-sqlserver/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Distance? Math? What?</title>
		<link>http://www.azavea.com/blogs/labs/2009/04/distance-math-what/</link>
		<comments>http://www.azavea.com/blogs/labs/2009/04/distance-math-what/#comments</comments>
		<pubDate>Thu, 16 Apr 2009 18:52:21 +0000</pubDate>
		<dc:creator>Carissa Brittain</dc:creator>
				<category><![CDATA[Posts]]></category>
		<category><![CDATA[IDL]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Math]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://www.azavea.com/blogs/labs/?p=31</guid>
		<description><![CDATA[A few days ago, I became painfully aware that the distance equation we all learn in geometry class, while it works perfectly well on flat, local projections,  is woefully inadequate when we&#8217;re talking about global coordinate systems. In the midst of implementing Google Maps in our up-coming Sajara sample application, I realized that the International [...]]]></description>
			<content:encoded><![CDATA[<p>A few days ago, I became painfully aware that the distance equation we all learn in geometry class, while it works perfectly well on flat, local projections,  is woefully inadequate when we&#8217;re talking about global coordinate systems.</p>
<p>In the midst of implementing <a title="Google Maps API" href="http://code.google.com/apis/maps/documentation/index.html" target="_blank">Google Maps</a> in our up-coming <a title="Sajara Product Site" href="http://www.azavea.com/Products/Sajara/Home.aspx" target="_blank">Sajara</a> sample application, I realized that the <a title="Wikipedia: IDL" href="http://en.wikipedia.org/wiki/International_Date_Line" target="_blank">International Date Line</a> was causing problems. Large problems. Whenever the IDL was <a title="Play Ball!" href="http://en.wikipedia.org/wiki/List_of_baseball_jargon_(I)#in_play">in play</a>, I never retrieved the correct results from our database. One large problem was how we defined our <a title="Openlayers bounding box" href="http://dev.openlayers.org/apidocs/files/OpenLayers/BaseTypes/Bounds-js.html#OpenLayers.Bounds">bounding box</a> inside Sajara itself. Once that was fixed, however, I realized that something was still wrong. The Nearest-to-Farthest sort was not behaving quite right: it was really doing a Nearest-on-this-side-of-the-IDL-first sort! The IDL was acting like a <a href="http://en.wikipedia.org/wiki/Hadrian%27s_wall">wall</a> for our distance sort.</p>
<div id="attachment_39" class="wp-caption aligncenter" style="width: 310px"><img class="size-medium wp-image-39" src="http://www.azavea.com/blogs/labs/wp-content/uploads/2009/04/distance-300x234.gif" alt="distance" width="300" height="234" /><p class="wp-caption-text">Example of linear distance with IDL in play. X = center of map</p></div>
<p style="text-align: center">
<p>Here&#8217;s what we used before (in <a title="Transact SQL" href="http://en.wikipedia.org/wiki/TSQL">sql-speak</a>):</p>
<pre><span style="color: #800000">RETURN sqrt(power(@FromX - @ToX,2) + power(@FromY - @ToY,2))</span></pre>
<p>Your standard square-root of difference-squared plus difference-squared. This formula is fast and worked perfectly well so long as I operated under these two criteria:</p>
<p>1. a FLAT <a href="http://en.wikipedia.org/wiki/Map_projection">projection</a><br />
2. POSITIVE numbers only</p>
<p>Once either of those things aren&#8217;t true anymore, I can&#8217;t use the basic distance formula. In my case, both things stopped being true at the same time! The solution? Something fairly math-magical to my mind, but accepted as THE formula to get at the distance between any two global coordinates: the <a title="Haversine Formula" href="http://en.wikipedia.org/wiki/Haversine_formula">Haversine Formula</a>. Delving into descriptions of the formula brings up concepts such as <a href="http://mathworld.wolfram.com/SphericalTriangle.html">spherical triangles</a>, the planet&#8217;s <a title="Elipticity" href="http://en.wikipedia.org/wiki/Ellipsoid">elipticity</a>, <a title="Great Circles" href="http://en.wikipedia.org/wiki/Great_circle">great circles</a> and other things very important to <a title="Polynesian Navigation" href="http://www.teara.govt.nz/NewZealanders/MaoriNewZealanders/CanoeNavigation/2/en">navigation</a>. It&#8217;s accurate down to about a meter, which is plenty for anything I&#8217;ll be doing with it.</p>
<p>Haversine Formula <a title="javascript implementation" href="http://www.movable-type.co.uk/scripts/latlong.html">in Javascript</a>:</p>
<pre style="margin-left: 0pt"><span style="color: #800000">var R = 6371; // radius of the earth
var dLat = (lat2-lat1).toRad();
var dLon = (lon2-lon1).toRad();
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
        Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) *
        Math.sin(dLon/2) * Math.sin(dLon/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var distance = R * c;</span></pre>
<p>So here is the resulting SQL function that gives me the right distance between any two global coordinates.. basically a direct translation of the above javascript into T-SQL:</p>
<pre style="margin-left: 0pt"><span style="color: #800000">CREATE FUNCTION [dbo].[distance] (@FromX float, @FromY float, @ToX float, @ToY float)
RETURNS float AS BEGIN
DECLARE @R AS FLOAT;
SET @R = 6371;
DECLARE @DLAT AS FLOAT;
DECLARE @DLON AS FLOAT;
DECLARE @A AS FLOAT;
DECLARE @C AS FLOAT;
DECLARE @D AS FLOAT;
SET @DLAT = RADIANS(@ToY - @FromY);
SET @DLON = RADIANS(@ToX - @FromX);
SET @A =
SIN(@DLAT/2) * SIN(@DLAT/2) +
COS(RADIANS(@FromY)) * COS(RADIANS(@ToY)) * SIN(@DLON/2) * SIN(@DLON/2);
SET @C = 2 * ATN2(SQRT(@A), SQRT(1-@A));
SET @D = @R * @C;
RETURN @D
END</span></pre>
<p><a title="http://en.wikipedia.org/wiki/Haversine_formula " href="http://en.wikipedia.org/wiki/Haversine_formula" target="_blank"><br />
</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.azavea.com/blogs/labs/2009/04/distance-math-what/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

