» on minimalism

Every so often, I mention to my wife that we have too much stuff and we need to get rid of it. Every time, she agrees and suggests that we start getting rid of stuff. And every time she says we should start with my books.

NOOOOO NOT MY BOOKS

We usually don't talk about it any more after that.

Actually, we do. She then points out that we don't have a lot of stuff, which I think is debatable. We talk about that for a little while and then drop the matter.

At least I have been learning to live with something more than minimalism in other parts of my life. Packing for trips, for instance. I like to pack compactly: not insanely compactly, but I will take a rolling suitcase that fits in the overhead bin for trips of a week or more.

Packing this way does not work when you have multiple children and go to anyplace more involved than Chick-fil-A.

I used to get really annoyed when we'd pack the car for trips to see our parents. “What? Another bag? What's that for?” “Why do you have to take three dolls and a box of blocks? You have toys at [destination] to play with” Now I just breathe, make little yoga motions with my hands, and carry the bag out to the car. I am at peace.

But I'm still really happy when we can get rid of stuff.

posted by Nate @ 11:46 PM [ 26 January A.D. 2012 ]

» no sharing for you

There was an item in my Facebook news feed saying that two of my friends had shared an article via the Washington Post Social Reader. OK, click on the article name to try to read it.

Hm, that takes me to a page where I'm supposed to sign up for the Washington Post Social Reader. That's odd. Maybe I clicked the link for the reader thingie. Back to news feed. Click.

Nope, still at the signup page. Never mind, you've made linking to your articles easy, but actually reading them tremendously hard. No thanks. This is not how the web works, folks.

(Yo, I hear you like social networks, so I put a social network in your social network so you can network while you network. Or somesuch.)

posted by Nate @ 11:43 PM [ 24 January A.D. 2012 ]

» taking struggles seriously

I love Francis Schaeffer's writings and outlook. For instance, this quote from a series on Schaeffer's “compassionate engagement”:

As Schaeffer spoke across the United States at various colleges, he would not only impress listeners with his engagement with the wider culture and his ability to make Christianity appear intellectually tenable and relevant to the contemporary era, he also demonstrated a notable compassion for those whose works he would analyze and interpret. This latter characteristic of Schaeffer's approach to intellectual engagement was illustrated vividly when, after reading a nonsensical poem by an unbelieving author, rebuked the laughing crowd, saying,

I get so tired of Bible believing Christians who laugh at these people—who laugh at them when they look at their tortured paintings. Do you laugh at a man at the door of hell? When evangelicals learn to stop their laughing and take such men and their struggles seriously then [evangelicals] can again begin to speak to our generation (Hankins, 77).

I offer this in juxtaposition, from Karl Schroeder's musings on the Fermi paradox:

The mystery deepens almost by the day, because we've now identified 700 extrasolar planets and the count is increasing rapidly. We should shortly be racking up lists of Earthlike worlds, and we're closing in on good estimates of how many there must be in our galaxy. And the number is in the billions. So one central argument against the existence of alien life--the 'rare Earth' argument that environments to host it must be rare--has been more or less disproven. And that, just this year.

As possible explanations dwindle, we are being drawn inexorably toward the one explanation that is no explanation: that we really are alone. Why should this be? As Wiley shows, all it would take would be one alien species with our capabilities appearing, sometime in the past couple of billion years, and for that species to surpass where we are now technologically by, oh, say, a couple of hundred years... and the evidence for their existence should be present right here in our own solar system. It's an astonishing conclusion.

So are we alone? Well, there is one other possibility, at this point. I've lately been trumpeting my revision of Clarke's Law (which originally said 'any sufficiently advanced technology is indistinguishable from magic'). My revision says that any sufficiently advanced technology is indistinguishable from Nature. (Astute readers will recognize this as a refinement and further advancement of my argument in Permanence.) Basically, either advanced alien civilizations don't exist, or we can't see them because they are indistinguishable from natural systems. I vote for the latter.

posted by Nate @ 4:47 PM [ 22 January A.D. 2012 ]

» my summer vacation

