Thursday, April 30, 2009

Bright of the Sky

Bright of the Sky is a 2007 science-fiction-and/or-fantasy novel by Kay Kenyon, marking the start of the series entitled — poetically, if opaquely — The Entire and the Rose.

It is slightly less weird, I think, than Perdido Street Station, and slightly weirder than Wicked.

It depicts in thin slices a future Earth, and in broad swaths a strange microuniverse known to its inhabitants as the Entire. The back of the book describes the Entire with the bizarre phrase "a landlocked galaxy," which describes it about as well as any other concatenation of two dictionary words. Its geography (cosmography?), variable and not-quite-fractal, remains outside my mental grasp: I can understand it as far as being a five-limbed rosette* with branching tendrils, larger than the Ringworld by several orders of magnitude, but details beyond that elude me.

Despite the decidedly nonplanetary nature of the Entire, the novel might best be classified as planetary romance — although I wouldn't be half surprised if it slides into sword-and-planet somewhere along the way. The storyline is compelling, if somewhat fragmentary: this is understandable given that it's the first in a series, and only cursorily attempts to be a full story in and of itself. (Unusually, much of the action takes place before the novel's beginning, though it does not really start in medias res per se... apologies for the vagueness; I'm desperately trying to avoid spoilers.)

So far it scores 1/1; this is enough for me to intend to head out to B&N tomorrow after work and pick up the next in the series (A World Too Near, and frankly City Without End if they have it). I'm very much looking forward to seeing where Ms. Kenyon takes the Entire.


* Yes, there is a horrible, vile pun here.

Wednesday, April 29, 2009

Making C++ do C99 things (part 3/3)

So the code works in three stages.

