Jekyll2023-12-14T17:27:09+00:00https://ochafik.github.io/feed.xmlChé zOliveprograblah blah (yawn). Opinions expressed are my own.
OpenSCAD 3D rendering just got an order of magnitude faster. Here’s how and what may come next.2022-02-09T00:03:07+00:002022-02-09T00:03:07+00:00https://ochafik.github.io/jekyll/update/2022/02/09/openscad-fast-csg-contibution<p><strong>TL;DR: <a href="https://openscad.org/">OpenSCAD</a> users: download a <a href="https://openscad.org/downloads.html#snapshots">nightly build</a> & enable <code class="language-plaintext highlighter-rouge">fast-csg</code> in settings for 10x faster render (YMMV). Make your models more ambitious and report issues / successes <a href="https://github.com/openscad/openscad/pull/4087">here</a>!</strong></p>
<p><em>Note: opinions expressed here are my own.</em></p>
<ul id="markdown-toc">
<li><a href="#openscad--3d-cad-for-developers" id="markdown-toc-openscad--3d-cad-for-developers">OpenSCAD = 3D CAD for developers</a></li>
<li><a href="#cgal-nef-polyhedra--gmp--so-precise-it-hurts-performance" id="markdown-toc-cgal-nef-polyhedra--gmp--so-precise-it-hurts-performance">CGAL Nef Polyhedra + GMP = so precise it hurts (performance)</a></li>
<li><a href="#just-concatenating-meshes-huh" id="markdown-toc-just-concatenating-meshes-huh">Just concatenating meshes, huh?</a></li>
<li><a href="#cgals-other-hidden-gem-corefinement-functions" id="markdown-toc-cgals-other-hidden-gem-corefinement-functions">CGAL’s other hidden gem: corefinement functions</a></li>
<li><a href="#great-results-already" id="markdown-toc-great-results-already">Great results already</a></li>
<li><a href="#what-about-multithreading-or-skipping-operations-altogether-" id="markdown-toc-what-about-multithreading-or-skipping-operations-altogether-">What about multithreading? Or skipping operations altogether? 🙃</a></li>
<li><a href="#rewriting-trees-to-increase-laziness-and-parallelizability" id="markdown-toc-rewriting-trees-to-increase-laziness-and-parallelizability">Rewriting trees to increase laziness and parallelizability</a></li>
<li><a href="#whats-next" id="markdown-toc-whats-next">What’s next?</a></li>
<li><a href="#thanks" id="markdown-toc-thanks">Thanks!</a></li>
</ul>
<h2 id="openscad--3d-cad-for-developers">OpenSCAD = 3D CAD for developers</h2>
<p>OpenSCAD is a popular open-source design tool for 3D printing afficionados (and others). It’s essentially a CAD software for programmers with a minimalist UI. A simple declarative programming language defines <a href="https://en.wikipedia.org/wiki/Constructive_solid_geometry">Constructive Solid Geometry</a> (CSG) operations like unions, intersections, differences, which can be parameterized with loops and variables.</p>
<p><img src="https://user-images.githubusercontent.com/273860/153035451-e0ab2792-d6de-449b-9fb3-ae22307d48f6.png" alt="image" /></p>
<p>Last year I grew fond of it to design ever more complex models, but started running into limitations: while interactive rendering was fine, the final rendering (creating the STL files to give to the 3D printing slicer) was horrendously slow. Slow enough to prevent me from doing what I wanted, which was to generate large, varying scalemail patterns:</p>
<p><img src="https://user-images.githubusercontent.com/273860/153035188-d18a8db7-a18c-4d04-aecc-0b7cabfa77e8.png" alt="a very slow model to render" /></p>
<p>But something was off: my slicer software (Cura) was able to handle 10x10 grids of my scalemail pattern without breaking a sweat, so why was OpenSCAD so slow? So after investigating alternatives (wasn’t keen to get locked in a certain popular but proprietary CAD software with huge a learning curve and high prices after its 1 year hobbyist licenses), I dove into OpenSCAD’s codebase and tried to understand what it was up to.</p>
<h2 id="cgal-nef-polyhedra--gmp--so-precise-it-hurts-performance">CGAL Nef Polyhedra + GMP = so precise it hurts (performance)</h2>
<p>As it turns out, OpenSCAD is using the <a href="https://www.cgal.org/">Computational Geometry Algorithms Library</a> (CGAL) for its CSG operations. That amazing library allows for completely generic numeric types, and the type OpenSCAD is using is some voodoo magic “exact” numeric type based on the <a href="https://gmplib.org/">GNU Multiple Precision Arithmetic Library</a> (GMP).</p>
<p>More specifically, OpenSCAD is using <a href="https://doc.cgal.org/latest/Nef_3/classCGAL_1_1Nef__polyhedron__3.html">3D boolean operations on Nef Polyhedra</a>, which provides extrely robust and accurate results, two welcome properties in the 3D printing hobby, but also is extremely complex and slow to run (especially with those exact underlying number abstractions).</p>
<h2 id="just-concatenating-meshes-huh">Just concatenating meshes, huh?</h2>
<p>But surely I thought, if we just need to assemble a grid of my interlocking patterns without any intersection, it’s just a matter of concatenating the meshes, no special operations needed.</p>
<p>Even for unions, many geometrical operations are required when overlaps / intersections require creating new points, new edges, so as to maintain the topological soundness (<a href="https://en.wikipedia.org/wiki/Manifold">manifoldness</a>) of solids so they can be 3D-printed later, etc.</p>
<p>So I started exploring the “fast-union” route (<a href="https://github.com/openscad/openscad/pull/3636">openscad#3636</a>), in which I’d literally concatenated meshes if I could determine that they can’t actually intersect with each other based on their bounding boxes. This worked great for some models, but ran into weird performance for others. Searching for good operands to union together is important for many models, e.g. in a grid of overlapping tiles you can skip a tile to do a fast-union but two consecutive tiles would need a proper union. That search neededs to be bounded (otherwise would be in quadratic time of # of operands; randomizing the operands would kind of work well enough), the bounding box operations need to be lighter than the geometry itself (e.g. not true when unioning a swarm of cubes), many other things needed to be taken into account.</p>
<p>I’ve paused this track for now but might explore it again.</p>
<h2 id="cgals-other-hidden-gem-corefinement-functions">CGAL’s other hidden gem: corefinement functions</h2>
<p>As some of the extremely friendly and helpful OpenSCAD project maintainers ❤️ pointed out <a href="https://openscad.org/community.html#irc">on IRC</a>, there was another option in stock: faster operations using the <a href="https://doc.cgal.org/latest/Polygon_mesh_processing/index.html">Polygon Mesh Processing</a> CGAL package (authored by <a href="https://github.com/sloriot">sloriot@</a>) and its “corefinement” functions. For that I had to introduce <a href="https://doc.cgal.org/latest/Surface_mesh/index.html">Surface_mesh</a> (after trying w/ less efficient <a href="https://doc.cgal.org/latest/Polyhedron/classCGAL_1_1Polyhedron__3.html">Polyhedron_3</a>) into OpenSCAD.</p>
<p>Corefinement works great in some cases, crashes (sometimes in unrecoverable ways) or politely fails in others (for instance it dislikes non-manifold inputs, or inputs that share edges / vertices). So I ended up creating a hybrid of Surface_mesh corefinement and Nef operations, reverting to the slow safety of Nefs when we detect it’s likely unsafe to use corefinement (<a href="https://github.com/openscad/openscad/pull/4087">openscad#4087</a>). My goals was to provide the maximum possible backwards compatibility with all the existing model files out there.</p>
<h2 id="great-results-already">Great results already</h2>
<p><strong>The result: 10x faster or more for <a href="https://gist.github.com/ochafik/2db96400e3c1f73558fcede990b8a355">my models</a> 🎉🎉🎉</strong></p>
<p>And <strong>up to 100x</strong> if you remove the aforementioned safety checks with the <code class="language-plaintext highlighter-rouge">fast-csg-trust-corefinement</code> feature (<a href="https://github.com/openscad/openscad/pull/4101, which may earn you some crashes 🤷♂️">openscad#4101</a>.</p>
<p>You should test it yourself (<a href="https://openscad.org/downloads.html#snapshots">grab a nightly build</a>; also hopefully we get some official benchmark suite soon, see discussion in <a href="https://github.com/openscad/openscad/issues/3931">openscad#3931</a>).</p>
<h2 id="what-about-multithreading-or-skipping-operations-altogether-">What about multithreading? Or skipping operations altogether? 🙃</h2>
<p>So I was getting there, performance-wise, but my models were still too slow to <em>really</em> scale up in complexity.</p>
<p>It was quite obvious from the start that OpenSCAD’s rendering is mono-threaded, so <a href="https://github.com/ochafik/openscad/commits/multithreaded-hack2">I tried multithreading it</a> (as others had done <a href="https://github.com/openscad/openscad/pull/3636">here</a> and <a href="https://github.com/openscad/openscad/pull/3193">there</a>, which I didn’t know yet) but found it hard to get good speedups because of the tree structure of lots of models. Dependencies limit the amount of parallel operations that can be performed.</p>
<p>I then discovered that new experimental <code class="language-plaintext highlighter-rouge">lazy-union</code> feature (<a href="url">openscad#350</a>, in nightly builds since a year) which essentially leaves the final top-level union up to the slicer to do. This can be a big deal if your model is just a top-level concatenation of very complex models, as it literally takes no time at all to (not) do that top-level union.</p>
<p><strong>BUT</strong>, as soon as modules are involved, or for loops, or transforms, etc, <code class="language-plaintext highlighter-rouge">lazy-union</code>’s benefits are out of reach and OpenSCAD does perform actual unions, which may be 100x faster with <code class="language-plaintext highlighter-rouge">fast-csg</code>, but still not fast enough to scale my scalemail to 100x100 grids :-D</p>
<h2 id="rewriting-trees-to-increase-laziness-and-parallelizability">Rewriting trees to increase laziness and parallelizability</h2>
<p>So the other promising approach is rewriting the CSG tree to something that provides more lazy-unioniable top-level operands, and also increases the arity of each individual CGS operation, especially those that can be parallelized (e.g. union and intersection).</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">union</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">a</span><span class="p">();</span>
<span class="nx">translate</span><span class="p">([</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">])</span>
<span class="nx">union</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">color</span><span class="p">(</span><span class="dl">"</span><span class="s2">red</span><span class="dl">"</span><span class="p">)</span> <span class="nx">square</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="nx">color</span><span class="p">(</span><span class="dl">"</span><span class="s2">green</span><span class="dl">"</span><span class="p">)</span> <span class="nx">sphere</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="nx">translate</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">])</span> <span class="nx">sphere</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>The result of flattening this tree is to have a top-level union that can be skipped w/ <code class="language-plaintext highlighter-rouge">lazy-unions</code>:</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">a</span><span class="p">();</span>
<span class="nx">color</span><span class="p">(</span><span class="dl">"</span><span class="s2">red</span><span class="dl">"</span><span class="p">)</span> <span class="nx">translate</span><span class="p">([</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">])</span> <span class="nx">square</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="nx">color</span><span class="p">(</span><span class="dl">"</span><span class="s2">green</span><span class="dl">"</span><span class="p">)</span> <span class="nx">translate</span><span class="p">([</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">])</span> <span class="nx">sphere</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="nx">translate</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">])</span> <span class="nx">sphere</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
</code></pre></div></div>
<p>So there you go: <code class="language-plaintext highlighter-rouge">rewrite-tree</code> (incubated <a href="https://github.com/ochafik/openscad/commits/rewrite-tree">in this branch</a>) completely drops the amount of time it takes to render this from 1min to 400ms (<code class="language-plaintext highlighter-rouge">rewrite-tree</code> + <code class="language-plaintext highlighter-rouge">lazy-union</code>). It would have taken 2sec with <code class="language-plaintext highlighter-rouge">fast-csg</code>. You can even go to <code class="language-plaintext highlighter-rouge">N=10</code> (100 spheres) in 4 seconds, which wouldn’t complete in reasonable time without the new options (you’d then typically reduce <code class="language-plaintext highlighter-rouge">$fn=50</code> or use other tricks).</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">$fn</span><span class="o">=</span><span class="mi">50</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="nx">i</span><span class="o">=</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="nx">N</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span> <span class="nx">translate</span><span class="p">([</span><span class="nx">i</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">])</span>
<span class="k">for</span> <span class="p">(</span><span class="nx">j</span><span class="o">=</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="nx">N</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span> <span class="nx">translate</span><span class="p">([</span><span class="mi">0</span><span class="p">,</span><span class="nx">j</span><span class="p">,</span><span class="mi">0</span><span class="p">])</span>
<span class="nx">sphere</span><span class="p">(</span><span class="nx">d</span><span class="o">=</span><span class="mf">1.1</span><span class="p">);</span>
</code></pre></div></div>
<h2 id="whats-next">What’s next?</h2>
<p>Please <a href="https://openscad.org/downloads.html#snapshots">download a nightly build</a> and (stress) test these features (enable in the settings, or in CLI with <code class="language-plaintext highlighter-rouge">--enable=fast-csg</code>), <a href="https://github.com/openscad/openscad/issues">file bugs</a> (or simply report any success on the <a href="https://github.com/openscad/openscad/pull/3641">umbrella PR</a>). That’s how open-source software gets better 🙏.</p>
<p>Roadmap to making OpenSCAD lightning fast:</p>
<ul class="task-list">
<li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />Introduce corefinement CSG operations instead of Nef polyhedra (<code class="language-plaintext highlighter-rouge">fast-csg</code> feature in Nightly builds, <a href="https://github.com/openscad/openscad/pull/4087">openscad#4087</a>; initial discussions in <a href="https://github.com/openscad/openscad/pull/3641">openscad#3641</a>)</li>
<li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />Trust corefinement to handle more cases (<code class="language-plaintext highlighter-rouge">fast-cst-trust-corefinement</code> feature, <a href="https://github.com/openscad/openscad/pull/4101">openscad#4101</a>). Likely to get more crashes here.</li>
<li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />Investigate non-lazy CGAL kernels. Currently need <code class="language-plaintext highlighter-rouge">fast-csg-exact</code> feature to avoid some extreme cases.</li>
<li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />Experiment with CGAL’s upcoming simplification routines (<a href="https://github.com/CGAL/cgal/pull/5461">cgal#5461</a>). Corefinement currently produces more triangles than Nefs, which can make some models larger and even slower.</li>
<li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />Enable <code class="language-plaintext highlighter-rouge">fast-csg</code> (and maybe <code class="language-plaintext highlighter-rouge">fast-csg-trust-corefinement</code>) by default in the next OpenSCAD release unless blockers are found.</li>
<li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />Introduce <code class="language-plaintext highlighter-rouge">rewrite-tree</code> feature to vastly expand cases covered by <code class="language-plaintext highlighter-rouge">lazy-union</code>.</li>
<li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />Ensure unions and intersections are parallelized to some level, maybe using one of the existing experiments.</li>
</ul>
<h2 id="thanks">Thanks!</h2>
<p>Huge thanks to the dedicated team of OpenSCAD maintainers for their endless patience & support (special shoutouts to <a href="https://github.com/t-paul">t-paul</a>, <a href="https://github.com/thehans">thehans</a>, <a href="https://github.com/redlizard">redlizard</a>, <a href="https://github.com/rcolyer">rcolyer</a> and <a href="https://github.com/MichaelAtOz">MichaelAtOz</a>) and CGAL corefinement guru <a href="https://github.com/thehans">sloriot</a> for providing the magic (and prompt support) to make the magic happen.</p>
<p>Oh and thank <em>you</em> for reading!</p>
<p>Please <strong>add any comments to <a href="https://gist.github.com/ochafik/6e95596a6e6188b2062ee056b55ce47d">this gist</a></strong>
(there are also comment <strong>threads <a href="https://www.reddit.com/r/openscad/comments/so3gv2/openscad_3d_rendering_just_got_an_order_of/">on reddit</a>, <a href="https://news.ycombinator.com/item?id=30277356">hacker news</a> and <a href="https://lists.openscad.org/empathy/thread/B7O2DPEAFI44QV76F2DO2YGKYSFVA54J">on the openscad mailing-list</a></strong>).</p>
<p><strong>Follow <a href="https://twitter.com/ochafik">ochafik@</a></strong> on Twitter to follow my next experiments!</p>TL;DR: OpenSCAD users: download a nightly build & enable fast-csg in settings for 10x faster render (YMMV). Make your models more ambitious and report issues / successes here!JNAerator 0.12 released: a year’s worth of fixes and improvements!2015-04-08T23:35:00+00:002015-04-08T23:35:00+00:00https://ochafik.github.io/jnaerator-0-12-released-a-years-worth-of-fixes-and-improvements<p><a href="http://code.google.com/p/jnaerator/">JNAerator</a> (<a href="http://code.google.com/p/jnaerator/wiki/CreditsAndLicense">licensed under LGPL 3.0</a>) lets Java programmers access native libraries transparently, using a runtime such as <a href="http://code.google.com/p/bridj/">BridJ</a> (C / C++, BSD-license), <a href="http://jna.java.net/">JNA</a> (C only, LGPL) or <a href="http://code.google.com/p/rococoa/">Rococoa</a> (Objective-C), and now <a href="https://nodejs.org/">Node.js</a>!</p>
<p>This release took a while longer than usual, but JNAerator’s moving to <a href="https://github.com/nativelibs4java/JNAerator/">its own GitHub repo</a> with Travis integration and all, hopefully making contributions easier :-).</p>
<p>The 0.12 release can be <a href="https://code.google.com/p/jnaerator/wiki/Downloads?tm=2">downloaded here</a>, and here are its release notes (see <a href="https://github.com/nativelibs4java/JNAerator/blob/master/CHANGELOG.md">full CHANGELOG</a>):</p>
<ul>
<li>Added <code class="language-plaintext highlighter-rouge">-library foo -dependencies bar,baz</code> to generate <code class="language-plaintext highlighter-rouge">@Library("foo", dependencies = {"bar", "baz"})</code>(<a href="https://github.com/nativelibs4java/nativelibs4java/issues/535">issue nativelibs4java#535</a>)</li>
<li>Added JNA-only -forceStringSignatures option to force String and String[] params even with char* and char** (as opposed to const char* and const char**) (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/476">issue nativelibs4java#476</a>)</li>
<li>Added -skipDeprecated option for JNA output (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/480">issue nativelibs4java#480</a>)</li>
<li>Added -forceNames option to issue Name annotations for all supported entities (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/443">issue nativelibs4java#443</a>)</li>
<li>Added <code class="language-plaintext highlighter-rouge">@Name</code> support to all entities (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/443">issue nativelibs4java#443</a>)</li>
<li>Added partial support for C++ namespaces with GCC-compiled libraries (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/446">issue nativelibs4java#446</a>)</li>
<li>Added a new “peer pointer” constructor to JNA structures (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/442">issue nativelibs4java#442</a>, thanks to topikachu@ for the patch!)</li>
<li>Added -publicRawBindings and -noRawBindings options (since -genRawBindings is now the default)</li>
<li>Added support for JNA 4.0.0 (implement getFieldOrder in all structs, see <a href="https://github.com/nativelibs4java/nativelibs4java/issues/384">issue nativelibs4java#384</a>)</li>
<li>Added support for node.js target runtime (see example of bindings: <a href="https://github.com/ochafik/node-opencl">https://github.com/ochafik/node-opencl</a>)</li>
<li>Added -optionalFunctions option to tag functions with <code class="language-plaintext highlighter-rouge">@org.bridj.ann.Optional</code></li>
<li>Added mechanism to skip generation of entities (-skipStructs, -skipEnums, -skipFunctions)</li>
<li>Added -noStaticInit option for BridJ</li>
<li>Added -extractDeclarations option to create an interface with all the methods and types of a library (BridJ-specific)</li>
<li>Improved harvesting of header comments: go further away before the declaration, and remove leading * in oxygen comment lines (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/481">issue nativelibs4java#481</a>)</li>
<li>Improved raw mode for BridJ callbacks: in raw mode, generate two crossed callbacks, one of which must be overridden.</li>
<li>Reverted to by-default chunks parsing, and added -parseInOnePiece instead of -parseChunks (makes parsing more robust to syntax errors)</li>
<li>Moved to ECJ 4.2.2</li>
<li>Dropped support for bit fields in JNA structs (users should implement bit manipulation logic manually or use BridJ: JNAerator’s fork of JNA that added this feature incurred too much maintenance work).</li>
<li>Dropped old shared library (DLL, Mach-O) scanning code, superseded by dyncall/dynload and BridJ’s demanglers.</li>
<li>Fixed missing actual name in raw native methods (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/499">issue nativelibs4java#499</a>, thanks to @washley for the patch!)</li>
<li>Fixed handling of <code class="language-plaintext highlighter-rouge">const char * const *</code> params for JNA runtime (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/476">issue nativelibs4java#476</a>)</li>
<li>Fixed duplicate bindings with -reification, caused by interaction with interface extraction feature (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/500">issue nativelibs4java#500</a>)</li>
<li>Fixed duplicate & mismatching <code class="language-plaintext highlighter-rouge">@Name</code> annotations with -beautifyNames (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/460">issue nativelibs4java#460</a>)</li>
<li>Fixed routing of simple callback with ptr-ptr arg (e.g. <code class="language-plaintext highlighter-rouge">typedef void* (*F3)(int** pptr)</code>)</li>
<li>Fixed pointer casts in constants (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/132">issue nativelibs4java#132</a>)</li>
<li>Fixed some GLib parsing issues: type literals of null TypeRefs, support signatures with va_list / __gnuc_va_list and __builtin_va_list, and fixed NPE (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/132">issue nativelibs4java#132</a>)</li>
<li>Fixed parsing of exotic enums (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/459">issue nativelibs4java#459</a>)</li>
<li>Fixed parsing of many Objective-C (property) attributes</li>
<li>Fixed case-sensitivity of C/C++ modifiers, which prevented some variables from being parsed (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/449">issue nativelibs4java#449</a>)</li>
<li>Fixed parsing of unsigned long constants (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/362">issue nativelibs4java#362</a>, <a href="https://github.com/nativelibs4java/nativelibs4java/issues/374">issue nativelibs4java#374</a>)</li>
<li>Fixed generation of raw bindings for callback return types (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/386">issue nativelibs4java#386</a>)</li>
<li>Fixed generation of raw bindings with varargs (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/386">issue nativelibs4java#386</a>, patch contributed by twitwi!)</li>
<li>Fixed generation of pointer to fake pointer for JNA target (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/403">issue nativelibs4java#403</a>)</li>
<li>Fixed handling of library names with hyphens (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/260">issue nativelibs4java#260</a>)</li>
<li>Fixed support of identifiers with Object method names (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/375">issue nativelibs4java#375</a>)</li>
<li>Fixed support of enums inside objc classes (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/370">issue nativelibs4java#370</a>)</li>
<li>Fixed parsing of <code class="language-plaintext highlighter-rouge">@optional</code> and <code class="language-plaintext highlighter-rouge">@required</code> objective-c annotations (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/369">issue nativelibs4java#369</a>)</li>
<li>Fixed UTF32Char, added VOID, CHAR and byte as predefined types (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/363">issue nativelibs4java#363</a>)</li>
<li>Fixed silent disappearance of struct field conversion errors (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/390">issue nativelibs4java#390</a>)</li>
<li>Fixed pom files for Maven output modes (removed rococoa dependency by default, added commented repo needed by it)</li>
<li>Fixed resolution of typedef’d structs when the typedef name was chosen as “better” than the original struct tag (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/367">issue nativelibs4java#367</a>)</li>
<li>Fixed restitution of hex constants (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/362">issue nativelibs4java#362</a>)</li>
<li>Fixed parsing of <strong>restrict</strong> args</li>
<li>Fixed parsing of MinGW system headers (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/373">issue nativelibs4java#373</a>)</li>
<li>Fixed wrong use of stdcall mapper outside Windows in JNAerator Runtime</li>
<li>Fixed recursive typedefs</li>
<li>Fixed typedefs of forward-declared enums and structs (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/430">issue nativelibs4java#430</a>)</li>
<li>Fixed handling of large unicode values (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/401">issue nativelibs4java#401</a>)</li>
<li>Fixed warnings for getFieldOrder (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/408">issue nativelibs4java#408</a>)</li>
<li>Fixed handling of constant array sizes that depend on enums for BridJ (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/354">issue nativelibs4java#354</a>)</li>
<li>Fixed handling of hypens in package names (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/260">issue nativelibs4java#260</a>)</li>
<li>Fixed OSGi imports (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/429">issue nativelibs4java#429</a>, thanks to Michael Werle for the pull request!) …</li>
</ul>
<p>Special thanks to the users and bug reporters that helped getting this version out !</p>
<p>You can contribute to the project by <a href="https://github.com/nativelibs4java/JNAerator/issues">reporting bugs here</a> and joining the <a href="http://groups.google.com/group/nativelibs4java">NativeLibs4Java Community</a>.</p>zOliveJNAerator (licensed under LGPL 3.0) lets Java programmers access native libraries transparently, using a runtime such as BridJ (C / C++, BSD-license), JNA (C only, LGPL) or Rococoa (Objective-C), and now Node.js!BridJ 0.7.0 released: experimental Android & RPi support, tons of fixes!2015-04-08T23:34:58+00:002015-04-08T23:34:58+00:00https://ochafik.github.io/bridj-0-7-0-released-experimental-android-rpi-support-tons-of-fixes<p><a href="http://code.google.com/p/bridj/">BridJ</a> (<a href="http://code.google.com/p/bridj/wiki/CreditsAndLicense" target="_blank">BSD-licensed</a>) is an innovative native bindings library that lets Java programmers use native libraries (written in C, C++, ObjectiveC and more) in a very natural way (inspired by the great <a href="http://jna.java.net/" target="_blank">JNA</a>, with better performance, C++ and generics added).</p>
<p>Huge thanks to <a href="https://github.com/nativelibs4java/BridJ/graphs/contributors">BridJ’s contributors</a> and bug reporters who made that version possible!</p>
<p>Here’s a summary of the changes since <a href="/p_763">version 0.6.2</a> (see <a href="https://github.com/nativelibs4java/BridJ/blob/master/CHANGELOG.md" target="_blank">full CHANGELOG</a>):</p>
<ul>
<li>Added LRU pointer cache (disable with -Dbridj.cache.pointers=false or BRIDJ_CACHE_POINTERS=0), which helps keep short-lived pointer garbage to a minimum for some use cases (see <a href="https://github.com/nativelibs4java/nativelibs4java/issues/440">issue nativelibs4java#440</a>)</li>
<li>Added experimental support for Raspberry Pi (Linux/armhf, hard-float ABI).</li>
<li>Added a new all-in-one android release zip with classes JAR (now contains no native lib), native libs, sources & javadoc.</li>
<li>Added programmatic setting of library dependencies: BridJ.addNativeLibraryDependencies (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/424">issue nativelibs4java#424</a>), -Dbridj.Xyz.dependencies=Abc,Def and BRIDJ_XYZ_DEPENDENCIES=Abc,Def (issue #391)</li>
<li>Added a very useful BRIDJ_DEBUG_POINTER_RELEASES=1 / -Dbridj.debug.pointer.releases=true mode that helps track double releases (also enabled when BRIDJ_DEBUG_POINTERS=1 / -Dbridj.debug.pointers=true).</li>
<li>Added Pointer.pointerToAddress(peer, size, io, release)</li>
<li>Added fallback to GCC demangler for mingw32 on Windows (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/356">issue nativelibs4java#356</a>).</li>
<li>Added support for exact library file name (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/424">issue nativelibs4java#424</a>)</li>
<li>Added Pointer.pointerTo(IntValuedEnum<E>) ([issue nativelibs4java#414](https://github.com/nativelibs4java/nativelibs4java/issues/414))</E></li>
<li>Added support for C++ namespaces (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/446">issue nativelibs4java#446</a>)</li>
<li>Added support for @Name annotations on structs and enums (allows refactoring of such classes, <a href="https://github.com/nativelibs4java/nativelibs4java/issues/443">issue nativelibs4java#443</a>)</li>
<li>Added support for new JNAerator-generated crossed callbacks (one with an object-heavy signature, and one with raw types, each calling the other, one of the two being overridden)</li>
<li>Dropped C# runtime stubs</li>
<li>Dropped linux-only and mac-only packages.</li>
<li>Improved performance of all operations of Pointers with bounds (~ 25% faster).</li>
<li>Improved concurrency of callbacks and structs creation.</li>
<li>Improved logs (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/328">issue nativelibs4java#328</a>, <a href="https://github.com/nativelibs4java/nativelibs4java/issues/346">issue nativelibs4java#346</a>).</li>
<li>Improved C++ templates (still WIP, std::list protoype and fixed std::vector)</li>
<li>Improved Grails integration with Platform.getClassLoader change (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/431">issue nativelibs4java#431</a>)</li>
<li>Improved PointerIO caching.</li>
<li>Refactored StructIO (split out description of struct and its fields as top-level entities, StructIO now just does IO). This is what justifies version bump.</li>
<li>Rebuilt Linux binaries with –hash-style=both for better backwards compatibility (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/436">issue nativelibs4java#436</a>)</li>
<li>Rebuilt Linux binaries with -z noexecstack</li>
<li>Rebuilt Unix libraries with -fno-stack-protector, and force GLIBC dependency down to 2.3.4 (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/467">issue nativelibs4java#467</a>)</li>
<li>Rebuilt Solaris binaries with statically linked libgcc (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/452">issue nativelibs4java#452</a>)</li>
<li>Fixed C++ demangling of int vs. pointer (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/482">issue nativelibs4java#482</a>)</li>
<li>Fixed bit fields in structs! (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/496">issue nativelibs4java#496</a>)</li>
<li>Fixed Windows c library alias: “msvcrt”, not “mscvrt” (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/492">issue nativelibs4java#492</a>, thanks to @rkraneis for the patch!)</li>
<li>Fixed multithreading crashes due to strerror (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/450">issue nativelibs4java#450</a>)</li>
<li>Fixed @Alignment annotation</li>
<li>Fixed demangling of pointer types (now stricter matching of target types, with support for callbacks).</li>
<li>Fixed support for Android/arm: artifact of last two releases lacked the binary, and had to move android libs from lib/ to libs/ (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/382">issue nativelibs4java#382</a>)</li>
<li>Fixed usage of local refs in getLibrarySymbols to avoid reaching Dalvik’s limit (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/376">issue nativelibs4java#376</a>)</li>
<li>Fixed openjdk library path (take it from sun.boot.library.path)</li>
<li>Fixed VARIANT memory management: use VariantInit and VariantClear + allocate it (and other structs tagged with COMRuntime) with CoTaskMemAlloc (see <a href="https://github.com/nativelibs4java/nativelibs4java/issues/389">issue nativelibs4java#389</a>)</li>
<li>Fixed typo in EllipsisHelper that broke some varargs</li>
<li>Fixed loading of dependent libraries on Windows using LoadLibraryEx + LOAD_WITH_ALTERED_PATH (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/378">issue nativelibs4java#378</a>)</li>
<li>Fixed binding of c library on windows</li>
<li>Fixed pointerToCStrings: don’t update string array (might be causing / aggravating #397)</li>
<li>Fixed native library lookup logic (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/406">issue nativelibs4java#406</a>)</li>
<li>Fixed NPE in DefaultParameterizedType.hashCode (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/411">issue nativelibs4java#411</a>)</li>
<li>Fixed handling of @Name when demangler goes nuts (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/413">issue nativelibs4java#413</a>)</li>
<li>Fixed FlagSet.toString() and had FlagSet.fromValue(int, E[]) to return raw enum when possible instead of always a FlagSet (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/414">issue nativelibs4java#414</a>)</li>
<li>Fixed alignment on 32-bit linux (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/320">issue nativelibs4java#320</a>)</li>
<li>Fixed warnings about missing vtables for COM objects (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/355">issue nativelibs4java#355</a>)</li>
<li>Fixed disappearing MFC & STL classes in artifacts (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/392">issue nativelibs4java#392</a>)</li>
<li>Fixed some GCC demangling shortcut cases like repeated const pointers.</li>
<li>Documented effects of protected mode (<a href="https://github.com/nativelibs4java/nativelibs4java/issues/394">issue nativelibs4java#394</a>)</li>
<li>Documented DefaultParameterizedType.paramType (see <a href="https://github.com/nativelibs4java/nativelibs4java/issues/418">issue nativelibs4java#418</a>) …</li>
</ul>
<p>Special thanks to the users, <a href="http://code.google.com/p/bridj/wiki/CreditsAndLicense" target="_blank">contributors</a> and bug reporters that helped getting this version out !</p>
<p>You can contribute to the project by <a href="https://github.com/ochafik/nativelibs4java/issues?labels=BridJ" target="_blank">reporting bugs here</a> and joining the <a href="http://groups.google.com/group/nativelibs4java" target="_blank">NativeLibs4Java Community</a>.</p>
<p>Wait no longer : <a href="http://code.google.com/p/bridj/wiki/Download" target="_blank">download and use BridJ</a> now !</p>zOliveBridJ (BSD-licensed) is an innovative native bindings library that lets Java programmers use native libraries (written in C, C++, ObjectiveC and more) in a very natural way (inspired by the great JNA, with better performance, C++ and generics added).JavaCL 1.0.0-RC4: bugfixes + partial support for OpenCL 1.22015-04-08T23:34:52+00:002015-04-08T23:34:52+00:00https://ochafik.github.io/javacl-1-0-0-rc4-bugfixes-partial-support-for-opencl-1-2<p><a href="http://code.google.com/p/javacl/">JavaCL</a> v1.0.0 RC4 is available!</p>
<table>
<tbody>
<tr>
<td><a href="http://code.google.com/p/javacl/wiki/Usage" target="_blank">Download / Install</a> </td>
<td> <a href="http://nativelibs4java.sourceforge.net/javacl/api/stable" target="_blank">Browse JavaDoc</a> </td>
<td> <a href="http://code.google.com/p/javacl/wiki/GettingStarted" target="_blank">Getting Started (Tutorial)</a> </td>
<td> <a href="http://groups.google.fr/group/nativelibs4java/" target="_blank">Discuss</a></td>
</tr>
</tbody>
</table>
<p>JavaCL is a BSD-licensed library that provides object-oriented OpenCL bindings for Java, helping run massively-parallel computations on graphic cards (and/or CPUs).</p>
<p>The project is migrating to <a href="https://github.com/nativelibs4java/JavaCL/">its own GitHub repository</a>, where all <a href="https://github.com/nativelibs4java/JavaCL/issues">new issues</a> should be filed.</p>
<h2 id="release-notes">Release Notes</h2>
<p>Here are the changes between <a href="/p_768">1.0.0-RC3</a> and 1.0.0-RC4 (see <a href="https://github.com/nativelibs4java/JavaCL/blob/master/CHANGELOG.md" target="_blank">full CHANGELOG</a>) :</p>
<ul class="task-list">
<li>
Dropped Blas artifact from main deployment (requires addional repo since ujmp is not in Maven Central)
</li>
<li>
Dropped support for JNA variant of JavaCL. Migration is highly encouraged to get more features and bugfixes: [https://code.google.com/p/javacl/wiki/MigratingFromJNAToBridJ](https://code.google.com/p/javacl/wiki/MigratingFromJNAToBridJ)
</li>
<li>
Updated to BridJ 0.7 (brings fixes and lots of performance enhancements)
</li>
<li>
Optimized allocation of native memory throughout the library (reusing thread-local pointer pools)
</li>
<li>
Optimized (CLDevice, CLPlatform).hasExtension
</li>
<li>
Added basic handling of structs in JavaCL Generator ([issue nativelibs4java#421](https://github.com/nativelibs4java/nativelibs4java/issues/421), [issue nativelibs4java#422](https://github.com/nativelibs4java/nativelibs4java/issues/422), [issue nativelibs4java#423](https://github.com/nativelibs4java/nativelibs4java/issues/423))
</li>
<li>
Added CLBuffer.copyTo, .copyBytesTo, .copyElementsTo
</li>
<li>
Added CLBuffer.fillBuffer to support OpenCL 1.2 clEnqueueFillBuffer ([issue nativelibs4java#232](https://github.com/nativelibs4java/nativelibs4java/issues/232))
</li>
<li>
Added CLDevice.getParent()
</li>
<li>
Added CLDevice.getPrintfBufferSize(), .isPreferredInteropUserSync(), .isLinkerAvailable()
</li>
<li>
Added CLImage.copyTo ([issue nativelibs4java#508](https://github.com/nativelibs4java/nativelibs4java/issues/508))
</li>
<li>
Added CLImage.fillImage ([issue nativelibs4java#232](https://github.com/nativelibs4java/nativelibs4java/issues/232))
</li>
<li>
Added CLPlatform.unloadPlatformCompiler() with automatic switch between OpenCL 1.1 clUnloadCompiler and OpenCL 1.2 clUnloadPlatformCompiler ([issue nativelibs4java#232](https://github.com/nativelibs4java/nativelibs4java/issues/232))
</li>
<li>
Added CLQueue.enqueueBarrier & .enqueueMarker to support clEnqueueBarrierWithWaitList & clEnqueueMarkerWithWaitList (switching between OpenCL 1.1 and OpenCL 1.2 variants automatically) ([issue nativelibs4java#232](https://github.com/nativelibs4java/nativelibs4java/issues/232))
</li>
<li>
Added CLQueue.enqueueMigrateMemObjects ([issue nativelibs4java#232](https://github.com/nativelibs4java/nativelibs4java/issues/232))
</li>
<li>
Added JAVACL_LOG_CALLS=1 / -Djavacl.logCalls=true to log every native call (similar to BRIDJ_LOG_CALLS except it prints the parameter and return values)
</li>
<li>
Added many missing CLDevice 1.2 info getters ([issue nativelibs4java#232](https://github.com/nativelibs4java/nativelibs4java/issues/232)),
</li>
<li>
Added MapFlags.WriteInvalidateRegion (CL_MAP_WRITE_INVALIDATE_REGION from OpenCL 1.2) ([issue nativelibs4java#232](https://github.com/nativelibs4java/nativelibs4java/issues/232))
</li>
<li>
Fixed crash in CLPlatform.getBinaries()
</li>
<li>
Fixed excessive logs for deprecated features and missing OpenCL 1.1 and 1.2 functions (especially if version < deprecatedVersion)
</li>
<li>
Fixed [issue nativelibs4java#387](https://github.com/nativelibs4java/nativelibs4java/issues/387): don't call clReleaseDevice (OpenCL 1.2) unless explicitly needed
</li>
<li>
Fixed [issue nativelibs4java#397](https://github.com/nativelibs4java/nativelibs4java/issues/397): crash on Radeon due to bug in driver (attempts to get the source from a program created with clCreateProgramWithBinary yields a segfault)
</li>
<li>
Fixed [issue nativelibs4java#397](https://github.com/nativelibs4java/nativelibs4java/issues/397): major bug in CLProgram
</li>
<li>
Fixed [issue nativelibs4java#420](https://github.com/nativelibs4java/nativelibs4java/issues/420): horrible random native crash (double release, found with new -Dbridj.debug.pointer.releases=true).
</li>
<li>
Fixed [issue nativelibs4java#453](https://github.com/nativelibs4java/nativelibs4java/issues/453): don't try to load cached binaries for programs created from binaries!
</li>
<li>
Fixed [issue nativelibs4java#455](https://github.com/nativelibs4java/nativelibs4java/issues/455): when reading binaries, skip devices that are not allowed
</li>
<li>
Fixed [issue nativelibs4java#479](https://github.com/nativelibs4java/nativelibs4java/issues/479): avoid some NPEs in CLProgram.getProgramBuildInfo
</li>
<li>
Fixed typo: CLDevice.getOpenCLVersion -> getOpenCLCVersion
</li>
</ul>
<p> </p>
<p> </p>
<h2 id="getting-started">Getting started</h2>
<p>You can read the <a href="http://code.google.com/p/javacl/wiki/GettingStarted" target="_blank">Getting Started (Tutorial) page</a> on the wiki to get started very quickly !</p>
<p>Please join the <a href="http://groups.google.fr/group/nativelibs4java/" target="_blank">NativeLibs4Java Google Group</a> to discuss JavaCL, get the latest news and ask for support from the growing JavaCL community.</p>zOliveJavaCL v1.0.0 RC4 is available!Scalaxy/MacroExtensions: a DSL / compiler plugin to write macro-based DSLs (enrichments without runtime dependency!)2013-02-20T11:24:44+00:002013-02-20T11:24:44+00:00https://ochafik.github.io/scalaxymacroextensions-a-dsl-compiler-plugin-to-write-macro-based-dsls-extension-methods-with-no-runtime-dependency<p><em>Quick link: <a href="https://github.com/ochafik/Scalaxy/tree/master/MacroExtensions/">Scalaxy/MacroExtensions on GitHub</a></em></p>
<p>Scala’s <a href="http://www.artima.com/weblogs/viewpost.jsp?thread=179766">enrich-my-library pattern</a> allows Scala developers to add methods (and more) to existing classes.</p>
<!-- https://gist.github.com/4994362 -->
<div class="language-scala highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">implicit</span> <span class="k">def</span> <span class="nf">Extensions</span><span class="o">(</span><span class="n">self</span><span class="k">:</span> <span class="kt">Any</span><span class="o">)</span> <span class="k">=</span> <span class="k">new</span> <span class="nc">Extensions</span><span class="o">(</span><span class="n">self</span><span class="o">)</span>
<span class="k">class</span> <span class="nc">Extensions</span><span class="o">(</span><span class="n">self</span><span class="k">:</span> <span class="kt">Any</span><span class="o">)</span> <span class="o">{</span>
<span class="k">def</span> <span class="nf">quoted</span><span class="o">(</span><span class="n">quote</span><span class="k">:</span> <span class="kt">String</span><span class="o">)</span> <span class="k">=</span> <span class="n">quote</span> <span class="o">+</span> <span class="n">self</span> <span class="o">+</span> <span class="n">quote</span>
<span class="o">}</span>
<span class="nf">println</span><span class="o">(</span><span class="mf">10.</span><span class="nf">quoted</span><span class="o">(</span><span class="s">"'"</span><span class="o">))</span> <span class="c1">// prints "'10'"</span>
</code></pre></div></div>
<p>Scala 2.10 facilitates this pattern by providing <a href="http://docs.scala-lang.org/overviews/core/implicit-classes.html">implicit classes</a>:</p>
<!-- https://gist.github.com/4994346 -->
<div class="language-scala highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">implicit</span> <span class="k">class</span> <span class="nc">Extensions</span><span class="o">(</span><span class="n">self</span><span class="k">:</span> <span class="kt">Any</span><span class="o">)</span> <span class="o">{</span>
<span class="k">def</span> <span class="nf">quoted</span><span class="o">(</span><span class="n">quote</span><span class="k">:</span> <span class="kt">String</span><span class="o">)</span> <span class="k">=</span> <span class="n">quote</span> <span class="o">+</span> <span class="n">self</span> <span class="o">+</span> <span class="n">quote</span>
<span class="o">}</span>
<span class="nf">println</span><span class="o">(</span><span class="mf">10.</span><span class="nf">quoted</span><span class="o">(</span><span class="s">"'"</span><span class="o">))</span> <span class="c1">// prints "'10'"</span>
</code></pre></div></div>
<p>This works great, but…</p>
<ul>
<li>It usually implies some object creation at runtime (lightweight though it might be, expecially if the extension is a <a href="http://docs.scala-lang.org/overviews/core/value-classes.html">value class</a>),</li>
<li>Your extension library is a new runtime dependency (which is not such a bad thing, but it can be avoided, please read on).</li>
</ul>
<p>The other day, <a href="https://twitter.com/emchristiansen">Eric Christiansen</a> rightly <a href="https://groups.google.com/d/topic/nativelibs4java/o577ZXRAheQ/discussion">complained on NativeLibs4Java’s mailing list</a> that <a href="https://github.com/ochafik/Scalaxy/tree/master/Compilets">Scalaxy/Compilets</a> were quite constrained by the typer, and that he wished he could define extension methods more easily.</p>
<p>I gave that a serious thought, and came up with <a href="https://gist.github.com/ochafik/4978627">a compiler plugin that runs before the typer / namer and performs the following expansion</a>:</p>
<!-- https://gist.github.com/4994373 -->
<ul>
<li>
<p>Input.scala:</p>
<div class="language-scala highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@extend</span><span class="o">(</span><span class="nc">Any</span><span class="o">)</span> <span class="k">def</span> <span class="nf">quoted</span><span class="o">(</span><span class="n">quote</span><span class="k">:</span> <span class="kt">String</span><span class="o">)</span> <span class="k">=</span> <span class="n">quote</span> <span class="o">+</span> <span class="n">self</span> <span class="o">+</span> <span class="n">quote</span>
</code></pre></div> </div>
</li>
<li>
<p>Output.scala:</p>
<div class="language-scala highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Transformed AST after the compiler plugin's phase:</span>
<span class="k">implicit</span> <span class="k">class</span> <span class="nc">quoted</span><span class="o">(</span><span class="n">self</span><span class="k">:</span> <span class="kt">Any</span><span class="o">)</span> <span class="o">{</span>
<span class="k">def</span> <span class="nf">quoted</span><span class="o">(</span><span class="n">quote</span><span class="k">:</span> <span class="kt">String</span><span class="o">)</span> <span class="k">=</span> <span class="n">quote</span> <span class="o">+</span> <span class="n">self</span> <span class="o">+</span> <span class="n">quote</span>
<span class="o">}</span>
</code></pre></div> </div>
</li>
</ul>
<p>Quite exciting syntax twisting, but overall not a huge line-saver.</p>
<p>Then I realized there’s another pattern that could benefit from such rewrites: macros enrichments.</p>
<p><strong>A macro enrichment?</strong></p>
<p>A macro enrichment just extends the “enrich-my-library” pattern by implementing the extension method using a macro. As a result, the enrichment is “inlined” at compilation time, and there’s no runtime dependency nor overhead. See my recent experiments for examples of such macro enrichments:</p>
<ul>
<li><a href="/p_806">optimized loops</a>,</li>
<li><a href="/p_803">Java beans syntactic sugar</a>,</li>
<li><a href="/p_847">smart asserts</a> and</li>
<li><a href="https://github.com/ochafik/Scalaxy/tree/master/Fx">JavaFX DSL</a>.</li>
</ul>
<p><a href="https://github.com/ochafik/Scalaxy/tree/master/MacroExtensions/">Scalaxy/MacroExtensions</a> just uses the exact same syntax as above to create all the implicit class / macro wiring necessary to implement the extension as a macro:</p>
<!-- https://gist.github.com/4994400 -->
<ul>
<li>
<p>Input.scala:</p>
<div class="language-scala highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@scalaxy</span><span class="o">.</span><span class="py">extension</span><span class="o">[</span><span class="kt">Any</span><span class="o">]</span>
<span class="k">def</span> <span class="nf">quoted</span><span class="o">(</span><span class="n">quote</span><span class="k">:</span> <span class="kt">String</span><span class="o">)</span> <span class="k">=</span> <span class="n">quote</span> <span class="o">+</span> <span class="n">self</span> <span class="o">+</span> <span class="n">quote</span>
</code></pre></div> </div>
</li>
<li>
<p>Output.scala:</p>
<div class="language-scala highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Transformed AST after the `scalaxy-extensions` compilation phase:</span>
<span class="k">import</span> <span class="nn">scala.language.experimental.macros</span>
<span class="k">implicit</span> <span class="k">class</span> <span class="nc">scalaxy$extensions$quoted$1</span><span class="o">(</span><span class="n">self</span><span class="k">:</span> <span class="kt">Any</span><span class="o">)</span> <span class="o">{</span>
<span class="k">def</span> <span class="nf">quoted</span><span class="o">(</span><span class="n">quote$Expr$1</span><span class="k">:</span> <span class="kt">String</span><span class="o">)</span> <span class="k">=</span> <span class="n">macro</span> <span class="nv">scalaxy$extensions$quoted$1</span><span class="o">.</span><span class="py">quoted</span>
<span class="o">}</span>
<span class="k">object</span> <span class="nc">scalaxy$extensions$quoted$1</span> <span class="o">{</span>
<span class="k">def</span> <span class="nf">quoted</span><span class="o">(</span><span class="n">c</span><span class="k">:</span> <span class="kt">scala.reflect.macros.Context</span><span class="o">)</span>
<span class="o">(</span><span class="n">quote$Expr$1</span><span class="k">:</span> <span class="kt">c.Expr</span><span class="o">[</span><span class="kt">String</span><span class="o">])</span><span class="k">:</span> <span class="kt">c.Expr</span><span class="o">[</span><span class="kt">String</span><span class="o">]</span> <span class="k">=</span> <span class="o">{</span>
<span class="k">import</span> <span class="nn">c.universe._</span>
<span class="k">val</span> <span class="nv">Apply</span><span class="o">(</span><span class="k">_</span><span class="o">,</span> <span class="nc">List</span><span class="o">(</span><span class="n">selfTree$1</span><span class="o">))</span> <span class="k">=</span> <span class="nv">c</span><span class="o">.</span><span class="py">prefix</span><span class="o">.</span><span class="py">tree</span>
<span class="k">val</span> <span class="nv">self$Expr$1</span> <span class="k">=</span> <span class="nv">c</span><span class="o">.</span><span class="py">Expr</span><span class="o">[</span><span class="kt">Any</span><span class="o">](</span><span class="n">selfTree$1</span><span class="o">)</span>
<span class="nf">reify</span><span class="o">({</span>
<span class="k">val</span> <span class="nv">self</span> <span class="k">=</span> <span class="nv">self$Expr$1</span><span class="o">.</span><span class="py">splice</span>
<span class="k">val</span> <span class="nv">quote</span> <span class="k">=</span> <span class="nv">quote$Expr$1</span><span class="o">.</span><span class="py">splice</span>
<span class="n">quote</span> <span class="o">+</span> <span class="n">self</span> <span class="o">+</span> <span class="n">quote</span>
<span class="o">})</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div> </div>
</li>
</ul>
<p><em>Update(Feb 22th 2013): Updated the syntax to use @scalaxy.extend instead of @extend.</em></p>
<p><a href="https://github.com/ochafik/Scalaxy/tree/master/MacroExtensions/">The plugin</a> supports two kinds of body for extension methods: regular code, and macro.</p>
<ul>
<li>If the body looks like some regular method implementation, as above, it will wrap it in a reify call and will wrap all references to self and to the method parameters in splice calls.</li>
<li>If the body is a macro implementation, it will put it verbatim in the resulting macro:</li>
</ul>
<p><!-- https://gist.github.com/4994437 --></p>
<ul>
<li>
<p>Input.scala:</p>
<div class="language-scala highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@scalaxy</span><span class="o">.</span><span class="py">extension</span><span class="o">[</span><span class="kt">Any</span><span class="o">]</span>
<span class="k">def</span> <span class="nf">quoted</span><span class="o">(</span><span class="n">quote</span><span class="k">:</span> <span class="kt">String</span><span class="o">)</span><span class="k">:</span> <span class="kt">String</span> <span class="o">=</span> <span class="n">macro</span> <span class="o">{</span>
<span class="c1">// `c` is defined as the macro Context.</span>
<span class="c1">// `quote` and `self` are in scope, defined as `c.Expr[Any]` and `c.Expr[String]`.</span>
<span class="nf">println</span><span class="o">(</span><span class="n">s</span><span class="s">"Currently expanding ${c.prefix}.quoted(${quote.tree})"</span><span class="o">)</span>
<span class="c1">// `c.universe._` is automatically imported, so `reify` is in scope.</span>
<span class="nf">reify</span><span class="o">({</span>
<span class="c1">// Make sure we're not evaluating quote twice, in case it's a complex expression!</span>
<span class="k">val</span> <span class="nv">q</span> <span class="k">=</span> <span class="nv">quote</span><span class="o">.</span><span class="py">splice</span>
<span class="n">q</span> <span class="o">+</span> <span class="nv">self</span><span class="o">.</span><span class="py">splice</span> <span class="o">+</span> <span class="n">q</span>
<span class="o">})</span>
<span class="o">}</span>
</code></pre></div> </div>
</li>
<li>
<p>Output.scala:</p>
<div class="language-scala highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Transformed AST after the `scalaxy-extensions` compilation phase:</span>
<span class="k">import</span> <span class="nn">scala.language.experimental.macros</span>
<span class="k">implicit</span> <span class="k">class</span> <span class="nc">scalaxy$extensions$quoted$1</span><span class="o">(</span><span class="n">self</span><span class="k">:</span> <span class="kt">Any</span><span class="o">)</span> <span class="o">{</span>
<span class="k">def</span> <span class="nf">quoted</span><span class="o">(</span><span class="n">quote</span><span class="k">:</span> <span class="kt">String</span><span class="o">)</span> <span class="k">=</span> <span class="n">macro</span> <span class="nv">scalaxy$extensions$quoted$1</span><span class="o">.</span><span class="py">quoted</span>
<span class="o">}</span>
<span class="k">object</span> <span class="nc">scalaxy$extensions$quoted$1</span> <span class="o">{</span>
<span class="k">def</span> <span class="nf">quoted</span><span class="o">(</span><span class="n">c</span><span class="k">:</span> <span class="kt">scala.reflect.macros.Context</span><span class="o">)</span>
<span class="o">(</span><span class="n">quote</span><span class="k">:</span> <span class="kt">c.Expr</span><span class="o">[</span><span class="kt">String</span><span class="o">])</span><span class="k">:</span> <span class="kt">c.Expr</span><span class="o">[</span><span class="kt">String</span><span class="o">]</span> <span class="k">=</span> <span class="o">{</span>
<span class="k">import</span> <span class="nn">c.universe._</span>
<span class="k">val</span> <span class="nv">Apply</span><span class="o">(</span><span class="k">_</span><span class="o">,</span> <span class="nc">List</span><span class="o">(</span><span class="n">selfTree$1</span><span class="o">))</span> <span class="k">=</span> <span class="nv">c</span><span class="o">.</span><span class="py">prefix</span><span class="o">.</span><span class="py">tree</span>
<span class="k">val</span> <span class="nv">self</span> <span class="k">=</span> <span class="nv">c</span><span class="o">.</span><span class="py">Expr</span><span class="o">[</span><span class="kt">Any</span><span class="o">](</span><span class="n">selfTree$1</span><span class="o">)</span>
<span class="nf">reify</span><span class="o">({</span>
<span class="c1">// Make sure we're not evaluating quote twice, in case it's a complex expression!</span>
<span class="k">val</span> <span class="nv">q</span> <span class="k">=</span> <span class="nv">quote</span><span class="o">.</span><span class="py">splice</span>
<span class="n">q</span> <span class="o">+</span> <span class="nv">self</span><span class="o">.</span><span class="py">splice</span> <span class="o">+</span> <span class="n">q</span>
<span class="o">})</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div> </div>
</li>
</ul>
<p>If you find this cool, <a href="https://github.com/ochafik/Scalaxy/tree/master/MacroExtensions/">just give it a try!</a> (and <a href="https://twitter.com/ochafik">follow me on Twitter</a> if you want to hear about my next experiments :-)).</p>zOliveQuick link: Scalaxy/MacroExtensions on GitHubScalaxy/Debug: macros that make Predef.assert, require and assume a joy to use!2013-02-16T18:56:53+00:002013-02-16T18:56:53+00:00https://ochafik.github.io/scalaxydebug-macros-that-make-predef-assert-require-and-assume-a-joy-to-use<p><em>Quick link: jump to <a href="https://github.com/ochafik/Scalaxy/tree/master/Debug">Scalaxy/Debug</a> straight away!</em></p>
<p>Throughout languages, <a href="http://en.wikipedia.org/wiki/Assertion_(computing)">assertions</a> have proved to be a handy tool for programmers who want “light” error checks for very unlikely error cases (these checks are typically only performed in Debug builds so as not to slow down Release code).</p>
<p><a href="http://en.wikipedia.org/wiki/Assert.h">In C / C++, assert macros</a> usually print out the exact source code of the expression that failed the assertion check, which is often more than enough to understand the meaning of the failure.</p>
<p>In Java and Scala though, you have to provide your own message if you don’t want to be presented with an anonymous failure trace:</p>
<!-- https://gist.github.com/4967971 -->
<ul>
<li>
<p>SomeAssert.java:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">assert</span> <span class="n">x</span><span class="o">.</span><span class="na">getSize</span><span class="o">()</span> <span class="o">==</span> <span class="mi">2</span> <span class="o">:</span> <span class="s">"Size of x is not 2"</span><span class="o">;</span> <span class="c1">// Java assert</span>
</code></pre></div> </div>
</li>
<li>
<p>SomeAssert.scala:</p>
<div class="language-scala highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">assert</span><span class="o">(</span><span class="nv">x</span><span class="o">.</span><span class="py">size</span> <span class="o">==</span> <span class="mi">2</span><span class="o">,</span> <span class="s">"Size of x is not 2"</span><span class="o">)</span> <span class="c1">// Scala assert</span>
</code></pre></div> </div>
</li>
</ul>
<p>How often do you find yourself writing the following code?</p>
<!-- https://gist.github.com/4967904 -->
<div class="language-scala highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">assert</span><span class="o">(</span><span class="n">a</span> <span class="o">==</span> <span class="n">b</span><span class="o">,</span> <span class="s">"a == b ("</span> <span class="o">+</span> <span class="n">a</span> <span class="o">+</span> <span class="s">" != "</span> <span class="o">+</span> <span class="n">b</span> <span class="o">+</span> <span class="s">")"</span><span class="o">)</span>
</code></pre></div></div>
<p>Or, more recently (<a href="http://docs.scala-lang.org/overviews/core/string-interpolation.html">string interpolation</a> FTW!):</p>
<!-- https://gist.github.com/4967906 -->
<div class="language-scala highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">assert</span><span class="o">(</span><span class="n">a</span> <span class="o">==</span> <span class="n">b</span><span class="o">,</span> <span class="n">s</span><span class="s">"a == b ($a != $b)"</span><span class="o">)</span>
</code></pre></div></div>
<p>Well, thanks to <a href="https://github.com/ochafik/Scalaxy/tree/master/Debug">Scalaxy/Debug</a> macros, you can now forget about this kind of grungy code:</p>
<!-- https://gist.github.com/4967916 -->
<div class="language-scala highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="nn">scalaxy.debug._</span>
<span class="k">val</span> <span class="nv">a</span> <span class="k">=</span> <span class="mi">10</span>
<span class="k">val</span> <span class="nv">b</span> <span class="k">=</span> <span class="mi">12</span>
<span class="nf">assert</span><span class="o">(</span><span class="n">a</span> <span class="o">==</span> <span class="n">b</span><span class="o">)</span>
<span class="c1">// this will throw:</span>
<span class="c1">// "assertion failed: a == b (10 != 12)"</span>
</code></pre></div></div>
<p>You just need to add the following to your build.sbt file to get going:</p>
<!-- https://gist.github.com/4967923 -->
<div class="language-scala highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Only works with 2.10.0+</span>
<span class="n">scalaVersion</span> <span class="o">:=</span> <span class="s">"2.10.0"</span>
<span class="c1">// Dependency at compilation-time only (not at runtime).</span>
<span class="n">libraryDependencies</span> <span class="o">+=</span> <span class="s">"com.nativelibs4java"</span> <span class="o">%%</span> <span class="s">"scalaxy-debug"</span> <span class="o">%</span> <span class="s">"0.3-SNAPSHOT"</span> <span class="o">%</span> <span class="s">"provided"</span>
<span class="c1">// Scalaxy/Debug snapshots are published on the Sonatype repository.</span>
<span class="n">resolvers</span> <span class="o">+=</span> <span class="nv">Resolver</span><span class="o">.</span><span class="py">sonatypeRepo</span><span class="o">(</span><span class="s">"snapshots"</span><span class="o">)</span>
</code></pre></div></div>
<p>Oh, and this works with <a href="http://daily-scala.blogspot.co.uk/2010/03/assert-require-assume.html">assert, assume and require</a>.</p>
<p>Enjoy! (please file any bug on <a href="https://github.com/ochafik/Scalaxy/tree/master/Debug">Scalaxy/Debug’s GitHub</a> and <a href="https://twitter.com/ochafik">follow me on Twitter</a> if you find this useful :-))</p>zOliveQuick link: jump to Scalaxy/Debug straight away!Scalaxy/Loops: Optimized foreach loops for Scala 2.10.0 have landed (+ recap on ScalaCL)2013-02-12T16:02:44+00:002013-02-12T16:02:44+00:00https://ochafik.github.io/scalaxyloops-optimized-foreach-loops-for-scala-2-10-0-have-landed-recap-on-scalacl<p><em>In a hurry? Skip this lengthy post and go straight to <a href="https://github.com/ochafik/Scalaxy/tree/master/Loops/">Scalaxy/Loops</a>!</em></p>
<p><em>Update</em>: edited description of what “-inline” does in the last-but-one section.</p>
<p><strong>Recap on an interesting performance issue</strong></p>
<p>A couple of years back, I created a startup with a friend and got to write all our code in Scala, which included some Monte Carlo simulations for logistics planning optimization.</p>
<p>I was horrified to see that my seemingly barebones code didn’t run nearly as fast as I expected:</p>
<!-- https://gist.github.com/4770096 -->
<div class="language-scala highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">for</span> <span class="o">(</span><span class="n">iteration</span> <span class="k"><-</span> <span class="mi">0</span> <span class="n">until</span> <span class="n">iterations</span><span class="o">)</span> <span class="o">{</span>
<span class="nf">for</span> <span class="o">(</span><span class="n">i</span> <span class="k"><-</span> <span class="mi">0</span> <span class="n">until</span> <span class="n">n</span><span class="o">)</span> <span class="o">{</span>
<span class="o">...</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p>The reason why this code is much slower than its Java equivalent for loop is that it is desugared as…</p>
<!-- https://gist.github.com/4770099 -->
<div class="language-scala highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">(</span><span class="mi">0</span> <span class="n">until</span> <span class="n">iterations</span><span class="o">).</span><span class="py">foreach</span><span class="o">(</span><span class="n">iteration</span> <span class="k">=></span> <span class="o">{</span>
<span class="o">(</span><span class="mi">0</span> <span class="n">until</span> <span class="n">n</span><span class="o">).</span><span class="py">foreach</span><span class="o">(</span><span class="n">i</span> <span class="k">=></span> <span class="o">{</span>
<span class="o">...</span>
<span class="o">})</span>
<span class="o">})</span>
</code></pre></div></div>
<p>… which creates a couple of objects at runtime and performs a truckload of method calls on them (each of these closures is an object, so the outer closure is created once and the inner closure is created once per iteration, and of course there’s a cost for calling each of them in each inner or outer loop iteration).</p>
<p>When I discovered this, I found myself starting to rewrite my code using while loops, like this:</p>
<!-- https://gist.github.com/4770105 -->
<div class="language-scala highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">{</span>
<span class="k">var</span> <span class="n">iteration</span> <span class="k">=</span> <span class="mi">0</span>
<span class="nf">while</span> <span class="o">(</span><span class="n">iteration</span> <span class="o"><</span> <span class="n">iterations</span><span class="o">)</span> <span class="o">{</span>
<span class="k">var</span> <span class="n">i</span> <span class="k">=</span> <span class="mi">0</span>
<span class="nf">while</span> <span class="o">(</span><span class="n">i</span> <span class="o"><</span> <span class="n">n</span><span class="o">)</span> <span class="o">{</span>
<span class="o">...</span>
<span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="o">}</span>
<span class="n">iteration</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p>But then my code became harder to read (I actually had nested loops on arrays, which looks even worse than ranges), and I wondered why I was doing this in Scala at the first place. <em>Something had to be done</em>.</p>
<p><em>Update</em>: also see this great post on <a href="http://dynamicsofprogramming.blogspot.co.uk/2013/01/loop-performance-and-local-variables-in.html">Loop Performance and Local Variables in Scala</a> by Mark Lewis.</p>
<p><strong>A first solution: compiler plugins (and ScalaCL was born!)</strong></p>
<p>When I decided I couldn’t write while loops by hand, it’s quite naturally that I turned to <a href="http://www.scala-lang.org/node/140">Scala compiler plugins</a>.</p>
<p>Steep learning curve, quite a few rough edges, but I soon released <a href="https://code.google.com/p/scalacl/wiki/ScalaCLPlugin">an optimizing compiler plugin</a> that covered all of my needs: Range, Array, List with foreach, map, reduce, fold, scan… you name it!</p>
<p>Despite my repeated red warnings that this was experimental-ware, people started using <a href="https://code.google.com/p/scalacl">ScalaCL</a> for production purposes, I went to present ScalaCL at <a href="http://scalathon.org/2011/projects.html">Scalathon 2011</a> and <a href="http://www.devoxx.com/display/FR12/GPGPU+facile+avec+JavaCL,+et+trivial+avec+ScalaCL+!">Devoxx France 2012</a>, and the sky was blue (oh, and it was also capable of running Scala on GPUs in a very experimental way, incidentally, which may have confused a few…).</p>
<p>In the last months where I had time to work on that project, I started optimizing chains of collection calls, ending up with quite a complex piece of engineering that I eventually didn’t stabilize (version 0.3 was almost ready… and now it’s quite stale 🙁 ).</p>
<p>The catch with ScalaCL was:</p>
<ul>
<li>Compiler plugins are a pain to write, and debug.</li>
<li>The internal APIs can be broken at every new release, making maintenance quite risky (and since I already had a few open-source projects to maintain, I had hardly enough hobby time left: <a href="https://code.google.com/p/jnaerator/">JNAerator</a>, <a href="https://code.google.com/p/bridj/">BridJ</a> and <a href="https://code.google.com/p/javacl/">JavaCL</a>).</li>
<li>Using the compiler plugin requires some special arguments for the compiler, and this scares some people off.</li>
</ul>
<p><strong>A new approach: macros</strong></p>
<p>Now with Scala 2.10, we’ve got a shiny new API that exposes the internals of the compiler in a clean and (hopefully) future-proof way (although it’s still an experimental feature), which doesn’t require any setup of a compiler plugin.</p>
<p>Moreover, it brings an extremely powerful “reification” mechanism which allows for painless AST construction from macros.</p>
<p>Playing around with <a href="/p_803">Scalaxy/Beans</a> and <a href="https://github.com/ochafik/Scalaxy/tree/master/Fx">Scalaxy/Fx</a> last week just wasn’t enough: I had to restart my work on loops with macros:</p>
<p><a href="https://github.com/ochafik/Scalaxy/tree/master/Loops">Scalaxy/Loops</a></p>
<p>This concludes a year of catching up with Scala 2.10 milestones, with various rewrites of ScalaCL and Scalaxy (+ an experiment on <a href="https://github.com/ochafik/Scalaxy/tree/master/Compilets">Compilets</a>), and the scope is voluntarily smaller than before: <em>Scalaxy/Loops</em> optimizes simple loops (and does it well), period.</p>
<p><strong>How to make your loops faster in 30 seconds</strong></p>
<p>If you’ve started using Scala 2.10 and use Sbt, you’re in luck: just edit your <em>build.sbt</em> file as follows:</p>
<!-- https://gist.github.com/4770208 -->
<div class="language-scala highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Only works with 2.10.0+</span>
<span class="n">scalaVersion</span> <span class="o">:=</span> <span class="s">"2.10.0"</span>
<span class="c1">// Dependency at compilation-time only (not at runtime).</span>
<span class="n">libraryDependencies</span> <span class="o">+=</span> <span class="s">"com.nativelibs4java"</span> <span class="o">%%</span> <span class="s">"scalaxy-loops"</span> <span class="o">%</span> <span class="s">"0.3-SNAPSHOT"</span> <span class="o">%</span> <span class="s">"provided"</span>
<span class="c1">// Scalaxy/Loops snapshots are published on the Sonatype repository.</span>
<span class="n">resolvers</span> <span class="o">+=</span> <span class="nv">Resolver</span><span class="o">.</span><span class="py">sonatypeRepo</span><span class="o">(</span><span class="s">"snapshots"</span><span class="o">)</span>
</code></pre></div></div>
<p>Now you just need to <em>import scalaxy.loops.__ and append _optimized</em> to all the ranges which <em>foreach</em> loops you want to optimize:</p>
<!-- https://gist.github.com/4770222 -->
<div class="language-scala highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="nn">scalaxy.loops._</span>
<span class="nf">for</span> <span class="o">(</span><span class="n">iteration</span> <span class="k"><-</span> <span class="mi">0</span> <span class="n">until</span> <span class="n">iterations</span> <span class="n">optimized</span><span class="o">)</span> <span class="o">{</span>
<span class="nf">for</span> <span class="o">(</span><span class="n">i</span> <span class="k"><-</span> <span class="mi">0</span> <span class="n">until</span> <span class="n">n</span> <span class="n">optimized</span><span class="o">)</span> <span class="o">{</span>
<span class="o">...</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p>That’s it!</p>
<p>(so far it’s limited to Range.foreach, but Range.map and Array.map / .foreach might follow soon)</p>
<p><strong>Cool, but (why) is it (still) faster?</strong></p>
<p>Oh yeah, it’s faster!</p>
<p>I’m uncomfortable announcing speedups because it depends on your JVM, on your code, etc… But see for yourself (expect x3+ speedups for tight loops):</p>
<p><a href="https://github.com/ochafik/Scalaxy/tree/master/Loops/Benchmarks">Scalaxy/Loops naive Benchmark</a></p>
<p>Now for the “why”, it’s a bit more complicated. My understanding is that the Scala team didn’t want to invest resources into such “specific” optimizations and instead chose to focus on more generalistic ones, like inlining.</p>
<p>Looking at code compiled with “-optimise -Yinline -Yclosure-elim” in 2.10, you can see that Range foreach method is indeed inlined… But not its closure (the call of which is what takes all the time 🙁 ).</p>
<p><em>Update</em>: there’s some <a href="http://magarciaepfl.github.com/scala/">amazing work on a new Scalac optimizer</a> going on, hope it magically solves all our issues in a future version!</p>
<p>Anyway, hope it’s useful to some people, and stay tuned for a stable release soon.</p>
<p><strong>Keep in touch</strong></p>
<p>Whether you <a href="https://github.com/ochafik/Scalaxy/issues">file bugs in Scalaxy’s tracker</a>, join the <a href="http://groups.google.com/group/nativelibs4java">NativeLibs4Java mailing-list</a> or <a href="https://twitter.com/ochafik">ping me on Twitter (@ochafik)</a>, any feedback or help will be greatly appreciated!</p>zOliveIn a hurry? Skip this lengthy post and go straight to Scalaxy/Loops!Scalaxy/Beans: type-safe macro-powered syntax candy for your Java beans in Scala.2013-02-11T11:18:24+00:002013-02-11T11:18:24+00:00https://ochafik.github.io/scalaxybeans-type-safe-macro-powered-syntax-candy-for-your-java-beans-in-scala<p>Following up on my previous post that described a <a href="/p_786">Type-safe dynamic beans factory with Scala 2.10 macros + Dynamic</a>, I’ve modified the syntax of the hack…</p>
<!-- https://gist.github.com/4753654 -->
<ul>
<li>
<p>an_example.scala:</p>
<div class="language-scala highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="nn">scalaxy.beans._</span>
<span class="k">new</span> <span class="nc">MyBean</span><span class="o">().</span><span class="py">set</span><span class="o">(</span><span class="n">foo</span> <span class="k">=</span> <span class="mi">10</span><span class="o">,</span> <span class="n">bar</span> <span class="k">=</span> <span class="mi">12</span><span class="o">)</span>
</code></pre></div> </div>
</li>
<li>
<p>build.sbt:</p>
<div class="language-scala highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Only works with 2.10.0+</span>
<span class="n">scalaVersion</span> <span class="o">:=</span> <span class="s">"2.10.0"</span>
<span class="c1">// Dependency at compilation-time only (not at runtime).</span>
<span class="n">libraryDependencies</span> <span class="o">+=</span> <span class="s">"com.nativelibs4java"</span> <span class="o">%%</span> <span class="s">"scalaxy-beans"</span> <span class="o">%</span> <span class="s">"0.3-SNAPSHOT"</span> <span class="o">%</span> <span class="s">"provided"</span>
<span class="c1">// Scalaxy/Beans snapshots are published on the Sonatype repository.</span>
<span class="n">resolvers</span> <span class="o">+=</span> <span class="nv">Resolver</span><span class="o">.</span><span class="py">sonatypeRepo</span><span class="o">(</span><span class="s">"snapshots"</span><span class="o">)</span>
</code></pre></div> </div>
</li>
</ul>
<p>… and made it available for use in Maven / Sbt projects.</p>
<p>Sources and tests are available on <a href="https://github.com/ochafik/Scalaxy/tree/master/Beans">GitHub in Scalaxy/Beans</a>.</p>
<p>Enjoy!</p>zOliveFollowing up on my previous post that described a Type-safe dynamic beans factory with Scala 2.10 macros + Dynamic, I’ve modified the syntax of the hack…Type-safe dynamic beans factory with Scala 2.10 macros + Dynamic2013-02-08T01:16:58+00:002013-02-08T01:16:58+00:00https://ochafik.github.io/type-safe-dynamic-beans-factory-with-scala-2-10-macros-dynamic<p>With <a href="http://www.scala-lang.org/node/27499">Scala 2.10.0</a> just out, we’ve now got a couple of shiny new toys:</p>
<ul>
<li><a href="http://docs.scala-lang.org/overviews/macros/overview.html">Macros</a> provide a clean (but experimental) way to plug into the Scala compiler, making AST rewrites very easy and mostly type-safe.</li>
<li><a href="http://docs.scala-lang.org/sips/pending/type-dynamic.html">Dynamic</a> is a type that lets you hijack method calls to predefined “fallback” methods (<a href="http://www.scala-lang.org/archives/downloads/distrib/files/nightly/docs/library/index.html#scala.Dynamic">applyDynamic and al.</a>).</li>
</ul>
<p>The very interesting thing here is that despite its name, Dynamic only involves compile-time routing of unknown methods… and it is possible to implement applyDynamic using a macro!</p>
<p>This means using Dynamic you can create DSLs with code that is loosely typed (in Scala type system terms) and with macros we can still add your own custom compilation-time type-checks, and even rewrite the code so that it no longer refers to Dynamic at the first place!</p>
<p><strong>Some practice: a type-safe dynamic beans factory</strong></p>
<p>Java Beans are a bit tedious to create from Scala:</p>
<!-- https://gist.github.com/4735505 -->
<div class="language-scala highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">{</span>
<span class="k">val</span> <span class="nv">bean</span> <span class="k">=</span> <span class="k">new</span> <span class="nc">MyBean</span>
<span class="nv">bean</span><span class="o">.</span><span class="py">setFoo</span><span class="o">(</span><span class="mi">10</span><span class="o">)</span>
<span class="nv">bean</span><span class="o">.</span><span class="py">setBar</span><span class="o">(</span><span class="mi">12</span><span class="o">)</span>
<span class="n">bean</span>
<span class="o">}</span>
</code></pre></div></div>
<p>Well, with a Dynamic subclass that implements applyDynamicNamed using a macro, we can reach the following syntax:</p>
<!-- https://gist.github.com/4735506 -->
<div class="language-scala highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">beans</span><span class="o">.</span><span class="py">create</span><span class="o">[</span><span class="kt">MyBean</span><span class="o">](</span>
<span class="n">foo</span> <span class="k">=</span> <span class="mi">10</span><span class="o">,</span>
<span class="n">bar</span> <span class="k">=</span> <span class="mi">12</span>
<span class="o">)</span>
<span class="cm">/*
UPDATE: the latest code in github (see link below) implements
the following, more flexible and friendly syntax:
new MyBean().set(
foo = 10,
bar = 12
)
*/</span>
</code></pre></div></div>
<p>And of course, this is all type-checked and <strong>rewritten to the exact same setter-intensive code as above</strong>, with the exact same runtime performance (nifty, isn’t it?).</p>
<p>Enjoy! (see newest <a href="https://github.com/ochafik/Scalaxy/blob/master/Beans/">sources and tests in Scalaxy’s repository</a>)</p>
<!-- https://gist.github.com/4737530 -->
<div class="language-scala highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">package</span> <span class="nn">scalaxy</span>
<span class="k">import</span> <span class="nn">scala.language.dynamics</span>
<span class="k">import</span> <span class="nn">scala.reflect.NameTransformer</span>
<span class="k">import</span> <span class="nn">scala.reflect.macros.Context</span>
<span class="cm">/**
Syntactic sugar to instantiate Java beans with a very Scala-friendly syntax.
(full sources and tests: https://github.com/ochafik/Scalaxy/tree/master/Beans)
The following expression:
import scalaxy.beans
beans.create[MyBean](
foo = 10,
bar = 12
)
Gets replaced (and type-checked) at compile time by:
{
val bean = new MyBean
bean.setFoo(10)
bean.setBar(12)
bean
}
Doesn't bring any runtime dependency (macro is self-erasing).
Don't expect code completion from your IDE as of yet.
*/</span>
<span class="k">object</span> <span class="nc">beans</span> <span class="k">extends</span> <span class="nc">Dynamic</span>
<span class="o">{</span>
<span class="k">def</span> <span class="nf">applyDynamicNamedImpl</span><span class="o">[</span><span class="kt">R</span> <span class="kt">:</span> <span class="kt">c.WeakTypeTag</span><span class="o">]</span>
<span class="o">(</span><span class="n">c</span><span class="k">:</span> <span class="kt">Context</span><span class="o">)</span>
<span class="o">(</span><span class="n">name</span><span class="k">:</span> <span class="kt">c.Expr</span><span class="o">[</span><span class="kt">String</span><span class="o">])</span>
<span class="o">(</span><span class="n">args</span><span class="k">:</span> <span class="kt">c.Expr</span><span class="o">[(</span><span class="kt">String</span>, <span class="kt">Any</span><span class="o">)]*)</span> <span class="k">:</span> <span class="kt">c.Expr</span><span class="o">[</span><span class="kt">R</span><span class="o">]</span> <span class="k">=</span>
<span class="o">{</span>
<span class="k">import</span> <span class="nn">c.universe._</span>
<span class="c1">// Check that the method name is "create".</span>
<span class="nv">name</span><span class="o">.</span><span class="py">tree</span> <span class="k">match</span> <span class="o">{</span>
<span class="k">case</span> <span class="nc">Literal</span><span class="o">(</span><span class="nc">Constant</span><span class="o">(</span><span class="n">n</span><span class="o">))</span> <span class="k">=></span>
<span class="nf">if</span> <span class="o">(</span><span class="n">n</span> <span class="o">!=</span> <span class="s">"create"</span><span class="o">)</span>
<span class="nv">c</span><span class="o">.</span><span class="py">error</span><span class="o">(</span><span class="nv">name</span><span class="o">.</span><span class="py">tree</span><span class="o">.</span><span class="py">pos</span><span class="o">,</span> <span class="n">s</span><span class="s">"Expected 'create', got '$n'"</span><span class="o">)</span>
<span class="k">case</span> <span class="k">_</span> <span class="k">=></span>
<span class="nv">c</span><span class="o">.</span><span class="py">error</span><span class="o">(</span><span class="nv">name</span><span class="o">.</span><span class="py">tree</span><span class="o">.</span><span class="py">pos</span><span class="o">,</span> <span class="s">"Unexpected name structure error"</span><span class="o">)</span>
<span class="o">}</span>
<span class="c1">// Get the bean type.</span>
<span class="k">val</span> <span class="nv">beanTpe</span> <span class="k">=</span> <span class="n">weakTypeTag</span><span class="o">[</span><span class="kt">R</span><span class="o">].</span><span class="py">tpe</span>
<span class="c1">// Choose a non-existing name for our bean's val.</span>
<span class="k">val</span> <span class="nv">beanName</span> <span class="k">=</span>
<span class="nf">newTermName</span><span class="o">(</span><span class="nv">c</span><span class="o">.</span><span class="py">fresh</span><span class="o">(</span><span class="s">"bean"</span><span class="o">))</span>
<span class="c1">// Create a declaration for our bean's val.</span>
<span class="k">val</span> <span class="nv">beanDef</span> <span class="k">=</span>
<span class="nc">ValDef</span><span class="o">(</span><span class="nc">Modifiers</span><span class="o">(),</span> <span class="n">beanName</span><span class="o">,</span> <span class="nc">TypeTree</span><span class="o">(</span><span class="n">beanTpe</span><span class="o">),</span> <span class="nc">New</span><span class="o">(</span><span class="nc">TypeTree</span><span class="o">(</span><span class="n">beanTpe</span><span class="o">),</span> <span class="nc">Nil</span><span class="o">))</span>
<span class="c1">// Try to find a setter in the bean type that can take values of the type we've got.</span>
<span class="k">def</span> <span class="nf">getSetter</span><span class="o">(</span><span class="n">name</span><span class="k">:</span> <span class="kt">String</span><span class="o">,</span> <span class="n">valueTpe</span><span class="k">:</span> <span class="kt">Type</span><span class="o">,</span> <span class="n">valuePos</span><span class="k">:</span> <span class="kt">Position</span><span class="o">)</span> <span class="k">=</span> <span class="o">{</span>
<span class="nv">beanTpe</span><span class="o">.</span><span class="py">member</span><span class="o">(</span><span class="nf">newTermName</span><span class="o">(</span><span class="n">name</span><span class="o">)).</span><span class="py">filter</span> <span class="o">{</span>
<span class="k">case</span> <span class="n">s</span> <span class="k">=></span>
<span class="nv">s</span><span class="o">.</span><span class="py">isMethod</span> <span class="o">&&</span> <span class="o">(</span>
<span class="nv">s</span><span class="o">.</span><span class="py">asMethod</span><span class="o">.</span><span class="py">paramss</span><span class="o">.</span><span class="py">flatten</span> <span class="k">match</span> <span class="o">{</span>
<span class="k">case</span> <span class="nc">Seq</span><span class="o">(</span><span class="n">param</span><span class="o">)</span> <span class="k">=></span>
<span class="c1">// Check that the parameter can be assigned a convertible type.</span>
<span class="c1">// (typeOf[Int] weak_<:< typeOf[Double]) == true.</span>
<span class="nf">if</span> <span class="o">(!(</span><span class="n">valueTpe</span> <span class="n">weak_<:<</span> <span class="nv">param</span><span class="o">.</span><span class="py">typeSignature</span><span class="o">))</span>
<span class="nv">c</span><span class="o">.</span><span class="py">error</span><span class="o">(</span><span class="n">valuePos</span><span class="o">,</span> <span class="n">s</span><span class="s">"Value of type $valueTpe cannot be set with $beanTpe.$name(${param.typeSignature})"</span><span class="o">)</span>
<span class="kc">true</span>
<span class="k">case</span> <span class="k">_</span> <span class="k">=></span>
<span class="kc">false</span>
<span class="o">}</span>
<span class="o">)</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="c1">// Generate one setter call per argument.</span>
<span class="k">val</span> <span class="nv">setterCalls</span> <span class="k">=</span> <span class="nv">args</span><span class="o">.</span><span class="py">map</span><span class="o">(</span><span class="nv">_</span><span class="o">.</span><span class="py">tree</span><span class="o">).</span><span class="py">map</span>
<span class="o">{</span>
<span class="c1">// Match Tuple2.apply[String, Any](fieldName, value).</span>
<span class="k">case</span> <span class="nc">Apply</span><span class="o">(</span><span class="k">_</span><span class="o">,</span> <span class="nc">List</span><span class="o">(</span><span class="n">n</span> <span class="k">@</span> <span class="nc">Literal</span><span class="o">(</span><span class="nc">Constant</span><span class="o">(</span><span class="n">fieldName</span><span class="k">:</span> <span class="kt">String</span><span class="o">)),</span> <span class="n">v</span> <span class="k">@</span> <span class="n">value</span><span class="o">))</span> <span class="k">=></span>
<span class="c1">// Check that all parameters are named.</span>
<span class="nf">if</span> <span class="o">(</span><span class="n">fieldName</span> <span class="o">==</span> <span class="kc">null</span> <span class="o">||</span> <span class="n">fieldName</span> <span class="o">==</span> <span class="s">""</span><span class="o">)</span>
<span class="nv">c</span><span class="o">.</span><span class="py">error</span><span class="o">(</span><span class="nv">v</span><span class="o">.</span><span class="py">pos</span><span class="o">,</span> <span class="s">"Please use named parameters."</span><span class="o">)</span>
<span class="c1">// Get beans-style setter or Scala-style var setter.</span>
<span class="k">val</span> <span class="nv">setterSymbol</span> <span class="k">=</span>
<span class="nf">getSetter</span><span class="o">(</span><span class="s">"set"</span> <span class="o">+</span> <span class="nv">fieldName</span><span class="o">.</span><span class="py">capitalize</span><span class="o">,</span> <span class="nv">value</span><span class="o">.</span><span class="py">tpe</span><span class="o">,</span> <span class="nv">v</span><span class="o">.</span><span class="py">pos</span><span class="o">)</span>
<span class="o">.</span><span class="py">orElse</span><span class="o">(</span><span class="nf">getSetter</span><span class="o">(</span><span class="nv">NameTransformer</span><span class="o">.</span><span class="py">encode</span><span class="o">(</span><span class="n">fieldName</span> <span class="o">+</span> <span class="s">"_="</span><span class="o">),</span> <span class="nv">value</span><span class="o">.</span><span class="py">tpe</span><span class="o">,</span> <span class="nv">v</span><span class="o">.</span><span class="py">pos</span><span class="o">))</span>
<span class="nf">if</span> <span class="o">(</span><span class="n">setterSymbol</span> <span class="o">==</span> <span class="nc">NoSymbol</span><span class="o">)</span>
<span class="nv">c</span><span class="o">.</span><span class="py">error</span><span class="o">(</span><span class="nv">n</span><span class="o">.</span><span class="py">pos</span><span class="o">,</span> <span class="n">s</span><span class="s">"Couldn't find a setter for field '$fieldName' in type $beanTpe"</span><span class="o">)</span>
<span class="nc">Apply</span><span class="o">(</span><span class="nc">Select</span><span class="o">(</span><span class="nc">Ident</span><span class="o">(</span><span class="n">beanName</span><span class="o">),</span> <span class="n">setterSymbol</span><span class="o">),</span> <span class="nc">List</span><span class="o">(</span><span class="n">value</span><span class="o">))</span>
<span class="o">}</span>
<span class="c1">// Build a block with the bean declaration, the setter calls and return the bean.</span>
<span class="nv">c</span><span class="o">.</span><span class="py">Expr</span><span class="o">[</span><span class="kt">R</span><span class="o">](</span><span class="nc">Block</span><span class="o">(</span><span class="nc">Seq</span><span class="o">(</span><span class="n">beanDef</span><span class="o">)</span> <span class="o">++</span> <span class="n">setterCalls</span> <span class="o">:+</span> <span class="nc">Ident</span><span class="o">(</span><span class="n">beanName</span><span class="o">)</span><span class="k">:</span> <span class="k">_</span><span class="kt">*</span><span class="o">))</span>
<span class="o">}</span>
<span class="k">def</span> <span class="nf">applyDynamicNamed</span><span class="o">[</span><span class="kt">R</span><span class="o">](</span><span class="n">name</span><span class="k">:</span> <span class="kt">String</span><span class="o">)(</span><span class="n">args</span><span class="k">:</span> <span class="o">(</span><span class="kt">String</span><span class="o">,</span> <span class="kt">Any</span><span class="o">)*)</span><span class="k">:</span> <span class="kt">R</span> <span class="o">=</span>
<span class="n">macro</span> <span class="n">applyDynamicNamedImpl</span><span class="o">[</span><span class="kt">R</span><span class="o">]</span>
<span class="o">}</span>
</code></pre></div></div>zOliveWith Scala 2.10.0 just out, we’ve now got a couple of shiny new toys:JavaCL 1.0.0-RC3 released: massive performance improvements, bugfixes, OSGi2013-01-08T16:43:21+00:002013-01-08T16:43:21+00:00https://ochafik.github.io/javacl-1-0-0-rc3-released-massive-performance-improvements-bugfixes<p><a href="http://code.google.com/p/javacl/">JavaCL</a> v1.0.0 RC3 is available!</p>
<table>
<tbody>
<tr>
<td><a href="http://code.google.com/p/javacl/wiki/Usage" target="_blank">Download / Install</a> </td>
<td> <a href="http://nativelibs4java.sourceforge.net/javacl/api/stable" target="_blank">Browse JavaDoc</a> </td>
<td> <a href="http://code.google.com/p/javacl/wiki/GettingStarted" target="_blank">Getting Started (Tutorial)</a> </td>
<td> <a href="http://groups.google.fr/group/nativelibs4java/" target="_blank">Discuss</a></td>
</tr>
</tbody>
</table>
<p>JavaCL is a BSD-licensed library that lets you use OpenCL from Java, in order to run massively-parallel computations on your graphic card (and/or CPU).</p>
<h2 id="release-notes">Release Notes</h2>
<p>Here are the main changes between <a href="/p_747">1.0.0-RC2</a> and 1.0.0-RC3 (<a href="https://github.com/ochafik/nativelibs4java/blob/master/libraries/OpenCL/CHANGELOG" target="_blank">see full change log</a>) :</p>
<ul>
<li>Fixed byte order hack for ATI platforms</li>
<li>Fixes / optimized event callbacks (but broke API: CLEvent.EventCallback now only takes the completion status as argument, not the event anymore)</li>
<li>Fixed library probe</li>
<li>Fixed handling of image2d_t and image3d_t in Maven plugin (contrib. from Remi Emonet, request #308 and <a href="https://github.com/ochafik/nativelibs4java/issues/307">issue #307</a>)</li>
<li>Fixed OpenGL interop on Windows (<a href="https://github.com/ochafik/nativelibs4java/issues/312">issue #312</a>)</li>
<li>Fixed error about mismatching byte order for byte buffers, and replaced mentions to getKernelsDefaultByteOrder() by getByteOrder() (<a href="https://github.com/ochafik/nativelibs4java/issues/336">issue #336</a>)</li>
<li>Fixed AMD App 2.7 Linux library loading code for</li>
<li>Fixed AMD download link in demos.</li>
<li>Added CLEvent.FIRE_AND_FORGET to avoid returning events from all the methods that accept a vararg eventsToWaitFor.</li>
<li>Added naive OSGi support to the main JAR.</li>
<li>Added list of devices in program errors.</li>
<li>Added CLBuffer.allocateCompatibleMemory(CLDevice)</li>
<li>Added client properties to CLContext (lazy + concurrent)</li>
<li>Optimized low-level bindings on OpenCL 1.1+ platforms, with dynamic runtime switch (removed synchronized keyword from all native calls), and made OpenCL 1.0 synchronization a warning.</li>
<li>Enhanced CLDevice.toString (include platform name)</li>
<li>Deprecated CLKernel.enqueueNDRange with int[] parameters</li>
<li>Return CLUserEvent from CLContext.createUserEvent();</li>
</ul>
<h2 id="getting-started">Getting started</h2>
<p>You can read the <a href="http://code.google.com/p/javacl/wiki/GettingStarted" target="_blank">Getting Started (Tutorial) page</a> on the wiki to get started very quickly !</p>
<p>Please join the <a href="http://groups.google.fr/group/nativelibs4java/" target="_blank">NativeLibs4Java Google Group</a> to discuss JavaCL / ScalaCL, get the latest news and ask for support from the growing JavaCL community.</p>zOliveJavaCL v1.0.0 RC3 is available!