I always disliked the inevitable “My Summer Vacation” assignment in grade school. Not that I had not enjoyed my summer, mind you, but I was never the kid who went hunting for lions on the Serengeti or the kid who defended a small Brazilian village from ant hordes with a hoe and a glass of water. My summer vacations always sounded rather boring in comparison, even when compared against my classmates who had done virtually the same things: a family vacation, maybe some swimming or tennis lessons. Maybe I do not have a flair for the dramatic in my writing.

My big news this summer was starting a new job; I left my position at CodeSourcery for a quite different position at Mozilla, working on things related to Firefox performance. I flew to California for a week of orientation, raided the bike room for company shirts, came back on my first red-eye ever, and headed to Gamefest 2011 to spend a great time with old college friends. (And we are getting old.) The summer was off to a good start.

A week later, one of the aforementioned company shirts had been sliced open after I went into cardiac arrest, Tricia's mom called 911, and Tricia and her dad performed chest compressions until the paramedics came to intubate me and shock my heart.

Even now, it sounds surreal to write those words; I have no memory of the actual cardiac arrest or the time spent in the ICU in a medically-induced coma. (A bit bummed that I have no “I saw the light” stories.) As near as the doctors could figure out, I suffered from streptococcal myocarditis, an infection of the heart by the bacteria that causes strep throat (which I had and was taking antibiotics for). The doctors said this sort of disease is not supposed to happen in the states; it's common in the developing world, but antibiotics tend to prevent complications like mine from ever showing up. (We called the on call cardiologist one night later on and he said he had never heard of such a disease.) I did not have a heart attack; there was no blockage in my arteries, my heart merely stopped pumping properly and sat there quivering instead.

As you can imagine, this turned life quite upside down; my father-in-law recalls Tricia saying, “Stay with me, Nathan!” as they both gave me CPR before the paramedics arrived. Things were a bit touch-and-go in the ICU; Tricia posted a lot of updates on Facebook and got many, many well-wishes and prayers through doing so. Neither of us knows the full extent of the network of people we had praying for us; I'm sure the circle was much bigger than both of us imagined. Fortunately, I did come out of my medically-induced coma with no brain damage, spent a few days in the hospital (a boring hospital room was quickly enlivened with numerous drawings from my daughters), had a pacemaker put in, and came home rather weak, but expecting a full recovery.

And thanks be to God, recovered I have! I went through seven weeks or so of cardiac rehab at the hospital: walking/running/biking/weights three times a week (with which, I must say, we've been grateful for the extensive help from folks giving me rides and whatnot to help Tricia out). I'm happy to say that I showed steady progress through those sessions and have come out of them feeling in about the shape I was prior to hospitalization. As far as we can tell, I've had virtually no memory loss or other mental issues, which is great. I went back to work at the beginning of August (I needed a doctor's note to resume sitting in a chair and staring at a computer screen all day, which I found funny) and I've resumed running. I generally feel like nothing happened, except that I'm not supposed to drive until Christmas and I have a small metal saucer embedded in my chest.

Well, almost nothing. Me being my unemotional self, it was hard for me to even think of anything really bad happening. Sure, I went to the hospital unconscious in an ambulance, was in a coma for a couple days, but I could see myself improving in the hospital, could watch myself getting stronger in rehab, and so forth. Of course I was going to come through! Sure, we had to deal with a strep relapse about a month after, and I seemed in rough shape then (they took my blood pressure as something like 80 over 55 at the clinic), but I took drugs and they worked that time! What, me, worry?

Until about three weeks ago when Tricia's parents came to visit for the weekend; they had thankfully been here the weekend of my cardiac arrest and were extremely helpful in getting me to the hospital and probably for keeping Tricia sane as well. We went to Taste Cafe for breakfast, as we had done that previous weekend, and as we were going home (or maybe shortly after we arrived home), Tricia's dad said to me totally in jest, “Don't take another three hour nap now!” (Fatigue is one sign of heart problems.).

I freaked out. I still can't really explain what was going on, just this vague sense of dread that something bad was going to happen and I couldn't do anything about it. That Bad Things Happening was just going to be The Way Things Were when Mom and Dad visited. Or when we went to Taste for breakfast, or whatever. Wisely, Tricia told me go off and introvertly recharge for the afternoon, and after that and talking to Mom and Dad about that weekend, I came out of things feeling much better. And then my Mom and Dad came the weekend after that (they flew out the day I was hospitalized) and I was able to talk with them too, which helped some more.