First, the expressions ‍bit_gravity_ = ForgetGravity etc. are executed. Misleadingly, each of these returns a value of type ParameterSetter. ParameterSetter is itself an aggregate of POD type, so it can be used to initialize a value of type ParameterSetter in a C89-style structure initializer. Each ParameterSetter contains information on how to set a single member of the underlying structure, and what to set it to. (It's perfectly safe to store the latter data in an array of bytes: each member of a POD struct is POD, and POD data can be copied bytewise.)

Second, struct XSetWindowAttributes_ is also of POD type, and therefore can be initialized by a C89-style structure initializer. Furthermore, as a POD aggregate, all members of XSetWindowAttributes_ whose values are not specified are zero-initialized. The values in the initializer correctly match the first several members of the structure.

Third, the converting operators simply take the data and code-references in the ParameterSetters, and execute the latter on the former until an unspecified (and therefore zero-initialized) ParameterSetter is hit — at which point we're done!

The fun part is that a C++ compiler willing to go through enough levels of constant folding, function inlining, dead store elimination, and application of the return value optimization could actually take that code and turn it into the same assembly as the ISO C99 compiler would produce — everything is known at initialization time, and every step it would need to take is a small one that most commercial compilers already know how to take. We're not talking superoptimization here.

(It'd be a little harder, but not at all outside the realm of feasibility, to do something similar for at least simple nonconstant initalization values: e.g., bit_gravity_ = old_gravity and so forth.)

Edit 2009-04-30: grammar fixes (removed ghosts of edits past); some minor clarifications.

Tuesday, April 28, 2009

Making C++ do C99 things (part 2/3)

XSetWindowAttributes_ xswa = {
‍ ‍ bit_gravity_ = ForgetGravity,
‍ ‍ background_pixmap_ = None
};
So here is how you do it. Note that this is a sketch of an implementation rather than a full implementation, but it should suffice as a proof of viability of the concept. (Though not of its sanity. If you want that, see the previous post's equivalence.)

For reference, XSetWindowAttributes is defined here.


// If this line doesn't work -- it's untested -- it may be necessary
// to extract the type via template deduction instead.
#define MEMBER_TYPEOF(x) BOOST_TYPEOF((NULL)->*(x))

struct background_pixmap_tag {
‍ ‍ typedef MEMBER_TYPEOF(XSetWindowAttributes::background_pixmap) type;
‍ ‍ static type XSetWindowAttributes::* const mptr =
‍ ‍ ‍ ‍ XSetWindowAttributes::background_pixmap;
‍ ‍ static void apply(XSetWindowAttributes &str, char const *buf)
‍ ‍ { str.*mptr = *(type const *)buf; }
};

struct background_pixel_tag {
‍ ‍ typedef MEMBER_TYPEOF(XSetWindowAttributes::background_pixel) type;
‍ ‍ static type XSetWindowAttributes::* const mptr =
‍ ‍ ‍ ‍ XSetWindowAttributes::background_pixel;
‍ ‍ static void apply(XSetWindowAttributes &str, char const *buf)
‍ ‍ { str.*mptr = *(type const *)buf; }
};

// ... and so forth; these tag-types are boring and can be generated by,
// e.g., a macro taking the type name and a Boost.PP Sequence of member names.
// (And save that sequence; you'll want it for other things.)



// Compute the maximum size of the raw data types of each member of the
// underlying struct; this is left as an exercise for the reader. Hint:
// generate a boost::mpl::vector of tag-types from the Boost.PP.Sequence
// of member names.
static const size_t max_data_size = boost::mpl:: ... ;

struct ParameterSetter {
‍ ‍ apply_fptr_t apply_fun;
‍ ‍ char buffer[max_data_size];
}

template <typename Tag>
struct Parameter {
‍ ‍ ParameterSetter operator=(typename Tag::type value) {
‍ ‍ ‍ ‍ inline ParameterSetter ps = { &Tag::apply };
‍ ‍ ‍ ‍ (typename Tag::type *)(void *)(char *)(ps.buffer) = value;
‍ ‍ ‍ ‍ return ps;
‍ ‍ }
};

Parameter background_pixmap_;
Parameter background_pixel_;
// ... more preprocessor-handlable declarations ...

struct XSetWindowAttributes_ {
‍ ‍ ParameterSetter a0;
‍ ‍ ParameterSetter a1;
‍ ‍ // ... the maximum N needed is the sequence size == member count ...
‍ ‍ ParameterSetter aN;

‍ ‍ XSetWindowAttributes attr;
‍ ‍ inline operator XSetWindowAttributes &() {
‍ ‍ ‍ ‍ if (a0.apply_fun) (a0.apply_fun)(attr, a0.buffer) else return attr;
‍ ‍ ‍ ‍ if (a1.apply_fun) (a1.apply_fun)(attr, a1.buffer) else return attr;
‍ ‍ ‍ ‍ // ... you know the drill by now ...
‍ ‍ ‍ ‍ if (aN.apply_fun) (aN.apply_fun)(attr, aN.buffer) else return attr;
‍ ‍ ‍ ‍ return attr;
‍ ‍ }
‍ ‍ inline XSetWindowAttributes* operator &()
‍ ‍ { return &(this->operator XSetWindowAttributes &()); }
};

// ... and Bob's your uncle.

XSetWindowAttributes_ xswa = {
‍ ‍ bit_gravity_ = ForgetGravity,
‍ ‍ background_pixmap_ = None
};


(Explanations next time.)

Monday, April 27, 2009

Making C++ do C99 things (part 1/3)

C99 (the 1999 ISO revision of the ANSI C standard) was extended to allow a special syntax for initializing structures: designated initializers. This allows the initialization of a possibly-complicated structure using the names of the individual entries. For example,
XSetWindowAttributes xswa = {
‍ ‍ .bit_gravity = ForgetGravity,
‍ ‍ .background_pixmap = None
};
is a legal way of setting only the named members of the structure. (The remainder of the structure members will be default-initialized.)

Designated initializers have not been approved for C++0x, and seem unlikely to be, due to lack of time and consideration. This is fair, really; in C++ one could simply write an immediate local subclass—
struct xswa_t : XSetWindowAttributes {
‍ ‍ xswa_t() : bit_gravity(ForgetGravity), background_pixmap(None) {}
‍ ‍ XSetWindowAttributes &POD() { return this; }
‍} xswa;
which would effectively function exactly as the designated-initializer version does, right down to &xswa being a legal argument to XChangeWindowAttributes(). (It wouldn't quite be POD, because it doesn't have a trivial default constructor; this might matter if you had to pass it into a metaprogrammatic POD-aware template function, so the POD() method has been outlined above, as a shorthand for (XSetWindowAttributes&).)

But that's just too easy; so next time I'll describe how to make the following syntax work.
XSetWindowAttributes_ xswa = {
‍ ‍ bit_gravity_ = ForgetGravity,
‍ ‍ background_pixmap_ = None
};


Edit 2009-04-28: Fixed minor verbiage error and minor syntax error.

Sunday, April 26, 2009

C++ and the lambda cube

So the three axes of the lambda cube are:
  • Types depending on types
  • Terms depending on types
  • Types depending on terms
(If you don't have terms depending on terms, you don't have a programming language at all, really.)

C++ appears to have all three, but doesn't really. I shall elucidate.
  • Types depending on types are simple: those are any form of type constructor of kind * -> *. Specifically, int *, int class A::*, and std::vector<int> are all examples of type constructors applied to int.
  • Terms depending on types are in general less familiar to novice C++ programmers, but are still well-known: the humble sizeof (present since C) is an example of this. User-defined type-to-term "functions" are also possible:

    template <typename T> class is_int { static const bool value = false; };
    template <> class is_int<int> { static const bool value = true; };

    assert(is_int<int>::value);
    assert(!is_int<long>::value);
  • Types depending on terms would seem to exist: the template std::array takes an argument of type std::size_t — e.g., std::array<int, sizeof(long)+6*7>.
However, this last one merely relies on an implicit hoisting into the type-system of integers and their operations. That is, for each integer value of each integral type, there is a basic unnamable type corresponding to that integer and that integer alone; and there are metaoperations defined across those types to produce each other. (Haskell does this sort of thing all the time as an exercise.) The constexpr extension in C++0x will allow users to easily define type metaoperations. (This was already possible, of course — see, e.g., Boost.MPL — it will now merely be easier.)

The presence of this dichotomy is evident from the fact that, while the above declaration of std::array is legal, the simpler int n = 0; std::array<int, n> is impossible to compile. "Types depending on terms" is not something that a statically typed language can easily have, if at all.

Because of inheritance and subtyping, it is possible for the underlying type of an object to depend on the value of a term; but the structural type of that object will still be fixed, being at most the supertype (limit superior) of all the underlying concrete types it could be. In a language like C++, where there is no ultimate supertype, you cannot have a function that returns, directly, either an int or a float depending on the values of its parameters.

Not that I can imagine ever wanting to. I'm just saying.

Saturday, April 25, 2009

Friday, April 24, 2009

More mad science

The Heart of Brazil is the most expensive gemstone in the world. It cost several hundred million dollars to synthesize and stabilize, and continues to cost millions to protect it.

It's not much to look at — it certainly doesn't appear edible. The untrained eye might mistake it for quartz, and even the trained eye (noting its monoclinic rather than orthorhombic structure) might still dismiss it as an admittedly unusually well-formed rod of gypsum.

In fact, the Heart of Brazil is made entirely of crystallized theobromine.

Of the five most recent attempts on it, four were by amateurs who admitted they intended to eat it; the fifth had been hired, and his employer had intended to sell pieces of it as very expensive candy to very rich idiots (several of whom had already prepaid for the chance to eat it).

Considering that a) crystalline theobromine is actually merely bitter, b) the company that produced the Heart is currently beginning mass production of theobromine for use as a food additive (not available in retail, but still obtainable), and also c) LD50 for theobromine is believed to be around 175mg/kg — less than 25 grams, or 15 cc, and d) facts a through c are posted on the placard next to the Heart...


