-
Notifications
You must be signed in to change notification settings - Fork 0
/
rss.xml
921 lines (822 loc) · 148 KB
/
rss.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Ian's Blog</title><link>http://insertinterestingnamehere.github.io/</link><description>My comments on math, numerical computing, and the tools used for computational science.</description><atom:link href="http://insertinterestingnamehere.github.io/rss.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><lastBuildDate>Mon, 21 Dec 2020 02:30:10 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>A Brief Intro to Family History</title><link>http://insertinterestingnamehere.github.io/posts/a-brief-intro-to-family-history/</link><dc:creator>Ian Henriksen</dc:creator><description><div><h2>Forward</h2>
<p>This post has been a long time in coming.
I've been fortunate to have taught a few family history classes in my church over the past several years.
There hasn't been a fixed curriculum that has suited our needs, so each time I and those I was working with improvised course materials roughly along the lines of what's presented here.
My original intent was to write this series of blog posts as a way to make family history more approachable for people during the lockdowns caused by the COVID-19 pandemic.
It's been a crazy year and although time at home abounds, time for side projects has been at a minimum.
Still, with vaccines arriving soon, I suspect that there will continue to be a need for this material both in the immediate future as the pandemic roars to a close and as we all try to pick up life afterward.</p>
<p>What I present here I learned mostly from my parents.
I went on my mission and came back to find them embroiled in family history work.
This was surprising since noone in my immediate family had been involved much in family history work, but it was not unwelcome.
In our church we're tought that families are an eternal organization and that, as a part of that, the duty of each of us is to search out our ancestors.
Up to that point, I had understood that this was a "thing", but had never really understood the practical details of what it involved.
Fortunately my parents figured out some of the not-so-hard details and shared them with me.
I'm not an expert by any means, but I know there's a need for simple introductory material on the practical side of family history work.
This is my attempt to fill that need.</p>
<p>These posts will be mostly geared towards members of the Church of Jesus Christ of Latter Day Saints who are interested in getting started on their family history.
That said, I'll do my best to make the writing approachable so that the material is easy for anyone to follow.</p>
<h2>Outline</h2>
<p>These posts will follow roughly the following outline:</p>
<ul>
<li>Intro (this post)</li>
<li>What does "family history" even mean?<ul>
<li>What role does it play in Church of Jesus Christ of Latter Day Saints?</li>
<li>What does FamilySearch have to do with this?</li>
</ul>
</li>
<li>How does someone "find" a family member?<ul>
<li>What searching services are freely available?</li>
</ul>
</li>
<li>How do I connect to deceased relatives already recorded in FamilySearch?</li>
<li>How do I find new names if my tree isn't filled in?</li>
<li>How do I find new names if my tree has already been researched to death?</li>
<li>What about sources?</li>
<li>What constitutes a reputable source?</li>
<li>What about duplicates?</li>
<li>What if I make mistakes?</li>
<li>What about indexing?</li>
<li>How do I avoid getting stuck?</li>
<li>How do I better utilize search tools?</li>
<li>How do I help others get started with family history?</li>
</ul>
<p>I'll try to come back and link the individual posts here and update this outline as the series of posts progresses.
The material in these first posts should be relatively universal, but there will still be some bias from the fact that most of the work I've done has involved finding people who lived in England in the 1800's.
It turns out that you can get pretty far with that in my family.</p>
<p>Provided I make it this far, I hope to follow on with some additional region-specific posts covering tricks for searching records in specific areas.
Specialized topics I'm currently aware of include:
- Navigating English records
- Finding maiden names from English christening records
- Inferring family connections based off of naming patterns
- Navigating Swedish and Danish records</p>
<h2>Recommended Activity</h2>
<p>If you haven't already, get a log-in set up for <a href="http://insertinterestingnamehere.github.io/posts/a-brief-intro-to-family-history/familysearch.org">familysearch.org</a>.
Accounts are free for everyone.
If you're a member of the Church of Jesus Christ of Latter Day Saints, you should associate your account there with your church membership record.
If you already have an account at <a href="http://insertinterestingnamehere.github.io/posts/a-brief-intro-to-family-history/churchofjesuschrist.org">churchofjesuschrist.org</a>, that same account should work.
If you need your membership record number, you can get it by contacting the ward clerk of the congregation that corresponds to where you currently live.
You don't need to be a member to use FamilySearch though.</p></div></description><category>Genealogy</category><guid>http://insertinterestingnamehere.github.io/posts/a-brief-intro-to-family-history/</guid><pubDate>Sun, 25 Oct 2020 20:32:44 GMT</pubDate></item><item><title>DyND Callables: Speed and Flexibility</title><link>http://insertinterestingnamehere.github.io/posts/dynd-callables-speed-and-flexibility/</link><dc:creator>Ian Henriksen</dc:creator><description><div><p>(This is a post I wrote for the <a href="https://www.continuum.io/blog/developer-blog">Continuum Developer Blog</a>. You can see the original <a href="https://www.continuum.io/blog/developer-blog/dynd-callables-speed-and-flexibility">here</a>)</p>
<h3>Introduction</h3>
<p>We've been working hard to improve DyND in a wide variety of ways over the past few months.
While there is still a lot of churn in our codebase, now is a good time to show a few basic examples of the great functionality that's already there.
The library is available on GitHub at <a href="https://github.com/libdynd/libdynd">https://github.com/libdynd/libdynd</a>.</p>
<p>Today I want to focus on DyND's callable objects.
Much of the code in this post is still experimental and subject to change.
Keep that in mind when considering where to use it.</p>
<p>All the examples here will be in C++14 unless otherwise noted.
The build configuration should be set up to indicate that C++14, the DyND headers, and the DyND shared libraries should be used.
Output from a line that prints something will be shown directly in the source files as comments.
DyND also has a Python interface, so several examples in Python will also be included.</p>
<h3>Getting Started</h3>
<p>DyND's callables are, at the most basic level, functions that operate on arrays.
At the very lowest level, a callable can access all of the data, type-defined metadata (e.g. stride information), and metadata for the arrays passed to it as arguments.
This makes it possible to use callables for functionality like multiple dispatch, views based on stride manipulation, reductions, and broadcasting.
The simplest case is using a callable to wrap a non-broadcasting non-dispatched function call so that it can be used on scalar arrays.</p>
<p>Here's an example of how to do that:</p>
<pre class="code literal-block"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"></span>
<span class="c1">// Main header for DyND arrays:</span>
<span class="cp">#include</span> <span class="cpf">&lt;dynd/array.hpp&gt;</span><span class="cp"></span>
<span class="c1">// Main callable object header:</span>
<span class="cp">#include</span> <span class="cpf">&lt;dynd/callable.hpp&gt;</span><span class="cp"></span>
<span class="k">using</span> <span class="k">namespace</span> <span class="n">dynd</span><span class="p">;</span>
<span class="c1">// Write a function to turn into a DyND callable.</span>
<span class="kt">double</span> <span class="nf">f</span><span class="p">(</span><span class="kt">double</span> <span class="n">a</span><span class="p">,</span> <span class="kt">double</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">a</span> <span class="o">*</span> <span class="p">(</span><span class="n">a</span> <span class="o">-</span> <span class="n">b</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// Make the callable.</span>
<span class="n">nd</span><span class="o">::</span><span class="n">callable</span> <span class="n">f_callable</span> <span class="o">=</span> <span class="n">nd</span><span class="o">::</span><span class="n">callable</span><span class="p">(</span><span class="n">f</span><span class="p">);</span>
<span class="c1">// Main function to show how this works:</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="c1">// Initialize two arrays containing scalar values.</span>
<span class="n">nd</span><span class="o">::</span><span class="n">array</span> <span class="n">a</span> <span class="o">=</span> <span class="mf">1.</span><span class="p">;</span>
<span class="n">nd</span><span class="o">::</span><span class="n">array</span> <span class="n">b</span> <span class="o">=</span> <span class="mf">2.</span><span class="p">;</span>
<span class="c1">// Print the dynamic type signature of the callable f_callable.</span>
<span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">f_callable</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
<span class="c1">// &lt;callable &lt;(float64, float64) -&gt; float64&gt; at 000001879424CF60&gt;</span>
<span class="c1">// Call the callable and print its output.</span>
<span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">f_callable</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
<span class="c1">//array(-1,</span>
<span class="c1">// type="float64")</span>
<span class="p">}</span>
</pre>
<p>The constructor for <code>dynd::nd::callable</code> does most of the work here.
Using some interesting templating mechanisms internally, it is able to infer the argument types and return type for the function, select the corresponding DyND types, and form a DyND type that represents an analogous function call.
The result is a callable object that wraps a pointer to the function <code>f</code> and knows all of the type information about the pointer it is wrapping.
This callable can only be used with input arrays that have types that match the types for the original function's arguments.</p>
<p>The extra type information contained in this callable is <code>"(float64, float64) -&gt; float64"</code>, as can be seen when the callable is printed.
The syntax here comes from the <a href="http://datashape.readthedocs.org/en/latest/">datashape</a> data description system—the same type system used by <a href="http://blaze.readthedocs.org/en/latest/index.html">Blaze</a>, <a href="http://odo.readthedocs.org/en/latest/">Odo</a>, and several other libraries.</p>
<p>One key thing to notice here is that the callable created now does its type checking dynamically rather than at compile time.
DyND has its own system of types that is used to represent data and the functions that operate on it at runtime.
While this does have some runtime cost, dynamic type checking removes the requirement that a C++ compiler verify the types for every operation.
The dynamic nature of the DyND type system makes it possible to write code that operates in a generic way on both builtin and user-defined types in both static and dynamic languages.
I'll leave discussion of the finer details of the DyND type system for another day though.</p>
<h3>Broadcasting</h3>
<p>DyND has other functions that make it possible to add additional semantics to a callable.
These are higher-order functions (functions that operate on other functions), and they are used on existing callables rather than function pointers.
The types for these functions are patterns that can be matched against a variety of different argument types.</p>
<p>Things like array broadcasting, reductions, and multiple dispatch are all currently available.
In the case of broadcasting and reductions, the new callable calls the wrapped function many times and handles the desired iteration structure over the arrays itself.
In the case of multiple dispatch, different implementations of a function can be called based on the types of the inputs.
DyND's multiple dispatch semantics are currently under revision, so I'll just show broadcasting and reductions here.</p>
<p>DyND provides broadcasting through the function <code>dynd::nd::functional::elwise</code>.
It follows broadcasting semantics similar to those followed by NumPy's generalized universal functions—though it is, in many ways, more general.
The following example shows how to use <code>elwise</code> to create a callable that follows broadcasting semantics:</p>
<pre class="code literal-block"><span class="c1">// Include &lt;cmath&gt; to get std::exp.</span>
<span class="cp">#include</span> <span class="cpf">&lt;cmath&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;dynd/array.hpp&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;dynd/callable.hpp&gt;</span><span class="cp"></span>
<span class="c1">// Header containing dynd::nd::functional::elwise.</span>
<span class="cp">#include</span> <span class="cpf">&lt;dynd/func/elwise.hpp&gt;</span><span class="cp"></span>
<span class="k">using</span> <span class="k">namespace</span> <span class="n">dynd</span><span class="p">;</span>
<span class="kt">double</span> <span class="nf">myfunc_core</span><span class="p">(</span><span class="kt">double</span> <span class="n">a</span><span class="p">,</span> <span class="kt">double</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">a</span> <span class="o">*</span> <span class="p">(</span><span class="n">a</span> <span class="o">-</span> <span class="n">b</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">nd</span><span class="o">::</span><span class="n">callable</span> <span class="n">myfunc</span> <span class="o">=</span> <span class="n">nd</span><span class="o">::</span><span class="n">functional</span><span class="o">::</span><span class="n">elwise</span><span class="p">(</span><span class="n">nd</span><span class="o">::</span><span class="n">callable</span><span class="p">(</span><span class="n">myfunc_core</span><span class="p">));</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="c1">// Initialize some arrays to demonstrate broadcasting semantics.</span>
<span class="c1">// Use brace initialization from C++11.</span>
<span class="n">nd</span><span class="o">::</span><span class="n">array</span> <span class="n">a</span><span class="p">{{</span><span class="mf">1.</span><span class="p">,</span> <span class="mf">2.</span><span class="p">},</span> <span class="p">{</span><span class="mf">3.</span><span class="p">,</span> <span class="mf">4.</span><span class="p">}};</span>
<span class="n">nd</span><span class="o">::</span><span class="n">array</span> <span class="n">b</span><span class="p">{</span><span class="mf">5.</span><span class="p">,</span> <span class="mf">6.</span><span class="p">};</span>
<span class="c1">// Create an additional array with a ragged second dimension as well.</span>
<span class="n">nd</span><span class="o">::</span><span class="n">array</span> <span class="n">c</span><span class="p">{{</span><span class="mf">9.</span><span class="p">,</span> <span class="mf">10.</span><span class="p">},</span> <span class="p">{</span><span class="mf">11.</span><span class="p">}};</span>
<span class="c1">// Print the dynamic type signature of the callable.</span>
<span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">myfunc</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
<span class="c1">// &lt;callable &lt;(Dims... * float64, Dims... * float64) -&gt; Dims... * float64&gt;</span>
<span class="c1">// at 000001C223FC5BE0&gt;</span>
<span class="c1">// Call the callable and print its output.</span>
<span class="c1">// Broadcast along the rows of a.</span>
<span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">myfunc</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
<span class="c1">// array([[-4, -8], [-6, -8]],</span>
<span class="c1">// type="2 * 2 * float64")</span>
<span class="c1">// Broadcast the second row of c across the second row of a.</span>
<span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">myfunc</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">c</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
<span class="c1">// array([[ -8, -16], [-24, -28]],</span>
<span class="c1">// type="2 * 2 * float64")</span>
<span class="p">}</span>
</pre>
<p>A similar function can be constructed in Python using DyND's Python bindings and Python 3's function type annotations.
If Numba is installed, it is used to get JIT-compiled code that has performance relatively close to the speed of the code generated by the C++ compiler.</p>
<pre class="code literal-block"><span class="kn">from</span> <span class="nn">dynd</span> <span class="kn">import</span> <span class="n">nd</span><span class="p">,</span> <span class="n">ndt</span>
<span class="nd">@nd</span><span class="o">.</span><span class="n">functional</span><span class="o">.</span><span class="n">elwise</span>
<span class="k">def</span> <span class="nf">myfunc</span><span class="p">(</span><span class="n">a</span><span class="p">:</span> <span class="n">ndt</span><span class="o">.</span><span class="n">float64</span><span class="p">,</span> <span class="n">b</span><span class="p">:</span> <span class="n">ndt</span><span class="o">.</span><span class="n">float64</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">ndt</span><span class="o">.</span><span class="n">float64</span><span class="p">:</span>
<span class="k">return</span> <span class="n">a</span> <span class="o">*</span> <span class="p">(</span><span class="n">a</span> <span class="o">-</span> <span class="n">b</span><span class="p">)</span>
</pre>
<h3>Reductions</h3>
<p>Reductions are formed from functions that take two inputs and produce a single output.
Examples of reductions include taking the sum, max, min, and product of the items in an array.
Here we'll work with a reduction that takes the maximum of the absolute values of the items in an array.
In DyND this can be implemented by using <code>nd::functional::reduction</code> on a callable that takes two floating point inputs and returns the maximum of their absolute values.
Here's an example:</p>
<pre class="code literal-block"><span class="c1">// Include &lt;algorithm&gt; to get std::max.</span>
<span class="cp">#include</span> <span class="cpf">&lt;algorithm&gt;</span><span class="cp"></span>
<span class="c1">// Include &lt;cmath&gt; to get std::abs.</span>
<span class="cp">#include</span> <span class="cpf">&lt;cmath&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;dynd/array.hpp&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;dynd/callable.hpp&gt;</span><span class="cp"></span>
<span class="c1">// Header containing dynd::nd::functional::reduction.</span>
<span class="cp">#include</span> <span class="cpf">&lt;dynd/func/reduction.hpp&gt;</span><span class="cp"></span>
<span class="k">using</span> <span class="k">namespace</span> <span class="n">dynd</span><span class="p">;</span>
<span class="c1">// Wrap the function as a callable.</span>
<span class="c1">// Then use dynd::nd::functional::reduction to make a reduction from it.</span>
<span class="c1">// This time just wrap a C++ lambda function rather than a pointer</span>
<span class="c1">// to a different function.</span>
<span class="n">nd</span><span class="o">::</span><span class="n">callable</span> <span class="n">inf_norm</span> <span class="o">=</span> <span class="n">nd</span><span class="o">::</span><span class="n">functional</span><span class="o">::</span><span class="n">reduction</span><span class="p">(</span><span class="n">nd</span><span class="o">::</span><span class="n">callable</span><span class="p">(</span>
<span class="p">[](</span><span class="kt">double</span> <span class="n">a</span><span class="p">,</span> <span class="kt">double</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">max</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">abs</span><span class="p">(</span><span class="n">a</span><span class="p">),</span> <span class="n">std</span><span class="o">::</span><span class="n">abs</span><span class="p">(</span><span class="n">b</span><span class="p">));}));</span>
<span class="c1">// Demonstrate the reduction working along both axes simultaneously.</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="n">nd</span><span class="o">::</span><span class="n">array</span> <span class="n">a</span><span class="p">{{</span><span class="mf">1.</span><span class="p">,</span> <span class="mf">2.</span><span class="p">},</span> <span class="p">{</span><span class="mf">3.</span><span class="p">,</span> <span class="mf">4.</span><span class="p">}};</span>
<span class="c1">// Take the maximum absolute value over the whole array.</span>
<span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">inf_norm</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
<span class="c1">// array(4,</span>
<span class="c1">// type="float64")</span>
<span class="p">}</span>
</pre>
<p>Again, in Python, it is relatively easy to create a similar callable.</p>
<pre class="code literal-block"><span class="kn">from</span> <span class="nn">dynd</span> <span class="kn">import</span> <span class="n">nd</span><span class="p">,</span> <span class="n">ndt</span>
<span class="nd">@nd</span><span class="o">.</span><span class="n">functional</span><span class="o">.</span><span class="n">reduction</span>
<span class="k">def</span> <span class="nf">inf_norm</span><span class="p">(</span><span class="n">a</span><span class="p">:</span> <span class="n">ndt</span><span class="o">.</span><span class="n">float64</span><span class="p">,</span> <span class="n">b</span><span class="p">:</span> <span class="n">ndt</span><span class="o">.</span><span class="n">float64</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">ndt</span><span class="o">.</span><span class="n">float64</span><span class="p">:</span>
<span class="k">return</span> <span class="nb">max</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">a</span><span class="p">),</span> <span class="nb">abs</span><span class="p">(</span><span class="n">b</span><span class="p">))</span>
</pre>
<p>The type for the reduction callable <code>inf_norm</code> is a bit longer.
It is <code>(Dims... * float64, axes: ?Fixed * int32, identity: ?float64, keepdims: ?bool) -&gt; Dims... * float64</code>.
This signature represents a callable that accepts a single input array and has several optional keyword arguments.
In Python, passing keyword arguments to callables works the same as it would for any other function.
Currently, in C++, initializer lists mapping strings to values are used since the names of the keyword arguments are not necessarily known at compile time.</p>
<h3>Exporting Callables to Python</h3>
<p>The fact that DyND callables are C++ objects with a single C++ type makes it easy to wrap them for use in Python.
This is done using the wrappers for the callable class already built in to DyND's Python bindings.
Using DyND in Cython merits a discussion of its own, so I'll only include a minimal example here.</p>
<p>This Cython code in particular is still using experimental interfaces.
The import structure and function names here are very likely to change.</p>
<p>The first thing needed is a header that creates the desired callable.
Since this will only be included once in a single Cython based module, additional guards to make sure the header is only applied once are not needed.</p>
<pre class="code literal-block"><span class="c1">// inf_norm_reduction.hpp</span>
<span class="cp">#include</span> <span class="cpf">&lt;algorithm&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;cmath&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;dynd/array.hpp&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;dynd/callable.hpp&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;dynd/func/reduction.hpp&gt;</span><span class="cp"></span>
<span class="k">static</span> <span class="n">dynd</span><span class="o">::</span><span class="n">nd</span><span class="o">::</span><span class="n">callable</span> <span class="n">inf_norm</span> <span class="o">=</span>
<span class="n">dynd</span><span class="o">::</span><span class="n">nd</span><span class="o">::</span><span class="n">functional</span><span class="o">::</span><span class="n">reduction</span><span class="p">(</span><span class="n">dynd</span><span class="o">::</span><span class="n">nd</span><span class="o">::</span><span class="n">callable</span><span class="p">(</span>
<span class="p">[](</span><span class="kt">double</span> <span class="n">a</span><span class="p">,</span> <span class="kt">double</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">max</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">abs</span><span class="p">(</span><span class="n">a</span><span class="p">),</span> <span class="n">std</span><span class="o">::</span><span class="n">abs</span><span class="p">(</span><span class="n">b</span><span class="p">));}));</span>
</pre>
<p>The callable can now be exposed to Python through Cython.
Some work still needs to be done in DyND's Python bindings to simplify the system-specific configuration for linking extensions like this to the DyND libraries.
For simplicity, I'll just show the commented Cython distutils directives that can be used to build this file on 64 bit Windows with a libdynd built and installed from source in the default location.
Similar configurations can be put together for other systems.</p>
<pre class="code literal-block"><span class="c"># py_inf_norm.pyx</span>
<span class="c"># distutils: include_dirs = "c:/Program Files/libdynd/include"</span>
<span class="c"># distutils: library_dirs = "c:/Program Files/libdynd/lib"</span>
<span class="c"># distutils: libraries = ["libdynd", "libdyndt"]</span>
<span class="k">from</span> <span class="nn">dynd</span> <span class="k">import</span> <span class="n">nd</span><span class="p">,</span> <span class="n">ndt</span>
<span class="k">from</span> <span class="nn">dynd.cpp.callable</span> <span class="k">cimport</span> <span class="nb">callable</span> <span class="k">as</span> <span class="n">cpp_callable</span>
<span class="k">from</span> <span class="nn">dynd.nd.callable</span> <span class="k">cimport</span> <span class="n">dynd_nd_callable_from_cpp</span>
<span class="k">cdef</span> <span class="kr">extern</span> <span class="k">from</span> <span class="s">"inf_norm_reduction.hpp"</span> <span class="k">nogil</span><span class="p">:</span>
<span class="c"># Have Cython call this "cpp_inf_norm", but use "inf_norm" in</span>
<span class="c"># the generated C++ source.</span>
<span class="n">cpp_callable</span> <span class="n">inf_norm</span>
<span class="n">py_inf_norm</span> <span class="o">=</span> <span class="n">dynd_nd_callable_from_cpp</span><span class="p">(</span><span class="n">inf_norm</span><span class="p">)</span>
</pre>
<p>To build the extension I used the following setup file and ran it with the command <code>python setup.py build_ext --inplace</code>.</p>
<pre class="code literal-block"><span class="c1"># setup.py</span>
<span class="c1"># This is a fairly standard setup script for a minimal Cython module.</span>
<span class="kn">from</span> <span class="nn">distutils.core</span> <span class="kn">import</span> <span class="n">setup</span>
<span class="kn">from</span> <span class="nn">Cython.Build</span> <span class="kn">import</span> <span class="n">cythonize</span>
<span class="n">setup</span><span class="p">(</span><span class="n">ext_modules</span><span class="o">=</span><span class="n">cythonize</span><span class="p">(</span><span class="s2">"py_inf_norm.pyx"</span><span class="p">,</span> <span class="n">language</span><span class="o">=</span><span class="s1">'c++'</span><span class="p">))</span>
</pre>
<h3>A Short Benchmark</h3>
<p><code>elwise</code> and <code>reduction</code> are not heavily optimized yet, but, using IPython's <code>timeit</code> magic, it's clear that DyND is already doing well:</p>
<pre class="code literal-block"><span class="n">In</span> <span class="p">[</span><span class="mi">1</span><span class="p">]:</span> <span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
<span class="n">In</span> <span class="p">[</span><span class="mi">2</span><span class="p">]:</span> <span class="kn">from</span> <span class="nn">py_inf_norm</span> <span class="kn">import</span> <span class="n">py_inf_norm</span>
<span class="n">In</span> <span class="p">[</span><span class="mi">3</span><span class="p">]:</span> <span class="n">a</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">random</span><span class="o">.</span><span class="n">rand</span><span class="p">(</span><span class="mi">10000</span><span class="p">,</span> <span class="mi">10000</span><span class="p">)</span>
<span class="n">In</span> <span class="p">[</span><span class="mi">4</span><span class="p">]:</span> <span class="o">%</span><span class="n">timeit</span> <span class="n">py_inf_norm</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="mi">1</span> <span class="n">loop</span><span class="p">,</span> <span class="n">best</span> <span class="n">of</span> <span class="mi">3</span><span class="p">:</span> <span class="mi">231</span> <span class="n">ms</span> <span class="n">per</span> <span class="n">loop</span>
<span class="n">In</span> <span class="p">[</span><span class="mi">5</span><span class="p">]:</span> <span class="o">%</span><span class="n">timeit</span> <span class="n">np</span><span class="o">.</span><span class="n">linalg</span><span class="o">.</span><span class="n">norm</span><span class="p">(</span><span class="n">a</span><span class="o">.</span><span class="n">ravel</span><span class="p">(),</span> <span class="nb">ord</span><span class="o">=</span><span class="n">np</span><span class="o">.</span><span class="n">inf</span><span class="p">)</span>
<span class="mi">1</span> <span class="n">loop</span><span class="p">,</span> <span class="n">best</span> <span class="n">of</span> <span class="mi">3</span><span class="p">:</span> <span class="mi">393</span> <span class="n">ms</span> <span class="n">per</span> <span class="n">loop</span>
</pre>
<p>These are just a few examples of the myriad of things you can do with DyND's callables.
For more information take a look at our <a href="https://github.com/libdynd/libdynd">github repo</a> as well as <a href="http://insertinterestingnamehere.github.io/posts/dynd-callables-speed-and-flexibility/libdynd.org">libdynd.org</a>.
We'll be adding a lot more functionality, documentation, and examples in the coming months.</p></div></description><guid>http://insertinterestingnamehere.github.io/posts/dynd-callables-speed-and-flexibility/</guid><pubDate>Tue, 15 Mar 2016 19:22:33 GMT</pubDate></item><item><title>GSOC Concluding Thoughts</title><link>http://insertinterestingnamehere.github.io/posts/gsoc-concluding-thoughts/</link><dc:creator>Ian Henriksen</dc:creator><description><div><p>After many long weeks of hunting bugs and reorganizing code, my GSOC has come to an end.
My project turned out significantly different than I had expected, but much of my work still proved to be very valuable.
I originally envisioned being able to use many of DyND's features within Cython in a transparent way.
Much of the work that I did was in fixing bugs and laying the groundwork for making things like that possible.
There are still several bugs to fix and features to add in Cython before that's really possible, but I'm still pleased with the progress I made during my GSOC.
My bugfixes served to simplify some of the difficult problems that arise when wrapping and interfacing with nontrivial C++ code.
My restructuring of the DyND Python bindings, as expected, made it much easier to transition between the C++-level DyND constructs and the Python classes used in its Python bindings.</p>
<p>Here's a minimum working example that works with the latest versions of libdynd and dynd-python (as of this post).</p>
<pre class="code literal-block"><span class="c1">// myfunc.cpp</span>
<span class="cp">#include</span> <span class="cpf">"dynd/func/callable.hpp"</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">"dynd/func/apply.hpp"</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">"dynd/func/elwise.hpp"</span><span class="cp"></span>
<span class="c1">// Write a function to turn into a DyND callable.</span>
<span class="kt">double</span> <span class="nf">f</span><span class="p">(</span><span class="kt">double</span> <span class="n">a</span><span class="p">,</span> <span class="kt">double</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">a</span> <span class="o">*</span> <span class="p">(</span><span class="n">a</span> <span class="o">-</span> <span class="n">b</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// Make the callable object.</span>
<span class="n">dynd</span><span class="o">::</span><span class="n">nd</span><span class="o">::</span><span class="n">callable</span> <span class="n">f_broadcast</span> <span class="o">=</span> <span class="n">dynd</span><span class="o">::</span><span class="n">nd</span><span class="o">::</span><span class="n">functional</span><span class="o">::</span><span class="n">elwise</span><span class="p">(</span><span class="n">dynd</span><span class="o">::</span><span class="n">nd</span><span class="o">::</span><span class="n">functional</span><span class="o">::</span><span class="n">apply</span><span class="p">(</span><span class="o">&amp;</span><span class="n">f</span><span class="p">));</span>
</pre>
<pre class="code literal-block"><span class="c"># custom_callable.pyx</span>
<span class="c"># distutils: extra_compile_args = -std=c++11</span>
<span class="c"># distutils: libraries = dynd</span>
<span class="k">from</span> <span class="nn">dynd.cpp.func.callable</span> <span class="k">cimport</span> <span class="nb">callable</span> <span class="k">as</span> <span class="n">cpp_callable</span>
<span class="k">from</span> <span class="nn">dynd.nd.callable</span> <span class="k">cimport</span> <span class="nb">callable</span>
<span class="k">from</span> <span class="nn">dynd</span> <span class="k">import</span> <span class="n">nd</span>
<span class="c"># Declare the C++ defined callable object.</span>
<span class="k">cdef</span> <span class="kr">extern</span> <span class="k">from</span> <span class="s">"myfunc.cpp"</span> <span class="k">nogil</span><span class="p">:</span>
<span class="n">cpp_callable</span> <span class="n">f_broadcast</span>
<span class="c"># Construct a Python object wrapping the DyND callable.</span>
<span class="k">cdef</span> <span class="kt">callable</span> <span class="nf">py_f</span> <span class="o">=</span> <span class="nb">callable</span><span class="p">()</span>
<span class="n">py_f</span><span class="o">.</span><span class="n">v</span> <span class="o">=</span> <span class="n">f_broadcast</span>
<span class="c"># A short demonstration.</span>
<span class="k">def</span> <span class="nf">test</span><span class="p">():</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">nd</span><span class="o">.</span><span class="n">array</span><span class="p">([</span><span class="mf">1.</span><span class="p">,</span> <span class="mf">2.</span><span class="p">,</span> <span class="mf">3.</span><span class="p">,</span> <span class="mf">2.</span><span class="p">])</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">nd</span><span class="o">.</span><span class="n">array</span><span class="p">([</span><span class="mf">3.</span><span class="p">,</span> <span class="mf">2.</span><span class="p">,</span> <span class="mf">1.</span><span class="p">,</span> <span class="mf">0.</span><span class="p">])</span>
<span class="k">print</span> <span class="n">py_f</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
</pre>
<pre class="code literal-block"><span class="c1"># setup.py</span>
<span class="kn">from</span> <span class="nn">distutils.core</span> <span class="kn">import</span> <span class="n">setup</span>
<span class="kn">from</span> <span class="nn">Cython.Build</span> <span class="kn">import</span> <span class="n">cythonize</span>
<span class="n">setup</span><span class="p">(</span><span class="n">ext_modules</span><span class="o">=</span><span class="n">cythonize</span><span class="p">(</span><span class="s2">"*.pyx"</span><span class="p">,</span> <span class="n">language</span><span class="o">=</span><span class="s1">'c++'</span><span class="p">))</span>
</pre>
<p>As you can see, it is now very easy for external modules to transition smoothly between using DyND in C++ and providing Python-level functionality.
There's still a lot to be done, but I find the fact that this is now such a simple process really remarkable.
This example uses the strengths of both Cython and Dynd to provide useful and significant functionality, and I'm thrilled it is finally working.</p></div></description><guid>http://insertinterestingnamehere.github.io/posts/gsoc-concluding-thoughts/</guid><pubDate>Sun, 23 Aug 2015 04:30:52 GMT</pubDate></item><item><title>Cython Collaboration</title><link>http://insertinterestingnamehere.github.io/posts/cython-collaboration/</link><dc:creator>Ian Henriksen</dc:creator><description><div><p>I've spent the majority of these last few weeks working on adding new features to Cython.
I just recently finished my work there, though the pull request involving exception handling for overloaded operators is still waiting to be merged.
Overloading the assignment operator should now work in all cases for C++ classes.
Once the exception handling pull request is merged, translating C++ exceptions into Python exceptions should also work perfectly well.
It has been a relief to finally get these bugs taken care of.
There were a variety of features I wanted to add to Cython, but I've run out of time to work on them now, so they will have to wait till later.
The Cython developers were very helpful in getting these bugs fixed.
They've helped find and take care of a few corner cases that I missed in the pull requests that have been merged thus far.
I wasn't able to finish all the features I wanted, but I was able to make a lot of good progress and start building a consensus on what some features should look like further down the road.
I got a lot of good things done, but I'm ready to move back to working on DyND.</p>
<p>One of the major features I added was allowing C++ classes to use an overloaded <code>operator=</code> within Cython.
It is all working now and is on-schedule to be released as a part of 0.23.
Handling cascaded assignment proved to be particularly tricky, since Cython mimics the Python semantics in the case of <code>a = b = c</code> rather than following the C++ behavior for C++ objects.
With the help of the Cython developers, I was able to get it all working fine.</p>
<p>Making Cython respect the exception handling declarations for overloaded C++ operators used within Cython proved to be a lengthy bit of work.
In order to make it work properly, the type analysis code that determines when an exception handler should be used had to be connected to the C++ generation code that, if an exception handler is used, wraps the given arithmetic expression in a try-catch statement at the C++ level.
This was challenging, not so much because it was hard to see what needed to be changed in the output, but because the needed changes consisted of identifying and making many small changes in many places.
I'm pleased with the result now.
Respecting different exception declarations for different operators requires that Cython generate a separate try-catch block for each operator used.
Forming a try-except statement for each call to an overloaded operator also requires that the result of each subexpression be stored in a temporary variable.
In theory, good removal of temporaries and good branch prediction should make it so that all of these extra temporary variables and try-catch statements have no additional effect on the time needed to evaluate a given expression, but that ideal may be difficult for C++ compilers to reach.
Either way, that was the only way to properly conform to the existing API for overloaded operators that is already documented and used extensively in Cython.
At some future point it would be nice to add a way to let users consolidate different try-except blocks, but that is well outside the scope of my current project.</p>
<p>Thanks to the exception handling logic that I've added, things like the following raise an appropriate Python exception now rather than crash the Python interpreter:</p>
<pre class="code literal-block"><span class="k">cdef</span> <span class="kr">extern</span> <span class="k">from</span> <span class="s">"myheader.hpp"</span> <span class="k">nogil</span><span class="p">:</span>
<span class="n">cppclass</span> <span class="n">thing</span><span class="p">:</span>
<span class="n">thing</span><span class="p">()</span>
<span class="n">thing</span><span class="p">(</span><span class="nb">int</span><span class="p">)</span>
<span class="n">operator</span><span class="o">+</span><span class="p">(</span><span class="n">thing</span> <span class="o">&amp;</span><span class="n">other</span><span class="p">)</span> <span class="k">except</span> <span class="o">+</span>
<span class="k">def</span> <span class="nf">myfunc</span><span class="p">():</span>
<span class="c"># Initialize some "thing"s to some values</span>
<span class="k">cdef</span> <span class="kt">thing</span> <span class="nf">a</span> <span class="o">=</span> <span class="o">...</span>
<span class="k">cdef</span> <span class="kt">thing</span> <span class="nf">b</span> <span class="o">=</span> <span class="o">...</span>
<span class="k">cdef</span> <span class="kt">thing</span> <span class="nf">c</span>
<span class="c"># Now do an operation that throws a C++ exception.</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span>
</pre>
<p>One of the key features I was hoping to work through with the Cython developers was finding an appropriate API for assignment to a multidimensional index.
In C++ this is easily implemented as an assignment to an lvalue reference resulting from an overloaded or variadic function call.
The Cython developers were opposed to allowing assignment to function calls, since an interface of that sort is fairly un-pythonic.
That's a sensible opinion, but it leaves the problem of assigning to a multidimensional index unsolved.
The only workable proposal that came from the discussion was one that would allow inline definitions of methods like <code>__getitem__</code> and <code>__setitem__</code> in the Cython extern declaration of the C++ class.
Though that would provide a Python-like interface for users, I didn't opt to implement it that way for a variety of reasons.
First, when working with a C++ library with Python bindings written in Cython, it forces users to keep track of three interfaces (the C++ interface, the Cython interface built on top of the C++ interface, and the Python interface) instead of two (the C++ and Python interfaces).
Second, it makes library writers write larger amounts of oddly placed boilerplate code that is more difficult to understand and maintain.
Third, it causes possible naming conflicts when working with C++ classes that overload both <code>operator[]</code> and <code>operator()</code> (this is primarily a theoretical concern, but it is still troubling).
In order to allow C++-like control over the number of indices used (without using <code>std::tuple</code> and requiring C++11), these special functions would have to support C++ style function signature overloading as well, which requires that they have entirely different signatures than their corresponding Python variants.
The maintainability of such a feature is also a concern, since it would require a wide variety of changes to the Cython code base, all of which are unlikely to be used frequently in many other projects.
In spite of all these concerns, this is still a workable proposal, but I have avoided implementing it thus far in the hope that something better would surface.
Given how much time I have left to work on this GSOC project, this feature may have to be left for later.</p>
<p>Another important feature I spent some time trying to add was support for non-type template parameters.
I posted two different possible API's: one which specifies only the number of parameters and allows the C++ compiler to verify that all the parameters are the correct type, and another that requires that the types of the parameters be specified at the Cython level so that they can all be checked when Cython generates the C++ source file.
After waiting several days and receiving no response, I started work on the former, primarily because it seemed like the simplest option available.
Adding the additional type declarations to the template parameters would have required finding a way to apply the existing operator overloading logic to template parameters, and I was uncertain of whether or not that would be doable while still mirroring the C++ template semantics.
After I had spent a pair of days implementing most of the more lenient syntax, one of the Cython developers chimed in to support the stricter type checking.
The argument in favor of stricter type checking makes sense since it lets users avoid having to debug the generated C and C++ files, but it would have been nice to hear a second opinion before spending a few days implementing the other syntax.
This is another feature that, given how much time I have left, I'll probably have to leave for later.</p>
<p>While discussing non-type template parameters, we also discussed adding support for variadic templates.
The consensus on the syntax was to allow variadic template arguments to be used by simply adding an ellipsis where the C++ expression <code>typenames ...</code> would go.
I also proposed allowing something like <code>types ...</code>, and that syntax may be adopted in the end anyway.
I didn't get the time to add that feature, but at least the design ideas are there for someone to use later on.
Currently, due to some incomplete type checking, variadic templated functions are already usable in Cython, but this is really a bug and not a feature.
(EDIT: This is actually just a creative use of the fact that C variadic functions accept pretty much anything and is most certainly not a bug.)
For example:</p>
<pre class="code literal-block"><span class="c1">// variadic_print.hpp</span>
<span class="cp">#pragma once</span>
<span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"></span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span>
<span class="kt">void</span> <span class="n">cpp_print</span><span class="p">(</span><span class="n">T</span> <span class="n">value</span><span class="p">){</span>
<span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">value</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="p">,</span> <span class="k">typename</span><span class="p">...</span> <span class="n">Args</span><span class="o">&gt;</span>
<span class="kt">void</span> <span class="n">cpp_print</span><span class="p">(</span><span class="n">T</span> <span class="n">value</span><span class="p">,</span> <span class="n">Args</span><span class="p">...</span> <span class="n">args</span><span class="p">){</span>
<span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">value</span> <span class="o">&lt;&lt;</span> <span class="s">", "</span><span class="p">;</span>
<span class="n">cpp_print</span><span class="p">(</span><span class="n">args</span><span class="p">...);</span>
<span class="p">}</span>
</pre>
<pre class="code literal-block"><span class="c"># cpp_print.pyx</span>
<span class="c"># The extra compile arguments here assume gcc or clang is used.</span>
<span class="c"># distutils: extra_compile_args = ['-std=c++11']</span>
<span class="k">from</span> <span class="nn">libcpp.string</span> <span class="k">cimport</span> <span class="n">string</span>
<span class="k">cdef</span> <span class="kr">extern</span> <span class="k">from</span> <span class="s">"variadic_print.hpp"</span> <span class="k">nogil</span><span class="p">:</span>
<span class="n">void</span> <span class="n">cpp_print</span><span class="p">(</span><span class="o">...</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">test</span><span class="p">():</span>
<span class="k">cdef</span><span class="p">:</span>
<span class="nb">int</span> <span class="n">thing1</span> <span class="o">=</span> <span class="mf">1</span>
<span class="n">double</span> <span class="n">thing2</span> <span class="o">=</span> <span class="mf">2</span>
<span class="nb">long</span> <span class="nb">long</span> <span class="n">thing3</span> <span class="o">=</span> <span class="mf">3</span>
<span class="nb">float</span> <span class="n">thing4</span> <span class="o">=</span> <span class="mf">4</span>
<span class="n">string</span> <span class="n">thing5</span> <span class="o">=</span> <span class="s">"5"</span>
<span class="n">cpp_print</span><span class="p">(</span><span class="n">thing1</span><span class="p">,</span> <span class="n">thing2</span><span class="p">,</span> <span class="n">thing3</span><span class="p">,</span> <span class="n">thing4</span><span class="p">,</span> <span class="n">thing5</span><span class="p">)</span>
</pre>
<p>This definitely isn't a feature though.
It's just a cleverly exploited bug that hasn't been fixed yet and is certainly not usable in anything more than entertaining examples.
(EDIT: yep, it's a feature, though it wasn't directly made for templates.
It applies to situations where the return type is well defined regardless of the input types and no explicit instantiations are needed to resolve the function call.
In other words, anything that looks like a C variadic call when it is actually used, can be wrapped this way instead of trying to mess with declaring multiple template interfaces.
Pretending a template is a variadic call is more of an exploit than a standard way of doing things, but it can give the desired results provided that explicit instantiations are not needed and nobody tries to do anything silly like taking the address of the template masquerading as a variadic function.)</p>
<p>It would also be nice to see things like overloading in-place operations and overloading <code>operator||</code> and <code>operator&amp;&amp;</code> in Cython at some point, but I haven't done that yet.</p>
<p>All things considered, even though I wasn't able to accomplish all I had hoped in Cython, I was still able to do a lot of useful things.
The existing design philosophy in Cython didn't prove to be completely amenable to exposing a Cython-level API for a relatively advanced C++ library.
The existing features are designed primarily to allow users to write Python-like code that manipulates C and C++ objects.
The features that are focused toward interfacing with external C++ libraries are effective for constructing and exposing Python wrappers for C++ objects, but can often prove to be very unwieldy for exposing Cython-level APIs for C++ libraries.
It's certainly still possible, but it definitely stretches the limits of the tools at hand.</p>
<p>Now, moving forward after my work on Cython, I've shifted toward contributing to libdynd and dynd-python again.
I've worked with my mentors to isolate a mysterious segfault that we were seeing when using clang to build libdynd and dynd-python.
I've also worked on several improvements to the build system.
Everything should be building with MinGW again soon, but, for now, my linux environment is good enough to work on some new features too.
I've also spent some time working on some minimal examples of using the Cython declarations in dynd-python outside the installed Python package.</p>
<p>To help with testing libdynd and dynd-python, I've also overhauled the Travis-CI build to make use of the new container-based infrastructure.
Thus far the builds are running noticeably faster.
These changes should be a great help to all of us in the future as we continue to develop both packages.</p>
<p>Over these last few weeks I expect to spend most of my time making it as easy as possible to use as much of libdynd as possible within Cython.
The infrastructure is already in place for most of the core pieces that need to be taken care of, so I'm feeling optimistic.</p></div></description><guid>http://insertinterestingnamehere.github.io/posts/cython-collaboration/</guid><pubDate>Wed, 05 Aug 2015 21:55:07 GMT</pubDate></item><item><title>Fixing Cython Bugs</title><link>http://insertinterestingnamehere.github.io/posts/fixing-cython-bugs/</link><dc:creator>Ian Henriksen</dc:creator><description><div><p>Last week I went to the SciPy conference.
It was great.
I got to meet many of the major contributors to open source, including one of my mentors, Mark Wiebe.
I also got to give a <a href="https://www.youtube.com/watch?v=R4yB-8tB0J0">talk</a> about some of my previous work on SciPy and see <a href="https://www.youtube.com/watch?v=Le1GdRFt3E8">my wife's talk</a> about our new applied math curriculum here at BYU.
There were a lot of great presenters at the conference this year and it was good to see how many people are interested in and working on the software in the scientific Python stack.
Above all, there were free t-shirts. Lots of free t-shirts.</p>
<p>Other than that, the past few weeks I've spent a lot of time fixing and following up on a series of Cython bugs.
A lot of my time has been spent reading large chunks of the Cython codebase to properly understand what is going on.
My understanding of what is going on is still very incomplete, but I've managed to get enough of a hold on things to be able to start fixing bugs.
As I currently understand it, the Cython parser goes through a file and constructs a series of nodes representing the abstract syntax tree.
Once the abstract syntax tree is constructed, there is a type resolution pass on all the existing nodes where some of the more generic nodes can specialize themselves as instances of more specific nodes.
That helps localize parts of the code that deal with entirely different cases for the different types.
This type resolution phase is also where all the static types are checked for correctness.
Once types have all been checked and the proper nodes for code generation are in place, another pass is made to generate the correct code for each operation.
Compiler directives are taken into account and different preambles are included conditionally as well.
Most of the code for performing the type analysis pass and the code generation pass on the abstract syntax tree is in the different methods of the classes defined in <code>Cython/Compiler/ExprNodes.py</code> and <code>Cython/Compiler/Nodes.py</code>.
That's a very rough overview of what is going on, but it has been enough for me to fix a few things.</p>
<p>The biggest bug I've been working on has been the fact that, until now, exception declarations for operators overloaded at the C++ level have not been respected in the generated C++ code.
This means that, when an operation like <code>a + b</code> ought to throw a C++ error, catch the C++ error, then translate it into a Python error, the only thing that really happens is the whole program crashing due to an uncaught C++ error.
Fixing this has been a little tricky since temporary variables must be allocated and used to store the result of each operation, and many of the overloadable operations are handled separately throughout the Cython code.
In spite of the fact that this is a large and delicate bug to fix, I have managed to get everything working for arithmetic and unary operators.
Indexing and function calls still need more work/testing.</p>
<p>I've also been discussing the best way to do multidimensional indexing with the Cython developers.
In C++, multidimensional indexing of C++ objects can be written easily as "a(1, 2, 3)".
That is all well and good, except that such an expression cannot be used properly as a left-value in assignment in Cython even though that is perfectly valid in C++.
The primary reasoning as far as I can tell is that allowing that would be decidedly un-pythonic.
My personal preference is very strongly toward allowing the C++ syntax when working with C++ objects, but we're still trying to settle on a reasonable solution.</p>
<p>I've also resurrected an existing patch to allow using an overloaded call operator for stack-allocated objects and put in some initial code toward allowing users to declare and use an overloaded <code>operator=</code> for a C++ class.
There will be more patches coming soon on that.</p>
<p>Once I've fixed a few more of these Cython bugs, I expect to be able to continue my work in refactoring DyND's Python bindings to make the transition between Python, Cython/DyND, and C++/DyND much smoother.</p></div></description><guid>http://insertinterestingnamehere.github.io/posts/fixing-cython-bugs/</guid><pubDate>Mon, 13 Jul 2015 19:26:32 GMT</pubDate></item><item><title>Structure Plans and More Examples</title><link>http://insertinterestingnamehere.github.io/posts/structure-plans-and-more-examples/</link><dc:creator>Ian Henriksen</dc:creator><description><div><p>Despite a few setbacks, these past two weeks have been ones of progress.
I was able to work with my mentors, Mark and Irwin, to come up with a plan for how to restructure the C++ namespaces in dynd-python.
We opted to separate the namespaces for the Python interoperability functions and the namespaces for the primary DyND C++ functionality.
This will make it so that Cython wrapper types for specific C++ types can have the same name without causing any sort of naming conflict.
Users that want to use both types within the same file can use the different namespaces to separate them.
Within Cython this will be even easier since types can be aliased on import the same way Python objects can.
I finished the name separation work shortly after my last blog post.</p>
<p>We also developed a plan with regards to how to structure the pxd files so that they can be easily used in third party extension modules.
I'm working to separate the existing Cython pxd files in the project so that there is one for each header.
That will make it so that the structure of the headers is clear and it will be easy to add new declarations.
It will also make it so that projects that do not wish to include swathes of project headers will be able to avoid that when they only want to include specific things.
On the other hand, for users that want to throw something together quickly, I'll also put together another set of pxd files that use Cython's relative cimports to mimic the namespace structure currently in the DyND library.
I am in the process of that restructuring, and hope to be able to get it done soon.</p>
<p>With regards to dynamically loading C++ classes via Cython, for now, we're going to continue including the C++ project headers and linking against the original DyND library.
I suspect that there is a way of dynamically loading C++ classes from other Python modules without having to link against the original module.
However, I haven't figured it out yet.
It appears to be a cool feature that could be added later, but brings relatively little added benefit other than a slightly simplified API.
Cython certainly does not support anything like that currently and getting it to do that would require significant modifications.</p>
<p>On the other hand, in Cython, it is relatively easy to export functions and variables in a way that does not require client extension modules to link against the original library.
For now I'm going to employ that approach so that, when all is said and done, as much of the existing library as possible can be loaded via Cython's cimport machinery.</p>
<p>I have spent some time putting together a basic example of working with DyND's C++ objects within Cython, but I have run across some unresolved issues with current project structure.
I expect that we'll be able to get those resolved and I'll be able to post a working example soon.</p>
<p>During the past two weeks I also had the opportunity to learn how DyND's arrfuncs work.
Arrfuncs operate on DyND arrays the same way that gufuncs operate on NumPy arrays.
I found that arrfuncs are surprisingly easy to both construct and use.
Here's a simple program that shows some arrfuncs in action:</p>
<pre class="code literal-block"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;dynd/array.hpp&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;dynd/func/arrfunc.hpp&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;dynd/func/apply.hpp&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;dynd/func/elwise.hpp&gt;</span><span class="cp"></span>
<span class="k">using</span> <span class="k">namespace</span> <span class="n">dynd</span><span class="p">;</span>
<span class="k">namespace</span> <span class="p">{</span>
<span class="c1">// Functions to use to create arrfuncs.</span>
<span class="kt">double</span> <span class="n">f</span><span class="p">(</span><span class="kt">double</span> <span class="n">x</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">x</span> <span class="o">*</span> <span class="n">x</span><span class="p">;</span> <span class="p">}</span>
<span class="kt">double</span> <span class="n">g</span><span class="p">(</span><span class="kt">double</span> <span class="n">x</span><span class="p">,</span> <span class="kt">double</span> <span class="n">y</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">x</span> <span class="o">*</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span> <span class="o">*</span> <span class="n">y</span><span class="p">;</span> <span class="p">}</span>
<span class="c1">// A print function that mimics Python's,</span>
<span class="c1">// but only accepts one argument.</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="kt">void</span> <span class="n">print</span><span class="p">(</span><span class="n">T</span> <span class="n">thing</span><span class="p">)</span> <span class="p">{</span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">thing</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
<span class="c1">// First make versions of f and g that operate on</span>
<span class="c1">// DyND array types rather than native C++ types.</span>
<span class="n">nd</span><span class="o">::</span><span class="n">arrfunc</span> <span class="n">square_0</span> <span class="o">=</span> <span class="n">nd</span><span class="o">::</span><span class="n">functional</span><span class="o">::</span><span class="n">apply</span><span class="p">(</span><span class="o">&amp;</span><span class="n">f</span><span class="p">);</span>
<span class="n">nd</span><span class="o">::</span><span class="n">arrfunc</span> <span class="n">norm2_0</span> <span class="o">=</span> <span class="n">nd</span><span class="o">::</span><span class="n">functional</span><span class="o">::</span><span class="n">apply</span><span class="p">(</span><span class="o">&amp;</span><span class="n">g</span><span class="p">);</span>
<span class="c1">// Now make versions of f and g that operate on DyND arrays</span>
<span class="c1">// and follow NumPy-like broadcasting semantics.</span>
<span class="n">nd</span><span class="o">::</span><span class="n">arrfunc</span> <span class="n">square</span> <span class="o">=</span> <span class="n">nd</span><span class="o">::</span><span class="n">functional</span><span class="o">::</span><span class="n">elwise</span><span class="p">(</span><span class="n">square_0</span><span class="p">);</span>
<span class="n">nd</span><span class="o">::</span><span class="n">arrfunc</span> <span class="n">norm2</span> <span class="o">=</span> <span class="n">nd</span><span class="o">::</span><span class="n">functional</span><span class="o">::</span><span class="n">elwise</span><span class="p">(</span><span class="n">norm2_0</span><span class="p">);</span>
<span class="c1">// Try applying these functions to DyND scalars.</span>
<span class="n">nd</span><span class="o">::</span><span class="n">array</span> <span class="n">a</span> <span class="o">=</span> <span class="mf">2.</span><span class="p">;</span>
<span class="n">nd</span><span class="o">::</span><span class="n">array</span> <span class="n">b</span> <span class="o">=</span> <span class="mf">3.</span><span class="p">;</span>
<span class="n">print</span><span class="p">(</span><span class="n">square_0</span><span class="p">(</span><span class="n">a</span><span class="p">));</span>
<span class="n">print</span><span class="p">(</span><span class="n">norm2_0</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">));</span>
<span class="n">print</span><span class="p">(</span><span class="n">square</span><span class="p">(</span><span class="n">a</span><span class="p">));</span>
<span class="n">print</span><span class="p">(</span><span class="n">norm2</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">));</span>
<span class="c1">// Now apply these functions to DyND arrays.</span>
<span class="n">a</span> <span class="o">=</span> <span class="p">{</span><span class="mf">1.</span><span class="p">,</span> <span class="mf">2.</span><span class="p">,</span> <span class="mf">3.</span><span class="p">,</span> <span class="mf">2.</span><span class="p">};</span>
<span class="n">b</span> <span class="o">=</span> <span class="p">{</span><span class="mf">3.</span><span class="p">,</span> <span class="mf">2.</span><span class="p">,</span> <span class="mf">1.</span><span class="p">,</span> <span class="mf">0.</span><span class="p">};</span>
<span class="n">print</span><span class="p">(</span><span class="n">square</span><span class="p">(</span><span class="n">a</span><span class="p">));</span>
<span class="n">print</span><span class="p">(</span><span class="n">norm2</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">));</span>
<span class="c1">// Run a two-dimensional example.</span>
<span class="n">a</span> <span class="o">=</span> <span class="p">{{</span><span class="mf">1.</span><span class="p">,</span> <span class="mf">2.</span><span class="p">},</span> <span class="p">{</span><span class="mf">2.</span><span class="p">,</span> <span class="mf">3.</span><span class="p">},</span> <span class="p">{</span><span class="mf">3.</span><span class="p">,</span> <span class="mf">4.</span><span class="p">}};</span>
<span class="n">b</span> <span class="o">=</span> <span class="p">{{</span><span class="mf">2.</span><span class="p">,</span> <span class="mf">1.</span><span class="p">},</span> <span class="p">{</span><span class="mf">3.</span><span class="p">,</span> <span class="mf">3.</span><span class="p">},</span> <span class="p">{</span><span class="mf">2.</span><span class="p">,</span> <span class="mf">1.</span><span class="p">}};</span>
<span class="n">print</span><span class="p">(</span><span class="n">square</span><span class="p">(</span><span class="n">a</span><span class="p">));</span>
<span class="n">print</span><span class="p">(</span><span class="n">norm2</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">));</span>
<span class="c1">// Broadcast the function with two arguments along the rows of a.</span>
<span class="n">b</span> <span class="o">=</span> <span class="p">{</span><span class="mf">1.</span><span class="p">,</span> <span class="mf">2.</span><span class="p">};</span>
<span class="n">print</span><span class="p">(</span><span class="n">norm2</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">));</span>
<span class="c1">// Broadcast a scalar with an array.</span>
<span class="n">a</span> <span class="o">=</span> <span class="p">{{</span><span class="mf">1.</span><span class="p">,</span> <span class="mf">2.</span><span class="p">,</span> <span class="mf">3.</span><span class="p">},</span> <span class="p">{</span><span class="mf">2.</span><span class="p">,</span> <span class="mf">3.</span><span class="p">,</span> <span class="mf">4.</span><span class="p">}};</span>
<span class="n">b</span> <span class="o">=</span> <span class="mf">2.</span><span class="p">;</span>
<span class="n">print</span><span class="p">(</span><span class="n">norm2</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">));</span>
<span class="n">print</span><span class="p">(</span><span class="n">norm2</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">a</span><span class="p">));</span>
<span class="c1">// Broadcast a row and column together.</span>
<span class="n">a</span> <span class="o">=</span> <span class="p">{{</span><span class="mf">3.</span><span class="p">},</span> <span class="p">{</span><span class="mf">2.</span><span class="p">},</span> <span class="p">{</span><span class="mf">1.</span><span class="p">}};</span>
<span class="n">b</span> <span class="o">=</span> <span class="p">{{</span><span class="mf">2.</span><span class="p">,</span> <span class="mf">1.</span><span class="p">}};</span>
<span class="n">print</span><span class="p">(</span><span class="n">norm2</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">));</span>
<span class="p">}</span>
</pre>
<p>I compiled this C++ file on Windows with a recent MinGW-w64 g++ using the command</p>
<pre class="code literal-block">g++ -O3 -I<span class="s2">"c:/Program Files (x86)/libdynd/include"</span> -std<span class="o">=</span>c++11 ufunc.cpp -L<span class="s2">"c:/Program Files (x86)/libdynd/lib/static"</span> -ldynd -o ufunc.exe
</pre>
<p>Again, I was very impressed with how naturally I was able to create a C++ arrfunc that followed all the expected broadcasting rules.
In another few weeks I expect to be able to do this sort of thing just as naturally in Cython.</p></div></description><guid>http://insertinterestingnamehere.github.io/posts/structure-plans-and-more-examples/</guid><pubDate>Tue, 23 Jun 2015 21:15:07 GMT</pubDate></item><item><title>Basic Examples</title><link>http://insertinterestingnamehere.github.io/posts/basic-examples/</link><dc:creator>Ian Henriksen</dc:creator><description><div><p>The past two weeks have been an adventure.
I've spent a great deal of time working to find a reasonable way to refactor the DyND Python bindings in a way that works well for exporting all the existing Python/C++ compatibility functions at both the Cython and C++ level.
After some discussion with my mentors, Mark and Irwin, I was able to get to what seems to be a workable model.
I'm in the process of doing all the needed refactoring to put those changes into place.
I'll post more details once I've finished the main structural changes to the Python bindings.</p>
<p>For now, I'd like to show a few basic examples of how to use DyND.
The examples here showcase some of the similarities with NumPy as well as the simplicity of the notation.
I haven't done any sort of performance comparison.
The implementations I've put together here using DyND work using array slicing and array arithmetic, so the cost of dispatching for types is still present in each array arithmetic operation.
More efficient implementations could be created by coding a version of an algorithm that operates directly on the buffers of the arrays given.
More efficient and general implementations could be constructed using DyND's arrfuncs, which are similar in purpose to NumPy's gufuncs, but I'm still figuring out how they work, so I'll have to include examples of how to do that later on.</p>
<p>For my examples here, I'll focus on three different algorithms for polynomial evaluation.
For simplicity, I'll assume the coefficients are passed as an array and the parameter value at which to evaluate the polynomial(s) is a single double precision value.
Each algorithm will be presented in Python (using NumPy), in C++ (using DyND), and in Fortran.
Each file will either compile to an executable (C++ and Fortran) or be run-able as a script (Python).
The NumPy and DyND implementations will be roughly equivalent and will both operate on arbitrary dimensional arrays, operating on the first axis of the array and broadcasting along all trailing axes.
The NumPy and DyND versions will also work with relatively generic types (either floating point or complex).
The Fortran versions will apply only to 1-dimensional arrays and will only operate on arrays of double precision real coefficients.</p>
<p>Regarding the notation, I found it very easy to use DyND's <code>irange</code> object with its overloaded comparison operators very easy to use.
It is used to specify ranges of indices over which to slice an array.
Since multiple arguments are not allowed for the indexing operator in C++, the call operator is used for array slicing.</p>
<p>For compiling these examples on Windows, I used gfortran and a recent development version (3.7.0 dev) of clang compiled with mingw-w64.
The exact compiler calls replacing "(algorithm)" with the name of each particular algorithm were</p>
<pre class="code literal-block">clang++ -fPIC -O3 -I<span class="s2">"c:/Program Files (x86)/libdynd/include"</span> -std<span class="o">=</span>c++11 <span class="o">(</span>algorithm<span class="o">)</span>.cpp -L<span class="s2">"c:/Program Files (x86)/libdynd/lib/static"</span> -ldynd -o <span class="o">(</span>algorithm<span class="o">)</span>.exe
gfortran -fPIC -O3 <span class="o">(</span>algorithm<span class="o">)</span>.f90 -o <span class="o">(</span>algorithm<span class="o">)</span>_f.exe
</pre>
<p>The corresponding compiler calls on BSD, Linux, or other Unix-based operating systems are similar with the <code>-I</code> and <code>-L</code> directories being modified (or omitted) according to the location of the DyND headers and library.
The same set of flags should work with recent versions of clang++ and g++.</p>
<h3>Horner's Algorithm</h3>
<p>Horner's algorithm is the standard algorithm for evaluating a power basis polynomial at a parameter value, given the coefficients for the polynomial.
Here the coefficients are assumed to be given in order from highest to lowest degree.</p>
<pre class="code literal-block"><span class="c1"># Python</span>
<span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">print_function</span>
<span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
<span class="k">def</span> <span class="nf">horner</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">t</span><span class="p">):</span>
<span class="n">v</span> <span class="o">=</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">xrange</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">a</span><span class="o">.</span><span class="n">shape</span><span class="p">[</span><span class="mi">0</span><span class="p">]):</span>
<span class="n">v</span> <span class="o">=</span> <span class="n">t</span> <span class="o">*</span> <span class="n">v</span> <span class="o">+</span> <span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
<span class="k">return</span> <span class="n">v</span>
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span> <span class="s1">'d'</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">horner</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="o">.</span><span class="mi">3333</span><span class="p">))</span>
</pre>
<pre class="code literal-block"><span class="c1">// C++</span>
<span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;dynd/array.hpp&gt;</span><span class="cp"></span>
<span class="k">using</span> <span class="k">namespace</span> <span class="n">dynd</span><span class="p">;</span>
<span class="n">nd</span><span class="o">::</span><span class="n">array</span> <span class="n">horner</span><span class="p">(</span><span class="n">nd</span><span class="o">::</span><span class="n">array</span> <span class="n">a</span><span class="p">,</span> <span class="kt">double</span> <span class="n">t</span><span class="p">){</span>
<span class="n">nd</span><span class="o">::</span><span class="n">array</span> <span class="n">v</span> <span class="o">=</span> <span class="n">a</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="kt">size_t</span> <span class="n">e</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">get_dim_size</span><span class="p">();</span>
<span class="k">for</span><span class="p">(</span><span class="kt">size_t</span> <span class="n">i</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">e</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span>
<span class="n">v</span> <span class="o">=</span> <span class="n">t</span> <span class="o">*</span> <span class="n">v</span> <span class="o">+</span> <span class="n">a</span><span class="p">(</span><span class="n">i</span><span class="p">);}</span>
<span class="k">return</span> <span class="n">v</span><span class="p">;}</span>
<span class="kt">int</span> <span class="n">main</span><span class="p">(){</span>
<span class="n">nd</span><span class="o">::</span><span class="n">array</span> <span class="n">a</span> <span class="o">=</span> <span class="p">{</span><span class="mf">1.</span><span class="p">,</span> <span class="o">-</span><span class="mf">2.</span><span class="p">,</span> <span class="mf">3.</span><span class="p">,</span> <span class="mf">0.</span><span class="p">};</span>
<span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">horner</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="mf">.3333</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;}</span>
</pre>
<pre class="code literal-block"><span class="c">! Fortran</span>
<span class="k">module </span><span class="n">hornermodule</span>
<span class="k">implicit none</span>
<span class="k">contains</span>
<span class="kt">double precision </span><span class="k">function </span><span class="n">horner</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">t</span><span class="p">)</span>
<span class="kt">double precision</span><span class="p">,</span> <span class="k">intent</span><span class="p">(</span><span class="n">in</span><span class="p">)</span> <span class="kd">::</span> <span class="n">a</span><span class="p">(:)</span>
<span class="kt">double precision</span><span class="p">,</span> <span class="k">intent</span><span class="p">(</span><span class="n">in</span><span class="p">)</span> <span class="kd">::</span> <span class="n">t</span>
<span class="kt">double precision </span><span class="n">v</span>
<span class="kt">integer </span><span class="n">i</span><span class="p">,</span> <span class="n">n</span>
<span class="n">n</span> <span class="o">=</span> <span class="n">size</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="n">v</span> <span class="o">=</span> <span class="n">a</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="k">do </span><span class="n">i</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">n</span>
<span class="n">v</span> <span class="o">=</span> <span class="n">t</span> <span class="o">*</span> <span class="n">v</span> <span class="o">+</span> <span class="n">a</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
<span class="k">end do</span>
<span class="k"> </span><span class="n">horner</span> <span class="o">=</span> <span class="n">v</span>
<span class="k">end function </span><span class="n">horner</span>
<span class="k">end module </span><span class="n">hornermodule</span>
<span class="k">program </span><span class="n">main</span>
<span class="k">use </span><span class="n">hornermodule</span>
<span class="kt">double precision </span><span class="n">a</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>
<span class="n">a</span> <span class="o">=</span> <span class="p">(</span><span class="o">/</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">0</span><span class="o">/</span><span class="p">)</span>
<span class="k">print</span> <span class="o">*</span><span class="p">,</span> <span class="n">horner</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="p">.</span><span class="mi">3333</span><span class="n">D0</span><span class="p">)</span>
<span class="k">end program </span><span class="n">main</span>
</pre>
<h3>Decasteljau's Algorithm</h3>
<p>Decasteljau's Algorithm is used to evaluate polynomials in Bernstein form.
It is also often used to evaluate Bézier curves.</p>
<pre class="code literal-block"><span class="c1"># Python</span>
<span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">print_function</span>
<span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
<span class="k">def</span> <span class="nf">decasteljau</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">t</span><span class="p">):</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">xrange</span><span class="p">(</span><span class="n">a</span><span class="o">.</span><span class="n">shape</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">-</span><span class="mi">1</span><span class="p">):</span>
<span class="n">a</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span><span class="o">-</span><span class="n">t</span><span class="p">)</span> <span class="o">*</span> <span class="n">a</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">t</span> <span class="o">*</span> <span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span>
<span class="k">return</span> <span class="n">a</span>
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">],</span> <span class="s1">'d'</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">decasteljau</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="o">.</span><span class="mi">25</span><span class="p">))</span>
</pre>
<pre class="code literal-block"><span class="c1">// C++</span>
<span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;dynd/array.hpp&gt;</span><span class="cp"></span>
<span class="k">using</span> <span class="k">namespace</span> <span class="n">dynd</span><span class="p">;</span>
<span class="n">nd</span><span class="o">::</span><span class="n">array</span> <span class="n">decasteljau</span><span class="p">(</span><span class="n">nd</span><span class="o">::</span><span class="n">array</span> <span class="n">a</span><span class="p">,</span> <span class="kt">double</span> <span class="n">t</span><span class="p">){</span>
<span class="kt">size_t</span> <span class="n">e</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">get_dim_size</span><span class="p">();</span>
<span class="k">for</span><span class="p">(</span><span class="kt">size_t</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">e</span><span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span>
<span class="n">a</span> <span class="o">=</span> <span class="p">(</span><span class="mf">1.</span><span class="o">-</span><span class="n">t</span><span class="p">)</span> <span class="o">*</span> <span class="n">a</span><span class="p">(</span><span class="n">irange</span><span class="p">()</span><span class="o">&lt;</span><span class="p">(</span><span class="n">e</span><span class="o">-</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span> <span class="o">+</span> <span class="n">t</span> <span class="o">*</span> <span class="n">a</span><span class="p">(</span><span class="mi">0</span><span class="o">&lt;</span><span class="n">irange</span><span class="p">());}</span>
<span class="k">return</span> <span class="n">a</span><span class="p">;}</span>
<span class="kt">int</span> <span class="n">main</span><span class="p">(){</span>
<span class="n">nd</span><span class="o">::</span><span class="n">array</span> <span class="n">a</span> <span class="o">=</span> <span class="p">{</span><span class="mf">1.</span><span class="p">,</span> <span class="mf">2.</span><span class="p">,</span> <span class="mf">2.</span><span class="p">,</span> <span class="o">-</span><span class="mf">1.</span><span class="p">};</span>
<span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">decasteljau</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="mf">.25</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;}</span>
</pre>
<p>In the Fortran version of this algorithm, dynamic allocation within the function is needed.</p>
<pre class="code literal-block"><span class="c">! Fortran</span>
<span class="k">module </span><span class="n">decasteljaumodule</span>
<span class="k">implicit none</span>
<span class="k">contains</span>
<span class="kt">double precision </span><span class="k">function </span><span class="n">decasteljau</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">t</span><span class="p">)</span>
<span class="kt">double precision</span><span class="p">,</span> <span class="k">intent</span><span class="p">(</span><span class="n">in</span><span class="p">)</span> <span class="kd">::</span> <span class="n">a</span><span class="p">(:)</span>
<span class="kt">double precision</span><span class="p">,</span> <span class="k">intent</span><span class="p">(</span><span class="n">in</span><span class="p">)</span> <span class="kd">::</span> <span class="n">t</span>
<span class="kt">double precision</span><span class="p">,</span> <span class="k">allocatable</span> <span class="kd">::</span> <span class="n">b</span><span class="p">(:)</span>
<span class="kt">integer </span><span class="n">i</span><span class="p">,</span> <span class="n">n</span>
<span class="n">n</span> <span class="o">=</span> <span class="n">size</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="k">allocate</span><span class="p">(</span><span class="n">b</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span>
<span class="n">b</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span><span class="o">-</span><span class="n">t</span><span class="p">)</span> <span class="o">*</span> <span class="n">a</span><span class="p">(:</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="n">t</span> <span class="o">*</span> <span class="n">a</span><span class="p">(</span><span class="mi">2</span><span class="p">:)</span>
<span class="k">do </span><span class="n">i</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">n</span><span class="o">-</span><span class="mi">1</span>
<span class="n">b</span><span class="p">(:</span><span class="n">n</span><span class="o">-</span><span class="n">i</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span><span class="o">-</span><span class="n">t</span><span class="p">)</span> <span class="o">*</span> <span class="n">b</span><span class="p">(:</span><span class="n">n</span><span class="o">-</span><span class="n">i</span><span class="p">)</span> <span class="o">+</span> <span class="n">t</span> <span class="o">*</span> <span class="n">b</span><span class="p">(</span><span class="mi">2</span><span class="p">:</span><span class="n">n</span><span class="o">-</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span>
<span class="k">end do</span>
<span class="k"> </span><span class="n">decasteljau</span> <span class="o">=</span> <span class="n">b</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="k">end function </span><span class="n">decasteljau</span>
<span class="k">end module </span><span class="n">decasteljaumodule</span>
<span class="k">program </span><span class="n">main</span>
<span class="k">use </span><span class="n">decasteljaumodule</span>
<span class="kt">double precision </span><span class="n">a</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>
<span class="n">a</span> <span class="o">=</span> <span class="p">(</span><span class="o">/</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="o">/</span><span class="p">)</span>
<span class="k">print</span> <span class="o">*</span><span class="p">,</span> <span class="n">decasteljau</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="p">.</span><span class="mi">25</span><span class="n">D0</span><span class="p">)</span>
<span class="k">end program </span><span class="n">main</span>
</pre>
<h3>Clenshaw's Algorithm (Chebyshev Polynomials)</h3>
<p>Clenshaw's algorithm provides a simple recurrence for evaluating Chebyshev polynomials.
There is a similar algorithm for evaluating Legendre polynomials, but we will not demonstrate it here.
The code here is a simplified adaptation of the code </p>
<pre class="code literal-block"><span class="c1"># Python</span>
<span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">print_function</span>
<span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
<span class="k">def</span> <span class="nf">clenshaw</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">t</span><span class="p">):</span>
<span class="n">c0</span><span class="p">,</span> <span class="n">c1</span> <span class="o">=</span> <span class="n">a</span><span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">xrange</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="n">a</span><span class="o">.</span><span class="n">shape</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span>
<span class="n">c0</span><span class="p">,</span> <span class="n">c1</span> <span class="o">=</span> <span class="n">a</span><span class="p">[</span><span class="o">-</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="n">c1</span><span class="p">,</span> <span class="n">c0</span> <span class="o">+</span> <span class="n">c1</span> <span class="o">*</span> <span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">t</span><span class="p">)</span>
<span class="k">return</span> <span class="n">c0</span> <span class="o">+</span> <span class="n">c1</span> <span class="o">*</span> <span class="n">t</span>
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">4</span><span class="p">],</span> <span class="s1">'d'</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">clenshaw</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="o">-.</span><span class="mi">5</span><span class="p">))</span>
</pre>
<pre class="code literal-block"><span class="c1">// C++</span>
<span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;dynd/array.hpp&gt;</span><span class="cp"></span>
<span class="k">using</span> <span class="k">namespace</span> <span class="n">dynd</span><span class="p">;</span>
<span class="n">nd</span><span class="o">::</span><span class="n">array</span> <span class="n">clenshaw</span><span class="p">(</span><span class="n">nd</span><span class="o">::</span><span class="n">array</span> <span class="n">a</span><span class="p">,</span> <span class="kt">double</span> <span class="n">t</span><span class="p">){</span>
<span class="kt">size_t</span> <span class="n">e</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">get_dim_size</span><span class="p">();</span>
<span class="n">nd</span><span class="o">::</span><span class="n">array</span> <span class="n">c0</span> <span class="o">=</span> <span class="n">a</span><span class="p">(</span><span class="n">e</span><span class="o">-</span><span class="mi">2</span><span class="p">),</span> <span class="n">c1</span> <span class="o">=</span> <span class="n">a</span><span class="p">(</span><span class="n">e</span><span class="o">-</span><span class="mi">1</span><span class="p">),</span> <span class="n">temp</span><span class="p">;</span>
<span class="k">for</span><span class="p">(</span><span class="kt">size_t</span> <span class="n">i</span><span class="o">=</span><span class="mi">3</span><span class="p">;</span> <span class="n">i</span><span class="o">&lt;</span><span class="n">e</span><span class="o">+</span><span class="mi">1</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span>
<span class="n">temp</span> <span class="o">=</span> <span class="n">c0</span><span class="p">;</span>
<span class="n">c0</span> <span class="o">=</span> <span class="n">a</span><span class="p">(</span><span class="n">e</span><span class="o">-</span><span class="n">i</span><span class="p">)</span> <span class="o">-</span> <span class="n">c1</span><span class="p">;</span>
<span class="n">c1</span> <span class="o">=</span> <span class="n">temp</span> <span class="o">+</span> <span class="n">c1</span> <span class="o">*</span> <span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">t</span><span class="p">);}</span>
<span class="k">return</span> <span class="n">c0</span> <span class="o">+</span> <span class="n">c1</span> <span class="o">*</span> <span class="n">t</span><span class="p">;}</span>
<span class="kt">int</span> <span class="n">main</span><span class="p">(){</span>
<span class="n">nd</span><span class="o">::</span><span class="n">array</span> <span class="n">a</span> <span class="o">=</span> <span class="p">{</span><span class="mf">1.</span><span class="p">,</span> <span class="mf">2.</span><span class="p">,</span> <span class="o">-</span><span class="mf">1.</span><span class="p">,</span> <span class="o">-</span><span class="mf">4.</span><span class="p">};</span>
<span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">clenshaw</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="o">-</span><span class="mf">.5</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;}</span>
</pre>
<pre class="code literal-block"><span class="c">! Fortran</span>
<span class="k">module </span><span class="n">clenshawmodule</span>
<span class="k">implicit none</span>
<span class="k">contains</span>
<span class="kt">double precision </span><span class="k">function </span><span class="n">clenshaw</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">t</span><span class="p">)</span>
<span class="kt">double precision</span><span class="p">,</span> <span class="k">intent</span><span class="p">(</span><span class="n">in</span><span class="p">)</span> <span class="kd">::</span> <span class="n">a</span><span class="p">(:)</span>
<span class="kt">double precision</span><span class="p">,</span> <span class="k">intent</span><span class="p">(</span><span class="n">in</span><span class="p">)</span> <span class="kd">::</span> <span class="n">t</span>
<span class="kt">double precision </span><span class="n">c0</span><span class="p">,</span> <span class="n">c1</span><span class="p">,</span> <span class="n">temp</span>
<span class="kt">integer </span><span class="n">i</span><span class="p">,</span> <span class="n">n</span>
<span class="n">n</span> <span class="o">=</span> <span class="n">size</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="n">c0</span> <span class="o">=</span> <span class="n">a</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="n">c1</span> <span class="o">=</span> <span class="n">a</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="k">do </span><span class="n">i</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">n</span><span class="o">-</span><span class="mi">1</span>
<span class="n">temp</span> <span class="o">=</span> <span class="n">c0</span>
<span class="n">c0</span> <span class="o">=</span> <span class="n">a</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="n">i</span><span class="p">)</span> <span class="o">-</span> <span class="n">c1</span>
<span class="n">c1</span> <span class="o">=</span> <span class="n">temp</span> <span class="o">+</span> <span class="n">c1</span> <span class="o">*</span> <span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">t</span><span class="p">)</span>
<span class="k">end do</span>
<span class="k"> </span><span class="n">clenshaw</span> <span class="o">=</span> <span class="n">c0</span> <span class="o">+</span> <span class="n">c1</span> <span class="o">*</span> <span class="n">t</span>
<span class="k">end function </span><span class="n">clenshaw</span>
<span class="k">end module </span><span class="n">clenshawmodule</span>
<span class="k">program </span><span class="n">main</span>
<span class="k">use </span><span class="n">clenshawmodule</span>
<span class="kt">double precision </span><span class="n">a</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>
<span class="n">a</span> <span class="o">=</span> <span class="p">(</span><span class="o">/</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">4</span><span class="o">/</span><span class="p">)</span>
<span class="k">print</span> <span class="o">*</span><span class="p">,</span> <span class="n">clenshaw</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="o">-</span><span class="p">.</span><span class="mi">5</span><span class="n">D0</span><span class="p">)</span>
<span class="k">end program </span><span class="n">main</span>
</pre></div></description><guid>http://insertinterestingnamehere.github.io/posts/basic-examples/</guid><pubDate>Mon, 08 Jun 2015 16:26:00 GMT</pubDate></item><item><title>First Impressions And Overcoming Compilation Errors</title><link>http://insertinterestingnamehere.github.io/posts/first-impressions-and-overcoming-compilation-errors/</link><dc:creator>Ian Henriksen</dc:creator><description><div><p>Most of the past month was spent in a mad dash to finish my master's thesis.
Who knew that writing 100 pages of original research in math could take so long?
Either way, I'm finished and quite pleased with the result.
My thesis is written and I have been able to, mostly, move on to other endeavors, like starting the work on my GSOC project, the Cython API for DyND (see the <a href="https://www.google-melange.com/gsoc/project/details/google/gsoc2015/iandh/5707702298738688">brief description</a> and <a href="https://github.com/numfocus/gsoc/blob/master/2015/proposals/ian-henriksen.md">full proposal</a>).</p>
<p>I've been able to start familiarizing myself with the package a little more.
My background is primarily in using NumPy and Cython, but it has been really nice to be able to use a NumPy-like data structure in C++ without having to use the Python C API to do everything.
Stay tuned for a few nice snippets of code over the next few days.</p>
<p>Overall, I've been impressed by the amount of functionality that is already present.
A few things like allowing the use of an ellipsis in indexing or providing routines for basic linear algebra operations have yet to be implemented, but, for the most part, the library is easy to use and provides a great deal of useful functionality at both the C++ and Python levels.</p>
<p>Before beginning detailed work on my project, I was first faced with the task of getting everything working on my main development machine.
For a variety of reasons, it uses windows and needs to stay that way.
Undaunted, I ventured forth, and attempted to build libdynd and its corresponding Python bindings from source with my compiler of choice, MinGW-w64.</p>
<p>MinGW-w64 is a relatively new version of MinGW that targets 64 bit windows.
It is not as commonly used as MSVC, or gcc, so it is normal to have to fix a few compile errors when compiling large amounts of C/C++ code.
Python's support for MinGW is shaky as well, but usually things come together nicely with a little effort.</p>
<p>After several long and ugly battles with a variety of compiler errors, I was able to get it all working, though there are still some test failures that still need to be revisited.
The DyND source proved to be fairly easy to work with.
The most difficult errors I came up against came from conflicts between the environment provided by the compiler and some of the type definitions in the Python headers.
I'll document some of the useful information I picked up here.</p>
<p>For those that aren't familiar with it, the C preprocessor is an essential part of writing platform independent code.
Among other things, it lets you write specialized sections of code for pieces that are specific to a given operating system, compiler, or architecture.
For example, to write a section of code that applies only to Windows, you would write something like</p>
<pre class="code literal-block"><span class="c1">// If the environment variable indicating that you're compiling on Windows is defined</span>
<span class="cp">#ifdef _WIN32</span>
<span class="c1">// Platform-specific code goes here.</span>
<span class="cp">#endif</span>
</pre>
<p>Similarly, if you want to differentiate between compilers,</p>
<pre class="code literal-block"><span class="cp">#ifdef _MSC_VER</span>
<span class="c1">// Code for MSVC compiler here.</span>
<span class="cp">#elseif __GNUCC__</span>
<span class="c1">// Code for gcc/g++ here.</span>
<span class="c1">// Compilers that implement a GCC-like environment</span>
<span class="c1">// (e.g. ICC on Linux, or Clang on any platform)</span>
<span class="c1">// will also use this case.</span>
<span class="cp">#else</span>
<span class="c1">// Code for all other compilers.</span>
<span class="cp">#endif</span>
</pre>
<p>Most of the work I did to get everything running involved modifying blocks that look like this to get the right combination.
Frequently, code is defined to do one thing on windows (with the assumption that only MSVC will be used) and another on Linux, even though, for MinGW, many of the Linux configurations are needed for the compiler.
In the past, I've found myself continually searching for what the right ways to detect a given compiler, operating system, or architecture, but it turns out there is a fairly complete <a href="http://sourceforge.net/p/predef/wiki/Home/">list</a> where the variables indicating most common compilers and operating systems are shown.</p>
<p>The build system CMake also provides ways of detecting things like that.
A few useful examples:</p>
<pre class="code literal-block"><span class="nb">if</span><span class="p">(</span><span class="s">WIN32</span><span class="p">)</span>
<span class="c"># You're compiling for Windows</span>
<span class="nb">endif</span><span class="p">()</span>
<span class="nb">if</span><span class="p">(</span><span class="s2">"${CMAKE_SIZEOF_VOID_P}"</span> <span class="s">EQUAL</span> <span class="s2">"8"</span><span class="p">)</span>
<span class="c"># You're compiling for a 64-bit machine.</span>
<span class="nb">endif</span><span class="p">()</span>
<span class="nb">if</span><span class="p">(</span><span class="s2">"${CMAKE_CXX_COMPILER_ID}"</span> <span class="s">STREQUAL</span> <span class="s2">"GNU"</span><span class="p">)</span>
<span class="c"># You're compiling for gcc.</span>
<span class="nb">endif</span><span class="p">()</span>
<span class="nb">if</span><span class="p">(</span><span class="s2">"${CMAKE_CXX_COMPILER_ID}"</span> <span class="s">STREQUAL</span> <span class="s2">"MSVC"</span><span class="p">)</span>
<span class="c"># You're compiling for MSVC.</span>
<span class="nb">endif</span><span class="p">()</span>
</pre>
<p>Now, on to some of the tricker bugs.
Hopefully including them here can help others resolve similar errors later on.</p>
<p>It is a less commonly known fact that the order of compiler flags matters if you are linking against different libraries.
(An aside, for those that are new to the command line flags for gcc, there is a nice introduction <a href="http://www.rapidtables.com/code/linux/gcc.htm">here</a>)
As it turns out, the order of the flags for gcc also matters in some less than intuitive cases.
After compiling libdynd, in order to compile a basic working example I had to do <code>g++ -std=c++11 -fPIC declare_array.cpp -ldynd</code> rather than <code>g++ -std=c++11 -ldynd -fPIC declare_array.cpp</code>.
Running the latter would give a series of linker errors like</p>
<pre class="code literal-block"><span class="err">undefined reference to 'dynd::detail::memory_block_free(dynd::memory_block_data*)'</span>
</pre>
<p><code>clang++</code> accepted both orderings of the flags without complaint.</p>
<p>I also ran into <a href="http://bugs.python.org/issue11566">this bug in Python</a> where there is an unfortunate name collision between a preprocessor macro defined in Python and a function in the c++11 standard library.
The name collision results in the unusual error</p>
<pre class="code literal-block"><span class="c">error: '::hypot' has not been declared</span>
</pre>
<p>coming from the c++11 standard library headers.
It appears that a <a href="http://stackoverflow.com/a/12124708/1935144">generally known solution</a> is to include the standard library math header before <code>Python.h</code>.
This wasn't a particularly favorable resolution to the issue since the Python headers are supposed to come first, so I opted to define the symbol <code>_hypot</code> back again to be <code>hypot</code> via a command line argument, i.e. adding the flag <code>-D_hypot=hypot</code>.
It worked like a charm.</p>
<p>The last batch of errors came from my forgetting to define the macro <code>MS_WIN64</code> on the command line when working with the Python headers.
That macro is used internally to indicate that a Python extension module is being compiled for a 64 bit Python installation on Windows.
In this case, forgetting to include that flag resulted in the error</p>
<pre class="code literal-block"><span class="err">undefined reference to '__imp_Py_InitModule4'</span>
</pre>
<p>at link time.</p>
<p>In trying to fix the various errors from not defining <code>MS_WIN64</code>, I also came across errors where <code>np_intp</code> (a typedef of <code>Py_intptr_t</code>) was not the correct size, resulting in the error</p>
<pre class="code literal-block"><span class="n">error</span><span class="o">:</span> <span class="n">cannot</span> <span class="n">convert</span> <span class="s1">'long long int*'</span> <span class="n">to</span> <span class="s1">'npy_intp* {aka int*}'</span> <span class="k">in</span> <span class="n">argument</span> <span class="n">passing</span>
</pre>
<p>The fundamental problem is that the logic in the Python headers fails to detect the proper size of a pointer without some sort of extra compile switch.
Passing the command-line argument <code>-DMS_WIN64</code> to the compiler when compiling Python extensions was sufficient to address the issue.</p>
<p>With most of the compilation-related issues behind me, I am now continuing my work in putting together several simple examples of how DyND can be used to perform NumPy-like operations at the C++ level.
I'll be posting a few of them soon.</p>
<h4>Update (6/8/2015)</h4>
<p>In fixing a few more compilation errors, I found another <a href="http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system">useful table</a> of C preprocessor macros that can be used to identify a given operating system.
Among other things, it mentions that any BSD operating system can be detected using something like</p>
<pre class="code literal-block"><span class="cp">#ifdef __unix__</span>
<span class="cp">#include</span> <span class="cpf">&lt;sys/param.h&gt;</span><span class="cp"></span>
<span class="cp">#ifdef BSD</span>
<span class="c1">// BSD stuff</span>
<span class="cp">#endif</span>
<span class="cp">#endif</span>
</pre>
<p>The <a href="https://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html#Standard-Predefined-Macros">table in the GCC manual</a> also lists which preprocessor macros are required for a compiler implementing the relevant language standards.</p></div></description><guid>http://insertinterestingnamehere.github.io/posts/first-impressions-and-overcoming-compilation-errors/</guid><pubDate>Fri, 22 May 2015 04:23:11 GMT</pubDate></item></channel></rss>