And then there was this past week, when I went to California for my first Mozilla All-Hands. Sure, flying across the country is routine, but the circumstances surrounding the last flight certainly gave us cause to worry. (And I flew out on 9/11, which was just great from a superstitious standpoint.) I took strep-battling drugs with me just in case, and was anxious the first day or two out there, but gradually relaxed and treated things as Just Another Business Trip. And I wound up having a great time in California.

In any event, the stress/anxiety of the past couple of weeks have certainly given me a new appreciation for what exactly went on three months ago (tomorrow will be three months since I went to the hospital). We also now know that I don't always get sick when parents come to visit, I don't always go into cardiac arrest when I get strep, and shortly we'll be reassured that I can fly to California and not get sick the week after. All in all, we're doing pretty well; God has blessed us in our crisis.

Thanks for all of the well-wishes and prayers posted on Facebook and otherwise; thanks for all of the meals, lawn mowings, and offers of random help over the past couple months. We've both been astonished, grateful, and humbled at the outpouring of love and support we've been shown during this time.

posted by Nate @ 9:44 PM [ 18 September A.D. 2011 ]

» speeding up emacs saves

For a while now, I've noticed that saving files (maybe loading files, but saving files especially) was ridiculously slow in emacs. The busy cursor would come up for a good second or two when saving files. For a while I attributed it to the hard drive noticeably spinning up on my laptop (which it's doing now as I write this), but then I noticed--or got really annoyed--by the same behavior on my desktop. Particularly when editing files in a GCC git checkout, though I think it happened to other files as well.

Investigating, I could tell via strace that emacs was spinning off several processes (!) every time I saved a file. I tried using edebug, but that didn't seem to be working. (Somebody suggested that the routines I was trying to trace might be called directly from the C code in emacs and not go through whatever hooks edebug inserts into the system. This explanation sounds plausible, though quite unusual for emacs.) Finally some kind soul--cmm, I think--on #sbcl, where I ranted about this, suggested inserting:

(setq vc-handled-backends nil)

into my .emacs. Wow. It was like getting a computer upgrade, perhaps as radical of a change as an SSD might be; saves were now lightning fast compared to their prior speed.

I haven't poked into emacs's source code to see what was going on. And the puzzling thing is that this doesn't seem to be a consistent problem; James Knight/foom told me that he was dealing with large-ish git repos, as I was, and VC wasn't causing him any heartache. And clearly other emacs users aren't having similar problems--or perhaps everybody's silenty disabling VC and using more performant solutions. I did find a similar story to my own, but only with searching for vc-handled-backends explicitly, rather than other search terms (“slow,” “saving,” etc.).

So, hopefully search engines pick this post up and other afflicted people will find this solution and rejoice. Even better, somebody more knowledgeable about emacs than I will tell me what was really going on...

posted by Nate @ 9:12 PM [ 11 March A.D. 2011 ]

» final fantasy youtube videos

A while ago, once of my colleagues recommended Hayseed Dixie as an enjoyable bluegrass cover band. I went looking for them on YouTube and found a cover of AC/DC's “Highway to Hell”:

Why yes, that's a bluegrass cover of a rock'n'roll classic dubbed over a Final Fantasy video. Excellent.

Seeing this reminded me of my all-time favorite Final Fantasy video, set to The Offspring's “Staring at the Sun”:

And finally, because I clicked around after finding the Hayseed Dixie cover, I discovered this well-done video set to DHT's “Listen to Your Heart.” I'm not a huge fan of FFVIII (am a fan of the song, though), but the ballroom sequence at 1:12 is particularly sparkling.

posted by Nate @ 11:06 PM [ 16 February A.D. 2011 ]

» introducing nibbles

Steven Haflich, in an old Usenet posting, said:

The most pernicious failing of the ANA in my opinion is the refusal to admit the reality that computers deal in numeric bytes and characters with specific formats and codings. A portable ANSI CL program cannot write binary information to a socket or disk file that would be portably readable by another language platform, even a different Common Lisp, and even on the same system. A portable CL program cannot write characters and/or binary numbers of varying format to a single socket or stream. C and Java have no such problems, and portable programs can interact (modulo a little care about endianness byte order)...