(... I am not at all satisfied with this one.)

Thursday, April 23, 2009

Various fenestral things (continued)

... and as it turns out, some of those are actually words-in-use.

Circumfenestrate adj. is a biological term apparently only used to describe nematodes of genus Heterodera; it refers to the structure of the vulval cone (whatever that is), meaning that said cone is a single opening. It contrasts with the adjective ambifenestrate, which I hadn't even imagined; this latter means that there is a "vulval bridge" across the vulval cone, dividing it into two openings.

Some sources also appear to use the terms bifenestrate (where the vulval bridge sufficiently wide that the two openings appear distinct) and semifenestrate (either ambifenestrate or bifenestrate); these consider semifenestrate to contrast with circumfenestrate, and ambifenestrate to be limited to narrower vulval bridges. I think what's happened is that the older ambi-/bi- distinction has fallen to the wayside, being somewhat subjective, so that ambifenestrate has taken on the meaning that semifenestrate used to have; but I am not a nematologist of any stripe, and do not have access to the sort of scientific journals and references that I would need in order to test that hypothesis.

Interfenestrate is in use, interestingly, only as a verb, and at that apparently a back-formation from the noun form interfenestration, an architectural term meaning the space between windows. (Verb use citation here, where it is used, without explanation, to mean to place windows between.) This is related to fenestration, the act or process of adding windows to a building or schematic, whence comes the verb fenestrate by backformation.

Of course, fenestrate as an adjective, rhyming with the other adjectives and meaning windowed, is also in use.

(These are all undeniably words, rather than mere protologisms, as they are used in sentences without explanation or humor and are immediately understood by people other than the writer.)

Wednesday, April 22, 2009

De defenestratione

So you've probably run across the word defenestrate /dəˈfɛn.ɛˌstɹeɪt/ v.tr. 1. to throw [sth.] out a window 2. to remove windows from [a building, schematic, etc.]. 3. to remove (Microsoft) Windows from [a computer]. I'm not actually convinced that it is a word, except in sense 2: it seems that virtually all uses of the term, this one included, give its definition in the reference — it is scarcely ever used unexplained. Often — as here — it is accompanied by a comment that exfenestrate /ɛksˈfɛn.ɛˌstɹeɪt/ seems to be the proper word for that (sense 1 only).

Allegedly there is also a parallel word transfenestrate /tɹænsˈfɛn.ɛˌstɹeɪt/ v.tr. to throw [sth.] out a closed window, although it only gets 25 unique Google hits (well, 26 now), each and every one of which explains its meaning. (It seems to have been invented by Thomas Pynchon for use in his novel Vineland, whose protagonist apparently self-transfenestrates annually.) It, too, seems incorrect — it should really be perfenestrate /pɝˈfɛn.ɛˌstɹeɪt/, and perhaps this time we can catch the mistake before it spreads too far. (Of course perfenestrate could also mean, unqualified, to throw [sth.] out a window; but given that we seem to need two words anyway, it is not such a stretch.)

That got me to thinking, though: the (etymologically similar) term transfenestrate /ˈtɹæns.fɛnˌɛ.stɹət/ adj. 1. across a window 2. beyond a window — although note the stress and pronunciation changes! — is perfectly acceptable.

Some similar forms include:
affenestrate /ˈæf.fɛnˌɛ.stɹət/
adj. 1. toward a window
antefenestrate /ˈæn.tə.fɛnˌɛ.stɹət/
adj. 1. before a window (usu. 'before' of spatial position)
circumfenestrate /ˈsɹ̩.km̩.fɛnˌɛ.stɹət/
adj. 1. around a window
extrafenestrate /ˈɛks.tɹə.fɛnˌɛ.stɹət/
adj. 1. beyond anything pertaining to windows
intrafenestrate /ˈɪntɹə.fɛnˌɛ.stɹət/
adj. 1. within a window; within windows
interfenestrate /ˈɪntɝ.fɛnˌɛ.stɹət/
adj. 1. between windows
postfenestrate /ˈpoʊst.fɛnˌɛ.stɹət/
adj. 1. after a window
prefenestrate /ˈpɹi.fɛnˌɛ.stɹət/
adj. 1. before a window (usu. 'before' of temporal position)
subfenestrate /ˈsʌb.fɛnˌɛ.stɹət/
adj. 1. below a window
superfenestrate /ˈsupɝ.fɛnˌɛ.stɹət/
adj. 1. above a window

Tuesday, April 21, 2009

JAGS Wonderland

JAGS — the acronym standing, not inaccurately, for Just Another Gaming System — is a relatively unpretentious generic RPG system in the traditional style: anyone who has any experience with, say, GURPS or BESM 2nd/3rd will not find anything terribly surprising here.

JAGS Wonderland, on the other hand — available at the same link as JAGS itself — is the star of the JAGS setting and sourcebook lineup. It is (as the perspicacious reader may have surmised from the title) an infusion of horror into the works of Lewis Carroll, and anyone who has any experience with such works as the AD&D modules EX1-2 or American McGee's Alice... well, is still going to be awed and amazed, because Wonderland is several separate sinister and spicy-sour strata of screwed and screwed up, each delicious and flaky like so much player-character sanity.

I categorically refuse to go into spoilery details; the .pdfs are there for the reading, although if you think you'll ever potentially play in this setting, keep in mind that the Book of Knots is GM-only material — and you might not want to read even Wonderland.pdf. If you think you might want to run it, on the other hand, please do go read it, Knots included! (Alas, there are numerous typographical errors, and a fair amount of the artwork is "we can't afford real art" 3D renders; this is perhaps forgivable since, well, they can't, but it does occasionally grate.)

(Note: Although the word "JAGS" does appear in the book title, JAGS is reasonably generic, and so there are few hooks where a setting could be tightly coupled to the JAGS ruleset; Wonderland does not even make the attempt. If you have strong preferences about what kind of cup you drink your tea from, JAGS could be dissevered from Wonderland and another system grafted on in its place without the result appearing too much like the sort of twisted chimera one might expect to find too far down the rabbit hole.)

Monday, April 20, 2009

Differential Equations (Agnew, 1960)

Among my many, many other books is a red hardcover textbook entitled, simply and accurately, Differential Equations, by Ralph Palmer Agnew. It was first published in 1942; the second edition, which is the one I own, was printed in 1960.

It does not, I should emphasize, appear to be the copy of that edition that has gone missing from the National Library of Australia.

I obtained it, not from a bookseller, but from a furniture store — probably sometime in the mid-1990s: while my parents were shopping for, I think, a new couch, I entertained myself with a book; and, as they did end up making their purchase there, the salesman was kind enough to throw it in when I asked after it.

It is, strangely, the oldest book I own. Anyone who knows me reasonably well would probably expect me to own much older books than this, but if I do I can't find them anywhere. (I do have a number of Edgar Rice Burroughs novels in storage, but the oldest are the the 1973 Ballantine editions of the Barsoom series, with cover art by Gino D'Achille.)