If the language were redesigned today, I would like to see the definition get a lot closer to the realities of underlying platforms -- recognize that 8-bit-bytes have an important reality unshared by 9-bit bytes, recognize that real streams have endianess and need to have arbitrary varying datatypes passed through them,...

I have been writing a small library, nibbles, to address some of the shortcomings of Common Lisp in the above area. Specifically, nibbles features accessors on octet vectors for 16-, 32-, and 64-bit signed and unsigned integers in both endiannesses, and readers and writers from octet streams for the same. On x86oid SBCL, it also features efficient, optimized inlined versions of the vector accessors for simple vectors.

Code for reading and writing floats in various endiannesses is also present in the library, but has not been tested and is not exported in this release. Such support is planned for a future release.

Please check out the library, send feedback, and send patches if there are features you'd like to see added or bugs that need to be fixed. (It'd be great to have optimized inlined vector accessors for CCL, for instance...)

posted by Nate @ 10:48 PM [ 11 February A.D. 2011 ]

» reading into gene wolfe

Ultan's Library is a resource filled with articles about Gene Wolfe's books. Reading them is fascinating stuff; all sorts of possibilities are opened up by people who have clearly thought harder about this stuff than I have. Consider this passage, from the essay The Reader as Augur: Beginnings and Endings in Gene Wolfe's The Book of the Long Sun:

Chapter two of Nightside implies much: Silk visits the marketplace to buy a sacrificial victim, a signal that divination is imminently necessary; the fact that animals and vegetables, their names corresponding to the human nomenclature of Viron (men have animal, and women vegetable, names) are on sale suggests that a struggle is on for the ransom of souls; Silk rejects the purchase of a catachrest (which speaks distortedly, as its name implies) in favour of that of a night chough, which speaks clearly, if brokenly: he (and we) should heed whatever signs are honest in a world of deception (pp. 33-42).

Wow. That's just a small taste of the symbolism the essay author pulls out of the book. However...I understand that the point of this essay is to suggest how the reader can act as augur, drawing out the subtle implications of things as Silk himself might do. Fine. But am I really supposed to think about all that and understand all that while I'm reading? “A struggle is on for the ransom of souls.” Really? Did I miss the week of class (or even the whole class) where learning to read in this way was presented and practiced? Failing that, do people have a recommended book or two that discusses learning to read this way?

posted by Nate @ 7:34 PM [ 28 January A.D. 2011 ]

» books I didn't finish

Last year, I read that it was OK to not finish books. I practiced this idea, having resolved many times to buy no more books until I finished reading through the last stack, yet I have watched my book storage needs grow significantly over the years. But I never really absorbed it, insofar as giving myself permission to stop midway through a book, or even to skim it and count it as reading. Getting the majority of my books from the library has made doing this easier: I'm not personally invested in them, so it's OK if I don't finish them.

Like two recent books that I checked out from the library. I skimmed through Generation Ecstasy: Into the World of Techno and Rave Culture by Simon Reynolds. Since I'm a fan of electronica in various guises, I thought this book would be an interesting historical read. What it did teach me is that I know very little about electronic music, probably because a) I am not British and b) I don't take “recreational” drugs (part of his thesis is that electronic music is inescapably bound up with drug use, as you might have guessed from the title).

When the major acts with which you are familiar (The Prodigy, Chemical Brothers, etc.) are not brought up until the last chapter of the book and are described as electronica watered down for American sensibilities, you know you're in the wrong place. Orbital did receive roughly a page and their iconic song (Halcyon + On + On) did get a mention, so that was a familiar place to hang my hat. Speaking of Orbital, this is a great place to reference a fantastic performance of said song (skip to about 3:30 if you just want the punchline):

Quite a departure from the sublime ethereality of the original, but electronica anthem goodness nonetheless.

On the plus side, I now understand why I don't care for Massive Attack (radically different sub-genre of electronica).

I also buzzed through Endgame, volume II: Resistance by Derrick Jensen. I was pretty sure I wouldn't read the whole thing after flipping through it in the library, but I thought there might still be a nugget or two in there. Wow. I now understand what the capital-L Left looks like.

posted by Nate @ 8:05 AM [ 27 January A.D. 2011 ]

» swapping pieces

We had an unusually early dinner tonight, so I was able to play a game of chess with each of the girls tonight. Becca played a decent game; I tried to help her to avoid silly moves and to explain to her what moves were particularly good. She's at least thinking about things like attacking the center and so forth.

Ally's game was a little more interesting. She opened up with 1. h4 (“I'm attacking the center!” “Well, no, not really...”) and the game proceeded from there. We played for a while and I eventually maneuvered her into checkmate.

“I don't want the game to be done!” she said.

Mentally preparing for a discussion of being a good sport, I asked, “Why not?”

“Because I only have two pieces,” she replied, indicating my pieces next to her.

“You want to capture more pieces, and then the game can be over?” I asked. She nodded and I permitted her king to engage in a feat unknown to his kinsmen throughout the ages. The next bit of the game was then spent in me coming up with creative ways for her to take my pieces, usually by prompting her when opportunities arose, while trying to be careful to not totally give away the game.

After she had captured most of my “real” pieces, and I had sniped away her pawns, she indicated that it would be OK for me to capture pieces, too. So I went to work with my queen, along with prompting about what pieces to capture when. We wound up with my king and queen versus her king and you can probably guess the rest. She seemed happy enough about the whole thing, and we did have a chance to demonstrate good sportsmanship too.

posted by Nate @ 9:19 PM [ 23 January A.D. 2011 ]

» resolutions

I did only moderately well with resolutions this year. I read a lot of books, but not necessarily the ones I planned to read (sorry, Anathem, The Reformation, Personal Knowledge, American Catholic, and others; I'll catch you next year). I read quite a bit in my Bible, but not all the way through as I planned. For whatever reason, I get bogged down when I hit the wisdom books, particularly Psalms and Proverbs. I think I did an OK job of spending more time with my children this year, but probably not as much I thought I would at the beginning of the year. And so forth.

But there is one resolution I'm rather happy to have kept, only I didn't make it at the start of the year. Inspired partly by Clay Shirky's ideas of cognitive surplus and how we might do great things if we turned just a fraction of the time we spent watching TV into doing other things, I set a goal in mid-May of getting one patch per day for the rest of the year into GCC. I could have chosen other projects (my Common Lisp projects would have benefitted greatly from one patch per day for seven months), but for reasons that I'll not cover here (ask me offline if you really want to know), I decided to tidy up GCC a bit.

I'm happy to report at the end of the year that I've met my goal; git log --author=froydnj --since='11 May 2010' --format=oneline | wc -l says that I've made 220 commits. (That actually falls just slightly short of one patch per day, but I'm going to give myself some slack.) Granted, some of those were work related, but I'm going to ignore that and call it good. Some of them were bugfixes for problems I caused, but I was still doing useful stuff by fixing the bugs, right? And hey, that's an average, rather than one actual patch per day (especially with a new baby and with stage 3 being in effect, I haven't been doing much lately), but close enough.

Enough with the excuses; what did my patches do? I eliminated old interfaces (sadly, ditching __builtin_saveregs was not a easily done followup patch). I deleted dead code. I renamed things. I eliminated (minor) quadratic behavior (and again and again). I saved some space (several patches did this, but I think this one is the most significant). I starting untangling things that shouldn't be intertwined. I macro-ized common idioms. And so forth.

I learned a lot in doing all this. As I looked through the code, I also started to understand what bits needed to be cleaned up, and maybe even a little bit of why. And I have to say that I'm looking forward to when 4.6 is released and patches start being accepted for 4.7; I'm hoping that I'll find just as many opportunities to contribute next year as well.

posted by Nate @ 8:51 PM [ 24 December A.D. 2010 ]

» quotes from moral panics and the copyright wars

I recently finished Moral Panics and the Copyright Wars by William Patry and found it to be quite good. If you've read Free Culture by Lawrence Lessig, the books are quite similar; Patry's book is slightly more technical than Lessig's, but has less of the obvious heart that Free Culture exudes. Patry devotes a significant chunk of his book to unpacking the rhetoric of the copyright wars (just because piracy has been used to describe copyright breakers for two hundred years doesn't mean that we are not emotionally affected by the description, for instance, or that why describing the things involved as intellectual property elicits particular judgements about the parties involved); his analysis of the metaphors involved in describing the origins of copyright--and why those metaphors don't work very well--is particularly good. I found several of the quotes in the book to be right on the money, and I provide them for your enjoyment below.