It has a peculiar sense of humor: dry, self-aware, but detached and unintrusive. I never did finish it. (Nor did I ever grok diffy-Qs as well as I felt I ought, even when I studied them formally in college; but that's neither here nor there.)

Sunday, April 19, 2009

Dream (not a dream)

The Princess of Dream smiled her vacant smile in response, as the clouds of sweet pink smoke encircling her began to drift toward me. "Oh, yes, Sir Violet. I know. Why, it happens every morning, does it not? This realm is, after all, maya: destined to be rewoven nightly in sleep, and torn asunder daily in waking."

I carefully ignored the smoke; it curled suggestively, but approached no further. "Lady Dream, I do not mean this realm. The waking world will be ended, and with it all Oneiria!"

She leaned back upon her throne of silks and pillows, the smoke receding with her; and though no part of her face seemed to move, her half-lidded expression was no longer empty and blissful, but sharp as shattered ice. "Then destiny will be no more, nor illusion reign again."

And the Princess of Dream laughed. It was beautiful and melodious, and in thirteen years of service to My Lady of Nightmares I had never heard anything that chilled my blood so.

"Go!" she cried, as her court began to vanish in billows of dark pink smoke. "Return whence you came, Rider in the Dark, and tell my sister she will receive no aid from me: for the nightmare of Nightmares is the dream of Dreams."



Why is so much of my fiction in first-person?

Saturday, April 18, 2009

Flood

Sounds like the sort of thing I'd title a fiction piece (and probably will!), but today it's a statement of fact. My apartment complex is flooded — or the internal roads, are, anyway, easily enough to flood my poor Corolla. Several people who parked in less elevated areas than I did (and/or had low-riders: and who gets low-riders in a flood-prone area? Idiots, that's who) have had their cars flooded. I've been watching the water levels for a while, and it has gone down steadily ever since the rain mostly stopped at about ... what, 16:00? It vaguely drizzled for a while after that, but the clouds were already starting to pass by.

It's much like it was two years ago, or just after Hurricane Ike; people are coming out of their apartments and walking around. I've spoken to more of my complex-mates in the last five hours than I have in the five months preceding — yes, even during the snow day. (People were more interested in the snow than in each other, mostly. Or keeping an eye on the kids.)

Sorry; no pictures. It didn't really seem worth it this time, not like it did two years ago when it amazed me. Really, this is almost just a day in the life.

Friday, April 17, 2009

Entertainment

The local Fry's Electronics has far too many (soft) DDR pads in stock; it's kind of worrying, for no reason I can immediately put my finger on. However, they're about ten dollars each, so recently I decided to replace my existing, well-worn soft pad with two such of similar manufacture.

Furthermore, although a number of the Fry's employees I asked had no idea whether it was the case, it turns out that they do also sell Duck Tape, if you know where to look.

Thus, for the princely sum of roughly twenty-five dollars, I am now the proud owner of this affront to the eyes:


Surprisingly it performs rather well. While dancing there "feels" like there's an inch-high barrier between the two pads: there isn't, really, it's just a byproduct of the way they're taped together (there is a slight peak of less than 1cm where the black trims of the two pads meet, due to their natural upwards curvature), combined with my natural lack of grace and thus my propensity for letting my feet hit that peak.

I should note that I have considered getting a hard pad, or a even pair thereof; but it doesn't really seem like a worthwhile option — by the time I go through enough soft pads that a hard pad would have been worthwhile, the game consoles I dance with will have changed, and the connectors (or wireless protocols) built into the hard pad will no longer be usable!

Thursday, April 16, 2009

More bounding box blatherskeit

The previous definition of bounding box, or something mildly similar, could also arise from adding two additional elements to the domain of `⊴` — call them `⊴_bot` and `⊴_top` — which act respectively as a global infimum and supremum on `⊴`. These elements have a natural representation in `bbb F^n` (where `bbb F` is the set of IEEE floating-point numbers, of whatever precision is relevant) as, respectively, {-Inf, -Inf, ... -Inf} and {+Inf, +Inf, ... +Inf}.

This would imply the existence of semi-infinite bounding boxes extending either positivewards or negativewards on all axes, as well as the existence of the "world box" as the `sube`-supremum. However, the null box would still not be a bounding box under this definition; and the semi-infinite boxes don't have much use for, er, actually computing the bounding boxes of objects or sets. (The world box is at least a useful initial value for foldr `^^`!)

However, in vector spaces constructed as products of sets with with minimal and maximal elements — such as `[0, 2^{:2^{:n:}:}-1] nn NN` or the aforementioned `bbb F` — the local equivalent of `⊴` is already a bounded lattice, naturally yielding the `sube`-supremum as a bounding box in that space without defining it specially.

My initial definition — refined from the above `{⊴_bot, ⊴_top}`-conjoinment, which was itself refined into the definition in the previous entry — was closer to the actual final representation. Perhaps it would be more natural to study the behaviour of posets of pairs of points from lattices, like the representation itself, than to consider "boxes" to be actual delimited sets of points?

Wednesday, April 15, 2009

Bounding boxes

Select some fixed `n` and basis `\vec{e_i}, 1 lt i le n` of `RR^n`.

Define a relation `⊴` on points in `RR^n` such that `a ⊴ b` iff `forall i: (a.p_1 * \vec{e_i}) le (b.p_1 * \vec{e_i})`. Then (`RR^n`, `⊴`) is a poset, and in fact is also a lattice: the meet `a ^^ b` is merely the point `sum_{i=1}^n [ \vec{e_i} * max(a * \vec{e_i},b * \vec{e_i})]`, and the join is the same, with `min` substituting for `max`.

Let a bounding box be a set of points `B sube RR^n` such that a point `p in RR^n` is in `B` iff `vvv B ⊴ p ⊴ ^^^ B`. Intuitively (using the standard basis for `RR^n`), this is an axis-aligned closed box. A bounding box is uniquely defined by its `⊴`-infimum and `⊴`-supremum. (Note that these two points may be equal if `B` is the singleton set containing only that point; this is a perfectly legal bounding box.)

The relation `sube` defines a poset on the set `bbb B` of bounding-boxes, simply because it also defines one on the powerset of `RR^n`. We may use `sube` to extend `bbb B` into a join-semilattice: the join of two boxes `A` and `B` is the box defined by the `⊴`-infimum and `⊴`-supremum of `A uu B`.

The join is not always in `bbb B`, but we can extend `bbb B` to a complete lattice `bbb B^+` by adding two additional special bounding boxes not defined by their `⊴`-infimum and `⊴`-supremum: the nil box `bot = O/` and the world box `top = RR^n`. Then `(bbb B^+,sube)` is a proper lattice, in which the join is still defined as above (with global supremum `top`), and the meet is merely the intersection. Technically only `bot` is needed to make `bbb B^+` a lattice, but the inclusion of `top` makes it a bounded lattice, which is useful.



From a practical perspective, a bounding box may be conveniently represented as a pair of `n`-tuples of IEEE floats. Naively it might appear that we need an additional two bits — one to mark a degenerate case, and the other to distinguish between the two such — but with a small amount of cleverness in the representation, we can avoid both the additional two bits and the need for any special logic in the implementation of meet, join, or containment-of-point.

Specifically, we represent `top` as the pair of `n`-tuples `(-infty,-infty,...,-infty),(+infty,+infty,...,+infty)`, and `bot` as any pair `(a,b)` such that `a⋬b`, possibly with a canonical form `(+infty,+infty,...,+infty),(-infty,-infty,...,-infty)`. The large class of representations of `bot` makes equality testing slightly more difficult, but equality is a much rarer operation to perform on bounding boxes than meet, join, and containment. The natural implementations of binary meet on nondegenerate boxes (taking the min of each element of the left two tuples, and the max of each element of the right two), binary join (as meet, with max and min reversed), and containment-of-point (left[i] <= point[i] && point[i] <= right[i] for all i) naturally work with these as well.

Note that if we are working with integer boxes instead of floating-point, we cannot typically use `infty` as a value. However, most applications for integer bounding boxes involve an implicit universe of discourse (the size of the screen or what-have-you), and where this does not hold, -MAX_INT and MAX_INT will probably still do in practice.

Tuesday, April 14, 2009

In a body

The walls of the vein were long dry — wrinkled, shriveled, and petrified, resulting in a surface that would almost have been easier to climb, at least at an angle, than to walk.

Unfortunately, the dead god's bier was flatter than Kansas (and wouldn't that be an interesting simile to try to explain, I thought briefly), so we were stuck trudging through the "tunnel" on foot.

"At least it hasn't collapsed," I murmured, half unaware. Dovan flinched as I said it — he'd been ill at ease the entire way — and made a sign with his left hand that I'd come to recognize as a ward against ill fortune. I realized I'd said it aloud, and also flinched, though in my case out of embarrassment at my faux pas rather than any real fear. "Yeah," I said, and shook my head. "Any idea how much farther?"

"As far as it is," he snapped. "Why do you humans ask such useless questions?"

I blinked. "Well, I can't speak for anyone else, or even myself at any other time, but right now it's because if I'm making meaningless conversation it keeps me from thinking. Which means it keeps me specifically from thinking about how unutterably screwed we probably are, since, really, that's the only thing there is to think about until we get there."

Dovan didn't say anything to that for a long moment, as we passed another vein joining the inferior vena cava. "So," he said, with discernable forced cheer, "what's the weather like where you come from?"

I snrked. Possibly no dwarf had ever asked that question honestly. I tried to keep it interesting. "Hot and humid. I live near the coast, almost on flood plains. The soil's really porous, so you can't really build underground..."

Monday, April 13, 2009

Visual Studio

Problem: The Find in Files dialog in Visual Studio (2003, 2005, or 2008, at least) refuses to search the entire solution, claiming "No files were found to look in. Find stopped progress."

Solution: Press Ctrl + Scroll Lock while Visual Studio has focus. Find in Files will then work as expected.

Allow me to add my voice to the dozens of others across the Internet in saying: what the hell? The good news is, I did actually find one voice explaining things. Well, a couple, but they're easily synthesized. The bad news is, it really is as crazy as it sounds.

First, there is Raymond Chen's explanation that Ctrl + Scroll Lock and Ctrl + Break are the same thing as far as the keyboard — the physical electronic device at your fingertips — will ever admit. While perhaps unreasonable, certainly any unreason there is unlikely rightfully to be laid at the feet of Microsoft.

And in fact Ctrl + Break works as well as Ctrl + Scroll Lock. And seems inherently much more plausible, to boot: even without further explanation I could vaguely understand, and even see as plausible, the statement that a Ctrl + Break might jar something loose in Visual Studio's internals. It's normally code for "cancel build", and (disregarding the universal Undo-Cut-Copy-Paste collection) is easily the keychord I use most frequently in VS that doesn't deal with the clipboard; but it's applicable in a much wider range of scenarios than Visual Studio under its nom de guerre of VK_CANCEL.

Unfortunately that latter name is where the problem starts to kick in, and you can see the rest of the explanation here. Find in Files (quite sensibly) runs in a separate thread from the main UI thread, and if you press the 'Stop Find' button on its dialog, the main UI thread will pass a cancellation signal to FiF. However, the FiF thread also pretends to have some right to the UI, and calls GetAsyncKeyState(VK_CANCEL) directly to find out if the user is 'currently' (i.e., whenever the FiF thread happens to check, in between scanning file contents or waiting on crazy-high-latency over-the-network blocking operations) holding down VK_CANCEL.

Leaving aside the immediate implication that it's quite plausible that an irritated-verging-on-enraged user can jab Ctrl + Break several times without FiF noticing — and if you think this isn't normal user behavior, you've clearly not used any recent release of Visual Studio — there's apparently a known bug (see previous link) in GetAsyncKeyState that causes it to sometimes go spung! when accompanied by cross-application focus-shifts. (As if debugging WM_ACTIVATE handlers wasn't bad enough on its own.)

Sunday, April 12, 2009

Failure

At the end of the day, I found myself standing in the middle of the too-large office, with nothing around me to hide behind. Every instinct I had was shouting Danger! — to run and hide from predators — but I managed, surprisingly, to stand my ground.

It's not like running would have helped.

Uncle Peter, from behind his desk, looked at me over the rims of his glasses. "Well, Leroy," he said, "I'm really not sure what to say to you."

I didn't say anything. I wasn't really sure what to say either.

"I'm not sure it would matter if I say anything to you, anyway," he continued. "Either you already understand or you don't; and it doesn't change anything either way." His eyes went distant, and his ears tensed slightly. "Not a damned thing."

Uncle Peter had never cursed before, as far as I could remember. I flinched. I'm not sure if he noticed, though.

"I'm not going to ask you to clean out your desk, actually. There's likely to be less paperwork this way, if we just wait a few days." He was calm. Too calm. "With this many eggs lost... you do realize, boy, that you're not going to live through the week?"

I should have been surprised. Appalled. Afraid. Angry. Instead I was kind of relieved: at least I knew, now. The wide-open space didn't even bother me much anymore.

"Go home, Leroy," he said, finally. He looked old — years older than he should have. "Go home, and enjoy your damned Trix, whatever comfort they are to you." He angrily smashed a button with his entire left forepaw; there was a brief buzz. "Mopsy! Have someone escort Leroy to the door, if you would."

"Yes, Mr. Cottontail," came the voice over the intercom. I'd never heard Mopsy speak in person, I realized, and now I probably never would. Two rabbits came in — they must have been waiting — and almost politely nudged me out, and to the rear entrance, avoiding everyone along the way.

Saturday, April 11, 2009

Ow, ow, ow, ow, ow

I could plead illness, but instead / will write a post about my head.

Specifically, my brain has been wrapped in barbed wire that has itself been soaked in lemon juice and acetic acid. Meanwhile, my temples are throbbing along with the beat set by the mad pipers of the court of Azathoth, and the fixed joints of my skull are threatening to become unfixed as a result.

My eyes have been doused with nanite-bearing liquid which, having reached the interior of my eye-sockets, has collected into a plaque and unfolded into a trillion tiny caltrops, the tip of each of which has an embedded payload of perhaps a picogram of crystalline capsaicin. The visible surface of my eyes, on the other hand, has merely been scalded by unnaturally close proximity to red-hot pig iron.

The muscles at the back of my neck have clearly been operated on by a very competent but equally malicious acupuncturist, as they are both sore and too loose to properly stabilize the weight of the remainder of my head; the resulting instability itself results in augmentation and exacerbation of the other irritations and inflammations.

Strangely, my sinuses aren't bothering me at all.

Friday, April 10, 2009

Omegle

Omegle is a quick way to meet utterly banal people.

To save you the trouble, Omegle is a web chat where you click 'connect' and get randomly connected with some other person who has also just wandered by, and chat. No introduction, no details, no profile, no anything; you're both totally anonymous.

I think I can sum it up by saying that before today, I had managed to go five years without seeing the phrase a/s/l? uttered in earnest, and I am not at all happy to have had my streak broken twice in ten minutes.

Of twenty conversations, only one person ever punctuated and capitalized correctly, and they left off doing so after greeting me ("Hi! Woot! How are you?"). I'm more than willing to forgive the Swede with whom I had the longest conversation — not merely because English was not their native language, but also because it was 4:46 AM Stockholm time — but neither of those was true for most of the people I spoke with.

People are stupid, have you noticed?

(Via Randall Munroe.)

Thursday, April 9, 2009

Sufficiently advanced programming

[...] but unfortunately the event subsystems of the latter two are fundamentally incompatible.

... wait, aren't we using both of them now? How did you get it to work?

Me? Heavy wizardry, deep magic, and voodoo.

[laughs] Well, yeah, but specifically?

Well, the heavy wizardry is actually one of the canonical examples of heavy wizardry in the Jargon File: knowing how to interface to X11 without a toolkit. I have to a) manually track down the windows and/or pseudowindows for which each event is intended — which is not always the one named in the event, unfortunately — b) determine which toolkit or toolkits those windows belong to, and then c) get those toolkits to accept the event as though they had each retrieved it with their own event loops. So heavy wizardry in a) and c), deep magic in b) and c).

So where's the voodoo come in?

Oh, that's getting all three toolkits to run without their own event loops active. Which is easy enough for Xt — it's documented; they basically expect you to replace it — but the other two... yeah, notsomuch. So to take care of that, I have two minor loa in my stomach, one for each of them. They keep the program working, and I supply them with Mountain Dew.

...

What, you didn't think I could drink all that Dew myself, did you? Anyway, yeah, that's why SE2 was having problems on Saturday, and why they're not seeing those problems today, now that I'm in. Just let them know that they can't use the app on weekdays or holidays for now, and it'll be taken care of in the next version.

...

... Jim? Are you okay?

Wednesday, April 8, 2009

Black Magic Woman

There are some people who can write about the mundane and trivial, and make it new again: who can bring forth wonder and awe from the quotidian details of everyday life, and conjure an Oz out of Kansas.

And then, on the other hand, there are people who can write about the fantastic, and in so doing make it as dull and banal as a plastic knife from McDonald's.

Black Magic Woman is a novel by Justin Gustainis, first published in 2008. It is also very much a plastic knife from McDonald's.

The setting is a suspension-of-disbelief-breakingly near-real present-day United States of America, in which a) magic works, and witches both white and black (the distinction is presented as fundamental) can be found for hire, but nonetheless b) virtually nobody believes in magic, because they forget about it and/or rationalize it away. (Except only sometimes.) Magic in this setting sems to work in a vague way that I can either describe clinically as 'Post-Vietnam American New-Age Christian Pansyncretic', or more viciously as 'letting unexamined detritus build up in your faith hole'.