Copyright and trademark are not matters of strong moral principle. Intellectual property regimes are economic legislation based on policy decisions that assign rights based on assessments of what legal rules will produce the greatest economic good for society as a whole.

Sarl Louis Feraud Intl' vs. Viewfinder, Inc., 2nd Circuit 2007

The principle of copyright is this. It is a tax on readers for the purpose of giving a bounty to writers. The tax is an exceedingly bad one; it is a tax on one of the most innocent and most salutary of human pleasures; and never let us forget, that a tax on innocent pleasures is a premium on vicious pleasures. I admit, however, the necessity of giving a bounty to genius and learning. In order to give such a bounty, I willingly submit even to this sever and burdensome tax. Nay, I am ready to increase the tax, if it can be shown that by so doing I should proportionally increase the bounty. My complaint is, that my honourable and learned friend doubles, triples, quadruples, the tax, and makes scarcely and perceptible addition to the bounty.

...It is good that authors should be remunerated; and the least exceptionable way of remunerating them is by a monopoly. Yet monopoly is an evil. For the sake of the good we must submit to the evil; but the evil ought not to last a day longer than is necessary for the purpose of securing the good.

--Lord Thomas Macaulay

We should be trying to hone the system so that the greatest rewards and encouragement go to those industries which need and deserve them the most. Where IP rights perform their function of advancing the science or arts, they should be encouraged to do so. Where or to the extent that they do not, they have no justification and the normal disciple of competition should apply. The gluttony which has resulted in the growth of of completely unnecessary or excessively long IP rights undermines the system itself.

--Sir Hugh Laddie

It may seem unfair that much of the fruit of the compiler's labor may be used by others without compensation. As Justice Brennan has correctly observed, however, this is not “some unforseen byproduct of a statutory scheme.”...It is, rather, “the essence of copyright,”...and a constitutional requirement. The primary goal of copyright is not to reward authors, but “to promote the Progress of Science and useful Arts.”

--Justice Sandra Day O'Connor, Feist Publications, Inc. v. Rural Telephone Service Company

Not surprisingly, then, the metaphor of authors as parents of their works was not first put forth by authors, but instead by London book publishers in the eighteenth century, at the dawn of modern copyright, to justify their assertion of perpetual commodity rights in authors' works. As commodities, those works were acquired by book publishers from authors for as little money as possible (and sometimes no money). The invocation of the metaphor was thus the beard for publishers' economic objectives. From the beginning of modern copyright, we see one of the central rhetorical features of copyright discourse--authors put forth as the basis for and beneficiaries of rights that are in truth owned by publishers and other corporations who regard authors as a negative item on balance sheets to be reduced as much as possible.

posted by Nate @ 5:33 PM [ 18 December A.D. 2010 ]

» optimizing pixel conversion

In the previous post a previous post, I described a framework for doing pixel conversion where the separate steps were kept at arm's length: pixel reading, conversion proper, pixel writing, and the loop over the pixels in question. All of these steps were tucked away behind generic functions and closures, making it difficult for a static compiler to glom everything together and generate high-performance code. Runtime compilation might also have problems, but at least there are more ways to attack the separation.

This post is about a way to open up optimization possibilities for a static compiler and keep most of the abstraction.

The core idea behind the last proposal was that generic functions could specify how to read, write, and convert pixels. The core idea here is that we need to extend the protocol to talk about how to loop over the pixels: we need to provide a way to specialize operations at the pixel buffer level.

With that in mind, our entry point looks like:

(defun convert-pixels (dst-format src-format dst-buffer dst-start
                       src-buffer src-start n-pixels)
  (funcall (find-bulk-converter dst-format src-format)
           dst-buffer dst-start src-buffer src-start n-pixels))

find-bulk-converter can, by default, return the simple converter we already discussed.

(defun simple-converter (reader converter writer n-pixels)
  (loop repeat n-pixels
        do (multiple-value-call writer
             (multiple-value-call converter (funcall reader)))))

(defmethod find-bulk-converter (dst-format src-format)
  (let ((converter (find-pixel-converter dst-format src-format)))
    #'(lambda (dst-buffer dst-start src-buffer src-start n-pixels)
        (let ((reader (pixel-reader src-format src-buffer src-start))
              (writer (pixel-writer dst-format dst-buffer dst-start)))
          (simple-converter reader converter writer n-pixels)))))