The main characters, on the other hand, have no character at all, but read like character sheets out of a World of Darkness game: Quincey Morris, a great-grandson of Quincey Morris (late of Stoker's Dracula), lightly colored caricature-Texan ('podner'?) with a fear of snakes, and Elizabeth 'Libby' Chastain, the most Christian-inoffensive bisexual Wiccan possible.

(The secondary main characters, Fenton and Van Dreenan, at least have personalities: but Fenton's the one who seems to accept the existence of magic on hearsay whereas poor Sidney Prendergast never again questions how she got off the roof of that building — never mind the poor forensic analysts who have to clean up after a bit of black magic. I suppose Fenton's shining blue PC aura protects him from sudden sense failure.)

The actual events of the book are vaguely interesting but fail to make up for the irritation induced by the people and world. 1/1, and good riddance.


Edit 2009-05-17: removed a now-confusing footnote left over from an early draft.

Tuesday, April 7, 2009

Win32 vs. MFC

I am, by trade, a C++ programmer. This becomes relevant.

The fundamental Windows API, somewhat inaccurately known as the Win32 API, is written in C, and from a very C-ish point of view. Many of the underlying functions and structures have gone through two fundamental architecture shifts — from 16- to 32-bit, then from 32- to 64-bit, and with a sidestep into the MIPS world along the way; between that and the slow accretion of features, its warts are in many cases are painfully visible.

Contrariwise, MFC ("Microsoft Foundation Classes," although no one ever uses that name) is written in C++, being essentially a C++ layer handling setup details and resource allocation and so forth. It provides wrapper classes for all the various structures and functions.

Despite all three of the above, I would much rather work with raw Win32 calls than deal with the many-faceted madness known as MFC. It actually has to break C++ in order to work: notably, out-of-memory failures are suddenly no longer signaled by std::bad_alloc exceptions but by the special MFC CMemoryException * (yes, I said *) because Microsoft decided a) to extend C++ to include exceptions (reasonable: Standard C++ now has them, in slightly different form) and b) to build MFC around and into their implementation of exceptions (significantly less reasonable).

Mind, when I really have my druthers I'll grab a reasonably sane C++ toolkit like wxWidgets. (GTK+, despite being C and Unix at heart, isn't bad either.) But ...

Monday, April 6, 2009

C++0x

So C++0x, that rough beast, slouches toward... well, nowhere in particular, still. At this point it does indeed look like the 0x on the end will be a hexadecimal prefix; there are simply too many issues to address before the October meeting in Santa Cruz.

I was amused to note that the Chinese and Canadian responses to the N2800 draft consisted of only two comments each, and in both cases one was simply an adjuration to the committee to 'consider' (CA) or 'address' (CH) the 187 open issues. (In the wake of the hundreds of other comments from the UK [344], the US [98], Japan [81], and others [less], the open issues now number 327, with a fair number of issues raised that have not yet been assigned defect numbers). I was further amused to note that, while China's other comment did concern a relevant, highly technical issue (and one which I'd run into myself, at that), it had nothing to do with C++0x; it's actually been around since C++98. (And I suspect it'll get pushed off to revision-after-0x, too.)

(N2800 has since been superseded by N2857, if you're interested, although it'd probably be easier to read the proposals named here and/or the papers submitted here, instead.)

Sunday, April 5, 2009

Review: Fleet of Worlds

Fleet of Worlds is a 2007 science-fiction novel by Larry Niven and Edward M. Lerner, set in Niven's Known Space universe.