(I've renamed find-converter from the first post into find-pixel-converter to more accurately capture what the function is supposed to do.)

Diversion: If you want to be obsessively micro-optimizing, you might rewrite the pixel-reader and pixel-writer functions slightly:

(defmethod pixel-reader ((format rgba))
  #'(lambda (buffer start)
    #'(lambda ()
        (multiple-value-prog1 (values (aref buffer start)
                                      (aref buffer (+ start 1))
                                      (aref buffer (+ start 2))
                                      (aref buffer (+ start 3)))
          (incf start 4)))))

(defmethod pixel-writer ((format rgba))
  #'(lambda (buffer start)
    #'(lambda (r g b a)
        (setf (aref buffer start) r
              (aref buffer (+ start 1)) g
              (aref buffer (+ start 2)) b
              (aref buffer (+ start 3)) a)
        (incf start 4)
        (values))))

Why would you do this? Well, because now you can move more work—specifically, generic function calls—out of the conversion function proper:

(defmethod find-bulk-converter (dst-format src-format)
  (let ((converter (find-pixel-converter dst-format src-format))
        (reader-gen (pixel-reader format))
        (writer-gen (pixel-writer format)))
    #'(lambda (dst-buffer dst-start src-buffer src-start n-pixels)
        (let ((reader (funcall reader-gen src-buffer src-start))
              (writer (funcall writer-gen dst-buffer dst-start)))
          (simple-converter reader converter writer n-pixels)))))

And because the double lambdas are pretty sweet. Of course, nobody reading this would do such things without profiling first, right? Good. Now, back to why we wanted to move to find-bulk-converter in the first place.

The advantage of this approach is that now you can write specialized conversion routines that deal with entire buffers at once. Need RGBA to CMYK conversion to go fast?

(defmethod find-bulk-converter ((dst-format cmyk) (src-format rgba))
  ;; Write whatever you like.  Maybe manually inlining the
  ;; read/convert/write routines is sufficient.  Maybe you can figure
  ;; out a clever way to share code between this routine and pixel
  ;; routines so the compiler does most of the heavy lifting for you.
  ;; Maybe write vectorized code if your implementation supports it.
  ;; Maybe call out to C if you really need to.
  ...)

Sure, you do have to duplicate all the stuff I mentioned above--pixel reading, pixel writing, looping logic, etc. But you only have to do it for the cases that really matter. And if you do something like vectorizing the code, chances are that the loop structure and such would look quite different between routines anyway. If it doesn't? Good, try to abstract things away there, too.

posted by Nate @ 5:07 PM [ 29 September A.D. 2010 ]

» on piracy

I've started reading Piracy: The Intellectual Property Wars from Gutenberg to Gates by Adrian Johns recently, and I've found it to be engrossing reading. Granted, I'm only 40 pages in, but the story so far has been great. The NEC brandjacking story at the beginning of the book boggles the mind.

I have also been suitably chastised with regards to the word “piracy.” Long ago, a more ignorant version of myself was much impressed with GNU's suggestion to avoid various words, one of which is “piracy”; I will quote their reasoning here:

Publishers often refer to copying they don't approve of as “piracy.” In this way, they imply that it is ethically equivalent to attacking ships on the high seas, kidnapping and murdering the people on them. Based on such propaganda, they have procured laws in most of the world to forbid copying in most (or sometimes all) circumstances. (They are still pressuring to make these prohibitions more complete.)

If you don't believe that copying not approved by the publisher is just like kidnapping and murder, you might prefer not to use the word “piracy” to describe it. Neutral terms such as “unauthorized copying” (or “prohibited copying” for the situation where it is illegal) are available for use instead. Some of us might even prefer to use a positive term such as “sharing information with your neighbor.”

I think it is fair to say that one might come away from reading this with the expectation that this appropriation of “piracy” is a recent doing. A younger, idealistic version of myself might be forgiven for wanting to fight back against the media companies's propaganda campaign. However, Piracy states:

When and where exactly did people begin to refer to intellectual purloining as piracy? The answer is clearer than one might suppose. It is easy to establish that the usage emerged in English before it did in other European languages. It is more difficult to establish the exact moment the term was coined, but it seems clear that it occurred some time in the mid-seventeenth century. In around 1600 piracy seems not to have carried this meaning at all, except on a few isolated occasions as a metaphor...

At the other end of the century, however, piracy suddenly appears everywhere. It is prominent in the writing of Defoe, Swift, Addison, Gay, Congreve, Ward, and Pope, and pirate suddenly starts to be defined in dictionaries as “one who unjustly prints another person's copy.” Very soon after that, it can be seen invoked in learned or medical contentions...And dictionaries of other European languages published in the late seventeenth and eighteenth centuries then show the term spreading — first to France, then to Italy, and at length to Germany too...

So if Johns is to be believed, the usage of the word is not exactly a new phenomenon—we've been using it as a synonym for unauthorized copying for several centuries now. Definitely not a late twentieth century invention; probably a little late to turn back the clock. Also worthwhile to note that the term appears to have been introduced/popularized by the writers, not the publishers—though the publishers probably had an opinion.

Johns goes on to write about the origins of “piracy”:

Ancient writers bequeathed two principal associations of the word pirate. Pirates were seagoing thieves, certainly. But there was more to them than that. They were irritants to the civilized order itself. Their very existence amounted to a test of that order. Cicero, for example, invoked the pirate as his ur-criminal — he who declined even the honor that supposedly obtained among thieves. The thing about pirates, for Cicero, was that they lay beyond all society. They had no set place, and owed no customary allegiance to legitimate authority. Their existence required that society distinguish itself and its conduct from all that they did...Indeed, it was their sheer unsociability that for him seemed the defining characteristic of pirates...

I think the people in pirate parties would not necessarily object to the second description above.

posted by Nate @ 8:56 PM [ 28 September A.D. 2010 ]

» more pixel conversion

A couple of thoughts on the previous post.

First, thanks to everyone who pointed out that I should have been using multiple-value-prog1 instead of prog1.

Second, one person commented that they didn't really understand the point of the post. I should have explained the context behind the post.

If you look at graphics code--or at least the open-source graphics code I've happened to look at in the past week or so, maybe there's better stuff out there--there's a lot of repeated code. Cut-and-paste programming, sure, but also just a lack of abstraction in general. Maybe that's a result of using C; maybe it's a result of a lack of imagination. Maybe using C causes a lack of imagination. wink

I wanted to see if I could be more abstract. If I have to write pixel conversion routines from grayscale to RGBA and CMYK to RGBA, I think it'd be a clever thing to only write the “stuff pixels in RGBA format here” once. Likewise, if I have to write CMYK to grayscale, I shouldn't have to rewrite the “grab pixels in CMYK format” bits again. Writing out the core conversion loops gets tedious after a while. We have first-class functions; we ought to be able to separate out the looping logic from the “do this inside the loop” logic. And so on.

Part of the subtext also is that for me is that when I sit down to write Lisp, I often get distracted by the One True Way to do it, the way that will yield the fastest code out of the compiler the first time. I might not always succeed at doing it, but I get distracted by it.

For whatever reason, I don't have this problem when writing Python or even C, only in Lisp. I don't write prototyping code very well in Lisp. So whipping out thirty lines of code that looks reasonably useful and that might not be screaming performance-wise is a good exercise for me.

From all that came the sketch of the ideas yesterday: write the “read a pixel in this format” once, write the “write a pixel in this format” once, write the core conversion loop once, etc. As a bonus, a function like:

(defmethod pixel-reader ((format rgba) buffer start)
  #'(lambda ()
      (multiple-value-prog1 (values (aref buffer start)
                                    (aref buffer (+ start 1))
                                    (aref buffer (+ start 2))
                                    (aref buffer (+ start 3)))
        (incf start 4))))

would work regardless of the particular datatype of the RGBA components, assuming the inheritance hierarchy is written sanely. 8-bit bytes, 16-bit words, single-precision floats, all of these and more are taken care of with one function. Granted, you'd probably want to write separate methods for each datatype if you were being serious about taking this route.

I felt pretty good about my codesketch. I prototyped, it looked reasonable, and it didn't have to cons 0 bytes and run 20x faster than the naive method. I wanted to share. That's the explanation that should have gone in yesterday's post.

posted by Nate @ 9:01 PM [ 27 September A.D. 2010 ]