I cede that it has been many years since I've read a novel by Niven himself; and those novels themselves were years or decades old at the time, so his writing style may well have changed significantly in the interim: but it does not feel like a Niven novel. I suspect that it would be more accurate to label it fanfiction, if professionally-published and author-approved. (And, given the cover credit, probably also at least author-edited.)

It is not, thankfully, bad fanfiction. It is not, I think, a very good novel, but it is at least not bad fanfiction.

Fleet of Worlds centers primarily around the Puppeteer known to humanity as Nessus, whom some may remember from the original Ringworld — though the events of Fleet predate those of Ringworld by some 200 years or more. It begins with the hitherto-undescribed — and, under further analysis, completely ludicrous — initial premise that the Puppeteers hold on their homeworlds a population of humans derived from the crew and cargo of a captured colony ship that happened upon their Kemplerer Rosette [sic`{::}^2`] and kept ignorant of Earth (despite the Puppeteers being anything but ignorant thereof).

I am still waiting for an explanation as to why a hyperparanoid species such as the Puppeteers — the arguably Puppeteer-insane Experimentalist political faction notwithstanding — didn't just vaporize the ship and have done.

Eh. It's diverting, but it wasn't worth getting in hardback, like I did a year and a half ago. Perhaps I should have been clued in by the SciFi logo? 1/1, and probably not worth your time.

Saturday, April 4, 2009

In the Canyon, which was the World,

“You know,” she said, smiling bouncing lightly on the balls of her feet, “this is the part where I'm supposed to tell you my motivations, isn't it?”

A butterfly flew out of the underbrush, coming to rest on a nearby flower. The sun, still visible above Kelei, sparkled on its wings.

“It's really very simple,” she went on. “This world is too small — not just for me, but for everyone, really. Kelei and Tanei have been killing us all, slowly choking us.”

I felt my face go white with shock, and in my mind's eye I saw her again, dancing on the rubble of the westernmost Gate. "You... you intend to bring down the Worldwalls?"

She laughed. It was a brilliant, musical laugh, with nothing in it that was not terrifying. “Bring them down? Oh, no, no, my dear Kahal. Nothing so vulgar as that.”

Briefly, there was movement: the butterfly fluttered up and away from the flower, and alighted on her headpiece. She turned, and strode lightly toward me; and I found I could not move, frozen in place by fear or enchantment or both.

She raised her arms up and out, almost as though about to embrace me; but instead she closed her hands into fists, each impossibly grasping one of the very horizons

— and the butterfly and I both trembled

— and she pulled.

Friday, April 3, 2009

Pong

Pong is a one- or two-player competitive game, produced by Atari and —

— no, you know what? The hell with that. It's Pong. It doesn't need an introduction. There aren't even any videos of Pong on the Atari 2600 on YouTube, and you know why? Because everyone already knows what it looks like.

(Here's one of the original arcade version, though.)

I actually first played Pong on the Atari video computer system, which is what they called the 2600 before they called it the 2600. I couldn't have been more than four — I have vague memories of playing it sometime before I moved to Texas. Yes, I played it with the paddles — pushing buttons or twiddling tiny thumbsticks just isn't the same; half the fun was putting your whole arm, if not your whole body, into twisting the controller. (I bet you could do a nifty Wii version, though.)

Also it still inspires people, although this is probably not saying much; nostalgia often does.

Tangentially, here is a video of Welshmen doing mildly inappropriate things with sheep and sheepdogs. (Also appropriate things with LEDs, because sheep are kind of hard to see in the dark.)

Thursday, April 2, 2009

Another dream

So apparently there was this parallel universe of sorts that essentially operated on dream-logic. (As in, in the dream, we knew that that world didn't really play by reliable rules. Kind of like Ursula Vernon's gearworld, except in overgrown-ruined-city flavor.)

Anyway, Craig (whoever that was; I've never even met a Craig) got ambushed and his dreamplane werewolf mirror-twin Craig' took his place on the way back. I can only assume Craig was a jerk, because even though we all realized this relatively quickly, none of us much cared. (Craig' didn't know much about any of us beyond our names, what classes Craig was taking, or when any of his projects or assignments were due. This improved slightly when he found — by which I mean one of us led him into finding — Craig's video-notes on his cell-phone.)

Of course, eventually Craig' stole my cell phone and started impersonating me with it — which I learned about on Google — at which point I decided to head back to the dreamplane to find Craig, first looking up his last known location in the dreamplane on Google.

So up pops an image from Image Search, from a stairway on the outside (formerly inside) of a building, looking out at the overgrowth-and-ruin. The viewpoint slips into the screen and suddenly I am Craig, wondering if I'll ever get back to the real world. I wander around, tracing a letter L in an otherwise illegible word — but I know it was supposed to be "Location," because I remember watching it being carved by a fellow dreamplane-visitor.

It's at around this time that I wake up.

Wednesday, April 1, 2009

Alas, yet another thing

Alas, yet another thing one can't do with cloth yet.

Take this. Then replace Pinky's thought-bubble with an LCD screen — say, smartphone-sized, or perhaps a bit less — and have it display random images from your iPod / smartphone / thumbdrive / neural interface / potato chip, set to shuffle.

... it's admittedly only slightly different from a tabletop picture-frame, but.

A number of shirts in that particular competition are strangely compelling: I direct the interested reader to Twilight Zone, Twilight Zone, Bionic Woman, Sailor Moon, Monk, Thunder Cats, and Future Rama, any of which should inspire. Of course they also have Ghost in the Shell and Time Warp (and more) if you're interested in diversion rather than inspiration.

shirt.woot.com is invariably interesting; it's a shame I don't wear T-shirts. I wonder if they'd be interested in doing a derby of designs specifically for button-down shirts? (I don't think they can at present, though: the manufacturing process and usual materials for button-downs and T-shirts are completely different.)