Erik McClure

In the wake of America deciding democracy was a bad idea, several of my friends have tried to halt my slide into misanthropy by trying to “reassure” me that people aren’t evil, they’re just really dumb and easily mislead!

This is not as reassuring as they think it is.

It doesn’t help that I was already something of a misanthrope. What kept me optimistic was transhumanism, the belief that, even if the average human is too dumb to ever sustain an interstellar empire, we are rapidly approaching the point at which we can augment our own intelligence and move beyond the constraints of our biology. Perhaps then, the way forward was through augmentation, either mechanical, biological, or simply uploading ourselves to computers somehow. This possible future, however, is now at risk, it’s very existence looking very unlikely.

In 10-20 years, we will likely see one of three things happen: radical biological modification from bioengineering DNA, the rise of androids thanks to the minificiation of ECMO systems, or partial mind uploading made possibly by brain-computer interfaces.

However, this election has made two things painfully clear: a majority of people are very dumb, and a majority of people hate what they don’t understand. This means they are definitely going to hate anything coming out of the transhumanist movement. Any attempt I make to augment myself will be met with fear, hostility, and guns. It doesn’t matter if they’re just “scared and confused”, they’ll still shoot me all the same. And, y’know, the threat of being shot is very good at dissuading people from doing things.

People do not seem to understand just how bad things are going to get. You can say “how bad can 4 years be?” and be somewhat right: I think Trump is too senile to actually dismantle American democracy. That’s not the problem. The problem is that this entire election has solidified conservative power in a big way. Do you really think they’ll stop at concentration camps for “illegal” immigrants? I can see today’s waves crash into tomorrow’s shores, and it’s not pretty.

Holy shit everyone in the office is like, Pro trump rn. Even tho its awful for canada. They literally told me climate change isnt real

Part of Project 2025 says they are going to dismantle all attempts at addressing climate change. This means you’d better familiarize yourself with what things will look like in 2050 without any reduction in emissions, because that’s what is going to happen. Don’t buy a house unless it will survive a 70 meter rise in sea levels.

The cruel irony is that this will fuel an explosion in VR entertainment in the next 5-10 years that will cause hundreds of millions of people to realize they aren’t as normal as they thought they were, only to be thrown into a world of their own making that hates them for it. The sheer amount of suffering that we have created in this moment is mind-boggling. 4 years of Trump is nothing compared to the decades of civil rights unrest that we are about to plow into. Did you really think they were going to stop at attacking trans people? They’ve already been gearing up to go against furries. The bigotry will never stop, because there will be a never ending supply of people they hate - anyone who is different from them, anyone with the wrong “vibes”, anyone who isn’t an heterosexual cisgendered extrovert is going to be ground into dust or thrown into a camp.

The astounding success of fearmongering conservative politics means the dystopian world of Dues Ex is somehow optimistic, one where augmentation was possible at all. Given the current political climate, it seems unlikely that widespread augmentation will ever be tolerated. The rich will find ways to get augmented, and then simply fearmonger all the poor people into ensuring none of the other poor people get augmented, which is exactly what the cartoon villains in Dues Ex wanted. Drone warfare will become commonplace. Civilians will become targets. Scientific progress will be heavily bottlenecked, as rampant elitism makes herding behavior much worse.

I no longer see any viable way out of this for humanity as a whole. Perhaps if we splinter into factions, one of us might get lucky and colonize the moon, or something, from inside the comfort of a glass dome. But right now, we are in a crab bucket, and this election has proven beyond a shadow of a doubt that humans will do anything they can to drag everyone else down to their level. The only escape now is to hide from the other crabs, so that one small group might be able to continue making progress.

Either way, this will probably be my last blog post, unless something changes. I may be forced to delete the blog entirely, given how everything on this website will inevitably be weaponized against me. Besides, I no longer have any desire to talk to other people. I’d rather buy a gun.

One of the most fundamental problems with Rust is the design of Result. It is a lightweight, standardized error return value, similar to C-style error codes but implemented at a type system level that can contain arbitrary information. They are easy to use and very useful, and the ecosystem encourages you to use them over panic! whenever possible. Unfortunately, this ends up creating a problem. Result is not like a C++ exception because it doesn’t contain a stacktrace by default, nor does the compiler have any idea where it was first constructed, unless the error type it contains decides to include that information upon construction by using backtrace.

You can catch an unwinding panic!, which is implemented much more like a C++ exception, but a panic! that aborts cannot be caught and it’s impossible to tell if a panic will unwind at compile-time because the behavior can be changed at runtime. Another interesting difference is that the panic handler is invoked before the panic starts unwinding the stack. These implementation details push you towards using the panic handlers purely as uncaught exception handlers, when you can do nothing but perhaps save critical information and dump a stacktrace before exiting. As a result, panic! is designed for and used almost exclusively for unrecoverable errors.

If you want an error that is recoverable, you use Result… which doesn’t have a backtrace, unless you and all your dependencies are using some variant of anyhow (or it’s various forks), which allows you to add backtrace information. If the error is coming from a dependency that doesn’t use anyhow, you’re screwed. There actually is an RFC to fix this, but it’s been open for six years and shows no signs of being merged anytime soon.

“But”, I hear you ask, “what does this have to do with Rust Async?” Well, like most things, Rust Async makes this annoying part of Rust twice as annoying because the default behavior is to silently eat the error and drop the future, unless you have stored the join handle somewhere, and you are in a position where you can access that join handle to find out what the actual error was. The API for making tokio panic when an unhandled panic happens is still unstable, with the interesting comment of “dropping errors silently is definitely the correct default behavior”. Really? In debug mode? In release mode, fine, that’s reasonable, but if I’ve compiled my program in debug mode I’m pretty sure I want to know if random errors are being thrown. Even with this API change, you’ll have to manually opt-in to it, they won’t helpfully default to this behavior when you compile in debug mode.

Until that feature gets stabilized, you basically have to throw all your JoinHandle’s into a JoinSet blender so you can tell when something errored out, and unless you are extremely sure you didn’t accidentally drop any JoinHandle’s on the floor (because Rust does not warn you if you do this), you probably need a timeout function even after your main future has returned, in case there are zombie tasks that are still deadlocked.

Oh, have I mentioned deadlocks? Because that’s what Rust async gives you instead of errors. Did you forget to await something? Deadlock. Did you await things in the wrong order? Deadlock. Did you forget to store the join handle and an error happened? Deadlock. Did you call a syncronous function that invokes the async runtime 5 layers deep in the callstack because it doesn’t know it’s already inside an async call and you forgot it tried to do that? Deadlock. Did you implement a poll() function incorrectly? Deadlock.

For simple deadlocks, something like tokio-console might be able to tell you something useful (“might” is doing a lot of work here). However, any time you forget to await something, or don’t call join on the localset, or add things to the wrong localset, or your poll function isn’t returning the right value, or the async waker was called incorrectly, you’re just screwed, because there is no list of “pending futures that have not been awaited yet” that you can look through, unless you get saved by your IDE noticing you didn’t await the future, which it often doesn’t. It definitely doesn’t tell you about accidentally dropping a JoinHandle, which is one of the most common issues.

But why would you have to implement a poll function? That’s reserved for advanced users– Nope, nope, actually you have to do that when implementing literally any AsyncRead/AsyncWrite trait. Oh, sorry, there’s actually 4 different possible AsyncRead/AsyncWrite implementations and they’re all slightly different and completely incompatible with each other, but they’re all equally easy to fuck up. Everything in Rust Async is absurdly easy to fuck up, and your reward is always the same: [your-program].exe has been running for over 60 seconds.

I haven’t even mentioned how the tokio and futures runtimes are almost the same but have subtle differences between them, and tokio relies on aspects of futures that have been factored out into future-util, which should be in the standard library but isn’t because the literal only thing they actually standardized on was std::future itself. All this is ignoring the usual complaints about async function color-coding - I’m complaining about obnoxious implementation footguns on top of all the usual annoyances involved with poll-based async. Trying to use async is like trying to use a hammer made out of hundreds of tiny footguns hot-glued together.

I wish async was just one cursed corner of Rust that had its warts relatively self-contained, but that isn’t the case. Rust async is a microcosm of an endless stream of basic usability problems that the language simply doesn’t fix, and might not ever fix. I’m honestly not sure how they’re going to fix the split-borrow problem because the type system isn’t powerful enough to encode where a particular borrow came from, which is required to implement spatially disjoint borrows, which ends up creating an endless cascade of subtle complications.

For example, there are quite a few cases where serde_json errors are not very helpful. None of these situations would matter if you could open a debugger and go straight to what was throwing the error, but you can’t because this is Rust and serde_json doesn’t implement anyhow so you can’t inject any errors. format_serde_error was created to solve this exact problem, but it is no longer maintained and is buggy. Also, artifact dependencies still aren’t stabilized, despite the very obvious use-case of needing to test inter-process communication that comes up in basically any process management framework? So this crazy hack exists instead.

Rust’s ecosystem heavily relies on two undebuggable-by-default constructions: macros and async, which makes actually learning how to debug production Rust code about as fun as pulling your own teeth out. I have legitimately had an easier time hunting down memory corruption errors in C++ then trying to figure out where a particular error is being thrown when it is hidden inside a macro inside an error with no stacktrace information, because C++ has mature tooling for hunting down various kinds of memory errors.

Because of last year’s shenanigans, I am no longer confident that any of these problems will be fixed anymore. Rust’s development has slowed to a crawl, and it seems like it’ll take years to stabilize features like variadic generics, which are currently still in the design phase despite all the problems the ecosystem runs into without them. It is extremely frustrating to see comments saying “oh the ecosystem is just immature” when those comments are 5 years old. On the other hand, I am tired of clueless C or C++ fans trying to throw bricks at Rust over these kinds of problems when C++ has far worse sins. Because of this, I will continue building all future projects in Rust, at least until the dependently typed language I’m working on has a real compiler instead of a half-broken interpreter.

Because hey, at least it isn’t C.

Recently, Rust people have been getting frustrated with C developers who seem to base their entire personal identity on being able to do unsafe memory things. The thing is, this is not a phenomenon unique to C developers, or even software developers in general, although the visibility of the kernel C developers is higher than the average programmer. Most people will be upset about technology that makes their particular skillset irrelevent. This is best summarized by a famous quote:

"It is difficult to get a man to understand something, when his salary depends upon his not understanding it" — Upton Sinclair

Professional C developers who dislike Rust’s borrow checker are almost always extremely good at doing manual memory management while making very few detectable errors (I say detectable because they usually miss some edge-case that turns into a security nightmare 10 years later). They are either paid lots of money to do this specific task, or they have almost no experience doing anything else. They are one-trick ponies, and they are terrified of their one skill being made irrelevent, at which point they will either no longer make lots of money, or not have a job at all.

You could argue that they could simply learn Rust, but you must understand that they believe they are singularly talented at C, which in some cases may actually be true. If they start learning Rust now, they might end up just being an average Rust developer, and the thought of being average is absolutely terrifying to them. This is because it’s percieved to be a loss of social status, which human brains are hardwired to avoid at all costs. It sounds like they’re about to be “deported” because that is the exact psychological response that potentially losing social status provokes.

It’s not just languages, either. When programmers ask “why is this ecosystem such a disaster”, half the time it’s because somebody is getting paid to deal with it. Our industry is trapped in an endless loop of a startup building a new technology on top of some half-broken ecosystem, exploding in popularity, and then everyone using the startup’s technology hires people to deal with the ecosystem it’s built on top of, and those people don’t actually want anyone to fix it or they’ll be out of a job. There is no escaping the fact that, if someone was getting paid to deal with something that was broken, and you fix it, you just made them irrelevent.

In 30 years, when Rust is slowly being replaced by something better, Rust developers will behave the exact same way. Someone will invent a borrow checker that is much more powerful and capable of solving most of the annoying borrow situations that baffle the current Rust borrow checker. Their response will be that this language is for “lazy” programmers, who don’t want to be as precise as a Real Rust Programmer. They’ll complain about things that don’t make any sense because they’ve never actually used the language they’re complaining about. The Rust programmers will sound just as dumb as C programmers do today.

I know this will happen because this already happens in literally every other field in existence. Musicians still sometimes claim that if you can’t play an actual instrument you aren’t a “real” musician, whatever that is. There was a big fight when Photoshop came out because artists complained that “ctrl-Z” was cheating and if you can’t paint on a real canvas you aren’t a Real Artist. It’s everywhere, and it’s universal.

This is not a programmer problem, it’s a people problem. When you look at this through the lens of livelihoods being threatened, you can instantly see that this is all the exact same instinctual human reaction: they have a high status because they are incredibly skilled at a particular thing, and New Thing is threatening to make that skill either irrelevent, or less important, and they don’t want to lose status.

The best defense against this behavior seems to be skill generalization and good self-esteem. If you are confident in your abilities as a musician, you don’t need to worry about people who are good at using a sequencer, instead you might try to team up with them. If you are confident in your general problem solving abilities as a programmer, then the language barely matters, what matters is which language is best suited for the problem at hand.

Software engineering in particular seems to suffer from hyper-specialization, with people having jobs working with extremely specific frameworks, like React, or Kubernetes, or whatever the newest Javascript framework is. It might be that the complexity of our problems are outstripping our tool’s abstractions, but regardless of what the cause is, if we don’t get things under control soon, this will just keep getting worse.

Sturgeon’s law states that 90% of everything is crap. Combined with Hanlon’s Razor, we arrive at the inescapable conclusion that most problems are caused by incompetence. What’s particularly interesting is that the number of incompetent people in a system tends to increase the higher up you go. Part of this is due to the Peter Principle, where organizations promote employees until they become incompetent, but this happens in the first place because it becomes harder to measure competence’ the longer it takes the effects of actions to be felt, and as a species we have no way of measuring long-term incompetence. Instead, we rely on social cues, and tend to use whatever our local culture determines is “competent”.

One way to try to address this is to teach better critical thinking, but this almost always runs into fierce objections from parents who don’t want schools to “undermine parental authority”, which is what happened with the 2012 Republican Party of Texas platform (original). This kind of thinking is actually fairly common, and it is not a fluke of human nature - it is a feature.

To understand why humans can be inquisitive and intelligent on an individual level, but follow arbitrary and sometimes counterproductive rituals on a cultural level, you must understand that our ancestors lived in epistemic hell. My favorite example is the tribe that had a very long and complicated ritual for preparing manioc, which contained dangerous amounts of cyanide:

In the Americas, where manioc was first domesticated, societies who have relied on bitter varieties for thousands of years show no evidence of chronic cyanide poisoning. In the Colombian Amazon, for example, indigenous Tukanoans use a multistep, multiday processing technique that involves scraping, grating, and finally washing the roots in order to separate the fiber, starch, and liquid. Once separated, the liquid is boiled into a beverage, but the fiber and starch must then sit for two more days, when they can then be baked and eaten.

[..] even if the processing was ineffective, such that cases of goiter (swollen necks) or neurological problems were common, it would still be hard to recognize the link between these chronic health issues and eating manioc. Low cyanogenic varieties are typically boiled, but boiling alone is insufficient to prevent the chronic conditions for bitter varieties. Boiling does, however, remove or reduce the bitter taste and prevent the acute symptoms.

So, if one did the common-sense thing and just boiled the high-cyanogenic manioc, everything would seem fine. [..] Consider what might result if a self-reliant Tukanoan mother decided to drop any seemingly unnecessary steps from the processing of her bitter manioc. She might critically examine the procedure handed down to her from earlier generations and conclude that the goal of the procedure is to remove the bitter taste. She might then experiment with alternative procedures by dropping some of the more labor-intensive or time-consuming steps. She’d find that with a shorter and much less labor-intensive process, she could remove the bitter taste. Adopting this easier protocol, she would have more time for other activities, like caring for her children. Of course, years or decades later her family would begin to develop the symptoms of chronic cyanide poisoning.

Thus, the unwillingness of this mother to take on faith the practices handed down to her from earlier generations would result in sickness and early death for members of her family. Individual learning does not pay here, and intuitions are misleading. — "The Secret Of Our Success" by Joseph Henrich

Without modern tools, there is no possible way (other than acquiring brain damage from chronic cyanide poisoning), for an ancient human to realize that every step of the ritual is actually necessary, because without extensive experimentation over many human lifetimes, it isn’t obvious what danger the ritual is guarding against, and if it’s working as intended, no one will have seen the danger or be able to know about it in the first place! It seems that evolution always kept around enough sacrificial intelligent humans to tinker with new possible rituals, but always ensured that the majority of the population would obey the safe, known ways of doing things, without questioning them, because trying to rationally evaluate an opaque ritual meant death. Not even the culture itself knew what disaster or point of failure the ritual was actually preventing, only that it kept them alive. Religion is simply a convenient way of packaging rituals; if you look in the rules set out by many ancient religions, a lot of them start looking like “how to run a functioning society” and include things like “keep your toilet clean”. They got popular because they worked, we just had no idea why and in many cases couldn’t have possibly figured out why with the technology at the time. Even worse, if you got it wrong, it could take you decades until you finally manifested an affliction that actually started causing problems.

This is the core evolutionary drive behind religion and conservative mindsets, where obeying authority is paramount to survival. In modern times, we could communicate to our children why doing a particular thing is bad, because we know the entire chain of cause and effect. Just a few hundred years ago, we couldn’t even do that! A famous example is the effort to get iodine added to salt. Doctors didn’t resist the idea of adding iodine to salt for no reason, they resisted it because at every dosage amount that seemed like it could have an effect, it made people sick! They had experiments on fish that showed that iodine seemed to make goiters go away, but giving people iodine supplements would always make them sick. At this point in time, nobody had any evidence whatsoever that micronutrients existed. Giving people just 150 micrograms of iodine a day, accomplished by evenly mixing tiny grains of potassium iodide into a kilogram of salt, seemed like homeopathic medicine. There was no known substance that had any effect at that little concentration. Only by taking a leap of faith could Otto Bayard theorize that perhaps we needed just a tiny amount of iodine, going against all known nutritional science at the time.

Humans likely evolved culture as an alternative to animal’s reliance on old pack members to know what to do in case an extremely rare but devastating event happened every hundred-ish years. Rituals could seem completely nonsensical inside a single human lifespan, because they addressed problems at a societal level that only happened every 200 years, or slow acting chronic issues. In one case, ancient elephant matriarchs were the only ones capable of remembering waterholes far enough from a drought that only happened once every 35 years. The packs that lost their matriarchs all died because they had lost this knowledge.

We evolved logic to solve problems that had clear first-order effects, but we aren’t very good at evaluating second-order effects. Long lived humans were capable of finding cause and effect links that happened over a human lifespan, but only human culture perpetuating strange and bizarre rituals created out of random experimentation could deal with problems that had very long, unknowable cause and effect chains. It is very hard to tell if the person building your house is competent if the house only collapses every 150 years when a massive earthquake hits. Various cultures have developed all sorts of indirect methods of measuring competence, but many of them emphasize students obeying their teachers, because the teachers are often perpetuating rituals that are critically important without actually understanding why the rituals are important or what they guard against. It is culture guarding against Chesterton’s fence over enormous timespans. Another good example of epistemic hell is how we cured scurvy by accident and then ruined the cure:

Originally, the Royal Navy was given lemon juice, which works well because it contains a lot of vitamin C. But at some point between 1799 and 1870, someone switched out lemons for limes, which contain a lot less vitamin C. Worse, the lime juice was pumped through copper tubing as part of its processing, which destroyed the little vitamin C that it had to begin with.

This ended up being fine, because ships were so much faster at this point that no one had time to develop scurvy. So everything was all right until 1875, when a British arctic expedition set out on an attempt to reach the North Pole. They had plenty of lime juice and thought they were prepared — but they all got scurvy. The same thing happened a few more times on other polar voyages, and this was enough to convince everyone that citrus juice doesn’t cure scurvy.

Our ancestors weren’t stupid. They were trying to find some kind of logical progression of cause-and-effect, but they lived in epistemic hell. This is why cargo-cult programming exists. This is why urban legends persist. This is why parents simply want their children to do as they say. This is why we have youtubers chastising NASA for not reading their own Apollo 11 postmortem. This is why corporate procedures emphasize checking boxes instead of critically examining the problem. When your cause-and-effect chain is a hundred steps long and caused by something 5 years ago, economic pressure incentivizes simply trying to avoid blame instead of trying to find the actual systemic problem. The farther up the chain of management a problem is, the longer it takes for the effects to be felt, and the worse we get at finding the root cause. Software engineering has the same issue, where incompetence may only cause performance issues years later, after the original coder has left, and the system has scaled up beyond a critical breaking point. This is why we still don’t know how to hire programmers.

Only in the modern era do we have the necessary technological progress and the historical records to be able to accurately evaluate the usefulness of our rituals. Only now can we watch chemical reactions happen at an atomic level. Only now can we have Just Culture and blameless post-mortems that allows identifying actual systemic failures. Only now can I watch a YouTube video explaining how to go from a quantum simulation of particle collisions to a dynamical fluid simulation. Only now can I watch a slow-motion capture at 200000 frames per second to see exactly how a tiny filament explodes into hot globules that then fly into a nest of zirconium filings and set it aflame exactly where each one lands.

The engineers who invented these flashbulbs couldn’t see any of this. They had to infer it from experimentation, whereas I can just watch it happen and immediately understand exactly what is going on. We live in a pivotal moment of human history, on the cusp of being able to truly understand the entire chain of cause-and-effect for why things happen. We have the ability to measure events with unprecedented accuracy, to tease out tiny differences that catalyze huge reactions.

Unfortunately, the ability to merely see cause-and-effect is not sufficient when large systems tend to be chaotic. We do not yet have good mathematical frameworks for predicting emergent behavior, and our ability to analyze complex chaotic systems is still in its infancy. We know that large groups of humans consistently display emergent behavior, such as crowd dynamics closely following the equations of fluid dynamics. Likewise, large human organizations are themselves largely emergent behavior, and we never really understood how they were working in the first place. Organizational competence, and coordination problems in general are our modern epistemic hell, and it means there is no easy way for us to address the failure of our institutions, because we still have no holistic way to analyze the effectiveness of a given organization.

We are tantalizingly close to grasping the true nature of reality, to having the machinations of the universe laid out before us, but we are still missing the tools to fully analyze subtle patterns, to lift a whispered signal out of the thundering noise of spacetime. There is simply no escape from emergent behaviors evolving out of chaotic systems. Until we have the means to analyze these kinds of complex systems, we will forever be at odds with our nature, still tempted to cling on to superstitions of old, because long ago, that was the only thing that kept us alive.

I remember growing up with that same old adage of how you could be the next scientist to invent a cure for cancer, or a solution to climate change, or whatever. What they don’t tell you is that we already have solutions for a lot of problems, we just don’t use them. Sometimes this is because the solution is too expensive, but usually it’s because competing interests create a tragedy of the commons. Most problems in the modern age aren’t complicated engineering problems, they’re the same problem: coordination failure.

It was recently unveiled that basically every single UEFI SecureBoot implementation ever made can be bypassed with a malicious image file. This means that any manufacturer that allows the user to customize the boot image is now vulnerable to a complete bypass of SecureBoot and Intel Boot Guard. Luckily, the fix for this is pretty simple: don’t make the logo customizable. But how did something this absurd happen in the first place?

The results from our fuzzing and subsequent bug triaging unequivocally say that none of these image parsers were ever tested by IBVs or OEMs. We can confidently say this because we found crashes in almost every parser we tested. Moreover, the fuzzer was able to find the first crashes after running just for a few seconds and, even worse, certain parsers were crashing on valid images found on the Internet. — binarly.io

It’s pretty obvious what happened, actually. The image parsers were written with the assumption they’d only ever need to load an image file provided by the manufacturer. When this assumption was violated, all hell broke loose, because we don’t test software anymore. None of this happened because engineering is hard. None of this happened because of some tricky, subtle bug. It happened because the people writing the image parsers made an incredibly stupid mistake and then didn’t bother testing it, because the software industry doesn’t bother with QA anymore. Thus, there was no swiss cheese. There was just one slice of cheese with a gaping hole in it, because it turns out that some manufacturers decided to let users customize their boot image, thinking it would be harmless, and that by itself was enough to wreak havoc.

Every layer of this problem is a different flavor of coordination failure. No one on the team who implemented this either thought that there might need to be a warning about untrusted images, or whoever did bring it up was ignored because it was supposed to be handled by another team. Except whoever was supposed to put in a warning about this either wasn’t told, or buried it inside a technical document nobody ever reads. The vendors who decided to implement user-customizable boot logos didn’t ask whether this would be a problem, or weren’t told about it.

And nobody, not a single layer in this clown train, implemented a proper QA or pentesting process that could have caught this bug, because we just don’t bother testing anything anymore. Our economic incentives have somehow managed to incentivize building the worst possible piece of shit that still technically works. We know how to avoid this situation. We have decades of experience building in-depth QA processes that we are simply ignoring. We could fix this, we just don’t.

This is not exclusive to software, as this fantastic video about the popcorn button explains. Our economic race to the bottom has been sabotaging almost every aspect of engineering in our society. To save a few cents per microwave, the cheap microwaves don’t include a humidity sensor and then lie about having a popcorn button when it can’t actually work properly, which leads to everyone saying “don’t use the popcorn button” and now nobody uses the popcorn buttons even on microwaves that actually have a humidity sensor and a working popcorn button. The cheapskates control the supply chain now. They have pissed in the proverbial pool, and if this sounds familiar, that’s because it’s a classic example of the Tragedy of the Commons.

Except, that’s not an excuse. What’s truly absurd is that the tragedy of the commons isn’t inevitable. We know this because ancient human tribes managed to navigate responsible utilization of common resources all the time. It has no historical basis whatsoever. The tragedy of the commons only happens when you have a total failure of collective action. It is the original symptom of societal enshittification.

[...] many nomadic pastoralist societies of Africa and the Middle East in fact "balanced local stocking ratios against seasonal rangeland conditions in ways that were ecologically sound", reflecting a desire for lower risk rather than higher profit...

We actually have a cure for blood cancer now, by the way. Like, we’ve done it. It’s likely that a similar form of immunotherapy will generalize to most forms of cancer. Unfortunately, the only approved gene therapy we have is for sickle-cell disease and costs $2 million per patient, so most people in America simply assume they will never be able to afford any of these treatments, even if they were dying of cancer, because insurance will never cover it. This is actually really bad, because if nobody can afford the treatment, then biotech companies won’t bother investing into it, because it’s not profitable! We have built a society that can’t properly incentivize CURING CANCER. This is despite the fact that socialized healthcare is a proven effective strategy (as long as the government doesn’t sabotage it). We could fix this, we just don’t.

Some people try to complain that this happens because democracy is hard, or whatever, and they’re also wrong. We know exactly what’s wrong with our current voting systems and CGP Grey even put out a video on it 13 fucking years ago. It inevitably results in a two-party system, because strategic voting is rational behavior, and you can’t break out of this two-party system because of the spoiler effect, and the solution is Ranked Choice Voting (or the Alternative Vote). If you want to go further and address gerrymandering you can use the Single Transferable Vote. All of these better systems were proposed decades ago. We have implemented exactly none of them for the presidential election (except for Maine and Alaska). In fact, America still uses the electoral vote system, which is strictly worse than the popular vote, we all know it’s worse, and we even have a potential solution but we still can’t get rid of it due to counterproductive societal interests.

We HAVE solutions for these problems. We just don’t use them. We could be running fiber-optic cable to every house in America, and we even know how much it would cost. We just don’t because we gave the money to corporations who then used none of it and instead paid themselves huge bonuses. We know that automation is chipping away at low-skill jobs, which means our workforce needs to be better educated, and that providing free college to everyone would be a good idea, we just don’t. We know how to build interstate high-speed commuter rail, we just don’t (although Biden is trying). We could fix everything, we just don’t.

We have no excuses anymore. None of these are novel or difficult problems, not even the tragedy of the commons. We can do better. We don’t need AI to fix things. We don’t need new technology to solve these problems. We already know how to do better, we’ve just dug ourselves into a cooperation slump that’s so bad we can’t even implement solutions we already know about, let alone invent new ones. We’re in this hole simply because society is run by people who are incentivized to sabotage cooperation in the name of profits. That’s it.

It’s January 1st of the new year, and with all these people wishing each other a “better year”, I am here to remind you that it will only get worse unless we do something. Society getting worse is not something you are hallucinating. It cannot be fixed by you biking to work, or winning the lottery. We are running on the fumes of our wild technological progress of the past 100 years, and our inability to build social systems that can cooperate will destroy civilization as we know it, unless we do something about it.

We live in what is perhaps the most critical turning point in all of human history, and we’re on a ship that has drifted far off course. The rapid current of technology means that we are swept along faster and faster, making it exponentially harder to steer away from the icebergs ahead of us. We must address our coordination failures. We must build systems that foster better cooperation, or this century won’t be a turning point for humanity, it will be the end of humanity.

"All that would remain of us would be a thin layer in some future rock face. This is the future we must avoid at all costs." — John D. Boswell (melodysheep)
Sorry, I need my computer to work

I originally posted an even more snarky response to this, but later deleted it when I realized they were just a teenager. Kids do not have decades of experience with buggy drivers, infuriating edge-cases, and broken promises necessary to understand and contribute to the underlying debate here (nor do they have the social context to know that Xe and I were just joking with each other). Of course, they also don’t know that it’s generally considered poor taste to interject like this, as it tends to annoy everyone and almost always fails to take into consideration the greater context in which someone might be using Windows, or Mac, or TikTok, or Twitter, or whatever corporate hellscape they are trapped in. The thing is, there’s always a reason. You might not like the reason, but there is usually a reason someone has locked themselves inside the Apple ecosystem, or subjected themselves to Twitter, or tried to eke a living from beneath the lovecraftian whims of YouTube’s recommendation algorithm.

People can only care about so much.

They can’t care about everything. You might think something is important, and it probably is, but… so is everything else. Everything matters to someone, and everything is important to society in general to some degree. Some people think that YouTube isn’t very important, but they’re objectively wrong, as YouTube creators reach billions of people. They change people’s lives on a daily basis. We could argue about how important art and music and creativity is to society, yet observe that our capitalist hellhole treats creatives as little more than wage slaves, but then we’d be here all day.

As this blog post bemoaning the loss of Bandcamp explains, They Can And Will Ruin Everything You Love. The only thing that is important to the money vultures is… money. The only people who can build another Bandcamp are people who believe it’s important. I particularly care about the Bandcamp debacle because one of my hobbies is writing music, and I prefer selling it on Bandcamp. If Bandcamp dies, I will no longer have anywhere to offer downloadable lossless versions of my songs. Everything has devolved into shitty streaming services, and there’s nothing I can do about it. I’m too busy fixing everything else that’s broken, there’s no time for me to build a Bandcamp alternative and I’m terrible at web development anyway. Don’t get me started on whether the new solution should be FOSS, because some people believe FOSS is important, and they’d be right! Just look at Cory Doctorow’s talk about enshittification and how proprietary platforms are squeezing the life out of us.

Everything is important!!!

…But I can’t care about everything. You can’t care about everything either, you have to pick your battles. No, that’s too many battles, put some back. That’s still too many battles. You only have 16 waking hours every day to do anything. You have to pick something, and everything you care about has a cost. When everything is important, nothing happens. No websites are created. No projects are built. No progress is made. We simply sit around, bikeshedding over whose pet issue is the most important. There are always trade-offs, and sometimes you can make the wrong ones:

As the corresponding blog post later elaborates on, when you are 19 / still a student / unemployed, time is all you have to spend. It can be easy to forget how valuable time is to some people. Even if I won’t touch Apple devices with a 10-foot-pole, I can understand why people use them. If all your use cases fall inside Apple’s supported list of behaviors, it can be great to have devices that just work (assuming you can afford them, of course). On the other hand, while I prefer Windows, I know many people who use Linux because Windows either won’t let them do what they want, or literally just doesn’t even work. They are willing to put in the time and effort to make their linux machines work just the way they want, and to maintain them, and occasionally do batshit insane source-code patches that I hopefully will never have to do in my life, because it’s important to them.

Back when I was still writing fiction, I got a great comment from an editor who said something along the lines of “writing should be fun, you should only pursue perfection as far as you enjoy.” You can spend your entire life chasing perfection, but you’ll never reach it, and at some point you have to ship something. I’ve been trying to finish up some songs for an album recently and I’ve had to rely on formulaic crutches more than I want to, because at the end of the day, it’s just a hobby, and I simply don’t have the time to be as experimental as I want. My choice is to either release an okay song, or none at all. You can tell where I was hopelessly chasing an unattainable goal for over two years when my output completely stops:

Song Output

Everyone has to make trade-offs, and it can take time to figure out which ones are right for you. Not everyone can contribute to your particular social cause. When you ask someone to care about something, you are implicitly asking them to stop caring about something else, because they have a finite amount of time. They can’t do everything. In order to help you, they must give up something else. Is it grocery shopping? Time to cook? Time to sleep? A social gathering? Playtime with their children?

By no means should you stop asking people to care about something, that part is kind of important. Raising awareness allows individuals to make informed decisions about what trade-offs they are making with their time. However, if someone says they aren’t interested in something you care about… it’s because they have different priorities, and the trade-offs didn’t make sense. Maybe they care more about adding a feature to a 50 year old programming language, and thank goodness they did, because would you have cared enough to put up with this nonsense?

Your time is precious. Other people’s time, doubly so. Mind it well.

Discord’s Recent Announcement made a lot of people mad, mostly because of Hyrum’s Law - users were relying on unintended observable behavior in the original username system, and are mad that their use-cases are being broken despite very good evidence that the current system is problematic. I think the major issue here is that Discord didn’t go far enough, and as a result, it’s confusing users who are unaware of the technical and practical reasons for the username change, or what a username is even for.

There are several issues being brought up with the username change. One is that users are very upset about usernames being ascii-only alphanumeric, presumably because they do not realize that Discord is only ever going to show their usernames for the purposes of adding friends. Their Display Name is what everyone will normally see, which can be any arbitrary unicode. Discord only spent a single sentence mentioning the problem with someone’s username being written in 𝕨𝕚𝕕𝕖 𝕥𝕖𝕩𝕥 and I think a lot of users missed just how big of a problem this is. Any kind of strange character in a username would be liable to render it completely unsearchable, could easily get corrupted when sent over ascii-only text mediums, and essentially had to be copy+pasted verbatim or it wouldn’t work.

However, some users wanted to be unsearchable, because they had stalkers or were very popular and didn’t want random people finding their discord account. Discriminators and case-sensitivity essentially created a searchability problem which users were utilizing on purpose to make it harder for people to search them. The solution to this is extremely simple, and was in fact a feature of many early chat apps: let the user turn off the ability for people to search for their username. That’s what people actually want.

What discord is trying to do, and communicating incredibly poorly, is transform usernames into friend codes. They say this in a very roundabout way for some reason, and they are also allowing people to essentially reserve custom friend codes. This is silly. Discord should instead replace usernames with friend codes, and provide an opt-in fuzzy search mechanism that tries to find someone based on their Display Name, if users want to be discoverable that way. Discord should let you either regenerate or completely disable your own friend code, if users don’t want random people trying to friend them.

What makes this so silly is that nothing is preventing discord from doing this, because you log in with your e-mail anyway! By replacing usernames with display names, Discord has removed all functionality from them aside from friend codes, so they should just turn usernames into friend codes and stop confusing everyone so much. There is absolutely no reason a user should have to keep track of their username, display name, and server specific nicknames, and letting users reserve custom friend codes is never going to work, because everyone is going to fight over common friend codes. Force the friend codes to be random 10-digit alphanumeric strings. Stop pretending they should be anything else. Stop letting people reserve specific ones.

There is one exception to this that I would tolerate: a custom profile URL. If you wanted to allow people with nitro to, for whatever reason, pay to have a special URL that linked to their profile, this could be done on a first-come first-serve basis, and it would be pretty obvious to everyone why it had to be unique and an ascii-compatible URL.

I’m really tired of companies making a decision for good engineering reasons, and then implementing that decision in the most confusing way possible and blaming anyone who complains as luddites who hate change. There are better ways to communicate these kinds of changes. If your users are confused and angry about it, then it’s your fault, not theirs.

We are fucked.

In fact, we are so fucked that Tom Scott conveniently released a new video talking about how fucked we are. Of course, he didn’t actually say that we’re fucked, because he’s much nicer than I am. He uses soft and gentle words that disguise the raging maelstrom beneath us. His video talks about how “everything is about to change”, and he’s right. I think he’s more right than he wants to be, he knows it, and he’s terrified.

Google’s new AI chatbot produced a factual error in it’s demo, and their stock dropped by $100 billion. Meanwhile, Bing’s AI chatbot produced a ton of errors during their presentation, and nobody noticed. People are noticing when the Bing AI chatbot goes completely bonkers, though, and this is precisely the problem.

We can tell when an AI goes completely off the rails and start spewing word salad, but most of the time the AI will confidently hallucinate completely nonsense and nobody can tell the difference. We already have the citogenesis problem, and then we had the social media “fake news” problem, and now we have AIs that can reliably gaslight anyone into believing almost anything they don’t already know about. Just wait until this starts making the replication crisis even worse.

Linus Tech Tips did an episode of WAN recently where they gave Linus three articles, and told him that at least one of those articles had been mostly written by an AI (with some minor fixups by a human), and he had to guess which ones were AI-written and which ones were written by a human. His answers were, one was probably human, one could be either human or AI, and one was probably AI. The two AI articles were actually the one he thought was human, and the one he thought was AI. The one that was written by a human was the one Linus wasn’t sure about.

We used to be worried about DeepFake videos, but now we already have people using AI to create fake images of a French cop hugging a protestor, while real artists are getting banned from /r/art because their art “looks ai-generated”. Meanwhile, CNET has been writing hundreds of articles using an AI for almost a year. Time has an article about how Big Tech needs to fix the “AI misinformation problem”, but nobody seems to know how. Who decides what is “misinformation”? If we already had the Wikipedia Citogenesis problem before ChatGPT, how can we possibly figure out what a trustworthy source is?

What’s really happening is that AI is amplifying a much more fundamental problem: Search Engine Optimization. We’re exposed to so much information on a daily basis that we don’t know what’s real, and Google can’t help us. As SEO makes Google searches progressively more useless, the web has become a morass of nonsensical data, blurring the line between fact and fiction. AI is now allowing us to generate even more information at an accelerating rate, essentially weaponizing disinformation. We have absolutely no way to deal with this, because we’ve invented the informational equivalent of gunpowder and decided it would be a good idea to give it to everyone.

Welcome to the Age of Bullshit.

What’s amazing is that almost all of this started just six years ago, with a paper from Google in 2017. The last time anything like this happened was when we invented the world wide web in 1994, which then exploded into the dot-com crash of 2001. Back then, the problem with the internet was finding things, which is what Google solved. The problem we now face, which is being made much worse by AI, is filtering things, as we get blasted by thousands of “relevent” search results. The successor to Google will be whoever invents a filter engine, to shield ourselves from the infinite amount of bullshit that we now have to wade through just to find high quality answers instead of ai-generated copies of translations of summaries of articles. Ironically, this is almost exactly the kind of fictional technology that Tom Scott talked about in 2014, almost 9 years ago.

We should be thankful that the current transformer based models are not sufficient to implement AGI, at least not in their current form, so we don’t have to worry about accidentally destroying the world with ChatGPT. This means AI researchers still have time to solve the alignment problem before someone figures out how to create a self-improving transformer model that no longer requires curated training data and promptly eradicates humanity. But who knows, maybe Google will publish a paper on this topic next year…?

Given our track record, maybe we should be spending more money on this alignment problem before we really fuck things up.

Decades ago, something absolutely unheard of happened - a nerd became the richest person on the planet. This, of course, was merely a consequence of Software Eating The World, a fact we are all now painfully aware of. Programming, once delegated to glasses-wearing nerds banging away on strange boxey devices that could add numbers, has been transformed into something that many people are interested in (mostly because it makes tons of money). Nowadays, as software permeates almost every aspect of modern life, programming is “cool”, firmly entrenched alongside doctors and lawyers as a respected, high income career path, so long as you get hired at a large company.

If you think about it, this represents a radical societal restructuring. All these nerds being put in charge of things tend to be more progressive and willing to support social movements. Combined with the fact that the best programmers can come from anywhere, including diverse and underserved backgrounds, this has forced software companies to cater specifically to minorities, accelerating existing societal shifts simply because they want to attract good programmers. Adding benefits specifically designed for trans people is a common example, but the shift to remote work is another.

As our world changes, the kinds of people we need to support our society changes with it. I don’t think people appreciate just how much the world has diverged from the neurotypical-cisgendered-heterosexual norms that were so entrenched just a hundred years ago. The United States only enshrined woman’s suffrage with the 19th amendment in 1920, just after World War I. It’s not just that the social fabric of society has changed, the world has changed. The global reality we live in has changed. Climate Change is now an existential threat that is beginning to have visible effects. Software and the digital world have not simply merged with reality, the internet now dominates it. 6 of the 10 largest companies by market cap are software or computer hardware companies. The exceptions are Johnson & Johnson, Berkshire Hathaway, United Health, and Exxon Mobil. The world’s largest oil company is #9 on that list. This is a titanic shift in economic power that’s happened only in the past few decades.

This is not unique to modern history. Each major technological or geopolitical shift in human history changes the balance of power. World War II’s Rosie The Riveter is the most recent example of a sudden geopolitical change (a global Total War necessitating a drastic social shift), when women were encouraged to take manufacturing jobs previously reserved for men. This was extremely unusual at the time, and after the war ended, the government abruptly started pressuring women to “return to normalcy”. Sound familiar? While most women reluctantly returned to more traditional jobs, many historians consider it the impetus for The Quiet Revolution, which eventually resulted in women permanently entering the workforce. The First and Second Industrial Revolution notably involved a steep decline in infant mortality, but not child mortality, as the baby boom resulted in a massive increase in child labor that was much more deadly than the farm work they were doing before. This eventually resulted in much stricter child labor laws in the UK and United States, eliminating children from the pool of available physical labor.

Going back farther, ancient history is full of tribes and civilizations that displayed a huge amount of variation depending on their particular geographic and technological pressures, including concepts of alternative genders or even different ways of expressing time. A society is a particular subset of all possible personalities that are able to self-organize and maintain order. In any society, what exactly a “reasonable person” is and what constitutes a crime may vary significantly. Factions within a society grow or shrink depending on economic and environmental influences, which can change the favored social fabric. This evolution of the social fabric is happening right now as technological advances allow entire forgotten sects of humanity to express their true potential in ways never before possible.

VR is still in an early adopter phase and its real impact has yet to be appreciated. We have only a scant few video games that can take meaningful advantage of it, a few poor attempts at metaverses, and hardly any useful productivity apps. We are teetering on the edge of another technological reorganization of society, where the entire world gets eaten by VR and AR in ways that people have difficulty appreciating right now because the hardware isn’t there yet. Once we solve the last few critical problems - like comfortable reading without headaches and less bulky headsets - then everything will change, very suddenly.

Over half my friends have ADHD, and when hyperfocused are capable of things few neurotypical people could ever do. Many of them are autistic, able to think in ways that most neurotypicals can only replicate with a lot of drugs. They don’t just think outside the box, they think outside of boxes people aren’t aware of. Some hyperfocused ADHD people can take advantage of the entire interactive volume around them in VR space, allowing them to open 5 different reference manuals while working on a project, or cross-reference a dozen sources in realtime, or set up a massive set of realtime data visualizations while monitoring a system. A persistent, freely navigable workspace inside VR (that could also be non-euclidean) makes it easier to return to tasks later without having to reconstruct an entire mental state. However, the ability to do many things at once sometimes translates into a need to do many things at once, and the ability to focus for long periods of time on one task can translate into an inability to do anything else, like getting food or remembering to mail an important tax form.

Unfortunately, in our modern society, houses have little to no interior noise insulation and almost every single electronic device makes a constant high-frequency drone. Neurotypicals either do not hear these sounds, or tune them out after a few minutes (and then claim the sound doesn’t exist, having immediately forgotten it). These houses are then built right next to roads with noisy cars, often without sidewalks, and sometimes with ubiquitous traffic noises when buried deep inside the city. How distracting these noises are depends on the person, the noise, whether it is speech, music, a kind of music you don’t like, or a ticking clock. Many places make these sounds inescapable, like restaurants with loud music and conversations, or offices with ticking clocks in every single room.

In contrast, in VR you can wear noise-cancelling headphones and put on music no one else can hear that is automatically attenuated if someone is talking to you. VR lets you tightly control your auditory environment - you can selectively isolate sound sources to only hear the conversation around you instead of having to tune out the dozens of other conversations. Nameplates on avatars can help faceblind people and avatars themselves can be more visually distinct than human faces. Being able to share a funny image with someone without having to show them your phone and hoping you don’t get an embarrassing notification at that exact moment would be useful for many people. Making things more accessible helps everyone.

A lot of what makes these problems so damaging for neurodivergents is the refusal of accommodation from neurotypicals. Often, this is simply authority figures forcing neurodivergent people to remain in environments causing them physical pain. Sadly, humans have a tendency to reject any culture other than their own as invalid or barbaric, possibly due to tribalism. Those of us living in a western country point to history as justification, while conveniently ignoring the fact that history is written by the victors. Countries like America are often willfully ignorant of the natives they subjugated now living in a post-apocalyptic world. While many executives acknowledge the rise of LGBTQIA+ individuals, or at least pay lip-service to them, it is painfully obvious that most do not understand the true cultural upheaval that is upon us. For example, Meta is inherently doomed for a very simple reason: It’s not furry enough.

Despite the prevalence of how Furries Run The Internet, an amazing number of tech workers still do not understand the significance of furries. Just two years ago, a coworker of mine came out as both trans and a furry, in the same e-mail. I never saw the need to “come out” as a furry (which should be obvious, given my avatar) but the reality is that furries are now a significant social force, which is largely going ignored. The one significant competitor to VRchat is NeosVR, developed by… furries. A starbucks union organizer wears his fursuit to rallies. The furry revolution is already here and nobody is paying attention to the fact that furries will not only dominate VR tech, they will determine the fate of any VR “metaverse”, because furries are the ultimate VR power user.

This cultural blindspot is just one example of how humans are often laughably bad at predicting the future precisely because we are blind to social changes caused by technological advancements. This is why we laugh at visions of the future from 100 years ago, because they could only envision technological advances within the confines of their own culture. I still see people today predicting that VR will revolutionize painfully obvious things, like medical analysis, or 3D modeling, or architecture. No one talks about how it will provide a way for autistic people to be more confident about social gatherings when they control their sensory input sphere or allow plural people to switch between avatars depending on who is fronting. When people talk about “the dangers of VR”, it’s always the same stupid reading argument, instead of predicting the inevitable moral panic over weird VR sex. It reminds me of the old adage about science fiction:

“It would take an inventor to predict the automobile, and it would take a real visionary to predict highways and gas stations. But it would take a science fiction writer to predict the traffic jam.” - Ed Bryant

Death: No. Humans need fantasy to be human. To be the place where the falling angel meets the rising ape.
Susan: With tooth fairies? Hogfathers?
Death: Yes. As practice, you have to start out learning to believe the little lies.
Susan: So we can believe the big ones?
Death: Yes. Justice, mercy, duty. That sort of thing.

I want to start this by saying that I am in favor of a wealth tax. We should be increasing taxes on the wealthy and raising minimum wage, because we know that steadily increasing the relative buying power of the poor is the best way to improve an economy. However, none of this happens in a vacuum. When we talk about income equality, I have become distressed at the amount of ignorance on display about the economy, systemic societal problems, and even what money actually is.

One Pixel Wealth is a webpage from 2021 that helps visualize how truly insane the amount of wealth that the richest people have actually is. While the visualization is great at putting in perspective just how much Jeff Bezos’ wealth is on paper, it links to a refutation of the Paper Billionaire Argument to dispute the idea that Jeff Bezos doesn’t really have that much money in liquid assets. The paper billionaire argument is that, because most wealth is in stocks or bonds, selling it all at once would flood the market and crater the total value of those assets.

The proposed counter-argument is incredibly bad. It demonstrates a total lack of understanding about macro-economic forces. Ironically, this is because it cannot appreciate the scale of its own arguments, the exact issue that One Pixel Wealth is trying to address. Let me paraphrase the key points in this counter-argument:

  1. The Paper Billionaire argument doesn’t work, because you can liquidate the wealth over time in a controlled sell-off, which executives do regularly.
  2. Given that $122 trillion worth of stock changes hands in the US every year, you could liquidate a trillion dollars over five years and only constitute 0.16% of all the trading.
  3. Because 50% of all US households own stock, you will always be able find people to buy the stock the billionaires are selling, it’s not just other billionaires that will buy it.
  4. Even if the paper bilionaire argument was true, if selling all the stock would lose 80% of it’s value, that would leave behind $700 billion.

To start, #1 and #2 don’t work for a very simple reason: A stock’s value represents the market’s confidence in the stock producing future value. Owning stock, in some circumstances, is interpreted as having confidence in that future value. If the market loses confidence in your company, it doesn’t matter what assets you have, your stock price will crater if the market thinks you’ll start losing money. If the CEO starts liquidating their position (which they must state their intention to sell stock ahead of time, years before it completes), the market will panic and the stock price will implode at the mere announcement of the liquidation, let alone actually selling any stock. Elon Musk right now should make it painfully obvious that he was only ever the richest man in the world on paper, because he just lost $107 billion dollars this year! He only bought Twitter for $44 billion! You simply cannot make the combined GDPs of Bulgaria, Croatia, Iceland and Uruguay evaporate if that money was actually real in any sense.

Money does not represent physical assets. Money is supposed to represent human labor, and there is a fixed amount of human labor available on the planet. When someone dies or is incapacitated, it goes down. When someone graduates into the labor force, or becomes more skilled, it goes up. In ancient times, “human labor” was heavily correlated to how much physical activity someone could do, like lifting things or harvesting food. However, our modern economy is dominated by specialist jobs done by highly skilled laborers. So for the sake of analysis, we can say that the GDP of the entire planet should ideally represent the maximum amount of labor the entire human race could do, if we assigned everyone to the job they are most qualified for. We could then increase the total amount of labor we can do by either building machines or improving our skills.

This leads into why point #3 is complete nonsense. It reminds me of when Ben Shapiro, when talking about climate change, asked “you think that people aren’t going to just sell their homes and move?”

The entire point of wealth inequality is that the top 1% holds more money than the entire middle-class. That’s literally the problem! How can everyone else possibly buy all the stock the billionaires are selling if it would require all of their savings? Who are you selling the stocks to?! This isn’t how money works! One Pixel Wealth even tries to claim that if we just gave all the poor people in america a bunch of money it would fix poverty, while linking to a study that only applies to local economies. The world’s largest economy is NOT a local economy! These measures only work when the global economy can absorb the difference, which means making changes gradually or in small, localized areas.

Of course, even if you somehow magically liquidated all your assets and acquired $700 billion dollars in real, liquid cash, it’s not actually $700 billion dollars. It’s like saying that there are gold asteroids worth $10000 quadrillion dollars - the value would plummet if you actually had that much gold. Since money represents human labor, which is a limited resource, simply having more money does not let you do more things. $700 billion dollars is enough to hire 12 billion people for 1 day working at minimum wage ($7.25), but you can’t actually do that, because there’s only 7.8 billion people in the entire world. Having $700 billion in liquid assets would decrease the value of money itself. That’s what inflation is. People claim that some billions of dollars will be enough to eradicate malaria or provide drinking water to everyone, but it’s never that simple because these are always geopolitical issues. Bill Gates has donated billions of dollars since 2005 towards fighting malaria and we only got a vaccine 16 years later. We’re surrounded by so many dumb problems we can solve with more money that we’ve forgetten that some problems are really, truly, fundamentally difficult problems that cannot be solved by throwing money at them. At some point there are just too many cooks in the kitchen.

Note that this labor distribution problem applies to liquid assets, which is one theory on why inflation had (until 2021), remained fairly low despite the amount of wealth increasing to ridiculous amounts. Wealthy people are acting as gigantic money sinks - by absorbing all of the “money”, the actual amount of real, liquid cash in the economy increased at a modest rate, so inflation remained stable. Now, inflation has started to skyrocket in 2022, and some people blame the stimulus payments, but the reality is that the low interest rates during the pandemic, combined with other complex macroeconomic forces, likely caused it, although nobody knows for sure. If wealthy people started actually spending all their money at once, as people seem to want them to do, the amount of liquid assets would skyrocket and so would inflation.

I keep saying that money is supposed to represent human labor, because it’s really an approximation. Someone can be more productive at one job than another, so the amount of human labor is not a knowable value in the first place. Instead, it helps to think of money as representing percieved power imbalance (conservatives often make the mistake of thinking it represents actual power imbalance, which it does not). This power imbalance can come from economic, diplomatic, or military factors. Basically, money is just the current state of global geopolitics. You cannot fight wealth inequality by just redistributing money. Simply taking money from rich people does not fix the systemic issues that created the power imbalance in the first place, because it’s not actually wealth inequality, it’s power inequality, and that is a political issue, not economic. Money is simply our way of quantifying that imbalance. The government’s unwillingness to tax rich people is because of the power imbalance, not the cause of it. If politicians are unwilling to go after rich people, it’s because those rich people hold an alarming amount of sway over politicians, which makes them keys to power.

It means that we have allowed power to accumulate in dangerously high concentrations, and we need to deal with this at a political level before we get an economic solution. We must elect leaders that help tackle power inequality (like break up huge corporations) before we can make progress on wealth inequality. Basically, go vote.

You can’t have a 4-slot GPU. You just can’t.

We have finally left sanity behind, with nvidia’s 4000 series cards yielding a “clown car” of absurd GPU designs, as GamersNexus put it. These cards are so huge they need “GPU Support Sticks”, which are an actual real thing now. The fact that we insist on relegating the GPU to interfacing with the system while hanging off of a single, increasingly absurd PCIe 6.0 x16 slot that can push 128 GBps is completely insane. There is no real ability to just pick the GPU you want and then pair it with a cooler that is actually attached to the motherboard. The entire cooling solution has to be in the card itself and we are fast reaching the practical limitations here due to gravity and the laws of physics. Top-heavy GPUs are now essentially giant levers pulling on the PCIe slot, with the only possible anchor point that is above the center of mass being the bracket on one side.

A 4090 series card will demand a whopping 450 W, which dwarfs the Ryzen 9 5900X peak power consumption of only 140 W. That’s over 3 times as much power! The graphics card is now drawing more power than the entire rest of the computer! We’ll have to wait for benchmarks to be sure, but the laws of thermodynamics suggest that the GPU will now also be producing more heat than every other component of the PC, combined. And this is the thing we have hanging off of a PCIe slot that doesn’t have any other way of mounting a cooling solution to the motherboard?!

What the FUCK are we doing?!

Look, I’m not a hardware guy. I just write all the shader code that makes GPUs cry. I don’t actually know how we should fix this problem, because I don’t know what designs are thermally efficient or not. I do know, however, that something has to change. Maybe we can make motherboards with a GPU slot next to the CPU slot and have a unified massive radiator sitting on top of them - or maybe it’s a better idea to put the two processor units on opposite ends of the board. I don’t know, just do something so I can use a cooling solution that is actually screwed into the fucking motherboard instead of requiring a “GPU Support Stick” so gravity doesn’t rip it out of the PCIe slot.

As an example of alternative solutions, here is an MXM form-factor for laptops that allow them to provide custom cooling solutions appropriate for the laptop.

In fact, the PCIe spec itself actually contains a rear-bracket mount that, if anyone was paying attention, would help address this problem:

See that funky looking metal thing labeled “2” on the diagram? That sure looks like a good alternative to a “support stick” if anyone ever actually paid attention to the spec. Or maybe this second bracket doesn’t work very well and we need to rethink how motherboards work entirely. Should we have GPU VRAM slots alongside CPU RAM slots? Is that even possible? (Nope.) Or maybe we can come up with an alternative form factor for GPU cards that you can actually attach to the motherboard with screws?

I have no idea what is or isn’t practical, but please, just do something before the GPUs collapse under their own gravity and create strange new forms of matter inside my PC case.

21 years ago, I walked into my 5th grade teacher’s classroom and it was dead silent. The TV was on. Something was happening that I didn’t understand, but my instincts told me that This Was Very Wrong. That moment is carved into my memory not because of what actually happened on September 11th, which I was too young to fully grasp, but because the way the adults were behaving signaled to my young mind that this was very important and I needed to remember it.

I have one other distinct memory from that time, which was either someone on the news or a teacher in a classroom explaining that “the goal of the terrorist attack is to make us scared. If we let fear rule us, the terrorists have won.”

I guess I should congratulate the terrorists for winning the war on terror.

The utter lack of rational behavior that followed was something that continued to bother me as I grew up and went to college. I could tell something was wrong, but I wasn’t quite sure what it was. As I realized college wasn’t going to teach me anything useful, I just started taking more and more difficult classes in an effort to glean math jargon I could Google instead. My faith in institutions was shaken, and continued to decline when I got a job and realized how much of the business world was complete bullshit. However, Obama was president during this time, and as a result I still had some faith that while we clearly had problems, these problems were surmountable. We even signed the Paris agreement in 2015, and I hoped we would finally do something about Climate Change.

Then we elected Trump.

I’m not going to rehash the Trump years, we all know it was a clown show. But somehow, I still believed that Trump had only been elected thanks to massive voter suppression efforts. Then Covid happened, and it taught me a very important lesson: People don’t give a shit. We managed to politicize one of the worst pandemics in modern history. We completely refused to obey even a partial lockdown, let alone a full lockdown, or even slow the spread with properly implemented contact tracing and testing, because this required people to act for the sake of their community, instead of themselves. At this point, America is completely incapable of collective action.

Every single year that September 11th rolls around, people point out that 3000 people dying really isn’t that many when you compare it to, say, 1750 people dying from firearm homicides every month, which we continue to do nothing about, and every year people say this is in “bad taste” or is “disrespectful”. But now, idiots on social media are trying to say that this somehow isn’t the right time to point out that Covid-19 killed ONE MILLION PEOPLE in the United States alone, because we’re supposed to stop and remember the 3000 people who died because a terrorist from a group of rebels that we set up in the first place blew up a skyscraper?!

ARE YOU FUCKING KIDDING ME?

You want my respect? How about you explain to me why my friend’s boyfriend had to die from a preventable disease just because they lived in Venezuala and never had access to a vaccine that America was hoarding after scientists said this was a bad idea? He’s dead now. He’s just as dead as whoever was in the World Trade Center when it collapsed. Why are we honoring the people who died from being torn apart in an explosion and not the people who are being torn apart in slow motion by a trillion tiny viruses? Where are the Covid-19 memorials? Why does this country need something to fucking explode before we care about it?!

One of my friends is transgender. Their mom is, shall we say, not supportive, to say the least. Two years ago during the pandemic lockdown, her mom (who works as a nurse) showed up uninvited at her doorstep, without a mask, and essentially barged into her apartment. They messaged me for help, and I showed up to make sure her mom didn’t pull any stunts, because we already knew she was extremely manipulative. Meeting this slimy ghoul of a woman for the first time is something I will also never forget, because she made my skin crawl in a way that I can’t explain. It was like every word out of her mouth was dripping with deceit. Everything she said was an attempt to control the conversation or weaponize the situation against us. The entire time she misgendered and deadnamed her daughter while showing zero respect to anyone. All she did was act “polite” and then tried to pretend that saying please and thank you means being respectful. As the argument continued, she eventually said The Words.

“You should respect your elders.”

In that moment, it took every ounce of self-control I had to not tell this horrible woman that she had no right to tell me anything. Instead, I simply said “excuse me?”, because this was not my fight - I was there to support my friend’s decisions, not my own, and to ensure her mom actually listened to those decisions. We did eventually get her mom out of there, but the fact that someone actually said that has stuck with me, because it reeks of the bullshit I have been fed for the past decade from old people who demand respect yet have done nothing to earn it.

I want to make this absolutely crystal clear: I don’t respect any elders. They’re destroying the planet and they want me to respect them? Get out. I don’t think the older generations understand that you don’t ask for my respect, you earn it. One of the very few people from older generations that I do respect are my parents, because they never told me I should respect them. They didn’t tell me what to do. They simply tried to be good parents and respected me as a person by letting me make my own decisions, and as a result I deeply respect them, and they respect me, because respect is a two-way street.

The bullshit that conservatives say nowadays reminds me of my friend’s mom. It’s so patently disingenious, so obscenely manipulative, so obviously bad-faith that the only reason I take it seriously is because a real person said the same things to me in real life. I don’t think they respect anyone. I don’t think they care about anyone other than themselves. To conservatives, social behavior is just a game of pretend where everyone lies about everything all the time. It’s performance, where you say the words you’re supposed to say and do the things you’re supposed to do, and if you don’t you’re a Bad Person.

The worst part is that this bleeds into programming. When I was a senior at high school, I argued that garbage collected languages were too inefficient for core game systems because it would cause memory fragmentation. I was brushed off because people said that magic heap compaction from the garbage collector would take care of it. 15 years later, all mainstream game engines are still C++ and many have data-oriented architectures specifically designed to minimize memory fragmentation! Despite this, I still see people brushing off younger programmers pointing out that these same problems are precisely why Rust is necessary, but when I step in and make the exact same points, they listen to me, because I’m older and have a job at some game company they’ve heard of. This means people are not actually listening to the technical substance of an argument, but judging it by the credentials of the author. JeanHeyd Meneide mentions this exact phenomenon in a 2020 talk about problematic behavior in the C++ standards committee, a committee is supposedly purely about technical merit that is nonetheless plagued by intense hypocrisey.

Long ago, we had a hole in the Ozone layer caused by CFCs. World governments got together and banned it right before I was born, and now the ozone has partially recovered. Today, we can’t even hit the Paris Agreement goals, we’re dismantling nuclear power and replacing it with coal, we continue building car dependent infrastructure while refusing to maintain any of it. We are the architects of our own demise, except I didn’t vote for any of this garbage, and other millenials didn’t, either. The boomers won’t give us health care, they tell us to go to college but won’t pay for it, they buy up all the houses, and for good measure they almost took down the entire financial system.

These people want my respect?

Performative social behaviors are not respect, and you are not entitled to my respect, or anyone else’s. If you want respect, you can earn it, by respecting the agency of the other person, by actually listening to what they’re saying, and by having an honest dialogue instead of arguing over semantics. Maybe if boomers actually cared about other people, they’d get some respect.

This blog was started on LiveJournal shortly after I graduated high school in 2009. It has survived this long because I was very persistent about porting all my posts to Blogger, and then to my own static website. Of course, I have limits. Most of my terrible old posts were removed long ago, because they were so bad they didn’t contribute anything. One post was a rant about my high school internship at Microsoft. I took it down because it was bad, but more importantly I took it down because I wrote it before graduating college, while I was still completely delusional.

Let me explain.

I grew up 20 minutes from Microsoft. I had absolutely no idea what an absurdly warped childhood I had until I graduated college and met people who hadn’t grown up in a tech bubble. I never questioned how my middle school always somehow had the latest copy of Windows and maintained six different computer labs (one in each classroom hub, plus the library, plus a dedicated lab). I didn’t realize how unusual it was for my high school to offer an “intro to game dev course” in 2008, or how ridiculous it was that my AP Computer Science professor had worked on the first version of DirectX at Microsoft. I never thought it was weird that we had Microsoft Connector buses driving around town, creating an entire secondary bus system for the sole purpose of moving around Microsoft employees.

I definitely did not realize how utterly insane it was that, in July 2006, students from my high school (and a few other high schools around the area) were invited to a week long event where we would get to experiment with and “bug test” a beta version of Windows Vista, a full six months before it was released. At 8:00AM every morning, our parents dropped us off at Microsoft Building 40, and we were led into a room filled with rows of desks with computers on them. There were maybe 50 of us, and we were given guest accounts and full internet access while Microsoft employees gave presentations about various new features they had introduced for Vista.

I still remember some of those presentations. One that really stuck with me at the time was Microsoft jumping on the “192kHz sampling rate support” bandwagon, which makes absolutely no sense outside of music production, and in retrospect just seems incredibly dumb. Another presentation had us build wifi mesh networks between the computers, which was touted as a way to share files and communicate with friends in places with little to no internet connectivity. I remember this one both because I thought it was very cool, and because someone managed to bluescreen Windows while attempting to set it up, so they actually had an SDE come in and take a look.

In their attempts to make this a “camp” experience, they gave us all a project on the final day: create our own presentation (using the new Microsoft™ Office™ PowerPoint™ 2007, of course), about some new feature we wanted on Windows or some improvement that wasn’t there yet. I don’t remember what our presentation was, but I do know we were all terrible. Afterwards we were all invited to the “Windows Vista Consumer Support Assisted Beta”, a predecessor to the Windows Insider program.

This “Camp Vista” thing was a strange, one-time event, but the Hunt The Wumpus competition is still going. If you’re lucky enough to be attending school in the Lake Washington School District, you can team up with several other students and get tutoring from a Microsoft employee over the course of several months while you build a very basic video game and compete for Microsoft sponsored prizes. I fondly remember our attempts at building a game using XNA back when it was brand new (it’s now dead), and making a bad Descent clone. We tried to use SVN, but weren’t allowed to install it on school computers, so we resorted to an FTP folder and e-mailing zip files.

Here we have the crux of the problem with my initial impressions of my high school internship - it’s not a normal thing! Students worldwide compete for a chance to get college internships at Microsoft, but the high school interns are just random CS students from the Lake Washington School District. When my team learned I knew quite a bit of programming already, they had to come up with something else for me to do because they had assumed I barely knew how to code. It was just another outreach program for nearby high schools, only available to 31000 kids on the entire planet.

So in the midst of me having an experience that almost no other high school student gets to have, I am complaining about things like “wow, we have too many meetings” and “wow, this software is bad”. Yes, we know Microsoft is a dysfunctional catastrophe, but focusing on issues that are omnipresent in large corporations only serves to detract from the actual crazy parts of the internship, like how the program we were working on, if compiled with no optimizations, took 20 minutes to start. Or the meeting where the entire team spent 15 in-person minutes sitting around an actual table deciding that one of our function names was too long and debated over what to rename it before deciding not to change it. Or that one time the department head (my boss’s boss’s boss) took me, an intern, to a meeting with his boss, who I think directly reported to a vice president. It got better, though, because one afternoon, there was a 3-hour period of time where my boss, his boss, and the department head were all gone, so I, a 19-year-old high school student, was technically supposed to take my questions about how to use C# PInvoke to the department head’s boss.

I was really careful not to break anything for 3 hours.

Looking back at my teenage years has made me realize how easy it is for people to simply miss how some aspect of their upbringing was deeply unusual. For some, it may be a silent hindrance, but for others, it might be a quiet boon, softly sending opportunities their way that almost no one else has access to. How many opportunities did I let slip by, unaware of how unique they were?

Over 25 years ago, Brenden Eich created JavaScript, named after Java simply because it was popular. It’s prototypical nature and dynamic typing made it unsuitable for anything other than slow interpreters, forcing Google to invent a way to JIT the language just to make it fast. We even built a package manager for JavaScript which managed to create such an absurd dependency hell that one guy’s left-pad function managed to break web development for a day.

Now the entire world economy runs on JavaScript.

This is the kind of dumb future that we live in, and it is the kind of dumb future we can look forward to with blockchain. It is why people who insist that blockchain will never work because of various technological reasons are ignoring the simple fact that humanity is incredibly good at standardizing on the worst possible things, then building our entire future on top of them. In fact, there is a disturbing number of direct parallels between the rise of JavaScript and the rise of blockchain technologies, with a few key differences.

JavaScript was originally going to be Scheme, a lisp dialect. Sadly, the management demanded that it look more like Java, so Brenden hid Scheme inside a vaguely Java-esque syntax, which became Mocha, which became LiveScript, which then became JavaScript. This has led to many suffering web developers agonizing over the fact that “We could have had Lisp!”. Even worse, CSS originated in DSSSL, which was another dialect of Scheme for constructing style sheets, but it was deemed too complicated (too many parenthesis!), so a much simpler version was created, called CSS. Modern CSS, of course, has simply reinvented everything DSSSL had, except worse.

This is what drives the entire internet, and in turn, Amazon’s trillion dollar empire.

In 2009, Satoshi Nakamoto unleashed Bitcoin upon an unsuspecting world. Most people ignored it, for good reason - it was completely impractical for any sort of global transaction system, capable of processing a whopping 7 transaction per second. Then the first bubble happened and Bitcoin skyrocketed to $1000 USD in late 2013. It then promptly crashed to $300 in 2014, after which most people thought it had simply been a passing fad, and ignored it for the next 3 years, until the second bubble of 2017.

But not everyone. After his favorite World of Warcraft spell got nerfed by Blizzard, some maniac Vitalik Buterin argued that the Bitcoin network should support programmable smart contracts, at the peak of the 2013 bubble. Here, we almost had a repeat of JavaScript, nearly bolting on smart contracts to a blockchain algorithm that was never designed for it. However, history thankfully granted us a reprieve, because the Bitcoin developers told Vitalik to take a hike. So, he invented Ethereum, which is like Bitcoin except slightly less stupid. Unfortunately, it still ran on Proof-of-Work, which means burning coal to solve sudokus.

At this point, you may be expecting me to draw a parallel from Google’s V8 JavaScript engine to Proof-of-Stake, but that actually isn’t correct. Proof-of-Stake doesn’t make the network faster, it just lets the network run without wasting astronomical amounts of energy. Proof-of-Stake is more analogous to the introduction of AJAX in 1999, the foundational JavaScript extension that allowed for asynchronous websites, and in turn, the entire modern web. Proof-of-Stake is a change that finally makes Ethereum usable for large scale smart contracts without burning ludicrous amounts of electricity to run the network. This, however, isn’t enough, because Ethereum’s network is still painfully slow. Granted, at 14 transactions per second, it’s at least twice as fast as Bitcoin, but that doesn’t really count for much when you need to be several orders of magnitude faster.

So, naturally, just like we did with JavaScript, a bunch of extremely smart people are inventing ways to make Ethereum’s horribly slow network go really fast, either by creating Layer 2 Rollups, or via sharding through the proposed Shard Chains. Individually, these optimizations are expected to yield 2000-3000 transactions per second, and if combined, the optimistic estimate is that it will allow hundreds of thousands of transactions per second. We’ll have to wait until we see the true results of the speedups, but even the pessimistic estimations expect a 100x increase in transaction speed with existing Layer 2 rollup solutions, which is a pretty big deal.

Of course, if you give an inch, they’ll take a mile, and when Web Developers discovered that we could make JavaScript go fast, they started putting entire software solutions on the web. We got Web Apps. We got Electron. Now I’ve got JavaScript running in my goddamn IDE and there’s no end in sight. We’ve forgotten how to make native apps (and the lack of good UI solutions for anything other than JavaScript hasn’t helped, either), so now the Web isn’t just inside your Web Browser, it’s in all your programs too. We’ve created a monster, and there’s no getting it back in the box.

This, I think, is something we should keep in mind when criticizing “unnecessary” blockchain solutions. Opponents of blockchain correctly point out that there are, in fact, very few things that actually need to be decentralized. Oftentimes, you can achieve decentralization through federation, or a DHT, or some other option instead, without needing an entire decentralized permanent public ledger. In many cases, having a permanent write-only public ledger is objectively worse than existing solutions.

These criticisms are all 100% true and also don’t matter. If software actually needed to work well in order for people to use it, nobody would use anything Oracle made. Our future is filled with blockchains that we have spent obscene amounts of time and effort to make fast so we can create centralized decentralized solutions, private public ledgers, and dumb smart contracts. There are good ideas buried underneath this mess, but if we spend our time railing against blockchain instead of implementing them, all we’ll get is more left-pad. We only have one chance to make the future suck less, even if we’re just proposing less awful blockchain designs.

This is why I have begun learning the basics of blockchain - not because any of this makes sense, or is even a good idea. I simply recognize that the future is coming, and the future is dumb.

C++ Initialization Hell

What exactly happens when you write Foo* foo = new Foo();? A lot is packed into this one statement, so lets try to break it down. First, this example is allocating new memory on the heap, but in order to understand everything that’s going on, we’re going to have to explain what it means to declare a variable on the stack. If you already have a good understanding of how the stack works, and how functions do cleanup before returning, feel free to skip to the new statement.

Stack Lifetimes

Describing the stack is very often glossed over in many other imperative languages, despite the fact that those languages still have one (functional languages are an entirely different level of weird). Let’s start with something very simple:

int foobar(int b)
{
  int a;
  a = b;
  return a;
}
Here, we are declaring a function foobar that takes an int and returns an int. The first line of the function declares a variable a of type int. This is all well and good, but where is the integer?. On most modern platforms, int resolves to a 32-bit integer that takes up 4 bytes of space. We haven’t allocated any memory yet, because no new statement happened and no malloc() was called. Where is the integer?

The answer is that the integer was allocated on the stack. If you aren’t familiar with the computer science data structure of the same name, your program is given a chunk of memory by the operating system that is organized into a stack structure, hence the name. It’s like a stack of plates - you can push items on top of the stack, or you can remove items from the top of the stack, but you can’t remove things from the middle of the stack or all the plates will come crashing down. So if we push something on top of the stack, we’re stuck with it until we get rid of everything on top of it.

When we called our function, the parameter int b was pushed on to the stack. Parameters take up memory, so on to the stack they go. Hence, before we ever reach the statement int a, 4 bytes of memory were already pushed onto our stack. Here’s what our stack looks like at the beginning of the function if we call it with the number 90 (assuming little-endian):

Stack for b

int a tells the compiler to push another 4 bytes of memory on to the stack, but it has no initial value, so the contents are undefined:

Stack for a and b

a = b assigns b to a, so now our stack looks like this:

Stack for initialized a and b

Finally, return a tells the compiler to evaluate the return expression (which in our case is just a so there’s nothing to evaluate), then copy the result into a chunk of memory we reserved ahead of time for the return value. Some programmers may assume the function returns immediately once the return statement is executed - after all, that’s what return means, right? However, the reality is that the function still has to clean things up before it can actually return. Specifically, we need to return our stack to the state it was before the function was called by removing everything we pushed on top of it in reverse order. So, after copying our return value a, our function pops the top of the stack off, which is the last thing we pushed. In our case, that’s int a, so we pop it off the stack. Our stack now looks like this:

Stack without a

The moment from which int a was pushed onto the stack to the moment it was popped off the stack is called the lifetime of int a. In this case, int a has a lifetime of the entire function. After the function returns, our caller has to pop off int b, the parameter we called the function with. Now our stack is empty, and the lifetime of int b is longer than the lifetime of int a, because it was pushed first (before the function was called) and popped afterwards (after the function returned). C++ builds it’s entire concept of constructors and destructors on this concept of lifetimes, and they can get very complicated, but for now, we’ll focus only on stack lifetimes.

Let’s take a look at a more complex example:

int foobar(int b)
{
  int a;
  
  {
    int x;
    x = 3;
    
    {
      int z;
      int max;
      
      max = 999;
      z = x + b;
      
      if(z > max)
      {
        return z - max;
      }
      
      x = x + z;
    }
    
    // a = z; // COMPILER ERROR!
    
    {
      int ten = 10;
      a = x + ten;
    }
  } 
  
  return a;
}
Let’s look at the lifetimes of all our parameters and variables in this function. First, before calling the function, we push int b on to the stack with the value of whatever we’re calling the function with - say, 900. Then, we call the function, which immediately pushes int a on to the stack. Then, we enter a new block using the character {, which does not consume any memory, but instead acts as a marker for the compiler - we’ll see what it’s used for later. Then, we push int x on to the stack. We now have 3 integers on the stack. We set int x to 3, but int a is still undefined. Then, we enter another new block. Nothing interesting has happened yet. We then push both int z and int max on to the stack. Then we assign 999 to int max and assign int z the value x + b - if we passed in 900, this means z is now equal to 903, which is less than the value of int max (999), so we skip the if statement for now. Then we assign x to x + z, which will be 906.

Now things get interesting. Our topmost block ends with a } character. This tells the compiler to pop all variables declared inside that block. We pushed int z on to the stack inside this block, so it’s gone now. We cannot refer to int z anymore, and doing so will be a compiler error. int z is said to have gone out of scope. However, we also pushed int max on to the stack, and we pushed it after int z. This means that the compiler will first pop int max off the stack, and only afterwards will it then pop int z off the stack. The order in which this happens will be critical for understanding how lifetimes work with constructors and destructors, so keep it in mind.

Then, we enter another new scope. This new scope is still inside the first scope we created that contains int x, so we can still access x. We define int ten and initialize it with 10. Then we set int a equal to x + ten, which will be 916. Then, our scope ends, and int ten goes out of scope, being popped off the stack. Immediately afterwards, we reach the end of our first scope, and int x is popped off the stack.

Finally, we reach return a, which copies a to our return value memory segment, pops int a, and returns to our caller, who then pops int b. That’s what happens when we pass in 900, but what happens if we pass in 9000?

Everything is the same until we reach the if statement, whose condition is now satisfied, which results in the function terminating early and returning z - max. What happens to the stack?

When we reach return z - max, the compiler evaluates the statement and copies the result (8004) out. Then it starts popping everything off the stack (once again, in the reverse order that things were pushed). The last thing we pushed on to the stack was int max, so it gets popped first. Then int z is popped. Then int x is popped. Then int a is popped, the function returns, and finally int b is popped by the caller. This behavior is critical to how C++ uses lifetimes to implement things like smart pointers and automatic memory management. Rust actually uses a similar concept, but it uses it for a lot more than C++ does.

new Statements

Okay, now we know how lifetimes work and where variables live when they aren’t allocated, but what happens when you do allocate memory? What’s going on with the new statement? To look at this, let’s use a simplified example:

int* foo = new int();
Here we have allocated a pointer to an integer on the stack (which will be 8 bytes if you’re on a 64-bit system), and assigned the result of new int() to it. What happens when we call new int()? In C++, the new operator is an extension of malloc() from C. This means it allocates memory from the heap. When you allocate memory on the heap, it never goes out of scope. This is what most programmers are familiar with in other languages, except that most other languages handle figuring out when to deallocate it and C++ forces you to delete it yourself. Memory allocated on the heap is just there, floating around, forever, or until you deallocate it. So this function has a memory leak:
int bar(int b)
{
  int* a = new int();
  *a = b;
  return *a;
}
This is the same as our first example, except now we allocate a on the heap instead of the stack. So, it never goes out of scope. It’s just there, sitting in memory, forever, until the process is terminated. The new operator looks at the type we passed it (which is int in this case) and calls malloc for us with the appropriate number of bytes. Because int has no constructors or destructors, it’s actually equivelent to this:
int bar(int b)
{
  int* a = (int*)malloc(sizeof(int));
  *a = b;
  return *a;
}
Now, people who are familiar with C will recognize that any call to malloc should come with a call to free, so how do we do that in C++? We use delete:
int bar(int b)
{
  int* a = new int();
  *a = b;
  int r = *a;
  delete a;
  return r;
}
IMPORTANT: Never mix new and free or malloc and delete. The new/delete operators can use a different allocator than malloc/free, so things will violently explode if you treat them as interchangeable. Always free something from malloc and always delete something created with new.

Now we aren’t leaking memory, but we also can’t do return *a anymore, because it’s impossible for us to do the necessary cleanup. If we were allocating on the stack, C++ would clean up our variable for us after the return statement, but we can’t put anything after the return statement, so there’s no way to tell C++ to copy the value of *a and then manually delete a without introducing a new variable r. Of course, if we could run arbitrary code when our variable went out of scope, we could solve this problem! This sounds like a job for constructors and destructors!

Constructors and delete

Okay, let’s put everything together and return to our original statement in a more complete example:

struct Foo
{
  // Constructor for Foo
  Foo(int b)
  {
    a = b;
  }
  // Empty Destructor for Foo
  ~Foo() {}
  
  int a;
};

int bar(int b)
{
  // Create
  Foo* foo = new Foo(b);
  int a = foo->a;
  // Destroy
  delete foo;
  return a; // Still can't return foo->a
}
In this code, we still haven’t solved the return problem, but we are now using constructors and destructors, so let’s walk through what happens. First, new allocates memory on the heap for your type. Foo contains a 32-bit integer, so that’s 4 bytes. Then, after the memory is allocated, new automatically calls the constructor that matches whatever parameters you pass to the type. Your constructor doesn’t need to allocate any memory to contain your type, since new already did this for you. Then, this pointer is assigned to foo. Then we delete foo, which calls the destructor first (which does nothing), and then deallocates the memory. If you don’t pass any parameters when calling new Type(), or you are creating an array, C++ will simply call the default constructor (a constructor that takes no parameters). This is all equivelent to:
int bar(int b)
{
  // Create
  Foo* foo = (Foo*)malloc(sizeof(Foo));
  new (foo) Foo(b); // Special new syntax that ONLY calls the constructor function (this is how you manually call constructors in C++)
  int a = foo->a; 
  // Destroy
  foo->~Foo(); // We can, however, call the destructor function directly
  free(foo);
  
  return a; // Still can't return foo->a
}
This uses a special new syntax that doesn’t allocate anything and simply lets us call the constructor function directly on our already allocated memory. This is what the new operator is doing for you under the hood. We then call the destructor manually (which you can do) and free our memory. Of course, this is all still useless, because we can’t return the integer we allocated on the heap!

Destructors and lifetimes

Now, the magical part of C++ is that constructors and destructors are run when things are pushed or popped from the stack [1]. The fact that constructors and destructors respect variable lifetimes allows us to solve our problem of cleaning up a heap allocation upon returning from a function. Let’s see how that works:

struct Foo
{
  // Default constructor for Foo
  Foo()
  {
    a = new int();
  }
  // Destructor frees memory we allocated using delete
  ~Foo()
  {
    delete a;
  }
  
  int* a;
};

int bar(int b)
{
  Foo foo;
  *foo.a = b;
  return *foo.a; // Doesn't leak memory!
}
How does this avoid leaking memory? Let’s walk through what happens: First, we declare Foo foo on the stack, which pushes 4 bytes on to the stack, and then C++ calls our default constructor. Inside our default constructor, we use new to allocate a new integer and store it in int* a. Returning to our function, we then set our integer pointer foo.a to b. Then, we return the value stored in foo.a from the function[2]. This copies the value out of foo.a first by dereferencing the pointer, and then C++ calls our destructor ~Foo before Foo foo is popped off the stack. This destructor deletes int* a, ensuring we don’t leak any memory. Then we pop off int b from the stack and the function returns. If we could somehow do this without constructors or destructors, it would look like this:
int bar(int b)
{
  Foo foo;
  foo.a = new int();
  *foo.a = b;
  int retval = *foo.b;
  delete a;
  return retval;
}
The ability to run a destructor when something goes out of scope is an incredibly important part of writing good C++ code, becuase when a function returns, all your variables go out of scope when the stack is popped. Thus, all cleanup that is done during destructors is gauranteed to run no matter when you return from a function. Destructors are gauranteed to run even when you throw an exception! This means that if you throw an exception that gets caught farther up in the program, you won’t leak memory, because C++ ensures that everything on the stack is correctly destroyed when processing exception handling, so all destructors are run in the same order they normally are.

This is the core idea behind smart pointers - if a pointer is stored inside an object, and that object deletes the pointer in the destructor, then you will never leak the pointer because C++ ensures that the destructor will eventually get called when the object goes out of scope. Now, if implemented naively there is no way to pass the pointer into different functions, so the utility is limited, but C++11 introduced move semantics to help solve this issue. We’ll talk about those later. For now, let’s talk about different kinds of lifetimes and what they mean for when constructors and destructors are called.

Static Lifetimes

Because any struct or class in C++ can have constructors or destructors, and you can put structs or classes anywhere in a C++ program, this means that there are rules for how to safely invoke constructors and destructors in all possible cases. These different possible lifetimes have different names. Global variables, or static variables inside classes, have what’s called “static lifetime”, which means their lifetime begins when the program starts and ends once the program exits. The exact order these constructors are called, however, is a bit tricky. Let’s look at an example:

struct Foo
{
  // Default constructor for Foo
  Foo()
  {
    a = new int();
  }
  // Destructor frees memory we allocated using delete
  ~Foo()
  {
    delete a;
  }
  
  int* a;
  static Foo instance;
};

static Foo GlobalFoo;

int main()
{
  *GlobalFoo.a = 3;
  *Foo::instance.a = *GlobalFoo.a;
  return *Foo::instance.a;
}
When is instance constructed? When is GlobalFoo constructed? Can we safely assign to GlobalFoo.a immediately? The answer is that all static lifetimes are constructed before your program even starts, or more specifically, before main() is called. Thus, by the time your program has reached your entry point (main()), C++ gaurantees that all static lifetime objects have already been constructed. But what order are they constructed in? This gets complicated. Basically, static variables are constructed in the order they are declared in a single .cpp file. However, the order these .cpp files are constructed in is undefined. So, you can have static variables that rely on each other inside a single .cpp file, but never between different files.

Likewise, all static lifetime objects get deconstructed after your main() function returns, and once again, this order is random, although it should be in the reverse order they were constructed in. Technically this should be respected even if an exception occurs, but because the compiler can assume the process will terminate immediately after an unhandled exception occurs, this is unreliable.

Static lifetimes still apply for shared libraries, and are constructed the moment the library is loaded into memory - that’s LoadLibrary on Windows and dlopen on Linux. Most kernels provide a custom function that fires when the shared library is loaded or unloaded, and these functions fall outside of the C++ standard, so there’s no gaurantee about whether the static constructors have actually been called when you’re inside the DllLoad, but almost nobody actually needs to worry about those edge cases, so for any normal code, by the time any function in your DLL can be called by another program, you can rest assured all static and global variables have had their constructors called. Likewise, they are destructed when the shared library is unloaded from memory.

While we’re here, there are a few gotchas in the previous example that junior programmers should know about. You’ll notice that I did not write static Foo* = new GlobalFoo(); - this will leak memory!. In this case, C++ doesn’t actually call the destructor because Foo doesn’t have a static lifetime, the pointer it’s stored in does!. So the pointer will get it’s constructor called before the program starts (which does nothing, because it’s a primitive), and then the pointer will have it’s destructor called after main() returns, which also does nothing, which means Foo never actually gets deconstructed or deallocated. Always remember that C++ is extremely picky about what you do. C++ won’t magically extend Foo’s lifetime to the lifetime of the pointer, it will instead do exactly what you told it to do, which is to declare a global pointer primitive.

Another thing to avoid is to not accidentally write Foo::instance.a = GlobalFoo.a;, because this doesn’t copy the integer, it copies the pointer from GlobalFoo to Foo::instance. This is extremely bad, because now Foo::instance will leak it’s pointer and instead try to free GlobalFoo’s pointer, which was already deleted by GlobalFoo, so the program will crash, but only AFTER successfully returning 3. In fact, it will crash outside of the main() function completely, which is going to look very weird if you don’t know what’s going on.

Implicit Constructors and Temporary Lifetimes

Lifetimes in C++ can get complicated, because they don’t just apply to function blocks, but also function parameters, return values, and expressions. This means that, for example, if we are calling a function, and we construct a new object inside the function call, there is an implicit lifetime that exists for the duration of the function call, which is well-defined but very weird unless you’re aware of exactly what’s going on. Let’s look at a simple example of a function call that constructs an object:

class Foo
{
  // Implicit constructor for Foo
  Foo(int b)
  {
    a = b;
  }
  // Empty Destructor for Foo
  ~Foo() {}
  
  int a;
}

int get(Foo foo)
{
  return foo.a;
}

int main()
{
  return get(3);
}
To understand what’s going on here, we need to understand implicit constructors, which are a “feature” of C++ you never wanted but got anyway. In C++, all constructors that take exactly 1 argument are implicit, which means the compiler will attempt to use call them to satisfy a type transformation. In this case, we are trying to pass 3 into the get() function. 3 has the type int, but get() takes an argument of type Foo. Normally, this would just cause an error, because the types don’t match. But because we have a constructor for Foo that takes an int, the compiler actually calls it for us, constructing an object of type Foo and passing it into the function! Here’s what it looks like if we do this ourselves:
int main()
{
  return get(Foo(3));
}
C++ has “helpfully” inserted this constructor for us inside the function call. So, now that we know our Foo object is being constructed inside the function call, we can ask a different question: When does the constructor get called, exactly? When is it destructed? The answer is that all the expressions in your function call are evaluated first, from left-to-right. Our expression allocated a new temporary Foo object by pushing it onto the stack and then calling the constructor. However, do be aware that compilers aren’t always so great about respecting initialization order in function calls or other initialization lists. But, ostensibly, they’re supposed to be evaluated from left-to-right.

So, once all expressions inside the parameteres have been evaluated, we then push the parameters on to the stack and copy the results of the expressions into them, allocate space on the stack for the return value, and then we enter the function. Our function executes, copies a return value into the space we reserved, finishes cleaning up, and returns. Then we do something with the return value and pop our parameters off the stack. Finally, after all the function parameter boilerplate has been finished, our expressions go out of scope in reverse order. This means that destructors are called from right-to-left after the function returns. This is all roughly equivilent to doing this:

int main()
{
  int b;
  {
    Foo a = Foo(3); // Construct Foo
    b = get(a); // Call function and copy result
  } // Deconstruct Foo
  return b;
}
This same logic works for all expressions - if you construct a temporary object inside an expression, it exists for the duration of the expression. However, the exact order that C++ evaluates expressions is extremely complicated and not always defined, so this is a bit harder to nail down. Generally speaking, an object gets constructed right before it’s needed to evaluate the expression, and gets deconstructed afterwards. These are “temporary lifetimes”, because the object only briefly exists inside the expression, and is deconstructed once the expression is evaluated. Because C++ expressions are not always ordered, you should not attempt to rely on any sort of constructor order for arbitrary expressions. As an example, we can inline our previous get() function:
int main()
{
  return Foo(3).a;
}
This will allocate a temporary object of type Foo, construct it with 3, copy out the value from a, and then deconstruct the temporary object before the return statement is evaluated. For the most part, you can just assume your objects get constructed before the expression happens and get destructed after it happens - try not to rely on ordering more specific than that. The specific ordering rules are also changing in C++20 to make it more strict, which means how strict the ordering is will depend on what compiler you’re using until everyone implements the standard properly.

For the record, if you don’t want C++ “helpfully” turning your constructors into implicit ones, you can use the explicit keyword to disable that behavior:

struct Foo
{
  explicit Foo(int b)
  {
    a = b;
  }
  ~Foo() {}
  
  int a;
};

Static Variables and Thread Local Lifetimes

Static variables inside a function (not a struct!) operate by completely different rules, because this is C++ and consistency is for the weak.

struct Foo
{
  explicit Foo(int b)
  {
    a = b;
  }
  ~Foo() {}
  
  int a;
};

int get()
{
  static Foo foo(3);
  
  return foo.a;
}

int main()
{
  return get() + get();
}
When is foo constructed? It’s not when the program starts - it’s actually only constructed the first time the function gets called. C++ injects some magic code that stores a global flag saying whether or not the static variable has been initialized yet. The first time we call get(), it will be false, so the constructor is called and the flag is set to true. The second time, the flag is true, so the constructor isn’t called. So when does it get destructed? After main() returns and the program is exiting, just like global variables!

Now, this static initialization is gauranteed to be thread-safe, but that’s only useful if you intend to share the value through multiple threads, which usually doesn’t work very well, because only the initialization is thread-safe, not accessing the variable. C++ has introduced a new lifetime called thread_local which is even weirder. Thread-local static variables only exist for the duration of the thread they belong to. So, if you have a thread-local static variable in a function, it’s constructed the first time you call the function on a per-thread basis, and destroyed when each thread exits, not the program. This means you are gauranteed to have a unique instance of that static variable for each thread, which can be useful in certain concurrency situations.

I’m not going to spend any more time on thread_local because to understand it you really need to know how C++ concurrency works, which is out of scope for this blog post. Instead, let’s take a brief look at Move Semantics.

Move Semantics

Let’s look at C++’s smart pointer implementation, unique_ptr<>.

int get(int* b)
{
  return *b;
}

int main()
{
  std::unique_ptr<int> p(new int());
  *p = 3;
  int a = get(p.get());
  return a;
}
Here, we allocate a new integer on the heap by calling new, then store it in unique_ptr. This ensures that when our function returns, our integer gets freed and we don’t leak memory. However, the lifetime of our pointer is actually excessively long - we don’t need our integer pointer after we’ve extracted the value inside get(). What if we could change the lifetime of our pointer? The actual lifetime that we want is this:
int get(int* b)
{
  return *b;
  // We want the lifetime to end here
}

int main()
{
  // Lifetime starts here
  std::unique_ptr<int> p(new int());
  *p = 3;
  int a = get(p.get());
  return a;
  // Lifetime ends here
}
We can accomplish this by using move semantics:
int get(std::unique_ptr<int>&& b)
{
  return *b;
  // Lifetime of our pointer ends here
}

int main()
{
  // Lifetime of our pointer starts here
  std::unique_ptr<int> p(new int());
  *p                = 3;
  int a             = get(std::move(p));
  return a;
  // Lifetime of p ends here, but p is now empty
}
By using std::move, we transfer ownership of our unique_ptr to the function parameter. Now the get() function owns our integer pointer, so as long as we don’t move it around again, it will go out of scope once get() returns, which will delete it. Our previous unique_ptr variable p is now empty, and when it goes out of scope, nothing happens, because it gave up ownership of the pointer it contained. This is how you can implement automatic memory management in C++ without needing to use a garbage collector, and Rust actually uses a more sophisticated version of this built into the compiler.

Move semantics can get very complex and have a lot of rules surrounding how temporary values work, but we’re not going to get into all that right now. I also haven’t gone into the many different ways that constructors can be invoked, and how those constructors interact with the different ways you can initialize objects. Hopefully, however, you now have a grasp of what lifetimes are in C++, which is a good jumping off point for learning about more advanced concepts.


[1] Pedantic assembly-code analysts will remind us that the stack allocations usually happen exactly once, at the beginning of the function, and then are popped off at the very end of the function, but the standard technically doesn’t even require a stack to exist in the first place, so we’re really talking about pushing and popping off the abstract stack concept that the language uses, not what the actual compiled assembly code really does.

[2] We’re dereferencing the pointer here because we want to return the value of the pointer, not the pointer itself! If you tried to return the pointer itself from the function, it would point to freed memory and crash after the function returned. Trying to return pointers from functions is a common mistake, so be careful if you find yourself returning a pointer to something. It’s better to use unique_ptr to manage lifetimes of pointers for you.

There’s been a lot of hand-wringing over The Technical Interview lately. Many people realize that inverting a binary tree on a whiteboard has basically zero correlation to whether or not someone is actually a good software developer. The most effective programming test anyone’s come up with is still Fizzbuzz. One consequence of this has been an increased emphasis on Open Source Contributions, but it turns out these aren’t a very good metric either, because most people don’t have that kind of time.

The most effective programming interview we have now is usually some kind of take-home project, where a candidate is asked to fix a bug or implement a small feature within a few days. This isn’t great because it takes up a lot of time, and they could recieve outside help (or, if the feature is sufficiently common, google it). On the other hand, some large companies have instead doubled-down on whiteboard style interviews by subjecting prospective engineers to multiple hour-long online coding assessments, with varying levels of invasive surveillience.

All these interviewing methods pale in comparison to a very simple metric: playing Factorio with someone. Going through an entire run of Factorio is almost the best possible indication of how well someone deals with common technical problems. You can even tweak the playthrough based on the seniority of the position you’re hiring for to get a better sense of how they’ll function in that role.

Factorio?

Factorio is a game about automation. The best introduction is probably this trailer, but in essence, your job is to build an automated factory capable of launching a rocket into space.

You begin with nothing. You mine stone manually to craft a smelter that can smelt iron ore you mined into iron plates, which you then use to build a coal-driven automatic miner. You could grab the iron ore from the miner and put it in the smelter yourself, but it’s more efficient to use an inserter to do the inserting for you. Then you can use the iron this gives you to make another miner, which automates coal mining. Then you can use belts to take the coal and use an inserter to put it in the iron miner. Then you use the iron plates this tiny factory produces to make a third miner to start gathering copper, which then lets you craft copper wire, which lets you craft a circuit, which lets you build a water pump. Combined with a boiler and a steam engine, you can then build produce power, and use this power to run a research facility to unlock new technology, like assembly machines. Once you’ve unlocked assembly machines, you can use your circuits to craft an assembly machine that can craft copper wire for you, and insert this into an assembly machine that crafts circuits for you.

Eventually you unlock trains and robots and logistic systems which help you deal with the increasing logistic complexity the game demands, until you finally manage to launch a rocket into space.

Self-Direction

The beginning of the game starts with no goals and barely any direction. A senior developer should be able to explore the UI and figure out a goal, then establish a plan for accomplishing that goal. A junior developer should be able to perform a task that a senior developer has provided for them. An intern is expected to require quite a bit of mentoring, but a junior developer should be able to troubleshoot basic problems with their own code before requiring assistance from the senior developer. An intermediate developer should be able to operate independently once given a task, but is not expected to do any architecture design.

In more concrete terms, you might expect the following:

  • An Intern is generally expected to be able to fill in a pre-placed blueprint, and use belts to hook up their blueprint with something else, like an ore patch.
  • A Junior Developer should be able to build a production line by themselves, although it probably won’t be very optimal. They may need assistance from the senior developer on how to route the belts properly to all of the intermediate assembly machines.
  • An Intermediate Developer should be capable of designing a near-optimal production line (without beacons) once given direction, with minimal oversight.
  • The Senior Developer needs no direction, and is capable of determining what goals need to happen and designing a plan of action, then delegating these tasks to other coders.

Teamwork

A critical aspect of software development is the ability to work on a team. This means coordinating your efforts with other people, accomadating the needs of other people’s designs and cooperating with the team, instead of simply running off on your own and refusing to adjust your design to help integrate it with someone else’s work. This, naturally, arises all the time in Factorio, because base layout designs are limited by physical space. As a result, you need to carefully consider what other people are doing, and sometimes adjust your design to fit in size constraints or deal with someone else’s design that took more room than anticipated.

Anyone who simply runs off and starts doing things themselves or fixing problems without telling people is going to quickly earn the ire of their fellow players, for the exact same reasons cowboy programmers do. Luckily, Factorio includes a built-in equivelent to git blame, by showing you the last player that modified any entity. Thus, when people duct tape temporary solutions and don’t inform the team about the problem they were fixing, when their temporary solution finally blows up, people will find out. If people want to win they game, they’ll have to learn to cooperate well with their teammates.

Debugging

One of the most important skills for any programmer is their ability to debug problems. This is perhaps the most obvious parallel between Factorio and real software engineering. Something can go wrong very far away from the actual source of the problem. Being able to rapidly hone in on the real problem is a critical skill, and the thinking process is almost identical to tracing the cause of a crash in an actual program. If an assembly machine has stopped working, first you have to see if there are multiple outputs that got backed up. Then you have to check what ingredient it’s missing. Then you have to trace the ingredient back through your factory to find out where you’re making it, and repeat ad nauseum.

Factorio’s debugging gets fairly complicated quite quickly. As soon as you start working on oil processing you’ll be dealing with cracking, where you’re dealing with 3 different outputs and if any of them get backed up for any reason, the entire thing stops. There are cases where your entire factory can grind to a halt because you started researching something that doesn’t require yellow science, which stopped using up robot frames, which stopped using up electric engines, which stopped using lubricant, which stopped consuming heavy oil, which backed up and stopped oil production, which made you run out of petroleum, which broke plastic, which broke red circuits, which broke the rest of the factory. Seasoned players will anticipate scenarios like this and use circuits to construct self-balancing oil cracking to ensure the system is balanced and will only back up if petroleum backs up. A new player who is a good programmer, when presented with a factory that has collapsed, will usually be able to trace the issue back to the source, realize what’s happened, and promptly attempt to figure out a solution. On the other hand, if someone simply plops down a few storage tanks, unless they can provide a good reason (they are very confident we will never stop consuming lubricant in the future), then this is a red flag for how they approach problem solving in their programs.

Situations like these allow Factorio to closely mimic the complex interdependencies that programmers routinely deal with, and the complexity simply increases the more gameplay concepts are added. This closely follows the increased complexity that additional layers of abstraction introduce when attempting to debug a crash that could have potentially occured deep inside one of the frameworks you use.

Code Reviews

Often, initial designs need to be tweaked for performance or throughput. Good programmers will not only accept critique of their designs, but incorporate that feedback into their future work. If they disagree with a proposed change, they will provide a concrete reason for why they disagree so that the team can more accurately weigh the pros and cons of the proposed change.

Resisting feedback without providing good reasons is a well-known red flag, but what can also be problematic is a programmer who begrudgingly accepts proposed changes, but refuses to adjust future designs accordingly. They end up requiring constant reminders to adhere to some standard way of solving a problem while giving no reason for why they don’t seem to like the way the team is doing things. These can be ticking time-bombs in organizations, because when left unsupervised they can rapidly accumulate technical debt for other team members. This kind of problem is almost impossible to catch in a traditional interview, unless it’s an internship.

Code Style and Frameworks

Refusing to incorporate feedback is often just a slice of a much larger problem, where someone is unable to integrate properly into an existing framework being used. There are many ways to build a factory in Factorio, and each one requires standard methods of building pieces. Failing to adhere to standards can very quickly jam up an entire factory, often in subtle ways that aren’t necessarily obvious to a careless developer.

In the Main Belt design, a set of 4-8 chunk of belts, divided by 2 spaces to allow for underground belts, are placed in the center of the factory, and all production happens perpendicular to the belt. This design relies on several rules that can wreck havoc if not followed correctly. One, players must always use a splitter to pull items off of a belt, never redirecting the entire belt, otherwise using the empty space for a different belt of items means you’ll have permanently lost one entire belt of resources, even after upgrading belts. Two, all factories must be scalable in a direction perpendicular to the main belt. Failing to do this will rapidly result in either a massive waste of space, or a production line that cannot be scaled up because it’s surrounded by other production lines.

There are also different ways of building logistic networks. The simplest method is with passive provider chests, but another method uses a storage chest with a filter, which is used to solve the trashed item problem. Both of these methods require properly setting limiters in the right location. Passive provider chests generally are limited by chest space. Storage chests require hooking the inserter for the chest up to the logistics network and ensuring that less than N of an item exists before inserting it. Forgetting to perform these limiting steps is a massive waste of resources. Consistently forgetting to put limiters on outputs is a red flag for someone who is careless about performance in real-world applications.

In other cases, the team may be using some pre-designed blueprints, like a nuclear reactor design, or a bot factory. These can be extremely complex, but as long as people are willing to learn how to use them, they can be huge time-savers. Beware of candidates who don’t want to learn how to set up a new item in the bot factory simply because they can’t debug the complex logic that drives it, or ones that get frustrated learning how to use a bot factory despite the clear and obvious benefits.

Multithreading

Trains in Factorio are a direct analogue to multithreading: one train is one thread of execution, and each train intersection or train stop is a place in memory where two threads could potentially write at the same time. Train signals are locks, or mutexes. All bugs in train networks manifest in exactly the same way software race conditions do, because they’re literally physical race conditions. All of the tradeoffs apply here as well - if you make a lock too large, it slows down your throughput, because now the intersection is blocked for a longer period of time. Incorrectly signaled tracks routinely cause train deadlocks that are exactly the same as a software deadlock, because you end up with a circular lock dependency. The most common deadlock is when a train is too long and unexpectedly blocks a second intersection while waiting to enter one. This second intersection then prevents another train from leaving, preventing the first intersection from ever being unblocked.

The number of lanes of track in your network is equivilent to the number of cores available in your CPU. A single rail line is difficult to scale beyond a few threads because the entire system gets throughput limited very quickly, even with wait areas. The most common design is a two-lane design where each lane is a single direction, but this will eventually suffer from throughput issues when you need trains constantly being unloaded. Thus, large bases tend to have at least 4 lanes, with two outer lanes acting as bypasses to avoid the intersection whenever possible.

Missing signal problems in these systems can take a ridiculous amount of time to actually show up. A single missing signal in one rail network once caused a deadlock after functioning correctly for two weeks. This is remniscient of difficult to pin down race conditions in software that only occur once a month or so when under high contention.

Scaling

Just like in software, scaling up production in Factorio introduces new problems with initial designs, and often require complete redesigns that can pipe resources into factories as fast as possible, while taking advange of production modules and speed module beacons. Belt limits become problematic even at the fastest belt speed, forcing players to find ways to split designs up so that more belts can be put in later down the line, or split up their factories into modules.

Handling your logistics network itself becomes a logistics problem in the late game because of how problematic expansive bot networks are. You generally need to start segmenting the logistics network and either using trains to transport items between them, or build a requester chest/provider chest that propagates items across bounderies.

Managing trains in the late game necessitates switching to a pull architecture from a push architecture, because the push architecture can’t function in high throughput. This inevitably requires taking advantage of the Train Limits feature and learning how circuit networks can be used to encode basic logic, such that a station only requests a train when it is actually ready to completely fill the train with resources, instead of the common early game tactic of simply telling a bunch of trains to go to stations named “Iron Pickup”. This minimizes the number of trains you need while making sure all stops are served on the network.

Often times, limitations in the number of possible inputs to an assembly machine and inserter speed require redesigning factories around them, just like how high-speed computing requires being aware of subtle bottlenecks in how your CPU works. These bottlenecks are almost never a problem until you reach a certain scale, at which point they begin to dominate your efficiency.

Microservices and Plugin Architectures

Eventually, factories get so enormous they must abandon a simple main belt or spaghetti design and use a more scalable framework instead. To reach Megabase-scale, factories generally either use a train system or a module system, which corresponds roughly to microservices or a plugin-architecture.

A train-based megabase is sometimes referred to a “city-block” design, where trains surrounded factory blocks and control all input and output. Thus, each individual city-block is isolated from all other city-blocks, since all their input is “pure” in that it comes from the train network. This is almost identical to a micro-services architecture (over HTTP) or a multi-process design (using IPC), and has similar potential issues with input and output latency, because results cannot be continually provided, they must be emitted in “packets”, or trains along the network.

The plugin architecture seeks to maintain some semblence of a main-belt, but instead splits belts off through the factory and uses modular blocks that take standard inputs and standard outputs. Sometimes this can be achieved entirely through bots, but materials usually need to be belted over long distances. This closely resembles a plugin system for a monolithic application, and has similar tradeoffs.

These megabases mark the extreme upper end of a vanilla Factorio server. However, there are plenty of mods to make things much more complex.

Distributed Systems

Space Exploration is an overhaul of Factorio that adds an entire space segment of the game, and makes planets have limited resources, requiring players to colonize other planets and use rockets to transfer resources between planets. Because of the enormous latency involved with shipping materials between planets, coordinating these different bases winds up having similar problems to a globally distributed database system. Even the circuit network has to contend with latency, because an automatic request system loses track of items that have been launched but haven’t yet reached the target planet. Not accounting for this will result in a double-request for all the items you wanted, which is the exact same problem that distributed systems have when trying to ensure consistency.

Conclusion

Collectively, the software industry simply has no idea how to hire software developers. Factorio is probably the best technical interview we have right now, and that’s embarassing. It is also wildly impractical, taking over 20 hours in an initial multiplayer playthrough, or 8 hours if you have a lot of people and know what you’re doing. What’s the takeaway from this? I don’t know. We certainly can’t switch to using Factorio as an interviewing method - you might as well just give a candidate a take-home assignment.

At the very least, we can do better than whiteboard interviews.

C++17 introduced an alignment argument to ::operator new(). It’s important to note that if you allocate something using aligned new, you absolutely must deallocate it using aligned delete, or the behavior is undefined. LLVM 10.x takes advantage of this alignment parameter, if the compiler supports it. That means if you are compiling on Windows with MSVC set to C++14, __cpp_aligned_new is not defined and the extra argument isn’t passed. Otherwise, if it’s compiled with MSVC set to C++17, __cpp_aligned_new is defined and the extra argument is passed.

There’s just one teeny tiny little problem - the check was in a header file.

Now, if this header file were completely internal and LLVM itself only ever called ::operator new() from inside it’s libraries, this wouldn’t be a problem. As you might have guessed, this was not the case. LLVM was calling allocate_buffer() from inside header files. The corresponding deallocate_buffer call was inside the same header file, but sadly, it was called from a destructor, and that destructor had been called from inside one of LLVM’s libraries, which meant it didn’t know about aligned allocations… Oops!

This means, if your program uses C++17, but LLVM was compiled with C++14, your program will happily pass LLVM aligned memory, which LLVM will then pass into the wrong delete operator, because it’s calling the unaligned delete function from C++14 instead of the aligned delete function from C++17. This results in strange and bizarre heap corruption errors because of the mismatched ::operator new and ::operator delete. Arguably, the real bug here is LLVM calling any allocation function from a header file in the first place, as this is just begging for ABI problems.

Of course, one might ask why a C++17 application would be linking against LLVM compiled with C++14. Well, you see, the prebuilt LLVM binaries were compiled against C++14… OOPS! Suddenly if you wanted to avoid compiling LLVM yourself, you couldn’t use C++17 anymore!

Luckily this has now been fixed after a bunch of people complained about the extremely unintuitive errors resulting from this mismatch. Unfortunately, as of this writing, LLVM still hasn’t provided a new release, which means you will still encounter this problem using the latest precompiled binaries of LLVM. Personally, I recompile LLVM using C++17 for my own projects, just to be safe, since LLVM does not gaurantee ABI compatibility in these situations.

Still, this is a particularly nasty case of an unintentional ABI break between C++ versions, which is easy to miss because most people assume C++ versions are backwards compatible. Be careful, and stop allocating memory in header files that might be deallocated inside your library!

Today, in response to a tweet talking about old untitled song ideas, I mentioned that I had a strange file called “t.mp3” sitting in my downloads folder that had been there for years and have no attached metadata or hint as to where it came from. It appeared to be a complete recording of a chiptune song, and it sounded very nice, but I had no way of knowing the original source. To my surprise, someone else had heard the song and hunted down a source on youtube: S0 C1os3 - H4X0r.

But something was wrong. That video was uploaded in 2019. The file I had was last modified in January 2010, over 10 years ago, and for that matter it had been sitting in my downloads folder for almost as long. Perhaps the artist simply hadn’t uploaded it to YouTube until recently? I decided to scroll through the comments, and discovered that someone posted the real name of the track: “So Close” by Floppi. I was even able to find the original XM file, and sure enough, it had been uploaded way back in 2003.

Now, some random person uploading an old song on youtube and trying to take credit isn’t really that surprising, but this Youtube channel is special - it’s a Topic channel, which is autogenerated from the Google Play Store. It even says in the description, “Provided to YouTube by DistroKid”. DistroKid is a music distribution service that automatically registers and uploads your album to all the major online music stores. I’ve used a similar service for my own albums, and do in fact have my own autogenerated Topic channel on Youtube, which is… kind of creepy, but that’s besides the point.

The point is that someone has stolen 11 classic demoscene tracker songs and is selling them on every major online music store. The album is called “H4x0r R007z” and it consists entirely of blatantly stolen tracker songs lazily renamed using 1337 text, which usually means finding the original song is pretty easy. Because it was published via DistroKid, you can find it on Spotify, Google Play, iTunes, Amazon, Deezer, iHeartRadio and it’s been registered into the automatically populated copyrighted songs databases! That means the artist “H4x0r” could legally issue copyright takedowns for every other legitimate upload of the actual songs, or abuse Google’s automatic fingerprinting system to force monetization on all of the videos and take all the income.

The songs that were stolen were often used in keygen cracking software that was popular in the 2000s to pirate software. Many people have noted that this was often their first introduction to tracker music, and this is likely the source of the name “H4x0r R007z”, even though the songs themselves usually had nothing to do with the hacker groups. The original tracker files are still available in the scene archives, and other Youtube channels have uploaded MP3 recordings of the songs with proper attribution. I was able to source 9 out of the 11 songs from the album, with the real name and artist, plus a Youtube or Soundcloud recording (if you’d like to play the original files yourself, you can use XMPlay).

  1. 0 Pr1m4ry
    Real Name: “primary” by Ramosa
    Original file: ramosa-primary.mod
    Only exists on the H4x0r channel
  2. 5murf-E5Que
    Real Name: “Smurf-Esque ‘98” by AGAiN
    Author Info: Made with FastTracker 2 by Three Little Elks (3LE): Android (Jonas Kapla) Ant (Anton Halldin), Coma (Daniel Johansson), Nude (Sten Ulfsson), Tabasco (Niklas Soerensson)
    Original file: smurf-es.mod
    Youtube
  3. Vib35 F20m Pa57
    Real Name: “Vibes From Past” by Fegolhuzz (Figge Wasberger)
    Original file: fegolhuzz_-_vibes_from_past.xm
    SoundCloud
  4. Bra1n Wound
    Real Name: “Brain Wound” by Ghidorah
    Original file: bw.xm
    Youtube
  5. Hy8r1d 50n9
    Real Name: “Funky Stars (Hybrid Song)” by Quazar (Axel Christofer Hedfors)
    Author Info: Quazar is an old alias of Axwell, one of the members of the Swedish House Mafia.
    Original file: external.xm
    Youtube
  6. D0d3ch3dr0n
    I was unable to source this song, possibly because the original song name was a mispelling of Dodecahedron
  7. 51ne-15te2
    Real Name: “Sine-ister” by dreamfish
    Original file: sineiste.mod
    Youtube (Some recordings seem to have more clarity than XMPlay provides, but it’s not clear if this was intended)
  8. Au70ma71k
    Real Name: “Automatik” by Rez
    Original file: rez-automatik.mod
    Youtube
  9. S3rV1l
    I was also unable to source this song, possibly due to spelling errors.
  10. S0 C1os3
    Real Name: “So Close” by Floppi (Tero Laihanen)
    Original file: intro13.xm
    Youtube
  11. 5or3 Po1nt
    Real Name: “Sore Point”
    Author Information: The original author of this song is unknown, although it was converted to .xm format for Infinitode 2. It was featured in several keygens made by AiR.
    Original file: Unknown. Various conversions to other formats are available.
    Youtube

Back when Discord was a wee little chat platform with no rate limiting whatsoever, it’s API had already been reverse-engineered by a bunch of bot developers who then went around spamming random servers with so many messages it would crash the client. My friends and I were determined to keep our discord server public, so I went about creating the first anti-spam bot for Discord.

I am no longer maintaining this bot beyond simple bugfixes because I have better things to do with my time, and I’m tired of people trying to use it because “it’s the best anti-spam bot” even after I deprecated it. This post is an effort to educate all the other anti-spam bots on how to ascend beyond a simple “mute someone if they send more than N messages in M seconds” filter and hopefully make better anti-spam bots so I don’t have to.

Architecture

There are disagreements over exactly how an anti-spam bot should work, with a wide-range of preferred behaviors that differ between servers, depending on the community, size of the server, rate of growth of the server, and the administrators personal preferences. Many anti-spam solutions lock down the server by forcing new members to go through an airlock channel, but I consider this overkill and the result of poor anti-spam bots that are bad at actually stopping trolls or responding to raids.

My moderation architecture goes like this:

-- Channels --  
#Moderation Channel  
#Raid Containment  
#Silence Containment  
#Log Channel

-- Roles --  
@Member  
@Silence  
@New

When first-time setup is run on a server, the bot queries and stores all the permissions given to the @everyone role. It adds all these permissions to the @Member role, then goes through all existing users and adds the @Member role to them. It then removes all permissions from @everyone, but adds an override for #Raid Containment so that anyone without the @Member role can only speak in #Raid Containment.

Then, it creates the @Silence role by adding permission overrides to every single channel on the server that prevent you from sending messages on that channel, except for the #Silence Containment channel. This ensures that, no matter what new roles might be added in the future, @Silence will always prevent you from sending messages on any channel other than #Silence Containment. The admins of the server can configure the visibility of the containment channels. Most servers make it so #Raid Containment is only visible to anyone without the @Member role, ensure #Silence Containment is only visible to anyone with the @Silence role, and hide #Log Channel from everyone except admins.

This architecture was chosen to allow the bot to survive a mega-raid, so that even if 500+ bot accounts storm the server all at once, if the bot goes down or is rate-limited, they can’t do anything because they haven’t been given the @Member role, and so the server is protected by default. This is essentially an automated airlock that only engages if the bot detects a raid, instead of forcing all new members to go through the airlock. Some admins do not like this approach because they prefer to personally audit every new member, but this is not viable for larger servers.

The @Member role being added can also short-circuit Discord’s own verification rules, which is an unfortunate consequence, but in practice it usually isn’t a problem. However, to help compensate for this, the bot can also be configured to add a temporary @New role to newer users that expires after a configurable amount of time. What this role actually does is up to the administrators - usually it simply disables sharing images or embeds.

Operation

The bot has two distinct modes of operation. Under normal operation, when a new member joins the server, they are automatically given @Member (and @New if it’s been enabled) and are immediately allowed to speak. If they trigger the anti-spam, or a moderator uses the !silence command, they will have the @Silence role added, any messages sent in the last 5 seconds (by default) will be deleted, and they’ll be restricted to speaking in #Silence Containment. By default, silences that happen automatically are never rescinded until a moderator manually unsilences someone. However, some server admins are lazy, so an automatic expiration can be added. A manual silence can also be configured to expire after a set period of time. If a user triggers the anti-spam filter again while they are in the containment channel, then the bot will automatically ban them.

It’s important to note that when silenced, users have both the @Member and the @Silence role. The reason is because many servers have opt-in channels that are only accessible if you add a role to yourself. Simply removing @Member would not suffice to keep them from talking in these channels, but @Silence can override these permissions and ensure they can’t speak in any channel without having to mess up anyone’s assigned roles.

The bot detects a raid if N joins happen within M seconds. It’s usually configured to be something like 3 joins in a 90 second interval for an active server. When this happens, the server enters raid mode, which automatically removes @Member from all the users that just triggered the raid alert. It sends a message pinging the moderators in #Moderator Channel and stops adding @Member to anyone who joins while it is still in raid mode. It also changes the server verification level, which actually does have an effect for the newly joined members, because they haven’t had any roles assigned to them yet. Moderators can either cancel the raid alert, which automatically adds @Member to everyone who was detected as part of the raid alert, or they can individually add @Member to people they have vetted. The raid mode automatically ends after M*2 seconds, which would be 180 in this example. A moderator can use a command to ban everyone who joined during the raid alert, or they can selectively add @Member to users who should be let in.

This method of dealing with raids ensures that the bot cannot be overwhelmed by the sheer number of joins. If it crashes or is taken down, the server stays in raid mode until the bot can recover, and the potential raiders will not be allowed in.

Pressure System

All the anti-spam logic in the bot is done by triggering an automatic silence, which gives someone the @Silence role. The bot determines when to silence someone by analyzing all the messages being sent using a pressure system. In essence, the pressure system is analogous to the gravity function used for calculating the “hotness” of a given post on a site like Hacker News.

Each message a user sends is assigned a “pressure score”. This is calculated from the message length, contents, whether it matches a filter, how many newlines it has, etc. This “pressure” is designed to simulate how disruptive the message is to the current chat. A wall of text is extremely disruptive, whereas saying “hi” probably isn’t. Attaching 3 images to your message is very disruptive, but embedding a single link isn’t that bad. Sending a blank message with 2000 newlines is incredibly disruptive, whereas sending a message with two paragraphs is probably fine. In addition, all messages are assigned a base pressure, the minimum amount of pressure that any message will have, even if it’s only a single letter.

My bot looks at the following values:

  • Max Pressure: The default maximum pressure is 60.
  • Base Pressure: All messages generate 10 pressure by default, so at most 6 messages can be sent at once.
  • Embed Pressure: Each image, link, or attachment in a message generates 8.3 additional pressure, which limits users to 5 images or links in a single message.
  • Length Pressure: Each individual character in a message generates 0.00625 additional pressure, which limits you to sending 2 maximum length messages at once.
  • Line Pressure: Each newline in a message generates 0.714 additional pressure, which limits you to 70 newlines in a single message.
  • Ping Pressure: Every single unique ping in a message generates 2.5 additional pressure, which limits users to 20 pings in a single message.
  • Repeat Pressure: If the message being sent is the exact same as the previous message sent by this user (copy+pasted), it generates 10 additional pressure, effectively doubling the base pressure cost for the message. This means a user copy and pasting the same message more than twice in rapid succession will be silenced.
  • Filter Pressure: Any filter set by the admins can add an arbitrary amount of additional pressure if a message triggers that filter regex. The amount is user-configurable.

And here a simplified version of my implementation. Note that I am adding the pressure piecewise, so that I can alert the moderators and tell them exactly which pressure trigger broke the limit, which helps moderators tell if someone just posted too many pictures at once, or was spamming the same message over and over:

if w.AddPressure(info, m, track, info.Config.Spam.BasePressure) {
	return true
}
if w.AddPressure(info, m, track, info.Config.Spam.EmbedPressure*float32(len(m.Attachments))) {
	return true
}
if w.AddPressure(info, m, track, info.Config.Spam.EmbedPressure*float32(len(m.Embeds))) {
	return true
}
if w.AddPressure(info, m, track, info.Config.Spam.LengthPressure*float32(len(m.Content))) {
	return true
}
if w.AddPressure(info, m, track, info.Config.Spam.LinePressure*float32(strings.Count(m.Content, "\n"))) {
	return true
}
if w.AddPressure(info, m, track, info.Config.Spam.PingPressure*float32(len(m.Mentions))) {
	return true
}
if len(m.Content) > 0 && m.Content == track.lastcache {
	if w.AddPressure(info, m, track, info.Config.Spam.RepeatPressure) {
		return true
	}
}
Once we’ve calculated how disruptive a given message is, we can add it to the user’s total pressure score, which is a measure of how disruptive a user is currently being. However, we need to recognize that sending a wall of text every 10 minutes probably isn’t an issue, but sending 10 short messages saying “ROFLCOPTER” in 10 seconds is definitely spamming. So, before we add the message pressure to the user’s pressure, we check how long it’s been since that user last sent a message, and decrease their pressure accordingly. If it’s only been a second, the pressure shouldn’t decrease very much, but if it’s been 3 minutes or so, any pressure they used to have should probably be gone by now. Most heat algorithms do this non-linearly, but my experiments showed that a linear drop-off tends to produce better results (and is simpler to implement).

My bot implements this by simply decreasing the amount of pressure a user has by a set amount for every N seconds. So if it’s been 2 seconds, they will lose 4 pressure, until it reaches zero. Here is the implementation for my bot, which is done before any pressure is added:

timestamp := bot.GetTimestamp(m)
track := w.TrackUser(author, timestamp)
last := track.lastmessage
track.lastmessage = timestamp.Unix()*1000 + int64(timestamp.Nanosecond()/1000000)
if track.lastmessage < last { // This can happen because discord has a bad habit of re-sending timestamps if anything so much as touches a message
	track.lastmessage = last
	return false // An invalid timestamp is never spam
}
interval := track.lastmessage - last

track.pressure -= info.Config.Spam.BasePressure * (float32(interval) / (info.Config.Spam.PressureDecay * 1000.0))
if track.pressure < 0 {
	track.pressure = 0
}
In essence, this entire system is a superset of the more simplistic “N messages in M seconds”. If you only use base pressure and maximum pressure, then these determine the absolute upper limit of how many messages can be send in a given time period, regardless of their content. You then tweak the rest of the pressure values to more quickly catch obvious instances of spamming. The maximum pressure can be altered on a per-channel basis, which allows meme channels to spam messages without triggering anti-spam. Here’s what a user’s pressure value looks like over time:

Pressure Graph

Because this whole pressure system is integrated into the Regex filtering module, servers can essentially create their own bad-word filters by assigning a huge pressure value to a certain match, which instantly creates a silence. These regexes can be used to look for other things that the bot doesn’t currently track, like all-caps messages, or for links to specific websites. The pressure system allows integrating all of these checks in a unified way that represents the total “disruptiveness” of an individual user’s behavior.

Worst Case Scenario

A special mention should go to the uncommon but possible worst-case scenario for spamming. This happens when a dedicated attacker really, really wants to fuck up your server for some reason. They can do this by creating 1000+ fake accounts with randomized names, and wait until they’ve all been on discord for long enough that the “new to discord” message doesn’t show up. Then, they have the bots join the server extremely slowly, at the pace of maybe 1 per hour. Then they wait another week or so, before they unleash a spam attack that has each account send exactly 1 message, followed by a different account sending another message.

If they do this fast enough, you can detect it simply by the sheer volume of messages being sent in the channel, and automatically put the channel in slow mode. However, in principle, it is completely impossible to automatically deal with this attack. Banning everyone who happens to be sending messages during the spam event will ban innocent bystanders, and if the individual accounts aren’t sending messages that fast (maybe one per second), this is indistinguishable from a normal rapid-fire conversation.

My bot has an emergency method for dealing with this where it tracks when a given user sent their first message in the server. You can then use a command to ban everyone who sent their first message in the past N seconds. This is very effective when it works, but it is trivial for spammers to get past once they realize what’s going on - all they need to do is have their fake accounts say “hi” once while they’re trickling in. Of course, a bunch of accounts all saying “hi” and then nothing else may raise enough suspicion to catch the attack before it happens.

Conclusion

Hopefully this article demonstrates how to make a reliable, extensible anti-spam bot that can deal with pretty much any imaginable spam attack. The code for my deprecated spam bot is available here for reference, but the code is terrible and most of it was a bad idea. You cannot add the bot itself to a server anymore, and the support channel is no longer accessible.

My hope is that someone can use these guidelines to build a much more effective anti-spam bot, and release me from my torment. I hate web development and I’d rather spend my time building a native webassembly compiler instead of worrying about weird intermittent cloudflare errors that temporarily break everything, or badly designed lock systems that deadlock under rare edge cases. Godspeed, bot developers.

I recently discovered that in Rust, this is a relatively common operation:

let foo = String::from("foo");
// stuff that needs ownership
let foo = &foo;  
Or this:
let mut vec = Vec::new();
vec.push("a");
vec.push("b");
let vec = vec; /* vec is immutable now */  
This is a particularly permissive form of name-shadowing, which allows you to re-declare a variable in an inner scope that shadows the name of a variable in an outer scope, making the outer variable inaccessible. Almost every single programming language in common use allows you to do this in some form or another. Rust goes a step further and lets you re-declare a variable inside the same scope as another variable.

This, to me, is pretty terrifying, because name-shadowing itself is often a dangerous operation. 90% of the time, name-shadowing causes problems with either temporary or index variables, such as i. These are all cases where almost you never want to name-shadow anything and doing so is probably a mistake.

for(int i = 0; i < width; ++i)
{
  for(int j = 0; j < height; ++j)
  {
    //
    // lots of unrelated code
    //
    
    float things[4] = {1,2,3,4};
    for(int i = 0; i < 4; ++i)
    	box[i][j] += things[i] // oops!
    //      ^ that is the wrong variable!
  }
}
These errors almost always crop up in complex for loop scenarios, which can obviously be avoided with iterators, but this isn’t always an option, espiecally in a lower-level systems programming language like Rust. Even newer languages like Go make it alarmingly easy to name-shadow, although they make it a lot harder to accidentally shoot yourself because unused variables are a compiler error:
foo, err := func()
if err != nil {
	err := bar(foo) // error: err is not used
}
println(err)
Unfortunately, Rust doesn’t have this error, only an unused-variables linter warning. If you want, you can add #![deny(clippy::shadow_unrelated)] to be warned about name-shadowing. However, a lot of Rust idioms depend on the ability to name-shadow, because Rust does a lot of type-reassignment, where the contents of a variable don’t change, but in a particular scope, the known type of the variable has changed to something more specific.
let foo = Some(5);
match foo {
    Some(foo) => println!("{}", foo),
    None => {},
}
Normally, in C++, I avoid name-shadowing at all costs, but this is partially because C++ shadowing rules are unpredictable or counter-intuitive. Rust, however, seems to have legitimate use cases for name-shadowing, which would be reasonable if name-shadowing could be made more explicit.

I doubt Rust would want to change it’s syntax, but if I were to work on a new language, I would define an explicit name-shadowing operator, either as a keyword or as an operator. This operator would redefine a variable as a new type and throw a compiler error if there is no existing variable to redefine. Attempting to redefine a variable without this operator would also throw a compiler error, so you’d have something like:

let foo = String::from("foo");
// stuff that needs ownership
foo := &foo;
Or alternatively:
let mut vec = Vec::new();
vec.push("a");
vec.push("b");
shadow vec = vec; /* vec is immutable now */
While the := operator is cleaner, the shadow keyword would be easier to embed in other constructions:
let foo = Some(5);
match foo {
    Some(shadow foo) => println!("{}", foo),
    None => {},
}
Which method would depend on the idiomatic constructions in the language syntax, but by making name-shadowing an explicit, rather than an implicit action, this allows you to get the benefits of name-shadowing while eliminating most of the dangerous situations it can create.

Unfortunately, most modern language design seems hostile to any feature that even slightly inconveniences a developer for the sake of code safety and reliability. Perhaps a new language in the future will take these lessons to heart, but in the meantime, people will continue complaining about unstable software, at least until we put the “engineer” back in “software engineering”.

Metaprogramming, or the ability to inspect, modify and generate code at compile-time (as opposed to reflection, which is runtime introspection of code), has slowly been gaining momentum. Programmers are finally admitting that, after accidentally inventing turing complete template systems, maybe we should just have proper first-class support for generating code. Rust has macros, Zig has built-in compile time expressions, Nim lets you rewrite the AST however you please, and dependent types have been cropping up all over the place. However, with great power comes great responsibility undecidable type systems, whose undefined behavior may involve summoning eldritch abominations from the Black Abyss of Rěgne Ūt.

One particular place where metaprogramming is particularly useful is low-level, high-performance code, which is what Terra was created for. The idea behind Terra is that, instead of crafting ancient runes inscribed with infinitely nested variadic templates, just replace the whole thing with an actual turing-complete language, like say, Lua (technically including LuaJIT extensions for FFI). This all sounds nice, and no longer requires a circle of salt to ward off demonic syntax, which Terra is quick to point out. They espouse the magical wonders of replacing your metaprogramming system with an actual scripting language:

In Terra, we just gave in to the trend of making the meta-language of C/C++ more powerful and replaced it with a real programming language, Lua.

The combination of a low-level language meta-programmed by a high-level scripting language allows many behaviors that are not possible in other systems. Unlike C/C++, Terra code can be JIT-compiled and run interleaved with Lua evaluation, making it easy to write software libraries that depend on runtime code generation.

Features of other languages such as conditional compilation and templating simply fall out of the combination of using Lua to meta-program Terra

Terra even claims you can implement Java-like OOP inheritance models as libraries and drop them into your program. It may also cure cancer (the instructions were unclear).

As shown in the templating example, Terra allows you to define methods on struct types but does not provide any built-in mechanism for inheritance or polymorphism. Instead, normal class systems can be written as libraries. More information is available in our PLDI Paper.

The file lib/javalike.t has one possible implementation of a Java-like class system, while the file lib/golike.t is more similar to Google’s Go language.

I am here to warn you, traveler, that Terra sits on a throne of lies. I was foolish. I was taken in by their audacious claims and fake jewels. It is only when I finally sat down to dine with them that I realized I was surrounded by nothing but cheap plastic and slightly burnt toast.

The Bracket Syntax Problem

Terra exists as a syntax extension to Lua. This means it adds additional keywords on top of Lua’s existing grammar. Most languages, when extending a syntax, would go to great lengths to ensure the new grammar does not create any ambiguities or otherwise interfere with the original syntax, treating it like a delicate flower that mustn’t be disturbed, lest it lose a single petal.

Terra takes the flower, gently places it on the ground, and then stomps on it, repeatedly, until the flower is nothing but a pile of rubbish, as dead as the dirt it grew from. Then it sets the remains of the flower on fire, collects the ashes that once knew beauty, drives to a nearby cliffside, and throws them into the uncaring ocean. It probably took a piss too, but I can’t prove that.

To understand why, one must understand what the escape operator is. It allows you to splice an abstract AST generated from a Lua expression directly into Terra code. Here is an example from Terra’s website:

function get5()
  return 5
end
terra foobar()
  return [ get5() + 1 ]
end
foobar:printpretty()
> output:
> foobar0 = terra() : {int32}
> 	return 6
> end
But, wait, that means it’s… the same as the array indexing operator? You don’t mean you just put it inside like–

local rest = {symbol(int),symbol(int)}

terra doit(first : int, [rest])
  return first + [rest[1]] + [rest[2]]
end

What.

WHAT?!

You were supposed to banish the syntax demons, not join them! This abomination is an insult to Nine Kingdoms of Asgard! It is the very foundation that Satan himself would use to unleash Evil upon the world. Behold, mortals, for I come as the harbinger of despair:

function idx(x) return `x end
function gen(a, b) return `array(a, b) end

terra test()
  -- Intended to evaluate to array(1, 2) 0
  return [gen(1, 2)][idx(0)]
end

For those of you joining us (probably because you heard a blood-curdling scream from down the hall), this syntax is exactly as ambiguous as you might think. Is it two splice statements put next to each other, or is a splice statement with an array index? You no longer know if a splice operator is supposed to index the array or act as a splice operator, as mentioned in this issue. Terra “resolves this” by just assuming that any two bracketed expressions put next to each other are always an array indexing operation, which is a lot like fixing your server overheating issue by running the fire suppression system all day. However, because this is Lua, whose syntax is very much like a delicate flower that cannot be disturbed, a much worse ambiguity comes up when we try to fix this.

function idx(x) return `x end
function gen(a, b) return `array(a, b) end

terra test()
  -- This is required to make it evaluate to array(1,2)[0]
  -- return [gen(1, 2)][ [idx(0)] ]
  -- This doesn't work:
  return [gen(1, 2)][[idx(0)]]
  -- This is equivalent to:
  -- return [gen(1, 2)] "idx(0)"
end

We want to use a spliced Lua expression as the array index, but if we don’t use any spaces, it turns into a string because [[string]] is the Lua syntax for an unescaped string! Now, those of you who still possess functioning brains may believe that this would always result in a syntax error, as we have now placed a string next to a variable. Not so! Lua, in it’s infinite wisdom, converts anything of the form symbol"string" or symbol[[string]] into a function call with the string as the only parameter. That means that, in certain circumstances, we literally attempt to call our variable as a function with our expression as a string:

local lookups = {x = 0, y = 1, z = 2, w = 3 };
  vec.metamethods.__entrymissing = macro(function(entryname, expr)
    if lookups[entryname] then
      -- This doesn't work
      return `expr.v[[lookups[entryname]]]
      -- This is equivalent to
      -- return `expr.v "lookups[entryname]"
      -- But it doesn't result in a syntax error, becase it's equivalent to:
      -- return `extr.v("lookups[entryname]")
    else
      error "That is not a valid field."
    end
  end)

As a result, you get a type error, not a syntax error, and a very bizarre one too, because it’s going to complain that v isn’t a function. This is like trying to bake pancakes for breakfast and accidentally going scuba diving instead. It’s not a sequence of events that should ever be related in any universe that obeys causality.

It should be noted that, after a friend of mine heard my screams of agony, an issue was raised to change the syntax to a summoning ritual that involves less self-mutilation. Unfortunately, this is a breaking change, and will probably require an exorcism.

The Documentation Is Wrong

Terra’s documentation is so wrong that it somehow manages to be wrong in both directions. That is, some of the documentation is out-of-date, while some of it refers to concepts that never made it into master. I can only assume that a time-traveling gremlin was hired to write the documentation, who promptly got lost amidst the diverging timelines. It is a quantum document, both right and wrong at the same time, yet somehow always useless, a puzzle beyond the grasp of modern physics.

  • The first thing talked about in the API Reference is a List object. It does not actually exist. A primitive incarnation of it does exist, but it only implements map() and insertall(). Almost the entire section is completely wrong for the 1.0.0-beta1 release. The actual List object being described sits alone and forgotten in the develop branch, dust already beginning to collect on it’s API calls, despite those API calls being the ones in the documentation… somehow.
  • :printpretty() is a function that prints out a pretty string representation of a given piece of Terra code, by parsing the AST representation. On it’s face, it does do exactly what is advertised: it prints a string. However, one might assume that it returns the string, or otherwise allows you to do something with it. This doesn’t happen. It literally calls the print() function, throwing the string out the window and straight into the stdout buffer without a care in the world. If you want the actual string, you must call either layoutstring() (for types) or prettystring() (for quotes). Neither function is documented, anywhere.
  • Macros can only be called from inside Terra code. Unless you give the constructor two parameters, where the second parameter is a function called from inside a Lua context. This behavior is not mentioned in any documentation, anywhere, which makes it even more confusing when someone defines a macro as macro(myfunction, myfunction) and then calls it from a Lua context, which, according to the documentation, should be impossible.
  • Struct fields are not specified by their name, but rather just held in a numbered list of {name, type} pairs. This is documented, but a consequence of this system is not: Struct field names do not have to be unique. They can all be the same thing. Terra doesn’t actually care. You can’t actually be sure that any given field name lookup will result in, y’know, one field. Nothing mentions this.
  • The documentation for saveobj is a special kind of infuriating, because everything is technically correct, yet it does not give you any examples and instead simply lists a function with 2 arguments and 4 interwoven optional arguments. In reality it’s absolutely trivial to use because you can ignore almost all the parameters. Just write terralib.saveobj("blah", {main = main}) and you’re done. But there isn’t a single example of this anywhere on the entire website. Only a paragraph and two sentences explaining in the briefest way possible how to use the function, followed by a highly technical example of how to initialize a custom target parameter, which doesn’t actually compile because it has errant semicolons. This is literally the most important function in the entire language, because it’s what actually compiles an executable!
  • The defer keyword is critical to being able to do proper error cleanup, because it functions similar to Go’s defer by performing a function call at the end of a lexical scope. It is not documented, anywhere, or even mentioned at all on the website. How Terra manages to implement new functionality it forgets to document while, at the same time, documenting functionality that doesn’t exist yet is a 4-dimensional puzzle fit for an extra-dimensional hyperintelligent race of aliens particularly fond of BDSM.
  • You’d think that compiling Terra on Linux would be a lot simpler, but you’d be wrong. Not only are the makefiles unreliable, but cmake itself doesn’t seem to work with LLVM 7 unless you pass in a very specific set of flags, none of which are documented, because compiling via cmake isn’t documented at all, and this is the only way to compile with LLVM 7 or above on the latest Ubuntu release!

Perhaps there are more tragedies hidden inside this baleful document, but I cannot know, as I have yet to unearth the true depths of the madness lurking within. I am, at most, on the third or fourth circle of hell.

Terra Doesn’t Actually Work On Windows

Saying that Terra supports Windows is a statement fraught with danger. It is a statement so full of holes that an entire screen door could try to sell you car insurance and it’d still be a safer bet than running Terra on Windows. Attempting to use Terra on Windows will work if you have Visual Studio 2015 installed. It might work if you have Visual Studio 2013 installed. No other scenarios are supported, especially not ones that involve being productive. Actually compiling Terra on Windows is a hellish endeavor comparable to climbing Mount Everest in a bathing suit, which requires either having Visual Studio 2015 installed to the default location, or manually modifying a Makefile with the exact absolute paths of all the relevant dependencies. At least up until last week, when I submitted a pull request to minimize the amount of mountain climbing required.

The problem Terra runs into is that it tries to use a registry value to find the location of Visual Studio and then work out where link.exe is from there, then finds the include directories for the C runtime. This hasn’t worked since Visual Studio 2017 and also requires custom handling for each version because compiling an iteration of Visual Studio apparently involves throwing the directory structure into the air, watching it land on the floor in a disorganized mess, and drawing lines between vaguely related concepts. Good for divining the true nature of the C library, bad for building directory structures. Unfortunately, should you somehow manage to compile Terra, it will abruptly stop working the moment you try to call printf, claiming that printf does not actually exist, even after importing stdio.h.

Many Terra tests assume that printf actually resolves to a concrete symbol. This is not true and hasn’t been true since Visual Studio 2015, which turned several stdio.h functions into inline-only implementations. In general, the C standard library is under no obligation to produce an actual concrete symbol for any function - or to make sense to a mere mortal, for that matter. In fact, it might be more productive to assume that the C standard was wrought from the unholy, broiling chaos of the void by Cthulhu himself, who saw fit to punish any being foolish enough to make reasonable assumptions about how C works.

Unfortunately, importing stdio.h does not fix this problem, for two reasons. One, Terra did not understand inline functions on Windows. They were ephemeral wisps, vanishing like a mote of dust on the wind the moment a C module was optimized. A pull request fixed this, but it can’t fix the fact that the Windows SDK was wrought from the innocent blood of a thousand vivisected COMDAT objects. Microsoft’s version of stdio.h can only be described as an extra-dimensional object, a meta-stable fragment of a past universe that can only be seen in brief slivers, never all at once.

Luckily for the Terra project, I am the demonic presence they need, for I was once a Microsoftie. Long ago, I walked the halls of the Operating Systems Group and helped craft black magic to sate the monster’s unending hunger. I saw True Evil blossom in those dark rooms, like having only three flavors of sparkling water and a pasta station only open on Tuesdays.

I know the words of Black Speech that must be spoken to reveal the true nature of Windows. I know how to bend the rules of our prison, to craft a mighty workspace from the bowels within. After fixing the cmake implementation to function correctly on Windows, I intend to perform the unholy incantations required to invoke the almighty powers of COM, so that it may find on which fifth-dimensional hyperplane Visual Studio exists. Only then can I disassociate myself from the mortal plane for long enough to tackle the stdio.h problem. You see, children, programming for Windows is easy! All you have to do is s͏̷E͏l͏̢҉l̷ ̸̕͡Y͏o҉u͝R̨͘ ̶͝sơ̷͟Ul̴

For those of you who actually wish to try Terra, but don’t want to wait for me to fix everything a new release, you can embed the following code at the top of your root Terra script:

if os.getenv("VCINSTALLDIR") ~= nil then
  terralib.vshome = os.getenv("VCToolsInstallDir")
  if not terralib.vshome then
    terralib.vshome = os.getenv("VCINSTALLDIR")
    terralib.vclinker = terralib.vshome..[[BIN\x86_amd64\link.exe]]
  else
    terralib.vclinker = ([[%sbin\Host%s\%s\link.exe]]):format(terralib.vshome, os.getenv("VSCMD_ARG_HOST_ARCH"), os.getenv("VSCMD_ARG_TGT_ARCH"))
  end
  terralib.includepath = os.getenv("INCLUDE")

  function terralib.getvclinker()
    local vclib = os.getenv("LIB")
    local vcpath = terralib.vcpath or os.getenv("Path")
    vclib,vcpath = "LIB="..vclib,"Path="..vcpath
    return terralib.vclinker,vclib,vcpath
  end
end

Yes, we are literally overwriting parts of the compiler itself, at runtime, from our script. Welcome to Lua! Enjoy your stay, and don’t let the fact that any script you run could completely rewrite the compiler keep you up at night!

The Existential Horror of Terra Symbols

Symbols are one of the most slippery concepts introduced in Terra, despite their relative simplicity. When encountering a Terra Symbol, one usually finds it in a function that looks like this:

TkImpl.generate = function(skip, finish) return quote
    if [TkImpl.selfsym].count == 0 then goto [finish] end 
    [TkImpl.selfsym].count = [TkImpl.selfsym].count - 1
    [stype.generate(skip, finish)]
end end

Where selfsym is a symbol that was set elsewhere.

“Aha!” says our observant student, “a reference to a variable from an outside context!” This construct does let you access a variable from another area of the same function, and using it to accomplish that will generally work as you expect, but what it’s actually doing is much worse more subtle. You see, grasshopper, a symbol is not a reference to a variable node in the AST, it is a reference to an identifier.

local sym = symbol(int)
local inc = quote [sym] = [sym] + 1 end

terra foo()
  var [sym] = 0
  inc
  inc
  return [sym]
end

terra bar()
  var[sym] = 0
  inc
  inc
  inc
  return [sym]
end

Yes, that is valid Terra, and yes, the people who built this language did this on purpose. Why any human being still capable of love would ever design such a catastrophe is simply beyond me. Each symbol literally represents not a reference to a variable, but a unique variable name that will refer to any variable that has been initialized in the current Terra scope with that particular identifier. You aren’t passing around variable references, you’re passing around variable names.

These aren’t just symbols, they’re typed preprocessor macros. They are literally C preprocessor macros, capable of causing just as much woe and suffering as one, except that they are typed and they can’t redefine existing terms. This is, admittedly, slightly better than a normal C macro. However, seeing as there have been entire books written about humanity’s collective hatred of C macros, this is equivalent to being a slightly more usable programming language than Brainfuck. This is such a low bar it’s probably buried somewhere in the Mariana Trench.

Terra is C but the Preprocessor is Lua

You realize now, the monstrosity we have unleashed upon the world? The sin Terra has committed now lies naked before us.

Terra is C if you replaced the preprocessor with Lua.

Remember how Terra says you can implement Java-like and Go-like class systems? You can’t. Or rather, you will end up with a pathetic imitation, a facsimile of a real class system, striped down to the bone and bereft of any useful mechanisms. It is nothing more than an implementation of vtables, just like you would make in C. Because Terra is C. It’s metaprogrammable C.

There can be no constructors, or destructors, or automatic initialization, or any sort of borrow checking analysis, because Terra has no scoping mechanisms. The only thing it provides is defer, which only operates inside Lua lexical blocks (do and end)… sometimes, if you get lucky. The exact behavior is a bit confusing, and of course can only be divined by random experimentation because it isn’t documented anywhere! Terra’s only saving grace, the singular keyword that allows you to attempt to build some sort of pretend object system, isn’t actually mentioned anywhere.

Of course, Terra’s metaprogramming is turing complete, and it is technically possible to implement some of these mechanisms, but only if you either wrap absolutely every single variable declaration in a function, or you introspect the AST and annotate every single variable with initialization statuses and then run a metaprogram over it to figure out when constructors or destructors or assignment operators need to be called. Except, this might not work, because the (undocumented, of course) __update metamethod that is supposed to trigger when you assign something to a variable has a bug where it’s not always called in all situations. This turns catching assignments and finding the l-value or r-value status from a mind-bogglingly difficult, herculean task, to a near-impossible trial of cosmic proportions that probably requires the help of at least two Avengers.

There Is No Type System

If Terra was actually trying to build a metaprogramming equivalent to templates, it would have an actual type system. These languages already exist - Idris, Omega, F*, Ada, Sage, etc. but none of them are interested in using their dependent type systems to actually metaprogram low-level code (although F* can produce it). The problem is that building a recursively metaprogrammable type system requires building a proof assistant, and everyone is so proud of the fact they built a proof assistant they forget that dependent type systems can do other things too, like build really fast memcpy implementations.

Terra, on the other hand, provides only the briefest glimpse of a type system. Terra functions enjoy what is essentially a slightly more complex C type system. However, the higher-level Lua context is, well, Lua, which has five basic types: Tables, Functions, Strings, Booleans and Numbers (it also has Thread, Nil, Userdata and CData for certain edge cases). That’s it. Also, it’s dynamic, not static, so everything is a syntax or a runtime error, because it’s a scripting language. This means all your metaprogramming is sprinkled with type-verification calls like :istype() or :isstruct(), except the top came off the shaker and now the entire program is just sprinkles, everywhere. This is fine for when your metaprograms are, themselves, relatively simple. It is not fine when you are returning meta-programs out of meta-meta-functions.

This is the impasse I find myself at, and it is the answer to the question I know everyone wants to know the answer to. For the love of heaven and earth and all that lies between, why am I still using Terra?

The truth is that the project I’m working on requires highly complex metaprogramming techniques in order to properly generate type-safe mappings for arbitrary data structures. Explaining why would be an entire blog post on it’s own, but suffice to say, it’s a complex user interface library that’s intended to run on tiny embedded devices, which means I can’t simply give up and use Idris, or indeed anything that involves garbage collection.

What I really want is a low-level, recursively metaprogrammable language that is also recursively type-safe, in that any type strata can safely manipulate the code of any layer beneath it, preferably via algebriac subtyping that ensures all types are recursively a subset of types that contain them, ad nauseam. This would then allow you to move from a “low-level” language to a “high-level” language by simply walking up the tower of abstraction, building meta-meta-programs that manipulate meta-programs that generate low-level programs.

Alas, such beauty can only exist in the minds of mathematicians and small kittens. While I may one day attempt to build such a language, it will be nothing more than a poor imitation, forever striving for an ideal it cannot reach, cursed with a vision from the gods of a pristine language no mortal can ever possess.

I wish to forge galaxies, to wield the power of computation and sail the cosmos upon an infinite wave of creativity. Instead, I spend untold hours toiling inside LLVM, wondering why it won’t print “Hello World”.

In conclusion, everything is terrible and the universe is on fire.

Today, there was an announcement about a new RISC-V chip, which has got a lot of people excited. I wish I could also be excited, but to me, this is just a reminder that RISC architectures are fundamentally unscalable, and inevitably stop being RISC as soon as they need to be fast. People still call ARM a “RISC” architecture despite ARMv8.3-A adding a FJCVTZS instruction, which is “Floating-point Javascript Convert to Signed fixed-point, rounding toward Zero”. Reduced instruction set, my ass.

The reason this keeps happening is because the laws of physics ensure that no RISC architecture can scale under load. The problem is that a modern CPU is so fast that just accessing the L1 cache takes anywhere from 3-5 cycles. This is part of the reason modern CPUs rely so much on register renaming, allowing them to have hundreds of internal registers that are used to make things go fast, as opposed to the paltry 90 registers actually exposed, 40 of which are just floating point registers for vector operations. The fundamental issue that CPU architects run into is that the speed of light isn’t getting any faster. Even getting an electrical signal from one end of a CPU to the other now takes more than one cycle, which means the physical layout of your CPU now has a significant impact on how fast operations take. Worse, the faster the CPU gets, the more this lag becomes a problem, so unless you shrink the entire CPU or redesign it so your L1 and L2 caches are physically closer to the transistors that need them, the latency from accessing those caches can only go up, not down. The CPU might be getting faster, but the speed of light isn’t.

Now, obviously RISC CPUs are very complicated architectures that do all sorts of insane pipelining to try and execute as many instructions at the same time as possible. This is necessary because, unless your data is already loaded into registers, you might spend more cycles loading data from the L1 cache than doing the actual operation! If you hit the L2 cache, that will cost you 13-20 cycles by itself, and L3 cache hits are 60-100 cycles. This is made worse by the fact that complex floating-point operations can almost always be performed faster by encoding the operation in hardware, often in just one or two cycles, when manually implementing the same operation would’ve taken 8 or more cycles. The FJCVTZS instruction mentioned above even sets a specific flag based on certain edge-cases to allow an immediate jump instruction to be done afterwards, again to minimize hitting the cache.

All of this leads us to single instruction multiple data (SIMD) vector instructions common to almost all modern CPUs. Instead of doing a complex operation on a single float, they do a simple operation to many floats at once. The CPU can perform operations on 4, 8, or even 16 floating point numbers at the same time, in just 3 or 4 cycles, even though doing this for an individual float would have cost 2 or 3 cycles each. Even loading an array of floats into a large register will be faster than loading each float individually. There is no escaping the fact that attempting to run instructions one by one, even with fancy pipelining, will usually result in a CPU that’s simply not doing anything most of the time. In order to make things go fast, you have to do things in bulk. This means having instructions that do as many things as possible, which is the exact opposite of how RISC works.

Now, this does not mean CISC is the future. We already invented a solution to this problem, which is VLIW - Very Large Instruction Word. This is what Itanium was, because researchers at HP anticipated this problem 30 years ago and teamed up with Intel to create what eventually became Itanium. In Itanium, or any VLIW architecture, you can tell the CPU to do many things at once. This means that, instead of having to build massive vector processing instructions or other complex specialized instructions, you can build your own mega-instructions out of a much simpler instruction set. This is great, because it simplifies the CPU design enormously while sidestepping the pipelining issues of RISC. The problem is that this is really fucking hard to compile, and that’s what Intel screwed up. Intel assumed that compilers in 2001 could extract the instruction-level parallelism necessary to make VLIW work, but in reality we’ve only very recently figured out how to reliably do that. 20 years ago, we weren’t even close, so nobody could compile fast code for Itanium, and now Itanium is dead, even though it was specifically designed to solve our current predicament.

With that said, the MILL instruction set uses VLIW along with several other innovations designed to compensate for a lot of the problems discussed here, like having deferred load instructions to account for the lag time between requesting a piece of data and actually being able to use it (which, incidentally, also makes MILL immune to Spectre because it doesn’t need to speculate). Sadly, MILL is currently still vaporware, having not materialized any actual hardware despite it’s promising performance gains. One reason for this might be that any VLIW architecture has a highly unique instruction set. We’re used to x86, which is so high-level it has almost nothing to do with the underlying CPU implementation. This is nice, because everyone implements the same instruction set and your programs all work on it, but it means the way instructions interact is hard to predict, much to the frustration of compiler optimizers. With VLIW, you would very likely have to recompile your program for every single unique CPU, which is a problem MILL has spent quite a bit of time on.

MILL, and perhaps VLIW in general, may have a saving grace with WebAssembly, precisely because it is a low-level assembly language that can be efficiently compiled to any architecture. It wouldn’t be a problem to have unique instruction sets for every single type of CPU, because if you ship WebAssembly, you can simply compile the program for whatever CPU it happens to be running on. A lot of people miss this benefit of WebAssembly, even though I think it will be critical in allowing VLIW instruction sets to eventually proliferate. Perhaps MILL will see the light of day after all, or maybe someone else can come up with a VLIW version of RISC-V that’s open-source. Either way, we need to stop pretending that pipelining RISC is going to work. It hasn’t ever worked and it’s not going to work, it’ll just turn into another CISC with a javascript floating point conversion instruction.

Every. Single. Time.

I’ve been writing code for over 12 years, and for a while I’ve been disgusted by the sorry state of programming. That’s why I felt a deep kinship with Nikita Prokopov’s article, Software Disenchantment. It captures the intense feeling of frustration I have with the software industry as a whole and the inability of modern programmers to write anything even remotely resembling efficient systems.

Unfortunately, much of it is wrong.

While I wholeheartedly agree with what Nikita is saying, I am afraid that he doesn’t seem to understand the details behind modern computers. This is unfortunate, because a misinformed article like this weakens both our positions and makes it more difficult to convince people that software bloat is a problem. Most of the time, his frustrations are valid, but his reasoning is misdirected. So, in this article, I’m going to write counterpoints to some of the more problematic claims.

1. Smooth Scroll

One of my hobbies is game development, and I can assure you that doing anything at 4K resolution at 60 FPS on a laptop is insanely hard. Most games struggle to render at 4K 60 FPS with powerful GPUs, and 2D games are usually graphically simplistic, in that they can have lots of fancy drawings, but drawing 200 fancy images on the screen with hardly any blending is not very difficult. A video is just a single 4K image rendered 60 times a second (plus interpolation), which is trivial. Web renderers can’t do that, because HTML has extremely specific composition rules that will break a naïve graphics pipeline. There is also another crucial difference between a 4K video, a video game, and a webpage: text.

High quality anti-aliased and sometimes sub-pixel hinted text at 10 different sizes on different colored backgrounds blended with different transparencies is just really goddamn hard to render. Games don’t do any of that. They have simple UIs with one or two fonts that are often either pre-rendered or use signed distance fields to approximate them. A web browser is rendering arbitrary unicode text that could include emojis and god knows what else. Sometimes it’s even doing transformation operations in realtime on an SVG vector image. This is hard, and getting it to run on a GPU is even harder. One of the most impressive pieces of modern web technology is Firefox’s WebRender, which actually pushes the entire composition pipeline to the GPU, allowing it to serve most webpages at a smooth 60 FPS. This is basically as fast as you can possibly get, which is why this is a particularly strange complaint.

I think the real issue here, and perhaps what Nikita was getting at, is that the design of modern webpages is so bloated that the web browsers can’t keep up. They’re getting inundated with <div> trees the size of Mount Everest and 10 megs worth of useless javascript bootstrapping ad campaigns that load entire miniature videos. However, none of this has anything to do with the resolution or refresh rate of your screen. Useless crap is going to be slow no matter what your GPU is. Inbox taking 13 seconds to load anything is completely unacceptable, but animating anything other than a white box in HTML is far more expensive than you think, and totally unrelated.

2. Latency

Latency is one of the least understood values in computer science. It is true that many text editors have abysmal response times caused by terrible code, but it’s a lot easier to screw this up than people realize. While CPUs have gotten faster, the latency between hardware components hasn’t improved at all, and in many cases cannot possibly improve. This is because latency is dominated by physical separation and connective material. The speed of light hasn’t changed in the past 48 years, so why would the minimum latency?

The problem is that you can’t put anything on top of a system without increasing its latency, and you can’t decrease the latency unless you bypass a system. That 42-year-old emacs system was basically operating at its theoretical maximum because there was barely anything between the terminal and the keyboard. It is simply physically impossible to make that system more responsive, no matter how fast the CPU gets. Saying it’s surprising that a modern text editor is somehow slower than a system operating at the minimum possible latency makes absolutely no sense, because the more things you put between the keyboard and the screen, the higher your latency will be. This has literally nothing to do with how fast your GPU is. Nothing.

It’s actually much worse, because old computers didn’t have to worry about silly things like composition. They’d do v-sync themselves, manually, drawing the cursor or text in between vertical blanks of the monitor. Modern graphics draw to a separate buffer, which is then flipped to the screen on it’s next refresh. The consequence, however, is that drawing a new frame right after a vertical blank ignores all the input you got that frame! You can only start drawing after you’ve processed all the user input, so once you start, it’s game over. This means that if a vertical blank happens every 16.6 ms, and you start drawing at the beginning of that frame, you have to wait 16.6 ms to process the user input, then draw the next frame and wait another 16.6 ms for the new buffer to get flipped to the screen!

That’s 33ms of latency right there, and that’s if you don’t screw anything up. A single badly handled async call could easily introduce another frame of lag. As modern hardware connections get more complex, they introduce more latency. Wireless systems introduce even more latency. Hardware abstraction layers, badly written drivers, and even the motherboard BIOS can all negatively impact the latency and we haven’t even gotten to the application yet. Again, the only way to lower latency is to bypass layers that add latency. At best, perfectly written software would add negligible latency and approach the latency of your emacs terminal, but could never surpass it (unless we start using graphene).

We should all be pushing for low-latency systems, but electron apps are simply the worst offender. This is something everyone, from the hardware to the OS to the libraries, has to cooperate on if we want responsive computers.

3. Features

It seems silly to argue that computers today have no new features. Of course they have new features. A lot of the features are ones I don’t use, but they do get new features and occasionally they are actually nice. I think the real problem here that each new feature, for some inexplicable reason, requires exponentially more resources than the feature before it, often for no apparent reason. Other times, basic features that are trivial to implement are left out, also for no apparent reason.

For example, Discord still doesn’t know how to de-duplicate resent client messages over a spotty connection despite this being a solved problem for decades, and if a message is deleted too quickly, the deletion packet is received before the message itself, and the client just… never deletes it. This could be trivially solved with a tombstone or even just a temporary queue of unmatched deletion messages, yet the client instead creates a ghost message that you can’t get rid of until you restart the client. There is absolutely no reason for this feature to not exist. It’s not even bloat, it’s just ridiculous.

However, a few other comparisons in here really don’t make any sense. For example, an installation of Windows 10 is only 4 GB because of extreme amounts of compression, yet the article compares this with a 6 GB uncompressed basic install of android. Windows 10 is actually 16 GB once it’s actually installed (20 GB for 64-bit). While software bloat is a very real problem, these kinds of comparisons are just nonsense.

4. Compilers

Now, this one I really don’t understand. Any language other than C++ or Rust basically compiles instantly until you hit 100k lines of code. At work, we have a C# monstrosity that’s half a million lines of code and compiles in 20 seconds. That’s pretty fast. Most other languages are JIT-compiled, so you can just run them instantly. Even then, you don’t really want to optimize for compile time on Release mode unless you’re just removing unnecessary bloat, and many modern compilers take a long time to compile things because they’re doing ridiculously complex optimizations that may require solving NP-hard optimization problems, which some actually do.

The original C language and Jonathon Blow’s language compile really fast because they don’t do anything. They don’t help you, they have an incredibly basic type system, they don’t do advanced memory analysis or a bunch of absurd optimizations to take advantage of the labyrinthine x86-64 instruction set. Languages in the 1990s compiled instantly because they had no features. Heck, sometimes compilation is actually disk bound, which is why getting an SSD can dramatically improve compile times for large projects. This has nothing to do with the compiler!

My question here is what on earth are you compiling that takes hours to compile?! The only projects I’m aware of that take this long are all C++ projects, and it’s always because of header files, because header files are terrible and thankfully no other language ever made that mistake ever again. I am admittedly disappointed in Rust’s compilation times, but most other languages try to ensure that at least debug compilation is ridiculously fast.

I think the complaints here are mostly due to bloated javascript ecosystems that pile NPM modules on top of each other until even a simple linter takes forever to run, or when coders write their entire program in a completely different language that transpiles to javascript and then minify the javascript and that’s if you don’t put it through Babel to polyfill back to earlier versions of javascript and… this sure seems like a javascript problem to me, not a general issue with modern compilers.

Hopefully, webassembly will eliminate this problem, at least on the web. As for everywhere else, unless you’re using a complex systems programming language, compilation times usually aren’t that bad, and even when they are, they exist for a reason.

Why would you complain about memory usage and then in the next breath complain about compilation times? Language features are not free. Rust’s lifetime analysis is incredibly difficult to do, but frees the programmer from worrying about memory errors without falling back to a stop-the-world garbage collector, which is important when garbage collection uses 2-3 times more memory than it actually needs (depending on how much performance you want).

Efficient code, fast compilation and memory safety. Pick two. If you feel that compilers can simply magically improve everything, you’ve probably been living in javascript land for too long, where everything is horrible all the time for no reason. The rest of computing is not actually that horrible. The real problem is that most things are now being written in javascript, so everyone inherits all of javascript’s problems. If you don’t want javascript’s problems, stop using it.

Conclusion

I care very deeply about the quality of code that our industry is putting out, and I love the Better World Manifesto that Nikita has proposed. However, it is painful for me to read an article criticizing bad engineering that gets the technical details wrong. A good engineer makes sure he understands what he’s doing, that’s the whole point of the article! If we truly want to be better engineers, we need to understand the problems we face and what we can do to fix them. We need to understand how our computers work and fundamental algorithmic trade-offs we make when we compare problem-solving approaches.

Years ago, I wrote my own article on this, and I feel it is still relevant today. I asked if anyone actually wants good software. At least now, I know some people do. Maybe together, we can do something about it.

Ever since 2013, I’ve consistently started getting registration e-mails in foreign languages from sites I definitely did not sign up for.

It started with Instagram, on which a bizarrely determined young boy from somewhere around Denmark was trying to register using my e-mail address. Instagram lets you remove an e-mail from an account, which is what I did, repeatedly, but the kid kept adding the non-functional e-mail back on to the account. Eventually I forced a password reset and forcibly deleted his account, in an attempt to dissuade him from using someone else’s e-mail in the future. Astonishingly, this did not work, and I was forced to register on Instagram just to prevent my e-mail from being used.

He shared a first name with me, and I noticed his name on a few of the other e-mails I had gotten. At first, I thought it was just this one kid, possibly related to the infamous gmail dot issue, but astoundingly, most of the time the e-mail had no dots and no apparent typos, it was just… my e-mail. Then I started getting even weirder e-mails.

  • Someone else near Denmark used my e-mail to open an Apple ID. I went in to disable the account and it included payment information and their home address, along with the ability to remotely disable their apple device.
  • I once got a Domino’s order receipt from someone on Rhode Island, which included their full name, home address, and phone number.
  • Just recently, someone signed up for Netflix, got the account temporarily suspended for lack of payment, and then added a payment option before I decided to go in and change the e-mail while also signing up for Netflix so I wouldn’t have to deal with that anymore. I could see part of the credit card payment option they had used.
  • Another time, I woke up to someone in a european timezone creating an account on Animoto and then uploading 3 videos to it before I could reset the password and lock out the account.
  • At least two sites included a plaintext password in the e-mail, although they didn’t seem very legitimate in the first place.

What’s really frightening is discovering just how fragile many of these websites are. Most of them that allow you to change your e-mail address don’t require the new e-mail to be verified, allowing me to simply change it to random nonsense and render the account permanently inaccessible. Others allow your account to function without any sort of e-mail verification whatsoever.

One of my theories was that people just assumed they were picking a username that happened to have @gmail.com on the end of it. My e-mail is my first name and a number, which probably isn’t hard for someone also named Erik to accidentally choose. However, some of these e-mails are for people clearly not named Erik, so where is the e-mail coming from? Why use it?

So far, I’ve had my e-mail used incorrectly to sign up for these services:

  • Netflix (Spanish) - Cely A.
  • PlayView (Spanish)
  • Mojang (English)
  • Apple ID (Danish) - Seier Madsen
  • Telekom Fon (Hungarian)
  • Nutaku (English) - Wyled1
  • Samsung (Spanish)
  • Forex Club (Russian) - Eric
  • Marvel Contest of Champions (Portuguese)
  • Jófogás (Hungarian)
  • Wargaming.net (Russian)
  • Deezer (English) - Erik Morales
  • Crossfire (Portuguese)
  • Instagram (Danish) - Erikhartsfield
  • List.am (Armenian)
  • ROBLOX (English) - PurpleErik18
  • cccraft.net (Hungarian)
  • ThesimpleClub (German)
  • Cadastro Dabam (Portuguese)
  • Első Találkozás (Hungarian) - Rosinec
  • Pinterest (Portuguese) - Erik
  • MEGA (Spanish)
  • mestermc.hu (Hungarian) - Rosivagyok
  • Snapchat (English)
  • Skype (Swedish)
  • PlayIT (Hungarian) - hírlevél
  • Animoto (English) - Erik
  • Geometry Dash (English) - erikivan1235
  • Club Penguin (Spanish)
  • LEGO ID (English) - szar3000
  • Seejaykay.com (English)
  • Dragon’s Prophet (English)
  • Sweepstakes (English) - ErikHartsfield
  • School.of.Nursing (English) - ErikHartsfield
  • SendEarnings (English) - ErikHartsfield
  • Talkatone (English) - Cortez
  • Anonymous VPN (English)
  • Penge (Hungarian)
  • Apple ID (Swedish) - Erik
  • Snapchat (Swedish) - kirenzo
  • Snapchat (Swedish) - erik20039
  • ROBLOX (English) - Mattias10036
  • Riot Games (English) - epik991122
  • Instagram (English) - opgerikdontcare
  • Goodgame Empire (English) - rulererikman

Given how fundamental e-mail is to our modern society, it’s disconcerting that some people, especially young kids, have no idea how powerful an e-mail is. When they provide the wrong e-mail for a service, they are handing over the master keys to their account. These services use e-mail as a primary source of identification, and some of them don’t even seem to realize they’re using the wrong e-mail.

Perhaps this speaks to the fact that, despite all the work large software corporations claim they put into making intuitive user interfaces, basic aspects of our digital world are still arcane and confusing to some people. Forget trying to replace passwords with biometrics, some people don’t even understand how e-mail works. Maybe the software industry needs to find a more intuitive way to assert someone’s identity.

Or maybe people are just dumb.

Whenever people talk about removing single points of failure, most of the suggestions involve “distributed systems” that are resilient to hardware failures. For software, we’ve invented code signing and smart contracts via blockchain to ensure the code we’re running is what we expected to run.

But none of these technologies can prevent a bug from taking down the entire system.

A lot of people point to Google being a single point of failure. They are only partially correct, because Google’s hardware is distributed and extremely redundant. No single piece of hardware in a Google Data center failing can take down the entire data center. You could probably nuke the entire data center and most Google services could fall back to another data center. In fact, Google has developed software canaries to catch bugs from propagating too far into production in an attempt to address the problem of their software being a single point of failure.

But something did take down the entirety of Google Compute once. It was a software bug in the canary itself. Of course, all the canaries were running the same software, so all of them had the same bug, and none of them could catch the configuration bug that was being propagated to all of their routers.

By creating a software canary, Google had simply shifted the single point of failure to its canary software. It was much harder for it to fail, but it was still a single point of failure, so when it did fail, it took down the entire system.

We’ve put a lot of work into trying to reduce the amount of bugs in mission critical systems, going so far as to try to create provably correct software. The problem is that no system can prove that it is free of design-flaws, which occur when the software operates correctly, but does something nobody actually wanted it to do. All of our code-signing and trusted computing initiatives do is make it very difficult for someone to sneak bad code into a widely used library. None of them, however, remove the single point of failure. Should the NSA ever succeed in sneaking in a backdoor to a widely used open source library, it will propagate to everything.

A very well guarded single point of failure is still a single point of failure, no matter how remote the chances of it actually failing. Tom Scott has an excellent video about how a trusted engineer at Google that is allowed to bypass all their security checks could go rogue and remove all the password checks on everything and it would be incredibly hard to stop them.

Physical infrastructure is much more resilient to these kinds of problems, because even if every piece of infrastructure has the same problem, you still have to physically get to it in order to exploit the problem. This makes it very hard for anyone to simultaneously sabotage any country’s offline infrastructure without an incredible amount of work. Software, however, lets us access everything from everywhere. The internet removes physical access as a last resort.

Of course, this is not an insurmountable problem, but it is deceptively difficult to overcome. For example, let’s say we have a bunch of drones we’re controlling. To avoid one bug from taking all of them out at once, half of them run one flying program and the other run a completely different flying program, developed independently. Unfortunately, both of these programs rely on the same library that reads the gyroscope data. If that library has a bug, the entire swarm will crash into a mountain. Having the swarm calculate the data for each other and compare results doesn’t help, because everyone gets the wrong result. The software logic itself is wrong.

The reason this is so insidious is that it runs counter to sane software development practices. To minimize bugs, we minimize complexity, which means writing the least amount of code possible, which inadvertently optimizes to a single point of failure. We re-use libraries and share code. We deliberately try to solve problems exactly once and re-use this code everywhere in our program. This a good thing because it means any bugs we fix propagate everywhere else, but this comes at the cost of propagating any bugs we introduce.

Soon, our world will be consumed by automation, one way or another. Cory Doctorow suggests that hardware should only run software the user trusts, but what if I end up trusting buggy software? If all our self-driving cars run the same software, what happens when it has a bug? Even worse, what if all the different self-driving car companies have their own software, custom built by highly paid engineers… that all use OpenSSL to securely download updates?

What if OpenSSL has a bug?

It’s not clear what can be done about this. Obviously we shouldn’t go around introducing unnecessary complexity that creates even more bugs, but at the same time we shouldn’t delude ourselves into thinking our distributed systems have no single point of failure. They may be robust to hardware failures, but the software they run on will continue to be a single point of failure for the foreseeable future.

I’ve finished constructing a new personal website for myself using hugo, and I’m moving my blog over there so I have more control over what gets loaded, and more importantly, so the page doesn’t attempt to load Blogger’s 5 MB worth of bloated javascript nonsense just to read some text. It also fixes math and code highlighting while reading on mobile. If you reached this post using Blogger, you’ll be redirected or will soon be redirected to the corresponding post on my new website.

All comments have been preserved from the original posts, but making new comments is currently disabled - I haven’t decided if I want to use Disqus or attempt something else. An RSS feed is available on the bottom of the page for tracking new posts that should mimic the Blogger RSS feed, if you were using that. If something doesn’t work, poke me on twitter and I’ll try to fix it.

I implemented share buttons with simple links, without embedding any crazy javascript bullshit. In fact, the only external resource loaded is a Google tracking ID for pageviews. Cloudflare is used to enforce an HTTPS connection over the custom domain even though the website is hosted on Github Pages.

Hopefully, the new font and layout is easier to read than Blogger’s tiny text and bullshit theme nonsense.

I was recently told that my niece was trying to memorize her times tables. As an applied mathematician whose coding involves plenty of multiplication, I was not happy to hear this. Nobody who does math actually memorizes times tables, and furthermore, forcing a child to memorize anything is probably the worst possible thing you can do in modern society. No one should memorize their times tables, they should learn how to calculate them. Forcing children to memorize useless equations for no reason is a great way to either ensure they hate math, teach them they should blindly memorize and believe anything adults tell them, or both. So for any parents who wish to teach their children how to be critical thinkers and give them an advantage on their next math test, I am going to describe how to derive the entire times tables with only 12 rules.

  1. Anything multiplied by 1 is itself. Note that I said anything, that includes fractions, pies, cars, the moon, or anything else you can think of. Multiplying it by 1 just gives you back the same result.

  2. Any number multiplied by 10 has a zero added on the end. 1 becomes 10, 2 becomes 20, 72 becomes 720, 9999 becomes 99990, etc.

  3. Any single digit multiplied by 11 simply adds itself on the end instead of 0. 1 becomes 11, 2 becomes 22, 5 becomes 55, etc. This is because you never need to multiply something by eleven. Instead, multiply it by 10 (add a zero to it) then add itself.

    \[ \begin{aligned} 11*11 = 11*(10 + 1) = 11*10 + 11 = 110 + 11 = 121\\ 12*11 = 12*(10 + 1) = 12*10 + 12 = 120 + 12 = 132 \end{aligned} \]

  4. You can always reverse the numbers being multiplied and the same result comes out. $$ 12*2 = 2*12 $$, $$ 8*7 = 7*8 $$, etc. This is a simple rule, but it’s very easy to forget, so keep it in mind.

  5. Anything multiplied by 2 is doubled, or added to itself, but you only need to do this up to 9. For example, $$ 4*2 = 4 + 4 = 8 $$. Alternatively, you can count up by 2 that many times:

    \[ 4*2 = 2 + 2 + 2 + 2 = 4 + 2 + 2 = 6 + 2 = 8 \]
    To multiply any large number by two, double each individual digit and carry the result. Because you multiply each digit by 2 separately, the highest result you can get from this is 18, so you will only ever carry a 1, just like in addition.
    \[ \begin{aligned} \begin{matrix} 3 & 6\\ & 2\\ \hline & \\ & \\ \hline & \end{matrix}\quad \begin{matrix} 3 & 6\\ & 2\\ \hline 1 & 2\\ & \\ \hline & \end{matrix}\quad \begin{matrix} 3 & 6\\ & 2\\ \hline 1 & 2\\ 6 & \\ \hline & \end{matrix}\quad \begin{matrix} 3 & 6\\ & 2\\ \hline 1 & 2\\ 6 & \\ \hline 7 & 2 \end{matrix} \end{aligned} \]
    This method is why multiplying anything by 2 is one of the easiest operations in math, and as a result the rest of our times table rules are going to rely heavily on it. Don’t worry about memorizing these results - you’ll memorize them whether you want to or not simply because of how often you use them.

  6. Any number multiplied by 3 is multiplied by 2 and then added to itself. For example:

    \[ 6*3 = 6*(2 + 1) = 6*2 + 6 = 12 + 6 = 18 \]
    Alternatively, you can add the number to itself 3 times: $$ 3*3 = 3 + 3 + 3 = 6 + 3 = 9 $$

  7. Any number multiplied by 4 is simply multiplied by 2 twice. For example: $$ 7*4 = 7*2*2 = 14*2 = 28 $$

  8. Any number multiplied by 5 is the same number multiplied by 4 and then added to itself.

    \[ 6*5 = 6*(4 + 1) = 6*4 + 6 = 6*2*2 + 6 = 12*2 + 6 = 24 + 6 = 30 \]
    Note that I used our rule for 4 here to break it up and calculate it using only 2. Once kids learn division, they will notice that it is often easier to calculate 5 by multiplying by 10 and halving the result, but we assume no knowledge of division.

  9. Any number multiplied by 8 is multiplied by 4 and then by 2, which means it’s actually just multiplied by 2 three times. For example: $$ 7*8 = 7*4*2 = 7*2*2*2 = 14*2*2 = 28*2 = 56 $$

  10. Never multiply anything by 12. Instead, multiply it by 10, then add itself multiplied by 2. For example: $$ 12*12 = 12*(10 + 2) = 12*10 + 12*2 = 120 + 24 = 144 $$

  11. Multiplying any single digit number by 9 results in a number whose digits always add up to nine, and whose digits decrease in the right column while increasing in the left column.

    \[ \begin{aligned} 9 * 1 = 09\\ 9 * 2 = 18\\ 9 * 3 = 27\\ 9 * 4 = 36\\ 9 * 5 = 45\\ 9 * 6 = 54\\ 9 * 7 = 63\\ 9 * 8 = 72\\ 9 * 9 = 81 \end{aligned} \]
    10, 11, and 12 can be calculated using rules for those numbers.

  12. For both 6 and 7, we already have rules for all the other numbers, so you just need to memorize 3 results:

    \[ \begin{aligned} 6*6 = 36\\ 6*7 = 42\\ 7*7 = 49 \end{aligned} \]
    Note that $$ 7*6 = 6*7 = 42 $$. This is where people often forget about being able to reverse the numbers. Every single other multiplication involving 7 or 6 can be calculated using a rule for another number.

And there you have it. Instead of trying to memorize a bunch of numbers, kids can learn rules that build on top of each other, each taking advantage of the rules established before it. It’s much more engaging then trying to memorize a giant table of meaningless numbers, a task that’s so mind-numbingly boring I can’t imagine forcing an adult to do it, let alone a small child. More importantly, this task teaches you what math is really about. It’s not about numbers, or adding things together, or memorizing a bunch of formulas. It’s establishing simple rules, and then combining those rules together into more complex rules you can use to solve more complex problems.

This also establishes a fundamental connection to computer science that is often glossed over. Both math and programming are repeated abstraction and generalization. It’s about combining simple rules into a more generalized rule, which can then be abstracted into a simpler form and combined to create even more complex rules. Programs start with machine instructions, while math starts with propositions. Programs have functions, and math has theorems. Both build on top of previous results to create more powerful and expressive tools. Both require a spark of creativity to recognize similarities between seemingly unrelated concepts and unite them in a more generalized framework.

We can demonstrate all of this simply by refusing to memorize our times tables.

Have you built an algorithm that mostly works? Does it account for almost everyone’s needs, save for a few weird outliers that you ignore because they make up 0.0001% of the population? Congratulations, your algorithm is racist! To illustrate how this happens, let’s take a recent example from Facebook. My friend’s message was removed for “violating community standards”. Now, my friend has had all sorts of ridiculous problems with Facebook, so to test my theory, I posted the exact same message on my page, and then had him report it.

Golly gee, look at that, Facebook confirmed the message I sent does not violate community guidelines, but he’s still banned for 12 hours for posting the exact same thing. What I suspect happened is this: Facebook has gotten mad at my friend for having a weird name multiple times, but he can’t prove what his name is because he doesn’t have access to his birth certificate because of family problems, and he thinks someone’s been falsely reporting a bunch of his messages. The algorithm for determining whether or not something is “bad” probably took these misleading inputs, combined it with a short list of so-called “dangerous” topics like “terrorism”, and then decided that if anyone reported one of his messages, it was probably bad. On the other hand, I have a very western name and nobody reports anything I post, so either the report actually made it to a human being, or the algorithm simply decided it was probably fine.

Of course, the algorithm was wrong about my friend’s message. But Facebook doesn’t care. I’m sure a bunch of self-important programmers are just itching to tell me we can’t deal with all the edge-cases in a commercial algorithm because it’s infeasible to account for all of them. What I want to know is, have any of these engineers ever thought about who the edge-cases are? Have they ever thought about the kind of people who can’t produce birth certificates, or don’t have a driver’s license, or have strange names that don’t map to unicode properly because they aren’t western enough?

Poor people. Minorities. Immigrants. Disabled people. All these people they claim to care about, all this talk of diversity and equal opportunity and inclusive policies, and they’re building algorithms that by their very nature will exclude those less fortunate than them. Facebook’s algorithm probably doesn’t even know that my friend is asian, yet it’s still discriminating against him. Do you know who can follow all those rules and assumptions they make about normal people? Rich people. White people. Privileged people. These algorithms benefit those who don’t need help, and disproportionately punish those who don’t need any more problems.

What’s truly terrifying is that Silicon Valley wants to run the world, and it wants to automate everything using a bunch of inherently flawed algorithms. Algorithms that might be impossible to perfect, given the almost unlimited number of edge-cases that reality can come up with. In fact, as I am writing this article, Chrome doesn’t recognize “outlier” as a word, even though Google itself does.

Of course, despite this, Facebook already built an algorithm that tries to detect “toxicity” and silences “unacceptable” opinions. Even if they could build a perfect algorithm for detecting “bad speech”, do these companies really think forcibly restricting free speech will accomplish anything other than improving their own self-image? A deeply cynical part of me thinks the only thing these companies actually care about is looking good. A slightly more optimistic part of me thinks a bunch of well-meaning engineers are simply being stupid.

You can’t change someone’s mind by punching them in the face. Punching people in the face may shut them up, but it does not change their opinion. It doesn’t fix anything. Talking to them does. I’m tired of this industry hiding problems behind shiny exteriors instead of fixing them. That’s what used car salesmen do, not engineers. Programming has devolved into an art of deceit, where coders hide behind pretty animations and huge frameworks that sweep all their problems under the rug, while simultaneously screwing over the people who were supposed to benefit from an “egalitarian” industry that seems less and less egalitarian by the day.

Either silicon valley needs to start dealing with people that don’t fit in neat little boxes, or it will no longer be able to push humanity forward. If we’re going to move forward as a species, we have to do it together. Launching a bunch of rich people into space doesn’t accomplish anything. Curing cancer for rich people doesn’t accomplish anything. Inventing immortality for rich people doesn’t accomplish anything. If we’re going to push humanity forward, we have to push everyone forward, and that means dealing with all 7 billion outliers.

I hope silicon valley doesn’t drag us back to the feudal age, but I’m beginning to think it already has.

A long time ago I thought Google was this magical company that truly cared about engineering and solving problems instead of maximizing shareholder value. Then Larry Page became CEO and I realized they were not a magical unicorn and lamented the fact that they had been transformed into “just another large company”. Several important things happened between that post and now: Microsoft got a new CEO, so I decided to give them a shot and got hired there. I quit right before Windows 10 came out because I knew it was going to be a disaster. More recently, it’s become apparent that Google had gone far past simply being a behemoth unconcerned with the cries of the helpless and transformed into something outright malevolent. It’s silenced multiple reporters, blocked windows phone from accessing youtube out of spite, and successfully gotten an entire group of researchers fired by threatening to pull funding (but that didn’t stop them).

This is evil. This is horrifying. This is the kind of stuff Microsoft did in the 90s that made everyone hate it so much they still have to fight against the repercussions of decisions made two decades ago because of the sheer amount of damage they did and lives they ruined. I’m at the point where I’d rather go back to Microsoft, whose primary sin at this point is mostly just being incompetent instead of outright evil, rather than Google, who is actually doing things that are fundamentally morally wrong. These are the kinds of decisions that are bald-faced abuses of power, without any possible “good intention” driving them. It’s vile. There is no excuse.

As an ex-Microsoft employee, I can assure you that at no point did I think Microsoft was doing something evil while I was there. I haven’t seen Microsoft do anything outright evil since I left, either. The few times they came close they backed off and apologized later. Microsoft didn’t piss people off by being evil, it pissed people off by being dumb. I was approached by a Google recruiter shortly after I left and I briefly considered going to Google because I considered them vastly more competent, and I still do. However, no amount of engineering competency can make me want to work for a company that actively does things I consider morally reprehensible. This is the same reason I will never work for Facebook. I’ve drawn a line in the sand, and I find myself in the surprising situation of being on the opposite side of Google, and discovering that Microsoft, of all companies, isn’t with them.

I always thought I’d be able to mostly disregard the questionable things that Google and Microsoft were doing and compare them purely on the competency of their engineers. However, it seems that Google has every intention of driving me away by doing things so utterly disgusting I could never work there and still be able to sleep at night. This worries me deeply, because as these companies get larger and larger, they eat up all the other sources of employment. Working at a startup that isn’t one of the big 5 won’t help if it gets bought out next month. One friend of mine with whom I shared many horror stories with worked at LinkedIn. He was not happy when he woke up one day to discover he now worked for the very company he had heard me complaining about. Even now, he’s thinking of quitting, and not because Microsoft is evil - they’re just so goddamn dumb.

The problem is that there aren’t many other options, short of starting your own company. Google is evil, Facebook is evil, Apple is evil if you care about open hardware, Microsoft is too stupid to be evil but might at some point become evil again, and Amazon is probably evil and may or may not treat it’s employees like shit depending on who you ask. Even if you don’t work directly for them, you’re probably using their products or services. At some point, you have to put food on the table. This is why I generally refuse to blame someone for working for an evil company because the economy punishes you for trying to stand up for your morals. It’s not the workers fault, here, it’s Wall Street incentivizing rotten behavior by rewarding short-term profits instead of long-term growth. A free market optimizes to a monopoly. Monopolies are bad. I don’t know what people don’t get about this. We’re fighting over stupid shit like transgender troops or gay rights instead of just treating other human beings with decency, all the while letting rich people rob us blind as they decimate the economy. This is stupid. I would daresay it’s almost more stupid than the guy at Microsoft who decided to fire all the testers.

But I guess I’ll take unrelenting stupidity over retaliating against researchers for criticizing you. At least until Microsoft remembers how to be evil. Then I don’t know what I’ll do.

I don’t know what anyone will do.

Men and women are fundamentally different. So are white people and black people and autistic people and gay people and transgender people and conservatives and liberals and every other human being along every imaginable axis of discrimination. Some of these differences are cultural. Others are genetic. Others depend on environmental factors. These differences mean that some of us are inherently better at certain tasks than others. On average, men are better at spatial temporal reasoning, women are better at reading comprehension and writing ability, and psychopaths can sometimes be excellent CEOs.

Whenever I meet a programmer who insists on doing everything a certain way, the chances I’ll hire them drop off a cliff. Just as object-oriented programming didn’t fix everything, neither will functional programming, or data-oriented programming or array-based programming or any other language. They are different tools that allow you to attack a problem from different directions, much like we have different classes of algorithms to attack certain classes of problems. Greedy algorithms, lazy evaluation, dynamic programming, recursive-descent, maximum flow, all of these are different ways to approach a problem. They represent looking at a problem from different perspectives. A problem that is difficult from one angle might be trivial when examined from a different angle.

When I stumbled upon this anti-diversity memo written by a Google employee, I wonder just how dysfunctional of an engineer that person is. Problems are never solved by being closed-minded. They are solved by opening ourselves to new possibilities and exploring the problem space as an infinitely-dimensional fabric of possible configurations. You do not find possible edge-cases by being closed-minded. You find them by probing the outer edges of your solution, trying to find singularities and inflection points that hint at unusual behavior.

You cannot build a great company by hiring people who are good at the same things you are. Attempting to maximize diversity only comes at a perceived cost of aptitude if you are measuring the wrong things. If your concept of what makes a “good programmer” is an extremely narrow set of skills, then you will inevitably select towards a specific ethnicity, culture, or sex, because the tiny statistical differences will be grossly magnified by the extremely narrow job requirements. Demand that all your programmers invert a binary tree on a whiteboard and you’ll filter out the guy who wrote the software 90% of your company uses.

If you think the field of computer science is really this narrow, you’re a terrible programmer. Turing completeness is a fundamental property of the universe, and we are only just beginning to explore the full implications of information theory, the foundations of type theory, NP-completeness, and the nature of computation itself. Disregarding other people because they can’t do something without ever considering what they can do will only hurt your team, and your company. Diversity inclusion programs shouldn’t try to hire more women and ethnic groups because they’re the same, they should be trying to hire them because they are different.

When hiring someone to complete a job, you should hire whoever is the best fit for the job. In a vacuum where there is a single task that needs to be completed, gender and ethnicity should be ignored in favor of a purely meritocratic assessment. However, if you have a company that must respond to a changing world, diversity can reveal solutions you never even knew existed. An established company like Google must actively seek to increase diversity so that it can explore new perspectives that may give it an edge over its rivals. They cannot select on a purely meritocratic basis, because all measures of merit would be based on what the company is already good at, not what it could be good at. You cannot explore new opportunities by hiring the same people.

Intelligent people value feedback from people who think differently than them. This is why many executives will deliberately hire people they disagree with so they can have someone challenge their views. This helps avoid creating an echo-chamber, which is the ultimate irony of a memo that’s called “Google’s Ideological Echo Chamber”, because scrapping the diversity inclusion programs as the memo suggests would itself create a new echo-chamber. You can’t remove an echo-chamber by removing diversity - the author’s premise is self-defeating. If they had stuck with only claiming that conservative ideologies should not be discriminated against, they would have been correct. Unfortunately, telling everyone they shouldn’t discriminate against your perspective, which itself involves discriminating against other perspectives, is by definition a contradiction.

We aren’t going to write better programs by doing the same thing we’ve been doing for the past 10 years. To improve is to change, and those who seek to become better software engineers must themselves embrace change, or they will be left behind to rot in the sewers of forgotten programs, maintaining rancid enterprise code for the rest of their lives. If we are unwilling to change who is writing the programs, we’ll be stuck making the same thing over and over again. A business that thinks nothing needs to change is one ripe for disruption. If you really think only hiring white males who correctly answer all your questions about graph theory and B-trees will help your business in the long-term, you’re an idiot.

While the news of SoundCloud imploding are fairly recent, musicians and producers have had a beef with the music uploading site’s direction for years. I still remember when SoundCloud only gave you a paltry 2 hours worth of free upload time and managed to convert my high quality lossless WAV files to the shittiest 128 kbps MP3 I’ve ever heard in my life. What really pissed me off was that they demanded a ridiculous $7 a month just to double your upload time. This is in contrast to Newgrounds, a tiny website run by a dozen people with an audio portal built almost as an afterthought that still manages to be superior to every single other offering. It gives you unlimited space, for free, and lets you upload your own MP3, which allows me to upload properly encoded joint-stereo 128 kbps MP3 files, or much higher quality MP3s for songs I’m giving out for free.

Obviously, Newgrounds is only able to offer unlimited free uploads because the audio portal just piggybacks on the rest of the site. However, I was so pissed off at SoundCloud’s disgusting subscription offering that I actually ran the numbers in terms of what it would cost to store lossless FLAC encodings of songs using Amazon S3. These calculations are now out of date, so I’ve redone them for the purposes of this blog.

The average size of an FLAC encoded song is around 60 MB, but we’ll assume it’s 80 MB as an upper-bound, and to include the cost of storing the joint-stereo 128 kbps streaming MP3, which is usually less than 10% the size (using OPUS would reduce this even more, but it is not supported on all browsers yet). Amazon offers the first 50 TB of storage at $0.023 per gigabyte, per month. This comes down to about $0.00184 per month, per song, in order to store the full uncompressed version. Now, obviously, we must also stream the song, but we’re only streaming the low-quality version, which is 10% the size, which is about 7 MB in our example (7 MB + 70 MB is about 80 MB for storage). The vast majority of music producers on the website have almost no following, and most will be lucky to get a single viral hit. As an example, after being on SoundCloud for over 7 years, I have managed to amass a mere 100000 views total. If I somehow got 20000 views of my songs every single month, the total cost of streaming 140 GB from Amazon S3 at $0.05 per GB would be $7 per month. That’s how much SoundCloud is charging just to double my storage space!

This makes even less sense when you calculate that 6 hours of FLAC would be 4.7 GB, or about 5 GB including the 128 kbps streaming MP3s. 5 GB of storage space costs a pathetic $0.12 cents a month to store on Amazon S3! All of the costs come down to bandwidth, which is relatively fixed by how many people are listening to songs, not how many songs there are. This means, if I’m paying any music service for the right to store music on their servers, I should get near unlimited storage space (maybe put in a sanity check of 10 GB max per month to limit abuse). I will point out that Clyp.it actually does this properly, giving you 6 hours of storage space for free and unlimited storage space if you pay them $6 a month.

Unfortunately, Clyp.it does not try to be SoundCloud as it has no comments, no reshares, and well, not much of anything, really. It’s like a giant pastebin for sounds where you can follow people or favorite things. It’s also probably screwed.

Even though I had a name and a website design, I never launched it because even if I could find a way to identify a copyrighted song via some sort of ContentID system, I couldn’t make it work without the record industry’s cooperation. The problem is that the system has to know what songs are illegal in order to block them in the first place. Otherwise, people could upload Justin Bieber songs with impunity and I’d still get sued out of existence. The hard part about making a site like SoundCloud isn’t actually making the website, it’s dealing with the insane, litigation-happy oligarchs that own the entire music industry.

SoundCloud’s ordeal is mentioned in this article. Surprisingly, it took until 2012 for them to realize they had to start making deals with the major music labels. It took until 2014 for many of those deals to actually happen, and they were not in SoundCloud’s favor. A deal with Warner Music Group, closed in 2014, gave Warner a 3-5% stake in the company and an undisclosed cut of ad-revenue, just so SoundCloud could have the privilege of not being sued out of existence. This wasn’t even an investment round, it was just so SoundCloud could have Warner Music Group’s catalog on the site and not get sued!

At this point, you have to be either very naive or very rich to go up against an industry that can and will send an army of lawyers after you. The legal system is not in your favor. It will be used to crush you like a bug and there is nothing you can do about it, because of one fundamental problem: You can’t detect copyright infringement without access to the original copy.

Because of this, the music industry holds the entire world hostage with a kind of Catch-22: They demand you take down all copyright infringing material, but in order to figure out if something is copyright infringement, you need access to their songs, which they only give out on their terms, which are never in your favor.

Lua is a popular scripting language due to its tight integration with C. LuaJIT is an extremely fast JIT compiler for Lua that can be integrated into your game, which also provides an FFI Library that directly interfaces with C functions, eliminating most overhead. However, the FFI library only accepts a subset of the C standard. Specifically, “C declarations are not passed through a C pre-processor, yet. No pre-processor tokens are allowed, except for #pragma pack.” The website suggests running the header file through a preprocesser stage, but I have yet to find a LuaJIT tutorial that actually explains how to do this. Instead, all the examples simply copy+paste the function prototype into the Lua file itself. Doing this with makefiles and GCC is trivial, because you just have to add a compile step using the -E option, but integrating this with Visual Studio is more difficult. In addition, I’ll show you how to properly load scripts and modify the PATH lookup variable so your game can have a proper scripts folder instead of dumping everything in bin.

Compilation

To begin, we need to download LuaJIT and get it to actually compile. Doing this manually isn’t too difficult, simply open an x64 Native Tools Command Prompt (or x86 Native Tools if you want 32-bit), navigate to src/msvcbuild.bat and run msvcbuild.bat. The default options will build an x64 or x86 dll with dynamic linking to the CRT. If you want a static lib file, you need to run it with the static option. If you want static linking to the CRT so you don’t have to deal with that annoying Visual Studio Runtime Library crap, you’ll have to modify the .bat file directly. Specifically, you need to find %LJCOMPILE% /MD and change it to %LJCOMPILE% /MT. This will then compile the static lib or dll with static CRT linking to match your other projects.

This is a bit of a pain, and recently I’ve been trying to automate my build process and dependencies using vcpkg to act as a C++ package manager. A port of LuaJIT is included in the latest update of vcpkg, but if you want one that always statically links to the CRT, you can get it here.

An important note: the build instructions for LuaJIT state that you should copy the lua scripts contained in src/jit to your application folder. What it doesn’t mention is that this is optional - those scripts contain debugging instructions for the JIT engine, which you probably don’t need. It will work just fine without them.

Once you have LuaJIT built, you should add it’s library file to your project. This library file is called lua51.lib (and the dll is lua51.dll), because LuaJIT is designed as a drop-in replacement for the default Lua runtime. Now we need to actually load Lua in our program and integrate it with our code. To do this, use lua_open(), which returns a lua_State* pointer. You will need that lua_State* pointer for everything else you do, so store it somewhere easy to get to. If you are building a game using an Entity Component System, it makes sense to build a LuaSystem that stores your lua_State* pointer.

Initialization

The next step is to load in all the standard Lua libraries using luaL_openlibs(L). Normally, you shouldn’t do this if you need script sandboxing for player-created scripts. However, LuaJIT’s FFI library is inherently unsafe. Any script with access to the FFI library can call any kernel API it wants, so you should be extremely careful about using LuaJIT if this is a use-case for your game. We can also register any C functions we want to the old-fashioned way via lua_register, but this is only useful for functions that don’t have C analogues (due to having multiple return values, etc).

There is one function in particular that you probably want to overload, and that is the print() function. By default, Lua will simply print to standard out, but if you aren’t redirecting standard out to your in-game console, you probably have your own std::ostream (or even a custom stream class) that is sent all log messages. By overloading print(), we can have our Lua scripts automatically write to both our log file and our in-game console, which is extremely useful. Here is a complete re-implementation of print that outputs to an arbitrary std::ostream& object:

int PrintOut(lua_State *L, std::ostream& out)
{
  int n = lua_gettop(L);  /* number of arguments */
  if(!n)
    return 0;
  int i;
  lua_getglobal(L, "tostring");
  for(i = 1; i <= n; i++)
  {
    const char *s;
    lua_pushvalue(L, -1);  /* function to be called */
    lua_pushvalue(L, i);   /* value to print */
    lua_call(L, 1, 1);
    s = lua_tostring(L, -1);  /* get result */
    if(s == NULL)
      return luaL_error(L, LUA_QL("tostring") " must return a string to "
        LUA_QL("print"));
    if(i > 1) out << "\t";
    out << s;
    lua_pop(L, 1);  /* pop result */
  }
  out << std::endl;
  return 0;
}
To overwrite the existing print function, we need to first define a Lua compatible shim function. In this example, I pass std::cout as the target stream:

int lua_Print(lua_State *L)
{
  return PrintOut(L, std::cout);
}
Now we simply register our lua_Print function using lua_register(L, "print", &lua_Print). If we were doing this in a LuaSystem object, our constructor would look like this:

LuaSystem::LuaSystem()
{
  L = lua_open();
  luaL_openlibs(L);
  lua_register(L, "print", &lua_Print);
}
To clean up our Lua instance, we need to both trigger a final GC iteration to clean up any dangling memory, and then we call lua_close(L), so our destructor would look like this:
LuaSystem::~LuaSystem()
{
  lua_gc(L, LUA_GCCOLLECT, 0);
  lua_close(L);
  L = 0;
}

Loadings Scripts via Require

At this point most tutorials skip to the part where you load a Lua script and write “Hello World”, but we aren’t done yet. Integrating Lua into your game means loading scripts and/or arbitrary strings as Lua code while properly resolving dependencies. If you don’t do this, any one of your scripts that relies on another script will have to do require("full/path/to/script.lua"). We also face another problem - if we want to have a scripts folder where we simply automatically load every single script into our workspace, simply loading them all can cause duplicated code, because luaL_loadfile does not have any knowledge of require. You can solve this by simply loading a single bootstrap.lua script which then loads all your game’s scripts via require, but we’re going to build a much more robust solution.

First, we need to modify Lua’s PATH variable, or the variable that controls where it looks up scripts relative to our current directory. This function will append a path (which should be of the form "path/to/scripts/?.lua") to the beginning of the PATH variable, giving it highest priority, which you can then use to add as many script directories as you want in your game, and any lua script from any of those folders will then be able to require() a script from any other folder in PATH without a problem. Obviously, you should probably only add one or two folders, because you don’t want to deal with potential name conflicts in your script files.

int AppendPath(lua_State *L, const char* path)
{
  lua_getglobal(L, "package");
  lua_getfield(L, -1, "path"); // get field "path" from table at top of stack (-1)
  std::string npath = path;
  npath.append(";");
  npath.append(lua_tostring(L, -1)); // grab path string from top of stack
  lua_pop(L, 1);
  lua_pushstring(L, npath.c_str());
  lua_setfield(L, -2, "path"); // set the field "path" in table at -2 with value at top of stack
  lua_pop(L, 1); // get rid of package table from top of stack
  return 0;
}
Next, we need a way to load all of our scripts using require() so that Lua properly resolves the dependencies. To do this, we create a function in C that literally calls the require() function for us:
int Require(lua_State *L,const char *name)
{
  lua_getglobal(L, "require");
  lua_pushstring(L, name);
  int r = lua_pcall(L, 1, 1, 0);
  if(!r)
    lua_pop(L, 1);
  WriteError(L, r, std::cout);
  return r;
}
By using this to load all our scripts, we don’t have to worry about loading them in any particular order - require will ensure everything gets loaded correctly. An important note here is WriteError(), which is a generic error handling function that processes Lua errors and writes them to a log. All errors in lua will return a nonzero error code, and will usually push a string containing the error message to the stack, which must then be popped off, or it’ll mess things up later.
void WriteError(lua_State *L, int r, std::ostream& out)
{
  if(!r)
    return;
  if(!lua_isnil(L, -1)) // Check if a string was pushed
  {
    const char* m = lua_tostring(L, -1);
    out << "Error " << r << ": " << m << std::endl;
    lua_pop(L, 1);
  }
  else
    out << "Error " << r << std::endl;
}

Automatic C Binding Generation

Fantastic, now we’re all set to load up our scripts, but we still need to somehow define a header file and also load that header file into LuaJIT’s FFI library so our scripts have direct access to our program’s exposed C functions. One way to do this is to just copy+paste your C function definitions into a Lua file in your scripts folder that is then automatically loaded. This, however, is a pain in the butt and is error-prone. We want to have a single source of truth for our function definitions, which means defining our entire LuaJIT C API in a single header file, which is then loaded directly into LuaJIT. Predictably, we will accomplish this by abusing the C preprocessor:

#ifndef __LUA_API_H__
#define __LUA_API_H__

#ifndef LUA_EXPORTS
#define LUAFUNC(ret, name, ...) ffi.cdef[[ ret lua_##name(__VA_ARGS__); ]]; name = ffi.C.lua_##name
local ffi = require("ffi")
ffi.cdef[[ // Initial struct definitions
#else
#define LUAFUNC(ret, name, ...) ret __declspec(dllexport) lua_##name(__VA_ARGS__)
extern "C" { // Ensure C linkage is being used
#endif

struct GameInfo
{
  uint64_t DashTail;
  uint64_t MaxDash;
};

typedef const char* CSTRING; // VC++ complains about having const char* in macros, so we typedef it here

#ifndef LUA_EXPORTS
]] // End struct definitions
#endif

  LUAFUNC(CSTRING, GetGameName);
  LUAFUNC(CSTRING, IntToString, int);
  LUAFUNC(void, setdeadzone, float);

#ifdef Everglade_EXPORTS
}
#endif

#endif
The key idea here is to use macros such that, when we pass this through the preprocessor without any predefined constants, it will magically turn into a valid Lua script. However, when we compile it in our C++ project, our project defines LUA_EXPORTS, and the result is a valid C header. Our C LUAFUNC is set up so that we’re using C linkage for our structs and functions, and that we’re exporting the function via __declspec(dllexport). This obviously only works for Visual Studio so you’ll want to set up a macro for the GCC version, but I will warn you that VC++ got really cranky when i tried to use a macro for that in my code, so you may end up having to redefine the entire LUAFUNC macro for each compiler.

At this point, we have a bit of a choice to make. It’s more convenient to have the C functions available in the global namespace, which is what this script does, because this simplifies calling them from an interactive console. However, using ffi.C.FunctionName is significantly faster. Technically the fastest way is declaring local C = ffi.C at the top of a file and then calling the functions via C.FunctionName. Luckily, importing the functions into the global namespace does not preclude us from using the “fast” way of calling them, so our script here imports them into the global namespace for ease of use, but in our scripts we can use the C.FunctionName method instead. Thus, when outputting our Lua script, our LUAFUNC macro wraps our function definition in a LuaJIT ffi.cdef block, and then runs a second Lua statement that brings the function into the global namespace. This is why we have an initial ffi.cdef code block for the structs up top, so we can include that second lua statement after each function definition.

Now we need to set up our compilation so that Visual Studio generates this file without any predefined constants and outputs the resulting lua script to our scripts folder, where our other in-game scripts can automatically load it from. We can accomplish this using a Post-Build Event (under Configuration Properties -> Build Events -> Post-Build Event), which then runs the following code:

CL LuaAPI.h /P /EP /u
COPY "LuaAPI.i" "../bin/your/script/folder/LuaAPI.lua" /Y
Visual Studio can sometimes be finicky about that newline, but if you put in two statements on two separate lines, it should run both commands sequentially. You may have to edit the project file directly to convince it to actually do this. The key line here is CL LuaAPI.h /P /EP /u, which tells the compiler to preprocess the file and output it to a *.i file. There is no option to configure the output file, it will always be the exact same file but with a .i extension, so we have to copy and rename it ourselves to our scripts folder using the COPY command.

Loading and Calling Lua Code

We are now set to load all our lua scripts in our script folder via Require, but what if we want an interactive Lua console? There are lua functions that read strings, but to make this simpler, I will provide a function that loads a lua script from an arbitrary std::istream and outputs to an arbitrary std::ostream:

const char* _luaStreamReader(lua_State *L, void *data, size_t *size)
{
  static char buf[CHUNKSIZE];
  reinterpret_cast<std::istream*>(data)->read(buf, CHUNKSIZE);
  *size = reinterpret_cast<std::istream*>(data)->gcount();
  return buf;
}

int Load(lua_State *L, std::istream& s, std::ostream& out)
{
  int r = lua_load(L, &_luaStreamReader, &s, 0);

  if(!r)
  {
    r = lua_pcall(L, 0, LUA_MULTRET, 0);
    if(!r)
      PrintOut(L, out);
  }

  WriteError(L, r, out);
  return r;
}
Of course, the other question is how to call Lua functions from our C++ code directly. There are many, many different implementations of this available, of varying amounts of safety and completeness, but to get you started, here is a very simple implementation in C++ using templates. Note that this does not handle errors - you can change it to use lua_pcall and check the return code, but handling arbitrary Lua errors is nontrivial.
template<class T, int N>
struct LuaStack;

template<class T> // Integers
struct LuaStack<T, 1>
{
  static inline void Push(lua_State *L, T i) { lua_pushinteger(L, static_cast<lua_Integer>(i)); }
  static inline T Pop(lua_State *L) { T r = (T)lua_tointeger(L, -1); lua_pop(L, 1); return r; }
};
template<class T> // Pointers
struct LuaStack<T, 2>
{
  static inline void Push(lua_State *L, T p) { lua_pushlightuserdata(L, (void*)p); }
  static inline T Pop(lua_State *L) { T r = (T)lua_touserdata(L, -1); lua_pop(L, 1); return r; }
};
template<class T> // Floats
struct LuaStack<T, 3>
{
  static inline void Push(lua_State *L, T n) { lua_pushnumber(L, static_cast<lua_Number>(n)); }
  static inline T Pop(lua_State *L) { T r = static_cast<T>(lua_touserdata(L, -1)); lua_pop(L, 1); return r; }
};
template<> // Strings
struct LuaStack<std::string, 0>
{
  static inline void Push(lua_State *L, std::string s) { lua_pushlstring(L, s.c_str(), s.size()); }
  static inline std::string Pop(lua_State *L) { size_t sz; const char* s = lua_tolstring(L, -1, &sz); std::string r(s, sz); lua_pop(L, 1); return r; }
};
template<> // Boolean
struct LuaStack<bool, 1>
{
  static inline void Push(lua_State *L, bool b) { lua_pushboolean(L, b); }
  static inline bool Pop(lua_State *L) { bool r = lua_toboolean(L, -1); lua_pop(L, 1); return r; }
};
template<> // Void return type
struct LuaStack<void, 0> { static inline void Pop(lua_State *L) { } };

template<typename T>
struct LS : std::integral_constant<int, 
  std::is_integral<T>::value + 
  (std::is_pointer<T>::value * 2) + 
  (std::is_floating_point<T>::value * 3)>
{};

template<typename R, int N, typename Arg, typename... Args>
inline R _callLua(const char* function, Arg arg, Args... args)
{
  LuaStack<Arg, LS<Arg>::value>::Push(_l, arg);
  return _callLua<R, N, Args...>(function, args...);
}
template<typename R, int N>
inline R _callLua(const char* function)
{
  lua_call(_l, N, std::is_void<R>::value ? 0 : 1);
  return LuaStack<R, LS<R>::value>::Pop(_l);
}

template<typename R, typename... Args>
inline R CallLua(lua_State *L, const char* function, Args... args)
{
  lua_getglobal(L, function);
  return _callLua<R, sizeof...(Args), Args...>(L, function, args...);
}
Now you have everything you need for an extensible Lua scripting implementation for your game engine, and even an interactive Lua console, all using LuaJIT. Good Luck!

The most surreal experience I ever had on discord was when someone PMed me to complain that my anti-spam bot wasn’t working against a 200+ bot raid. I pointed out that it was never designed for large-scale attacks, and that discord’s own rate-limiting would likely make it useless. He revealed he was selling spambot accounts at a rate of about $1 for 100 unique accounts and that he was being attacked by a rival spammer. My anti-spam bot had been dragged into a turf war between two spambot networks. We discussed possible mitigation strategies for worst-case scenarios, but agreed that most of them would involve false-positives and that discord showed no interest in fixing how exploitable their API was. I hoped that I would never have to implement such extreme measures into my bot.

Yesterday, our server was attacked by over 40 spambots, and after discord’s astonishingly useless “customer service” response, I was forced to do exactly that.

A Brief History of Discord Bots

Discord is built on a REST API, which was reverse engineered by late 2015 and used to make unofficial bots. To test out their bots, they would hunt for servers to “raid”, invite their bots to the server, then spam so many messages it would softlock the client, because discord still didn’t have any rate limiting. Naturally, as the designated punching bags of the internet, furries/bronies/Twilight fans/slash fiction writers/etc. were among the first targets. The attack on our server was so severe it took us almost 5 minutes of wrestling with an unresponsive client to ban them. Ironically, a few of the more popular bots today, such as “BooBot”, are banned as a result of that attack, because the first thing the bot creator did was use it to raid our server.

I immediately went to work building an anti-spam bot that muted anyone sending more than 4 messages per second. Building a program in a hostile environment like this is much different from writing a desktop app or a game, because the bot had to be bulletproof - it had to rate-limit itself and could not be allowed to crash, ever. Any bug that allowed a user to crash the bot was treated as P0, because it could be used by an attacker to cripple the server. Despite using a very simplistic spam detection algorithm, this turned out to be highly effective. Of course, back then, discord didn’t have rate limiting, or verification, or role hierarchies, or searching chat logs, or even a way to look up where your last ping was, so most spammers were probably not accustomed to having to deal with any kind of anti-spam system.

I added raid detection, autosilence, an isolation channel, and join alerts, but eventually we were targeted by a group from 4chan’s /pol/ board. Because this was a sustained attack, they began crafting spam attacks timed just below the anti-spam threshold. This forced me to implement a much more sophisticated anti-spam system, using a heat algorithm with a linear decay rate, which is still in use today. This improved anti-spam system eventually made the /pol/ group give up entirely. I’m honestly amazed the simplistic “X messages in Y seconds” approach worked as long as it did.

Of course, none of this can defend against a large scale attack. As I learned by my chance encounter with an actual spammer, it was getting easier and easier to amass an army of spambots to assault a channel instead of just using one or two.

Anatomy Of A Modern Spambot Attack

At peak times (usually during summer break), our server gets raided 1-2 times per day. These minor raids are often just 2-3 tweens who either attempt to troll the chat, or use a basic user script to spam an offensive message. Roughly 60-70% of these raids are either painfully obvious or immediately trigger the anti-spam bot. About 20% of the raids involve slightly intelligent attempts to troll the chat by being annoying without breaking the rules, which usually take about 5-10 minutes to be “exposed”. About 5-10% of the raids are large, involving 8 or more people, but they are also very obvious and can be easily confined to an isolation channel. Problems arise, however, with large spambot raids. Below is a timeline of the recent spambot attack on our server:

messages
19:41:25
19:41:45
19:42:05
19:42:25
19:42:45

This was a botched raid, but the bots that actually worked started spamming within 5 seconds of joining, giving the moderators a very narrow window to respond. The real problem, however, is that so many of them joined, the bot’s API calls to add a role to silence them were rate-limited. They also sent messages once every 0.9 seconds, which is designed to get around Discord’s rate limiting. This amounted to 33 messages sent every second, but it was difficult for the anti-spam to detect. Had the spambots reduced their spam cadence to 3 seconds or more, this attack could have bypassed the anti-spam detection entirely. My bot now instigates a lockdown by raising the verification level when a raid is detected, but it simply can’t silence users fast enough to deal with hundreds of spambots, so at some point the moderators must use a mass ban function. Of course, banning is restricted by the global rate limit, because Discord has no mass ban API endpoint, but luckily the global rate limit is something like 50 requests per second, so if you’re only banning people, you’re probably okay.

However, a hostile attacker could sneak bots in one-by-one every 10 minutes or so, avoiding setting off the raid alarm, and then activate them all at once. 500 bots sending randomized messages chosen from an English dictionary once every 5 seconds after sneaking them in over a 48 hour period is the ultimate attack, and one that is almost impossible to defend against, because this also bypasses the 10-minute verification level. As a weapon of last resort, I added a command that immediately bans all users that sent their first message within the past two minutes, but, again, banning is subject to the global rate limit! In fact, the rate limits can change at any time, and while message deletion has a higher rate limit for bots, bans don’t.

The only other option is to disable the @everyone role from being able to speak on any channel, but you have to do this on a per channel basis, because Discord ignores you if you attempt to globally disable sending message permissions for @everyone. Even then, creating an “approved” role doesn’t work because any automated assignment could be defeated by adding bots one by one. The only defense a small Discord server has is to require moderator approval for every single new user, which isn’t a solution - you’ve just given up having a public Discord server. It’s only a matter of time until any angry 13-year-old can buy a sophisticated attack with a week’s allowance. What will happen to public Discord servers then? Do we simply throw up our hands and admit that humanity is so awful we can’t even have public communities anymore?

The Discord API Hates You

The rate-limits imposed on Discord API endpoints are exacerbated by temporary failures, and that’s excluding network issues. Thus, if I attempt to set a silence role on a spammer that just joined, the API will repeatedly claim they do not exist. In fact, 3 separate API endpoints consistently fail to operate properly during a raid: A “member joined” event won’t show up for several seconds, but if I fall back to calling GetMember(), this also claims the member doesn’t exist, which means adding the role also fails! So I have to attempt to silence the user with every message they send until Discord actually adds the role, even though the API failures are also counted against the rate limit! This gets completely absurd once someone assaults your server with 1000 spambots, because this triggers all sorts of bottlenecks that normally aren’t a problem. The alert telling you a user has joined? Rate limited. It’ll take your bot 5-10 minutes to get through just telling you such a gigantic spambot army joined, unless you include code specifically designed to detect these situations and reduce the number of alerts. Because of this, a single user can trigger something like 5-6 API requests, all of which are counted against your global rate limit and can severely cripple a bot.

The general advice that is usually given here is “just ban them”, which is terrible advice because Discord’s own awful message handling makes it incredibly easy to trigger a false positive. If a message fails to send, the client simply sends a completely new message, with it’s own ID, and will continue re-sending the message until an Ack is received, at which point the user has probably send 3 or 4 copies of the same message, each of which have the same content, but completely unique IDs and timestamps, which looks completely identical to a spam attack.

Technically speaking, this is done because Discord assigns snowflake IDs server-side, so each message attempt sent by the client must have a unique snowflake assigned after it is sent. However, it can also be trivially fixed by adding an optional “client ID” field to the message, with a client-generated ID that stays the same if the message is resent due to a network failure. That way, the server (or the other clients) can simply drop any duplicate messages with identical client IDs while still ensuring all messages have unique IDs across their distributed cluster. This would single-handedly fix all duplicate messages across the entire platform, and eliminate almost every single false-positive I’ve seen in my anti-spam bot.

Discord Doesn’t Care

Sadly, Discord doesn’t seem to care. The general advice in response to “how do I defend against a large scale spam attack” is “just report them to us”, so we did exactly that, and then got what has to be one of the dumbest customer service e-mails I’ve ever seen in my life:

Discord Being Stupid

Excuse me, WHAT?! Sorry about somebody spamming your service with horrifying gore images, but please don’t delete them! What happens if the spammers just delete the messages themselves? What happens if they send child porn? “Sorry guys, please ignore the images that are literally illegal to even look at, but we can’t delete them because Discord is fucking stupid.” Does Discord understand the concept of marking messages for deletion so they are viewable for a short time as evidence for law enforcement?! My anti-spam bot’s database currently has more information than Discord’s own servers! If this had involved child porn, the FBI would have had to ask me for my records because Discord would have deleted them all!

Obviously, we’re not going to leave 500+ gore messages sitting in the chatroom while Discord’s ass-backwards abuse team analyzes them. I just have to hope my own nuclear option can ban them quickly enough, or simply give up the entire concept of having a public Discord server.

The problem is that the armies of spambots that were once reserved for the big servers are now so easy and so trivial to make that they’re beginning to target smaller servers, servers that don’t have the resources or the means to deal with that kind of large scale DDoS attack. So instead, I have to fight the growing swarm alone, armed with only a crippled, rate-limited bot of my own, and hope the dragons flying overhead don’t notice.

What the fuck, Discord.

The older I get, the more I realize that 90% of all disagreements or social drama results from a miscommunication of some kind. Every time I wind up having to resolve a dispute, I’ll try to get both sides of the story, only to realize that they’re the same story, and both parties were actually either in agreement or fighting over a perceived insult that never actually existed. Unsurprisingly, a disproportionate amount of this miscommunication often involves programmers being far too strict with their interpretations of what certain words mean.

A linguistics class teaches you about what a language actually is - a bunch of sounds that we mutually agree mean certain things. Language is, intrinsically, a social construct. The correct definition of a word is whatever the majority of your primary social circle thinks it is. However, this also means that if you interact with a secondary social circle, and they all think the word means something else, then whenever you interact with them, it really does mean something else. Language is inherently contextual, and the possible meanings of a word can change based on who is saying it and to whom they’re saying it to. If everyone else on Earth has decided that ’literally’ can also mean ‘figuratively’, then it does, even if the dictionary says otherwise. It also means most people don’t actually care if you say jif or gif, they’ll just say whatever pronunciation gets you to shut up about it.

It’s important to realize that a word’s meaning is not defined by a dictionary, but rather by how people use it. The dictionary is simply a reflection of it’s usage, and is generally a few years out of date. Just as the pronunciation of a word can vary by dialect, so can the potential meanings of a word. Meanings can be invented by regional subdialects and spread outward from there, which is the origin of many slang terms. Sometimes we invent entirely new words, like “dubstep”, but young words may have fuzzy definitions. In some dialects of electronic music listeners, “dubstep” is not actually a a specific genre, but instead refers to all electronic music. Using dubstep to refer to any electronic song is currently incorrect if used in general parlance, because most people think it is referring to a very specific kind of music. However, if this usage of the word continues to be popularized, eventually the meaning of the word will change into a synonym for electronica, and the dictionaries will be updated to reflect this.

The fluid nature of language is why prescriptive grammar is almost always unnecessary, unless you are deliberately conforming to a grammar standard for a specific medium, such as writing a story. In almost any other context, so long as everyone in your social group understands your ‘dialect’ of English, then it is valid grammar. However, if you attempt to use this dialect outside of your social circle with people who are not familiar with it, you will once again be in the wrong, as they will have no idea what you’re talking about. This, however, does not mean there are no mandatory grammar rules, it’s just that most of the rules that are actually necessary to speak the language properly are usually so ingrained that you don’t even think about them.

A fantastic example of this is a little known rule in English where all adjectives must come in a very specific order: opinion-size-age-shape-color-origin-material-purpose Noun. So you can have a lovely little old rectangular green French silver whittling knife, but if you switch the order of any of those adjectives you’ll sound like a maniac. Conversely, you can never have a green great dragon. Despite the fact that this grammar rule is basically never talked about in any prescriptive grammar book, it is mandatory because if you don’t follow it you won’t be speaking proper English and people will have difficulty understanding you. True grammar rules are ones that, if not followed, result in nonsensical sentences that are difficult or impossible to parse correctly.

However, this does not mean all sentences that are difficult to understand have incorrect grammar. In fact, even some words are completely ambiguous by default. If I say I’m “dusting an object”, the meaning of the phrase is completely dependent on what the object is. If it’s a cake, I’m probably dusting it with something. If it’s a shelf, I’m probably dusting it to get rid of the dust.

Programmers tend to be very literal minded people, and often like to think that language is a set of strict rules defined by their English class. In reality, language is a fluid, dynamic, ambiguous, constantly changing enigma that exists entirely because we all agree on what a bunch of sounds mean. We need to recognize this, and when we communicate to other people, we need to be on the lookout for potential misinterpretations of what we say, so we can provide clarifications when possible. If someone says something that seems ridiculous, ask them to clarify. I’m tired of resolving disagreements that exist only because nobody stopped to ask the other side to clarify what they meant.

Stop demanding that everyone explain things in a way you’ll understand. That’s impossible, because everyone understands language slightly differently. Instead, ask for clarification if someone seems to be saying something unusual or before you debate a point they made. Maybe then we can keep the debates to actual disagreements, instead of arguing over communication failures.

One of the most common things I hear from people is that companies should be “apolitical”. The most formal way this concept is expressed is that a company should make decisions based on what maximizes profits and not political opinions. Unfortunately, the statement “companies should only care about maximizing profits” is, itself, a political statement (and one I happen to disagree with). Thus, it is fundamentally impossible for a company to be truly apolitical, for the very act of attempting to be apolitical is a political statement.

How much a company can avoid politics generally depends on both the type and size of the company. Once your company becomes large enough, it will influence politics simply by virtue of its enormous size, and eventually becomes an integral part of political debates whether or wants to or not. Large corporations must take into account the political climate when making business decisions, because simply attempting to blindly maximize profit may turn the public against them and destroy their revenue sources—thus, politics themselves become part of the profit equation, and cannot be ignored. Certain types of businesses embody political statements simply by existing. Grindr, for example, is a dating app for gay men. It’s entire business model is dependent on enabling an activity that certain fundamentalists consider inherently immoral.

You could, theoretically, try to solve part of this quandary by saying that companies should also be amoral, insofar that the free market should decide moral values. The fundamentalists would then protest the companies existence by not using it (but then, they never would have used it in the first place). However, the problem is that, once again, this very statement is itself political in nature. Thus, by either trying to be amoral or moral, a company is making a political statement.

The issue at play here is that literally everything is political. When most everyone agrees on basic moral principles, it’s easier to pretend that politics is really just about economic policy and lawyers, but our current political divisions have demonstrated that this is a fantasy. Politics are the fundamental morals that society has decided on. It’s just a lot easier to argue about minor differences in economic policy instead of fundamental differences in basic morality.

Of course, how companies participate in politics is also important to consider. Right now, a lot of companies participate in politics by spending exorbitant amounts of money on lobbyists. This is a symptom of money in general, and should be solved not by removing corporate money from politics, but removing all money, because treating spending money as a form of speech gives more speech to the rich, which inherently discriminates against the poor and violates the constitutional assertion that all men are created equal (but no one really seems to be paying attention to that line anyway).

Instead of using money, corporations should do things that uphold whatever political values they believe in. As the saying goes, actions speak louder than words (or money, in this case). You could support civil rights activism by being more inclusive with your hiring and promoting a diverse work environment. Or, if you live in the Philippines, you could create an app that helps death squads hunt down drug users so they can be brutally executed. What’s interesting is that most people consider the latter to be a moral issue as opposed to a political one, which seems to derive from the fact that once you agree on most fundamental morals, we humans simply make up a bunch of pointless rules to satisfy our insatiable desire to tell other humans they’re wrong.

We’ve lived in a civilized world for so long, we’ve forgotten the true roots of politics: a clash between our fundamental moral beliefs, not about how much parking fines should be. Your company will make a political statement whether you like it or not, so you’d better make sure it’s the one you want.

** at a comfortable listening volume.*

EDIT: I have confirmed all the results presented here by taking the low frequency test with someone standing physically next to me. They heard a tone beginning at 30 Hz, and by the time I could hear a very faint tone around 70 Hz, they described the tone as “conversation volume level”, which is about 60 dB. I did not reach this perceived volume level until about 120 Hz, which strongly correlates with the experiment. More specific results would require a professional hearing test.

For almost 10 years, I’ve suspected that something was wrong with my ability to hear bass tones. Unfortunately, while everyone is used to people having difficulty hearing high tones, nobody takes you seriously if you tell them you have difficulty hearing low tones, because most audio equipment has shitty bass response, and human hearing isn’t very precise at those frequencies in the first place. People generally say “oh you’re just supposed to feel the bass, don’t worry about it.” This was extremely frustrating, because one of my hobbies is writing music, and I have struggled for years and years to do proper bass mixing, which is basically the only activity on the entire planet that actually requires hearing subtle changes in bass frequencies. This is aggravated by the fact that most hearing tests are designed to detect issues with high frequencies, not low frequencies, so all the basic hearing tests I took at school gave test results back that said “perfectly normal”. Since I now have professional studio monitor speakers, I’m going to use science to prove that I have an abnormal frequency sensitivity curve that severely hampers my ability to differentiate bass tones. Unfortunately, at the moment I live alone and nowhere near anyone else, so I will have to prove that my equipment is not malfunctioning without being able to actually hear it.

Before performing the experiment, I did this simple test as a sanity check. At a normal volume level, I start to hear a very faint tone in that example at about 70 Hz. When I sent it to several other people, they all reported hearing a tone around 20-40 Hz, even when using consumer-grade hardware. This is clear evidence that something is very, very wrong, but I have to prove that my hardware is not malfunctioning before I can definitively state that I have a problem with my hearing.

For this experiment, I will be using two JBL Professional LSR305 studio monitors plugged into a Focusrite Scarlett 2i2. Since these are studio monitors, they should have a roughly linear response all the way down to 20 Hz. I’m going to use a free sound pressure app on my android phone to prove that they have a relatively linear response time. The app isn’t suitable for measuring very quiet or very loud sounds, but we won’t be measuring anything past 75 dB in this experiment because I don’t want to piss off my neighbors.

Speaker Frequency Response Graph

The studio monitor manages to put out relatively stable noise levels until it appears to fall off at 50 Hz. However, when I played a tone of 30 Hz at a volume loud enough for me to feel, the sound monitor still reported no pressure, which means the microphone can’t detect anything lower than 50 Hz (I was later able to prove that the studio monitor is working properly when someone came to visit). Of course, I can’t hear anything below 50 Hz anyway, no matter how loud it is, so this won’t be a problem for our tests. To compensate for the variance in the frequency response volume, I use the sound pressure app to measure the actual sound intensity being emitted by the speakers.

The first part of the experiment will detect the softest volume at which I can detect a tone at any frequency, starting from D3 (293 Hz) and working down note by note. The loudness of the tone is measured using the sound pressure app. For frequencies above 200 Hz, I can detect tones at volumes only slightly above the background noise in my apartment (15 dB). By the time we reach 50 Hz I was unwilling to go any louder (and the microphone would have stopped working anyway), but this is already enough for us to establish 50 Hz as the absolute limit of my hearing ability under normal circumstances.

Threshold of Hearing Graph

To get a better idea of my frequency response at more reasonable volumes, I began with a D4 (293 Hz) tone playing at a volume that corresponded to 43 dB SPL on my app, and then recorded the sound pressure level of each note once it’s volume seemed to match with the other notes. This gives me a rough approximation of the 40 phon equal loudness curve, and allows me to overlay that curve on to the ISO 226:2003 standard:

Equal Loudness Contour

These curves make it painfully obvious that my hearing is severely compromised below 120 Hz, and becomes nonexistent past 50 Hz. Because I can still technically hear bass at extremely loud volumes, I can pass a hearing test trying to determine if I can hear low tones, but the instant the tones are not presented in isolation, they are drowned out by higher frequencies due to my impaired sensitivity. Because all instruments that aren’t pure sine waves produce harmonics above the fundamental frequency, this means the only thing I’m hearing when a sub-bass is playing are the high frequency harmonics. Even then, I can still feel bass if it’s loud enough, so the bass experience isn’t completely ruined for me, but it makes mixing almost impossible because of how bass frequencies interact with the waveform. Bass frequencies take up lots of headroom, which is why in a trance track, you can tell where the kicks are just by looking at the waveform itself:

Bass Example

When mixing, you must carefully balance the bass with the rest of the track. If you have too much bass, it will overwhelm the rest of the frequencies. Because of this, when I send my tracks to friends to get help on mixing, I can tell that the track sounds better, but I can’t tell why. The reason is because they are adjusting bass frequencies I literally cannot hear. All I can hear is the end result, which has less frequency crowding, which makes the higher frequencies sound better, even though I can’t hear any other difference in the track, so it seemes like black magic.

It’s even worse because I am almost completely incapable of differentiating tones below 120 Hz. You can play any note below B2 and I either won’t be able to hear it or it’ll sound the same as all the other notes. I can only consistently differentiate semitones above 400 Hz. Between 120-400 Hz, I can sometimes tell them apart, but only when playing them in total isolation. When they’re embedded in a song, it’s hopeless. This is why, in AP Music Theory, I was able to perfectly transcribe all the notes in the 4-part writing, except the bass, yet no other students seemed to have this problem. My impaired sensitivity to low frequencies mean they get drowned out by higher frequencies, making it more and more difficult to differentiate bass notes. In fact, in most rock songs, I can’t hear the bass guitar at all. The only way for me to hear the bass guitar is for it to be played by itself.

Incidentally, this is probably why I hate dubstep.

For testing purposes, I’ve used the results of my sensitivity testing to create an EQ filter that mimics my hearing problems as best I can. I can’t tell if the filter is on or off. For those of you that use FL Studio, the preset can be downloaded here.

EQ Curve

Below is a song I wrote some time ago that was mastered by a friend who can actually hear bass, so hopefully the bass frequencies in this are relatively normal. I actually have a bass synth in this song I can only barely hear, and had to rely almost entirely on the sequencer to know which notes were which.

This is the same song with the filter applied:

By inverting this filter, I can attempt to “correct” for my bass hearing, although this is only effective down to about 70 Hz, which unfortunately means the entire sub-bass spectrum is simply inaudible to me. To accomplish this, I combine the inverted filter with a mastering plugin that completely removes all frequencies below 60 Hz (because I can’t hear them) and then lowers the volume by about 8 dB so the amplified bass doesn’t blow the waveform up. This doesn’t seem to produce any audible effect on songs without significant bass, but when I tried it on a professionally mastered trance song, I was able to hear a small difference in the bass kick. I also tried it on Brothers In Arms and, for the first time, noticed a very faint bass cello going on that I had never heard before. If you are interested, the FL studio mixer state track that applies the corrective filter is available here, but for normal human beings the resulting bass is probably offensively loud. For that same reason, it is unfortunately impractical for me to use, because listening to bass frequencies at near 70 dB levels is bad for your hearing, and for that matter it doesn’t fix my impaired fidelity anyway, but at least I now know why bass mixing has been so difficult for me over the years.

I guess if I’m going to continue trying to write music, I need to team up with one of my friends that can actually hear bass.

It’s been known for a while that windows has a bad habit of eating your exceptions if you’re inside a WinProc callback function. This behavior can cause all sorts of mayhem, like your program just vanishing into thin air without any error messages due to a stack overflow that terminated the program without actually throwing an exception. What I didn’t realize is that it also eats assert(), which makes debugging hell, because the assertion would throw, the entire user callback would immediately terminate without any stack unwinding, and then windows would just… keep going, even though the program is now in a laughably corrupt state, because only half the function executed.

While trying to find a way to fix this, I discovered that there are no less than 4 different ways windows can choose to eat exceptions from your program. I had already told the kernel to stop eating my exceptions using the following code:

HMODULE kernel32 = LoadLibraryA("kernel32.dll");   
assert(kernel32 != 0);   
tGetPolicy pGetPolicy = (tGetPolicy)GetProcAddress(kernel32, "GetProcessUserModeExceptionPolicy");  
tSetPolicy pSetPolicy = (tSetPolicy)GetProcAddress(kernel32, "SetProcessUserModeExceptionPolicy");   
if(pGetPolicy && pSetPolicy && pGetPolicy(&dwFlags))  
  pSetPolicy(dwFlags & \~EXCEPTION_SWALLOWING); // Turn off the filter
However, despite this, COM itself was wrapping an entire try {} catch {} statement around my program, so I had to figure out how to turn that off, too. Apparently some genius at Microsoft decided the default behavior should be to just swallow exceptions whenever they were making COM, and now they can’t change this default behavior because it’d break all the applications that now depend on COM eating their exceptions to run properly! So, I turned that off with this code:
CoInitialize(NULL); // do this first   
if(SUCCEEDED(CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_L_VEL_PKT_PRIVACY, RPC_C_IMP_LEV_L_IMPERSONATE, NULL, EOAC_DYNAMIC_CLOAKING, NULL)))
{
  IGlobalOptions *pGlobalOptions;
  hr = CoCreateInstance(CLSID_GlobalOptions, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pGlobalOptions));
  if(SUCCEEDED(hr))
  {
    hr = pGlobalOptions->Set(COMGLB_EXCEPTION_HANDLING, COMGLB_EXCEPTION_DONOT_HANDLE);
    pGlobalOptions->Release();
  }
}
There are two additional functions that could be swallowing exceptions in your program: _CrtSetReportHook2 and SetUnhandledExceptionFilter, but both of these are for SEH or C++ exceptions, and I was throwing an assertion, not an exception. I was actually able to verify, by replacing the assertion #define with my own version, that throwing an actual C++ exception did crash the program… but an assertion didn’t. Specifically, an assertion calls abort(), which raises SIGABRT, which crashes any normal program. However, it turns out that Windows was eating the abort signal, along with every other signal I attempted to raise, which is a problem, because half the library is written in C, and C obviously can’t raise C++ exceptions. The assertion failure even showed up in the output… but didn’t crash the program!
Assertion failed!

Program: ...udio 2015\\Projects\\feathergui\\bin\\fgDirect2D_d.dll
File: fgEffectBase.cpp
Line: 20

Expression: sizeof(_constants) == sizeof(float)_(4_4 + 2)
No matter what I do, Windows refuses to let the assertion failure crash the program, or even trigger a breakpoint in the debugger. In fact, calling the __debugbreak() intrinsic, which outputs an int 3 CPU instruction, was completely ignored, as if it simply didn’t exist. The only reliable way to actually crash the program without using C++ exceptions was to do something like divide by 0, or attempt to write to a null pointer, which triggers a segfault.

Any good developer should be using assertions to verify their assumptions, so having assertions silently fail and then corrupt the program is even worse than ignoring they exist! Now you could have an assertion in your code that’s firing, terminating that callback, leaving your program in a broken state, and then the next message that’s processed blows up for strange and bizarre reasons that make no sense because they’re impossible.

I have a hard enough time getting my programs to work, I didn’t think it’d be this hard to make them crash.

About two months ago, I got a new laptop and proceeded to load all my projects on it. Despite compiling everything fine, my graphics engine that used DirectX mysteriously crashed upon running. I immediately suspected either a configuration issue or a driver issue, but this seemed weird because my laptop had a newer graphics card than my desktop. Why was it crashing on newer hardware? Things got even more bizarre once I narrowed down the issue - it was in my shader assignment code, which hadn’t been touched in almost 2 years. While I initially suspected a shader compilation issue, there was no such error in the logs. All the shaders compiled fine, and then… didn’t work.

Now, if this error had also been happening on my desktop, I would have immediately started digging through my constant assignments, followed by the vertex buffers assigned to the shader, but again, all of this ran perfectly fine on my desktop. I was completely baffled as to why things weren’t working properly. I had eliminated all possible errors I could think of that would have resulted from moving the project from my desktop to my laptop: none of the media files were missing, all the shaders compiled, all the relative paths were correct, I was using the exact same compiler as before with all the appropriate updates. I even updated drivers on both computers, but it stubbornly refused to work on the laptop while running fine on the desktop.

Then I found something that nearly made me shit my pants.

if(profile <= VERTEX_SHADER_5_0 && _lastVS != shader) {
  //...
} else if(profile <= PIXEL_SHADER_5_0 && _lastPS != shader) { 
  //...
} else if(profile <= GEOMETRY_SHADER_5_0 && _lastGS != shader) {
  //...
}
Like any sane graphics engine, I do some very simple caching by keeping track of the last shader I assigned and only setting the shader if it had actually changed. These if statements, however, have a very stupid but subtle bug that took me quite a while to catch. They’re a standard range exclusion chain that figures out what type of shader a given shader version is. If it’s less than say, 5, it’s a vertex shader. Otherwise, if it’s less than 10, that this means it’s in the range 5-10 and is a pixel shader. Otherwise, if it’s less than 15, it must be in the range 10-15, ad infinitum. The idea is that you don’t need to check if the value is greater than 5 because the failure of the previous statement already implies that. However, adding that cache check on the end breaks all of this, because now you could be in the range 0-5, but the cache check could fail, throwing you down to the next statement checking to see if you’re below 10. Because you’re in the range 0-5, you’re of course below 10, and the cache check will ALWAYS succeed, because no vertex shader would ever be in the pixel shader cache! All my vertex shaders were being sent in to directX as pixel shaders after their initial assignment!

For almost 2 years, I had been feeding DirectX total bullshit, and had even tested it on multiple other computers, and it had never given me a single warning, error, crash, or any indication whatsoever that my code was completely fucking broken, in either debug mode or release mode. Somehow, deep in the depths of nVidia’s insane DirectX driver, it had managed to detect that I had just tried to assign a vertex shader to a pixel shader, and either ignored it completely, or silently fixed my catastrophic fuckup. However, my laptop had the mobile drivers, which for some reason did not include this failsafe, and so it actually crashed like it was supposed to.

While this was an incredibly stupid bug that I must have written while sleep deprived or drunk (which is impressive, because I don’t actually drink), it was simply impossible for me to catch because it produced zero errors or warnings. As a result, this bug has the honor of being both the dumbest and the longest-living bug of mine, ever. I’ve checked every location I know of for any indication that anything was wrong, including hooking into the debug log of directX and dumping all it’s messages. Nothing. Nada. Zilch. Zero.

I’ve heard stories about the insane bullshit nVidia’s drivers do, but this is fucking terrifying.

Alas, there is more. I had been experimenting with direct2D as an alternative because, well, it’s a 2D engine, right? After getting text rendering working, a change in string caching suddenly broke the entire program. It broke in a particularly bizarre way, because it seemed to just stop rendering halfway through the scene. It took almost an hour of debugging for me to finally confirm that the moment I was rendering a particular text string, the direct2D driver just stopped. No errors were thrown. No warnings could be found. Direct2D’s failure state was apparently to simply make every single function call silently fail with no indication that it was failing in the first place. It didn’t even tell me that the device was missing or that I needed to recreate it. The text render call was made and then every single subsequent call was ignored and the backbuffer was forever frozen to that half-drawn frame.

The error itself didn’t seem to make any more sense, either. I was passing a perfectly valid string to Direct2D, but because that string originated in a different DLL, it apparently made Direct2D completely shit itself. Copying the string onto the stack, however, worked (which itself could only work if the original string was valid).

The cherry on top of all this is when I discovered that Direct2D’s matrix rotation constructor takes degrees, not radians, like every single other mathematical function in the standard library. Even DirectX takes radians!

WHO WRITES THESE APIs?!

As I draw closer to releasing the first early alpha of a library I’ve been working on for several years, I’ve noticed that it’s release time coincides with some rather depressing politics that I wish I could ignore. Unfortunately, it’s difficult to ignore politicians who seek to destroy the lives of your closest friends. A common theme I hear from my friends is a feeling of helplessness, as though we all know terrible things are happening, but no one really knows what to do about it.

But we are not helpless. It is so easy to lose ourselves in pessimism and cynicism, to think that everything will continue to be shit simply because it’s been shit for so many years. A common refrain I heard while still working at a large corporation was, we know our code is shit, but it’s okay, because everyone else’s code is shit. This kind of mentality really bothers me, not because it isn’t true, but because it seems to reflect a resigned, cynical view of the world, and never strives to do better. Yes, everything might end up being shit in the end, but if we don’t even attempt to build something better, we never will. If we hadn’t been trying to write better code we never would have invented structured programming, or object oriented programming, or functional programming. Each innovation builds on the last, and each innovation has it’s faults, but each brings us one step closer to not being shit.

What disturbs me is that the software industry’s inability to strive for better code now mirrors a feeling of political resignation, a malaise that seems to be settling on our polarized political discourse. If democracy isn’t working, what else can we do? If the entire system is corrupt, what hope do we have of fixing it? As wealth inequality rises to ever more absurd levels, our society is tumbling towards a breaking point. Just like a badly maintained software stack, our society is threatening to topple over under economic stresses it was never built to handle. How much longer can we keep it running with duct-tape and terrible hacks? It is our duty to push for real change, to build a better foundation for our future using whatever skills or resources we have.

As I prepare my library for its initial release, I’m not just zipping up a bunch of files to upload to GitHub. I’m lighting a fire, a beacon of hope that I will cast out into the endless night, praying that it might lead us to a brighter future. I am joined by millions of other flickering flames, many of which will fade with time. A few, however, will grow brighter and brighter, until they bring forth a new dawn and shepherd us into a bright new future, even if only for a moment, before sinking below the horizon. Our entire society is built on these brief moments of clarity. Some are longer than others, but all are important. Even when the night seems to stretch on without end, the rays of hope from a thousand stars can still point us in the right direction.

We all wish for a brighter future, a future free from disease and poverty and war and hunger. We seek the future that we envision for ourselves in our stories and movies. Sometimes, it seems like society is going backwards, when everything is going wrong and nothing seems to go right for anyone. But it is in these moments that we must not forget the most important thing: we cannot wait for the future to come to us, we must build it ourselves. 2016 was not a very good year for many people. 2017 shows signs of being even worse, but I don’t care.

I’m going to make 2017 be a better year. I’m going to make the future I want to live in. I’m going to build the tools I wish I had. We are not pawns in some cosmic game, we are human beings. We are free agents capable of making our own decisions, and I’m making a decision to make the future happen, whether it wants to or not.

I’m not letting this year take me down without a fight.

Did you know that CSS3 does all its linear gradients and color interpolation completely wrong? All color values in CSS3 are in the sRGB color space, because that’s the color space that gets displayed on our monitor. However, the problem is that the sRGB color space looks like this:

sRGB gamma curve

Trying to do a linear interpolation along a nonlinear curve doesn’t work very well. Instead, you’re supposed to linearize your color values, transforming the sRGB curve to the linear RGB curve before doing your operation, and then transforming it back into the sRGB curve. This is gamma correction. Here are comparisons between gradients, transitions, alpha blending, and image resizing done directly in sRGB space (assuming your browser complies with the W3C spec) versus in linear RGB:

sRGBLinear
At this point you’ve probably seen a bazillion posts about how you’re doing color interpolation wrong, or gradients wrong, or alpha blending wrong, and the reason is because… you’re doing it wrong. But one can hardly blame you, because everyone is doing it wrong. CSS does it wrong because SVG does it wrong because Photoshop does it wrong because everyone else does it wrong. It’s all wrong.

The amazing thing here is that the W3C is entirely aware of how wrong CSS3 linear gradients are, but did it anyway to be consistent with everything else that does them wrong. It’s interesting that while SVG is wrong by default, it does provide a way to fix this, via color-interpolation. Of course, CSS doesn’t have this property yet, so literally all gradients and transitions on the web are wrong because there is no other choice. Even if CSS provided a way to fix this, it would still have to default to being wrong.

It seems we have reached a point where, after years of doing sRGB interpolation incorrectly, we continue to do it wrong not because we don’t know better, but because everyone else is doing it wrong. So everyone’s doing it wrong because everyone else is doing it wrong. A single bad choice done long ago has locked us into compatibility hell. We got it wrong the first time so now we have to keep getting it wrong because everyone expects the wrong result.

It doesn’t help that we don’t always necessarily want the correct interpolation. The reason direct interpolation in sRGB is wrong is because it changes the perceived luminosity. Notice that when going from red to green, the sRGB gradient gets darker in the middle of the transition, while the gamma-corrected one has constant perceived luminosity. However, an artist may prefer the sRGB curve to the linearized one because it puts more emphasis on red and green. This problem gets worse when artists use toolchains inside sRGB and unknowingly compensate for any gamma errors such that the result is roughly what one would expect. This is a particular issue in games, because games really do need gamma-correct lighting pipelines, but the GUIs were often built using incorrect sRGB interpolation, so doing gamma-correct alpha blending gives you the wrong result because the alpha values were already chosen to compensate for incorrect blending.

In short, this is quite a mess we’ve gotten ourselves into, but I think the most important thing we can do is give people the option of having a gamma correct pipeline. It is not difficult to selectively blend things with proper gamma correction. We need to have things like SVG’s color-interpolation property in CSS, and other software needs to provide optional gamma correct pipelines (I’m looking at you, photoshop).

Maybe, eventually, we can dig ourselves out of this sRGB hell we’ve gotten ourselves into.

Today, a friend asked me for help figuring out how to calculate the standard deviation over a discrete probability distribution. I pulled up my notes from college and was able to correctly calculate the standard deviation they had been unable to derive after hours upon hours of searching the internet and trying to piece together poor explanations from questionable sources. The crux of the problem was, as I had suspected, the astonishingly bad notation involved with this particular calculation. You see, the expected value of a given distribution $$ X $$ is expressed as $$ E[X] $$, which is calculated using the following formula:

\[ E[X] = \sum_{i=1}^{\infty} x_i p(x_i) \]
The standard deviation is the square root of the variance, and the variance is given in terms of the expected value.
\[ Var(X) = E[X^2] - (E[X])^2 \]
Except that $$ E[X^2] $$ is of course completely different from $$ (E[X])^2 $$, but it gets worse, because $$ E[X^2] $$ makes no notational sense whatsoever. In any other function, in math, doing $$ f(x^2) $$ means going through and substitution $$ x $$ with $$ x^2 $$. In this case, however, $$ E[X] $$ actually doesn’t have anything to do with the resulting equation, because $$ X \neq x_i $$, and as a result, the equation for $$ E[X^2] $$ is this:
\[ E[X^2] = \sum_i x_i^2 p(x_i) \]
Only the first $$ x_i $$ is squared. $$ p(x_i) $$ isn’t, because it doesn’t make any sense in the first place. It should really be just $$ P_{Xi} $$ or something, because it’s a discrete value, not a function! It would also explain why the $$ x_i $$ inside $$ p() $$ isn’t squared - because it doesn’t even exist, it’s just a gross abuse of notation. This situation is so bloody confusing I even explicitely laid out the equation for $$ E[X^2] $$ in my own notes, presumably to prevent me from trying to figure out what the hell was going on in the middle of my final.

That, however, was only the beginning. Another question required them to find the covariance between two seperate discrete distributions, $$ X $$ and $$ Y $$. I have never actually done covariance, so my notes were of no help here, and I was forced to return to wikipedia, which gives this helpful equation.

\[ cov(X,Y) = E[XY] - E[X]E[Y] \]
Oh shit. I’ve already established that $$ E[X^2] $$ is impossible to determine because the notation doesn’t rely on any obvious rules, which means that $$ E[XY] $$ could evaluate to god knows what. Luckily, wikipedia has an alternative calculation method:
\[ cov(X,Y) = \frac{1}{n}\sum_{i=1}^{n} (x_i - E(X))(y_i - E(Y)) \]
This almost works, except for two problems. One, $$ \frac{1}{n} $$ doesn’t actually work because we have a nonuniform discrete probability distribution, so we have to substitute multiplying in the probability mass function $$ p(x_i,y_i) $$ instead. Two, wikipedia refers to $$ E(X) $$ and $$ E(Y) $$ as the means, not the expected value. This gets even more confusing because, at the beginning of the Wikipedia article, it used brackets ($$ E[X] $$), and now it’s using parenthesis ($$ E(X) $$). Is that the same value? Is it something completely different? Calling it the mean would be confusing because the average of a given data set isn’t necessarily the same as finding what the average expected value of a probability distribution is, which is why we call it the expected value. But naturally, I quickly discovered that yes, the mean and the average and the expected value are all exactly the same thing! Also, I still don’t know why Wikipedia suddenly switched to $$ E(X) $$ instead of $$ E[X] $$ because it stills means the exact same goddamn thing.

We’re up to, what, five different ways of saying the same thing? At least, I’m assuming it’s the same thing, but there could be some incredibly subtle distinction between the two that nobody ever explains anywhere except in some academic paper locked up behind a paywall that was published 30 years ago, because apparently mathematicians are okay with this.

Even then, this is just one instance where the ambiguity and redundancy in our mathematical notation has caused enormous confusion. I find it particularly telling that the most difficult part about figuring out any mathematical equation for me is usually to simply figure out what all the goddamn notation even means, because usually most of it isn’t explained at all. Do you know how many ways we have of taking the derivative of something?

$$ f'(x) $$ is the same as $$ \frac{dy}{dx} $$ or $$ \frac{df}{dx} $$ even $$ \frac{d}{dx}f(x) $$ which is the same as $$ \dot x $$ which is the same as $$ Df $$ which is technically the same as $$ D_xf(x) $$ and also $$ D_xy $$ which is also the same as $$ f_x(x) $$ provided x is the only variable, because taking the partial derivative of a function with only one variable is the exact same as taking the derivative in the first place, and I’ve actually seen math papers abuse this fact instead of use some other sane notation for the derivative. And that’s just for the derivative!

Don’t even get me started on multiplication, where we use $$ 2 \times 2 $$ in elementary school, $$ * $$ on computers, but use $$ \cdot $$ or simply stick two things next to each other in traditional mathematics. Not only is using $$ \times $$ confusing as a multiplicative operator when you have $$ x $$ floating around, but it’s a real operator! It means cross product in vector analysis. Of course, the $$ \cdot $$ also doubles as meaning the Dot Product, which is at least nominally acceptable since a dot product does reduce to a simple multiplication of scalar values. The Outer Product is generally given as $$ \otimes $$, unless you’re in Geometric Algebra, in which case it’s given by $$ \wedge $$, which of course means AND in binary logic. Geometric Algebra then re-uses the cross product symbol $$ \times $$ to instead mean commutator product, and also defines the regressive product as the dual of the outer product, which uses $$ \nabla $$. This conflicts with the gradient operator in multivariable calculus, which uses the exact same symbol in a totally different context, and just for fun it also defined $$ * $$ as the “scalar” product, just to make sure every possible operator has been violently hijacked to mean something completely unexpected.

This is just one area of mathematics - it is common for many different subfields of math to redefine operators into their own meaning and god forbid any of these fields actually come into contact with each other because then no one knows what the hell is going on. Math is a language that is about as consistent as English, and that’s on a good day.

I am sick and tired of people complaining that nobody likes math when they refuse to admit that mathematical notation sucks, and is a major roadblock for many students. It is useful only for advanced mathematics that take place in university graduate programs and research laboratories. It’s hard enough to teach people calculus, let alone expose them to something useful like statistical analysis or matrix algebra that is relevant in our modern world when the notation looks like Greek and makes about as much sense as the English pronunciation rules. We simply cannot introduce people to advanced math by writing a bunch of incoherent equations on a whiteboard. We need to find a way to separate the underlying mathematical concepts from the arcane scribbles we force students to deal with.

Personally, I understand most of higher math by reformulating it in terms of lambda calculus and type theory, because they map to real world programs I can write and investigate and explore. Interpreting mathematical concepts in terms of computer programs is just one way to make math more tangible. There must be other ways we can explain math without having to explain the extraordinarily dense, outdated notation that we use.

Something that really bothers me about the GPL and free software crusaders in general is that they don’t seem to understand the nuances behind the problem they are attempting to solve. I’m not entirely sure they are even trying to solve the right problem in the first place.

The core issue at play here is control. In a world run by software, we need control over what code is being executed on our hardware. This issue is of paramount importance as we move into an age of autonomous vehicles and wearable devices. Cory Doctorow’s brilliant essay, Lockdown: The coming war on general-purpose computing, gives a detailed explanation of precisely why it is of such crucial importance that you have control over what software gets executed on your machine, and not some corporation. Are you really going to buy a car and then get into it when you have no way of controlling what it does? This isn’t some desktop computer anymore, it’s a machine that can decide whether you live or die.

It is completely true that, if everything was open source, we would then have total control over everything that is being run on our machines. However, proponents of open source software don’t seem to realize that this is the nuclear option. Yes, it solves your problem, but it does so via massive overkill. There are much less extreme ways to achieve exactly what you want that don’t involve requiring literally everything to be open source.

Our goal is to ensure that only trusted code is run on our machine. In order to achieve this goal, the firmware and operating system must be open source. This is because both the operating system and the firmware act as gatekeepers - if we have something like Intel’s Trusted Execution Technology, we absolutely must have access to the firmware’s source code, because it is the first link in our trust chain. If we can make the TXT engine work for us, we can use it to ensure that only operating systems we approve of can be run on our hardware.

We now reach the second stage of our trust chain. By using a boot-time validation of a cryptographic signature, we can verify that we are running an operating system of our choice. Because the operating system is what implements the necessary program isolation and protection mechanisms, it too is a required part of our trust chain and therefore must be open source. We also want the operating system to implement some form of permission restriction - ideally it would be like Android, except that anything running on the OS must explicitly tell you what resources it needs to access, not just apps you download from the store.

And… that’s it. Most free software zealots that are already familiar with this chain of events would go on to say that you should only install open source software and whatever, but in reality this is unnecessary. You certainly want open source drivers, but once you have control over the firmware and the operating system, no program can be run without your permission. Any closed-source application can only do what I have given it permission to do. It could phone home without my knowledge or abuse the permissions I have granted it in other ways, but the hardware is still under my control. I can simply uninstall the application if I decide I don’t like it. Applications cannot control my hardware unless I give them explicit permission to do so.

Is this enough? The FSF would argue that, no, it’s not enough until your entire computer is running only open source code that can be verified and compiled by yourself, but I disagree. At some point, you have to trust someone, somewhere, as demonstrated by the Ken Thompson Hack. I’m fine with trusting a corporation, but I need have total control over who I am trusting. If a corporation controls my firmware or my operating system, then they control who I trust. I can ask them politely to please trust or not trust some program, but I can’t actually be sure of anything, because I do not control the root of the trust chain. Open source software is important for firmware and operating systems, because it’s the only way to establish a chain of trust that you control. However, once I have an existing chain of trust, I don’t need open-source programs anymore. I now control what runs on my computer. I can tell my computer to never run anything written by Oracle, and be assured that it will actually never trust anything written by Oracle.

If I sell you a piece of software, you have a right to decompile it, modify it, hack it, or uninstall it. This does not, however, require me to explain how it works to you, nor how to assemble it. If you trust me, you can run this piece of software on your hardware, but if you don’t trust me, then a verifiable chain of trust will ensure that my software never runs on your machine. This is what matters. This is what having control means. It means being able to say what does or doesn’t run on your computer. It does not require that everything is open source. It only requires an open source, verifiable chain of trust, and faith in whatever company made the software you’ve chosen to run. If a company’s software is proprietary and they do something you don’t like, use something else.

Open source code is important for firmware and operating systems, not everything.

On one hand, America was built on the values of free speech, which are obviously important. We cannot control what people are saying or our democracy falls apart. On the other hand, allowing harassment has a stifling effect on free speech, because it allows people to be bullied into silence. Before the internet, this distinction was fairly simple: Someone with a megaphone screaming hate speech in a park is exercising their right to free speech. Someone with a megaphone following a guy down the street is harassing them.

The arrival of the internet has made this line much more vague. However, the line between free speech and harassment is not nearly as blurry as some people might think. Our concept of reasonable freedom of speech is guided primarily by our ability to ignore it. The idea is, someone can go to a public park and say whatever they want, because other people can simply go somewhere else. As long as people have the ability to ignore whatever you’re saying, you can say pretty much whatever you want. We have some additional controls on this for safety reasons, so you can’t go to a park and talk about how you’re going to kill all the gay people, tomorrow, with a shotgun, because that is a death threat.

Unfortunately, in the midst of defending free speech, a disturbing number of people have gotten it into their heads that other people aren’t allowed to ignore them. This is harassment. The moment you take away someone’s right to ignore what you are saying, you have crossed the line from free speech into harassment. Freedom of speech means that you have the right to say whatever you want, and everyone else has the right to ignore you. I’m not entirely sure why people think that free speech somehow lets them bypass blocking on a social network. Blocking people on the internet is what gives us our ability to ignore them. Blocking someone on the internet is the equivalent of walking away from some guy in the park who was yelling obscenities at you. If you bypass the blocking mechanism, this is basically chasing them down as they run to their car, screaming your opinions at them with a megaphone. Most societies think this is completely unacceptable behavior in real life, and it should be just as unacceptable on the internet.

On the other hand, enforcing political correctness is censorship. Political correctness is obviously something that should be encouraged, but enforcing it when someone is saying things you don’t like in a public place is a clear violation of free speech. This is not a blurry line. This is not vague. If a Nazi supporter is saying how much they hate Jews, and they are not targeting this message at any one individual, this is clearly protected free speech. Now, if the Nazi is actually saying we should murder all of the Jews, this turns into hate speech because it is inciting violence against a group of people, and is restricted for the same safety reasons that prevent you from shouting “FIRE!” in a crowded movie theater.

Now, what if the Nazi supporter tells a specific person they are a dirty Jew? This gets into fuzzy territory. On one hand, we can say it isn’t harassment so long as the targeted person can block the Nazi and the Nazi never attempts to circumvent this, or we can start classifying certain speech as being harassment if it is ever targeted at a specific individual. When we are debating what counts as harassment, this is the kind of stuff we should be debating. This is what society needs to figure out. Arguing that mass-block lists on twitter are hurting free speech is absurd. If someone wants to disregard everything you’re saying because you happen to be walking past a group of Nazi supporters, they have a right to do that. If someone wants to ignore everyone else on the planet, they have a right to do that.

This kind of stuff is a problem when the vast majority of humanity uses a single private platform to espouse their opinions. Namely, Facebook. This is because Facebook has recently been banning people for saying faggot, and because it’s a private company, this is completely legal. This is also harmful to free speech. What appears to be happening is that websites, in an attempt to crack down on harassment, have instead accidentally started cracking down on free speech by outright banning people who say hateful things, instead of focusing on people who say hateful things to specific individuals.

Both sides of the debate are to blame for this. Extreme harassment on the internet has caused a backlash, resulting in a politically correct movement that calls for tempering all speech that might be even slightly offensive to anyone. In response, free speech advocates overreact and start attacking them by bypassing blocking mechanisms and harassing their members. This causes SJWs to overcompensate and start clamping down on all hateful speech, even hateful speech that is clearly protected free speech and has nothing to do with harassment. This just pisses off the free speech movement even more, causing them to oppose any restrictions on free speech, even reasonable ones. This just encourages SJWs to censor even more stuff in an endless spiral of aggression and escalation, until on one side, everyone is screaming obscenities and racial slurs in an incoherent cacophony, and on the other side, no one is saying anything at all.

If society is going to make any progress on this at all, we need to hammer out precisely what constitutes harassment and what is protected free speech. We need to make it absolutely clear that you can only harass an individual, and that everyone has the right to a block button. If a Nazi supporter starts screaming at you on twitter, you have the right to block him, and he has the right to block you. We cannot solve harassment with censorship. Instead of banning people we disagree with, we need to focus on building tools that let us ignore people we don’t want to listen to. If you object to everyone blocking you because you use insulting racial epithets all the time, maybe you should stop doing that, and perhaps some of them might actually listen to you.

Of course, if you disagree with me, you are welcome to exercise your right to tell me exactly how much you hate my guts and want me to die in the comments section below, and I will exercise my right to completely ignore everything you say.

A disturbing number of otherwise intelligent programmers seem to believe that, one day in the distant future, everyone will use the same magical programming language that solves everyone’s problems at the same time. Often, this involves garbage collection, with lots of hand-waving about computers built with Applied Phlebotinum.

For the sake of argument, let’s assume it is the year 30XX, and we are a budding software developer on Mars. We have quantum computers that run on magic pixie dust and let us calculate almost anything we want as fast as we want so long as we don’t break any laws of physics. Does everyone use the same programming language?

No. Obviously, even if we built quantum computers capable of simulating a classical computer a thousand times faster than normal for some arbitrary reason[1], we would still want to write software in a way that was easy to comprehend, and qubits are anything but. So, the standard programming language our Mars programmer would be using would not interact with the quantum computer at all. Perhaps it would be some form of functional language, which the cool kids seem to think will save the entire software industry and make everything faster, better, more reliable and probably cure cancer in the process[2].

But now, this same programming language that allows you to ignore the quantum computer must also be used to write it’s own compiler that runs on… a quantum computer. So it needs to simultaneously be an elegant language for writing quantum programs. It also needs to be the perfect language for writing games and business applications and hypernet sites and machinery and brain implants and rocket trajectories and robot AI and planetary weather simulators and life support systems and hologram emittors and—

… Wouldn’t it be a lot easier to just have domain-specific languages?

If you want to get technical, you can do all that with Lisp. It’s just lambda calculus. It’s also a giant pain in the ass when you use it for things that it was never meant for, like low level drivers or game development. You could try extending Lisp to better handle those edge-cases, and that’s exactly what many lisp-derivatives do. The problem is that we will always be able to find new edge-cases. So, you would have to continue bolting things on to your magical language of ultimate power, playing a game of context-free whack-a-grammar for the rest of eternity.

This is ultimately doomed to fail, because it ignores the underlying purpose of programming languages: A programming language is a method of communication. Given two grammars, one that can do everything versus one that can do the one thing you’re trying to do really well, which one are you going to pick for that particular project? Trying to get everyone to use the same language while they are trying to solve radically different problems is simply bad engineering. Do you really want to write your SQL queries using Lisp? You can only stuff so many tools into a swiss army knife before it becomes completely impractical.

Of course, a language that could do everything would also allow you to define any arbitrary new language within it, but this is equivalent to building an entire new language from scratch, because now everyone who wants to contribute to your project has to learn your unique grammar. However, having a common ground for different languages is a powerful tool, and we are headed in that direction with LLVM. You wouldn’t want to write a program in LLVM, but it sure makes writing a compiler easier.

Instead of a future with one true programming language, perhaps we should be focused on a future with standard low-level assembly. A future with many different languages that can all talk to each other. A future where we don’t need to argue about which programming language is the best, because every language could be used for whatever task it is best suited for, all in the same project. Different compilers could interpret the standard low-level assembly in their own ways, optimizing for different use-cases.

A universal standard for low-level assembly would solve everyth—

mandatory xkcd

… Actually, nevermind[3].


1 As of right now, this is not actually true for the vast majority of computations we know how to do with qubits. We know that certain classes of problems are exponentially faster with quantum computers, but many other functions would get a mere linear increase in speed, at most. Whether or not this will change in the future is an active area of research. 2 They totally didn't say the same thing about object-oriented programming 30 years ago. 3

June 26, 2015 was a historic moment. That was the day the Supreme Court legalized gay marriage on a federal level in the United States. As far as I’m concerned, this victory was the inevitable result of a point of view that relied entirely on logical fallacies and irrational hatred. Yet, it was a battle that was fought for centuries, and continues on, as obstinate conservatives vow to continue fighting to the bitter end. The fact that gay rights was ever a political issue will be considered barbaric by future civilizations, because being gay is inherently harmless, and attempting to control who people are allowed to love is an egregious violation of individual rights.

It was this innate emotional connection that won the battle. Every human being on this planet can empathize with the desire to love freely. We were united in our desire for love to win, just like it does in all of our fairy tales.

Abortion, on the other hand, is likely to remain an issue for hundreds of years. I’m not sure if it will ever be put to rest until we invent technology that renders the entire debate irrelevant. The problem is that, with abortion, there is no moral high ground. This is because, under all circumstances, abortion leaves us with two choices: we can pick an arbitrary point in time where a fetus suddenly has rights, or we will be forced to violate someone’s rights no matter what option we choose.

First, let me clarify why we cannot base the point at which a fetus suddenly gains rights on any meaningful science: babies do not have on switches. Conciousness is an emergent phenomenon, and we have known for years that animals have some degree of awareness. They have a consciousness much like we do, but operating on a lower level (in some cases, it may simply be on a different level). Babies can’t even pass the mirror test until they’re about 18 months old. Because of this, we will be forced to pick some completely arbitrary point in time at which the baby suddenly gains rights, if we want to avoid violating those rights.

Now, if we don’t do that (and I find it incredibly hard to believe that we will, given the number of people who think that a fertilized egg has human rights), we have two choices:

  1. We forbid abortion, violating both the mother’s right to her own body and her right to live (0.019% of pregnancies are fatal).
  2. We allow abortion, violating the baby’s right to live.

There is no way out of this. We cannot use logic to pick a point in time where the baby suddenly gains rights because it will inherently be arbitrary. We’d basically have to say “Well, if you’re 80% human, we’ll give you rights, because, well, 80% sounds like a good number.” No matter how much reasoning we have behind that number, it’s still fundamentally arbitrary and therefore it will always be a valid argument to say it is morally wrong. This means we are forced to violate someone’s rights no matter what we do. Some people think the baby is more important. Some people think the women is more important. Some people think whose important depends on how far along the baby is. There is no nice, clean solution to this. We have to screw somebody over no matter what we do.

My personal view, which is that we should allow abortions only in the first trimester, is not born out of some moral argument. It is simple engineering pragmatism: it is the least objectionable and most practical solution that I can come up with. I am forced to fall back to my engineering background for this problem because there is no valid moral solution. If someone asks me why I think it’s okay that we’re killing a fetus, I would say that it’s not okay. However, it’s also not okay to deny a women the right to her own body. It’s not okay to allow unwanted pregnancies to result in unwanted children that get left in orphanages. It’s not fair that the hypothetical wanted child that could have been born later will now never be born. No part of this situation is ever okay, on either side of the debate.

If we want to resolve the debate, society as a whole simply has to try and figure out how to minimize the damage. That is all we can do. There is no right answer. There are only wrong answers, and we have to pick the least wrong one.

I am going to tell you a story.

This story began with me getting pissed off at Windows for reasons that don’t really need to be articulated. Just, pick your favorite reason to hate Windows, and let’s pretend that was the tipping point. I had some spare space on my secondary drive, so I decided to give Linux another whirl. After all, it had been three or four years since I last attempted anything like this (it’s been so long I don’t rightly remember the last time I tried), and people have been saying that Linux has gotten a lot better recently!

The primary reason I was attempting this is because of Valve’s attempts to move to linux, which have directly resulted in much better nVidia driver support. Trying to install proper nVidia drivers is the thing that wrecked my last attempt. This time, I figured, I could just install the nVidia drivers straight from the repo and everything would be hunky dory, and I could just spend the rest of my time beating on the rest of linux with a comically oversized wrench until it did what I wanted.

I’d had good experiences with XFCE and Fedora on my Linux VM, but I didn’t really like Fedora itself (but it interfaced very well with my VM environment). I wanted to install Ubuntu, because it has the best support and I don’t like trying to dig through arcane forum posts trying to figure out why my computer screen has suddenly turned into an invisible pink unicorn. Unfortunately, Ubuntu is a bloated mess, and I hate it’s default desktop environment. In the past, I had tried Linux Mint, which had been okay, but support had been shaky. I spotted Lubuntu, which is supposed to be a lightweight ubuntu on top of LXDE, a minimal window manager similar to XFCE. This was perfect! So I downloaded Lubuntu 15.04 and installed it on my secondary drive and everything was nice and peachy.

Well, until Linux started, anyway. The first problem was that the package manager in pretty much every linux distro lists all the packages, including all the ones I don’t understand. I was trying to remove some pre-included Paint application and it had two separate packages, one named after itself, and one named <name>-common, but the common package wasn’t automatically removed when the program was! The nVidia packages also had both an nvidia-drivers-340[1] package, and an nvidia-drivers-340-update package, both of which had identical descriptions. I just went with the most basic one because it seemed sensible, but I felt really sorry for someone less tech savvy trying to find anything in that godforsaken list.

So after everything updated and I restarted and told the package manager to start installing my nVidia drivers, I started noticing annoying things about LXDE. A lot of annoying things. Here, let me list them for you:

  • The file manager, when unmounting anything, would helpfully close itself.
  • Trying to change the time to not display military time involves editing some arcane string whose only value is %r, and I still don’t know what that means and don’t want to know what that means. All I wanted to do was change it to say AM or PM!
  • In order to get a shortcut onto the desktop, you had to right-click the menu item and then a new menu would show up that would let you add it to the desktop. You can’t drag anything out of the start menu.
  • The shortcuts seemed disturbingly fickle, occasionally taking 4 rapid clicks to get things to start up.
  • Steam simply didn’t start at all. Unfortunately, we will never know why.
  • Skype managed to spawn a window halfway above the top of the screen, which resulted in me having to look up alt+space in order to rescue it.
  • Skype also cut off everything below the baseline of the bottom-most line of text, so you couldn’t tell if something was an i or a j.
  • Like in Windows, in Linux, modal dialogs have a really bad habit of sucking up keyboard focus, focusing on a button, and then making my next keystroke click the button. The fact that this is a widespread UI problem across most operating systems is just silly.

There were more nitpicks, but I felt like a large number of these issues could have probably be resolved by switching to a better window manager. I was honestly expecting better than this, though. LXDE was supposed to be like XFCE, but apparently it’s actually XCFE with all it’s redeeming qualities removed. However, it turns out that this doesn’t matter! To discover why, we have to examine what happened next.

My friend suggested to get Linux Mint, which has a better window manager and would probably address most of those issues. So, I downloaded the ISO. I already had a USB set up for booting that had Lubuntu on it, so I wanted to see if I could just extract the contents of the ISO and put them on the USB stick. I have no idea if this would have actually worked or not, and I never got to find out because upon clicking and dragging the contents of the ISO out of the archive manager, with the intent of extracting them, the entire system locked up.

Now, I’m not sure how stupid trying to drag a file out of an ISO was, but I’m pretty sure it shouldn’t render my entire computer unusable. This seems like an unfair punishment. Attempts to recover the desktop utterly failed, as did ctrl-alt-del, alt-F2, alt-anything else, or even trying to open a terminal (my friend would later inform me that it is actually *ctrl-alt-F2* that opens the terminal, but I couldn’t ask him because the entire desktop had locked up!). So I just restarted the machine.

That was the last time I saw my Lubuntu desktop.

Upon restarting my machine, I saw the Lubuntu loading screen come up, and then… nothing. Blackness. About 20 seconds later, an error message pops up: “Soft Lock on CPU#0!”. Then the machine rebooted.

After spending just one hour using linux, it had bricked itself.[2] I hadn’t even gotten steam working yet, and now it was completely unusable. This is not “getting better”, this is strapping a rocket to your ass and going so fast in the wrong direction you break the sound barrier. Now, if you have been paying attention, you will note that I had just finished installing my nVidia drivers before the desktop locked up, and that the drivers probably wouldn’t actually be used by the desktop environment until the process was restarted. After mounting my linux partition in windows and extracting my log files, I sent them to my friend, who discovered that it had indeed been the nVidia driver that had crashed the system.[3]

This is problematic for a number of reasons, because those drivers were written for Ubuntu based distros, which means my system could potentially lock up if I installed any other ubuntu based distro, which is… just about all the ones that I cared about. Including Linux Mint. At this point, I had a few options:

  1. Install another ubuntu based distro anyway and hope it was a fluke.
  2. Install something based on Debian or maybe Fedora.
  3. Use the open-source drivers.
  4. Fuck this shit.

Unfortunately, I have little patience left at this point, and after seeing Linux first lock up after trying to drag files before bricking itself, I don’t really have much confidence in the reverse-engineered open-source nVidia drivers, and I certainly am not going to entrust my video card to them in the hopes it doesn’t melt. I really, really don’t want to play whack-a-mole with Linux distros, trying to find the magical one that wouldn’t wreck my graphics card, so I have simply opted for option 4.

But it doesn’t end there.

About two or three hours after this all happened (I had been fairly distracted, and by distracted I mean }}blinded by rage), I noticed that my windows clock was way off. At this point, I remembered something my friend had told me about - Linux, like any sane operating system would, sets the hardware clock to UTC and then modifies it based on the timezone. Windows, on the other hand, decided it would be a fantastic idea to set the hardware clock to local time. Of course, this should have been an easy fix. I just set the time back, forced an update, and bam, time was accurate again. Crisis averted, right?

No, of course not. Linux had not yet finished punishing me for foolishly believing I was worthy of installing something of it’s calibre. Because then I opened Skype, and started receiving messages in the past. Or more accurately, my chat logs were now full of messages that had been sent tomorrow.

It was at this point I realized what had happened. It wasn’t that the timezone had been changed, or something reversible like that. The hardware clock itself had been modified to an incorrect value. Skype had spent the past two hours happily sending messages with a timestamp 8 hours in the future because some idiot at Microsoft thought it was a good idea to set the hardware clock to local time, and now all these incorrect client side timestamps had been propagated to the cloud and synced across all my devices.

I slowly got up from my computer. I walked over to my bed, lied down, curled into a ball, and wept for the future of mankind.


1 I may have gotten these package names slightly wrong, but I can’t verify them because Linux won’t boot up! 2 It’s probably entirely possible to rescue the system by mounting the file system and modifying the x config file to not use nvidia, but this was supposed to just be “install linux and set it up”, not “install linux and spend the next 5 hours frantically trying to get it to boot properly.” 3 After submitting my log files to #ubuntu to report the issue, my friend discovered that the drivers for ATI/AMD graphics drivers are also currently broken for many ubuntu users. What timing! This certainly makes me feel confident about using this operating system!

"I have the solution, but it only works in the case of a spherical cow in a vacuum." - *[old physics proverb](https://en.wikipedia.org/wiki/Spherical_cow)*
Whenever I am designing something, be it an API or a user interface, I try to remember that I am not designing this for a perfectly rational agent. Instead, I am designing software for a bunch of highly emotional, irrational creatures called *human beings*, all of whom have enormously different tastes. I try to include options, or customization, or if that isn't possible, a compromise. I try to keep the door open, to let my software be used as a tool to enhance someone's productivity no matter what workflow they use, instead of trying to impose my own workflow on them.

For some reason, many programmers seem to struggle with the concept of people being different. They get hung up on this naïve concept of right or wrong, as if life is some kind of mathematical equation that has a closed form solution. Let me say right now that any solution to life is going to be one heck of a chaotic nonlinear PDE, which won’t have any closed form solution at all, and certainly not one using elementary functions. When you are developing software, you must keep in mind the range of customers who will be using your product, whether they are office workers or fellow programmers.

Maybe someone is using your product to try and finish a presentation in time to go home and catch a nap before they get up to work their second job so they can support a wife and a screaming baby. Someone else might use your product to track their progress as they try to revolutionize search from their bedroom instead of study for their finals next week. Someone else might be an elderly man trying to figure out how his vacation is going to go.

We are all different. We arise from all walks of life and are bound together in a great journey on this blue ball hurtling through space. It is not cowardice when two people try to put aside their differences and work together, it is strength. It requires enormous courage to admit that there are no simple answers in life. There are no answers in the back of the textbook. There are many different answers, all different in subtle ways, all suitable for slightly different circumstances, all both right and wrong in their own, strange, quirky ways.

Some programmers seem distressingly incapable of compassion or empathy. Many claim to live through the cold hard logic of data, without apparently realizing that data itself is inherently meaningless. It is only given meaning through a human’s interpretation, and a human can interpret data to mean whatever they want. They seem to think they can solve problems by reducing everyone into neat little collections of numbers that can be easily analyzed. It’s certainly a lot less frustrating to work with real numbers instead of real people, but inevitably, a programmer must come to terms with the fact that life is about human beings, not numbers on a screen.

The cold hard logic of our code is good for speaking to computers—it is not good for speaking to other human beings.

*The only thing more addicting than heroine are numbers that keep getting larger.*

Incrementer and idle games are seemingly simplistic games where you wait or click to increase a counter, then use that counter to buy things to make the counter go up faster. Because of the compounding effects involved, these types of games inevitably turn into a study of growth rates and how different functions interact. Cookie Clicker is perhaps the most well-known, which employs an exponential growth curve for the costs of buildings that looks like this:

\[ Cost_n = Cost_0\cdot 1.15^n \]

Where $$ Cost_0 $$ is the initial cost of the building. Each building, however, has a fixed income, and so the entire game is literally the player trying to purchase upgrades and buildings to fight against an interminable exponential growth curve of the cost function. Almost every single feature added to Cookie Clicker is yet another way to battle the growth rate of the exponential function, delaying the plateauing of the CPS as long as possible. This includes the reset functionality, which grants heavenly chips that yield large CPS bonuses. However, no feature can compensate for the fact that the buildings do not have a sufficient growth rate to keep up with the exponential cost function, so you inevitably wind up in a dead end where it becomes almost impossible to buy anything in a reasonable amount of time regardless of player action.

Pony Clicker is based off Cookie Clicker, but takes a different approach. Instead of having set rates for each building, each building generates a number of smiles based on the number of ponies and friendships that you have, along with other buildings that “synergize” with that building. The more expensive buildings generate more smiles because they have a higher growth rate than the buildings below them. This makes the game extremely difficult to balance, because you only have equations and the cost curves to work with, instead of simply being able to set the per-building SPS. Furthermore, the SPS of a building continues to grow and change over the course of the game, further complicating the balance equation. Unfortunately, in the first version of the game, the growth rate of the end building exceeded the growth rate of the cost function, which resulted in immense end-game instability and all around unhappiness. To address balance problems in pony clicker, rather than simply throwing ideas at the wall and trying to play test them infinitely, I wrote a program that played the game for me. It uses a nearly optimal strategy of buying whatever the most efficient building is in terms of cost per +1 SPS increase. This is not a perfectly optimal strategy, which has to take into account how long the next building will need to take, but it was pretty close to how players tended to play.

Using this, I could analyze a game of pony clicker in terms of what the SPS looked like over time. My first graph was not very promising:

The SPS completely exploded and it was obviously terrible. To help me figure out what was going on, I included a graph of the optimal store purchases and the time until the next optimal purchase. My goal in terms of game experience was that no building would be left behind, and that there shouldn’t be enormous gaps between purchases. I also wanted to make sure that the late game or the early game didn’t take too long to get through.

In addition to this, I created a graph of the estimate SPS generation of each individual building, on a per-friendship basis. This helped compensate for the fact that the SPS changed as the game state itself changed, allowing me to ensure the SPS generation of any one building wasn’t drastically out of whack with the others, and that it increased on a roughly linear scale.

This information was used to balance the game into a much more sane curve:

I then added upgrades to the main graph, and quickly learned that I was giving the player certain upgrades way too fast:

This was used to balance the upgrades and ensure they only gave a significant SPS increase when it was really needed (between expensive buildings, usually). The analysis page itself is available here, so you can look at the current state of pony clicker’s growth curve.

These graphs might not be perfect, but they are incredibly helpful when you are trying to eliminate exponential explosions. If you got a value that spirals out of control, a graph will tell you immediately. It makes it very easy to quickly balance purchase prices, because you can adjust the prices and see how this affects the optimal gameplay curve. Pony Clicker had so many interacting equations it was basically the only way i could come up with a game that was even remotely balanced (although it still needs some work). It’s a great example of how important rapid feedback is when designing something. If you can get immediate feedback on what changing something does, it makes the process of refining something much faster, which lets you do a better job of refining it. It also lets you experiment with things that would otherwise be way too complex to balance by hand.

*"Any headline that ends in a question mark can be answered by the word 'No'."* - Davis' law

Putting Commercial and Open-Source together is often considered an oxymoron. Part of this is caused by constant confusion between the terms Open-Source and Free Software, which is made even worse by people who have more liberal interpretations of the phrase “Open-Source”. In many cases, keeping the source code of a product proprietary serves no other purpose than to prevent people from stealing the product. Putting an application under the GPL and selling it is perfectly reasonable for software aimed at end-users, whom are unlikely to know how to compile the freely available source. Libraries aimed at developers, however, usually must resort to Dual Licensing.

To me, dual licensing is a bit of a hack job. Using two fundamentally incompatible licenses at the same time always rubbed me the wrong way, even if it’s perfectly legal for the creator of the software. The other problem is that this is usually done via copyleft licenses, and I would prefer more permissive licenses, given that I only care about whether or not the result is commercial or not. This, however, turns out to be a bit of a problem.

My ideal license for a commercial library would state that anyone is free to modify, distribute, or use the source code in anything they want, provided the resulting source code retains the provided license. If the resulting product is strictly noncommercial, it would be free. If, however, the source code or any derivation of the source code is used in a commercial product, there would be a fee. It’d basically be an MIT license with an added fee for commercial derivative works, with additional restrictions on what commercial derivative works are allowed.

The problem is, even if I were to use a dual-licensing strategy, there is no open-source license that contains a noncommercial restriction, because this isn’t open-source. Specifically, it violates Freedom 1 as defined by OSI:

1. The license **shall not restrict any party from selling** or giving away the software as a component of an aggregate software distribution containing programs from several different sources. **The license shall not require a royalty or other fee for such sale.**

So, the first sentence of the definition of open-source software has made it abundantly clear that my software isn’t open-source because I’m trying to make money off of it. This seems overly restrictive to me, because the source code is still freely available for people to distribute and modify, just not sell. Even then, they can still sell things made with the source code, they just pay a royalty or fee for it.

Now, there are good reasons why actual free software would forbid this. For example, if someone made an open-source library that required a royalty for commercial use whose code was repeatedly modified over and over again until it crept into all sorts of projects, it could then claim royalties on all of those products, even if only a few lines of its source code were used. This is obviously not conducive to creating a culture of sharing code.

However, there is another benefit of open-source software, which is now becoming progressively more obvious. It’s the fact that, if you have the source code and compile it yourself, you can verify the NSA (probably) hasn’t injected a backdoor into it. This is a benefit of visibility, and I think it should be encouraged. The problem is that the restrictions placed on free software are too harsh for most commercial libraries, who will then often resort to simply being proprietary.

So, sadly, there are no open-source commercial licenses, because those aren’t open-source. Perhaps we need a new term, for software whose source is accessible but has usage restrictions. Even then, it’s not entirely apparent what such a license would look like, or if sites like GitHub would actually allow it on public repositories. I took a peek at the Unreal Engine 4 license, but despite claiming to have it’s source code available on github, it’s actually in a private repository you must gain access to. To make matters worse, the actual Unreal Engine 4 license is incredibly restrictive. You are only allowed to distribute the engine code to other people who have agreed to the license! This obviously isn’t what I want, but apparently no one else seems to think that software that’s kind of open-source is actually valuable.

It’s an awful shame, because I really don’t want to make my project proprietary, but right now I don’t have much choice. As far as I’m concerned, releasing something under a restricted open-source license is preferable to making it entirely proprietary. Unfortunately, the loudest programmers are also the least likely to be willing to compromise over ideological divides.

Are there any programmers left that actually care about writing good software? As far as I can tell, the software development industry has turned into a series of echo chambers where managers scream about new features and shipping software and analyzing feedback from customers. Then they ignore all the feedback and implement whatever new things are supposed to be cool, like flat design, or cloud computing, or software as a service.

The entire modern web is built on top of the worst programming language that’s still remotely popular. It’s so awful that IE now supports asm.js just so we can use other languages instead. With everyone relentlessly misquoting “Premature optimization is the root of all evil”, it’s hard to get programmers to optimize any of their code at all, let alone get them to care about things like CPU caches and why allocation on the heap is slow and how memory locality matters.

Some coders exist at large corporations that simply pile on more and more lines of code and force everyone to use gigantic frameworks built on top of more gigantic frameworks built on top of even more gigantic frameworks and then wonder why everything is so slow. Other coders exist in startups that use Scala/Hadoop/Node.js and care only about pumping out features or fixing bugs. The thing is, all of these companies make a lot of money, which leads me to ask, does anyone actually want good software anymore?

Do customers simply not care? Is everyone ok with Skype randomly not sending messages and trying (poorly) to sync all your messages and randomly deciding that certain actions are always unread on other computers and dropping calls and creating all sorts of other strange and bizarre bugs? Is everyone ok with an antivirus that demands you sign in to a buggy window that keeps losing focus every time you try to type in your password? Is everyone ok with Visual Studio deciding it needs to open a text file and taking 15 seconds to actually start up an entirely new instance even though I already have one running just to display the stupid file?

It seems to me that we’re all so obsessed with making cool stuff, we’ve forgotten how to make stuff that actually works.

Did you know that every single person I know (except for two people) hates flat design? They don’t like it. I don’t like it. There’s a bunch of stuckup, narcissistic designers shoving flat design down everyone’s throats and I hate it. The designers don’t care. They insist that it’s elegant and modern and a bunch of other crap that’s all entirely subjective no matter how hard they try to pretend otherwise. Design is about opinions. If I don’t like your design, you can’t just go and say my opinion is wrong. My opinion isn’t wrong, I just don’t agree with you. There’s a difference.

However, it has become increasingly apparent to me that opinions aren’t allowed in programming. I’m not allowed to say that garbage collectors are bad for high performance software. I’m not allowed to say that pure functional programming isn’t some kind of magical holy grail that will solve all your problems. I’m not allowed to say that flat design is stupid. I’m definitely not allowed to say that I hate Python, because apparently Python is a religion.

Because of this, I am beginning to wonder if I am simply delusional. Apparently I’m the only human being left on planet earth who really, really doesn’t like typing magical bullshit into his linux terminal just to get basic things working instead of having a GUI that wasn’t designed by brain-dead monkeys. Apparently, I’m the only one who is entirely willing to pay money for services instead of having awful, ad-infested online versions powered by JavaScript™ and Node.js™ that fall over every week because someone forgot to cycle the drives in a cloud service 5000 miles away. Apparently, no one can fix the audio sample library industry or the fact that most of my VSTi’s manage to use 20% of my CPU when they aren’t actually doing anything.

Am I simply getting old? Has the software industry left me behind? Does anyone else out there care about these things? Should I throw in the towel and call it quits? Is the future of software development writing terrible monstrosities held together by duct tape? Is this the only way to have a sustainable business?

Is this the world our customers want? Because it sure isn’t what I want.

Unfortunately, writing music doesn’t pay very well.

*"Nothing is foolproof to a sufficiently talented fool."*   — Anonymous

Programmers love to bash things like templates and multiple-inheritance and operator overloading, saying that they are abused too often and must be unilaterally banned, going so far as to design them out of their programming languages thinking this is somehow going to save them.

This makes about as much sense as saying that bank robbers use cars to escape police too much, so we need to ban cars.

Templates, fundamentally, are very useful and perfectly reasonable things to use in most sane contexts. They are used for things like vectors, where you want an int vector and a float vector. However, people point to the horrible monstrosities like Boost and say “Look at all the havoc templates have wrought!” Well, yeah. That’s what happens when you abuse something. You can abuse anything, trust me. You simply cannot write a programming language that’s idiot proof, because if you make anything idiot proof, someone will just make a better idiot.

Multiple inheritance is usually useful for exactly one thing: taking two distinct object inheritance lines and combining them. If you ever inherit more than two things at once, you probably did something wrong. The problems arise when you start inheriting 8 things and create gigantic inheritance trees with diamonds all over the place. Of course, you can build something just as confusing and unmaintable with single-inheritance (just look at the .net framework), but the point is that the language doesn’t have a problem for letting you do this, you have an architectural issue because you’re being an idiot.

You do have code reviews, right? You do realize you can just tell programmers to not do this, or simply not use a library clearly written by complete maniacs? Chances are you probably shouldn’t have more than one or two template arguments or inherited classes, and you really shouldn’t overload the + operator to subtract things. If you do, someone should tell you you’re being an idiot in a code review, and if you keep doing it, they should just fire you.

What really bothers me about these constant attacks on various language features or methodologies is that nearly all of them are Slippery Slope fallacies. If we let programmers do this, they’ll just make something more and more complicated until nobody can use it anymore! It’s the same exact argument used for banning gay marriage! If your response to a programmer abusing a feature is to remove the feature, I really have to ask, why don’t you just fire them? The programmer is the problem here. If anyone succeeds in checking awful code into your code base, you either have a systemic failure in your process, or you’ve hired an idiot that needs to be fired.

Programming languages are toolboxes. I want my array of tools to be powerful and adaptable, not artificially castrated because other programmers can’t resist the temptation to build leaning towers of inheritance. It’s like forcing all your carpenters to use hammers without claws, or banning swiss army knives because someone was using it wrong. If someone is using a tool wrong, it’s because they haven’t been trained properly, or they’re incompetent. The mindset of banning problematic features in programming languages arises from coders who have to maintain bad code, and who are deluding themselves into thinking that if they got rid of those pesky templates, their lives would be much easier.

Having personally seen a visual basic program that succeeded in being almost impossible to decipher even after several weeks, I can assure you this is not the case, and never will be. The problem is that it’s bad code, not that it’s written in C++.

It’s that time of the year again, when everyone and their pony puts on a sale, except now it seems to have started much earlier than the traditional Black Friday. Needless to say, this is the only time of year I go around buying expensive sample libraries. One of these libraries was recommended by a friend: LA Scoring Strings - First Chair 2, a cheaper version of LA Scoring Strings. It’s $100 off, which is pretty nice, except that the page that describes the product doesn’t actually have a link to buy it. You have to click the STORE link, and then buy it from there, because this is a completely obvious and intuitive interface design (it isn’t).

So, after finding the proper link in the Store and verifying I am actually purchasing what I want to purchase, they give me exactly one payment option: Paypal. This is pretty common, so we’ll let it slide, and the whole process seems to go smoothly until they give me my receipt. On the receipt page, they gave me a link to download the files, and a serial number. How helpful! Until I click the download link, which does not open in a new window, and instead opens a completely different webpage with absolutely no way to get back to the page I was just on, because there is no store page with this information and I have no user account on this site. So, I have to go to my e-mail, where they have helpfully e-mailed me a copy of the receipt (probably for this exact reason) to get the serial number.

I then go back to the download page only to discover that I am required to use their stupid download manager in order to download the product I just bought. There is no alternative option whatsoever. So I download their stupid download manager and it magically installs itself somewhere on my computer I will likely never be able to find because it never asked my permission to do anything, and then demands that I log in. Well, obviously, I don’t have a log in, and no one asked me to register until now, so I go to register, which helpfully opens my web browser to register… on a forum. Well, ok, so I register on the forum with a randomly generated password, and activate my account.

So naturally, they then e-mail my password back to me, which by definition means they are storing it in plaintext. So now the password to my account was sent over an unencrypted, entirely open channel, which is insanely stupid, but this is just a sample library, so whatever. I go back to their download manager and put in my credentials and… the login fails. Well, maybe it takes a bit to propagate - no, it just isn’t working. I try again, and triple check that I have the password right. I log out and back into the forum with that very same password, and it still works. It just doesn’t work in the application.

Standard procedure at this point is for me to take every single weird punctuation character out of my password (making it much weaker) to address the possibility that these people are pants on head retarded and can’t handle a password with punctuation in it. I change my password to an alphanumeric one, and lo and behold, I can suddenly log in to the download manager! Let’s think about this for a moment. The password I used had some punctuation characters in it (like “!&#*@(?” etc.), but in order to make sure it was still a valid password, I logged in to the forum with that password, and it succeeded. I then went to this application and put in the same password and it failed to log me in, which means the program actually only accepts some random subset of all valid passwords that the forum lets you register with.

This is laughably bad programming, but my woes aren’t over yet. I click the download button only to get this incredibly helpful message: “Cannot connect to download servers.” Pissed off, I go play a game in the hopes that once I get back, the servers will work again. I close the game only to discover that my download manager is one giant grey screen no matter what i do to it. It’s forgotten how to draw it’s own UI at this point. I restart the program, and it has (of course) helpfully forgotten my login credentials. This time, it displays a EULA it apparently forgot to show me the first time around, and once I accept, clicking install successfully starts downloading the files!

Of course, once the files are installed, they aren’t actually installed installed. I have to go into Kontakt and add the libraries to it’s magical library in order for them to actually get recognized. I can’t tell if this is AudioBro’s fault or Native Instruments fault, but at this point I don’t care, because this has already become the worst installation experience of any piece of software I have had to go through in my entire life.

What’s frightening is that this is par for the course across the desolate wasteland that is Audio Sample Libraries. The entire audio engineering industry employs draconian and ultimately ineffective DRM security measures, often bundled with installers that look like they were written in 1998 and never updated. The entire industry uses software that is grotesquely bloated, digging it’s filthy claws into my operating system and doing all sorts of unspeakable things, and there is no way out.

You can’t disrupt this field, because samples rule everything. If you have good samples, people will buy your shitty sample libraries. EastWest moved from Kontakt (which is a pretty shitty piece of software considering it’s the best sampler in the entire industry) to their own proprietary PLAY engine, which is unstable, bloated, entirely dependent on ASIO4ALL to even work, and prone to crashing. They still make tons of money, because they have the best orchestral samples, which means people will put up with their incredibly bad sampler just so they can use their samples, which are all in a proprietary format that will get you violently sued if you attempt to reverse engineer it.

So, even if you develop the best sampler in the world, it won’t matter, because without samples, your software is dead on arrival. Almost all the samples that are worth having come in proprietary formats that your program can’t understand, and no one can convert these samples to another format (unless they want to reverse engineer the program and get sued, that is). So now the entire sampling industry is locked in a oligopoly of competing samplers that refuse to talk to each other, thus crushing competition by making the cost of entrance so prohibitively high no one can possibly compete with them. And then you get this shit.

*Reality is that which, when you stop believing in it, doesn't go away.* ― Philip K. Dick

Nowadays, you aren’t supposed to write anything yourself. In the world of open-source software, you’re supposed to find a library that does what you want, and if that doesn’t work, commit a change that makes it work. Writing your own library is a bad thing because it’s perceived as redundant if there’s already a library that does most of what you want. The problem is that this is inherently anti-competitive. If there’s only one library that does something, you have a monopoly, and then you get Heartbleed, because there’s zero diversification. However, if I try to invent my own wheel, I’ll just be scolded and told to contribute to an existing wheel instead, even if my wheel needs to have giant spikes on it.

I’m beginning to wonder if these people actually understand how software works. Code is not some kind of magical, amorphous blob that can just get better. It’s a skyscraper, built on top of layers and layers of code, all sitting on top of a foundation that dictates the direction the code evolves in. If someone invents a better way to architect your program, you can’t just swap pieces of it out anymore, because you are literally changing how the pieces fit together in order to improve the program. Now, I’m sure many coders would say that, if there’s a better architecture, you should just rip the entire program apart and rebuild it the better way.

The problem is that there is no one-size fits all solution for a given task. Ever. This is true for any discipline, and it is still true in the magical world of programming no matter how loudly you shout “LALALALALALA” while plugging your ears. By definition you cannot create a software library that is constructed in two different ways, because that is literally two different software libraries. Thus, just like how we have many different wheels for different situations, it is perfectly fine to reinvent the wheel to better suit the problem you are tackling instead of trying to extend an existing library to do what you want, because otherwise you’ll end up with a bloated piece of crap that still doesn’t do what you want. If you actually believe that it is possible to write a vector math library that covers all possible use scenarios for every possible solution, then I invite you to put monster truck tires on your smartcar and tell me how well that works. We might as well ask the Flying Spaghetti Monster to solve our problems instead.

You want there to be several different libraries for rendering vector graphics. You want there to be many different programming languages. You want there to be multiple text layout engines. These things create competition, and as each codebase vies to be used by more and more people, each will start catering to a slightly different set of problems. This creates lots of different tools that programmers can use, so instead of having to use their Super Awesome Mega Swiss Army Knife 4000, they can just use a butter knife because that’s all they goddamn need.

At this point, most coders will struggle to defend their position by falling back on the tried and true saying of “well, for most programmers, this is perfectly reasonable.” Exactly what do they mean by most programmers? Because most programmers use C++, C, and Java, and are probably maintaining systems that are 20 years old and couldn’t possibly apply anything they were just told in any realistic scenario. Do they just mean programmers who are making hip WebGL applications? What arbitrary subset of programmers are we talking about here? Of course, at this point, it doesn’t matter, because they are literally cherry picking whatever programming community supports their opinion, and we’re praying to the Flying Spaghetti Monster again.

Diversity is important. I am tired of programmers living in some fantasy world where all diversity has been eliminated and everyone follows the One True Path, and uses the One True Library for each individual task. This is not a world I want to live in, because my problems are not your problems, and even if your library is amazing at solving your problems, it probably won’t solve mine. I’ll go even further and say that this kind of thinking is dangerous. It reeks of cargo-cult coding and institutionalized knowledge designed to destroy creativity.

When people say you shouldn’t re-invent the wheel, they mean you shouldn’t re-invent the wheel if that’s not what you’re trying to do. If your main goal is to make a game, you shouldn’t write a graphics engine. If your main goal is to make a webpage, you shouldn’t write a webpage designer. However, if you just finished a game and think “Gee, that graphics engine was terrible, I’m going to make a better one,” then writing your own graphics engine is perfectly fine.

Including the entire jQuery library just so you can have the $("id") shortcut is like driving a smartcar with spiked monster truck wheels down a freeway. It’s dangerous, stupid, and completely unnecessary.

*When everyone's special, no one is.* — Anonymous

Time and time again, I hear the wise old members of our society insisting that my generation has been gravely misled. They claim that, by telling every child that they are special, no one is. They claim that everyone can’t be above average.

This is painfully ridiculous.

When someone says that every child is special, they are saying that each child is special in their own way. Each child is blessed with a gift of their own, wholly unique to them. Every child being above average is only a paradox if you are lumping every single human experience into one giant number, which is an insulting perversion of the diversity of life.

No human being will ever produce the exact same art, or solve a problem in the exact same way. Each of us brings our own unique experiences to the table, and that is why we are all valuable. Only by exploring a plurality of techniques can we find a better one. Only by bringing to bear a huge number of unique perspectives on a problem can we find an exceptionally elegant solution. One of those perspectives will see something that most of us don’t. One of those perspectives will create a work of art that no other human being could have conceived.

Yes, every child is special. Yes, every child can be above average… in their chosen field of interest.

A good example of this is to look at artists. Almost any artist who can do rudimentary shading is an above average artist. This is because most people aren’t professional artists. Once you start looking at professions, having even the tiniest drop of talent will likely catapult you into being above average, because our modern world is full of specialists. If you pick any random profession, the average skill level of that profession, when summing over the whole of the human race, will be close to zero, because most people aren’t in that profession.

So, simply by choosing a profession and learning the basics of it, a human being will be capable of doing things most other people can’t.

Telling kids they’re special is simply saying that they are unique, and that no other human being is like them. This is, much to the frustration of the institutions who would prefer us to be mindless factory drones, the truth. We each approach life in our own way, slightly different from everyone else. One person’s perspective may seem useless and bland, just a pale shadow of everyone else, until they happen to stumble on that one place where their slightly different view of the world let’s them see something no one else can.

When talking about a person as a whole, no one is better than anyone else. We simply experience the world in different, equally valid ways. We can be better than other people at a specific thing, but not in general.

Every snowflake is unique, but only when you look at them under a microscope. In the grand flurry of life, they all seem to blur together, forming featureless piles of uniformity. It is not enough to look for the truly exceptional. We must recognize that even the most insignificant details can make all the difference in the world.

It’s the little things that matter.

One of the most bizarre arguments I have ever heard in ethics is whether or not people can choose to be gay or not. The idea is, if being gay is genetically predetermined, it’s not their fault, therefore you can’t prosecute them for something they have no control over.

Since when did anyone get to choose what makes them happy? Can you choose to like strawberries? Can you choose to enjoy the smell of dandelions? At best, you can subject yourself to something over and over and over again and enjoy it as a sort of acquired taste, but this doesn’t always work, and the fact remains that you are still predisposed to enjoying certain experiences. Unless we make a concentrated effort to change our preferences, all enjoyable sensory experiences occur without our consent. We are not in charge of what combination of neural impulses our brain happens to find enjoyable. All we can do is slowly influence those preferences, and even then, only sometimes.

This concept of people choosing what they enjoy seems to have infected society, and is often at the root of much bizarre and often unfair prosecution. If we assume that people cannot significantly change the preferences they were dealt by life, either as a result of genetic or environmental influences, a host of moral issues become apparent.

Gender roles stop making sense. In fact, prosecuting anyone on the LGTB spectrum immediately becomes invalid. Attacking anyone’s sexual preferences, provided they are harmless, becomes unacceptable. Trying to attack anyone’s artistic or musical preferences becomes difficult, at best. We know for a fact that someone’s culinary preferences are influenced by the genetic distribution of taste buds in their mouth. It’s even hard to properly critique someone’s fashion choices if they happened to despise denim or some other fabric.

As far as I’m concerned, the answer to the question “why would someone like [x]” is always “because their brain is wired in a way that enjoys it.” Humans are, at a fundamental level, sensory processing machines that accidentally achieved self-awareness. We enjoy something because we are programmed to enjoy it. To insult what kinds of sensory input someone enjoys simply because they do not match up with your own is laughably juvenile. The only time this kind of critique is valid is when someone’s preferences cause harm to another person. We all have our own unique ways of processing sensory input, and so we will naturally enjoy different things, through no fault of our own. Sometimes, with a substantial amount of effort, we can slowly change some of those preferences, but most of the time, we’re stuck with whatever we were born with (or whatever environmental factors shaped our perception in our childhood).

Instead of accusing someone of liking something you don’t approve of, maybe next time you should try to understand why they like it, instead. Maybe you’ll find a new friend.

Frustrated with C profilers that are either so minimal as to be useless, or giant behemoths that require you to install device drivers, I started writing a lightweight profiler for my utility library. I already had a high precision timer class, so it was just a matter of using a radix trie that didn’t blow up the cache. I was very careful about minimizing the impact the profiler had on the code, even going so far as to check if extended precision floating point calculations were slowing it down.

Of course, since I was writing a profiler, I could use the profiler to profile itself. By pretending to profile a random number added to a cache-murdering int stuck in the middle of an array, I could do a fairly good simulation of profiling a function, while also profiling the act of profiling the function. The difference between the two measurements is how much overhead the profiler has. Unfortunately, my initial results were… unfavorable, to say the least.

BSS Profiler Heat Output: 
[main.cpp:3851] test_PROFILE: 1370173 µs   [##########
  [code]: 545902.7 µs   [##########
  [main.cpp:3866] outer: 5530.022 ns   [....      
    [code]: 3872.883 ns   [...       
    [main.cpp:3868] inner: 1653.139 ns   [.         
  [main.cpp:3856] control: 1661.779 ns   [.         
  [main.cpp:3876] beginend: 1645.466 ns   [.         
The profiler had an overhead of almost 4 microseconds. When you’re dealing with functions that are called thousands of times a second, you need to be aware of code speed on the scale of nanoseconds, and this profiler would completely ruin the code. At first, I thought it was my fault, but none of my tweaks seemed to have any measureable effect on the speed whatsoever. On a whim, I decided to comment out the actual _querytime function that was calling QueryPerformanceCounter, then run an external profiler on it.
Average control: 35 ns
What?! Well no wonder my tweaks weren’t doing anything, all my code was taking a scant 35 nanoseconds to run. The other 99.9% of the time was spent on that single, stupid call, which also happened to be the one call I couldn’t get rid of. However, that isn’t the end of the story; _querytime() looks like this:
void cHighPrecisionTimer::_querytime(unsigned __int64* _pval)
{
  DWORD procmask=_getaffinity(); 
  HANDLE curthread = GetCurrentThread();
  SetThreadAffinityMask(curthread, 1);
  
  QueryPerformanceCounter((LARGE_INTEGER*)_pval);
  
  SetThreadAffinityMask(curthread, procmask);
}

Years ago, it was standard practice to wrap all calls to QueryPerformanceCounter in a CPU core mask to force it to operate on a single core due to potential glitches in the BIOS messing up your calculations. Microsoft itself had recommended it, and you could find this same code in almost any open-source library that was taking measurements. It turns out that this is no longer necessary:

**Do I need to set the thread affinity to a single core to use QPC?**

No. For more info, see Guidance for acquiring time stamps. This scenario is neither necessary nor desirable.

I couldn’t get rid of the QueryPerformanceCounter call itself, but I could get rid of all that other crap it was doing. I commented it out, and voilà! The overhead had been reduced to a scant 340 nanoseconds, only a tenth of what it had been before. I’m still spending 90% of my calculation time calling that stupid function, but there isn’t much I can do about that. Either way, it was a good reminder about the entire reason for using a profiler - bottlenecks tend to crop up in the most unexpected places.

BSS Profiler Heat Output: 
[main.cpp:3851] test_PROFILE: 142416 µs   [##########
  [code]: 56575.4 µs   [##########
  [main.cpp:3866] outer: 515.43 ns   [....      
    [code]: 343.465 ns   [...       
    [main.cpp:3868] inner: 171.965 ns   [.         
  [main.cpp:3876] beginend: 173.025 ns   [.         
  [main.cpp:3856] control: 169.954 ns   [.         

I also tried adding standard deviation measurements, but that ended up giving me ludicrous values of 342±27348 ns, which isn’t very helpful. Apparently there’s quite a lot of variance in function call times, so much so that while the averages always tend to be the same over time, the statistical variance goes through the roof. This is probably why most profilers don’t include the standard deviation. I was able to add in accurate unprofiled code measurements, though, and the profiler uses a dynamic triple magnitude method of displaying how much time a function takes.

Many people assume that modern graphics technology is now capable of rendering photorealistic video games. If you define photorealistic as any still frame is indistinguishable from a real photo, then we can get pretty close. Unfortunately, the problem with video games is that they are not still frames - they move.

What people don’t realize is that modern games rely on faking a lot of stuff, and that means they only look photorealistic in a very tight set of circumstances. They rely on you not paying close attention to environmental details so you don’t notice that the grass is actually just painted on to the terrain. They precompute environmental convolution maps and bake ambient occlusion and radiance information into level architecture. You can’t knock down a building in a game unless it is specifically programmed to be breakable and all the necessary preparations are made. Changes in levels are often scripted, with complex physical changes and graphical consequences being largely precomputed and simply triggered at the appropriate time.

Modern photorealism, like the 3D graphics of ages past, is smoke and mirrors, the result of very talented programmers and artists using tricks of the eye to convince you that a level is much more detailed and interactive than it really is. There’s nothing wrong with this, but we’re so good at doing it that people think we’re a heck of a lot closer to photorealistic games then we really are.

If you want to go beyond simple photorealism and build a game that feels real, you have to deal with a lot of extremely difficult problems. Our best antialiasing methods are perceptual, because doing real antialiasing is prohibitively expensive. Global illumination is achieved by deconstructing a level’s polygons into an octree and using the GPU to cubify moving objects in realtime. Many advanced graphical techniques in use today depend on precomputed values and static geometry. The assumption that most of the world is probably going to stay the same is a powerful one, and enables huge amounts of optimization. Unfortunately, as long as we make that assumption, none of it will ever feel truly real.

Trying to build a world that does not take anything for granted rapidly spirals out of control. Where do you draw the line? Does gravity always point down? Does the atmosphere always behave the same way? Is the sun always yellow? What counts as solid ground? What happens when you blow it up? Is the object you’re standing on even a planet? Imagine trying to code an engine that can take into account all of these possibilities in realtime. This is clearly horrendously inefficient, and yet there is no other way to achieve a true dynamic environment. At some point, we will have to make assumptions about what will and will not change, and these sometimes have surprising consequences. A volcanic eruption, for example, drastically changes the atmospheric composition and completely messes up the ambient lighting and radiosity.

Ok, well, at least we have dynamic animations, right? Wrong. Almost all modern games still use precomputed animations. Some fancy technology can occasionally try to interpolate between them, but that’s about it. We have no reliable method of generating animations on the fly that don’t look horrendously awkward and stiff. It turns out that trying to calculate a limb’s shortest path from point A to point B while avoiding awkward positions and obstacles amounts to solving the Euler-Lagrange equation over an n-dimensional manifold! As a result, it’s incredibly difficult to create smooth animations, because our ability to fluidly shift from one animation to another is extremely limited. This is why we still have weird looking walk animations and occasional animation jumping.

The worst problem, however, is that of content creation. The simple fact is that at photorealistic detail levels, it takes way too long for a team of artists to build a believable world. Even if we had super amazing 3D modelers that would allow an artist to craft any small object in a matter of minutes (which we don’t), artists aren’t machines. Things look real because they have a history behind them, a reason for their current state of being. We can make photorealistic CGI for movies because each scene is scripted and has a well-defined scope. If you’re building GTA V, you can’t somehow manage to come up with three hundred unique histories for every single suburban house you’re building.

Even if we did invent a way to render photorealistic graphics, it would all be for naught until we figured out a way to generate obscene amounts of content at incredibly high levels of detail. Older games weren’t just easier to render, they were easier to make. There comes a point where no matter how many artists you hire, you simply can’t build an expansive game world at a photorealistic level of detail in just 3 years.

People always talk about realtime raytracing as the holy grail of graphics programming without realizing just what is required to take advantage of it. Photorealism isn’t just about processing power, it’s about content.

It seems that many people view success as some sort of absolute value, usually inextricably tied to how much money you make. Ignoring the fact that we should not be tying success to monetary value, we should also not be treating success as some sort of absolute value based on where you end up. What really matters is where you started from.

Climbing a mountain is not that impressive when you start half a mile from the peak. On the other hand, if you start all the way at the bottom, climbing the whole thing is very impressive, indeed. A blogger once said that being born as a middle-class straight white male is like playing life on easy mode. Minorities have many cultural barriers they must break down to reach the same level as a white male, often because they are born poor.

Poor people have a huge range of difficulties that are hard to appreciate unless one experiences them first-hand. To the middle-class, overdraft fees, parking tickets and unexpected taxes are nothing more than an annoyance. To the poor, they are the stuff of nightmares. A single slipup, a single misstep, and they will lose all the spending money they had for the next 3 months, and possibly not be able to buy dinner. They must work demanding, low-paying jobs that leave them physically and mentally exhausted, which itself makes it even harder for them to land a promotion or pursue their hobbies.

Robbed of the mental energy to work on things they find interesting and fun, poor people often slip into depression, or self-destructive lifestyles, because there literally is no way out. The only way out is for them to somehow be less stressed, which requires a better job, which requires them to have more time to spend bettering themselves, which requires them to be less stressed, which requires a better job…

It’s the worst kind of catch-22, and it’s one whose existence is repeatedly and blatantly denied by a middle-class oblivious to the struggles of the poor. They do not understand the herculean efforts it takes to do things that seem simple and routine for themselves. They do not appreciate how impressive it is when a poor person elevates themselves to a position that they might consider demeaning.

What’s worse is that they over-inflate their own progress, and then act as though a poor person could have done the same thing. “Just teach yourself how to do it,” they say. “Use the internet,” they say. They don’t understand that without a decent education, poor people either do not understand the importance of these things and shouldn’t be expected to, or they have so much to learn they can’t possibly find the time to do so in conjunction with the soul-sucking job that occupies most of their time. Being poor is not a slight disadvantage, it’s like starting a race half a mile behind your opponent with a lead weight attached to your ankle, and your opponent has a motorcycle.

Many of my acquaintances, when they hear of my 6-figure salary, automatically assume that I am successful. That I have somehow beaten the odds through concentrated effort and landed an amazing job they can only dream of. The truth is that what I have accomplished is hardly anything special. I won the genetic and environmental lottery. I was gifted with talents that gave me a jump start on skills that happened to be wildly in-demand in today’s economy. I went to excellent schools, and had attentive parents that never shielded me from my own failures, but encouraged me to learn from them. I worked just as hard as everyone else, but I didn’t even need to. My efforts in making music and building games never accomplished anything. All I had to do was dutifully finish my schoolwork until I graduated with a degree in applied mathematics, and poof, I had a fantastic, cushy job many people would kill for.

This is hardly impressive. I have simply traveled the path that was set up for me, and every attempt I made to excel, to do more than simply walk down the road in front of me me has been met with abject failure. I was given a gift, a free ride halfway up the mountain, and I haven’t made it very far at all. The people at the bottom look up to me and see success, without realizing that I have climbed the same distance they have.

They are just as successful as I am - they just started farther down.

When I see an artist just barely managing to make ends meet, I see success. When I see a musician living in a run-down apartment and paying rent, I see accomplishment. When I see a writer making ends meet with a few odd commissions, I see tenacity. Our culture heaps scorn on those who do what they love and barely manage to make a living out of it without realizing how brutally difficult this is to do. Simply managing to feed yourself by following your dream is an accomplishment on par with finishing a master’s degree.

I am not writing this to belittle myself, or others, but to elevate those who have accomplished a great deal, and get comparatively little recognition for it. I write this because too often artists set absurd goals for themselves without knowing that the ones they idolize didn’t climb nearly as many steps as themselves. Artists look around and see themselves barely surviving off of their art, and wonder if they are a failure, when in fact simply being able to sustain oneself like that is a great accomplishment. Sadly, it seems that it is an accomplishment that does not come with a diploma, or a trophy, or even respect.

I hope that artists, and poor people in general, will eventually realize that they are just as successful as everyone else - they just have more steps to climb.

Google is going down the drain.

That isn’t to say they aren’t fantastically successful. They are. I still use their products, mostly because I don’t put things on the internet I don’t want other people to find, and I’m not female, so I don’t have to worry about misogynists stalking me. They still make stupendous amounts of money and pump out some genuinely good software. They still have the best search engine. Like Microsoft, they’ll be a force to be reckoned with for many decades to come.

Google, however, represented an ideal. They founded the company with the motto “Don’t Be Evil”, and the unspoken question was, how long would this last? The answer, oddly enough, was “until Larry Page took over”.

In its early years, Google unleashed the creativity of the brilliant people it hired to the world and came up with a slew of fantastic products that were a joy to use. Google made huge contributions to the open-source world and solved scalability problems with an elegance that has yet to be surpassed. They famously let engineers use 20% of their time to pursue their own interests, and the result was an unstoppable tidal wave of innovation. Google was, for a brief moment, a shining beacon of hope, a force of good in a bleak world of corporations only concerned with maximizing profit.

Then Larry Page became CEO. Larry Page worshiped Steve Jobs, who gave him a bunch of bad advice centered around maximizing profit. The result was predictable and catastrophic, as the entire basis of what had made Google so innovative was destroyed for the sake of maximizing profit. Now it’s just another large company - only concerned about maximizing profit.

Google was a company that, for a time, I loved. To me, they represented the antithesis of Microsoft, a rebellion against a poisonous corporate culture dominated by profiteering that had no regard for its users. Google was just a bunch of really smart people trying to make the world a better place, and for a precious few years, they succeeded - until it all came tumbling down. Like an artist whose idol has become embroiled in a drug abuse scandal, I have lost my guiding light.

Google was largely the reason I wanted to start my own company, even if college kept me from doing so. As startup culture continued to suck the life out of silicon valley, I held on to Google as an ideal, an example of the kind of company I wanted to build instead of a site designed to sort cat photos. A company that made money because it solved real problems better than everyone else. A company that respected good programming practices, using the right tool for the job, and the value of actually solving a problem instead of just throwing more code at it.

Google was a company that solved problems first, and made money second.

Now, it has succumbed to maximizing stock price for a bunch of rich wall street investors who don’t care about anything other than filling their own pockets with as much cash as they possibly can. Once again, the rest of the world is forced to sit around, waiting until an investor accidentally makes the world a better place in the process of trying to make as much money as possible.

Most people think this is the only way to get things done. For a precious few years, I could point to Google and say otherwise. Now, it has collapsed, and its collapse has made me doubt my own resolve. If Google, of all companies, couldn’t maintain that idealistic vision, was it even possible?

Google gave me a reason to believe that humanity could do better. That we could move past a Wall Street that has become nothing more than a rotting cesspool of greed and corruption.

Now, Google has fallen, along with the ideal it encompassed. Is there a light at the end of the tunnel? Or is it a train, a force of reality come to remind us that no matter how much we reach for utopia, we will be sentenced to drown in our own greed?

**im·bro·glio** *noun* 1. an extremely confused, complicated, or embarrassing situation.
Across the country, there is a heated debate over our educational system. Unfortunately, it's a lot like watching members of the flat earth society argue about whose theory is right - there is no right answer, because *everyone is wrong*.

The most recent and perhaps egregious example of this is a breathtakingly misguided article by Kevin G. Welner, who is the director of the National Education Policy center, which is absolutely terrifying. He is attempting to discredit the idea of “tracking”, wherein low-performing students are separated from higher achieving students, because obviously you can’t teach kids who “get it” the same way as kids who are struggling. Unfortunately, the entire conclusion rests on a logical fallacy. He says, and I quote:

"When children fall behind academically, we have a choice. We can choose to sort them into less demanding classes where they will fall further behind, or we can choose to include them in classes that maintain high expectations."
This is a [false dichotomy](http://en.wikipedia.org/wiki/False_dilemma), since there are many other choices. We can sort them into a class with the same expectations, but an alternative teaching method. Sort them into a class that actually pays attention to the concepts that are giving them trouble. The idea is to help children who have fallen behind *catch up with their peers*, not throw them in a room and forget about them. Schools that simply lower their expectations of poorly performing students are doing it wrong. Furthermore, trying to argue that something can't work because no one's doing it properly is [another logical fallacy](http://en.wikipedia.org/wiki/Argument_from_ignorance).

There’s also a persistent argument against charter schools, which claims that the money spent on charter schools should instead be used to improve public schools instead. This is laughable, because public schools receive funding based on test scores. So, all the money would be spent improving test scores instead of actually teaching children anything. Charter schools are important because they aren’t bounded by these nonsensical restrictions and thus are free to experiment with alternative teaching styles. Throwing money at our public schools will only shore up a method of teaching that’s fundamentally broken. It’s like trying to fix the plumbing after the roof caved in - it’s completely missing the point.

To make matters worse, there’s also a war on free time. Recess is being cut in favor of increased instruction time, while educators cite minuscule increases in test scores as proof that this “works”. If by “works”, you mean it succeeds in cramming more useless junk into kids heads, then sure, it’s “working”. However, if you want kids to actually learn instead of memorize pointless facts that they will immediately forget, you have to give them time to process concepts. Their brains need rest, not more work. Bodybuilders don’t lift weights as long as they can every single day; they lift weights every other day and only for a few hours or so, because the muscle needs time to recover.

This, however, is an issue with a society that thinks hard work means working yourself to exhaustion. This is incredibly short-sighted and in direct opposition to plenty of evidence that points to rest being a necessary part of a healthy lifestyle. It can be your job, or school, or a hobby, it doesn’t matter. Humans do not function effectively when forced to focus on one thing for hours at a time. The only reason we attempt to do this is because we used to work in factories, but nowadays we have robots. Modern jobs are all about thinking creatively, which cannot be forced. You can’t force yourself to understand a concept. It’s like trying to force a broken leg to heal faster by going for a jog. You must give kids time absorb concepts instead of trying to cram it down their throats. They need to understand what they are learning, not memorize formulas.

Mainstream education doesn’t take this seriously. There are plenty of experiments that have effectively taught children advanced concepts with radically different teaching methods. One guy taught 3rd graders binary. These kids learned english and how to operate a computer without a teacher at all. There are plenty of cases that show just how woefully inadequate our teaching system is, but it seems that we care more about a one-size-fits-all method that can be mass-produced than a method that’s actually effective.

Our educational system is failing our students, and we refuse to even entertain notions that could make a difference. Instead, we just legislate more tests and take away their recess.

Because really, memorizing the date of the Battle of Gettysburg is more important than playing outside and having a childhood.

*Creating a life that reflects your values and satisfies your soul is a rare achievement. In a culture that relentlessly promotes avarice and excess as the good life, a person happy doing his own work is usually considered an eccentric, if not a subversive. Ambition is only understood if it's to rise to the top of some imaginary ladder of success. Someone who takes an undemanding job because it affords him the time to pursue other interests and activities is considered a flake. A person who abandons a career in order to stay home and raise children is considered not to be living up to his potential - as if a job title and salary are the sole measure of human worth. You'll be told in a hundred ways, some subtle and some not, to keep climbing, and never be satisfied with where you are, who you are, and what you're doing. There are a million ways to sell yourself out, and I guarantee you'll hear about them.

To invent your own life’s meaning is not easy, but it’s still allowed, and I think you’ll be happier for the trouble.*

  — Bill Watterson, 1990 speech at Kenyon College

Someone, once again, is complaining about those misbehaving youngsters who don’t understand the value of hard work. He lampoons the advice to follow your passion, saying that young people are just scared of hard work. He makes the dangerously misinformed claim that burn-out is just a myth: “Burn out is just a rationalization for giving up early.”

For someone who seems so sure of what they’re talking about, it would be difficult for him to be more wrong. Following your passion doesn’t mean you do less work. It doesn’t even mean you’ll avoid doing boring things. A standard 9-5 job doesn’t require you to think. You drive to work, get told what to do by some guy in a suit for 8 hours, then go home. It’s about following instructions, not actually doing anything difficult. Most programmers are lucky, and have plenty of employers who give them interesting problems to work on. In fact, for calling his post “The Hacker News Generation”, he doesn’t seem to understand his audience very well. One of the current talking points is startups overworking their employees by expecting 80 hour work weeks, and how employees are trained to think this is ok.

That kind of seems like the exact opposite of an aversion to hard work.

Following your passion is immeasurably more difficult than climbing a corporate ladder. You usually work more hours for less pay, and often have to struggle to make ends meet. You have to do every part of your job, including all the mind-numbingly boring stuff, because there isn’t anyone else to do it. People who are following their passion enjoy it more because they’re doing something that’s important to them, not because they’re doing less work. An artist is the one drawing constantly, every day, barely making enough money to feed themselves. The guy at Microsoft writes a bunch of test code, checks it in, then gets lunch at the cafeteria. Where does this glorification of doing boring, repetitive tasks come from?

These people are busy climbing a ladder that society has put in front of them. They look out and see someone running around on the ground, away from the ladder, and become convinced they are hopelessly lost. Clearly, they don’t understand the value of ladder climbing. When they realize that other people don’t care about the ladder, they immediately conclude that these people don’t understand what’s important, because the only success they know of is the success they were promised by society at the top of the ladder.

A human being’s worth cannot be measured in dollars or promotions. To follow one’s dreams is not an act of cowardice, but rather one of incredible courage. To resist taking the easy way out, to avoid the routine of a 9-5 job, is to accept a life that is often filled with failure and hardship. The difference is that it will be a life worth living.

I use FL Studio 11 to make my music. Some people find this surprising, due to FL Studio’s stigma as being a “toy” DAW that it simply cannot seem to shake, despite the fact it actually does most things as well or better than other professional DAWs. FL Studio has two real, significant issues: Large projects are unstable, and it has extremely bad 64-bit support.

This is almost never what people actually complain about. Instead, people complain about FL studio lacking features when they really just need to enable the right option. My friend lamented FL Studio’s poor handling of automation clips without knowing about the “browse parameters” feature that lists all of a synth’s parameters and highlights the one you are changing. He then complained that it didn’t play notes when you started playback in the middle of them - this can be toggled in the audio settings. He also didn’t know how to group multiple instruments to be controlled by the same piano roll, so I had to show him how to use Layers. Every single reason he gave for FL Studio being crap was just him not understanding how to use it properly, or not knowing where to find a specific feature.

This is the exact same problem Microsoft had with Word, and it’s what resulted in the Ribbon GUI overhaul. Every reason people gave for not liking Word was just a result of them not being able to find the feature they wanted in an endless cascade of menus. To address this, it required a GUI overhaul so those features were grouped in intuitive ways, so people could find them more easily.

Even APIs can suffer from the Microsoft Word Problem. OpenGL, especially it’s early incarnations, was essentially a giant, opaque list of functions that randomly referenced each other and had no clear organization. The online documentation is literally just an alphabetized list of every single OpenGL function in existence. The end result is that you need to know precisely what you want to do in order to find the right function. This is in contrast to DirectX, which (for example) has every single renderstate in a single, enormous enumerator. That enumerator contains something like 50 or so equivalent OpenGL function calls, which are not grouped in any meaningful way. It’s documentation, like everything else on MSDN, is organized in hierarchical groups. DirectX tells you every single possible thing you theoretically might be able to do with your graphics card. OpenGL, on the other hand, has extensions, which are both a blessing and a curse. It makes OpenGL inherently more adaptable than DirectX, but at the cost of having absolutely no idea what the graphics card may or may not be capable of, because it’s just not in OpenGL, it’s in some extension you have to dig up.

Just like Microsoft Word, the features are all there in OpenGL, they’re just harder to get to. And you’d better hope you know exactly what your technique is called, or you’ll never find the function you want. WebGL inherits this problem, and throws on a few of its own inherent with attempting to bolt a low-level C api on to a high level web language that needs to be sandboxed.

We can’t simply implement a feature, we have to make it easy to find, and easy to use, or it’s worthless. It’s amazing how quickly programmers forget the importance of context. In all of these cases, the solution to feature overload is conceptually very similar - Word created the Ribbon, which grouped related features under tabs and sub-groups. A similar grouping of OpenGL functions and parameters would do wonders for it’s usability. FL Studio would also benefit by dumping it’s left-hand browsing bar in favor of a Ribbon or module approach that didn’t force 15 wildly different GUI styles into a single menu.

Context is important. If I want to find the function that sets the alpha blending operation in OpenGL, I should not have to go through over 300 functions to find it. I should be able to go to the “sampling” functions and look in the “blending” subgroup, and poof, all the functions that have anything to do with blending are there. It doesn’t matter if we’re designing word processors, digital audio workstations, low level APIs, middleware, or web applications. Anything and everything is susceptible to the Microsoft Word Problem.

*"Everything should be as simple as possible, but not simpler."* - Albert Einstein ([paraphrased](http://quoteinvestigator.com/2011/05/13/einstein-simple/#more-2363))

The burgeoning complexity of software is perhaps one of the most persistent problems plaguing computer science. We have tried many, many ways of managing this complexity: inventing new languages, creating management systems, and enforcing coding styles. They have all proven to be nothing more than stopgaps. With the revelation that the NSA is utilizing the inherent complexity of software systems to sabotage our efforts at securing our systems, this problem has become even more urgent.

It’s easy to solve a problem with a lot of code - it’s hard to solve a problem with a little code. Since most businesses do not understand the advantage of having high quality software, the most popular method of managing complexity is not to reduce how much code is used, but to wrap it up in a self-contained library so we can ignore it, instead. The problem with this approach is that you haven’t gotten rid of the code. It’s still there, it’s just easier to ignore.

Until it breaks, that is. After we have wrapped complex systems into easy-to-use APIs, we then build even more complex systems on top of them, creating networks of interconnected components, each one encapsulating it’s own complex system. Instead of addressing this burgeoning complexity, we simply wrap it into another API and pave over it, much like one would pave over a landfill. When it finally breaks, we have to extract a core sample just to get an idea of what might be going wrong.

One of the greatest contributions functional programming has made is its concept of a pure function with no side-effects. When a function has side effects, it’s another edge on the graph of components where something could go wrong. Unfortunately, this isn’t enough. If you simply replace a large complex system with a bunch of large complex functions that technically have no side-effects, it’s still a large complex system.

Object-oriented programming tries to manage complexity by compartmentalizing things and (in theory) limiting how they interact with each other. This is designed to address spaghetti code that has a bunch of inter-dependent functions that are impossible to effectively debug. The OO paradigm has the right idea: “an object should do exactly one thing, and do it well”, but suffers from over-application. OO programming was designed to manage very large complex objects, not concepts that don’t need Get/Set functions for every class member. Writing these functions just in case you need them in the future is a case of future-proofing, which should almost always be avoided. If there’s an elegant, simple way to express a solution that only works given the constraints you currently have, USE IT. We don’t need any more leaning towers of inheritance.

The number of bugs in a software program is proportional to how much code you write, and that doesn’t include cheap tricks like the ternary operator or importing a bunch of huge libraries. The logic is still there, the complexity is still there, and it will still break in mysterious ways. In order to reduce the complexity in our software, it has to do less stuff. The less code you write, the harder it is for the NSA to sabotage your program without anyone noticing. The less code you write, the fewer points of failure your program will have. The less code you write, the less stuff will break. We cannot hide from complexity any longer; we must actively reduce it. We have to begin excavating the landfill instead of paving over it.

*Premature optimization is the root of all evil* - Donald Knuth

Ever since I started putting words on the internet, I have complained about the misinterpretation and overgeneralization of this Donald Knuth quote. Developers essentially use it as an excuse to never optimize anything, because they can always say they “aren’t done yet” and then permanently render all optimizations as premature. The fact that “premature” is inherently a subjective term doesn’t help. The quote was meant to target very low-level optimizations that are largely useless until you’re positive everything else is working properly and you have no other low-hanging fruit to optimize.

Instead of following that advice, and only doing complex optimizations after all the low-hanging fruit has been picked, developers tend to just stop optimizing after the low-hanging fruit is gone. Modern developers will sometimes stop optimizing things entirely and leave it up to the compiler, which almost always does a horrible job at it. Because web development is inherently dependent on one of the worst programming languages currently being used by anyone, these issues are even more prominent.

When people complain about stuff not working on their phones while on shitty internet connections (which is every single free wifi hotspot ever), the developers tell them to stop using shitty internet connections. When they complain about how slow and unresponsive a stupid, unnecessary app whose entire purpose is to just display text (I’m looking at you, Blogger), the developers tell them to get a better phone. When someone writes an app that doesn’t compress anything and sucks up bandwidth like a pig, for absolutely no reason at all, the developers tell them to get a better data plan.

What the fuck?

Just because you have a desktop with an 8-core processor and 32 gigs of RAM doesn’t mean your customers do. The number of people using the top-of-the-line technology is a tiny fraction of the total number of people who actually use the internet, which at this point is more than 1/3 the population of the entire human race. Only targeting hipster white kids who live in San Francisco and have rich parents may work for a small startup, but when Google’s mail app turns into a piece of sludge that moves about as fast as pitch at room temperature, we have crossed a line. Google is everywhere. Their stuff should work well on the shittiest internet connection you can imagine. You can’t go around expecting all your customers to have perfect internet all the time when it’s just not possible.

Don’t just target the latest version of Windows and tell the other versions to stuff it, because it’s almost never really necessary when all you’re doing is using 3 or 4 new functions introduced in Windows 7 that could easily be encapsulated in a small check. Don’t write your game in such a way that it will only be playable on a high end gaming machine because you will get a lot of flak. If making this happen is hard, you probably have a shitty game engine that has a bad architecture. Likewise, when my orchestral VSTi sucks up 10% of my CPU while it’s just sitting there and NOT ACTUALLY DOING ANYTHING, something is seriously wrong. I know it’s using the exact same sample format as Kontact (someone reverse-engineered it), except that it does everything 4 times slower. Yet, when people complain, and they complain all the time, the response is always “you need a better computer.”

Most people have shitty computers. Your customers don’t care about all the cool new features you can implement for your mail app now that you have time to work on them because you never bothered to optimize it properly - they just want a mail app that WORKS.

**Pros:**
  • For the most part, does what it claims it does, and gives you extremely precise, fast tracking of fingers.

Cons:

  • Really hates thumbs for some reason.
  • Has a lot of trouble with pens or other implements.
  • Fingers must be separated.
  • Fairly easy to get positions that break the camera because it can’t see the fingers.
  • No one has any idea how to write software for it.

I just got my Leap Motion device today, and for the most part, I like it. It does most of the things I expected it to do. It seems like something that could become very useful down the line. Unfortunately, right now, I wouldn’t recommend getting one if you wanted something that’s more than a toy.

This isn’t entirely the fault of the device itself, but more a combination of driver limitations and boneheaded software that doesn’t know what it’s doing. The device is so new, no one knows how to properly utilize it, so almost all the apps that exist right now are either garbage or ridiculously sensitive to your setup. There are, however, a few more serious problems that should be addressed by the Leap Motion team.

First of all, the driver hates thumbs. It seems like it’s trying to edit them out when they aren’t positioned like a finger, which makes any sort of pinching gesture impossible to do. In addition, it doesn’t like it when you try to use a pen, despite the fact that it’s specifically designed to let you do so. Both of these problems seem more like driver analysis problems, so I expect they’ll be corrected soon. I know these aren’t hardware limitations, because the camera can see the stupid pen, the driver just has to recognize it as a tool and disregard the hand holding it, which is really doesn’t want to do - It’s obsessed with hands. I should call it the Lyra driver from now on.

A more fundamental and concerning issue is the ease in which I can assume a position that blocks the camera’s view of some or most of my fingers. Pretty much anything that involves my fingers being vertically aligned breaks the driver, along with everything from a roughly 90 degree to 135 degree angle, pointed away from the device. This appears to be an inherent issue with the device itself, and its the same problem the kinect would have, because the camera’s view of the fingers gets blocked. How much more effective would a leap motion device with two cameras, one on either side of the monitor, be? Or just a wider camera angle (since it’s using dual emitters anyway to get depth information). As it is right now, it’s cute and futuristic looking, but any minority-report-esque gestures completely break it.

A much more unexpected issue is the fact that the device makes no attempt to deal with fingers that are held together, despite the fact that the shape of two touching fingers is fairly easy to figure out. If you’ve been tracking one finger and suddenly it meets up with another one and you end up with one really wide “finger”, it should be trivial to send this information as a “double finger” pointing, because this is an incredibly useful gesture (see below for details). It’s not like the finger is going to change into a hippopotamus all of a sudden.

3D Gestures

Most of the other problems are software oriented, not hardware or driver related. The simple fact is that no one has any idea how to properly utilize the device. Most apps seem to assume there’s only going to be one finger pointed at the screen, and will get confused if you have any other fingers hanging off even if they’re not pointed at the screen. The Leap Motion driver gives you a rough estimate of what it thinks the hand orientation is, and using this information its fairly trivial to figure out which finger someone is pointing with, even if their other fingers are only slightly below that finger. The camera is on a flat surface at a 90 degree angle from the screen, which means the finger you want is almost always going to be the finger that is the “highest” in relation to the hand orientation.

The rest of the apps either don’t do much processing on the raw data, or do an incredibly bad job of it. The touch screen recreation had this horrible tendency to start sliding off, and the cursor would sometimes jump around. I knew it shouldn’t be doing that because I’ve been watching the diagnostic information and it’s just getting confused by ghost fingers popping in and out. Guess what? A finger can’t teleport. If you’ve been tracking one finger, chances are you should keep tracking it no matter what else happens.

In addition, no one’s really come up with effective 3D gestures. All the apps try to use the 3D plane by turning it into a virtual touchscreen and it doesn’t work very well. Instead, we should be using gestures that are independent of a 2D plane. The apps need to be paying attention to the angle the finger is pointing in instead of trying to rely on moving your entire hand around. It seems like everyone is using the position information instead of the angle information, which the driver provides. If I’m pointing up and to the right, my cursor should be in the corner of the screen no matter where my hand is.

Furthermore, no one seems to be trying very hard to deal with noise. When the driver starts losing precision, you can tell because the angle information or position information will start to jitter. The more jittering, the less accurate the reading is. A simple way to quantify this is by calculating the variance of the recent data. The higher the variance, the less accurate your reading is. You should then scale how heavily you average out the points based on how much variance there is in the data. This allows you to avoid destroying precision while preventing the cursor from exploding when you lose accuracy. There’s a lot of algorithms dedicated to solving this exact problem, so it’s kind of ridiculous that no one is using them. In a more specific scenario, humans do precise manipulations with their fingers, not their hands. Small pertubations in the input data that occur in the hands should be removed from the finger positions, because it’s just the hand trembling, not the actual finger.

Instead of trying to recreate “pushing a button” in 3D, we should use a gesture interface that lets you move the cursor around with your index finger, and then when you bring up your middle finger against your index finger (so you are now pointing at the screen with two fingers), this counts as a “click” or a mouse-down. You can then drag things around with two fingers, or separate them to generate a mouse-up event. To right-click, bring your two fingers together again, and then rotate your hand clockwise. This could be combined with a more traditional “pushing a button” gesture for easier clicks, but provides a much more robust way of moving things around that isn’t awkward or difficult to use.

Since the driver currently doesn’t let you track two fingers held together, this same behavior can be emulated by simply keeping track of two fingers and detecting when both of them accelerate towards each other until one of them vanishes. On this same note, because fingers can drop out of tracking, programs can’t rely on the driver to be perfect. If you lose track of a finger, it’s not that hard to guess where it might be based on the orientation of the hand, which is necessary if we’re going to have good gesture recognition. The recognizer needs to be able to interpolate likely positions of lost fingers if it’s going to make an effective guess about what gesture was intended.

Leap Motion is really cool. Leap Motion is definitely the future. Unfortunately, we haven’t gotten to the future yet. We need a better software framework to build gesture interfaces on top of, and we need a new standard set of gestures for 3D that aren’t simply 2D ripoffs. Incidentally, I’d love to try building an open-source library that addresses a lot of the input sanitation problems I outlined in this article, but I’m a bit busy with the whole “finding a job so I don’t starve to death” thing. Hopefully, someone else will take up the cause, but until they do, don’t expect to be very productive with the Leap Motion.

Aurora Theory has been released! Buy it on bandcamp for $9, or $10 on iTunes, Amazon, and Google Play. The album is also available on Spotify, last.fm, other online radios, and can be previewed on YouTube.

Aurora Theory has been 4 years in the making, a compilation of all the songs I managed to make in the middle of attending university. The earlier songs have been extensively improved, and all songs have been remastered for the album’s release. This album represents nothing less than the highest quality work I can possibly manage at this point in my career. I’ve acquired a fair number of fans over the years, and I want to thank you for supporting my musical endeavors so far.

Track List:

  1. Soar (Original Mix) [5:49]
  2. Aurora Theory (Redux) [4:10]
  3. Cosminox [5:41]
  4. Tendril [5:32]
  5. Birefringence [3:57]
  6. Critical Damage (Extended Mix) [3:45]
  7. Starstruck [4:22]
  8. Dream Among The Stars [4:06]
  9. At The Nationals [4:02]
  10. The Cloud River [5:38]
  11. The Piano And The Cello [3:53]
  12. Snowflower [5:53]
  13. Spiral Nebula [5:44]
  14. Next Year [5:31]
*"In times of change, learners inherit the earth, while the learned find themselves beautifully equipped to deal with a world that no longer exists."* ― Eric Hoffer

Yesterday, the University of Washington finally mailed me my diploma. A Bachelor of Science in Applied Computational Math and Science: Discrete Math and Algorithms. I learned a lot of things in college. I learned how to take tests and how to pinpoint exactly what useless crap a particular final needed me to memorize. I learned that math is an incredibly beautiful thing that has been butchered so badly I hated it all the way until my second year of college. I learned that creativity is useless and all problems have one specific right answer you can find in the back of a textbook somewhere, because that’s all I was ever graded on. I learned that getting into the CSE major is more about fighting an enormous, broken bureaucratic mess than actually being good at computer science. But most of all, I learned that our educational system is so obsessed with itself it can’t even recognize it’s own shortcomings.

The first accelerated program I was accepted into was the Gifted program in middle school. I went from getting As in everything to failing every single one of my core classes. Determined to prove myself, I managed to recover my grades to Bs and Cs by the end of 7th grade, and by the end of 8th grade I was back up to As and Bs. I didn’t do this by getting smarter, I did it by getting better at following directions. I got better at taking tests. I became adept at figuring out precisely what the teacher wanted me to do, and then doing only that, so I could maximize both my free time and my grades. By the time I reached high school, I would always meticulously go over the project requirements, systematically satisfying each bullet point in order to maximize my score. During tests, I not only skipped over difficult questions, I would actively seek out hints in the later questions to help me narrow down possible answers. My ability to squeeze out high grades had more to do with my aptitude at filling in the right bubbles on a piece of paper then actually understanding the material.

I fantasized about attending college, where I would be judged on my intellectual prowess, and not on my test taking skills. I longed for the pursuit of knowledge in it’s purest form, only for this dream to be completely and utterly crushed. Instead of a place free from the endless battery of tests I had been subjected to during high school, I quickly realized that college was nothing but tests. I once had a math course where 95% of my grade was split between a first midterm, a second midterm, and a final. By the end of my second year of college, I simply stopped attending lectures. I could teach myself the material out of the textbook, and went to class only to take a test or turn in homework. I earned my degree by becoming incredibly adept at memorizing precisely which useless, specific facts were needed to properly answer questions. I was never asked nor told how to apply these to real world scenarios.

Thankfully, in one of the last classes I actually attended lecture in, the TA teaching the class said something that sparked a epiphany in me: “Math is simply repeated abstraction and generalization.” Suddenly, I was able to connect math and programming, and began to realize that I had loved math all my life. What I hated about math was the trivial nonsense they taught in middle school. I signed up for the most advanced math classes I could get away with, even when I could barely pass them. I began to realize that the most important thing these classes taught me was what I didn’t know. Once I knew what I didn’t know, I could teach it to myself, but only after I found the holes in my knowledge. You can’t fill a hole if you don’t know where it is. I didn’t know what combinatorics was until it was mentioned to me by that TA; Chrome still doesn’t think combinatorics is even a word.

Everyone finds the beauty of math in their own way, but we teach it like an automated assembly line of cars. Math is taught as some kind of rigid tool, when it is really a language for expressing logic, one with multiple dialects, each with their own personality. We invented music to express emotions that cannot be described; we invented math to express logical abstractions that defy explanation. Every tool in math is like another instrument in a grand orchestra, each note echoing off the others, reflecting a whole that is greater than the sum of its parts. Some composers prefer the string section, others prefer the woodwinds. There is no single right answer, only different ones. Instead of giving our children a brush and telling them to use their imagination, we give them a coloring book and grade them on how well they stay inside the lines.

I mean, we all know creativity is overrated. It must be, since we systematically destroy it even when we try to encourage it. It doesn’t matter how many programs we fund for encouraging things like art and music when the kids are still ultimately judged on how well they follow instructions and fill in little scantron bubbles. Kids are not stupid. I cannot believe how many adults still think they can get away with telling kids one thing and then doing another. They know what you’re up to. They know the only thing the school system cares about is their grades, and that their grades are based entirely on how well they follow directions. They know that answering a question “almost right” doesn’t matter. They know all problems have one answer in the back of the teacher’s textbook, and their job is to figure out what it is. The vast majority of them have absolutely no idea how to approach a problem that has no correct answer. They don’t know how to judge the correctness of a solution, because in school, everything is either right or wrong. All they know how to do is guess how likely it is that their solution is the solution the teacher wants, not how well the solution would actually work.

This is, of course, completely contradictory to everything in life. Life does not have answers in the back of the book. Life does not have a single correct answer to any problem. There is no right way to do anything, there are simply pros and cons. The fact that many people continue to delude themselves into thinking otherwise is a sad symptom of this issue. Our obsession with tests has trained a generation of robots, not engineers. They’re more skilled at working their way through a bureaucracy than designing rockets. Then again, considering that colleges have now turned into enormous, obstructive bureaucracies, perhaps this isn’t entirely a bad thing.

After all, with only 160 (now 200) spots open in its CSE major program each year when it has over 27000 undergraduate students enrolled[1], the University of Washington gets mighty picky about who they let in. After getting a 3.7 and 3.4 in my first two calculus classes, I slipped and got a 2.8 in my third math class, so despite the fact that I got a perfect 5 on the AP Computer Science AB exam and was qualified to skip both introductory programming courses, they rejected my application and demanded I take Matrix Algebra before letting me in. So I got a 3.9 in Matrix Algebra (a grade that was exceptionally good, according to one professor), and then… they still didn’t let me in. They complained that my entrance essay sounded “too cocky” and had me take the second introductory programming course even though I already had credit for it. When I failed to get an exceptionally good grade in that class for all the wrong reasons (like being graded down for having both too few comments and too many comments in my code), I simply could not bring myself to compete in a hyper-competitive environment where the only thing I was judged on was how many irrelevant details I could regurgitate. So, I majored in Applied Mathematics and simply took all the condensed, non-major CSE courses instead.

This obsession with tests extends into the evaluation of the educational system itself. One of the reasons nothing is getting better is because we use the very thing that is wrong with the educational system to judge it. We fill out ridiculous polls made out of those same interminable bubbles that are destroying the curriculum. We introduce more standardized testing. The entire system is completely obsessed with tests, and yet the only place that tests actually exist is… inside the system itself. Education has become so enraptured with this imaginary world it has constructed, it’s completely forgotten about the reality it’s supposed to be teaching kids about.

Kids know this imaginary world has nothing to do with reality. We lament about how to teach kids math when they refuse to understand it, without realizing that they are simply applying the same method of learning they use in everything else - memorize useless facts, then regurgitate them on a test. The reason our math curriculum is failing so badly is because in math, you can’t simply memorize things, you need to understand them. Consequently, Math acts as a canary in the coal mine for our entire educational system. Kids make no effort to understand anything, because they aren’t graded on how well they understand concepts, they are graded on how well they memorize random, useless details and follow directions.

We live in a world being overrun by automation. Any task that can be reduced to simply following a set of instructions over and over is being done by robots and software. This constant attrition of jobs involving menial work and physical labor will continue at a steady pace for the foreseeable future. We are teaching our kids skills that are being made irrelevant in a modern economy. We are preparing our children for a world that no longer exists. At the same time, while I could write a series of blog posts outlining an effective educational system, it will never be implemented in public schools. The establishment is too deeply entrenched. Foolish startups repeatedly and continually attempt to “disrupt” the educational system without realizing just how laughably outmatched they are. This is not something you can fix with a cute website. People complain about global warming, space travel, all sorts of adorable little problems, but miss the elephant in the room.

The greatest challenge our species has ever faced is the educational system itself.

What if I told you about an article that complained about how social media and instant gratification has eroded away at our social fabric? How we don’t take the time to pause and reflect on how we live our lives? How we fail to really work at making the world a better place, and instead waste time building websites to share cat photos on? I’d think that it raised several important issues about modern society.

What if I then told you that the entire article only applied this to men? What if it was titled, “Why Men Aren’t Really Men Anymore”? Suddenly, things just got a lot more sexist. In fact, that entire article is built almost entirely out of gender stereotypes. It’s that subtle, classy kind of sexism; bigotry that hides behind delicate prose, hiding it’s true nature. If the article were rewritten so that it described these issues in gender-nuetral terms, I’d be liable to agree with it. Trolling, aggression, lack of human interaction, billions of dollars being spent on worthless startups that solve first world problems - these are all real issues. Yet, to imply that men are the ones with these problems, to imply that any class of problems belong to only one gender, is sexist.

The article is wonderfully subtle in its sexism. Just look at how it claims “real” men should treat women:

*Real men are not selfish. Real men are just as concerned for the feelings, needs and minds of women as they are for their own — not just women’s bodies and their sexual usefulness. Real men have a well-defined code of ethics and respect that they follow.*
Isn't that sweet? Except, oh wait, we have this disturbing sentence in the middle of the article:
*Men have become lazy pussies. I don’t even want to use the word pussy because it brings to mind women, who nowadays have much more character than men.*
Not to be outdone, the article's last paragraph contains this gem:
*Some great women are settling for these fools and then finding that they themselves have no choice but to wear the pants in the family because their “man” is PMSing.*
This is **horribly sexist**. These three sentences enforce multiple gender stereotypes and tell us a number of things:
  1. Women want manly men. If they think they don’t want a manly man, they just haven’t found one manly enough yet.
  2. Men are always the ones who should be wearing the pants in the family, because men always have to be the manly ones.
  3. Women shouldn’t have more character than men.
  4. Women are allowed to be PMSing because they’re women, and everyone knows women get emotional, but a man should never be emotional, because he’s a man.

See, the reasoning behind all these is just “because men are men and women are women.” That isn’t a reason, it’s sexism. It’s bigotry. It’s enforcing stereotypes and trying to tell people how they should live their lives based on a set of gender roles that society arbitrarily decided on. It simply assumes it knows what women want, and goes so far to imply that the only reason a women wouldn’t want a “real” man is because they haven’t seen one yet. This is exactly like those annoying little assholes who tell you “Oh you just haven’t heard good dubstep! You’ll like it then!” Inevitably, after you still don’t like it, they just tell you that something is clearly wrong with you and you have no taste.

At no point do they entertain the notion that, maybe, just maybe, you actually don’t like dubstep.

Our society suffers from the same tunnel vision. We assume that when a women is working overtime and the man is doing laundry that it’s the man’s fault for not being manly enough and the women has been forced to become the head of the household. If she had just married a man manly enough, she wouldn’t have had to do that!

It never crosses their minds that maybe, just maybe, the women actually likes it this way. Maybe some men just don’t want to be manly. Maybe some women like men who aren’t manly. Maybe you can’t fit every single human being into nice neat little gender boxes.

It is not a man’s job to be manly simply because they are men. It is not a women’s job to be PMSing or making you a sandwich. It is not society’s place to tell anyone how they should live their lives. You do not know what they want and you should never pretend you do. We can make certain observations about genders, like men tend to be more aggressive, and women tend to be more emotional, but we should never assume that men should be more aggressive, or women should be more emotional. That is for the individual to decide, not society.

A human being is something precious, something complicated, something that can’t be easily categorized. Stop trying to stuff them into square boxes.

It's standard procedure at the University of Washington to allow a single sheet of handwritten notes during a Mathematics exam. I started collecting these sheets after I realized how useful it was to have a reference that basically summarized all the useful parts of the course on a single sheet of paper. Now that I've graduated, it's easy for me to quickly forget all the things I'm not using. The problem is that, when I need to say, develop an algorithm for simulating turbulent airflow, I need to go back and re-learn vector calculus, differential equations and nonlinear dynamics. So I've decided to digitize all my notes and put them in one place where I can reference them. I've uploaded it here in case they come in handy to anyone else.

The earlier courses listed here had to be reconstructed from my class notes because I'd thrown my final notesheet away or otherwise lost it. The classes are not listed in the order I took them, but rather organized into related groups. This post may be updated later with expanded explanations for some concepts, but these are highly condensed notes for reference, and a lot of it won't make sense to someone who hasn't taken a related course.

Math 124 - Calculus I
lost

Math 125 - Calculus II
lost

Math 126 - Calculus III
lost

Math 324 - Multivariable Calculus I
\[ r^2 = x^2 + y^2 \]
\[ x= r\cos\theta \]
\[ y=r\sin\theta \]

\[ \iint\limits_R f(x,y)\,dA = \int_\alpha^\beta\int_a^b f(r\cos\theta,r\sin\theta)r\,dr\,d\theta=\int_\alpha^\beta\int_{h_1(\theta}^{h_2(\theta)} f(r\cos\theta,r\sin\theta)r\,dr\,d\theta \]

\[ m=\iint\limits_D p(x,y)\,dA \begin{cases} \begin{aligned} M_x=\iint\limits_D y p(x,y)\,dA & \bar{x}=\frac{M_y}{m}=\frac{1}{m}\iint x p(x,y)\,dA \end{aligned} \\ \begin{aligned} M_y=\iint\limits_D x p(x,y)\,dA & \bar{y}=\frac{M_x}{m}=\frac{1}{m}\iint y p(x,y)\,dA \end{aligned} \end{cases} \]

\[ Q = \iint\limits_D \sigma(x,y)\,dA \]
\[ I_x = \iint\limits_D y^2 p(x,y)\,dA \]
\[ I_y = \iint\limits_D x^2 p(x,y)\,dA \]
\[ I_0 = \iint\limits_D (x^2 + y^2) p(x,y)\,dA \]

\[ \iiint f(x,y,z) dV = \lim_{l,m,n\to\infty}\sum_{i=1}^l\sum_{j=1}^m\sum_{k=1}^n f(x_i,y_j,z_k) \delta V \]
\[ \iiint\limits_B f(x,y,z)\,dV=\int_r^s\int_d^c\int_a^b f(x,y,z)\,dx\,dy\,dz = \int_a^b\int_r^s\int_d^c f(x,y,z)\,dy\,dz\,dx \]

$$E$$ = general bounded region
Type 1: $$E$$ is between graphs of two continuous functions of $$x$$ and $$y$$.
\[ E=\{(x,y,z)|(x,y)\in D, u_1(x,y) \le z \le u_2(x,y)\} \]

$$D$$ is the projection of E on to the xy-plane, where
\[ \iiint\limits_E f(x,y,z)\,dV = \iint\limits_D\left[\int_{u_1(x,y)}^{u_2(x,y)} f(x,y,z)\,dz \right]\,dA \]

$$D$$ is a type 1 planar region:
\[ \iiint\limits_E f(x,y,z)\,dV = \int_a^b \int_{g_1(x)}^{g_2(x)} \int_{u_1(x,y)}^{u_2(x,y)} f(x,y,z)\,dz\,dy\,dx \]

$$D$$ is a type 2 planar region:
\[ \iiint\limits_E f(x,y,z)\,dV = \int_d^c \int_{h_1(y)}^{h_2(y)} \int_{u_1(x,y)}^{u_2(x,y)} f(x,y,z)\,dz\,dx\,dy \]


Type 2: $$E$$ is between $$y$$ and $$z$$, $$D$$ is projected on to $$yz$$-plane
\[ E=\{(x,y,z)|(y,z)\in D, u_1(y,z) \le x \le u_2(y,z)\} \]
\[ \iiint\limits_E f(x,y,z)\,dV = \iint\limits_D\left[\int_{u_1(y,z)}^{u_2(y,z)} f(x,y,z)\,dx \right]\,dA \]

Type 3: $$E$$ is between $$x$$ and $$z$$, $$D$$ is projected on to $$xz$$-plane
\[ E=\{(x,y,z)|(x,z)\in D, u_1(x,z) \le y \le u_2(x,z)\} \]
\[ \iiint\limits_E f(x,y,z)\,dV = \iint\limits_D\left[\int_{u_1(x,z)}^{u_2(x,z)} f(x,y,z)\,dy \right]\,dA \]

Mass
\[ m = \iiint\limits_E p(x,y,z)\,dV \]
\[ \bar{x} = \frac{1}{m}\iiint\limits_E x p(x,y,z)\,dV \]
\[ \bar{y} = \frac{1}{m}\iiint\limits_E y p(x,y,z)\,dV \]
\[ \bar{z} = \frac{1}{m}\iiint\limits_E z p(x,y,z)\,dV \]
Center of mass: $$(\bar{x},\bar{y},\bar{z})$$
\[ Q = \iiint\limits_E \sigma(x,y,z)\,dV \]
\[ I_x = \iiint\limits_E (y^2 + z^2) p(x,y,z)\,dV \]
\[ I_y = \iiint\limits_E (x^2 + z^2) p(x,y,z)\,dV \]
\[ I_z = \iiint\limits_E (x^2 + y^2) p(x,y,z)\,dV \]

Spherical Coordinates:
\[ z=p\cos\phi \]
\[ r=p\sin\phi \]
\[ dV=p^2\sin\phi \]
\[ x=p\sin\phi\cos\theta \]
\[ y=p\sin\phi\sin\theta \]
\[ p^2 = x^2 + y^2 + z^2 \]
\[ \iiint\limits_E f(x,y,z)\,dV = \int_c^d\int_\alpha^\beta\int_a^b f(p\sin\phi\cos\theta,p\sin\phi\sin\theta,p\cos\phi) p^2\sin\phi\,dp\,d\theta\,d\phi \]

Jacobian of a transformation $$T$$ given by $$x=g(u,v)$$ and $$y=h(u,v)$$ is:
\[ \begin{aligned} \frac{\partial (x,y)}{\partial (u,v)} = \begin{vmatrix} \frac{\partial x}{\partial u} & \frac{\partial x}{\partial v} \\[0.1em] \frac{\partial y}{\partial u} & \frac{\partial y}{\partial v} \end{vmatrix} = \frac{\partial x}{\partial u} \frac{\partial y}{\partial v} - \frac{\partial x}{\partial v} \frac{\partial y}{\partial u} \end{aligned} \]

Given a transformation T whose Jacobian is nonzero, and is one to one:
\[ \iint\limits_R f(x,y)\,dA = \iint\limits_S f\left(x(u,v),y(u,v)\right)\left|\frac{\partial (x,y)}{\partial (u,v)}\right|\,du\,dv \]

Polar coordinates are just a special case:
\[ x = g(r,\theta)=r\cos\theta \]
\[ y = h(r,\theta)=r\sin\theta \]

\[ \frac{\partial (x,y)}{\partial (u,v)} = \begin{vmatrix} \frac{\partial x}{\partial r} & \frac{\partial x}{\partial \theta} \\ \frac{\partial y}{\partial r} & \frac{\partial y}{\partial \theta} \end{vmatrix} = \begin{vmatrix} \cos\theta & -r\sin\theta \\ \sin\theta & r\cos\theta \end{vmatrix} = r\cos^2\theta + r\sin^2\theta=r(\cos^2\theta + \sin^2\theta) = r \]

\[ \iint\limits_R f(x,y)\,dx\,dy = \iint\limits_S f(r\cos\theta, r\sin\theta)\left|\frac{\partial (x,y)}{\partial (u,v)}\right|\,dr\,d\theta=\int_\alpha^\beta\int_a^b f(r\cos\theta,r\sin\theta)|r|\,dr\,d\theta\]

For 3 variables this expands as you would expect: $$x=g(u,v,w)$$ $$y=h(u,v,w)$$ $$z=k(u,v,w)$$
\[ \frac{\partial (x,y,z)}{\partial (u,v,w)}=\begin{vmatrix} \frac{\partial x}{\partial u} & \frac{\partial x}{\partial v} & \frac{\partial x}{\partial w} \\ \frac{\partial y}{\partial u} & \frac{\partial y}{\partial v} & \frac{\partial y}{\partial w} \\ \frac{\partial z}{\partial u} & \frac{\partial z}{\partial v} & \frac{\partial z}{\partial w} \end{vmatrix} \]

\[ \iiint\limits_R f(x,y,z)\,dV = \iiint\limits_S f(g(u,v,w),h(u,v,w),k(u,v,w)) \left|\frac{\partial (x,y,z)}{\partial (u,v,w)} \right| \,du\,dv\,dw\]

Line Integrals
Parameterize: $$r(t)=\langle x(t),y(t),z(t) \rangle$$ where $$r'(t)=\langle x'(t),y'(t),z'(t) \rangle$$ and $$|r'(t)|=\sqrt{x'(t)^2 + y'(t)^2 + z'(t)^2} $$
\[ \int_C f(x,y,z)\,ds = \int_a^b f(r(t))\cdot |r'(t)|\,dt = \int_a^b f(x(t),y(t),z(t))\cdot\sqrt{x'(t)^2 + y'(t)^2 + z'(t)^2}\,dt\;\;\;a<t<b \]

For a vector function $$\mathbf{F}$$:
\[ \int_C \mathbf{F}\cdot dr = \int_a^b \mathbf{F}(r(t))\cdot r'(t)\,dt \]

Surface Integrals
\[ \]

Parameterize: $$r(u,v) = \langle x(u,v),y(u,v),z(u,v) \rangle$$
\[ \begin{matrix} r_u=\frac{\partial x}{\partial u}\vec{\imath} + \frac{\partial y}{\partial u}\vec{\jmath} + \frac{\partial z}{\partial u}\vec{k} \\ r_v=\frac{\partial x}{\partial v}\vec{\imath} + \frac{\partial y}{\partial v}\vec{\jmath} + \frac{\partial z}{\partial v}\vec{k} \end{matrix}\]
\[ r_u \times r_v = \begin{vmatrix} \vec{\imath} & \vec{\jmath} & \vec{k} \\ \frac{\partial x}{\partial u} & \frac{\partial y}{\partial u} & \frac{\partial z}{\partial u} \\ \frac{\partial x}{\partial v} & \frac{\partial y}{\partial v} & \frac{\partial z}{\partial v} \end{vmatrix} \]

\[ \iint\limits_S f(x,y,z) dS = \iint\limits_D f(r(t))|r_u \times r_v|\,dA \]

For a vector function $$\mathbf{F}$$:
\[ \iint\limits_S \mathbf{F}\cdot dr = \iint\limits_D \mathbf{F}(r(u,v))\cdot (r_u \times r_v)\,dA) \]

Any surface $$S$$ with $$z=g(x,y)$$ is equivalent to $$x=x$$, $$y=y$$, and $$z=g(x,y)$$, so
$$xy$$ plane:
\[ \iint\limits_S f(x,y,z)\,dS = \iint\limits_D f(x,y,g(x,y))\sqrt{\left(\frac{\partial z}{\partial x}\right)^2+\left(\frac{\partial z}{\partial y}\right)^2+1}\,dA \]

$$yz$$ plane:
\[ \iint\limits_S f(x,y,z)\,dS = \iint\limits_D f(x,h(x,z),z)\sqrt{\left(\frac{\partial y}{\partial x}\right)^2+\left(\frac{\partial y}{\partial z}\right)^2+1}\,dA \]

$$xz$$ plane:
\[ \iint\limits_S f(x,y,z)\,dS = \iint\limits_D f(g(y,z),y,z)\sqrt{\left(\frac{\partial x}{\partial y}\right)^2+\left(\frac{\partial x}{\partial z}\right)^2+1}\,dA \]

Flux:
\[ \iint\limits_S\mathbf{F}\cdot dS = \iint\limits_D\mathbf{F}\cdot (r_u \times r_v)\,dA \]

The gradient of $$f$$ is the vector function $$\nabla f$$ defined by:
\[ \nabla f(x,y)=\langle f_x(x,y),f_y(x,y)\rangle = \frac{\partial f}{\partial x}\vec{\imath} + \frac{\partial f}{\partial y}\vec{\jmath} \]

Directional Derivative:
\[D_u\,f(x,y) = f_x(x,y)a + f_y(x,y)b = \nabla f(x,y)\cdot u \text{ where } u = \langle a,b \rangle \]
\[ \int_C\,ds=\int_a^b |r'(t)|=L \]
\[ \]

If $$\nabla f$$ is conservative, then:
\[ \int_{c_1} \nabla f\,dr=\int_{c_2} \nabla f\,dr \]

This means that the line integral between two points will always be the same, no matter what curve is used to go between the two points - the integrals are path-independent and consequently only depend on the starting and ending positions in the conservative vector field.
A vector function is conservative if it can be expressed as the gradient of some potential function $$\psi$$: $$\nabla \psi = \mathbf{F}$$
\[ curl\,\mathbf{F} =\nabla\times\mathbf{F}\]
\[ div\,\mathbf{F} =\nabla\cdot\mathbf{F}\]


Math 326 - Multivariable Calculus II
$$f(x,y)$$ is continuous at a point $$(x_0,y_0)$$ if
\[ \lim\limits_{(x,y)\to(0,0)} f(x,y) = f(x_0,y_0) \]

$$f+g$$ is continuous if $$f$$ and $$g$$ are continuous, as is $$\frac{f}{g}$$ if $$g \neq 0$$
A composite function of a continuous function is continuous
\[ \frac{\partial f}{\partial x} = f_x(x,y) \]
\[ \frac{\partial f}{\partial x}\bigg|_{(x_0,y_0)}=\left(\frac{\partial f}{\partial x}\right)_{(x_0,y_0)}=f_x(x_0,y_0) \]

To find $$\frac{\partial z}{\partial x} F(x,y,z)$$, differentiate $$x$$ as normal, hold y constant, and differentiate $$z$$ as a function (such that $$z^2 = 2z \frac{\partial z}{\partial x}$$ and $$2z = 2 \frac{\partial z}{\partial x}$$)
Ex:
\[ F(x,y,z) = \frac{x^2}{16} + \frac{y^2}{12} + \frac{z^2}{9} = 1 \]
\[ \frac{\partial z}{\partial x} F = \frac{2x}{16} + \frac{2z}{}\frac{\partial z}{\partial x} = 0 \]

The tangent plane of $$S$$ at $$(a,b,c): z-c = f_x(a,b)(x-a) + f_y(a,b)(y-b)$$ where $$z=f(x,y)$$, or $$z =f(a,b) + f_x(a,b)(x-a) + f_y(a,b)(y-b)$$
Note that
\[ f_x(a,b)=\frac{\partial z}{\partial x}\bigg|_{(a,b)} \]
which enables you to find tangent planes implicitly.
Set $$z=f(x,y)$$. $$f_x=f_y=0$$ at a relative extreme $$(a,b)$$.
Distance from origin:
\[ D^2 = z^2 + y^2 + x^2 = f(a,b)^2 + y^2 + x^2 \]

Minimize $$D$$ to get point closest to the origin.
The differential of $$f$$ at $$(x,y)$$:
\[ df(x,y;dx,dy)=f_x(x,y)\,dx + f_y(x,y)\,dy \]
\[ dz=\frac{\partial f}{\partial x}\,dx + \frac{\partial f}{\partial y}\,dy \]

$$f$$ is called differentiable at $$(x,y)$$ if it $$s$$ defined for all points near $$(x,y)$$ and if there exists numbers $$A$$,$$B$$ such that
\[ \lim_{(n,k)\to(0,0)}\frac{|f(x+h,y+k) - f(x,y) - Ah - Bk|}{\sqrt{h^2 + k^2}}=0 \]

If $$f$$ is differentiable at $$(x,y)$$ it is continuous there.
\[ A = f_x(x,y) \]
and
\[ B=f_y(x,y) \]

If $$F_x(x,y)$$ and $$F_y(x,y)$$ are continuous at a point $$(x_0,y_0)$$ defined in $$F$$, then $$F$$ is differentiable there.
Ex: The differential of $$f(x,y)=3x^2y+2xy^2+1$$ at $$(1,2)$$ is $$df(1,2;h,k)=20h+11k$$
\[ d(u+v)=du+dv \]
\[ d(uv)=u\,dv + v\,du \]
\[ d\left(\frac{u}{v}\right)=\frac{v\,du -u\,dv}{v^2} \]

Taylor Series:
\[ f^{(n)}(t)=\left[\left(h\frac{}{} + k\frac{}{})^n F(x,y) \right) \right]_{x=a+th,y=b+tk} \]
Note:
\[ f''(t)=h^2 F_{xx} + 2hk F_{xy} + k^2 F_{yy} \]

\[ \begin{matrix} x=f(u,v) \\ y=g(u,v) \end{matrix} \]
\[ J=\frac{\partial(f,g)}{\partial(u,v)} \]
\[ \begin{matrix} u=F(x,y) \\ v=G(x,y) \end{matrix} \]
\[ j = J^{-1} = \frac{1}{\frac{\partial(f,g)}{\partial(u,v)}} \]

\[ \begin{matrix} x = u-uv \\ y=uv \end{matrix} \]
\[ \iint\limits_R\frac{dx\,dy}{x+y} \]
R bounded by
\[ \begin{matrix} x+y=1 & x+y=4 \\ y=0 & x=0 \end{matrix}\]
\[ \int_0^1\int_0^x \frac{du\,dv}{u-uv+ux}\left|\frac{\partial(x,y)}{\partial(u,v)}\right| \]

\[ \frac{\partial(F,G)}{\partial(u,v)}=\begin{vmatrix} \frac{\partial F}{\partial u} & \frac{\partial F}{\partial v} \\ \frac{\partial G}{\partial u} & \frac{\partial G}{\partial v} \end{vmatrix} \]
\[ \nabla f = \langle f_x, f_y, f_z \rangle \]
\[ G_x(s_0,t_0) =F_x(a,b)f_x(s_0,t_0) + F_y(a,b)g_x(s_0,t_0) \]
\[ U\times V = U_xV_y - U_yV_x \text{ or } A\times B = \left\langle \begin{vmatrix} a_y & a_z \\ b_y & b_z \end{vmatrix}, -\begin{vmatrix} a_x & a_z \\ b_x & b_z \end{vmatrix}, \begin{vmatrix} a_x & a_y \\ b_x & b_y \end{vmatrix} \right\rangle \]

Given $$G(s,t)=F(f(s,t),g(s,t))$$, then:
\[ \begin{matrix} \frac{\partial G}{\partial s} = \frac{\partial F}{\partial x}\frac{\partial f}{\partial s} + \frac{\partial F}{\partial y}\frac{\partial g}{\partial s} \\ \frac{\partial G}{\partial t} = \frac{\partial F}{\partial x}\frac{\partial f}{\partial t} + \frac{\partial F}{\partial y}\frac{\partial g}{\partial t} \end{matrix} \]

Alternatively, $$ u=F(x,y,z)=F(f(t),g(t),h(t))$$ yields
\[ \frac{du}{dt}=\frac{\partial u}{\partial x}\frac{dx}{dt} + \frac{\partial u}{\partial y}\frac{dy}{dt} + \frac{\partial u}{\partial z}\frac{dz}{dt} \]

Examine limit along line $$y=mx$$:
\[ \lim_{x\to 0} f(x,mx) \]

If $$g_x$$ and $$g_y$$ are continuous, then $$g$$ is differentiable at that point (usually $$0,0$$).
Notice that if $$f_x(0,0)=0$$ and $$f_y(0,0)=0$$ then $$df(0,0;h,l)=0h+0k=0$$

The graph of $$y(x,y)$$ lies on a level surface $$F(x,y,z)=c$$ means $$f(x,y(x,z),z)=c$$. So then use the chain rule to figure out the result in terms of $$F$$ partials by considering $$F$$ a composite function $$F(x,y(x,z),z)$$.

Fundamental implicit function theorem: Let $$F(x,y,z)$$ be a function defined on an open set $$S$$ containing the point $$(x_0,y_0,z_0)$$. Suppose $$F$$ has continuous partial derivatives in $$S$$. Furthermore assume that: $$F(x_0,y_0,z_0)=0, F_z(x_0,y_0,z_0)\neq 0$$. Then $$z=f(x,y)$$ exists, is continuous, and has continuous first partial derivatives.
\[ f_x = -\frac{F_x}{F_z} \]
\[ f_y = -\frac{F_y}{F_z} \]

Alternatively, if
\[ \begin{vmatrix} F_x & F_y \\ G_x & G_y \end{vmatrix} \neq 0 \]
, then we can solve $$x$$ and $$y$$ as functions of $$z$$. Since the cross-product is made of these determinants, if the $$x$$ component is nonzero, you can solve $$y,z$$ as functions of $$x$$, and therefore graph it on the $$x-axis$$.

To solve level surface equations, let $$F(x,y,z)=c$$ and $$G(x,y,z)=d$$, then use the chain rule, differentiating by the remaining variable (e.g. $$\frac{dy}{dx}$$ and $$\frac{dz}{dx}$$ means do $$x$$)
\[ \begin{matrix} F_x + F_y y_x + F_z z_x = 0 \\ G_x + G_y y_x + G_z z_x = 0 \end{matrix} \]
if you solve for $$y_x$$,$$z_x$$, you get
\[ \left[ \begin{matrix} F_y & F_z \\ G_y & G_z \end{matrix} \right] \left[ \begin{matrix} y_x \\ z_x \end{matrix} \right] = \left[\begin{matrix}F_x \\ G_x \end{matrix} \right] \]

Mean value theorem:
\[ f(b) - f(a) = (b-a)f'(X) \]
\[ a < X < b \]

or:
\[ f(a+h)=f(a)+hf'(a + \theta h) \]
\[ 0 < \theta < 1 \]

xy-plane version:
\[ F(a+h,b+k)-F(a,b)=h F_x(a+\theta h,b+\theta k)+k F_y(a+\theta h, b+\theta k) \]
\[ 0 < \theta < 1 \]

Lagrange Multipliers: $$\nabla f = \lambda\nabla g$$ for some scale $$\lambda$$ if $$(x,y,z)$$ is a minimum:
\[ f_x=\lambda g_x \]
\[ f_y=\lambda g_y \]
\[ f_z=\lambda g_z \]
Set $$f=x^2 + y^2 + z^2$$ for distance and let $$g$$ be given.

Math 307 - Introduction to Differential Equations
lost

Math 308 - Matrix Algebra
lost

Math 309 - Linear Analysis
lost

AMath 353 - Partial Differential Equations

Fourier Series:
\[ f(x)=b_0 + \sum_{n=1}^{\infty} \left(a_n \sin\frac{n\pi x}{L} + b_n\cos\frac{n\pi x}{L} \right) \]
\[ b_0 = \frac{1}{2L}\int_{-L}^L f(y)\,dy \]
\[ a_m \frac{1}{L}\int_{-L}^L f(y) \sin\frac{m\pi y}{L}\,dy \]
\[ b_m = \frac{1}{L}\int_{-L}^L f(y)\cos\frac{m\pi y}{L}\,dy \]
\[ m \ge 1 \]

\[ u_t=\alpha^2 u_{xx} \]
\[ \alpha^2 = \frac{k}{pc} \]
\[ u(x,t)=F(x)G(t) \]

Dirichlet: $$u(0,t)=u(L,t)=0$$
Neumann:$$u_x(0,t)=u_x(L,t)=0$$
Robin:$$a_1 u(0,t)+b_1 u_x(0,t) = a_2 u(L,t) + b_2 u_x(L,t) = 0$$
Dirichlet:
\[ \lambda_n=\frac{n\pi}{L}\;\;\; n=1,2,... \]
\[ u(x,t)=\sum_{n=1}^{\infty} A_n \sin\left(\frac{n\pi x}{L} \right)\exp\left(-\frac{n^2\alpha^2\pi^2 t}{L^2}\right) \]
\[ A_n = \frac{2}{L} \int_0^L f(y) \sin\frac{n\pi y}{L}\,dy = 2 a_m\text{ for } 0\text{ to } L \]

Neumann:
\[ \lambda_n=\frac{n\pi}{L}\;\;\; n=1,2,... \]
\[ u(x,t)=B_0 + \sum_{n=1}^{\infty} B_n \cos\left(\frac{n\pi x}{L} \right)\exp\left(-\frac{n^2\alpha^2\pi^2 t}{L^2}\right) \]
\[ B_0 = \frac{1}{L} \int_0^L f(y)\,dy \]
\[ B_n = \frac{2}{L} \int_0^L f(y) \cos\frac{n\pi y}{L}\,dy = 2 b_m\text{ for } 0\text{ to } L \]

Dirichlet/Neumann:
\[ \lambda_n=\frac{\pi}{2L}(2n + 1)\;\;\; n=0,1,2,... \]
\[ u(x,t)=\sum_{n=0}^{\infty} A_n \sin\left(\lambda_n x\right) \exp\left(-\alpha^2 \lambda_n^2 t\right) \]
\[ A_n = \frac{2}{L} \int_0^L f(y) \sin\left(\lambda_n y\right)\,dy \]

Neumann/Dirichlet:
\[ \lambda_n=\frac{\pi}{2L}(2n + 1)\;\;\; n=0,1,2,... \]
\[ u(x,t)=\sum_{n=0}^{\infty} B_n \cos\left(\lambda_n x\right) \exp\left(-\alpha^2 \lambda_n^2 t\right) \]
\[ B_n = \frac{2}{L}\int_0^L f(y)\cos(\lambda_n y)\,dy \]

\[ v_2(x,y)=\sum_{n=1}^{\infty} C_n(t)[\sin/\cos](\lambda_n x) \]
Replace $$[\sin/\cos]$$ with whatever was used in $$u(x,t)$$
\[ C_n(t)=\int_0^t p_n(s) e^{\lambda_n^2\alpha^2 (s-t)}\,ds \]
\[ p_n(t)=\frac{2}{L}\int_0^L p(y,t)[\sin/\cos](\lambda_n y)\,dy \]
Replace $$[\sin/\cos]$$ with whatever was used in $$u(x,t)$$. Note that $$\lambda_n$$ for $$C_n$$ and $$p_n(t)$$ is the same as used for $$u_1(x,t)$$
Sturm-Liouville:
\[ p(x)\frac{d^2}{dx^2}+p'(x)\frac{d}{dx}+q(x) \]
\[ a_2(x)\frac{d^2}{dx^2} + a_1(x)\frac{d}{dx} + a_0(x) \rightarrow p(x)=e^{\int\frac{a_1(x)}{a_2(x)}\,dx}\]
\[ q(x)=p(x)\frac{a_0(x)}{a_2(x)} \]

Laplace's Equation:
\[ \nabla^2 u=0 \]
\[ u=F(x)G(y) \]
\[ \frac{F''(x)}{F(x)} = -\frac{G''(y)}{G(y)} = c \]
for rectangular regions
\[ F_?(x)=A =\sinh(\lambda x) + B \cosh(\lambda x) \]
use odd $$\lambda_n$$ if $$F$$ or $$G$$ equal a single $$\cos$$ term.
\[ G_?(y)=C =\sinh(\lambda y) + D \cosh(\lambda y) \]
\[ u(x,?)=G(?) \]
\[ u(?,y)=F(y) \]

Part 1: All $$u_?(x,?)=0$$
\[ \lambda_n=\frac{n\pi}{L y}\text{ or }\frac{(2n+1)\pi}{2L y} \]
\[ u_1(x,y)=\sum_{n=0}^{\infty}A_n F_1(x)G_1(y) \]
\[ A_n = \frac{2}{L_y F_1(?)}\int_0^{L_y} u(?,y)G_1(y)\,dy \]
\[ u(?,y)=h(y) \]
\[ ? = L_x\text{ or }0 \]

Part 2: All $$u_?(?,y)=0$$
\[ \lambda_n=\frac{n\pi}{L x}\text{ or }\frac{(2n+1)\pi}{2L x} \]
\[ u_2(x,y)=\sum_{n=1}^{\infty}B_n F_2(x)G_2(y) \]
\[ B_n = \frac{2}{L_x G_2(?)}\int_0^{L_x} u(x,?)F_2(x)\,dx \]
\[ u(x,?)=q(x) \]
\[ ? = L_y\text{ or }0 \]

\[ u(x,y)=u_1(x,y)+u_2(x,y) \]

Circular $$\nabla^2 u$$:
\[ u_{rr} + \frac{1}{r} u_r + \frac{1}{r^2}u_{\theta \theta} = 0 \]
\[ \frac{G''(\theta)}{G(\theta)}= - \frac{r^2 F''(r) + r F(r)}{F(r)} = c\]

\[ \left\langle f,g \right\rangle = \int_a^b f(x) g(x)\,dx \]
\[ \mathcal{L}_s=-p(x)\frac{d^2}{dx^2}-p'(x)\frac{d}{dx} + q(x) \]
\[ \mathcal{L}_s\phi(x)=\lambda r(x) \phi(x) \]
\[ \left\langle\mathcal{L}_s y_1,y_2 \right\rangle =\int_0^L \left(-[p y_1']'+q y_1\right)y_2\,dx \]

$$\mathcal{L}_s = f(x)$$, then $$\mathcal{L}_s^{\dagger} v(x) = 0$$, where if $$v=0$$, $$u(x)$$ is unique, otherwise $$v(x)$$ exists only when forcing is orthogonal to all trivial solutions.
if $$c=0$$,
\[ G(\theta)=B \]
\[ F(r)=C\ln r + D \]

if $$c=-\lambda^2 <0$$,
\[ G(\theta)=A\sin(\lambda\theta) + B\cos(\lambda\theta) \]
\[ F(r) = C\left(\frac{r}{R} \right)^n + D\left( \frac{r}{R} \right)^{-n}\]
\[ u(r,\theta)=B_0 + \sum_{n=1}^{\infty} F(r) G(\theta) = B_0 + \sum_{n=1}^{\infty}F(r)[A_n\sin(\lambda\theta) + B_n\cos(\lambda\theta)] \]
\[ A_n = \frac{1}{\pi}\int_0^{2\pi} f(\theta)\sin(n\theta)\,d\theta \]
\[ B_n = \frac{1}{\pi}\int_0^{2\pi} f(\theta)\cos(n\theta)\,d\theta \]
\[ B_0 = \frac{1}{2\pi}\int_0^{2\pi} f(\theta)\,d\theta \]

Wave Equation:
\[ u_{tt}=c^2 u_{xx} \]
\[ u = F(x)G(t) \]
\[ \frac{F''(x)}{F(x)}=\frac{G''(t)}{G(t)}=k \text{ where } u(t,0)=F(0)=u(t,L)=F(L)=0 \]
\[ F(x) = A\sin(\lambda x) + B\cos(\lambda x) \]
\[ u_t(x,0)=g(x)=\sum_{n=1}^{\infty} A_n\lambda_n c \sin(\lambda_n x) \]
\[ A_n = \frac{2}{\lambda_n c L}\int_0^L g(y)\sin(\lambda_n y)\,dy \]

\[ G(t) = C\sin(\lambda t) + D\cos(\lambda t) \]
\[ u(x,0)=f(x)=\sum_{n=1}^{\infty}B_n\sin(\lambda_n x) \]
\[ B_n = \frac{2}{L}\int_0^L f(y)\sin(\lambda_n y)\,dy \]

\[ u(x,t)=\sum_{n=1}^{\infty}F(x)G(t)=\sum_{n=1}^{\infty}F(x)\left[C\sin(\lambda t) + D\cos(\lambda t)\right] \]
\[ \lambda_n=\frac{n\pi}{L}\text{ or }\frac{(2n+1)\pi}{2L} \]

Inhomogeneous:
\[ u(0,t)=F(0)=p(t) \]
\[ u(L,t)=F(L)=q(t) \]
\[ u(x,t)=v(x,t) + \phi(x)p(t) + \psi(x)q(t) \]

Transform to forced:
\[ v(x,y) = \begin{cases} v_{tt}=c^2 v_{xx} - \phi(x)p''(x) - \psi(x)q''(t) = c^2 v_{xx} + R(x,t) & \phi(x)=1 - \frac{x}{L}\;\;\;\psi(x)=\frac{x}{L}\\ v(0,t)=v(L,t)=0 & t>0 \\ v(x,0)=f(x)-\phi(x)p(0) - \psi(x)q(0) & f(x)=u(x,0) \\ v_t(x,0)=g(x)-\phi(x)p'(0) - \psi(x)q'(0) & g(x)=u_t(x,0) \end{cases} \]

Then solve as a forced equation.
Forced:
\[ u_{tt}=c^2 u_{xx} + R(x,t) \]
\[ u(x,t)=u_1(x,t)+u_2(x,t) \]
$$u_1$$ found by $$R(x,t)=0$$ and solving.
\[ u_2(x,t)=\sum_{n=1}^{\infty} C_n(t)\sin\left(\frac{n\pi x}{L}\right) \]
where $$\sin\frac{n\pi x}{L}$$ are the eigenfunctions from solving $$R(x,t)=0$$
\[ R(x,t)=\sum_{n=1}^{\infty} R_n(t)\sin\left(\frac{n\pi x}{L}\right) \]
\[ R_n(t)=\frac{2}{L}\int_0^L R(y,t)\sin\left(\frac{n\pi x}{L}\right)\,dy \]
\[ C_n''(t) + k^2 C_n(t)=R_n(t) \]
\[ C_n(t)=\alpha\sin(k t) + \beta\cos(k t) + sin(k t)\int_0^t R_n(s)\cos(k s)\,ds - \cos(k t)\int_0^t R_n(s)\sin(k s)\,ds \]

where $$C_n(0)=0$$ and $$c_n'(0)=0$$
Fourier Transform:
\[ \mathcal{F}(f)=\hat{f}(k)=\frac{1}{\sqrt{2\pi}}\int_{-\infty}^{\infty} f(\xi) e^{-i k \xi}\,d\xi \]
\[ \mathcal{F}^{-1}(f)=f(x)=\frac{1}{\sqrt{2\pi}}\int_{-\infty}^{\infty} \hat{f}(k) e^{ikx}\,dk \]
\[ \mathcal{F}(f+g)=\widehat{f+g}=\hat{f} + \hat{g} \]
\[ \widehat{fg}\neq\hat{f}\hat{g} \]
\[ \widehat{f'}=ik\hat{f}\text{ or }\widehat{f^{(n)}}=(ik)^n\hat{f} \]

\[ \widehat{u_t} = \frac{\partial \hat{u}}{\partial t} = \hat{u}_t \]
\[ \widehat{u_{tt}}=\frac{\partial^2\hat{u}}{\partial t^2}=\hat{u}_{tt} \]
\[ \widehat{u_{xx}}=(ik)^2\hat{u}=-k^2\hat{u} \]

\[ u(x,t)=\mathcal{F}^{-1}(\hat{u})=\frac{1}{\sqrt{2\pi}} \int_{-\infty}^{\infty} \hat{f}(k) e^{\alpha^2 k^2 t} e^{ikx}\,dk \]
\[ u(x,t)=\mathcal{F}^{-1}\left(\hat{f}(k) e^{-\alpha^2 k^2 t}\right) \]

Semi-infinite:
\[ \frac{1}{\sqrt{2\pi}} \int_{-\infty}^{\infty} \hat{F}(k) e^{\alpha^2 k^2 t} e^{ikx}\,dk \]
where
\[ \hat{F}(k)=-i\sqrt{\frac{2}{\pi}}\int_0^{\infty} f(\xi)\sin(k\xi)\,d\xi \]
$$f(x)$$$$\hat{f}(k)$$
\[1\text{ if } -s < x < s, 0\text{ otherwise }\]\[ \sqrt{\frac{2}{\pi}}\frac{\sin(ks)}{k} \]
\[ \frac{1}{x^2 + s^2} \]\[ \frac{1}{s}\sqrt{\frac{\pi}{2}}e^{-s|k|} \]
\[ e^{-sx^2} \]\[ \frac{1}{\sqrt{2s}}e^{\frac{k^2}{4s}} \]
\[ \frac{\sin(sx)}{x}\]\[ \sqrt{\frac{\pi}{2}}\text{ if } |k|<s, 0\text{ otherwise} \]
\[ e^{isx}\text{ if } a < x < b, 0\text{ otherwise} \]\[ \frac{i}{\sqrt{2\pi}}\left(\frac{1}{s-k} \right)\left(e^{ea(s-k)} - e^{ib(s-k)} \right) \]


AMath 402 - Dynamical Systems and Chaos
Dimensionless time
\[ \tau = \frac{t}{T} \]
where T gets picked so that
\[\frac{}{}\]
and
\[\frac{}{}\]
are of order 1.
Fixed points of $$x'=f(x)$$: set $$f(x)=0$$ and solve for roots
Bifurcation: Given $$x'=f(x,r)$$, set $$f(x,r)=0$$ and solve for $$r$$, then plot $$r$$ on the $$x-axis$$ and $$x$$ on the $$y-axis$$.
Saddle Node
Saddle Node
Transcritical Node
Transcritical
Subcritical Pitchfork
Subcritical Pitchfork
Supercritical Pitchfork
Supercritical Pitchfork

\[ \begin{matrix} x'=ax+by \\ y'=cx+dy \end{matrix} \]
\[ A=\begin{bmatrix} a & b \\ c & d \end{bmatrix}\]
\[ \begin{vmatrix} a-\lambda & b \\ c & d-\lambda \end{vmatrix}=0 \]
\[ \begin{matrix} \lambda^2 - \tau\lambda + \delta=0 & \lambda = \frac{\tau \pm \sqrt{\tau^2 - 4\delta}}{2} \\ \tau = a+d & \delta=ad-bc \end{matrix} \]
\[ x(t)=c_1 e^{\lambda_1 t}v_1 + c_2 e^{\lambda_2 t}v_2 \]
$$v_1,v_2$$ are eigenvectors.
Given $$\tau = \lambda_1 + \lambda_2$$ and $$\delta=\lambda_1\lambda_2$$:
if $$\delta < 0$$, the eigenvalues are real with opposite signs, so the fixed point is a saddle point.
otherwise, if $$\tau^2-4\delta > 0$$, its a node. This node is stable if $$\tau < 0$$ and unstable if $$\tau > 0$$
if $$\tau^2-4\delta < 0$$, its a spiral, which is stable if $$\tau < 0$$, unstable if $$\tau > 0$$, or a center if $$\tau=0$$
if $$\tau^2-4\delta = 0$$, its degenerate.
\[ \begin{bmatrix} x'=f(x,y) \\ y'=g(x,y) \end{bmatrix} \]
Fixed points are found by solving for $$x'=0$$ and $$y'=0$$ at the same time.
nullclines are when either $$x'=0$$ or $$y'=0$$ and are drawn on the phase plane.
\[ \begin{bmatrix} \frac{\partial f}{\partial x} & \frac{\partial f}{\partial y} \\ \frac{\partial g}{\partial x} & \frac{\partial g}{\partial y} \end{bmatrix} \]


$$\leftarrow$$ For nonlinear equations, evaluate this matrix at each fixed point, then use the above linear classification scheme to classify the point.

A basin for a given fixed point is the area of all trajectories that eventually terminate at that fixed point.
Given $$x'=f(x)$$, $$E(x)$$ is a conserved quantity if $$\frac{dE}{dt}=0$$
A limit cycle is an isolated closed orbit in a nonlinear system. Limit cycles can only exist in nonlinear systems.
If a function can be written as $$\vec{x}'=-\nabla V$$, then its a gradient function and can't have closed orbits.
The Liapunov function $$V(x)$$ for a fixed point $$x^*$$ satisfies $$V(x) > 0 \forall x \neq x^*, V(x^*)=0, V' < 0 \forall x \neq x^*$$
A Hopf bifurcation occurs as the fixed points eigenvalues (in terms of $$\mu$$) cross the imaginary axis.

Math 300 - Introduction to Mathematical Reasoning
PQ$$P \Rightarrow Q$$$$\neg P \vee Q$$
TTTT
TFFF
FTTT
FFTT

All valid values of $$x$$ constitute the Domain.
$$f(x)=y$$ The range in which $$y$$ must fall is the codomain
The image is the set of $$y$$ values that are possible given all valid values of $$x$$
So, $$\frac{1}{x}$$ has a domain $$\mathbb{R} - \{0\}$$ and a codomain of $$\mathbb{R}$$. However, no value of $$x$$ can ever produce $$f(x)=0$$, so the Image is $$\mathbb{R}-\{0\}$$

Injective: No two values of $$x$$ yield the same result. $$f(x_1)\neq f(x_2)$$ if $$x_1 \neq x_2$$ for all $$x$$
Surjective: All values of $$y$$ in the codomain can be produced by $$f(x)$$. In other words, the codomain equals the image.
Bijective: A Bijective function is both Injective and Surjective - all values of $$y$$ are mapped to exactly one value of $$x$$. A simple way to prove this is to solve $$f(x)$$ for $$x$$. If this can be done without creating multiple solutions (a square root, for example, yields $$\pm$$, not a single answer), then it's a bijective function.
If $$f(x)$$ is a bijection, it is denumerable. Any set that is equivalent to the natural numbers is denumerable.
$$\forall x \in \mathbb{R}$$ means "for all $$x$$ in $$\mathbb{R}$$", where $$\mathbb{R}$$ can be replaced by any set.
$$\exists y \in \mathbb{R}$$ means "there exists a $$y$$ in $$\mathbb{R}$$", where $$\mathbb{R}$$ can be replaced by any set.
\[ A \vee B = A\text{ or }B \]
\[ A \wedge B = A\text{ and }B \]
\[ P \Leftrightarrow Q\text{ means }P \Rightarrow Q \wedge Q\Rightarrow P \text{ or } P\text{ iff }Q \text{ (if and only if)} \]

$$A \cup B$$ = Union - All elements that are in either A or B, or both.
\[ \{x|x \in A \text{ or } x \in B \} \]

$$A \cap B$$ = Intersection - All elements that are in both A and B
\[ \{x|x \in A \text{ and } x \in B \} \]

$$A\subseteq B$$ = Subset - Indicates A is a subset of B, meaning that all elements in A are also in B.
\[ \{x \in A \Rightarrow x \in B \} \]

$$A \subset B$$ = Strict Subset - Same as above, but does not allow A to be equal to B (which happens if A has all the elements of B, because then they are the exact same set).
$$A-B$$ = Difference - All elements in A that aren't also in B
\[ \{x|x \in A \text{ and } x \not\in B \} \]

$$A\times B$$ = Cartesian Product - All possible ordered pairs of the elements in both sets:
\[ \{(x,y)|x \in A\text{ and }y\in B\} \]

ProofWe use induction on $$n$$
Base Case:[Prove $$P(n_0)$$]
Inductive Step:Suppose now as inductive hypothesis that [$$P(k)$$ is true] for some integer $$k$$ such that $$k \ge n_0$$. Then [deduce that $$P(k+1)$$ is true]. This proves the inductive step.
Conclusion:Hence, by induction, [$$P(n)$$ is true] for all integers $$n \ge n_0$$.
ProofWe use strong induction on $$n$$
Base Case:[Prove $$P(n_0)$$, $$P(n_1)$$, ...]
Inductive Step:Suppose now as inductive hypothesis that [$$P(n)$$ is true for all $$n \le k$$] for some positive integer $$k$$, then [deduce that $$P(k+1)$$ is true]. This proves the inductive step.
Conclusion:Hence, by induction [$$P(n)$$ is true] for all positive integers $$n$$.
Proof:Suppose, for contradiction, that the statement $$P$$ is false. Then, [create a contradiction]. Hence our assumption that $$P$$ is false must be false. Thus, $$P$$ is true as required.

The composite of $$f:X\rightarrow Y$$ and $$g:Y\rightarrow Z$$ is $$g\circ f: x\rightarrow Z$$ or just $$gf: X\rightarrow Z$$. $$g\circ f = g(f(x)) \forall x \in X$$
\[ a\equiv b \bmod m \Leftrightarrow b\equiv a \bmod m \]
If
\[ a \equiv b \bmod m\text{ and }b \equiv c \bmod m,\text{ then }a \]

Negation of $$P \Rightarrow Q$$ is $$P \wedge (\neg Q)$$ or $$P and (not Q)$$
If $$m$$ is divisible by $$a$$, then $$a b_1 \equiv a b_2 \bmod m \Leftrightarrow b_1 \equiv b_2 \bmod\left(\frac{m}{a} \right)$$
Fermat's little theorem: If $$p$$ is a prime, and $$a \in \mathbb{Z}^+$$ which is not a multiple of $$p$$, then $$a^{p-1}\equiv 1 \bmod p$$.
Corollary 1: If $$p$$ is prime, then $$\forall a \in \mathbb{Z}, a^p = a \bmod p$$
Corollary 2: If $$p$$ is prime, then $$(p-1)! \equiv -1 \bmod p$$

Division theorem: $$a,b \in \mathbb{Z}$$, $$b > 0$$, then $$a = bq+r$$ where $$q,r$$ are unique integers, and $$0 \le r < b$$. Thus, for $$a=bq+r$$, $$\gcd(a,b)=\gcd(b,r)$$. Furthermore, $$b$$ divides $$a$$ if and only if $$r=0$$, and if $$b$$ divides $$a$$, $$\gcd(b,a)=b$$

Euclidean Algorithm: $$\gcd(136,96)$$
$$136=96\cdot 1 + 40$$
\[ 290x\equiv 5\bmod 357 \rightarrow 290x + 357y = 5 \]

$$96=40\cdot 2 + 16$$
\[ ax\equiv b \bmod c \rightarrow ax+cy=b \]

$$40=16\cdot 2 + 8$$
$$16=8\cdot 2 + 0 \leftarrow$$ stop here, since the remainder is now 0
$$\gcd(136,96)=8$$

Diophantine Equations (or linear combinations):
$$140m + 63n = 35$$ $$m,n \in \mathbb{Z}$$ exist for $$am+bn=c$$ iff $$\gcd(a,b)$$ divides $$c$$
$$140=140\cdot 1 + 63\cdot 0$$
$$63=140\cdot 0 + 63\cdot 1$$ dividing $$am+bn=c$$ by $$\gcd(a,b)$$ always yields coprime $$m$$ and $$n$$.
$$14=140\cdot 1 - 63\cdot 2$$
$$7=63\cdot 1 - 14\cdot 4 = 63 - (140\cdot 1 - 63\cdot 2)\cdot 4 = 63 - 140\cdot 4 + 63\cdot 8 = 63\cdot 9 - 140\cdot 4 $$
$$0=14 - 7\cdot 2 =140\cdot 1 - 63\cdot 2 - 2(63\cdot 9 - 140\cdot 4) = 140\cdot 9-63\cdot 20 $$
So $$m=9$$ and $$n=-20$$

Specific: $$7=63\cdot 9 - 140\cdot 4 \rightarrow 140\cdot(-4)+63\cdot 9=7\rightarrow 140\cdot(-20)+63\cdot45=35$$
So for $$140m+63n=35, m=-20, n=45$$
Homogeneous: $$140m+63n=0 \; \gcd(140,63)=7 \; 20m + 9n = 0 \rightarrow 29m=-9n$$
$$m=9q, n=-20q$$ for $$q\in \mathbb{Z}$$ or $$am+bn=0 \Leftrightarrow (m,n)=(bq,-aq)$$
General: To find all solutions to $$140m+63n=35$$, use the specific solution $$m=-20, n=45$$
$$140(m+20) + 63(n-45) = 0$$
$$(m+20,n-45)=(9q,-20q)$$ use the homogeneous result and set them equal.
$$(m,n)=(9q-20,-20q+45)$$ So $$m=9q-20$$ and $$n=-20q+45$$
\[ [a]_m = \{x\in \mathbb{Z}| x\equiv a \bmod m \} \Rightarrow \{ mq + a|q \in \mathbb{Z} \} \]

$$ax\equiv b \bmod m$$ has a unique solution $$\pmod{m}$$ if $$a$$ and $$m$$ are coprime. If $$\gcd(a,b)=1$$, then $$a$$ and $$b$$ are coprime. $$[a]_m$$ is invertible if $$\gcd(a,m)=0$$.

Math 327 - Introduction to Real Analysis I
Cauchy Sequence: For all $$\epsilon > 0$$ there exists an integer $$N$$ such that if $$n,m \ge N$$, then $$|a_n-a_m|<\epsilon$$

Alternating Series: Suppose the terms of the series $$\sum u_n$$ are alternately positive and negative, that $$|u_{n+1}| \le |u_n|$$ for all $$n$$, and that $$u_n \to 0$$ as $$n\to\infty$$. Then the series $$\sum u_n$$ is convergent.

Bolzano-Weierstrass Theorem: If $$S$$ is a bounded, infinite set, then there is at least one point of accumulation of $$S$$.

$$\sum u_n$$ is absolutely convergent if $$\sum|u_n|$$ is convergent
If $$\sum u_n$$ is absolutely convergent, then $$\sum u_n = \sum a_n - \sum b_n$$ where both $$\sum a_n$$ and $$\sum b_n$$ are convergent. If $$\sum u_n$$ is conditionally convergent, both $$\sum a_n$$ and $$\sum b_n$$ are divergent.

\[ \sum u_n = U = u_0 + u_1 + u_2 + ... \]
\[ w_0 = u_0 v_0 \]
\[ w_1 = u_0 v_1 + u_1 v_0 \]

\[ \sum v_n = V = v_0 + v_1 + v_2 + ... \]
\[ w_n = u_0 v_n + u_1 v_{n-1} + ... + u_n v_0 \]

\[ \sum w_n = UV = w_0 + w_1 + w_2 + ... \]
Provided
\[ \sum u_n, \sum v_n \]
are absolutely convergent.

$$\sum a_n x^n$$ is either absolutely convergent for all $$x$$, divergent for all $$x\neq 0$$, or absolutely convergent if $$-R < x < R$$ (it may or may not converge for $$x=\pm R$$ ).
$$-R < x < R$$ is the interval of convergence. $$R$$ is the radius of convergence.
\[ R=\lim_{n \to \infty}\left|\frac{a_n}{a_{n+1}}\right| \]
if the limit exists or is $$+\infty$$
Let the functions of the sequence $$f_n(x)$$ be defined on the interval $$[a,b]$$. If for each $$\epsilon > 0$$ there is an integer $$N$$ independent of x such that $$|f_n(x) - f_m(x)| < \epsilon$$ where $$N \le m,n$$.

You can't converge uniformly on any interval containing a discontinuity.
\[ |a|+|b|\le|a+b| \]
\[ \lim_{n \to \infty}(1+\frac{k}{n})^n = e^k \]
\[ lim_{n \to \infty} n^{\frac{1}{n}}=1 \]
\[ \sum_{k=0}^{\infty}=\frac{a}{1-r} \]
if $$|r| < 1$$
\[\sum a_n x^n\]
has a radius of convergence
\[R = \lim_{n \to \infty}\left|\frac{a_n}{a_{n+1}} \right|\]
if it exists or is $$+\infty$$. The interval of convergence is $$-R < x < R$$
\[ \sum^{\infty}\frac{x^2}{(1+x^2)^n} = x^2\sum\left(\frac{1}{1+x^2}\right)^n = x^2\left(\frac{1}{1-\frac{1}{1+x^2}}\right) = x^2\left( \frac{1+x^2}{1+x^2-1}\right) = x^2\left( \frac{1+x^2}{x^2} \right) = 1+x^2 \]

Math 427 - Complex Analysis
0$$\frac{\pi}{6}$$$$\frac{\pi}{4}$$$$\frac{\pi}{3}$$$$\frac{\pi}{2}$$
$$\sin$$0$$\frac{1}{2}$$$$\frac{\sqrt{2}}{2}$$$$\frac{\sqrt{3}}{2}$$1
$$\cos$$1$$\frac{\sqrt{3}}{2}$$$$\frac{\sqrt{2}}{2}$$$$\frac{1}{2}$$0
$$\tan$$0$$\frac{1}{\sqrt{3}}$$1$$\sqrt{3}$$$$\varnothing$$
\[ \frac{z_1}{z_2} = \frac{x_1 x_2 + y_1 y_2}{x_2^2 + y_2^2} + i\frac{y_1 x_1 - x_1 y_2}{x_2^2 + y_2^2} \]
\[ |z| = \sqrt{x^2 + y^2} \]
\[ \bar{z} = x-i y \]
\[ |\bar{z}|=|z| \]

\[ \text{Re}\,z=\frac{z+\bar{z}}{2} \]
\[ \text{Im}\,z=\frac{z-\bar{z}}{2i} \]
\[ \text{Arg}\,z=\theta\text{ for } -\pi < \theta < \pi \]
\[ z=re^{i\theta}=r(\cos(\theta) + i\sin(\theta)) \]

\[ \lim_{z \to z_0} f(z) = w_0 \iff \lim_{x,y \to x_0,y_0} u(x,y) = u_0 \text{ and }\lim_{x,y \to x_0,y_0} v(x,y)=v_0 \text{ where } w_0=u_0+iv_0 \text{ and } z_0=x_0+iy+0 \]

\[ \lim_{z \to z_0} f(z) = \infty \iff \lim_{z \to z_0} \frac{1}{f(z)}=0 \]

\[ \lim_{z \to \infty} f(z) = w_0 \iff \lim_{z \to 0} f\left(\frac{1}{z}\right)=w_0\]
\[ \text{Re}\,z\le |\text{Re}\,z|\le |z| \]
\[ \text{Im}\,z\le |\text{Im}\,z| \le z \]

\[ \lim_{z \to \infty} f(z) = \infty \iff \lim_{z\to 0}\frac{1}{f\left(\frac{1}{z}\right)}=0\]
\[ \left| |z_1| - |z_2| \right| \le |z_1 + z_2| \le |z_1| + |z_2| \]

Roots:
\[ z = \sqrt[n]{r_0} \exp\left[i\left(\frac{\theta_0}{n} + \frac{2k\pi}{n} \right)\right] \]
Harmonic:
\[ f_{xx} + f_{yy} = 0 \text{ or } f_{xx}=-f_{yy} \]

Cauchy-Riemann:
\[ f(z) = u(x,y)+iv(x,y) \]
\[ \sinh(z)=\frac{e^z-e^{-z}}{2}=-i\sin(iz) \]
\[ \frac{d}{dz}\sinh(z)=\cosh(z) \]

\[ u_x = v_y \]
\[ u_y = -v_x \]
\[ \cosh(z) = \frac{e^z + e^{-z}}{2} = cos(iz) \]
\[ \frac{d}{dz}\cosh(z)=\sinh(z) \]

\[ f(z) = u(r,\theta)+iv(r,\theta) \]
\[ \sin(z)=\frac{e^{iz}-e{-iz}}{2i}=i-\sinh(iz)=\sin(x)\cosh(y) + i\cos(x)\sinh(y) \]

\[ r u_r = v_{\theta} \]
\[ u_{\theta}=-r v_r \]
\[ \cos(z)=\frac{e^{iz}+e^{-iz}}{2}=\cosh(iz)=\cos(x)\cosh(y) - i \sin(x)\sinh(y) \]

\[ \sin(x)^2 + \sinh(y)^2 = 0 \]
\[ |\sin(z)|^2 = \sin(x)^2 + \sinh(y)^2 \]
\[ |\cos(z)|^2 = \cos(x)^2 + \sinh(y)^2 \]

$$e^z$$ and Log:
\[ e^z=e^{x+iy}=e^x e^{iy}=e^x(\cos(y) + i\sin(y)) \]
\[ e^x e^{iy} = \sqrt{2} e^{i\frac{\pi}{4}} \]
\[ e^x = \sqrt{2} \]
\[ y = \frac{\pi}{4} + 2k\pi \]
\[ x = \ln\sqrt{2} \]
So,
\[ z = \ln\sqrt{2} + i\pi\left(\frac{1}{4} + 2k\right) \]
\[ \frac{d}{dz} log(f(z)) = \frac{f'(z)}{f(z)} \]

Cauchy-Gourgat: If $$f(z)$$ is analytic at all points interior to and on a simple closed contour $$C$$, then
\[ \int_C f(z) \,dz=0 \]

\[ \int_C f(z) \,dz = \int_a^b f[z(t)] z'(t) \,dt \]
\[ a \le t \le b \]
$$z(t)$$ is a parameterization. Use $$e^{i\theta}$$ for circle!
Maximum Modulus Principle: If $$f(z)$$ is analytic and not constant in $$D$$, then $$|f(z)|$$ has no maximum value in $$D$$. That is, no point $$z_0$$ is in $$D$$ such that $$|f(z)| \le |f(z_0)|$$ for all $$z$$ in $$D$$.
Corollary: If $$f(z)$$ is continuous on a closed bounded region $$R$$ and analytic and not constant through the interior of $$R$$, then the maximum value of $$|f(z)|$$ in $$R$$ always exists on the boundary, never the interior.
Taylor's Theorem: Suppose $$f(z)$$ is analytic throughout a disk $$|z-z_0|<R$$. Then $$f(z)$$ has a power series of the form
\[ f(z) = \sum_{n=0}^{\infty}\frac{f^{(n)}(z_0)}{n!}(z-z_0)^n \]
where $$|z-z_0| < R_0$$ and $$n=0,1,2,...$$
Alternatively,
\[ \sum_{n=0}^{\infty} a_n(z-z_0)^n \text{ where } a_n=\frac{f^{(n)}(z_0)}{n!} \]

For $$|z|<\infty$$:
\[ e^z = \sum_{n=0}^{\infty}\frac{z^n}{n!} \]
\[ \sin(z) = \sum_{n=0}^{\infty}(-1)^n\frac{z^{2n+1}}{(2n+1)!} \]
\[ \cos(z) = \sum_{n=0}^{\infty}(-1)^n\frac{z^{2n}}{(2n)!} \]

Note that
\[ \frac{1}{1 - \frac{1}{z}}=\sum_{n=0}^{\infty}\left(\frac{1}{z}\right)^n \text{ for } \left|\frac{1}{z}\right| < 1\]
, which is really $$1 < |z|$$ or $$|z| > 1$$
For $$|z| < 1$$:
\[ \frac{1}{1-z} = \sum_{n=0}^{\infty} z^n \]
\[ \frac{1}{1+z} = \sum_{n=0}^{\infty} (-1)^n z^n \]
For $$|z-1|<1$$:
\[ \frac{1}{z} = \sum_{n=0}^{\infty} (-1)^n (z-1)^n \]

Analytic: $$f(z)$$ is analytic at point $$z_0$$ if it has a derivative at each point in some neighborhood of $$z_0$$.
$$f(z)=u(x,y)+iv(x,y)$$ is analytic if and only if $$v$$ is a harmonic conjugate of $$u$$.
If $$u(x,y)$$ and $$v(x,y)$$ are harmonic functions such that $$u_{xx}=-u{yy}$$ and $$v_{xx}=-v_{yy}$$, and they satisfy the Cauchy-Reimann conditions, then $$v$$ is a harmonic conjugate of $$u$$.

Differentiable: $$f(z)=u(x,y)+iv(x,y)$$ is differentiable at a point $$z_0$$ if $$f(z)$$ is defined within some neighborhood of $$z_0=x_0+iy_0$$, $$u_x$$ $$u_y$$ $$v_x$$ and $$v_y$$ exist everywhere in the neighborhood, those first-order partial derivatives exist at $$(x_0,y_0)$$ and satisfy the Reimann-Cauchy conditions at $$(x_0,y_0)$$.
Cauchy Integral Formula:
\[ \int_C \frac{f(z)}{z-z_0}\,dz = 2\pi i f(z_0) \]
where $$z_0$$ is any point interior to $$C$$ and $$f(z)$$ is analytic everywhere inside and on $$C$$ taken in the positive sense. Note that $$f(z)$$ here refers to the actual function $$f(z)$$, not $$\frac{f(z)}{z-z_0}$$
Generalized Cauchy Integral Formula:
\[ \int_C \frac{f(z)}{(z-z_0)^{n+1}}\,dz = \frac{2\pi i}{n!} f^{(n)}(z_0) \]
(same conditions as above)
Remember, discontinuities that are roots can be calculated and factored:
\[ \frac{1}{z^2-w_0}=\frac{1}{(z-z_1)(z-z_2)} \]

Residue at infinity:
\[ \int_C f(z)\,dz = 2\pi i \,\mathop{Res}\limits_{z=0}\left[\frac{1}{z^2} f\left(\frac{1}{z}\right) \right] \]

A residue at $$z_0$$ is the $$n=-1$$ term of the Laurent series centered at $$z_0$$.
A point $$z_0$$ is an isolated singular point if $$f(z_0)$$ fails to be analytic, but is analytic at some point in every neighborhood of $$z_0$$, and there's a deleted neighborhood $$0 < |z-z_0| < \epsilon$$ of $$z_0$$ throughout which $$f$$ is analytic.
\[ \mathop{Res}\limits_{z=z_0}\,f(z)=\frac{p(z_0)}{q'(z_0)}\text{ where }f(z) = \frac{p(z)}{q(z)}\text{ and } p(z_0)\neq 0 \]

\[ \int_C f(z)\,dz = 2\pi i \sum_{k=1}^n\,\mathop{Res}\limits_{z=z_k}\,f(z) \]
where $$z_0$$, $$z_1$$, $$z_2$$,... $$z_k$$ are all the singular points of $$f(z)$$ (which includes poles).

If a series has a finite number of $$(z-z_0)^{-n}$$ terms, its a pole ($$\frac{1}{z^4}$$ is a pole of order 3). If a function, when put into a series, has no $$z^{-n}$$ terms, it's a removable singularity. If it has an infinite number of $$z^{-n}$$ terms, its an essential singularity (meaning, you can't get rid of it).

AMath 401 - Vector Calculus and Complex Variables
$$||\vec{x}||=\sqrt{x_1^2+x_2^2+ ...}$$
$$\vec{u}\cdot\vec{v} = ||\vec{u}||\cdot||\vec{v}|| \cos(\theta)=u_1v_1+u_2v_2+ ...$$
$$||\vec{u}\times\vec{v}|| = ||\vec{u}||\cdot||\vec{v}|| \sin(\theta) = \text{ area of a parallelogram}$$
\[ \vec{u}\times\vec{v} = \begin{vmatrix} \vec{\imath} & \vec{\jmath} & \vec{k} \\ u_1 & u_2 & u_3 \\ v_1 & v_2 & v_3 \end{vmatrix} \]
\[ \begin{vmatrix} a & b \\ c & d \end{vmatrix} = ad-bc \]
\[ \vec{u}\cdot\vec{v}\times\vec{w} = \vec{u}\cdot(\vec{v}\times\vec{w})=\text{ volume of a parallelepiped} \]

\[ h_?\equiv\left|\left|\frac{\partial\vec{r}}{\partial ?}\right|\right| \]
\[ \hat{e}_r(\theta)=\frac{1}{h_r}\frac{\partial\vec{r}}{\partial r} \]
\[ \hat{e}_r'(\theta)=\frac{d\hat{e}_r}{d\theta}=\hat{e}_{\theta}(\theta) \]

\[ \vec{r}=r(t)\hat{e}_r(\theta(t)) \]
\[ \vec{r}'(t)=r'(t)\hat{e}_r + r(t)\frac{d\hat{e}_r}{dt}\]
\[ \vec{r}'(t)=r'(t)\hat{e}_r + r(t)\frac{d\hat{e}_r}{d\theta}\frac{d\theta}{dt}=r'(t)\hat{e}_r + r(t)\hat{e}_{\theta} \theta'(t) \]

Projection of $$\vec{u}$$ onto $$\vec{v}$$:
\[ ||\vec{u}|| \cos(\theta) = \frac{\vec{u}\cdot\vec{v}}{||\vec{v}||} \]
Arc Length:
\[ \int_a^b \left|\left| \frac{d\vec{r}}{dt} \right|\right| \,dt = \int_a^b ds \]

Parametrization:
\[ s(t) = \int_a^t \left|\left|\frac{d\vec{r}}{dt}\right|\right| \,dt \]
\[ \frac{dx}{dt}=x'(t) \]
\[ dx = x'(t)\,dt \]
\[ \oint x \,dy - y \,dx = \oint\left(x \frac{dy}{dt} - y \frac{dx}{dt}\right)\,dt = \oint x y'(t) - y x'(t) \,dt \]
\[ \nabla = \frac{\partial}{\partial x}\vec{\imath} + \frac{\partial}{\partial y}\vec{\jmath} + \frac{\partial}{\partial z}\vec{k} \]
\[ \nabla f = \left\langle \frac{\partial f}{\partial x},\frac{\partial f}{\partial y},\frac{\partial f}{\partial z} \right\rangle \]
\[ D_{\vec{u}} f(\vec{P})=f'_{\vec{u}}=\nabla f \cdot \vec{u} \]
\[ \nabla(fg)=f\nabla g + g \nabla f \]

\[ \vec{F}(x,y,z)=F_1(x,y,z)\vec{\imath} + F_2(x,y,z)\vec{\jmath} + F_3(x,y,z)\vec{k} \]

\[ \text{div}\, \vec{F} = \nabla \cdot \vec{F} = \frac{\partial F_1}{\partial x} + \frac{\partial F_2}{\partial y} + \frac{\partial F_3}{\partial z} \]

\[ \text{curl}\, \vec{F} = \nabla \times \vec{F} = \left\langle \frac{\partial F_3}{\partial y} - \frac{\partial F_2}{\partial z}, \frac{\partial F_1}{\partial z} - \frac{\partial F_3}{\partial x}, \frac{\partial F_2}{\partial x} - \frac{\partial F_1}{\partial y} \right\rangle \]

Line integral:
\[ \int_{\vec{r}(a)}^{\vec{r}(b)}\vec{F}\cdot \vec{r}'(t)\,dt = \int_{\vec{r}(a)}^{\vec{r}(b)}\vec{F}\cdot d\vec{r} \]
Closed path:
\[ \oint \vec{F}\cdot d\vec{r} \]
\[ d\vec{r} = \nabla\vec{r}\cdot \langle du_1,du_2,du_3 \rangle = h_1 du_1 \hat{e}_1 + h_2 du_2 \hat{e}_2 + h_3 du_3 \hat{e}_3 \]
\[ h_?= \left|\left| \frac{\partial\vec{r}}{\partial ?} \right|\right| = \frac{1}{||\partial ?||} \]
\[ \hat{e}_?=\frac{1}{h_?}\frac{\partial\vec{r}}{\partial?}=h_?\nabla?(x,y,z)=\frac{\nabla?}{||\nabla?||} \]
If $$\vec{r}=\vec{r}(s)$$ then
\[ \int_a^b\vec{F}\cdot \frac{d\vec{r}}{ds} \,ds = \int_a^b\vec{F}\cdot\vec{T} \,ds\]

\[ \nabla f \cdot \hat{e}_?=\frac{1}{h_?}\frac{\partial f}{\partial ?} \]
\[ \nabla f = (\nabla f \cdot \hat{e}_r)\hat{e}_r + (\nabla f \cdot \hat{e}_{\theta})\hat{e}_{\theta} = \frac{\partial f}{\partial r}\hat{e}_r + \frac{1}{r}\frac{\partial f}{\partial \theta}\hat{e}_{\theta} \]
\[ ds = \sqrt{d\vec{r}\cdot d\vec{r}} = \left|\left| \frac{d\vec{r}}{dt}dt \right|\right| = \sqrt{h_1^2 du_1^2 + h_2^2 du_2^2+h_3^2 du_3^2} \]

\[ Spherical: h_r=1, h_{\theta}=r, h_{\phi}=r\sin(\theta) \]

\[ \vec{r}=\frac{\nabla f}{||\nabla f||} \]
\[ \vec{r}=\vec{r}(u,v) \]
\[ \vec{n}= \frac{\frac{\partial\vec{r}}{\partial u}\times\frac{\partial\vec{r}}{\partial v}}{\left|\left| \frac{\partial\vec{r}}{\partial u}\times\frac{\partial\vec{r}}{\partial v} \right|\right|} \]

$$\vec{F}$$ is conservative if:
\[ \vec{F}=\nabla\phi \]
\[ \nabla\times\vec{F}=0 \]
\[ \vec{F}=\nabla\phi \iff \nabla\times\vec{F}=0 \]

\[ \iint\vec{F}\cdot d\vec{S} \]
\[ d\vec{S}=\left(\frac{\partial\vec{r}}{\partial u} \times \frac{\partial\vec{r}}{\partial v} \right)\,du\,dv \]
\[ d\vec{S}=\vec{n}\,dS \]
Surface Area:
\[ \iint \,dS \]

Flux:
\[ \iint\vec{F}\cdot d\vec{S} \]

Shell mass:
\[ \iint p\cdot dS \]

Stokes:
\[ \iint(\nabla\times\vec{F})\cdot d\vec{S} = \oint\vec{F}\cdot d\vec{r} \]

Divergence:
\[ \iiint\limits_V\nabla\cdot\vec{F}\,dV=\iint\limits_{\partial v} \vec{F}\cdot d\vec{S} \]

If $$z=f(x,y)$$, then
\[ \vec{r}(x,y) = \langle x,y,f(x,y) \rangle \]

\[ \nabla\cdot\vec{F}=\frac{1}{h_1 h_2 h_3}\left[\frac{\partial}{\partial u_1}(F_1 h_2 h_3) + \frac{\partial}{\partial u_2}(F_2 h_1 h_3) + \frac{\partial}{\partial u_3}(F_3 h_1 h_2) \right] \]
\[ dV = \left| \frac{\partial\vec{r}}{\partial u_1}\cdot\left(\frac{\partial\vec{r}}{\partial u_2}\times\frac{\partial\vec{r}}{\partial u_3} \right) \right| du_1 du_2 du_3 \]
If orthogonal,
\[ I = \iiint\limits_V f(u_1,u_2,u_3)h_1 h_2 h_3\,du_1\,du_2\,du_3 \]
\[ (x-c_x)^2 + (y-c_y)^2 = r^2 \Rightarrow \vec{r}(t)=\langle c_x + r\cos(t),c_y+r\sin(t) \rangle \]

Ellipse:
\[ \Rightarrow \vec{r}(t)=\langle c_x+a\cos(t), c_y+b\sin(t) \rangle \]

For spherical, if $$\theta$$ is innermost, its max value is $$\pi$$, or if its on the z value.
\[ \vec{r}(\theta,\phi)=\langle \sin(\theta)\cos(\phi), \sin(\theta)\sin(\phi),\cos(\theta) \rangle \]


Laplace Transform:
\[ \mathcal{L}\left[f(t)\right]=F(s)=\int_0^{\infty}e^{-st}f(t)\,dt \]
\[ \mathcal{L}[f'(t)] = s\mathcal{L}[f(t)] - f(0) = s\cdot F(s)-f(0)\]
\[ \mathcal{L}[f''(t)] = s^2\mathcal{L}[f(t)] - s\cdot f(0) - f'(0) = s^2\cdot F(s) - s\cdot f(0) - f'(0)\]

\[ \mathcal{L}[0] = 0 \]
\[ \mathcal{L}[1] = \frac{1}{s} \]
\[ \mathcal{L}[k] = \frac{k}{s} \]
\[ \mathcal{L}[e^{at}] = \frac{1}{s-a} \]
\[ \mathcal{L}[\cos(\omega t)] = \frac{s}{s^2 + \omega^2} \]
\[ \mathcal{L}[\sin(\omega t)] = \frac{\omega}{s^2 + \omega^2} \]


Math 461 - Combinatorial Theory I
General Pigeon: Let $$n$$,$$m$$, and $$r$$ be positive integers so that $$n>rm$$. Let us distribute $$n$$ balls into $$m$$ boxes. Then there will be at least 1 box in which we place at least $$r+1$$ balls.



Base Case:Prove $$P(0)$$ or $$P(1)$$
Inductive Step:Show that by assuming the inductive hypothesis $$P(k)$$, this implies that $$P(k+1)$$ must be true.
Strong Induction:Show that $$P(k+1)$$ is true if $$P(n)$$ for all $$n < k+1$$ is true.

There are $$n!$$ permutations of an $$n$$-element set (or $$n!$$ linear orderings of $$n$$ objects)
$$n$$ objects sorted into $$a,b,c,...$$ groups have $$\frac{n!}{a!b!c!...}$$ permutations. This is also known as a $$k$$-element multiset of $$n$$.
Number of $$k$$-digit strings in an $$n$$-element alphabet: $$n^k$$. All subsets of an $$n$$-element set: $$2^n$$
Let $$n$$ and $$k$$ be positive integers such that $$n \ge k$$, then the number of $$k$$-digit strings over an $$n$$-element alphabet where no letter is used more than once is $$\frac{n!}{(n-k)!}=(n)_k$$
\[ \binom{n}{k} = \frac{n!}{k!(n-k)!} = \frac{(n)_k}{k!} \rightarrow \]
This is the number of $$k$$-element subsets in $$[n]$$, where $$[n]$$ is an $$n$$-element set.
\[ \binom{n}{k} = \binom{n}{n-k} \]
\[ \binom{n}{0} = \binom{n}{n} = \binom{0}{0} = 1 \]

Number of $$k$$-element multisets in $$[n]$$:
\[ \binom{n+k-1}{k} \]

Binomial Theorem:
\[ (x+y)^n = \sum_{k=0}^n\binom{n}{k}x^k y^{n-k} \text{ for } n \ge 0 \]

Multinomial Theorem:
\[ (x_1 + x_2 + ... + x_k)^n = \sum_{a_1,a_2,...,a_k} \binom{n}{a_1,a_2,...,a_k} x_1^{a_1} x_2^{a_2} ... x_k^{a_k} \]
\[ \binom{n}{k} + \binom{n}{k+1} = \binom{n+1}{k+1} \text{ for } n,k \ge 0 \]
\[ \binom{k}{k} + \binom{k+1}{k} + ... + \binom{n}{k} = \binom{n+1}{k+1} \text{ for } n,k \ge 0 \]
\[ \binom{n}{k} \le \binom{n}{k} \text{ if and only if } k \le \frac{n-1}{2} \text{ and } n=2k+1 \]
\[ \binom{n}{k} \ge \binom{n}{k} \text{ if and only if } k \ge \frac{n-1}{2} \text{ and } n=2k+1 \]
\[ \binom{n}{a_1,a_2,...,a_k} = \frac{n!}{a_1!a_2!...a_k!} \]
\[ \binom{n}{a_1,a_2,...,a_k} = \binom{n}{a_1}\cdot \binom{n-a_1}{a_2} \cdot ... \cdot \binom{n-a_1-a_2-...-a_{k-1}}{a_k} \text{ if and only if } n=\sum_{i=1}^k a_i\]
\[ \binom{m}{k} = \frac{m(m-1)...(m-k+1)}{k!} \text{ for any real number } m \]
\[ (1+x)^m = \sum_{n\ge 0}^{\infty} \binom{m}{n}x^n \]
\[ \sum_{k=0}^n (-1)^k\binom{n}{k} = 0 \text{ for } n \ge 0 \]
\[ 2^n = \sum_{k=0}^n \binom{n}{k} = 0 \text{ for } n \ge 0 \]
\[ \sum_{k=1}^n k\binom{n}{k} = n 2^{n-1} \text{ for } n \ge 0 \]
\[ \binom{n+m}{k} = \sum_{i=0}^k \binom{n}{i} \binom{n}{k-i} \text{ for } n,m,k \ge 0 \]

\[ |E| = \frac{1}{2}\sum_{v\in V} deg(v) \]
or, the number of edges in a graph is half the sum of its vertex degrees.
Compositions:$$n$$ identical objects
$$k$$ distinct boxes
\[\binom{n-1}{k-1}\]$$n$$ identical objects
any number of distinct boxes
$$2^{n-1}$$
Weak Compositions:
(empty boxes allowed)
$$n$$ identical objects
$$k$$ distinct boxes
\[ \binom{n+k-1}{k-1} \]$$n$$ distinct objects
$$k$$ distinct boxes
$$k^n$$

Split $$n$$ people into $$k$$ groups of $$\frac{n}{k}$$:
Unordered:
\[ \frac{n!}{\left(\left(\frac{n}{k}\right)!\right)^k k!} \]
Ordered:
\[ \frac{n!}{\left(\left(\frac{n}{k}\right)!\right)^k} \]

Steps from (0,0) to (n,k) on a lattice:
\[\binom{n+k}{k}\]

Ways to roll $$n$$ dice so all numbers 1-6 show up at least once: $$6^n - \binom{6}{5}5^n + \binom{6}{4}4^n + \binom{6}{3}3^n + \binom{6}{2}2^n + \binom{6}{1}$$
The Sieve: $$|A_1| + |A_2| - |A_1\cap A_2|$$ or $$|A_1| + |A_2| + |A_3| - |A_1\cap A_2| - |A_1\cap A_3| - |A_2\cap A_3| + |A_1\cap A_2\cap A_3|$$
Also, $$|S - (S_A\cap S_B\cap S_C)| = |S| - |S_A| - |S_B| - |S_C| + |S_A\cap S_B| + |S_A\cap S_C| + |S_B\cap S_C| - |S_A\cap S_B\cap S_C|$$

Graphs: A simple graph has no loops (edges connecting a vertex to itself) or multiple edges between the same vertices. A walk is a path through a series of connected edges. A trail is a walk where no edge is traveled on more than once. A closed trail starts and stops on the same vertex. A Eulerian trail uses all edges in a graph. A trail that doesn't touch a vertex more than once is a path. $$K_n$$ is the complete graph on $$n$$-vertices.
If one can reach any vertex from any other on a graph $$G$$, then $$G$$ is a connected graph.
A connected graph has a closed Eulerian trail if and only if all its vertices have even degree. Otherwise, it has a Eulerian trail starting on S and ending on T if only S and T have odd degree.
In a graph without loops there are an even number of vertices of odd-degree. A cycle touches all vertices only once, except for the vertex it starts and ends on. A Hamiltonian cycle touches all vertices on a graph.
Let $$G$$ be a graph on $$n \ge 3$$ vertices, then $$G$$ has a Hamiltonian cycle if all vertices in $$G$$ have degree equal or greater than $$n/2$$. A complete graph $$K_n$$ has $$\binom{n}{k}\frac{(k-1)!}{2}$$ cycles of $$k$$-vertices.
Total Cycles:
\[ \sum_{k=3}^n\binom{n}{k}\frac{(k-1)!}{2} \]
Hamiltonian cycles:
\[ \frac{(n-1)!}{2} \]

Two graphs are the same if for any pair of vertices, the number of edges connecting them is the same in both graphs. If this holds when they are unlabeled, they are isomorphic.
A Tree is a minimally connected graph: Removing any edge yields a disconnected graph. Trees have no cycles, so any connected graph with no cycles is a tree.
All trees on $$n$$ vertices have $$n-1$$ edges, so any connected graph with $$n-1$$ edges is a tree.
Let $$T$$ be a tree on $$n \ge 2$$ vertices, then T has at least two vertices of degree 1.
Let $$F$$ be a forest on $$n$$ vertices with $$k$$ trees. Then F has $$n-k$$ edges.
Cayley's formula: The number of all trees with vertex set $$[n]$$ is $$A_n = n^{n-2}$$
A connected graph $$G$$ can be drawn on a plane so that no two edges intersect, then G is a planar graph.
A connected planar graph or convex polyhedron satisfies: Vertices + Faces = Edges + 2
$$K_{3,3}$$ and $$K_5$$ are not planar, nor is any graph with a subgraph that is edge-equivalent to them.
A convex Polyhedron with V vertices, E edges, and F faces satisfies: $$3F \le 3E$$, $$3V \le 3E$$, $$E \le 3V-6$$, $$E \le 3F-6$$, one face has at most 5 edges, and one vertex has at most degree 5.
$$K_{3,3}$$ has 6 vertices and 9 edges
A graph on $$n$$-vertices has $$\binom{n}{2}$$ possible edges.
If a graph is planar, then $$E \le 3V - 6$$. However, some non-planar graphs, like $$K_{3,3}$$, satisfy this too.
Prüfer code: Remove the smallest vertex from the graph, write down only its neighbor's value, repeat.

Math 462 - Combinatorial Theory II
All labeled graphs on $$n$$ vertices:
\[ 2^{\binom{n}{2}} \]

There are $$(n-1)!$$ ways to arrange $$n$$ elements in a cycle.
Given $$h_n=3 h_{n-1} - 2 h_{n-2}$$, change to $$h_{n+2}=3 h_{n+1} - 2 h_n$$, then $$h_{n+2}$$ is $$n=2$$ so multiply by $$x^{n+2}$$
\[ \sum h_{n+2}x^{n+2} = 3 \sum h_{n+1}x^{n+2} - 2 \sum h_n x^{n+2} \]
Then normalize to
\[ \sum_{n=2}^{\infty}h_n x^n \]
by subtracting $$h_0$$ and $$h_1$$
\[ \sum h_n x^n - x h_1 - h_0 = 3 x \sum h_{n+1}x^{n+1} - 2 x^2 \sum h_n x^n \]

\[ G(x) - x h_1 - h_0 = 3 x (G(x)-h_0) - 2 x^2 G(x) \]
Solve for:
\[ G(x) = \frac{1-x}{2x^2-3x+1} = \frac{1}{1-2x} = \sum (2x)^n \]

\[ G(x) = \sum(2x)^n = \sum 2^n x^n = \sum h_n x^n \rightarrow h_n=2^n \]

\[ \sum_{n=0}^{\infty} \frac{x^n}{n!} = e^x \]
\[ \sum_{n=0}^{\infty} (cx)^n = \frac{1}{1-cx} \]

Also,
\[ 2e_1 + 5e_2 = n \rightarrow \sum h_n x^n = \sum x^{2e_1+5e_2} = \sum x^{2e_1} x^{5e_2} = \left(\sum^{\infty} x^{2e_1}\right)\left(\sum^{\infty} x^{5e_2}\right)=\frac{1}{(1-x^2)(1-x^5)}\]


$$S(n,k)$$: A Stirling number of the second kind is the number of nonempty partitions of $$[n]$$ into k blocks where the order of the blocks doesn't matter. $$S(n,k)=S(n-1,k-1)+k S(n-1,k)$$, $$S(n,n-2) = \binom{n}{3} + \frac{1}{2}\binom{k}{2}\binom{n+2}{2}$$
Bell Numbers:
\[ B(n) = \sum_{i=0}^n S(n,i) \]
, or the number of all partitions of $$[n]$$ into nonempty parts (order doesn't matter).
Catalan Number $$C_n$$:
\[ \frac{1}{n+1}\binom{2n}{n} \]
derived from
\[ \sum_{n \ge 1} c_{n-1} x^n = x C(x) \rightarrow C(x) - 1 = x C(x)\cdot C(x) \rightarrow C(x) = \frac{1 - \sqrt{1-4x}}{2x} \]

Products: Let $$A(n) = \sum a_n x^n$$ and $$B(n) = \sum b_n x^n$$. Then $$A(x)B(x)=C(x)=\sum c_n x^n$$ where
\[ c_n = \sum_{i=0}^n a_i b_{n-i} \]


Cycles: The number of $$n$$-permuatations with $$a_i$$ cycles of length $$i \in [n]$$ is \frac{n!}{a_1!a_2!...a_n!1^{a_1}2^{a_2}...n^{a_n}}
The number of n-permutations with only one cycle is $$(n-1)!$$
$$c(n,k)$$: The number of $$n$$-permutations with $$k$$-cycles is called a signless stirling number of the first kind.
$$c(n,k) = c(n-1,k-1) + (n-1) c(n-1,k)$$
\[ c(n,n-2)= 2\binom{n}{3} + \frac{1}{2}\binom{n}{2}\binom{n-2}{2} \]

$$s(n,k) = (-1)^{n-k} c(n,k)$$ and is called a signed stirling number of the first kind.

Let $$i \in [n]$$, then fro all $$k \in [n]$$, there are $$(n-1)!$$ permutations that contain $$i$$ in a $$k$$-cycle.

\[ T(n,k)=\frac{k-1}{2k}n^2 - \frac{r(k-r)}{2k} \]
Let Graph $$G$$ have $$n$$ vertices and more than $$T(n,k)$$ edges. Then $$G$$ contains a $$K_{k+1}$$ subgraph, and is therefore not $$k$$-colorable.

$$N(T)$$ = all neighbors of the set of vertices $$T$$
$$a_{s,d} = \{ s,s+d,s+2d,...,s+(n-1)d \}$$
$$\chi(H)$$: Chromatic number of Graph $$H$$, or the smallest integer $$k$$ for which $$H$$ is $$k$$-colorable.
A 2-colorable graph is bipartite and can divide its vertices into two disjoint sets.
A graph is bipartite if and only if it does not contain a cycle of odd length.
A bipartite graph has at most $$\frac{n^2}{4}$$ edges if $$n$$ is even, and at most $$\frac{n^2 - 1}{4}$$ edges if $$n$$ is odd.
If graph $$G$$ is not an odd cycle nor complete, then $$\chi(G) \le$$ the largest vertex degree $$\ge 3$$.
A bipartite graph on $$n$$ vertices with a max degree of $$k$$ has at most $$k\cdot (n-k)$$ edges.
A tree is always bipartite (2-colorable).

Philip Hall's Theorem: Let a bipartite graph $$G=(X,Y)$$. Then $$X$$ has a perfect matching to $$Y$$ if and only if for all $$T \subset X, |T| \le |N(T)|$$

$$R(k,l):$$ The Ramsey Number $$R(k,l)$$ is the smallest integer such that any 2-coloring of a complete graph on $$R(k,l)$$ vertices will contain a red $$k$$-clique or blue $$l$$-clique. A $$k$$-clique is a complete subgraph on $$k$$ vertices.
\[ R(k,l) \le R(k,l-1) + R(k-1,l) \]
\[ R(k,k) \le 4^{k-1} \]
\[ R(k,l) \le \binom{k+l-2}{l-1} \]


Let $$P$$ be a partially ordered set (a "poset"), then:
1) $$\le$$ is reflexive, so $$x \le x$$ for all $$x \in P$$
2) $$\le$$ is transitive, so that if $$x \le y$$ and $$y \le z$$ then $$x \le z$$
3) $$\le$$ is anti-symmetric, such that if $$x\le y$$ and $$y \le x$$, then $$x=y$$

Let $$P$$ be the set of all subsets of $$[n]$$, and let $$A \le B$$ if $$A \subset B$$. Then this forms a partially ordered set $$B_n$$, or a Boolean Algebra of degree $$n$$.

\[ E(X)=\sum_{i \in S} i\cdot P(X=i) \]

A chain is a set with no two incomparable elements. An antichain has no comparable elements.
Real numbers are a chain. $$\{ (2,3), (1,3), (3,4), (2,4) \}$$ is an antichain in $$B_4$$, since no set contains another.
Dilworth: In a finite partially ordered set $$P$$, the size of any maximum antichain is equal to the number of chains in any chain cover.

Weak composition of n into 4 parts: $$a_1 + a_2 + a_3 + a_4 = n$$
Applying these rules to the above equation: $$a_1 \le 2, a_2\text{ mod }2 \equiv 0, a_3\text{ mod }2 \equiv 1, a_3 \le 7, a_4 \ge 1$$
Yields the following:
\[ a_1 + 2a_2 + (2a_3 + 1) + a_4 = n \]
\[(\sum_0^2 x^{a_1})(\sum_0^{\infty} x^{2a_2})(\sum_0^3 x^{2a_3 + 1})(\sum_1^{\infty} x^{a_4})=\frac{1+x+x^2}{1-x^2}(x+x^3+x^5+x^7)\left(\frac{1}{1-x} - 1\right)\]


Math 394 - Probability I
both E and F:
\[ P(EF) = P(E\cap F) \]
If E and F are independent, then
\[ P(E\cap F) = P(E)P(F) \]


$$P(F) = P(E) + P(E^c F)$$ $$P(E\cup F) = P(E) + P(F) - P(EF)$$
$$P(E\cup F \cup G) = P(E) + P(F) + P(G) - P(EF) - P(EG) - P(FG) + P(EFG)$$

E occurs given F:
\[P(E|F)=\frac{P(EF)}{P(F)} \]
$$P(EF)=P(FE)=P(E)P(F|E)$$
Bayes formula:
\[ P(E)=P(EF)+P(EF^c) \]
\[P(E)=P(E|F)P(F) + P(E|F^c)P(F^c) \]
\[P(E)=P(E|F)P(F) + P(E|F^c)[1 - P(F)] \]

\[ P(B|A)=P(A|B)\frac{P(B)}{P(A)} \]

The odds of A:
\[ \frac{P(A)}{P(A^c)} = \frac{P(A)}{1-P(A)} \]
\[P[\text{Exactly } k \text{ successes}]=\binom{n}{k}p^k(1-p)^{n-k} \]

\[ P(n \text{ successes followed by } m \text{ failures}) = \frac{p^{n-1}(1-q^m)}{p^{n-1}+q^{m-1}-p^{n-1}q^{m-1}} \]
where $$p$$ is the probability of success, and $$q=1-p$$ for failure.

\[ \sum_{i=1}^{\infty}p(x_i)=1 \]
where $$x_i$$ is the $$i^{\text{th}}$$ value that $$X$$ can take on.
\[ E[X] = \sum_{x:p(x) > 0}x p(x) \text{ or }\sum_{i=1}^{\infty} x_i p(x_i) \]
\[ E[g(x)]=\sum_i g(x_i)p(x_i) \]
\[ E[X^2] = \sum_i x_i^2 p(x_i) \]

\[ Var(X) = E[X^2] - (E[X])^2 \]
\[ Var(aX+b) = a^2 Var(X) \]
for constant $$a,b$$
\[ SD(X) = \sqrt{Var(X)} \]


Binomial random variable $$(n,p)$$:
\[ p(i)=\binom{n}{i}p^i(1-p)^{n-i}\; i=0,1,...,n\]
where $$p$$ is the probability of success and $$n$$ is the number of trials.
Poisson:
\[ E[X] = np \]
\[ E[X^2] = \lambda(\lambda + 1) \]
\[ Var(X)=\lambda \]
\[ P[N(t)=k)] = e^{-\lambda t}\frac{(\lambda t)^k}{k!} \: k=0,1,2,... \]
where $$N(t)=[s,s+t]$$
\[ E[X] = \int_{-\infty}^{\infty} x f(x) \,dx \]
\[ P\{X \le a \} = F(a) = \int_{-\infty}^a f(x) \,dx \]
\[ \frac{d}{da} F(g(a))=g'(a)f(g(a))\]
\[ E[g(X)]=\int_{-\infty}^{\infty} g(x) f(x) \,dx \]
\[ P\{ a \le X \le b \} = \int_a^b f(x) \,dx \]

Uniform:
\[ f(x) = \frac{1}{b-a} \text{ for } a\le x \le b \]
\[ E[X] = \frac{a+b}{2} \]
\[ Var(X) = \frac{(b-a)^2}{12}\]

Normal:
\[ f(x) = \frac{1}{\sqrt{2\pi} \sigma} e^{-\frac{(x-\mu)^2}{2\sigma^2}} \text{ for } -\infty \le x \le \infty \]
\[ E[X] = \mu \]
\[ Var(X) = \sigma^2 \]
\[ Z = \frac{X-\mu}{\sigma} \]

\[ P\left[a \le X \le b\right] = P\left[ \frac{a - \mu}{\sigma} < \frac{X - \mu}{\sigma} < \frac{b - \mu}{\sigma}\right] = \phi\left(\frac{b-\mu}{\sigma}\right) - \phi\left(\frac{a-\mu}{\sigma}\right) \]



\[ \phi(x) = GRAPH \]
\[ P[X \le a]=\phi\left(\frac{a-\mu}{\sigma}\right) \]
\[ P[Z > x] = P[Z \le -x] \]
\[ \phi(-x)=1-\phi(x) \]

\[ Y=f(X) \]
\[ F_Y=P[Y\le a]= P[f(X) \le a] = P[X \le f^{-1}(a)]=F_x(f^{-1}(a)) \]
\[ f_Y=\frac{d}{da}(f^{-1}(a))f_x(f^{-1}(a)) \]
\[ Y = X^2 \]
\[ F_Y = P[Y \le a] = P[X^2 \le a] = P[-\sqrt{a} \le X \le \sqrt{a}] = \int_{-\sqrt{a}}^{\sqrt{a}} f_X(x) dx \]
\[ f_Y = \frac{d}{da}(F_Y) \]


\[N(k) \ge x \rightarrow 1 - N(k) < x \]
\[ P(A \cap N(k) \ge x) = P(A) - P(A \cap N(k) < x) \]




Discrete:
\[ P(X=1) = P(X \le 1) - P(X < 1) \]
Continuous:
\[ P(X \le 1) = P(X < 1) \]


Exponential:
\[ f(x) = \lambda e^{-\lambda x} \text{ for } x \ge 0 \]
\[ E[X] = \frac{1}{\lambda} \]
\[ Var(X) = \frac{1}{\lambda^2} \]


Gamma:
\[ f(x) = \frac{\lambda e^{-\lambda x} (\lambda x)^{\alpha - 1}}{\Gamma(\alpha)} \]
\[ \Gamma(\alpha)=\int_0^{\infty} e^{-x}x^{\alpha-1} \,dx \]
\[ E[X] = \frac{\alpha}{\lambda} \]
\[ Var(X) = \frac{\alpha}{\lambda^2} \]

\[ E[X_iX_j] = P(X_i = k \cap X_j=k) = P(X_i = k)P(X_j = k|X_i=k) \]


Stat 390 - Probability and Statistics for Engineers and Scientists
\[ p(x) = \text{categorical (discrete)} \]
\[ f(x) = \text{continuous} \]
$$\mu_x=E[x]$$$$\sigma_x^2 = V[x]$$
Binomial$$n\pi$$$$n\pi (1-\pi)$$
Normal$$\mu$$$$\sigma^2$$
Poisson$$\lambda$$$$\lambda$$
Exponential$$\frac{1}{\lambda}$$$$\frac{1}{\lambda^2}$$
Uniform$$\frac{b+a}{2}$$$$\frac{(b-a)^2}{12}$$
Binomial\[ p(x) = \binom{n}{x} \pi^x (1 - \pi)^{n-x}\]
Poisson\[ p(x) = \frac{e^{-\lambda} \lambda^x}{x!} \]
Normal\[ f(x) = \frac{1}{\sqrt{2 \pi \sigma^2}} e^{-\frac{1}{2} \left(\frac{x - \mu}{\sigma} \right)}\]
Exponential\[ f(x) = \lambda e^{-\lambda x} \]
Uniform\[ f(x) = \frac{1}{b-a}\]
$$\pi = p =$$ proportion
$$n\pi = C = \lambda =$$ mean
$$\mu = n \pi$$
$$\sigma^2 = n \pi (1 - \pi)$$
Sample mean: $$\bar{x} =$$\[ \frac{1}{n} \sum_{i=1}^n x_i \]Sample median:\[\tilde{x} = \text{if } n \text{ is odd,} \left(\frac{n+1}{2}\right)^{\text{th}} \text{ value} \] \[ \text{if } n \text{ is even, average} \frac{n}{2} \text{ and } \frac{n}{2}+1\]
Sample variance:\[s^2 = \frac{1}{n-1}\sum (x_i - \bar{x})^2 = \frac{S_{xx}}{n-1} = \sum x_i^2 - \frac{1}{n} \left( \sum x_i \right)^2\]Standard deviation: $$s = \sqrt{s^2}$$

low/high quartile: median of lower/upper half of data. If $$n$$ is odd, include median in both.
low = 1st quartilehigh = 3rd quartilemedian = 2nd quartile

IQR: high - low quartiles
range: max - min
Total of something: $$\bar{x} n$$
An outlier is any data point outside the range defined by IQR $$\cdot 1.5$$
An extreme is any data point outside the range defined by IQR $$\cdot 3$$

\[ \mu_{\bar{x}} = \mu = \bar{x} \]
\[ \sigma_{\bar{x}} = \frac{\sigma}{\sqrt{n}} \]
\[ \mu_p = p = \pi \]
\[ \sigma_p = \sqrt{\frac{p(1-p)}{n}} \]

$$p(x)$$ distribution
[discrete]
mean: $$\mu_x = \sum x \cdot p(x) = E[x]$$
variance: $$\sigma_x^2 = \sum(x-\mu_x)^2 p(x) = V[x]$$
$$f(x)$$ distribution
[continuous]
mean:
\[ \mu_x = \int_{-\infty}^{\infty} x \cdot f(x) \]

median:
\[ \tilde{\mu} \rightarrow \int_{-\infty}^{\tilde{\mu}} f(x) = \int_0^{\tilde{\mu}} f(x) = 0.5 \]

variance:
\[ \sigma^2 = \int_{-\infty}^{\infty} (x =\mu_x)\cdot f(x) \]
Normal
\[ k = \frac{\mu + k \sigma - \mu}{\sigma} \]
standardize:
\[ \frac{x - \mu}{\sigma} \]
\[ -k = \frac{\mu - k \sigma - \mu}{\sigma} \]
upper quartile:
\[ \mu + 0.675\sigma \]
lower quartile:
\[ \mu - 0.675\sigma \]
Exponential
\[ -ln(c) \cdot \frac{1}{\lambda} \text{ where c is the quartile }(0.25,0.5,0.75) \]
\[ S_{xx} = \sum x_i^2 - \frac{1}{n}\left(\sum x_i\right)^2 = \sum(x_i - \bar{x})^2 \]
\[ S_{yy} = \sum y_i^2 - \frac{1}{n}\left(\sum y_i\right)^2 = \sum(y_i - \bar{y})^2 \]
\[ S_{xy} = \sum{x_i y_i} - \frac{1}{n}\left(\sum x_i\right)\left(\sum y_i\right) \] \[ \text{SSResid} = \text{SSE (error sum of squares)} = \sum(y_i - \hat{y}_i)^2 = S_{yy} - b S_{xy} \]
\[ \text{SSTo} = \text{SST} = S_{yy} = \text{Total sum of squares} = \text{SSRegr} + \text{SSE} = \text{SSTr} + \text{SSE} = \sum_i^k \sum_j^n (x_{ij} - \bar{\bar{x}})^2 \]
\[ \text{SSRegr} = \text{regression sum of squares} \]
\[ r^2 = 1 - \frac{\text{SSE}}{\text{SST}} = \frac{\text{SSRegr}}{\text{SST}} = \text{coefficient of determination} \]

\[ r = \frac{S_{xy}}{\sqrt{S_{xx}}\sqrt{S_{yy}}} \]
\[ \hat{\beta} = \frac{S_{xy}}{S_{xx}} \]
\[ \hat{\alpha} = \bar{y} - \beta\bar{x} \]
prediction:
\[ \hat{\alpha} = \bar{y} - \beta\bar{x} \]
Percentile ($$\eta_p$$):
\[ \int_{-\infty}^{\eta_p} f(x) = p \]

MSE (Mean Square Error) =
\[ \frac{1}{n} SSE = \frac{1}{n}\sum (y_i-\hat{y}_i)^2 = \frac{1}{n} \sum (y_i - \alpha - \beta x_i)^2 \]

MSTr (Mean Square for treatments)

ANOVA
\[ SST = SS_{\text{explained}} + SSE \]
\[ R^2 = 1 - \frac{SSE}{SST} \]
\[ \sum(y_i - \bar{y})^2 = \sum(\hat{y}_i - \bar{y})^2 + \sum(y_i - \hat{y}_i)^2 \]
\[ s_e^2 = \frac{SSE}{n-2} \text{ or } \frac{SSE}{n-(k+1)} \]
\[ R_{adj}^2 = 1-\frac{SSE(n-1)}{SST(n-(k+1))}\]
\[ H_0: \mu_1 = \mu_2 = .. = \mu_k \]
\[ \bar{\bar{x}} = \left(\frac{n_1}{n}\right)\bar{x}_1 + \left(\frac{n_2}{n}\right)\bar{x}_2 + ... + \left(\frac{n_k}{n}\right)\bar{x}_k \]
\[ SSTr = n_1(\bar{x}_1 - \bar{\bar{x}})^2 + n_2(\bar{x}_2 - \bar{\bar{x}})^2 + ... + n_k(\bar{x}_k - \bar{\bar{x}})^2 \]

SourcesdfSSMSF
Between Samples$$k-1$$SSTrMSTr$$\frac{\text{MSTr}}{\text{MSE}}$$
Within Samples$$n-k$$SSEMSE
Total$$n-1$$SST

One-sample t interval:
\[ \bar{x} \pm t^* \frac{s}{\sqrt{n}} \]
(CI)
Prediction interval:
\[ \bar{x} \pm t^* s\sqrt{1+\frac{1}{n}} \]
(PI)
Tolerance interval:
\[ \bar{x} \pm k^* s \]

Difference t interval:
\[ \bar{x}_1 - \bar{x}_2 \pm t^*\sqrt{\frac{s_1^2}{n_1} + \frac{s_2^2}{n_2}} \]

Adjusted
\[ R^2 = 1 - \left(\frac{n-1}{n-(k+1)}\right) \frac{SSE}{SST} \]

Type I error: Reject $$H_0$$ when true; If the F-test p-value is small, it's useful.
Type II error: Don't reject $$H_0$$ when false.
B(Type II) =
\[ z^* \sqrt{\frac{\sigma_1^2}{n_1} + \frac{\sigma_2^2}{n_2}} \]


Simple linear regression: $$y = \alpha + \beta x$$
General multiple regression: $$y = \alpha + \beta_1 x_1 + ... + \beta_k x_k$$
Prediction error: $$\hat{y} - y^* = \sqrt{s_{\hat{y}}^2 + s_e^2} \cdot t$$
\[ t = \frac{\hat{y}-y^*}{\sqrt{s_{\hat{y}}^2 + s_e^2}} \]

\[ P(\hat{y} - y^* > 11) = P\left(\sqrt{s_{\hat{y}}^2 + s_e^2} \cdot t > 11\right) = P\left(t > \frac{11}{\sqrt{s_{\hat{y}}^2 + s_e^2}}\right) \]

\[ \mu_{\hat{x}_1 - \hat{x}_2} = \mu_{\hat{x}_1} - \mu_{\hat{x}_2} = \mu_1 - \mu_2 \]
\[ \sigma_{\hat{x}_1 - \hat{x}_2} = \sqrt{\frac{\sigma_1^2}{n_1} + \frac{\sigma_2^2}{n_2}} \]
\[ \hat{x}_1 - \hat{x}_2 \pm z^* \sqrt{\frac{s_1^2}{n_1} + \frac{s_2^2}{n_2}} \]


To test if $$\mu_1 = \mu_2$$, use a two-sample t test with $$\delta = 0$$
If you're looking for the true average, it's a CI, not the standard deviation about the regression.
A large n value may indicate a z--test, but you must think about whether or not its paired or not paired.
A hypothesis is only valid if it tests a population parameter. Do not extrapolate outside of a regression analysis unless you use a future predictor.

F-Test
\[ F = \frac{MSRegr}{MSE} \]
\[ MSRegr = \frac{SSRegr}{k} \]
\[ MSResid = \frac{SSE}{n - (k+1)} \]
\[ H_0: \beta_1=\beta_2=...=\beta_k=0 \]


Chi-Squared ($$\chi^2$$)
\[ H_0: \pi_1 = \frac{\hat{n}_1}{n_1},\pi_2 = \frac{\hat{n}_2}{n_2}, ..., \pi_k = \frac{\hat{n}_k}{n_k} \]
\[ \chi^2 = \sum_{i=1}^k \frac{(n_i - \hat{n}_i)^2}{\hat{n}_i} = \sum \left(\frac{\text{observed - expected}}{\text{expected}}\right) \]


Linear Association Test
\[ H_0: p=0 \]
\[ t = \frac{r\sqrt{n-2}}{\sqrt{1-r^2}} \]
\[ \sigma_{\hat{y}} = \sigma \sqrt{\frac{1}{n} + \frac{(x^* - \bar{x})^2}{S_{xx}} } \]
\[ \mu_{\hat{y}} = \hat{y} = \alpha + \beta x^* \]
\[ \hat{y} \pm t^* s_{\hat{y}} df = n-2 \text{ for a mean y value (population)} \]
\[ \hat{y} \pm t^* \sqrt{s_e^2 + s_{\hat{y}}^2} df=n-2 \text{ for single future y-values (PI)} \]


Paired T-test
\[ \bar{d} = \bar{(x-y)} \]
\[ t = \frac{\bar{d} - \delta}{\frac{s_d}{\sqrt{n}}} \]
\[ \sigma_d = \sigma \text{ of x-y pairs } = s_d \]


Large Sample:
\[ z = \frac{\bar{x} - 0.5}{\frac{s}{\sqrt{n}}} \]
\[ \text{P-value } \le \alpha \]

Small Sample:
\[ z = \frac{\bar{x} - \mu}{\frac{s}{\sqrt{n}}} \]
\[ df = n-1 \]


Difference:
\[ H-0: \mu_1 - \mu_2 = \delta \]
\[ t = \frac{\bar{x}_1 - \bar{x}_2 - \delta}{\sqrt{\frac{s_1^2}{n_1} + \frac{s_2^2}{n_2}}} \]
\[ df = \frac{\left(\frac{s_1^2}{n_1} + \frac{s_2^2}{n_2} \right)}{\frac{1}{n_1-1} \left(\frac{s_1^2}{n_1}\right)^2 + \frac{1}{n_2-1} \left(\frac{s_2^2}{n_2}\right)^2 } \]
*"We must be the change we want to see in the world." - Mahatma Gandhi*
Given the enormous influence of The Matrix on a lot of what I make, many people assume that it is my favorite movie. My favorite movie of all time is actually [Contact](https://en.wikipedia.org/wiki/Contact_(film)).

Many people assume the message behind Contact is that Religion and Science aren’t mutually exclusive, but this is only part of the equation. Contact is really about faith. It’s about never losing faith in your own passion, regardless of what it is. It can be science, religion, art, music, it doesn’t matter. All that matters is that you find your passion, and you have faith in it, and no matter what happens, no matter what stands in your way, you fight for it.

Naturally, in real life, we don’t have a Dues Ex Hadden Industries to magic away all our problems, but the movie does an excellent job of making sure the drama that plays out on screen does not undermine it’s purpose. Even with virtually unlimited funding, Ellie finds out she’s being forcefully kicked out of the Very Large Array. No matter what anyone says to her, she refuses to let it go. At that point in the movie, it is abundantly clear that absolutely nothing will stop this woman from pursuing her passion, no matter how insane or misunderstood it is, no matter what obstacles are put in her path, no matter what friends she may lose along the way. At this darkest hour, after everything seems to be falling apart, she goes to a cliffside to think.

And then she comes back.

She comes back, and she starts listening again, because she isn’t going to give up, and that is when she hears the signal. That is when our hollywood movie is yanked out of reality and brings us on a fantastic journey through the stars. It happens after Ellie refuses to give up, even after the universe itself seems to be conspiring to ruin her.

Then, the project is stolen from her repeatedly, and she has to fight to keep it. Then, she is denied her desire to be the one to ride through the machine. Then the machine is completely destroyed and everything she fought for is taken away from her.

Then, our little Dues Ex Hadden comes back. Hadden gave Ellie her funding because of her emotional outburst at the investor meeting. Hadden saw the passion she had, the unstoppable fire and unshakable faith she had in her science project, and that is when he decided to fund her. Once again, Hadden moves us into the realm of fiction, and gives Ellie a second chance.

Contact is brilliant because it begins firmly anchored in reality, and only later, with a few nudges in the right direction, throws us into a world of make-believe. Carl Sagan is trying to make us ask, what if? What if we could fly? What if we could go to the moon? What if we colonized Mars? What if aliens contacted us? Contact shows us how beautiful life can be. It reminds us of all the amazing things that human beings are capable of when we ask that simple question, What If?

To answer it, we just need a little faith.

I am, by no means, a very good web developer. I am, however, a highly experienced C++ developer. The end result is that people usually ask me why I like C++ so much when everyone else hates it, and everyone is supposedly in agreement that C++ is the worst language ever made and unless you are writing drivers you should never, ever use it. I mean, you can write games in Python now, right?

While these kinds of ignorant opinions are frustrating for me and my fellow C++ developers who actually need efficient cross-platform programs, that’s not what I’m here to debate. In fact, if you think C++ is a complete piece of shit, I won’t argue with you about that at all. For all I know, you may be right!

Unfortunately for you, web development is just as bad as C++.

Of course, I just said that I’m not very good at web development, so doesn’t this disqualify me from having an opinion about it? On the contrary, the fact that I’m not very good at web development is extremely important. The reason is that one of the major complaints about C++ is that good C++ code is hard to write if you are an inexperienced developer. I can certainly attest to that fact, it’s taken me years to develop my C++ skills to this point. The fact that Python code is so easy and natural to write is one of its major selling points.

The thing is, good HTML/CSS code is also hard to write if you are an inexperienced developer. I can attest to this too, because I’m an inexperienced developer, and its really goddamn hard to write good HTML/CSS code. Let me clarify what I mean by “good” here: by “good” I mean code that works on all platforms, doesn’t blow up, and doesn’t contain strange edge cases that will cause it to fail for no reason. Many developers preach the joys of functional programming, which eliminates most edge cases by prohibiting functions that have side-effects.

Everyone knows about the subtle, nasty bugs that can crop up in C++, often as a result of doing something that was intuitive, yet wrong. This is rehashed in the “C++ is bad” arguments over and over and over without end, especially with the functional programming zealots. The problem is that HTML/CSS has all sorts of really stupid crap that can happen when you do something subtly wrong with the HTML that is not immediately obvious to a new developer.

It took me a while to learn that you shouldn’t be putting block level elements inside inline elements in your HTML - it will almost always work, until it doesn’t, and it won’t be obvious what exactly is going wrong. Many people new to HTML aren’t even aware of HTML resets, so they’ll have to try and remember which elements are block-level by default and which aren’t. Then the new standard introduced a bunch of psuedo-block level elements that try to fix some of these problems, except they aren’t supported by everything because MICROSOFT, so now you’re stuck with a bunch of workarounds for IE that take forever to develop.

Just recently I discovered an amazingly weird bug with my webpage, wherein upon first loading it, all my buttons would be stacked vertically. It appeared that Chrome was ignoring float:left on those elements… until the page was refreshed or any other part of the website was visited, at which point everything started working again! Firefox, of course, didn’t have any issues with it. The problem was that I had a <p> element defined as a giant button, then put <a href=""></a> around it because I wanted the entire button to be a link. This, of course, violates the inline/block element mandate I outlined above, despite it being a very natural thing to do - you want the entire button to link somewhere? Put a link around it. It’ll almost always work, until it doesn’t.

Trying to write perfectly standards conformant HTML is exceedingly difficult because half the time what you want to do isn’t in the standard or is some hack that works almost all the time but not quite. The rest of the time, the “standard” way of doing things is completely and utterly bizarre, like using margin:auto 0; to center elements. But wait, that only works on horizontal elements! If you want to vertically center an arbitrary element, you have to use a lot of weird crap just to get it to work on everything. Or you could just use a table. But tables are bad, so you should never use them, even though they actually solve a whole lot of problems new developers have because their non-table solutions are completely unintuitive, because we’re all trying to use a document layout engine to make GUIs, for crying out loud.

Many web developers argue that these problems are going away now that we have a better standard. Sadly, they are just getting started - WebGL will become exceedingly important in the next 5 years, and its standardization is an absolute mess almost to the point of it being unusable. Then there’s the sordid situation with HTML5 audio and video, which is only just starting to get tolerable. These problems are not going away - they are simply being replaced by different problems. Of course, some stuff actually is becoming easier in HTML - just like a lot of stuff is becoming easier in C++11. So either you ignore both the new C++ features and the new HTML features, or you admit that C++ has become less horrible recently.

Of course, C++ is still way too easy to write unmaintainable code in, and HTML/CSS code is clearly self-documenting! Except it obviously isn’t, given the endless horror stories of terrifying CSS dependencies with random !important keywords flung around in a giant mess that’s just as impossible to understand as templatized C++ hell.

But wait, if you just write proper HTML, it won’t have that problem! Well, duh, if you write proper C++, you don’t have that problem either. I’m sorry, if you are going to hate something, you can’t have your cake and eat it too. If C++ supporting features that can be abused to make code impossible to read, like operator overloading, makes it a bad language, then CSS is a bad language, because there is an endless list of obscure, bizarre syntax you can use in your CSS style sheets (like !important) that will make your HTML almost impossible to read. But wait, C++ is also incredibly hard to parse! HTML being easy to parse must be why Opera recently gave up trying to maintain its own HTML layout engine… Oh wait. Well at least javascript is a consistent, easy to understand language that doesn’t have any weird quirks… JUST KIDDING!

So it seems modern technology has succeeded in replacing a very fast, difficult to use, inconsistent language with 3 different, very slow, difficult to use, inconsistent languages.

Now, if you want to believe that HTML/CSS is still good when used correctly, then all I ask is that you grudgingly admit that, maybe, just maybe, C++ is also good when used correctly. If you still think C++ is an abomination from the depths of cthulu, I hope you can admit that web development therefore must also be an abomination.

Or we can just keep arguing with each other, because that’s always productive.

So I have this dll that’s doing a bunch of horrible WinAPI calls for me. It’s designed to abstract away all the pain and unholy functions feeding on innocent blood. Little did I know that trying to cage WinAPI into a more manageable corner would be my undoing.

The window is created and assigned a WndProc callback function inside this DLL, as per the various absurd requirements involving how you create windows in Windows. Everything works just fine and dandy until the application window suddenly closes, an error “ding” is heard, and the program silently crashes without any sort of error message whatsoever.

What just happened?

Well, I’m afraid you just triggered an assertion. But instead of doing what an assertion is supposed to do, which is immediately crash the program so you know what the fuck just happened, it instead somehow manages to create an infinite callback loop caused by the operating system actually trying to assign the assertion dialog to the window. You know, the same window that was part of an application that’s supposed to be in the middle of CRASHING?! This causes another message to be sent, thus causing another assertion to be violated, et cetera until the stack overflows, except it doesn’t actually tell you the stack overflows, it just crashes with absolutely no explanation. Even while in a debugger, which is truly amazing.

Specifically, the assertion triggers a dialog box to be displayed, but this dialog box forcibly sends another WM_CANCELMODE message to the application, apparently completely bypassing the entire point of having a message queue, because the program never gets to go back to it. It’s WndProc is simply called with WM_CANCELMODE because fuck you, and so if your assertion fails when you’re processing WM_CANCELMODE, it will simply do this over and over and over until the entire window tree collapses in on itself from the intense gravitational pull of astronomical amounts of stupidity.

The resulting black hole sucks in all nearby sources of sanity, which include some sort of error message about the stack overflowing, or perhaps the actual fucking assertion error, and then explodes, leaving you without a goddamn clue about what just happened. This is usually followed by copious amounts of screaming, then disbelief, then finally assuming the fetal position and praying for forgiveness for attempting to touch the windows API, as the Microsoft gods laugh and drag another developer’s soul into their black circle of hell.

Somehow, every time I touch the windows API, it always ends with me curled into a ball, moaning “what the fuck” over and over again while crying.

While I have never been suicidal, I’ve had to deal with suicidal friends more than I’d like. The hardest thing in the world is to get suicidal people to understand that, contrary to their entire life’s experience, and contrary to every shred of evidence they have, things will get better. Eventually, they will have an experience they could never have imagined, they just have to hold on long enough. Sometimes it feels like our dreams are on the brink of suicide for similar reasons, and we must also convince ourselves that we just need to hold on to them for a little while longer.

The death of Aaron Swartz affected me deeply even though I honestly didn’t know who he was until he died. Unlike what many people seem to be writing about on Hacker News, however, it was not because he was some kind of brilliant programmer (although he clearly was), it was because he was fighting for many of the same things I am fighting for. We were both disillusioned about the massive corruption that underlies modern society, and we can both be considered idealists. That Aaron’s dreams were so oppressed that he took his own life is deeply disturbing to me.

Whenever you attempt to do something, you will encounter resistance. If you haven’t had someone tell you you’re an idiot for doing something yet, you just haven’t been looking hard enough. It is not possible to post a blog on the internet and not have a comment telling you that everything you wrote is misinformed crap. Every time you start writing a program, you will use the wrong language. You will use the wrong library, make the wrong API choices, set the wrong default values, have terrible coding practices, and be both too high level and too low level at the same time. Every solution you come up with will be fundamentally flawed and used as a reason for why software development has gone downhill. At least one person will tell you to never write another line of code ever again for the benefit of mankind.

When the language fetishists start flinging mud over the fence, it is easy to get discouraged after they rail on about how terrible your language of choice is. Sometimes you’ll wonder if some of your C++ code should really be C code, or if your event subsystem should be in Haskell. You launch products to the sounds of crickets. Repeated failures can be extremely draining to one’s perseverance.

None of this matters. The visions that find us in our daydreams and play with us at night are what make life worth living. The dreams we fight for give us reason to exist, regardless of whether we achieve them or not. Just because things don’t turn out the way we want to doesn’t mean we can’t still have a positive influence on the world.

If I could have told Aaron anything the night before he died, it would have been that no matter how hopeless things get, his dreams will always be worth fighting for. By simply being alive, we continue to uphold our ideals. Never stop trying, and you will continue to fight for what you believe in, even if you don’t succeed the way you wanted to. People will tell you to give up, that its fruitless, meaningless, hopeless, misguided and useless. They are wrong.

For Aaron’s sake, in memory of all his hopes and ideals, fight for your dreams, and never let go.

Technology tends to serve one of two purposes - to make us more efficient at some task, or to entertain us in our resulting free time. However, when we fixate on productivity to the exclusion of everything else, we often forget about the big picture. Perhaps the best example of this are people insisting that real coders need to use Vim to be productive due to it’s unmatched text editing powers.

This is totally absurd. I spend maybe 10% of my time actually writing code, 30% debugging that code, and the remaining 60% trying to solve a problem. Even if I could write all my code instantly, I have only improved my productivity by 10%. I’ve found that changing my code patterns to let me catch bugs faster and earlier has had a much more significant impact on my coding speed, because taking a chunk out of 30% has a much greater effect on my overall productivity.

But what about the 60%? I’m sure I could make some of that go away with more powerful visualization tools and intense mental training, but when I hit a problem that’s simply really hard to solve, nothing short of a cybernetic implant that makes my brain bigger is going to make a dent in how much time I spend thinking about something unless I want to make a stupid mistake and regret it later.

The issue that’s arising from our hyperproductive tools is that our productivity is beginning to outstrip our ability to think. We are so productive we can’t think fast enough to utilize it. Vim may be the most amazing text editor ever, but it doesn’t matter because I spend more time thinking than I do actually editing text. We’re so focused on making everyone super productive we seem to forget that we are beginning to receive diminishing returns from some of our efforts.

One consequence of this is that, obviously, we should be focusing on tools to help us think faster. We need to do profiling of people’s lives to find the chokepoints and focus on those instead of doing the equivalent of micro-optimizations in C code that’s only called every 5 minutes. That, however, does not concern me. What does concern me is the repeated mistakes futurists make when attempting to predict the future of technology.

This Microsoft video is a superb example of good technology predictions implemented in the worst way possible. The entire video treats human beings as machinery that needs to complete various tasks in the quickest way possible, instead of recognizing that human beings are, in fact, people. Many of the human interactions feel fake because all the interactions are treated simply as tasks that must be completed efficiently, regardless of how beneficial the time saved actually is. Productivity is not important, the way it feels is important.

Futuristic architecture often makes this same mistake, creating cold, bland environments that, while they do feel futuristic, are not things anyone would want to live or work in. We need environments that feel warm, inviting, and natural. When building futuristic environments, we must be extremely careful about where the future is peeking in, because there is such a thing as too much future in one room.

We make things look like wood simply because we like how wood looks, not because we need to build anything out of wood anymore. We like trees growing around our houses. We make our lights look like the sun instead of actually being white. We are constantly making arbitrary choices that have nothing to do with productivity and everything to do with making us feel comfortable. Until designers recognize this and stop sucking the life out of everything in an effort to make it more “productive”, they will inevitably be shunned in favor of slightly less efficient, but more inviting designs.

Design is an optimization problem that must maximize both productivity and feel, not one or the other. Some people actually like color in their IDEs and webpages that consist of more than flat text, faint lines and whitespace.

I have a Zune I got as a prize at a Microsoft Hunt The Wumpus competition back when Microsoft was still under the delusion that they could actually compete with the iPod. My Zune has served me faithfully for almost 7 years. I am now on my third pair of earbuds for my Zune, and have noticed a disturbing trend.

The Zune has a volume control that goes from 0 to 20. I have sensitive ears, so with my first pair of earbuds, which came with the Zune and were presumably made by Microsoft, I listened to music at a volume of 3. Sometimes it was bumped up to 4, but never higher unless a particular song was abnormally quiet. I wish I could say this will let me keep my hearing pristine for many years to come, but standing next to the freeway for 4 years has probably screwed me over anyway.

Eventually these gave out and I had to get new ones. I picked the “Gumy” brand because it was almost identical to my previous earbuds and I like that style. I can’t even hear bass properly due to a hearing defect so I really don’t give a shit about “EXTREME BASS LOUDNESS!!!11!1!!one!!”, and I’ve heard bad things about Skullcandy, which was literally the only other brand there. After plugging in my new earbuds, however, I noticed that a volume level of 3 was too loud - I thought my ears might be playing tricks on me, but after several tests, including a blind test, I was absolutely positive 3 was definitely too loud, and I’d have to reduce my volume to 2. Once again, volume level 3 would be used for quieter songs.

After another 2 or 3 years, my old Gumy earbuds have finally died, so I just went and bought new ones. Not interested in trying any new brands, I got the exact same brand, type, and color, such that my new earbuds were almost completely indistinguishable from my old ones. Then I plugged them in. Once again, they were significantly louder than my previous ones. Thinking perhaps my ears were not accustomed to the sound or perhaps my old earbuds had decreased in volume, I ran several tests, but I eventually realized that my comfortable level of listening had been reduced to a volume level of 1.

There is nothing below 1. If this trend continues, I will be forced to either find an exotic brand of earbuds I can only buy over the internet from a manufacturing plant on the moon that lets me actually listen to songs at a volume that does not cause hearing damage, or I will be forced to stop listening to music on my Zune. I’m not entirely sure how this trend is even possible, although it may have something to do with a miniature amplifier inside the earbuds, but it seems to be mirroring the infamous Loudness Wars. The issues involved with the Loudness Wars are a topic for another day, but this same phenomenon has occured with my headphones plugged into my computer. A comfortable volume is something like 5 on a scale from 0 to 100. At least in windows I can punch it into behaving reasonably, but it’s still just as ridiculous.

I have always been annoyed at people listening to music at volumes that are obviously going to cause hearing damage for no real apparent reason, and its also why I avoid concerts like the plague, but now it seems that our society’s obsession with loud music is making it almost impossible for me to not listen to loud music and it’s pissing me the fuck off.

For now, my earbuds are working fine, and I can still listen to them comfortably on a volume level of 1 without problems, but if anyone knows a pair of non-stupid earbuds that does not fall victim to this trend, it would be useful information 3 years down the road when this pair gives out.

Also, if you are going to have a volume control, make it actually useful, please. I’m sick and tired of volume controls with a range from “Almost Too Loud” to “What The Fuck?!” At least some of us don’t want to listen to music at offensively loud decibel levels. I can still tweak the volume in FL Studio when I’m mixing my tracks, but studio-quality headphones become a lot less useful when they have an effective integer volume range of 0-8.

Back when I started making music, I quickly realized that trying to make sample-based music without a significant sample library is really hard. While there are thousands of sample libraries for sale, the problem with starting out is that, by definition, you suck, you’re probably in high school, and your allowance is likely going towards other, more important things, and not your silly musical experiments.

Over the years, I’ve been frustrated with how difficult it is to find good free samples. It turns out that there’s some really great royalty-free stuff out there, if you can find it. This post is a categorized list of every single sample pack and soundfont I have that is royalty-free, and of reasonable quality in an effort to give beginner musicians a much better foundation to build their music off of. Some of these are soundfonts compressed with sfArk - just drag the file on to sfArkXTc.exe to generate a self-extracting executable that will create the sf2 file when run. Others are compressed using sfpack.exe. A few use the SFZ format (usually when the soundfont in question would take up too much RAM), which can be read by the free sForzando VSTi.

Instrumental

000_Florestan_Piano

198-StratocasterVS

MIS Stereo Piano [ SoundFont | Directwave ]

MIS Orchestra Samples [Requires Directwave]

SGM-V2.01

Nylon Guitar 1

Sonatina Symphonic Orchestra SF2 (original SFZ)

HQ Orchestra Samples

070 Bassoon Ethan Nando

Roland Sound Canvas

Tubular Bells

Maestro Concert Piano (SFZ)

Percussion

SAMPLES - 5000 DRUMHITS

1400 Samples Drum Kit

mhak kicks

drums_industrial

drums_ken_ardency

RolandOrchestralRythm

JD Rockset 5

Ellade Drums

The Freq’s Glitch Hop Sample Pack

VSTi

While not samples, these are free VSTi plugins, compatible with most modern DAWs.

Bitcrusher

Tube Screamer

Rez v2.0

Reaktor 5 (free version)

Reaktor 5 Factory Selection

Mikro Prism [Requires Reaktor]

dmiHammer

Jug Drum (free version) [Requires Kontact]

Dryer Drum [Requires Kontact]

The SimulAnalog Guitar Suite is very nice, but is for non-commercial use only.

What are these samples capable of? You know you can’t ask me that without getting a bunch of disgusting self-promoting links for a programmer’s pathetic music making attempts, right? Oh well, if you insist:

More songs like these can be found in their respective albums: Solar Noise - EP Aurora Theory

These samples are extremely versatile, so don’t mistake my own laughable attempts at using them for some imaginary limitations. There are thousands of samples in these packs, so get creative!

So on thursday morning my friend mentioned a hackathon at his college, San Jose University. I expressed interest but pointed out that I live 800 miles away. So he bought me a ticket on the last plane flying to San Francisco that night. 10 hours after he had mentioned this hackathon with me, I was riding on a train to San Jose University (after missing one train and getting off on the wrong stop).

The hackathon had prizes - $3100, $1500, and $600 for 1st, 2nd, and 3rd, respectively. The goal was to build, in 24 hours, a AI for a game. The game was a 7x7 board with empty tiles on it. To win a round, you must construct a continuous path from one side to the other. Player 1 must construct a path connecting the left and right sides, while player 2 must construct a path from top to bottom. The squares are grouped into randomized sets, which are then run through over and over, and each time a set is made available, each bot places a bid on the set. The highest bid gets to pick any square from that set and claim it. You had 98 credits to bid with (7_7_2 = 98) and there was no way to get more.

I was able to build an atemporal pathfinding algorithm that constructed a 7-turn path by figuring out in advance which squares would be available which turn. To prevent difficult edge cases I simplified it so it would always try to do it in 7 turns and simply bid 14 credits each time. My friend helped with debugging and brainstorming ideas, as well as setting everything up, and we had to keep correcting each other on how the game actually worked, but the entire time I was also learning how to use a mac, since my only laptop was a piece of shit and he only had macs.

We were also trying to use Codelite in the hopes that it would be better than Xcode, but that ended up being a disaster with constant crashes and failed debuggers. As a result, I learned two things from this hackathon: I fucking hate macs, and Codelite is a horrible, unstable IDE you should never use.

I was only able to stabilize our algorithm with 40 minute left in the competition. I attempted to implement an aggressive analysis algorithm that would detect a potential win condition for the opponent and block it, but it never worked. Had I instead extended the algorithm to simply look for alternative paths longer than 7 turns, we probably would have won, but I didn’t realize that until after the competition. Even though we only had a very basic algorithm, our pathfinding was extremely strong and as a result we got all the way to 4th place. Unfortunately, that wasn’t enough for a cash prize, so we weren’t able to recoup the plane ticket cost.

So then we took a train back up to his house in San Francisco, went out for dinner, and did more music stuff with his crazy studio monitor setup. The next day involved fisherman’s wharf, candy, being lost, and getting to play around on a hardware synth. Then I went to bed and today I got flown back to Seattle.

All because my friend looked at a hackathon advertisement on Thursday morning.

[ 1 · 2 · 3 · 4 · 5 · 6 · 7 ]

If you are familiar with C#, you should be familiar with the difference between C#’s struct and class declarations. Namely, a struct is a value type and a class is a reference type, meaning that if you pass a struct to a function, its default behavior is for the entire struct to be copied into the function’s parameter, so any modifications made to it won’t affect whatever was passed in. On the flip side, a class is a reference value, so a reference is passed into the function, and any changes made to that reference will be reflected in the object that was originally passed into the function.

// Takes an integer, or a basic value type
public static int add(int v)
{
  v+=3;
  return 4+v;
}

public struct Oppa
{
  public string gangnam;
}

// Takes a struct, or a complex value type
public static Oppa style(Oppa g)
{
  g.gangnam="notstyle";
  return g;
}

public class Psy
{
  public int style;
}

// Takes a class, or a reference type
public static void change(Psy psy)
{
  psy.style=5;
}

// Takes an integer, but forces it to be passed by reference instead of by value.
public static int addref(ref int v)
{
  v+=3;
  return 4+v;
}

int a = 0;
int b = add(a);
// a is still 0
// b is now 7

int c = addref(a);
// a is now 3, because it was passed by reference
// c is now 7

Oppa s1;
s1.gangnam="style";
Oppa s2 = style(s1);
//s1.gangnam is still "style"
//s2.gangnam is now "notstyle"

Psy psy = new Psy();
psy.style=0;
change(psy);
// psy.style is now 5, because it was passed by reference
C++ also lets you pass in parameters by reference and by value, however it is more explicit about what is happening, so there is no default behavior to know about. If you simply declare the type itself, for example (myclass C, int B), then it will be passed by value and copied. If, however, you use the reference symbol that we’ve used before in variable declarations, it will be passed by reference. This happens no matter what. If a reference is passed into a function that takes a value, it will still have a copy made.

// Integer passed by value
int add(int v)
{
  v+=3;
  return 4+v;
}

class Psy
{
public:
  int style;
};

// Class passed by value
Psy change(Psy psy)
{
  psy.style=5;
  return psy;
}

// Integer passed by reference
int addref(int& v)
{
  v+=3;
  return 4+v;
}

// Class passed by reference
Psy changeref(Psy& psy)
{
  psy.style=5;
  return psy;
}

int horse = 2;
int korea = add(horse);
// horse is still 2
// korea is now 9

int horse2 = 2;
int korea2 = addref(horse2);
// horse2 is now 5
// korea2 is now 9

Psy psy;
psy.style = 0;
Psy ysp = change(psy);
// psy.style is still 0
// ysp.style is now 5

Psy psy2;
psy2.style = 0;
Psy ysp2 = changeref(psy2);
// psy2.style is now 5
// ysp2.style is also 5
However, in order to copy something, C++ needs to know how to properly copy your class. This gives rise to the copy constructor. By default, the compiler will automatically generate a copy constructor for your class that simply invokes all the default copy constructors of whatever member variables you have, just like C#. If, however, your class is holding on to a pointer, then this is going to cause a giant mess when two classes are pointing to the same thing and one of the deletes what it’s pointing to! By specifying a copy constructor, we can deal with the pointer properly:

class myString
{
public:
  // The copy constructor, which copies the string over instead of copying the pointer
  myString(const myString& copy)
  {
    size_t len = strlen(copy._str)+1; //+1 for null terminator
    _str=new char[len];
    memcpy(_str,copy._str,sizeof(char)*len);
  }
  // Normal constructor
  myString(const char* str)
  {
    size_t len = strlen(str);
    _str=new char[len];
    memcpy(_str,str,sizeof(char)*len);
  }
  // Destructor that deallocates our string
  ~myString()
  {
    delete [] _str;
  }

private:
  char* _str;
};

This copy constructor can be invoked manually, but it will simply be implicitly called whenever its needed. Of course, that isn’t the only time we need to deal with our rogue pointer that screws things up. What happens when we set our class equal to another class? Remember, a reference cannot be changed after it is created. Observe the following behavior:

int a = 3;
int b = 2;
int& ra = a;
int* pa = &a;

b = a; //b is now 3
a = 0; //b is still 3, but a is now 0
b = ra; // b is now 0
a = 5; // b is still 0 but now a is 5
b = *pa; // b is now 5
b = 8; // b is now 8 but a is still 5

ra = b; //a is now 8! This assigns b's values to ra, it does NOT change the reference!
ra = 9; //a is now 9, and b is still 8! ra STILL refers to a, and NOTHING can change that.

pa = &b; // Now pa points to to b
a = *pa; // a is now 8, because pointers CAN be changed.
*pa = 7; // Now b is 7, but a is still 8

int*& rpa = pa; //Now we have a reference to a pointer (C++11)
//rpa = 5; // COMPILER ERROR, rpa is a reference to a POINTER
int** ppa = &pa;
//rpa = ppa; // COMPILER ERROR, rpa is a REFERENCE to a pointer, not a pointer to a pointer!
rpa = &a; //now pa points to a again. This does NOT change the reference!
b = *pa; // Now b is 8, the same as a.
So somehow, we have to overload the assignment operator! This brings us to Operator Overloading. C# operator overloading works by defining global operator overloads, ones that take a left and a right argument, and are static functions. By default, C++ operator overloading only take the right argument. The left side of the equation is implied to be the class itself. Consequently, C++ operators are not static. C++ does have global operators, but they are defined outside the class, and the assignment operator isn’t allowed as a global operator; you have to define it inside the class. All the overload-able operators are shown below with appropriate declarations:

class someClass
{
someClass operator =(anything b); // me=other
someClass operator +(anything b); // me+other
someClass operator -(anything b); // me-other
someClass operator +(); // +me
someClass operator -(); // -me (negation)
someClass operator *(anything b); // me*other
someClass operator /(anything b); // me/other
someClass operator %(anything b); // me%other
someClass& operator ++(); // ++me
someClass& operator ++(int); // me++
someClass& operator --(); // --me
someClass& operator --(int); // me--
// All operators can TECHNICALLY return any value whatsoever, but for many of them only certain values make sense.
bool operator ==(anything b); 
bool operator !=(anything b);
bool operator >(anything b);
bool operator <(anything b);
bool operator >=(anything b);
bool operator <=(anything b);
bool operator !(); // !me
// These operators do not usually return someClass, but rather a type specific to what the class does.
anything operator &&(anything b); 
anything operator ||(anything b);

anything operator ~();
anything operator &(anything b);
anything operator |(anything b);
anything operator ^(anything b);
anything operator <<(anything b);
anything operator >>(anything b);
someClass& operator +=(anything b); // Should always return *this;
someClass& operator -=(anything b);
someClass& operator *=(anything b);
someClass& operator /=(anything b);
someClass& operator %=(anything b);
someClass& operator &=(anything b);
someClass& operator |=(anything b);
someClass& operator ^=(anything b);
someClass& operator <<=(anything b);
someClass& operator >>=(anything b);
anything operator [](anything b); // This will almost always return a reference to some internal array type, like myElement&
anything operator *();
anything operator &();
anything* operator ->(); // This has to return a pointer or some other type that has the -> operator defined.

anything operator ->*(anything a);
anything operator ()(anything a1, U a2, ...);
anything operator ,(anything b);
operator otherThing(); // Allows this class to have an implicit conversion to type otherThing
void* operator new(size_t x); // These are called when you write new someClass()
void* operator new[](size_tx); // new someClass[num]
void operator delete(void*x); // delete pointer_to_someClass
void operator delete[](void*x); // delete [] pointer_to_someClass

};

// These are global operators that behave more like C# operators, but must be defined outside of classes, and a few operators do not have global overloads, which is why they are missing from this list. Again, operators can technically take or return any value, but normally you only override these so you can handle some other type being on the left side.
someClass operator +(anything a, someClass b);
someClass operator -(anything a, someClass b);
someClass operator +(someClass a);
someClass operator -(someClass a);
someClass operator *(anything a, someClass b);
someClass operator /(anything a, someClass b);
someClass operator %(anything a, someClass b);
someClass operator ++(someClass a);
someClass operator ++(someClass a, int); // Note the unnamed dummy-parameter int - this differentiates between prefix and suffix increment operators.
someClass operator --(someClass a);
someClass operator --(someClass a, int); // Note the unnamed dummy-parameter int - this differentiates between prefix and suffix decrement operators.

bool operator ==(anything a, someClass b);
bool operator !=(anything a, someClass b);
bool operator >(anything a, someClass b);
bool operator <(anything a, someClass b);
bool operator >=(anything a, someClass b);
bool operator <=(anything a, someClass b);
bool operator !(someClass a);
bool operator &&(anything a, someClass b);
bool operator ||(anything a, someClass b);

someClass operator ~(someClass a);
someClass operator &(anything a, someClass b);
someClass operator |(anything a, someClass b);
someClass operator ^(anything a, someClass b);
someClass operator <<(anything a, someClass b);
someClass operator >>(anything a, someClass b);
someClass operator +=(anything a, someClass b);
someClass operator -=(anything a, someClass b);
someClass operator *=(anything a, someClass b);
someClass operator /=(anything a, someClass b);
someClass operator %=(anything a, someClass b);
someClass operator &=(anything a, someClass b);
someClass operator |=(anything a, someClass b);
someClass operator ^=(anything a, someClass b);
someClass operator <<=(anything a, someClass b);
someClass operator >>=(anything a, someClass b);
someClass operator *(someClass a);
someClass operator &(someClass a);

someClass operator ->*(anything a, someClass b);
someClass operator ,(anything a, someClass b);
void* operator new(size_t x);
void* operator new[](size_t x);
void operator delete(void* x);
void operator delete[](void*x);
We can see that the assignment operator mimics the arguments of our copy constructor. For the most part, it does the exact same thing; the only difference is that existing values must be destroyed, an operation that should mostly mimic the destructor. We extend our previous class to have an assignment operator accordingly:

class myString
{
public:
  // The copy constructor, which copies the string over instead of copying the pointer
  myString(const myString& copy)
  {
    size_t len = strlen(copy._str)+1; //+1 for null terminator
    _str=new char[len];
    memcpy(_str,copy._str,sizeof(char)*len);
  }
  // Normal constructor
  myString(const char* str)
  {
    size_t len = strlen(str);
    _str=new char[len];
    memcpy(_str,str,sizeof(char)*len);
  }
  // Destructor that deallocates our string
  ~myString()
  {
    delete [] _str;
  }

  // Assignment operator, does the same thing the copy constructor does, but also mimics the destructor by deleting _str. NOTE: It is considered bad practice to call the destructor directly. Use a Clear() method or something equivalent instead.
  myString& operator=(const myString& right)
  {
    delete [] _str;
    size_t len = strlen(right._str)+1; //+1 for null terminator
    _str=new char[len];
    memcpy(_str,right._str,sizeof(char)*len);
  }

private:
  char* _str;
};
These operations take an instance of the class and copy it’s values to our instance. Consequently, these are known as copy semantics. If this was 1998, we’d stop here, because for a long time, C++ only had copy semantics. Either you passed around references to objects, or you copied them. You could also pass around pointers to objects, but remember that pointers are value types just like integers and floats, so you are really just copying them around too. In fact, until recently, you were not allowed to have references to pointers. Pointers were the one data type that had to be passed by value. Provided you are using a C++0x-compliant compiler, this is no longer true, as you may remember from our first examples. The new standard released in 2011 allows references to pointers, and introduces move semantics.

Move semantics are designed to solve the following problem. If we have a series of dynamic string objects being concatenated, with normal copy constructors we run into a serious problem:

std::string result = std::string("Oppa") + std::string(" Gangnam") + std::string(" Style") + std::string(" by") + std::string(" Psy");
// This is evaluated by first creating a new string object with its own memory allocation, then deallocating both " by" and " Psy" after copying their contents into the new one
//std::string result = std::string("Oppa") + std::string(" Gangnam") + std::string(" Style") + std::string(" by Psy");
// Then another new object is made and " by Psy" and " Style" are deallocated
//std::string result = std::string("Oppa") + std::string(" Gangnam") + std::string(" Style by Psy");
// And so on and so forth
//std::string result = std::string("Oppa") + std::string(" Gangnam Style by Psy");
//std::string result = std::string("Oppa Gangnam Style by Psy");
// So just to add 5 strings together, we've had to allocate room for 5 additional strings in the middle of it, 4 of which are then simply deallocated!
This is terribly inefficient; it would be much more efficient if we could utilize the temporary objects that are going to be destroyed anyway instead of reallocating a bunch of memory over and over again only to delete it immediately afterwards. This is where move semantics come in to play. First, we need to define a “temporary” object as one whose scope is entirely contained on the right side of an expression. That is to say, given a single assignment statement a=b, if an object is both created and destroyed inside b, then it is considered temporary. Because of this, these temporary values are also called rvalues, short for “right values”. C++0x introduces the syntax variable&& to designate an rvalue. This is how you declare a move constructor:

class myString
{
public:
  // The copy constructor, which copies the string over instead of copying the pointer
  myString(const myString& copy)
  {
    size_t len = strlen(copy._str)+1; //+1 for null terminator
    _str=new char[len];
    memcpy(_str,copy._str,sizeof(char)*len);
  }
  // Move Constructor
  myString(myString&& mov)
  {
    _str = mov._str;
    mov._str=NULL;
  }
  // Normal constructor
  myString(const char* str)
  {
    size_t len = strlen(str);
    _str=new char[len];
    memcpy(_str,str,sizeof(char)*len);
  }
  // Destructor that deallocates our string
  ~myString()
  {
    if(_str!=NULL) // Make sure we only delete _str if it isn't NULL!
      delete [] _str;
  }

  // Assignment operator, does the same thing the copy constructor does, but also mimics the destructor by deleting _str. NOTE: It is considered bad practice to call the destructor directly. Use a Clear() method or something equivalent instead.
  myString& operator=(const myString& right)
  {
    delete [] _str;
    size_t len = strlen(right._str)+1; //+1 for null terminator
    _str=new char[len];
    memcpy(_str,right._str,sizeof(char)*len);
    return *this;
  }

private:
  char* _str;
};
NOTE: Observe that our destructor functionality was changed! Now that _str can be NULL, we have to check for that before deleting the object.

The idea behind a move constructor is that, instead of copying the values into our object, we move them into our object, setting the source to some NULL value. Notice that this can only work for pointers, or objects containing pointers. Integers, floats, and other similar types can’t really be “moved”, so instead their values are simply copied over. Consequently, move semantics is only beneficial for types like strings that involve dynamic memory allocation. However, because we must set the source pointers to 0, that means we can’t use const myString&&, because then we wouldn’t be able to modify the source pointers! This is why a move constructor is declared without a const modifier, which makes sense, since we intend to modify the object.

But wait, just like a copy constructor has an assignment copy operator, a move constructor has an equivalent assignment move operator. Just like the copy assignment, the move operator behaves exactly like the move constructor, but must destroy the existing object beforehand. The assignment move operator is declared like this:

myString& operator=(myString&& right)
  {
    delete [] _str;
    _str=right._str;
    right._str=0;
    return *this;
  }

Move semantics can be used for some interesting things, like unique pointers, that only have move semantics - by disabling the copy constructor, you can create an object that is impossible to copy, and can therefore only be moved, which guarantees that there will only be one copy of its contents in existence. std::unique_ptr is an implementation of this provided in C++0x. Note that if a data structure requires copy semantics, std::unique_ptr will throw a compiler error, instead of simply mysteriously failing like the deprecated std::autoptr.

There is an important detail when you are using inheritance or objects with move semantics:

class Substring : myString
{
  Substring(Substring&& mov) : myString(std::move(mov))
  {
    _sub = std::move(mov._sub);
  }

  Substring& operator=(Substring&& right)
  {
    myString::operator=(std::move(right));
    _sub = std::move(mov._sub);
    return *this;
  }

  myString _sub;
};
Here we are using std::move(), which takes a variable (that is either an rvalue or a normal reference) and returns an rvalue for that variable. This is because rvalues stop being rvalues the instant they are passed into a different function, which makes sense, since they are no longer on the right-hand side anymore. Consequently, if we were to pass mov above into our base class, it would trigger the copy constructor, because mov would be treated as const Substring&, instead of Substring&&. Using std::move lets us pass it in as Substring&& and properly trigger the move semantics. As you can see in the example, you must use std::move when moving any complex object, using base class constructors, or base class assignment operators. Note that std::move allows you to force an object to be moved to another object regardless of whether or not its actually an rvalue. This would be particularly useful for moving around std::unique_ptr objects.

There’s some other weird things you can do with move semantics. This most interesting part is the strange behavior of && when it is appended to existing references.

  • A& & becomes A&
  • A& && becomes A&
  • A&& & becomes A&
  • A&& && becomes A&&

By taking advantage of the second and fourth lines, we can perform perfect forwarding. Perfect forwarding allows us to pass an argument as either a normal reference (A&) or an rvalue (A&&) and then forward it into another function, preserving its status as an rvalue or a normal reference, including whether or not it’s const A& or const A&&. Perfect forwarding can be implemented like so:

template<typename U>
void Set(U && other)
{
  _str=std::forward<U>(other);
}
Notice that this allows us to assign our data object using either the copy assignment, or the move assignment operator, by using std::forward<U>(), which transforms our reference into either an rvalue if it was an rvalue, or a normal reference if it was a normal reference, much like std::move() transforms everything into an rvalue. However, this requires a template, which may not always be correctly inferred. A more robust implementation uses two separate functions forwarding their parameters into a helper function:

class myString
{
public:
  // The copy constructor, which copies the string over instead of copying the pointer
  myString(const myString& copy)
  {
    size_t len = strlen(copy._str)+1; //+1 for null terminator
    _str=new char[len];
    memcpy(_str,copy._str,sizeof(char)*len);
  }
  // Move Constructor
  myString(myString&& mov)
  {
    _str = mov._str;
    mov._str=NULL;
  }
  // Normal constructor
  myString(const char* str)
  {
    size_t len = strlen(str);
    _str=new char[len];
    memcpy(_str,str,sizeof(char)*len);
  }
  // Destructor that deallocates our string
  ~myString()
  {
    if(_str!=NULL) // Make sure we only delete _str if it isn't NULL!
      delete [] _str;
  }
  void Set(myString&& str)
  {
    _set<myString&&>(std::move(str));
  }
  void Set(const myString& str)
  {
    _set<const myString&>(str);
  }


  // Assignment operator, does the same thing the copy constructor does, but also mimics the destructor by deleting _str. NOTE: It is considered bad practice to call the destructor directly. Use a Clear() method or something equivalent instead.
  myString& operator=(const myString& right)
  {
    delete [] _str;
    size_t len = strlen(right._str)+1; //+1 for null terminator
    _str=new char[len];
    memcpy(_str,right._str,sizeof(char)*len);
    return *this;
  }

private:
  template<typename U>
  void _set(U && other)
  {
    _str=std::forward<U>(other);
  }

  char* _str;
};
Notice the use of std::move() to transfer the rvalue correctly, followed by std::forward<U>() to forward the parameter. By using this, we avoid redundant code, but can still build move-aware data structures that efficiently assign values with relative ease. Now, its on to Part 5: Delegated Llamas! Or, well, delegates, function pointers, and lambdas. Possibly involving llamas. Maybe.

I see a lot of people get excited about extreme concurrency in modern hardware bringing us closer to the magical holy grail of raytracing. It seems that everyone thinks that once we have raytracing, we can fully simulate entire digital worlds, everything will be photorealistic, and graphics will become a “solved problem”. This simply isn’t true, and in fact highlights several fundamental misconceptions about the problems faced by modern games and other interactive media.

For those unfamiliar with the term, raytracing is the process of rendering a 3D scene by tracing the path of a beam of light after it is emitted from a light source, calculating its properties as it bounces off various objects in the world until it finally hits the virtual camera. At least, you hope it hits the camera. You see, to be perfectly accurate, you have to cast a bajillion rays of light out from the light sources and then see which ones end up hitting the camera at some point. This is obviously a problem, because most of the rays don’t actually hit the camera, and are simply wasted. Because this brute force method is so incredibly inefficient, many complex algorithms (such as photon-mapping and Metropolis light transport) have been developed to yield approximations that are thousands of times more efficient. These techniques are almost always focused on attempting to find paths from the light source to the camera, so rays can be cast in the reverse direction. Some early approximations actually cast rays out from the camera until they hit an object, then calculated the lighting information from the distance and angle, disregarding other objects in the scene. While highly efficient, this method produced extremely inaccurate results.

It is with a certain irony that raytracing is touted as being a precise, super-accurate rendering method when all raytracing is actually done via approximations in the first place. Pixar uses photon-mapping for its movies. Most raytracers operate on stochastic sampling approximations. We can already do raytracing in realtime, if we get approximate enough, it just looks boring and is extremely limited. Graphics development doesn’t just stop when someone develops realtime raytracing, because there will always be room for a better approximation.

1. Photorealism

The meaning of photorealism is difficult to pin down, in part because the term is inherently subjective. If you define photorealism as being able to render a virtual scene such that it precisely matches a photo, then it is almost impossible to achieve in any sort of natural environment where the slightest wind can push a tree branch out of alignment.

This quickly gives rise to defining photorealism as rendering a virtual scene such that it is indistinguishable from a photograph of a similar scene, even if they aren’t exactly the same. This, however, raises the issue of just how indistinguishable it needs to be. This seems like a bizarre concept, but there are different degrees of “indistinguishable” due to the differences between people’s observational capacities. Many people will never notice a slightly misaligned shadow or a reflection that’s a tad too bright. For others, they will stand out like sore thumbs and completely destroy their suspension of disbelief.

We have yet another problem in that the entire concept of “photorealism” has nothing to do with how humans see the world in the first place. Photos are inherently linear, while human experience a much more dynamic, log-based lighting scale. This gives rise to HDR photography, which actually has almost nothing to do with the HDR implemented in games. Games simply change the brightness of the entire scene, instead of combining the brightness of multiple exposures to brighten some areas and darken others in the same photo. If all photos are not created equal, then exactly which photo are we talking about when we say “photorealistic”?

2. Complexity

Raytracing is often cited as allowing an order of magnitude more detail in models by being able to efficiently process many more polygons. This is only sort of true in that raytracing is not subject to the same computational constraints that rasterization is. Rasterization must render every single triangle in the scene, whereas raytracing is only interested in whether or not a ray hits a triangle. Unfortunately, it still has to navigate through the scene representation. Even if a raytracer could handle a scene with a billion polygons efficiently, this raises completely unrelated problems involving RAM access times and cache pollution that suddenly become actual performance bottlenecks instead of micro-optimizations.

In addition, raytracing approximation algorithms almost always take advantage of rays that degrade quickly, such that they can only bounce 10-15 times before becoming irrelevant. This is fine and dandy for walking around in a city or a forest, but what about a kitchen? Even though raytracing is much better at handling reflections accurately, highly reflective materials cripple the raytracer, because now rays are bouncing hundreds of times off a myriad of surfaces instead of just 10. If not handled properly, it can absolutely devastate performance, which is catastrophic for game engines that must maintain constant render times.

3. Scale

How do you raytrace stars? Do you simply wrap a sphere around the sky and give it a “star” material? Do you make them all point sources infinitely far away? How does this work in a space game, where half the stars you see can actually be visited, and the other half are entire galaxies? How do you accurately simulate an entire solar system down to the surface of a planet, as the Kerbal Space Program developers had to? Trying to figure out how to represent that kind of information in a meaningful form with only 64 bits of precision, if you are lucky, is a problem completely separate from raytracing, yet of increasingly relevant concern as games continue to expand their horizons more and more. How do we simulate an entire galaxy? How can we maintain meaningful precision when faced with astronomical scales, and how does this factor in to our rendering pipeline? These are problems that arise in any rendering pipeline, regardless of what techniques it uses, due to fundamental limitations in our representations of numbers.

4. Materials

Do you know what methane clouds look like? What about writing an aerogel shader? Raytracing, by itself, doesn’t simply figure out how a given material works, you have to tell it how each material behaves, and its accuracy is wholly dependent on how accurate your description of the material is. This isn’t easy, either, it requires advanced mathematical models and heaps of data collection. In many places we’re actually still trying to figure out how to build physically correct material equations in the first place. Did you know that Dreamworks had to rewrite part of their cloud shader1 for How To Train Your Dragon? It turns out that getting clouds to look good when your character is flying directly beneath them with a hand raised is really hard.

This is just for common lighting phenomena! How are you going to write shaders for things like pools of magic water and birefringent calcite crystals? How about trying to accurately simulate circular polarizers when most raytracers don’t even know what polarization is? Does being photorealistic require you to simulate the Tyndall Effect for caustics in crystals and particulate matter? There are so many tiny little details all around us that affect everything from the color of our iris to the creation of rainbows. Just how much does our raytracer need to simulate in order to be photorealistic?

5. Physics

What if we ignored the first four problems and simply assumed we had managed to make a perfect, magical photorealistic raytracer. Congratulations, you’ve managed to co-opt the entirety of your CPU for the task of rendering a static 3D scene, leaving nothing left for the physics. All we’ve managed to accomplish is taking the “interactive” out of “interactive media”. Being able to influence the world around us is a key ingredient to immersion in games, and this requires more and more accurate physics, which are arguably just as difficult to calculate as raytracing is. The most advanced real-time physics engine to-date is the Lagoa Multiphysics, and it can only just barely simulate a tiny scene in a well-controlled environment before it completely decimates a modern CPU. This is without any complex rendering at all. Now try doing that for a scene with a radius of several miles. Oh, and remember our issue with scaling? This applies to physics too! Except with physics, its an order of magnitude even more difficult.

6. Content

As many developers have been discovering, procedural generation is not magic pixie dust you can sprinkle on problems to make them go away. Yet, without advances in content generation, we are forced to hire armies of artists to create the absurd amounts of detail required by modern games. Raytracing doesn’t solve this problem, it makes it worse. In any given square mile of a human settlement, there are billions of individual objects, ranging from pine cones, to rocks, to TV sets, to crumbs, all of which technically have physics, and must be kept track of, and rendered, and even more importantly, modeled.

Despite multiple attempts at leveraging procedural generation, the content problem has simply refused to go away. Until we can effectively harness the power of procedural generation, augmented artistic tools, and automatic design morphing, the advent of fully photorealistic raytracing will be useless. The best graphics engine in the world is nothing without art.

7. AI

<Patrician|Away> what does your robot do, sam <bovril> it collects data about the surrounding environment, then discards it and drives into walls — Bash.org quote [#240849](http://bash.org/?240849)
Of course, while we’re busy desperately trying to raytrace supercomplex scenes with advanced physics, we haven’t even left any CPU time to calculate the AI! The AI in games is so consistently terrible its turned into its own trope. The game industry spends all its computational time trying to render a scene, leaving almost nothing left for the AI routines, forcing them to rely on techniques from 1968. Think about that - we are approaching the point where AI in games comes down to a 50-year old technique that was considered hopelessly outdated before I was even born. Oh, and I should also point out that Graphics, Physics, Art, and AI are all completely separate fields with fundamentally different requirements that all have to work together in a coherent manner just so you can shoot headshots in Call of Duty 22.

I know that raytracing is exciting, sometimes simply as a demonstration of raw computational power. But it always disheartens me when people fantasize about playing amazingly detailed games indistinguishable from real life when that simply isn’t going to happen, even with the inevitable development2 of realtime raytracing. By the time it becomes commercially viable, it will simply be yet another incremental step in our eternal quest for infinite realism. It is an important step, and one we should strive for, but it alone is not sufficient to spark a revolution.


1 Found on the special features section of the How To Train Your Dragon DVD.
2 Disclaimer: I've been trying to develop an efficient raytracing algorithm for ages and haven't had much luck. These guys are faring much better.

Historians have noticed that the concept of teenage rebellion is a modern invention. Young adults often (but not always) have a tendency to be horny and impulsive, but the flagrant and sometimes violent rejection of authority associated with teenagers is a stereotype unique to modern culture. Many adults incorrectly assume this means we have gotten “too soft” and need to bring back spanking, paddles, and other harsher methods of punishment. As any respectable young adult will tell you, that isn’t the answer, and in fact highlights the underlying issue of ageism that is creating an aloof, frustrated, and repressed youth.

The problem is that adults refuse to take children seriously. Until puberty, kids are often aware of this, but most simply don’t care (and sometimes take advantage of it). As they develop into young adults, however, this begins to clash with their own aspirations. They want to be in control of their own lives, because they’re trying to figure out what they want their lives to be. They want to explore the world and decide where to stand and what to avoid. Instead, they are locked inside a school for 6-7 hours and spoon-fed buckets of irrelevant information, which they must then regurgitate on a battery of tests that have no relation to reality. They are not given meaningful opportunities to prove themselves as functional members of society. Instead, they are explicitly forbidden from participating in the adult world until the arbitrary age of 18, regardless of how mature or immature they are. They are told that they can’t be an adult not because of their behavior, but simply because they aren’t old enough. The high school dropout and the valedictorian get to be adults at exactly the same time - 18.

Our refusal to let young adults prove how mature they can be is doubly ironic in the context of a faltering global economy in desperate need of innovative new technologies to create jobs. Teenagers are unrestricted by concepts of impossibility, and free from the consequences of failed experiments. They don’t have to worry about acquiring government funding or getting published in a peer-reviewed journal. They just want to make cool things, and that is exactly what we need. So obviously, to improve student performance in schools, our politicians tie school funding to test scores. You can’t legislate innovation, you can only inspire it. Filling in those stupid scantron forms is not conducive to creative thinking. Our hyper-emphasis on test scores has succeeded only in ensuring that the only students who get into college are ones that are good at taking tests, not inventing things.

Young adults are entirely capable of being mature, responsible members of society if we just give them the chance to be adults instead of using a impartial age barrier that serves only to segregate them from the rest of society. They are doomed to be treated as second-class citizens not because they are behaving badly, but because they aren’t old enough. Physical labor and repetitive jobs are being replaced by automated machines, and these jobs aren’t coming back. The new economy isn’t run by office drones that follow instructions like robots, but by technological pioneers that change the world. You can’t institutionalize creativity, or put it on a test. You can’t measure imagination or grade ingenuity.

So what do we do? We cut funding for creative art programs and increase standardized testing. Our attempts to save our educational system are only ensuring its imminent demise as it prepares kids to live in a world that no longer exists.

The most valuable commodity in this new economy will be your imagination - the one thing computers can’t do. Maybe if we actually treated young adults like real people, their creativity could become the driving force of economic prosperity.

Today, xkcd featured a comic with a comically large image that is navigated by clicking and dragging. In the interests of SCIENCE (and possibly accidentally DDoSing Randall’s image server - sorry!), I created a static HTML file of the entire composite image.1

The collage is made up of 225 images2 that stretch out over a total image area 79872 pixels high and 165888 pixels wide. The images take up 5.52 MB of space and are named with a simple naming scheme "ydxd.png" where d represents a cardinal direction appropriate for the axis (n for north, s for south on the y axis and e for east, w for west on the x axis) along with the tile coordinate number; for example, "1n1e.png". Tiles are 2048x2048 png images with an average size of 24.53 KB. If you were to try and represent this as a single, uncompressed 32-bit 79872x165888 image file, it would take up 52.99 GB of space.

Assuming a human’s average height is 1.8 meters, that would give this image a scale of about 1 meter per 22 pixels. That means the total composite image is approximately 3.63 kilometers high and 7.54 kilometers wide. It would take an average human 1.67 hours to walk from one end of the image to the other. Note that the characters at the far left say they’ve been walking for 2 miles - they are 67584 pixels from the starting point, which translates to 3.072 km or ~1.9 miles, so this seems to indicate my rough estimates here are reasonably accurate.

If Randall spent, on average, one hour drawing each frame, it would take him 9.375 days of constant, nonstop work to finish this. If he instead spent an average of 10 minutes per frame, it would take ~37.5 hours, or almost an entire 40-hour work week.

Basically I’m saying Randall Munroe is fucking insane.

1 If you are on firefox or chrome, right-clicking and selecting "Save as" will download the HTML file along with all 225 images into a separate folder. 2 There are actually 3159 possible images (39 x 81), but all-white and all-black images are not included, instead being replaced by either the default white background or a massive black <div> representing the ground, located 28672 pixels from the top of the image, with a height of 51200.

I find that modern culture is often obsessed with a concept of wrongness. It is a tendency to paint things in a black and white fashion, as if there are simply wrong answers and right answers and nothing in-between. While I have seen this in every single imaginable discipline (including art and music, which is particularly disturbing), it is most obvious to me in the realm of programming.

When people aren’t making astonishingly over-generalized statements like trying to say one programming language is better than another without context, we often try to find the “best” way to do something. The problem is that we don’t often bother to think about exactly what makes the best answer the best answer. Does it have to be fast? If speed was the only thing that was important, we’d write everything in assembly. Does it have to be simple? I could list a thousand instances were simplicity fails to account for edge-cases that render the code useless. Does it have to be easy to understand? If you want something to be easy to understand, then the entire C standard library is one giant wrong answer that’s being relied upon by virtually every single program in the entire world.

For a concept taken for granted by most programmers, defining what exactly makes an implementation “optimal” is incredibly difficult. A frightening number of programmers are also incapable of realizing this, and continue to hang on to basic assumptions that one would think should hold everywhere, when very few of them actually do. Things like “the program should not crash” seem reasonable, but what if you want to ensure that a safety feature crashed the program instead of corrupting the system?

The knee-jerk reaction to this is “Oh yeah, except for that.” This phrase seems to underlie many of the schisms in the programming community. Virtually every single assumption that could be held by a programmer will be wrong somewhere. I regularly encounter programmers who think you should do something a specific way no matter what, until you ask them about making a kernel. “Oh yeah, except for that.” Or a sound processing library. “Oh yeah, except for that.” Or a rover on mars. Or a video decoder. Or a raytracer. Or a driver. Or a compiler. Or a robot. Or scientific computing.

All these except-for-that’s betray the fundamental failure of modern programming culture: There is no right answer. The entire concept of Right and Wrong does not belong in programming, because you are trying to find your way to a solution and there are billions of ways to get there, and the one that works best for your particular situation depends on hundreds of thousands of independent variables. Yet, there is a “right answer” on Stack Overflow. There are books on writing “proper code”. There are “best practices”. People talk about programming solutions that are “more right” than others. There are black and white, right and wrong, yes or no questions pervading the consciousness of the majority of programmers, who foolishly think that you can actually reduce an engineering problem into a mathematical one, despite overwhelming evidence that you simply cannot escape the clutches of reality and how long it takes an electron to reach the other side of a silicon wafer.

If you ask someone how to do something the right way, you are asking the wrong question. You should be asking them how to solve your problem. You didn’t do something the wrong way, you simply solved the wrong problem.

Today I learned that there are way too many coordinate systems, and that I’m an idiot (but that was already well-established). I have also learned to not trust graphics tutorials, but the reasons for that won’t become apparent until the end of this article.

There are two types of coordinate systems: left-handed and right-handed coordinate systems. By convention, most everyone in math and science uses right-handed coordinate systems with positive x going to the right, positive y going up, and positive z coming out of the screen. A left-handed coordinate system is the same, but positive z instead points into the screen. Of course, there are many other possible coordinate system configurations, each either being right or left-handed; some modern CAD packages have y pointing into the screen and z pointing up, and screen-space in graphics traditionally has y pointing down and z pointing into the screen.

If you start digging through DirectX and OpenGL, the handedness of the coordinate systems being used are ill-defined due to its reliance on various perspective transforms. Consequently, while DirectX traditionally uses a left-handed coordinate system and OpenGL uses a right-handed coordinate system, you can simply use D3DPerspectiveMatrixRH to give DirectX a right-handed coordinate system, and openGL actually uses a left-handed coordinate system by default on its shader pipeline - but all of these are entirely dependent on the handedness of the projection matrices involved. So, technically the coordinate system is whichever one you choose, but unlike the rest of the world, computer graphics has no real standard on which coordinate system to use, and so its just a giant mess of various coordinate systems all over the place, which means you don’t know what handedness a given function is for until things start getting funky.

I discovered all this, because today I found out that, for the past 6 or so years (the entire time my graphics engine has ever existed in any shape or form), it has been rotating everything backwards. I didn’t notice.

This happened due to a number of unfortunate coincidences. For many years, I simply didn’t notice because I didn’t know what direction the sign of a given rotation was supposed to rotate in, and even if I did I would have assumed this to be the default for graphics for some strange reason (there are a lot of weird things in graphics). The first hint was when I was integrating with Box2D and I had to reverse the rotation of its bodies to match up with my images. This did trigger an investigation, but I mistakenly concluded that it was Box2D that had it wrong, not me, because I was using atan2 to check coordinates, and I was passing them in as atan2(v.x,v.y). The problem is that atan2 is defined as float atan2(float y, float x), which means my coordinates were reversed and I was getting nonsense angles.

Now, here you have to understand that I was currently using a standard left-handed coordinate system, with y pointing up, x pointing right and z into the screen. The thing is, I wanted a coordinate system where y pointed down, and so I did as a tutorial instructed me to and reversed all of my y coordinates on the low-level drawing functions.

So, when atan2(x,y) gave me bad results, I mistakenly thought “Oh, i forgot to reverse the y coordinate!” Suddenly atan2(x,-y) was giving me angles that matched what my images were doing. The thing is, if you switch x and y and negate y, atan2(x,-y)==-atan2(y,x). One mistake had been incorrectly validated by yet another mistake, caused by yet another mistake!

You see, by inverting those y coordinates, I was accidentally reversing the result of my rotation matrices, which caused them to rotate everything backwards. This was further complicated by how the camera rotates things - if your camera is fixed, how do you make it appear that it is rotating? You rotate everything else in the opposite direction! Hence even though my camera was rotating backwards despite looking like it was rotating forwards, it was actually being rotated the right way for the wrong reason.

While I initially thought the fix for this would require some crazy coordinate system juggling, the actual solution was fairly simple. The fact was, a coordinate system with z pointing into the screen and y pointing down is still right-handed, which means it should play nicely with rotations from a traditional right-handed system. Since the handedness of a coordinate system is largely determined by the perspective matrix, reversing y-coordinates in the drawing functions was actually reversing them too late in the pipeline. Hence, because I used D3DXMatrixPerspectiveLH, I had a left-handed coordinate system, and my rotations ended up being reversed. D3DXMatrixPerspectiveRH negates the z-coordinate to switch the handedness of the coordinate system, but I like positive z pointing into the screen, so I instead hacked the left-handed perspective matrix itself and negated the y-scaling parameter in cell [2,2], then undid all the y-coordinate inversion insanity that had been inside my drawing functions (you could also negate the y coordinate in any world transform matrix sufficiently early in the pipeline by specifying a negative y scaling in [2,2]). Suddenly everything was consistent, and rotations were happening in the right direction again. Now the Camera rotation actually required the negative rotation, as one would expect, and I still got to use a coordinate system with y pointing down. Unfortunately it also reversed several rotation operations throughout the engine, some of which were functions that had been returning the wrong value this whole time so as to match up with the incorrect rotation of the engine - something that will give me nightmares for weeks, probably involving a crazed rabbit hitting me over the head with a carrot screaming “STUPID STUPID STUPID STUPID!”

What’s truly terrifying that all of this was indirectly caused by reversing the y coordinates in the first place. Had I instead flipped them in the perspective matrix itself (or otherwise properly transformed the coordinate system), I never would have had to deal with negating y coordinates, I never would have mistaken atan2(x,-y) as being valid, and I never would have had rotational issues in the first place.

All because of that one stupid tutorial.

P.S. the moral of the story isn’t that tutorials are bad, it’s that you shouldn’t be a stupid dumbass and not write unit tests or look at function definitions.

It’s almost a tradition.

Every time my graphics engine has been stuck in maintenence mode for 6 months, I’ll suddenly realize I need to push out an update or implement some new feature. I then realize that I haven’t actually paid attention to any of my testing programs, or their speed, in months. This is followed by panic, as I discover my engine running at half speed, or worse. Having made an infinite number of tiny tweaks that all could have caused the problem, I am often thrown into temporary despair only to almost immediately find some incredibly stupid mistake that was causing it. One time it was because I left the profiler on. Another time it was caused by calling the Render function twice. I’m gearing up to release the first public beta of my graphics engine, and this time is no different.

I find an old backup distribution of my graphics engine and run the tests, and my engine is running at 1100 FPS instead of 3000 or 4000 like it should be. Even the stress test is going at only ~110 FPS instead of 130 FPS. The strange part was that for the lightweight tests, it seemed to be hitting a wall at about 1100 FPS, whereas normally it hits a wall around 4000-5000 due to CPU⇒GPU bottlenecks. This is usually caused by some kind of debugging, so I thought I’d left the profiler on again, but no, it was off. After stepping through the rendering pipeline and finding nothing, I knew I had no chance of just guessing what the problem was, so I turned on the profiler and checked the results. Everything seemed relatively normal except-

PlaneShader::cEngine::_callpresent       1.0    144.905 us   19%        145 us   19%
PlaneShader::cEngine::Update             1.0     12.334 us    2%        561 us   72%
PlaneShader::cEngine::FlushMessages    1.0    546.079 us   70%        549 us   71%
What the FUCK?! Why is 70% of my time being spent in FlushMessages()? All that does is process window messages! It shouldn’t take any time at all, and here it is taking longer to process messages than it does to render an entire frame!
bool cEngine::FlushMessages()
{
PROFILE_FUNC();
_exactmousecalc();
//windows stuff
MSG msg;

while(PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);

    if(msg.message == WM_QUIT)
    {
      _quit = true;
      return false;
    }

}

_joyupdateall();
return !_quit; //function returns opposite of quit
}
Bringing up the function, there don’t seem to be many opportunities for it to fail. I go ahead and comment out _exactmousecalc() and _joyupdateall(), wondering if, perhaps, something in the joystick function was messing up? Lo and behold, my speeds are back to normal! After re-inserting the exact mouse calculation, it is, in fact, _joyupdateall() causing the problem. This is the start of the function:
void cInputManager::_joyupdateall()
{
JOYINFOEX info;
info.dwSize=sizeof(JOYINFOEX);
info.dwFlags= \[ Clipped... \];

for(unsigned short i = 0; i < _maxjoy; ++i)
{
if(joyGetPosEx(i,&info)==JOYERR_NOERROR)
{
if(_allbuttons\[i\]!=info.dwButtons)
{
Well, shit, there isn’t really any possible explanation here other than something going wrong with joyGetPosEx. It turns out that calling joyGetPosEx when there isn’t a joystick plugged in takes a whopping 34.13 µs (microseconds) on average, which is almost as long as it takes me to render a single frame (43.868 µs). There’s probably a good reason for this, but evidently it is not good practice to call it unnecessarily. Fixing this was relatively easy - just force an explicit call to look for active joystick inputs and only poll those, but its still one of the weirdest performance bottlenecks I’ve come up against.

Of course, if you aren’t developing a graphics engine, consider that 1/60 of a second is 16666 µs - 550 µs leaves a lot of breathing room for a game to work with, but a graphics engine must not force any unnecessary cost on to a program that is using it unless that program explicitly allows it, hence the problem.

Then again, calculating invsqrt(x)*x is faster than sqrt(x), so I guess anything is possible.

*"We are what and where we are because we have first imagined it."* - Donald Curtis

The wisdom of antiquity suggests that we must first imagine what we want to achieve if we are ever to succeed, but science has other ideas. A study demonstrated that visualizing yourself reaching a goal tricks your brain into thinking you actually did it, causing a relaxation response, which in turn robs you of ambition and energy.

This is a troubling counter-argument to age-old wisdom, but perhaps both sides can be right? I have been relentlessly pursuing the same goal for many years, and from my experience, it matters what you visualize just as much as if. In particular, one should imagine what you are actually trying to create, rather than what you would do with all your riches.

By coupling your imagination to your problem solving skills, you can draw a line between where you are now and what you need to do to make your vision come to life. This both solidifies your goals, highlights potential problem areas and outlines a clear plan of action, which helps prevent procrastination caused by not knowing what to do. Simply imagining that we are living the high life after hitting the big time, however, merely drains us of ambition by creating a false sense of accomplishment. You must visualize your finished creation, not the act of finishing it.

There is a marvelous, unspeakably beautiful thing that wanders around in my subconscious. Every now and then I am given another glimpse, or shown another spark of inspiration of this indescribable vision that seems so real and yet could not possibly be written about, because nothing like it has ever existed. It’s like looking into a future that could arrive tomorrow if only I could bring it to life. Sometimes I wonder if I’m losing my way, only for something else to trigger another magnificent concept. It shows me why I can never give up, even it if takes me an eternity to craft my thoughts into a new reality.

Your imagination is a tool, and like any other, it can be used or abused. Wield it wisely.

A couple years ago, when I first started designing a game engine to unify Box2D and my graphics engine, I thought this was a superb opportunity to join all the cool kids and multithread it. I mean all the other game developers were talking about having a thread for graphics, a thread for physics, a thread for audio, etc. etc. etc. So I spent a lot of time teaching myself various lockless threading techniques and building quite a few iterations of various multithreading structures. Almost all of them failed spectacularly for various reasons, but in the end they were all too complicated.

I eventually settled on a single worker thread that was sent off to start working on the physics at the beginning of a frame render. Then at the beginning of each subsequent frame I would check to see if the physics were done, and if so sync the physics and graphics and start up another physics render iteration. It was a very clean solution, but fundamentally flawed. For one, it introduces an inescapable frame of input lag.

Single Thread Low Load
  FRAME 1   +----+
            |    |
. Input1 -> |    |
            |[__]| Physics   
            |[__]| Render    
. FRAME 2   +----+ INPUT 1 ON BACKBUFFER
. Input2 -> |    |
. Process ->|    |
            |[__]| Physics
. Input3 -> |[__]| Render
. FRAME 3   +----+ INPUT 2 ON BACKBUFFER, INPUT 1 VISIBLE
.           |    |
.           |    |
. Process ->|[__]| Physics
            |[__]| Render
  FRAME 4   +----+ INPUT 3 ON BACKBUFFER, INPUT 2 VISIBLE

Multi Thread Low Load
  FRAME 1   +----+
            |    | 
            |    |
. Input1 -> |    | 
.           |[__]| Render/Physics START  
. FRAME 2   +----+        
. Input2 -> |____| Physics END
.           |    |
.           |    | 
. Input3 -> |[__]| Render/Physics START
. FRAME 3   +----+ INPUT 1 ON BACKBUFFER
.           |____|
.           |    | PHYSICS END
.           |    | 
            |____| Render/Physics START
  FRAME 4   +----+ INPUT 2 ON BACKBUFFER, INPUT 1 VISIBLE

The multithreading, by definition, results in any given physics update only being reflected in the next rendered frame, because the entire point of multithreading is to immediately start rendering the current frame as soon as you start calculating physics. This causes a number of latency issues, but in addition it requires that one introduce a separated “physics update” function to be executed only during the physics/graphics sync. As I soon found out, this is a massive architectural complication, especially when you try to put in scripting or let other languages use your engine.

There is another, more subtle problem with dedicated threads for graphics/physics/audio/AI/anything. It doesn’t scale. Let’s say you have a platformer - AI will be contained inside the game logic, and the absolute vast majority of your CPU time will either be spent in graphics or physics, or possibly both. That means your game effectively only has two threads that are doing any meaningful amount of work. Modern processors have 8 logical cores1, and the best one currently available has 12. You’re using two of them. You introduced all this complexity and input lag just so you could use 16.6% of the processor instead of 8.3%.

Instead of trying to create a thread for each individual component, you need to go deeper. You have to parallelize each individual component separately, then tie them together in a single-threaded design. This has the added bonus of being vastly more friendly to single-threaded CPUs that can’t thread things (like certain phones), because the parallization goes on at a lower level and is invisible to the overall architecture of the library. So instead of having a graphics thread and a physics thread, you simply call the physics update, then call the graphics update, and inside each physics and graphics update you spawn enough worker threads to match the number of cores you have to work with and concurrently process as much stuff as possible. This eliminates latency problems, complicated library designs, and it scales forever. Even if your initial implementation of concurrency won’t handle 32 cores, because the concurrency is encapsulated inside the engine, you can just go back and change it later without ever having to modify any programs that use the graphics engine.

Consequently, don’t try to multithread your games. It isn’t worth it. Separately parallelize each individual component instead and write your game engine single-threaded; only use additional threads for asynchronous activities like resource loading.


1
The processors actually only have 4 or 6 physical cores, but use hyperthreading techniques so that 8 or 12 logical cores are presented to the operating system. From a software point of view, however, this is immaterial.

I haven’t had a very good relationship with IP law. My 2 favorite childhood game franchises - Descent and Freespace, were thrown into IP limbo after Interplay shot itself in the foot too many times and finally fell over. As a result, I have come to utterly despise the common practice of publishers simply taking the IP of the developers for themselves, and in a more broad sense, forcing artists to give up their ownership on everything they make for a company. This becomes especially painful when they aren’t just making silly UI art, but creating a universe filled with lore and character and spirit, only to watch corporate meddling turn their idea into a wretched, free-to-play money-grubbing disaster.

What can the artist do? Exactly nothing. Under current IP law, the company usually owns all rights to everything the artist does for them, no matter what. If it doesn’t, it’s because the company screwed up its legal contracts, which is dangerous for both you and the company. There is essentially no middle ground. That means an artist can’t sue the company for screwing up their idea, because it isn’t their idea anymore. They can’t take it to another studio or even work on their own idea without permission from the company. It makes about as much sense as a company saying they own the rights to your startup idea because you came up with it at work one day and wrote a prototype during break. That isn’t just hypothetical, either, it’s a disturbingly common problem.

This is not beneficial to companies, either. Artists are increasingly aware of how little control they have over their own work. A paranoid artist who gets a great idea will be unwilling to tell anyone at the company about it until after they’ve been working on it in secret, distracting them from what they’re supposed to be working on and making them uncomfortable and stressed. They’ll worry about what will happen if they try to take the idea somewhere else and no one likes it. They could lose their only job. But if they tell anyone about the idea inside their current company, they risk losing all rights to it and then having the company decide it doesn’t like the idea and burying it forever, killing the artists brainchild without any hope of resuscitation. What’s worse is that an artist is just about as far from a lawyer as you can get - they have absolutely no idea how any of this stuff works and what they can or cannot do, so they tend to either screw up immediately and lose all rights to their idea or tell no one about it, ever. Your company will essentially lose an employee for months as they succumb to stress, and you might never even know about their idea because they’re too paranoid about you stealing it.

So what would good handling of IP be? A more fair agreement would give the company nonexclusive rights to use ideas the artist comes up with. The company only maintains nonexclusive rights to partially or completed work the artist created while employed at the company if the artist decides to quit, not the idea itself. It can even attempt to finish partially completed work, but the artist still retains the right to take his idea elsewhere. This is a compromise between ensuring a company can use everything an artist makes for them while employed without restriction, and ensuring that the artist can still walk out with his idea and bring it to life on his own or at another company. For game development companies, there would clearly need to be a clause protecting the companies right to finish a project if the lead designer leaves.

It seems reasonable to approximate this by assigning permanent nonexclusive rights to the company instead of exclusive rights, but things get complicated very quickly. If you don’t own all the rights to a copyrighted material, you can get sued if you modify the original even if you have permission to use it. It’s possible such situations could also occur with IP assignments, especially when you are specifically allocating certain nonexclusive rights in certain circumstances but not in others, or revoking certain rights upon termination. If an artist leaves a company in the middle of making a game, they shouldn’t be able to sue the resulting game because it used their old art, or even created new art based off their old art. Likewise, a company shouldn’t be able to sue an artist if they leave and create a game on their own using their idea even if the company had already released a game based on it. How one would achieve this, I have no idea. It gets even murkier when an idea is the collaborative effort of multiple people. Who owns what part? If one person leaves, the company must still retain the right to use his ideas and ideas based off his ideas, and he should only retain the right to use his own ideas, but not everyone else’s ideas or ideas based off everyone else’s ideas. What happens when they live in another country?

Because of the vast complexity of this issue, most companies say “fuck it” and simply assign all rights to themselves. This is standard advice from lawyers. The mentality is that you don’t have time to worry about silly little legal issues with artists. The problem is that it erodes artists’ rights, which are already disturbingly emancipated. This is unacceptable.

I’m not a lawyer. I don’t know how to fix this. I don’t know if it can be fixed. I don’t even know how to properly assign IP to my own company or write a contract. All I know is that artists are getting screwed over because IP law makes everyone an asshole.

Obligatory legal crap: The information provided in this blog is not intended as legal advice.

The fact that math, for most people, is about a set of rules, exemplifies how terrible our attempts at teaching it are. A disturbing amount of programming education is also spent hammering proper coding guidelines into students’ heads. Describing someone as a cowboy programmer is often derisive, and wars between standards, rules and languages rage like everlasting fires. It is into these fires we throw the burnt-out husks that were once our imaginations. We have taken our holy texts and turned them into weapons to crush any remnants of creativity that might have survived our childhood’s educational incarceration.

Math and programming are not sets of rules to be followed. Math is a language - an incredibly dense, powerful way of conveying ideas about abstraction and generalization taken to truly astonishing levels. Each theorem is another note added to a chord, and as the chords play one after another, they build on each other, across instruments, to form a grand symphony. Math, in the right hands, is the language of problem solving. Most people know enough math to get by. It’s like knowing enough French to say hello, order food, and call a taxi. You don’t really know the language, you’re just repeating phrases to accomplish basic tasks. Only when you have mastered a certain amount of fluency can you construct your own epigraphs, and taste the feeling of putting thoughts into words.

With the proper background, Math becomes a box of legos. Sometimes you use the legos to solve problems. Other times you just start playing around and see what you can come up with. Like any language, Math can do simple things, like talk about the weather. Or, you can write a beautiful novel with words that soar through the reader’s imagination. There are many ways to say things in Math. Perhaps you want to derive the formula for the volume of a sphere? You can use geometry, or perhaps calculus, or maybe it would be easier with spherical coordinates. Math even has dialects, there being many ways of writing a derivative, or even a partial derivative (one of my professors once managed to use three in a single lecture). As our mathematical vocabulary grows, we can construct more and more elegant sentences and paragraphs, refining the overall structure of our abstract essay.

Programming too, is just a language, one of concurrency, functions and flow-control. Programming could be considered a lingual descendant of Math. Just as English is Latin-based, so is programming a Math-based language. We can use it to express many arcane designs in an efficient manner. Each problem has many different solutions in many different dialects. There’s functional programming and procedural programming and object-oriented programming. But the programming community is obsessed with solving boring problems and writing proper code. Too overly concerned about maintainability, naming conventions and source control. What constitutes “common sense” varies wildly depending on your chosen venue, and then everyone starts arguing about semicolons.

Creativity finds little support in modern programming. Anything not adhering to strict protocols is considered useless at best, and potentially damaging at worst. Programming education is infused with corporate policy, designed to teach students how to behave and not get into trouble. Even then, its terribly inconsistent, with multiple factions warring with each other over whose corporate policies are superior. Programming languages are treated more like religions than tools.

The issue is that solving new problems, by definition, requires creative thinking. Corporate policy designed to stamp out anything not adhering to “best practices” is shooting itself in the foot, because it is incapable of solving new classes of problems that didn’t exist 5 years ago. Companies that finally succeed in beating the last drop of creativity out of their employees suddenly need to hire college graduates to solve new problems they don’t know how to deal with, and the cycle starts again. We become so obsessed with enforcing proper code etiquette that we forget how to play with the language. We think we’re doing ourselves a favor by ruthlessly enforcing strict coding guidelines, only to realize our code has already become irrelevant.

We need to separate our mathematical language from the proof. Just as there is more to English than writing technical specifications, there is more to Math than formal research papers, and more to programming than writing mission-critical production code. Rules and standards are part of a healthy programming diet, but we must remember to take everything in moderation. We can’t be so obsessed with writing standardized code that we forget to teach students all the wonderful obscurities of the language. We can’t be telling people to never use a feature of a programming language because they’ll never use it properly. Of course they won’t use it properly if they can’t even try! We should not only be teaching programmers the importance of formality, but where it’s important, and where it’s not. We should encourage less stringent rules on non-critical code and small side projects.

In mathematics, one never writes a proof from beginning to finish. Often you will work backwards, or take shortcuts, until you finally refine it to a point where you can write out the formal specification. When messy code is put into production, it’s not the programmer’s fault for being creative, it’s the idiot who didn’t refactor it first. Solving this by removing all creativity from the entire pipeline is like banning cars to lower the accident rate.

Corporate policy is for corporate code, not experimental features. Don’t let your creativity die. Stop following the rules.

When people leave the software industry citing all the horrors of programming, it confuses me when they blame software development itself as the cause of the problems. Programming is very similar to architecture - both an art and a science. The comparison, however, falls apart when you complain about architecture and buildings having all these well-established best practices. The art of making buildings hasn’t really changed all that much in the past 50 years. Programming didn’t exist 50 years ago.

The fact is, we’ve been building buildings for thousands of years. We’ve been writing programs for around 40, and in that period we have gone from computers the size of rooms to computers the size of watches. The instant we establish any sort of good practice, it’s bulldozed by new technology. Many modern functional programming languages had to be updated to elegantly handle concurrency at all, and we’ve only just barely established the concept of worker threads for efficiently utilizing 4-8 cores as we step into the realm of CPU/GPU collision and the advent of massively parallel processing on a large scale, which once again renders standard concepts of programming obsolete. The fact that software runs at all is, quite simply, astonishing. Windows still has old DOS code dating back to the 1980s having repercussions in Windows 7 (You can’t name a folder “con” because it was a reserved device name in DOS). If they were to completely rewrite the operating system now, it’ll be completely obsolete in 20 years anyway and we’d be complaining about NT’s lingering 32-bit compatibility issues and old functions not being threadsafe on a 128 core processor and problems I can’t even predict.

Standards can’t exist if we can’t agree on the right way to do things, and in software development, we can’t agree on the right way to do things because nobody knows (and if someone tells you they know, they’re lying). Just as we all begin to start settling down on good practices, new technology changes the rules again. This further complicates things because we often forget exactly which parts of the technology are changing. There’s a reason you write a kernel in C and not F#. Our processor architecture is the same fundamental concept it was almost 30 years ago. Ideally we would have moved away from complex instruction sets now that nobody uses them anymore, but we haven’t even done that. Language fanboys forget this and insist that everything should be written in whatever their favorite language is, without having any idea what they’re talking about. This results in a giant mess, with literally everyone telling everyone else they’re doing it wrong.

That’s the software industry today. It’s where everyone says everyone else is wrong, because we have no goddamn idea what software development should be, because what software development should be keeps changing, and its changing so rapidly we can barely keep up, let alone actually settle on a bunch of standards. Instead, individual groups standardize themselves and you get a bunch of competing ecosystems each insisting they are right, without observing that they are all right at the same time - each standard is built to match the demands of not only where, but when it is being used.

Luckily, I don’t program because I want to write programs all day. I program because I want to build something magnificent. If you make a living programming for a bunch of clients that try to tell you what to do and always say it should be faster and cheaper, well, welcome to being an artist.

*The following was written by [Saul Reynolds-Haertle](https://twitter.com/#!/saulrh), a close friend of mine who is too busy starting his PhD at Georgia Tech to run his own blog. It is posted here at his request.*

It seems like half of the internet is complaining about Google’s new wearable computers. They say that they’re distracting, they say that you can’t see through them, and they ask why you would want to be hooked into the internet like that in the first place. However, all of the basic usability complaints are built on critically unsound foundations: none of the complainers have used one of the devices. I’ve at least tried the technology1, and I have some facts and some ten-second experiments that I hope will address the more common concerns.

Obstructed Vision

We’ll begin with the claim that head-mounted displays would obstruct the wearer’s vision. This is the most common argument of the parody videos that spread like wildfire immediately after the announcement. All of them go wrong before they start, mostly because they fail to consider the fundamental differences between the human eye and the recorded video used to make the announcement. Here are a few of the ways in which this difference is important.

First, people are already missing huge chunks of their visual field. To start with, your brain only really pays attention to your foveal region, which is about the size of your thumb at arm’s length. On top of that, most adults have floaters, and everybody has the high-school-science “blind spot” where the eye’s neurons displace actual sensing elements2. Add in your nose, eye socket, hair, and sunglasses, and your brain is continually compensating for large portions of your visual field being useless. Since the icons presented by Project Glass are in the region occluded by hair and eyebrows, you won’t even notice them unless you go looking for the interface.

Secondly, and more interestingly, your cell phone makes you go blind every time you look at it.[pdf] The problem is focal length. It takes nearly half a second for the human eye to change its focus from something on the horizon to something at arm’s length, during which time you see just as much (or as little) as you do during a saccade. The trick here is that an HMD can be calibrated to appear as if it’s way far away, so your eye can view its image without having to waste time bending lenses around. The effect, when experienced in person, is somewhat striking.

The third fact that this argument misses is more important still. You have two eyes, but Project Glass is only on one of them! In order to convey how critical this omission is, I want you to conduct a short experiment. First, hold up your left hand. Second, cover your left eye using your left hand. Third, continue reading.

Texting While Walking

The next major complaint is that the glasses will present a crippling distraction. I’ll agree that the glasses will be distracting, but I’m equally sure that they’ll be less of a distraction than people think.

The big thing this argument forgets is that people are actually pretty good at being distracted. Next time you’re at the grocery store, count how many times you look down to read your shopping list while you’re still moving. While you’re walking down the street, pay attention to how often you look at things around you - eye-catching passersby, nice clothing in storefronts, birds flying across the edges of your vision, and so on. Count how many people you see with their noses buried in their book or their phone while they walk. Compared to all this, getting an email really isn’t that much of a problem.

Wearable ComputerI’ll even provide some direct evidence that HMDs aren’t distracting. The guy in the picture at right is Thad Starner. He’s been wearing a head-mounted display continuously since 1993; he’s also been deeply involved in Project Glass for a while. Unlike Project Glass, though, his HMD displays a full 1024x768 computer screen with an internet connection, a browser, and Emacs - far more distracting than Google’s streamlined interface. I work with some of his students and talk to him occasionally, so I can tell you one thing: he doesn’t run into walls very often.

Of course, “doesn’t run into walls very often” isn’t exactly a scientific measurement, so Dr. Starner has gone ahead and done some research.[pdf] In particular, he and his colleagues gave some german students a shelf full of bins and a series of orders to place. Some students were given lists of items on paper, others were given pictures of which bin to grab items from, others were given orders over an earphone, and the final group was shown the order on a head-mounted display. Despite having an image floating right in front of them, HMD-equipped users completed their tasks with a third as many errors and about fifteen seconds faster than their competitors. Head-mounted displays aren’t distracting; if anything, they’re less of a problem than the average intrusion.

Too Connected to Think

The final argument, and possibly the most important, is that a permanent internet connection is bad. As you might expect, I believe exactly the opposite.

Put simply, we use computers enough that we’ve become used to them, not only habitually, but in that our brains have physically shifted around to work with them. Research[pdf] shows that, if given some information and induced to memorize either the information itself or where it can be found, people are much better at remembering where information can be found. We’ve all observed this firsthand. We remember the name of the page on Wikipedia rather than its contents, we remember the name of the function or the class rather than its signature and we look it up in the documentation, and so on.

We’re well on our way towards Charles Stross’s “posthuman genius loci of the net”, where a person’s computer contains so much information that forced separation results in crippling amnesia. As another experiment, I challenge you to remember more than half of your address book, email or phone number or snail-mail, without using your computer. To recall a definition, a cyborg is “a person who is part machine”. Not a human body with robot bits, but a person, a self-aware consciousness, which leans on computers to do some of its work. We are all cyborgs. Project Glass simply makes it harder for us to lose our machine halves or drop them in the toilet.

Given that, why is there so much naysaying in the first place? You already have a laptop or a smartphone that organizes your pictures, navigates for you, handles your calendar and your address book, and (by way of Wikipedia) remembers the capital of Albania so you don’t have to. Most of you have it with you 24/7. I simply don’t understand the objection to making it more powerful and easier to use. I make my computer handle as much of my life as it can; when I’m not doing arithmetic, I can be doing calculus, and when I’m not trying to remember someone’s phone number, I can be talking with them about the meaning of life. My computer makes me a better human because it gives me the freedom to exercise my rationality and consciousness. Project Glass is something I welcome. It helps me be human even when I’m not sitting at my desk.

1 Virtual Retina Display

2 Demonstration

Sometimes it really amazes me when anyone actually takes language wars seriously. If I casually mention “pointless language wars” and someone leaves a comment ignoring my entire blog post, informing me that language wars are not pointless, I seriously question their priorities (and possibly their sanity).

*As a veteran language warrior, I resent the claim that my efforts are "pointless". There's a lot of terrible software out there, and one of the reasons for this is that inappropriate choices were made on the outset.*

Oh, was I not clear enough before? Language wars are pointless. They are pointless for 2 reasons: You are never actually arguing about the language, only design philosophies, and these language wars invariably disregard context, which makes all results of said war completely meaningless.

In this crazy rant Alex Munroe1 made about PHP being a terrible language, he seems to be confusing “PHP is a bad language” and “PHP adheres to bad design philosophies”, and even then its just design philosophies he doesn’t agree with. This is all well and good, but that doesn’t make PHP a bad language. It’s like saying a hammer is bad because you don’t like the handle - just because its not good for you doesn’t mean its not good for everyone. If you want to prove that PHP is fundamentally a bad language, you have to demonstrate that almost all the philosophies that it follows are bad for everyone. You can’t say a philosophy is good in one language and not good in another without accidentally tripping over yet another philosophy. A good example is his complaint about the ‘@’ operator suppressing errors. You can suppress errors in python too, its just harder. The argument is that its too easy to ignore errors, therefore it encourages bad programming, therefore PHP is the devil. This doesn’t make sense, because you aren’t saying PHP itself is bad, you are saying that you believe a programming language should make writing bad code difficult, which is a philosophy. Consequently, you can’t just say that PHP is bad, you have to say that every single language that does this is at least partially bad. Of course, the guy loves writing code in perl, so I suppose he prefers using a language that makes it hard to do anything.2

Let’s say you actually prove that something is bad for everyone. Have you proven that its bad for everyone in every possible context? You have to do that too. The problem with language wars is that people go “Yo man whatcha using PHP for we got dis new trunk called Django that’s so wicked sick goddamn get with the times homie” without ever actually asking you what you are trying to do and in what context you are doing it in. You cannot critique a language without first specifying what context you are critiquing it in. If you do not specify the context, even if its something vague like “for most non-performance critical applications”, everything you say is an over-generalization and therefore invalid. There is quite literally NOTHING that you can absolutely guarantee any piece of code should do - not even the fact that it should work (for example, testing static code analysis). Because of this, unless you are saying X is a bad language for doing Y, and not simply that a given language is bad, forever, no matter what, you are doing a bad job of critiquing. Even brainfuck is useful for illustrating how a Turing Machine works. As the old saying goes, never say never (or always).

With this said, most of the points Alex Munroe makes against PHP are actually quite valid.3 In fact, if he had instead argued that PHP is a poor choice of language for building a modern, professional website, I’d probably agree …but that doesn’t make it a bad language. Maybe its a bad language for that purpose, but that’s as far as you can go and still hold a legitimate opinion. There is an endless, endless torrent of people insisting that C++ is a terrible language, and it’s not that their reasons are wrong, it’s that they are ignoring the context of what I use C++ for. It just follows design philosophies they don’t agree with in their line of work. It’s fine that they don’t agree with them, but uh, that’s why we have lots of different programming languages and why we need to stop assuming programmers are all the same. What are you going to do, tell Linus Torvalds to code Linux using Lisp instead of C because Performance Doesn’t Matter?

This problem of blindly following idioms like “Performance Doesn’t Matter” and “SHARD EVERYTHING” in the database world is that you are separating the advice from the context it was given in. This makes language wars pointless and causes serious issues with the new wave of databases that are pissing off a lot of people (BUT MONDODB IS WEB SCALE) because fanboys who don’t understand the context those databases were designed for simply assume you should use them for everything and therefore anyone using MySQL or PostgreSQL is a dinosaur. You can’t just forget about Unknown unknowns (things you don’t know that you don’t know). If someone is using a language and you don’t understand why, don’t assume its because they’re an idiot because the language is bad no matter what, assume that its because there is a variable you forgot to account for.

It’s kind of like watching a carpenter yell at a plumber for building a house upside-down, except the plumber actually built a toilet and the carpenter just thinks it looks like an upside-down house.


1 whose name took me almost 2 minutes of digging around his blog, and then his site, until I finally found it buried in the fine print on the footer.

Yesterday, I saw a superb presentation called “When The Consoles Die, What Comes Next?” by Ben Cousins. It demonstrates that mobile gaming is behaving as a disruptive technology, and is causing the same market decline in consoles that consoles themselves did to arcades in the 1990s. He also demonstrates how TV crushed cinema in a similar manner - we just don’t think of it like that because we don’t remember back when almost 60% of the population was going to the movie theaters on a weekly basis. Today, most people tend to go to the movie theater as a special occasion, so the theaters didn’t completely die out, they just lost their market dominance. The role the movie theater played changed as new technology was introduced.

The game industry, and in fact the software industry as a whole, is in a similar situation. Due to the mass adoption of iPads and other tablets, we now have a mobile computing experience that is distinct from that of say, a console, or even a PC. Consequently, the role of consoles and PCs will shift in response to this new technology. However, while many people are eager to jump on the bandwagon (and it’s a very lucrative bandwagon), we are already losing sight of what will happen to stabilize the market.

People who want to sound futuristic and smart are talking about the “Post-PC Era”, which is a very inaccurate thing to say. PCs are clearly very useful for some tasks, and its unlikely that they will be entirely replaced by mobile computing, especially when screen real-estate is so important to development and productivity, and the difficulty of replicating an ergonomic keyboard. The underlying concept of a PC, in that you sit down at it, have a keyboard and mouse and a large screen to work at, is unlikely to change significantly. The mouse will probably be replaced by adaptive touch solutions and possibly gestures, and the screen might very well turn into a giant glass slab with OLEDs on it, or perhaps simply exist as the wall, but the underlying idea is not going anywhere. It will simply evolve.

Windows 8 is both a surprisingly prescient move on part of Microsoft, and also (not surprisingly) a horrible train wreck of an OS. The key concept that Microsoft correctly anticipated was the unification of operating systems. It is foolish to think that we will continue on with this brick wall separating tablet devices and PCs. The difference between tablets and PCs is simply one of both user interface and user experience. These are both managed by the highest layers of complexity in an operating system, such that it can simply adapt its presentation to suit whatever device it is currently on. It will have to once we introduce monitors the size of walls and OLED cards with embedded microchips. There will be such a ridiculous number of possible presentation mediums, that the idea of a presentation medium must be generalized such that a single operating system can operate on a stupendous range of devices.

This has important consequences for the future of software. Currently we seem to think that there should be “tablet versions” of software. This is silly and inconvenient. If you buy a piece of software, it should just work, no matter what you put it on. If it finds itself on a PC, it will analyze the screen size and behave appropriately. If its on a tablet, it will enable touch controls and reorganize the UI appropriately. More importantly, you shouldn’t have to buy a version for each of your devices, because eventually there won’t be anything other than a computer we carry around with us that plugs into terminals or interacts with small central servers at a company.

If someone buys a game I make, they own a copy of that game. That means they need to be able to get a copy of that game on all their devices without having to buy it 2 or 3 times. The act of buying the game should make it available to install on any interactive medium they want, and my game should simply adapt itself to whatever medium is being used to play it. The difference between PC and tablet will become blurred as they are reduced to simply being different modes of interaction, with the same underlying functionality.

This is what Microsoft is attempting to anticipate, by building an operating system that can work on both a normal computer and a tablet. They even introduce a Windows App Store, which is a crucial step towards allowing you to buy a program for both your PC and your tablet in a single purchase. Unfortunately, the train-wreck analogy is all too appropriate for describing the state of Windows 8. Rather than presenting an elegant, unified tablet and PC experience, they smash together two completely incompatible interfaces in an incoherent disaster. You are either presented with a metro interface, or a traditional desktop interface, with no in-between. The transition is about as smooth as your head smashing against a brick wall. They don’t even properly account for the fact that their new metro start menu is terribly optimized for a mouse, but try to make you use it anyway. It does the right thing, the wrong way.

The game industry has yet to catch on to this, since one designs either a “PC game” or a “mobile game”. When a game is released on a tablet, it’s a special “mobile version”. FL Studio has a special mobile version. There is no unification anywhere, and the two are treated as separate walled gardens. While this is currently an advantage during a time where tablets don’t have the kind of power a PC does, it will quickly become a disadvantage. The convenience of having familiar interfaces on all your devices, with all of the same programs, will trump isolated functionality. There will always be games and programs more suited to consoles, or to PCs, or to tablets, but unless we stop thinking of these as separate devices, and instead one of many possible user experiences that we must adapt our creations to, we will find ourselves on the wrong side of history.

So today I go to an orthodontist appointment at 11:30 AM, and its bright and sunny out, but fairly breezy. Several hours later I leave for a final exam for CSE 373 at the UW. Still nice and sunny out, but also still very breezy. We start the exam, and 40 minutes in, the power cuts out and we’re put into pitch blackness. A few seconds later, I can hear a generator hum to life and the power is suddenly back on.

*"Just so you know, if that happens again, I don't have a Plan B"* - My professor

10 minutes later, it happened again, as I heard the dying groans of the generator failing. For a few confused minutes, students used their cellphones to try and work on the test, until the evacuation alarm sounded. I hung around outside the building for a good 20 minutes before the professor finally cancelled the final outright due to extraneous circumstances. I realize I don’t actually know what happens when a final gets cancelled. Note that it is still warm and sunny outside, just very windy.

So, I go home on the bus, and things get a bit overcast, but nothing major. Then I get back to Redmond and the whole town is in the middle of a goddamn blizzard, which I then had to drive through back from the Park & Ride to get to my house. By the time I turned on my computer, the sun was out again.

Washington is fucking bipolar.

So I’d been using the developer preview of VS11 and liked some of its improvements. When the desaturated VS11 beta came out, I hated the color scheme but decided I still wanted the upgraded components, so I went to install VS11 beta. Unfortunately the beta only lets you change its install location if the preview developer preview isn’t installed, and the developer preview had installed itself into C:\ without ever letting me change the path, which was annoying. So I took the opportunity to fix things and uninstalled the developer preview, then installed the beta of VS11.

Everything was fine and dandy until I discovered that VS11 wasn’t compiling C++ DLLs that worked on XP. I don’t know how it managed to do this, since the DLL had no dependencies whatsoever, and that bug was only supposed to affect MFC and other windows related components and hence there was no windows flag for me to specify which version I wanted, but just to be sure I decided to try and compile it in VS2010. It was at this point I discovered that VS2010 could no longer open any projects at all. It was broken. Further investigation revealed that uninstalling VS11 developer preview will break VS2010. Now, I had an ultimate version of VS2010 I’ve had sitting around for a while I got from Dreamspark, so I figured I could just uninstall VS2010 and then reinstall the ultimate version and that would kill any remaining problems the pesky 2011 beta introduced.

The thing is, I can’t uninstall the SP1 update from VS2010. Not before I uninstalled VS2010, not after I uninstalled it, not even after I installed the ultimate version. It just gave me this:

*The removal of Microsoft Visual Studio 2010 Service Pack 1 may put this computer in an state in which projects cannot be loaded and Service Pack 1 cannot be reinstalled. For instructions about how to correct the problem, see the readme on the Microsoft Download Center website.*

So I just had to leave the Service Pack alone and attempted to re-apply it after installing VS2010 Ultimate, but the online installer failed. So then I downloaded the SP1 iso file and installed that. It failed too, but this time I could fix the problem - someone had forgotten to copy the F#_redist MSI file to the TEMP directory, instead only copying the CAB file. Note that I don’t even have F# installed.

I was able to resolve that problem and finished installing the service pack, but to no avail. Both the VS2010 installation and the service pack had forgotten to install the C++ standard library headers, which, as you can imagine, are kind of important. I searched around for a solution, but the only guy who had the same problem as me had simply reformatted and reinstalled windows (note the moderator’s excellent grasp of english grammar). The only thing I had to go off of was using a special utility they built to uninstall all traces of VS2010 from your computer. Unfortunately, the utility doesn’t actually succeed in uninstalling everything, and also doesn’t uninstall SP1, so you have to uninstall SP1 first before running the utility. The problem is, I can’t uninstall SP1 or I’ll never be able to install it again.

At this point it appears I am pretty much fucked. How does Microsoft consider this an acceptable scenario? I worked as an intern at Microsoft once, I know they use their own development tools. I used tools that hadn’t even been released yet. There was one guy on our team whose entire job was just the setup. And yet, through a series of astonishingly bad failures, any one of which being fixed would have prevented this scenario, my computer is now apparently fucked, and I’m going to have to upgrade my windows installation to 64 bit a lot sooner than I wanted.

EDIT: After using the uninstall tool to do a full uninstall and uninstalling SP1 and manually finding any VC10 related registry entries in the registry and deleting them, then reinstalling everything from scratch, I solved the header file problem (but had to reinstall SP1 or it wouldn’t let me open my project files). However then the broken VCTargetsPath problem showed up again, which a repair didn’t fix. I finally fixed the issue by finding someone else with a working installation of VC10, having them export their MSBuild registry key and manually merging it into my registry. If you have this problem, I’ve uploaded the registry key (which should be the same for any system, XP or 7) here. If you have a 64-bit machine, you may need to copy its values into the corresponding WoW64 nodes (just search for a second instance of MSBuild in your registry).

Several years ago, this famous rant by Bill Gates (here’s a more readable version) made its way around the internet. What was remarkable about it was that Bill Gates himself flaming his underlings for many of the things everyone else was complaining about did almost nothing to improve Windows. What improvements were eventually made are usually attributed to many outside influences, especially Apple and the rise of tablet PCs.

This really isn’t that remarkable to anyone inside the software industry. I’ve been an intern at Microsoft and I’ve seen all sorts of hilariously misconstrued practices and rules and regulations meant to bend employees into some magical definition of an awesome developer that is usually, itself, hopelessly misguided. Almost the entire modern business world runs on the idea that you hire someone and then tell them how to behave. It’s an authoritarian mindset derived from the idea that employees should be obedient little robots. You hire managers to manage the employees, and when you have too many managers you hire department heads to manage the managers, and so on.

This is not how you manage creative people. Creative people should not be told what to do, only be given a general direction to walk in. You should hire a creative person because you want him to do what he was doing anyway. If your operating system is bloated, then hire someone who thinks that it shouldn’t be bloated. You don’t have to TELL that employee to make the operating system less bloated because they want it to be less bloated, so they’ll just make it less bloated. If you don’t trust them to do a good job making the operating system less bloated you shouldn’t hire them.

In this context, the entire modern concept of a CEO driving the direction of a corporation breaks down. You do not drive the direction of a company by telling employees what to think. You drive the direction of a company by hiring people who think in the direction you want to go. Creative people work best when you simply let them do their jobs.

If you hire a web designer, you don’t tell them what to do. You tell them what the end goal is, what the restrictions are, and let them figure out the best way to do it. The entire concept of a CEO going through potential website designs until he finds one he “likes” is utterly ridiculous since you just hired them because they know that! A situation where a manager can do an employee’s job better than they can is extremely rare, because the people who tend to be the best at doing something are the people who are actually doing it. Just let them do the job you hired them to do.

If you hire a programmer to write a graphics engine, you don’t tell them what order to implement features in. You don’t even tell them what features you want them to implement, because someone else on your artistic team is supposed to know which features are needed, and the programmer is expected to prioritize those features properly because that’s what you freaking hired them for.

If I hire an artist/designer to make a game, I expect them to go and make the game. I give them certain limitations, like budget concerns or maximum development time, but I expect them to be able to work within these restrictions or I wouldn’t have hired them in the first place. If they don’t, I don’t hire a manager to make sure they do, I fire them (or move them somewhere else) because they aren’t doing their job. The only time you need a manager is when there is a conflict of interest in the workplace or someone is actually doing something wrong. If most modern software companies have managers managing people day in and day out, then apparently those companies think that an employee is doing something wrong every single day. If an employee is doing something wrong every single day, why did you hire them?

Even worse is that software companies do not consider themselves bastions of creativity. This is a problem, because software companies benefit greatly from this, since programmers tend to be naturally self-driven. A team working on a project simply needs a designated team leader to keep things focused, not a full-time manager, and the team leader definitely shouldn’t be spending his entire day attending meetings (coughMicrosoftcough). It’s the team’s project. They decide where it should go, and if this is a problem then you shouldn’t have hired them. Google is an example of a software company leaning in this direction.

Creative companies need to trust their employees. Managers exist because employers don’t trust employees. Software companies don’t realize they’re actually creative companies, and their employees hate this because the managers usually have no bloody idea what they’re talking about, and we see examples of this over and over and over in the news and laugh at them. But we never actually look at it as a problem that needs to be fixed, only as an inevitability.

We can fix this. In fact, it was fixed almost a decade ago. Valve has no managers. There’s just Gabe Newell and then everyone else. It works. If you happen to like Portal, I think you’d agree that it works really damn well. There is a significant chunk of the workforce that is not being utilized. The companies that do manage to utilize it are the ones that write the history books.

I do not usually involve myself with politics and bureaucracies, but they have a way of creeping into every facet of human experience in an almost parasitic manner. Even in my own profession of software engineering I have to deal with pointless language wars, followed by people being pissed off that I called them pointless. Well then, let me be perfectly clear here: Language wars are pointless. You know what else is pointless? Racism is pointless, sexism is pointless, rape culture is pointless, homophobia is pointless, religious dogma is pointless, and pretty much every single topic in modern politics is pointless, either by virtue of simply being ridiculous or by completely missing the point.

What bothers me about homophobia is twofold. One, obviously, is that it involves a religious person telling two people they can’t fall in love with each other because whatever god they happen to worship says so, as if they actually have the authority to tell two adults what to do. If those two adults choose to go to hell, your own goddamn bible says you’re supposed to be nice to them anyway. But what’s really disturbing is the fact that anyone even gives a shit about any of this. A dude wants to marry a dude, and this supposedly destroys the sanctity of marriage. I think you people are a tad bit sheltered, because there are teenage girls being sold into slavery, in a sex-trafficking ring, in America. I think, just maybe, you need to chill out, because being sold into slavery seems a lot worse than two guys kissing.

Then we have people who don’t believe in woman’s rights, or are still opposed to inter-racial marriage, as accounted by Kevin Roose in his book “The Unlikely Disciple”. These people actually care about trying to restrict woman from working or stopping inter-racial marriage. We have people campaigning against contraception and abortions at the same time without thinking about the difference between being right and being pragmatic. What about kids dying of thirst in Africa? What about the tyrannical despots still in control of various middle-eastern nations? What about China’s one-child policy? What about malaria epidemics in South America?

What happened to all the hard problems?

Why would anyone even care about burning a book? And why would some people proceed to laugh at the Taliban for doing that and then get pissed off about gay marriage? Do they simply not understand what being a hypocrite means? Why is it that the word “sheeple”, once used only by conspiracy theorist lunatics, now seems to describe Americans with disturbing accuracy? Has Facebook so changed our lives that we are now too incensed about a bunch of completely irrelevant topics that we forget about doing anything that actually has meaning? Have we ever actually cared about things that really matter?

In the late 1960s, America had a purpose (so did Russia). It is sad that we apparently require a war that threatens our livelihood to get us to think logically for 5 seconds, and even then this was in the middle of the civil rights movement - so even in our one moment of glory, we were still being assholes. Now America is so powerful it faces no existential threat, and has predictably devolved into a bunch of bickering toddlers (who are still assholes).

The future has not turned into 1984, nor does it involve flying cars. Instead, it is a strange amalgamation of realities, fused into a giant mess we call modern life. Facebook is still dependent on a 40 year old internet backbone. 95% of all modern software is crap and inherently dependent on code written several decades ago. We haven’t solved world hunger, or moved to electronic credits, or colonized the moon, or hell even gotten back to the moon at all. We’re too busy arguing about celebrities and gay marriage and religious books and a whole bunch of meaningless crap. We have failed to give our kids any sort of perspective, or priority. People do not understand the importance of compromise and instead criticize our president for trying to get things done. We seriously complain about our president doing exactly what politicians are supposed to do - compromise! We argue about teaching evolution in school, we argue about being forced to give girls Plan B!

CHILL OUT!

If a little girl was dying of thirst, would you ask her if she was a lesbian before giving her a drink?

One would hope that, in a distant future, while humanity will inevitably still bicker about silly things, we would at least know that ensuring reasonable quality of life for fellow sentient beings and trying to make our world (or solar system, at that point) a better place trumps silly arguments like why people are still using C++, or whose god has a bigger dick.

I’m not very optimistic.

For a long time, I have been frustrated with the poor UI design that is rampant in the software industry. As a consequence, many Linux enthusiasts have pointed out how productive you can be with Emacs, VIM, and other keyboard-shortcut/terminal oriented software. The UI design has gotten so bad, I have to agree that in comparison to recent user interface designs, keyboard shortcuts are looking rather appealing. This, however, doesn’t mean that one approach is inherently better than another, simply that modern user interfaces suck.

In this blog, I’m going to outline several improvements to user interfaces and the generalized alternative design philosophy that is behind many of them. To start, let’s look at this recent article about Visual Studio 11, which details Microsoft’s latest strategy to ruin their products by sucking all the color out of them:

Visual Studio 2010Visual Studio 2010
Visual Studio 11Visual Studio 11

See, color is kind of important. Notably, color is how I find icons in your toolbar. To me, color is a kind of filter. If I know what color(s) are most prominent in a given icon, I can mentally filter out everything else and only have to browse through a much smaller subset of your icons. Combined with having a vague notion of where a given icon is, this usually reduces the number of icons I have to mentally sift through to only one or two.

Color FilteringMental color and spatial filtering

If you remove color, I am left to only my spatial elimination, which can make things extremely annoying when there are a bunch of icons right next to each other. Microsoft claims to have done a study that shows that this new style does not harm being able to identify a given icon in terms of speed, but fails to take into account the mental tax that goes into finding an icon without color.

While we understand that opinions on this new style of iconography may vary, an icon recognition study conducted with 76 participants, 40 existing and 36 new VS users, showed no negative effect in icon recognition rates for either group due to the glyph style transition. In the case of the new VS users they were able to successfully identify the new VS 11 icons faster than the VS 2010 icons (i.e., given a command, users were faster at pointing to the icon representing that command).
You may still be able to find the icon, especially after you’ve been forced to memorize its position just to find it again, and do it reasonably fast, but whether you like it or not, the absence of color will force your brain to process more possible icons before settling down on the one you actually want. When I’m compiling something, I only have a vague notion of where the start button actually is. I don’t need to know exactly where it is or even what it looks like; it’s extremely easy to find since its practically the only green button on the entire toolbar. Same goes for save and open. The uniform color makes the icons very easy to spot, and all the other icons are immediately discarded.

That said, there are many poorly design icons in Visual Studio. Take this group of icons: Bad Icons!

I don’t really know what any of those buttons do. One of them is some sort of toolbox and one is probably the properties window, but they have too many colors. It becomes, again, mentally taxing when even looking at those icons because there is too much irrelevant information being processed. In this scenario, the colors are detrimental to the identification of the buttons. This is because there is no single dominant color, like on the play button, or the save button. Hence, the best solution is to design icons with principle colors, such that some or all the icon is one color and the rest is greyscale. The brain edits out the greyscale and allows identification by color, followed by location, followed by actual glyph shape. To avoid overloading the user with a rainbow of colors, consider scaling the amount of color to how likely a given button is to be used. Desaturate or shrink the colored area of buttons that are much less important. Color is a tool that can be used correctly or incorrectly - that doesn’t mean you should just throw it away the first time you screw up.

We can make better decisions by taking into account how the user is going to use the GUI. By developing an awareness of how a user interface is normally used, we develop vastly superior interactions that accelerate, rather than impede, workflow. To return to visual studio, let’s take a look at a feature in the VS11: pinning a variable preview. Variable PreviewPinned Variable Preview

This is a terrible implementation for a number of reasons. First, since the pin button is all the way on the other end, it is a moving target and you’ll never really be sure where it is until you need to pin something. Furthermore, you can drag the pinned variable around, and you’ll want to after Visual Studio moves it to a seemingly random location that is almost always annoying (but only after the entire IDE locks up for 3 seconds because you haven’t done it recently). When would a user be dragging a variable around? Only when its pinned. A better implementation is to make a handle on the left side of any variable preview. If you click the handle (and optionally drag the variable around), it is implicitly converted to a pinned variable without changing anything else, and a close button appears to the left of the handle.

Better Variable PreviewBetter Pinned Preview

This is much easier to use, because it eliminates a mouse click and prevents the variable from moving to some random location you must then locate afterwards to move it to your actual desired location. By shifting the close button to the left, it is no longer a moving target. To make this even better, you should make sure previews snap to each other so you can quickly build a list of them, and probably include a menu dropdown by the close button too.

We have just used Implicit UI Design, where instead of forcing the user to explicitly specify what they want to have happen, we can use contextual clues to imply a given action. We knew that the user could not possibly move a variable preview without wanting to pin it, so we simply made the act of moving the preview, pin it. Another example is docking windows. Both Adobe and Visual Studio are guilty of trying to make everything dockable everywhere without realizing that this is usually just extremely annoying, not helpful. I mean really, why would I want to dock the find window?

Bad Find Window!
Goddamn it, not again

Even if I was doing a lot of find and replace, it just isn’t useful. You can usually cover up half your code while finding and replacing without too much hassle. The only thing this does is make it really hard to move the damn window anywhere because if you aren’t careful you’ll accidentally dock it to the toolbar and then you have to pull the damn thing out and hope nothing else blew up, and if your really unlucky you’ll have to reconstruct the whole freaking solution window.

That isn’t helpful. The fact that the act of docking and undocking can be excruciatingly slow makes things even worse and is inexcusable. Only a UI that is bloated beyond my ability to comprehend could possibly have such a difficult time docking and undocking things, no doubt made worse by their fetishization of docking windows. Docking windows correctly requires that you account for the extremely common mistake of accidentally undocking or docking a window where you didn’t want it. If a mistake is so common and so annoying, you should make it either much harder to do, or make it very easy to undo. In this case, you should remember where the window was docked last (or not docked), and make a space for it to be dropped into, instead of forcing the user to figure out which magic location on the screen actually docks the window to the right position (which sometimes involves differences of 2 or 3 pixels, which is incredibly absurd).

Spot Holding
Spot Holding

Panels are related to docking (usually you can dock something into a collapsible panel), but even these aren’t done very efficiently. If you somehow manage to get the window you want docked into a panel, it defaults to pinning the entire group of panels, regardless of whether they were pinned before or not. I just wanted to pin one!

Pin Disaster
You have to drag the thing out and redock it to pin just that one panel.

There is a better way to do this. If we click on a collapsible panel, we know the user wants to show it. However, the only reason they even need to click on the panel is because we don’t show it immediately after the mouse hovers over the button. This time should be less than a tenth of a second, and it should immediately close if the mouse gets too far away. It should stay open if the mouse is close enough that the user might have temporarily left the window but may want to come back in. Hovering over another panel button immediately replaces the current panel (in this case, at least), and dragging the panel title bar or the panel button lets you dock or undock.

Now the user will never need to click the panel to make it show up, so we can make that operation do something else. Why not make clicking a panel pin it open? And don’t do any of that “pin the entire bunch of panels” crap either, just pin that one panel and have it so the other panels can still pop up over it. Then, if you click the panel button again, it’s unpinned. This is so much better than the clunky UI interfaces we have right now, and we did it by thinking about Implicit UI Design. By making the mouse click redundant, we could take that to imply that the user wants the panel to be pinned. Moving the mouse far away from the panel implies that the panel is no longer useful. To make sure a mistake is easy to correct, pinning a panel should be identical to simply having it be hovered over indefinitely, and should not change the surrounding UI in any way. Then a mistake can simply be undone by clicking the panel button again, which is a much larger target than a tiny little pin icon. Combine this with our improved docking above, so that a mistakenly undocked panel, when clicked and dragged again, has its old spot ready and waiting in case you want to undo your mistake.

Panel holding

It’s 2012. I think its high time our user interfaces reflected that.

Over the course of 3 hours spent trying to figure out why my Linux Mint 12 KDE installation would to go to a permanent black screen on boot, I managed to overheat part of my computer (at least that is the only thing that could explain this) to the point where it’d lock up on the POST and had to give up until this morning, where I managed to figure out that I could delete the xorg.conf file in Mint to force it to go to default settings. This finally got Mint 12 to show up, and I later confirmed that the nvidia drivers were broken. I then discovered that the nvidia drivers in the distribution for apt-get sources are almost 120 versions behind the current release (295), but the installer for that kept failing despite my attempts to fix it and having to add source repositories to apt-get because apparently these are disabled by default, which confused me greatly for a short period whilst trying to install the Linux source. This ultimately proved futile since Nvidia can’t be bothered to make anything remotely easy for Linux, so I’m stuck with a half-broken default driver that can’t use my second monitor with a mouse cursor that repeatedly blinks out of existence in a very aggravating manner.

Of course, the only reason I even have Linux installed is to compile things on Linux and make sure they work, so as long as my development IDE works, I should be fine! Naturally, it doesn’t. Kdevelop4 is the least insultingly bad coding IDE available for Linux that isn’t VIM or Emacs, which both follow in the tradition of being so amazingly configurable you’ll spent half your development cycle trying to get them to work work and then learning all the arcane commands they use in order to have some semblance of productivity. Like most bizarre, functionality-oriented Linux tools, after about 6 months of torturing yourself with them, you’ll probably be significantly more productive than someone on Visual Studio. Sadly, the majority of my time is not spent coding, it’s spent sitting in front of a computer screen for hours trying to figure out how to get 50 lines of code to work properly. Saying that your text editor lets you be super productive assumes you are typing something all the time, and if you are doing that you are a codemonkey, not a programmer. Hence, I really don’t give a fuck about how efficient a given text editor is so long as it has a couple commands I find useful in it. What’s more important is that it works. KDevelop4 looked like it might actually do this, but sadly it can’t find any include files. It also can’t compile anything that isn’t C++ because it builds everything with CMake and refuses to properly compile a C file. It has a bunch of hilariously bad user interface design choices, and basically just sucks.

So now i’m back to the command line, editing my code in Kate, the default text editor for Mint 12, forced to compile my code with GCC from the terminal. This, of course, only works when I have a single source file. Now I need to learn how to write makefiles, which are notoriously confusing and ugly and require me to do all sorts of weird things and hope GCC’s -M option actually generates the right rule because the compiler itself is too stupid to figure out dependencies, but I have no IDE to tell it what to do. Then I have to link everything, and then I have to debug my program from the terminal using command line gdb, which is one of the most incredibly painful experiences I have ever had. Meanwhile, every single user experience in Linux is still terribly designed, optimized for everything except what I want to do, difficult to configure because they let you configure too much stuff and are eager to tell you in 15000 lines of manual pages about every single esoteric command no one will ever use that makes it almost impossible to find anything until you find the exact sequence of letters that will actually let you find the command your looking for and not another one that looks almost like it but does something completely different. That, of course, is if you have a web browser. I don’t know what the fuck you’d even do with man. I assume you’d have to just pipe the thing into grep just to find anything.

This is not elegant. It’s a bit sad, but mostly it’s just painful. I hate Linux. I don’t hate the kernal. I don’t hate all the functionality. It’s just that the people who use Linux do not think about user experience. They think in terms of translating command line functions into GUIs and trying desperately to hang on to whatever pretty graphics are cool and when something doesn’t work they tell you to stop using proprietary drivers from Nvidia, except the non-proprietary drivers can’t actually do 3D yet but that’s ok, no one needs that stuff. Never mind that Linux mint 12 doesn’t actually come with any diagnostic or repair tools whatsoever. Never mind that every single distro I’ve tried so far has been absolutely terrible one way or another. The more I am forced to use Linux, the more I crave for Windows and the fact that things tend to just work in Windows. Things don’t work very well in Windows, but at this point that seems better than Linux’s apparent preference of “either it works really well or it doesn’t work at all”.

We could try to point fingers, but that usually doesn’t solve anything. It’s part nvidia’s fault, it’s part software vendors fault, its partly using a 40 year old window rendering engine that’s so out of touch with reality it is truly painful, and it’s partly the users either being too dumb to care about the broken things or too smart to use the broken things. It’s a lot of people’s fault. It’s a lot of crap. I don’t know how to fix it. I do know that it is crap, and it is broken, and it makes me want to punch the next person who says Linux is better than everything in the face, repeatedly, until he is a bloody mess on the ground begging for death to relieve his pain, because there are no words for expressing how much I hate this, and if you think I’m not being fair, good for you, I don’t give a fuck. But then I can never reason with people who are incapable of listening to alternative ideas, so its usually useless to bring the topic up anyway. I suggest hundreds of tweaks to things that need to do [x] or do [x] and people are like NO THAT ISN’T NECESSARY GO AWAY YOU KNOW NOTHING. Fine. Fuck you. I’m done with this shit.

Oh wait, I still have to do my Linux homework.

EDIT: Upon further inspection, Linux Mint 12 is melting my graphics card. The graphics card fan is on, all the time, and if I run mint for too long either installed or livecd or really anything, the fan will be on the whole time and upon restart the POST check locks up. However after turning off the computer for 10 minutes and going into windows, the temperature is at 46°C, which is far below dangerous levels, so either it has a very good heatsink or the card isn’t actually melting, it’s just being run improperly, which doesn’t really make me feel any better. Either way, I am now in an even more serious situation, because I have homework to do but Linux Mint is literally breaking my computer. I’d try to fix it by switching graphics drivers but at this point every single driver available is broken. ALL OF THEM. I don’t even know what to do anymore.

*"Beware of bugs in the above code; I have only proved it correct, not tried it."* - Donald Knuth

Earlier today, I came across a post during a google-fu session that claimed that no one should use the C++ standard library function make_heap, because almost nobody uses it correctly. I immediately started mentally ranting about how utterly ridiculous this claim is, because anyone whose gone to a basic algorithm class would know how to properly use make_heap. Then I started thinking about all the programmers who don’t know what a heap is, and furthermore probably don’t even need to know.

Then I realized that both of these groups are still called programmers.

When I was a wee little lad, I was given a lot of very bad advice on proper programming techniques. Over the years, I have observed that most of the advice wasn’t actually bad advice in-of-itself, but rather it was being given without context. The current startup wave has had an interesting effect of causing a lot of hackers to realize that “performance doesn’t matter” is a piece of advice riddled with caveats and subtle context, especially when dealing with complex architectures that can interact in unexpected ways. While this broken telephone effect arising from the lack of context is a widespread problem on its own, in reality it is simply a symptom of an even deeper problem.

The word programmer covers a stupendously large spectrum of abilities and skill levels. On a vertical axis, a programmer could barely know how to use vbscript, or they could be writing compilers for Intel and developing scientific computation software for aviation companies. On a horizontal axis, they could be experts on databases, or weeding performance out of a GPU, or building concurrent processing libraries, or making physics engines, or doing image processing, or generating 3D models, or writing printer drivers, or using coffeescript, HTML5 and AJAX to build web apps, or using nginx and PHP for writing the LAMP stack the web app is sitting on, or maybe they write networking libraries or do artificial intelligence research. They are all programmers.

This is insane.

Our world is being eaten by software. In the future, programming will be a basic course alongside reading and math. You’ll have four R’s - Reading, ‘Riting, ‘Rithematic, and Recursion. Saying that one is a programmer will become meaningless because 10% or more of the population will be a programmer on some level. Already the word “programmer” has so many possible meanings it’s like calling yourself a “scientist” instead of a physicist. Yet, what other choices do we have? The only current attempt at fixing this gave a paltry 3 options that are just incapable of conveying the differences between me and someone who graduated from college with a PhD in artificial intelligence. They do multidimensional mathematical analysis and evaluation using functional languages I will never understand without years of research. I’m supposed to write incredibly fast, clever C++ and HLSL assembly while juggling complex transformation matrices to draw pretty pictures on the screen. These jobs are both extremely difficult for completely different reasons, and neither person can do the other persons job. What is good practice for one is an abhorration for the other. We are both programmers. Even within our own field, we are simply graphics programmers or AI programmers or [x] programmers.

Do you know why we have pointless language wars, and meaningless arguments about what is good in practice? Do you know why nobody ever comes to a consensus on these views except in certain circles where “practice” means the same thing to everyone? Because we are overgeneralizing ourselves. We view ourselves as a bunch of programmers who happen to specialize in certain things, and we are making the mistake of thinking that our viewpoint applies outside of our area of expertise. We are industrial engineers trying to tell chemists how to run their experiments. We are architects trying to tell English majors how to design an essay because we both use lots of paper.

This attitude is deeply ingrained in the core of computer science. The entire point of computer science is that a bunch of basic data structures can do everything you will ever need to do. It is a fallacy to try and extend this to programming in general, because it simply is not true. We are forgetting that these data structures only do everything we need to do in the magical perfect land of mathematics, and ignore all the different implementations that are built for different areas of programming, for completely different uses. Donald Knuth understood the difference between theory and implementation - we should strive to recognize the difference between theoretical and implementation-specific advice.

It is no longer enough to simply ask someone if they are a programmer. Saying a programmer writes programs is like saying a scientist does science. The difference is that botanists don’t design nuclear reactors.

I assume we’ve all heard the term “deletionism”, but for the uninitiated, it simply describes a point of view that Wikipedia should only consist of high quality articles that would be relevant to an encyclopedia. This is in stark contrast to inclusionism, which contends that anything remotely useful should be retained. These two factions have been at war for quite some time, flaring up when any particularly contentious deletion debate arises. The funny thing is that both sides are right. The catch is that they are not fighting over what should be included in Wikipedia, they are fighting over what Wikipedia is.

The problem here is a classic case of intended usage not matching up with real usage. The crux of the issue is the introduction to Wikipedia, which states “Wikipedia is a free encyclopedia”. Consequently, taking everything about Wikipedia literally, the deletionists are in fact, correct. They delete articles that do not belong in an Encyclopedia, of which the ones in question quite often would not. Sometimes they get a little overzealous, but for the most part, they’re just trying to ensure Wikipedia stays an encyclopedia.

This is a problem, because Wikipedia isn’t used as an encyclopedia. As a culture, we treat Wikipedia as nothing less than a compendium of all human knowledge. We assume you can find anything on Wikipedia, and so long as we stay within the guidelines of an Encyclopedia, we’re usually ok. Unfortunately, an encyclopedia is not a repository for the sum of all human knowledge, and thus sometimes fails to provide information that doesn’t belong in an Encyclopedia, but would still be useful. Take a look at Wikipedia’s definition of an Encyclopedia:

*An **encyclopedia** (also spelled **encyclopaedia** or **encyclopædia**) is a type of reference work, a compendium holding a summary of information from either all branches of knowledge or a particular branch of knowledge.*

It’s a summary of information from branches of knowledge. This is where we start having problems. A person who is not particularly notable is still information, but not a significant part of any branch of knowledge and therefore doesn’t belong in any extended summary of that information. However, that information could undoubtedly be useful to at least a few people, which is where the inclusionists are coming from. A compendium of all human knowledge is, well, all human knowledge. The problem is that there is a lot of it. Wikipedia has millions of articles even after being substantially trimmed down. It is clearly designed from the ground up to be an encyclopedia, not a collection of all human knowledge. In contrast, people tend to use Wikipedia as a place to store ALL information they deem even remotely relevant.

What can be done about this? Wikipedia is already suffering from growing pains as it tries to deal with millions of articles. A compendium of all human knowledge would probably have to deal with hundreds of millions of articles. How do you deal with that kind of information overload? Should you rework Wikipedia itself, or introduce something completely new? Do you suck all the Wikipedia articles out of its archives and “fork” the project? Do you start fresh and decide to require people to register before editing articles? Is a giant compendium of all human knowledge even useful? These are the questions we are going to have to answer as the amount of information continues to explode at an exponential rate. Perhaps a small startup will be able to find some answers.

You’d think that programmers would get over these ridiculous language wars. The consensus should be that any one programmer is going to use whatever language they are most comfortable with that gets the job done most efficiently. If someone knows C/C++, C#, and Java, they’re probably going to use C++ to write a console game. You can argue that language [x] is terrible because of [x], but the problem is that ALL languages are terrible for one reason or another. Every aspect of a languages design is a series of trade-offs, and if you try to criticize a language that is useful in one context because it isn’t useful in another, you are ignoring the entire concept of a trade-off.

These arguments go on for hours upon hours, about what exactly is a trade-off and what languages arguably have stupid features and what makes someone a good programer and blah blah blah blah SHUT UP. I don’t care what language you used, if your program is shit, your program is shit. I don’t care if you wrote it in Clojure or used MongoDB or used continuations and closures in whatever esoteric functional language happens to be popular right now. Your program still sucks. If someone else writes a better program in C without any elegant use of anything, and it works better than your program, they’re doing their job better than you.

I don’t care if they aren’t as good a programmer as you are, by whatever stupid, arbitrary standards you’ve invented to make yourself feel better, they’re still doing a better job than you. I don’t care if your haskell editor was written in haskell. Good for you. It sucks. It is terribly designed. It’s workflow is about as conducive as a blob of molasses on a mountain in January. I don’t care if you are using a fantastic stack of professionally designed standard libraries instead of re-inventing the wheel. That guy over there re-invented the wheel the wrong way 10 times and his program is better than yours because it’s designed with the user in mind instead of a bunch of stupid libraries. I don’t care if you’re using Mercurial over SVN or Git on Linux using Emacs with a bunch of extensions that make you super productive. Your program still sucks.

I am sick and tired of people judging programmers on a bunch of rules that don’t matter. Do you know functional programming? Do you know how to implement a LAMP stack? Obviously you don’t use C++ or anything like that, do you?

These programmers have no goddamn idea what they’re talking about. But that isn’t what concerns me. What concerns me is that programmers are so obsessed over what language is best or what tool is best or what library they should use when they should be more concerned about what their program actually DOES. They get so caught up in building whatever elegant crap they’re trying to build they completely forget what the end user experience is, especially when the end user has never used the program before. Just as you are not a slave to your tools, your program is not enslaved to your libraries.

Your program’s design should serve the user, not a bunch of data structures.

A long, long time ago, in pretty much the same place I’m sitting in right now, I was learning how one would do 2D lighting with soft shadows and discovered the age old adage in 2D graphics: linear gradient lighting looks better than mathematically correct inverse square lighting.

Strange.

I brushed it off as artistic license and perceptual trickery, but over the years, as I dug into advanced lighting concepts, nothing could explain this. It was a mystery. Around the time I discovered microfacet theory I figured it could theoretically be an attempt to approximate non-lambertanian reflectance models, but even that wouldn’t turn an exponential curve into a linear one.

This bizarre law even showed up in my 3D lighting experiments. Attempting to invoke the inverse square law would simply result in extremely bright and dark areas and would look absolutely terrible, and yet the only apparent fix I saw anywhere was simply calculating light via linear distance in clear violation of observed light behavior. Everywhere I looked, people calculated light on a linear basis, everywhere, on everything. Was it the equations? Perhaps the equations being used operated on linear light values instead of exponential ones and so only output the correct value if the light was linear? No, that wasn’t it. I couldn’t figure it out. Years and years and years would pass with this discrepancy left unaccounted for.

A few months ago I noted an article on gamma correction and assumed it was related to color correction or some other post process effect designed to compensate for monitor behavior, and put it as a very low priority research point on my mental to-do-list. No reason fixing up minor brightness problems until your graphics engine can actually render everything properly. Yesterday, though, I happened across a Hacker News posting about learning modern 3D engine programming. Curious if it had anything I didn’t already know, I ran through its topics, and found this. Gamma correction wasn’t just making the scene brighter to fit with the monitor, it was compensating for the fact that most images are actually already gamma-corrected.

In a nutshell, the brightness of a monitor is exponential, not linear (with a power of about 2.2). The result is that a linear gradient displayed on the monitor is not actually increasing in brightness linearly. Because it’s mapped to a curve, it will actually increase in brightness exponentially. This is due to the human visual system processing luminosity on a logarithmic scale. The curve in question is this:

Gamma Response Curve
Source: GPU Gems 3 - Chapter 24: The Importance of Being Linear

You can see the effect in this picture, taken from the article I mentioned: Linear Curve

The thing is, I always assumed the top linear gradient was a linear gradient. Sure it looks a little dark, but hey, I suppose that might happen if you’re increasing at 25% increments, right? WRONG. The bottom strip is a true linear gradient1. The top strip is a literal assignment of linear gradient RGB values, going from 0 to 62 to 126, etc. While this is, digitally speaking, a mathematical linear gradient, what happens when it gets displayed on the screen? It gets distorted by the CRT Gamma curve seen in the above graph, which makes the end value exponential. The bottom strip, on the other hand, is gamma corrected - it is NOT a mathematical linear gradient. It’s values go from 0 to 134 to 185. As a result, when this exponential curve is displayed on your monitor, it’s values are dragged down by the exact inverse exponential curve, resulting in a true linear curve. An image that has been “gamma-corrected” in this manner is said to exist in sRGB color space.

The thing is, most images aren’t linear. They’re actually in the sRGB color space, otherwise they’d look totally wrong when we viewed them on our monitors. Normally, this doesn’t matter, which is why most 2D games simply ignore gamma completely. Because all a 2D engine does is take a pixel and display it on the screen without touching it, if you enable gamma correction you will actually over-correct the image and it will look terrible. This becomes a problem with image editing, because digital artists are drawing and coloring things on their monitors and they try to make sure that everything looks good on their monitor. So if an artist were visually trying to make a linear gradient, they would probably make something similar to the already gamma-corrected strip we saw earlier. Because virtually no image editors linearize images when saving (for good reason), the resulting image an artist creates is actually in sRGB color space, which is why only turning on gamma correction will usually simply make everything look bright and washed out, since you are normally using images that are already gamma-corrected. This is actually good thing due to subtle precision issues, but it creates a serious problem when you start trying to do lighting calculations.

The thing is, lighting calculations are linear operations. It’s why you use Linear Algebra for most of your image processing needs. Because of this, when I tried to use the inverse-square law for my lighting functions, the resulting value that I was multiplying on to the already-gamma-corrected image was not gamma corrected! In order to do proper lighting, you would have to first linearize the gamma-corrected image, perform the lighting calculation on it, and then re-gamma-correct the end result.

Wait a minute, what did we say the gamma curve value was? It’s $$ x^{2.2} $$, so $$ x^{0.45} $$ will gamma-correct the value $$ x $$. But the inverse square law states that the intensity of a light is actually $$ \frac{1}{x^2} $$, so if you were to gamma correct the inverse square law, you’d end up with:

\[ {\bigg(\frac{1}{x^2}}\bigg)^{0.45} = {x^{-2}}^{0.45} = x^{-0.9} ≈ x^{1} \]
That’s almost linear!2

OH MY GOD
MIND == BLOWN

That’s it! The reason I saw linear curves all over the place was because it was a rough approximation to gamma correction! The reason linear lighting looks good in a 2D game is because its actually an approximation to a gamma-corrected inverse-square law! Holy shit! Why didn’t anyone ever explain this?!3 Now it all makes sense! Just to confirm my findings, I went back to my 3D lighting experiment, and sure enough, after correcting the gamma values, using the inverse square law for the lighting gave correct results! MUAHAHAHAHAHAHA!

For those of you using OpenGL, you can implement gamma correction as explained in the article mentioned above. For those of you using DirectX9 (not 10), you can simply enable D3DSAMP_SRGBTEXTURE on whichever texture stages are using sRGB textures (usually only the diffuse map), and then enable D3DRS_SRGBWRITEENABLE during your drawing calls (a gamma-correction stateblock containing both of those works nicely). For things like GUI, you’ll probably want to bypass the sRGB part. Like OpenGL, you can also skip D3DRS_SRGBWRITEENABLE and simply gamma-correct the entire blended scene using D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION in the Present() call, but this has a lot of caveats attached. In DirectX10, you no longer use D3DSAMP_SRGBTEXTURE. Instead, you use an sRGB texture format (see this presentation for details).


1 or at least much closer, depending on your monitors true gamma response
2 In reality I'm sweeping a whole bunch of math under the table here. What you really have to do is move the inverse square curve around until it overlaps the gamma curve, then apply it, and you'll get something that is roughly linear.
3 If this is actually standard course material in a real graphics course, and I am just *really bad* at finding good tutorials, I apologize for the palm hitting your face right now.

Unrelated note: If you title your article “[x] considered harmful”, you are a horrible person with no originality. Stop doing it.

Signed integers have always bugged me. I’ve seen quite a bit of signed integer overuse in C#, but it is most egregious when dealing with C/C++ libraries that, for some reason, insist on using for(int i = 0; i < 5; ++i). Why would you ever write that? i cannot possibly be negative and for that matter shouldn’t be negative, ever. Use for(unsigned int i = 0; i < 5; ++i), for crying out loud.

But really, that’s not a fair example. You don’t really lose anything using an integer for the i value there because its range isn’t large enough. The places where this become stupid are things like using an integer for height and width, or returning a signed integer count. Why on earth would you want to return a negative count? If the count fails, return an unsigned -1, which is just the maximum possible value for your chosen unsigned integral type. Of course, certain people seem to think this is a bad idea because then you will return the largest positive number possible. What if they interpret that as a valid count and try to allocate 4 gigs of memory? Well gee, I don’t know, what happens when you try to allocate -1 bytes of memory? In both cases, something is going to explode, and in both cases, its because the person using your code is an idiot. Neither way is more safe than the other. In fact, signed integers cause far more problems then they solve.

One of the most painfully obvious issues here is that virtually every single architecture in the world uses the two’s complement representation of signed integers. When you are using two’s complement on an 8-bit signed integer type (a char in C++), the largest positive value is 127, and the largest negative value is -128. That means a signed integer can represent a negative number so large it cannot be represented as a positive number. What happens when you do (char)abs(-128)? It tries to return 128, which overflows back to… -128. This is the cause of a host of security problems, and what’s hilarious is that a lot of people try to use this to fuel their argument that you should use C# or Java or Haskell or some other esoteric language that makes them feel smart. The fact is, any language with fixed size integers has this problem. That means C# has it, Java has it, most languages have it to some degree. This bug doesn’t mean you should stop using C++, it means you need to stop using signed integers in places they don’t belong. Observe the following code:

if (*p == '*')
  {
    ++p;
    total_width += abs (va_arg (ap, int));
  }

This is retarded. Why on earth are you interpreting an argument as a signed integer only to then immediately call abs() on it? So a brain damaged programmer can throw in negative values and not blow things up? If it can only possibly be valid when it is a positive number, interpret it as a unsigned int. Even if someone tries putting in a negative number, they will serve only to make the total_width abnormally large, instead of potentially putting in -128, causing abs() to return -128 and creating a total_width that is far too small, causing a buffer overflow and hacking into your program. And don’t go declaring total_width as a signed integer either, because that’s just stupid. Using an unsigned integer here closes a potential security hole and makes it even harder for a dumb programmer to screw things up1.

I can only attribute the vast overuse of int to programmer laziness. unsigned int is just too long to write. Of course, that’s what typedef’s are for, so that isn’t an excuse, so maybe they’re worried a programmer won’t understand how to put a -1 into an unsigned int? Even if they didn’t, you could still cast the int to an unsigned int to serve the same purpose and close the security hole. I am simply at a loss as to why I see int’s all over code that could never possibly be negative. If it could never possibly be negative, you are therefore assuming that it won’t be negative, so it’s a much better idea to just make it impossible for it to be negative instead of giving hackers 200 possible ways to break your program.

1 There's actually another error here in that total_width can overflow even when unsigned, and there is no check for that, but that's beyond the scope of this article.

They’re teaching it wrong.

And I don’t just mean teaching the concepts incorrectly (although they do plenty of that), I mean their teaching priorities are completely backwards. Set Theory is really fun. Basic Set Theory can be taught to someone without them needing to know how to add or subtract. We teach kids Venn Diagrams but never teach them all the fun operators that go with them? Why not? You say they won’t understand? Bullshit. If we can teach third graders binary, we can teach them set theory. We take forever to get around to teaching algebra to kids, because its considered difficult. If something is a difficult conceptual leap, then you don’t want to delay it, you want to introduce the concepts as early as possible. I say start teaching kids algebra once they know basic arithmetic. They don’t need to know how to do crazy weird stuff like x * x = x² (they don’t even know what ² means), but you can still introduce them to the idea of representing an unknown value with x. Then you can teach them exponentiation and logs and all those other operators first in the context of numbers, and then in the context of unknown variables. Then algebra isn’t some scary thing that makes all those people who don’t understand math give up, its something you simply grow up with.

In a similar manner, what the hell is with all those trig identities? Nobody memorizes those things! You memorize like, 2 or 3 of them, and almost only ever use sin² + cos² = 1. In a similar fashion, nobody ever uses integral trig identities because if you are using them you should have converted your coordinate system to polar coordinates, and if you can’t do that then you can just look them up for crying out loud. Factoring and completing the square can be useful, but forcing students to do these problems over and over when they almost never actually show up in anything other than spoon-fed equations is insane.

Partial Fractions, on the other hand, are awesome and fun and why on earth are they only taught in intermediate calculus?! Kids are ALWAYS trying to pull apart fractions like that, and we always tell them to not do it - why not just teach them the right way to do it? By the time they finally got around to teaching me partial fractions, I was thinking that it would be some horrifically difficult, painful, complex process. It isn’t. You just have to follow a few rules and then 0 out some functions. How can that possibly be harder than learning the concept of differentiation? And its useful too!

Lets say we want to teach someone basic calculus. How much do they need to know? They need to know addition, subtraction, division, multiplication, fractions, exponentiation, roots, algebra, limits, and derivatives. You could teach someone calculus without them knowing what sine and cosine even are. You could probably argue that, with proper teaching, calculus would be about as hard, or maybe a little harder, than trigonometry. Trigonometry, by the way, has an inordinate amount of time spent on it. Just tell kids how right triangles work, sine/cosine/tangent, SOHCAHTOA, a few identities, and you’re good. You don’t need to know scalene and isosceles triangles. Why do we even have special names for them? Who gives a shit if a triangle has sides of the same length? Either its a right triangle and its useful or its not a right triangle and you have to do some crazy sin law shit that usually means your algorithm is just wrong and so the only time you ever actually need to use it you can just look up the formula because it is a obtuse edge case that almost never comes up.

Think about that. We’re grading kids by asking them to solve edge cases that never come up in reality and grading how well they are in math based off of that. And then we’re confused when they complain about math having no practical application? Well duh. The sheer amount of time spent on useless topics is staggering. Calculus should be taught to high school freshman. Differential equations and complex analysis go to the seniors, and by the time you get into college you’re looking at combinatorics and vector analysis, not basic calculus.

I have already seen some heavily flawed arguments against this. Some people say that people aren’t interested in math, so this will never work. Since I’m saying that teaching kids advanced concepts early on will make them interested in math, this is a circular argument and invalid. Other people claim that the kids will never understand because of some bullshit about needing logical constructs, which just doesn’t make sense because you should still introduce the concepts. Introducing a concept early on and having the student be confused about it is a good thing because it means they’ll try to work it out over time. The more time you give them, the more likely it will click. Besides, most students aren’t understanding algebra with the current system anyway, so I fail to see the point of that argument. It’s not working now so don’t try to change it or you’ll make it worse? That’s just pathetic.

TL;DR: Stop teaching kids stupid, pointless math they won’t need and maybe they won’t rightfully conclude that what they are being taught is useless.

When I complain to my friends about a recent spat of not being productive, they often remind me of the occasional 10 hours I spend forgetting to eat while hunting down a bug. When introducing myself, I am always clear that, most of the time, I am either busy, or trying to be busy. Everything to me is work, everything that makes me proud of myself is work, everything in my future will, hopefully, be more work. The entire concept of retiring to me is madness. I never want to stop working.

This is often mistaken as an unhealthy obsession with work, which is not entirely true. I am not torturing myself every day for 10 hours just so I can prove myself, I’m doing exactly what I want to do. I’m 21 years old, I can drink and smoke (but never do), I can drive (but I take the bus anyway), I go to college (but rarely attend classes), and in general am supposed to be an adult. Most people my age are finishing college and inevitably taking low paying jobs while they search for another low paying internship at a company so they can eventually get a high paying job that actually uses what they learned in college after they’re too old to care.

If I really wanted, I could be at Facebook or Microsoft right now. I even had a high school internship at Microsoft, and probably could have gotten a college one too. I could have spent my time learning all the languages the companies want you to learn, and become incredibly well-versed in everything that everyone else already knows. I could have taught myself proper documentation and proper standards and proper guidelines and kept up my goody two-shoes act for the rest of my fucking life and get congratulated for being such a well-behaved and successful clone.

Fuck that.

I am 21 years old, and I’m going to spend it doing what I like doing, working on the projects I want to work on, and figuring out a way to make a living out of it even if I have to live out of my parents house for another 6 months. I am not going to get a job doing what other people tell me is important. While I am often very critical of myself as a person, realistically speaking, my only regrets are the moments I spent not working, or wasting time on things that weren’t important. It doesn’t matter that I’ve been working on a project most people dismiss as a childish fantasy since I was 18. It doesn’t matter that I have no income and no normal job and no programming skills that would get me hired at a modern tech company because everyone hates C++ and only cares about web development.

I’m not working on something a CEO thinks is important, I’m working on something I think is important. I’m going to start a company so I can continue to work on what I think is important, and every single employee I will ever hire will work on something they think is important. This doesn’t necessarily mean its fun - finding a rogue typecast is anything but fun - but rather its something that you are willing to ride the highs and lows through because it is intrinsically important to you, as a person. You should not wait until you’re 35 with a family and a wife to worry about. Do it now. Do whatever is necessary to make it possible for you start working on whatever you think is important and then do it so hard you can make a living out of it.

Don’t waste the best 10 years of your life working on someone else’s dream.

(don’t waste 10 years of your life forgetting to eat, either. That just isn’t healthy)

[ 1 · 2 · 3 · 4 · 5 · 6 · 7 ]

Classes in C#, like most object-oriented languages, are very similar to their C++ counterparts. They are declared with class, exist between brackets and inherit classes using a colon ':'. Note, however, that all classes in C++ must end with a semicolon! You will forget this semicolon, and then all the things will break. You can do pretty much everything you can do with a C# class in a C++ class, except that C++ does not have partial classes, and in C++ classes themselves cannot be declared public, protected or private. Both of these features don’t exist because they are made irrelevant with how classes are declared in header files.

In C# you usually just have one code file with the class declared in it along with all the code for all the functions. You can just magically use this class everywhere else and everything is fun and happy with rainbows. As mentioned before, C++ uses header files, and they are heavily integrated into the class system. We saw before how in order to use a function somewhere else, its prototype must first be declared in the header file. This applies to both classes and pretty much everything else. You need to understand that unlike C#, C++ does not have magic dust in its compiler. In C++, it just goes down the list of .cpp files, does a bit of dependency optimization, and then simply compiles each .cpp file by taking all the content from all the headers that are included (including all the headers included in the headers) and pasting it before the actual code from the .cpp file, and compiling. This process is repeated separately for every single code file, and no order inconsistencies are allowed anywhere in the code, the headers, or even the order that the headers are included in. The compiler literally takes every single #include statement as it is and simply replaces it with the code of the header it points to, wherever this happens to be in the code. This can (and this has happened to me) result in certain configurations of header files working even though one header file is actually missing a dependency. For example:

//Rainbow.h

class Rainbow
{
  Unicorn _unicorns[5]; // 5 unicorns dancing on rainbows
}; // DO NOT FORGET THE SEMICOLON
//Unicorn.h

class Unicorn
{
  int magic;
};
//main.cpp

#include "Unicorn.h"
#include "Rainbow.h"

int main(int argc, char *argv[]) 
{
  Rainbow rainbow;
}
Compiling main.cpp will succeed in this case, even though Rainbow.h is referencing the Unicorn class without it ever being declared. The reason behind this is what happens when the compiler expands all the includes. Right before compiling main.cpp (after the preprocessor has run), main.cpp looks like this:
//main.cpp

//Unicorn.h

class Unicorn
{
  int magic;
};
//Rainbow.h

class Rainbow
{
  Unicorn _unicorns[5]; // 5 unicorns dancing on rainbows
}; // DO NOT FORGET THE SEMICOLON

int main(int argc, char *argv[]) 
{
  Rainbow rainbow;
}
It is now obvious that because Rainbow.h was included after Unicorn.h, the Unicorn reference was resolved since it was declared before Rainbow. However, had we reversed the order of the include files, we would have had an anachronism: an inconsistency in our chronological arrangement. It is very bad practice to construct headers that are dependent on the order in which they are included, so we usually resolve something like this by having Rainbow.h simply include Unicorn.h, and then it won’t matter what order they are included in.
//Rainbow.h

#include "Unicorn.h"

class Rainbow
{
  Unicorn _unicorns[5]; // 5 unicorns dancing on rainbows
};
Left as is, however, and we run into a problem. Lets try compiling main.cpp:
//main.cpp

#include "Rainbow.h"
#include "Unicorn.h"

int main(int argc, char *argv[]) 
{
  Rainbow rainbow;
}
//main.cpp

//Rainbow.h

#include "Unicorn.h"

class Rainbow
{
  Unicorn _unicorns[5]; // 5 unicorns dancing on rainbows
};
//Unicorn.h

class Unicorn
{
  int magic;
};

int main(int argc, char *argv[]) 
{
  Rainbow rainbow;
}
//main.cpp

//Rainbow.h

//Unicorn.h

class Unicorn
{
  int magic;
};

class Rainbow
{
  Unicorn _unicorns[5]; // 5 unicorns dancing on rainbows
};
//Unicorn.h

class Unicorn
{
  int magic;
};

int main(int argc, char *argv[]) 
{
  Rainbow rainbow;
}
We’ve just declared Unicorn twice! Obviously one way to solve this in our very, very simplistic example is to just remove the spurious #include statement, but this violates the unwritten rule of header files - any header file should be able to be included anywhere in any order regardless of what other header files have been included. This means that, first, any header file should include all the header files that it needs to resolve its dependencies. However, as we see here, that simply makes it extremely likely that a header file will get included 2 or 3 or maybe hundreds of times. What we need is an include guard.
//Unicorn.h

#ifndef __UNICORN_H__
#define __UNICORN_H__

class Unicorn
{
  int magic;
};

#endif
Understanding this requires knowledge of the C Preprocessor, which is what goes through and processes your code before its compiled. It is very powerful, but right now we only need to know the basics. Any statement starting with # is a preprocessor command. You will notice that #include is itself a preprocessor command, which makes sense, since the preprocessor was replacing those #include’s with the code they contained. #define lets you define a constant (or if you want to be technical, an object-like macro). It can be equal to a number or a word or just not be equal to anything and simply be in a defined state. #ifdef and #endif are just an if statement that allows the code inside of it to exist if the given constant is defined. #ifndef simply does the opposite - the code inside only exists if the given constant doesn’t exist.

So, what we do is pick a constant name that probably will never be used in anything else, like __UNICORN_H__, and put in a check to see if it is defined. The first time the header is reached, it won’t be defined, so the code inside #ifndef will exist. The next line tells the preprocessor to define __UNICORN_H__, the constant we just checked for. That means that the next time this header is included, __UNICORN_H__ will have been defined, and so the code will be skipped over. Observe:

//main.cpp

#include "Rainbow.h"
#include "Unicorn.h"

int main(int argc, char *argv[]) 
{
  Rainbow rainbow;
}
//main.cpp

//Rainbow.h

#include "Unicorn.h"

class Rainbow
{
  Unicorn _unicorns[5]; // 5 unicorns dancing on rainbows
};
//Unicorn.h

#ifndef __UNICORN_H__
#define __UNICORN_H__

class Unicorn
{
  int magic;
};

#endif

int main(int argc, char *argv[]) 
{
  Rainbow rainbow;
}
//main.cpp

//Rainbow.h

//Unicorn.h

#ifndef __UNICORN_H__
#define __UNICORN_H__

class Unicorn
{
  int magic;
};

#endif

class Rainbow
{
  Unicorn _unicorns[5]; // 5 unicorns dancing on rainbows
};
//Unicorn.h

#ifndef __UNICORN_H__
#define __UNICORN_H__

class Unicorn
{
  int magic;
};

#endif

int main(int argc, char *argv[]) 
{
  Rainbow rainbow;
}
//main.cpp

//Rainbow.h

//Unicorn.h

#ifndef __UNICORN_H__
#define __UNICORN_H__

class Unicorn
{
  int magic;
};

#endif

class Rainbow
{
  Unicorn _unicorns[5]; // 5 unicorns dancing on rainbows
};
//Unicorn.h

#ifndef __UNICORN_H__
#endif

int main(int argc, char *argv[]) 
{
  Rainbow rainbow;
}
//main.cpp

//Rainbow.h

//Unicorn.h


class Unicorn
{
  int magic;
};


class Rainbow
{
  Unicorn _unicorns[5]; // 5 unicorns dancing on rainbows
};
//Unicorn.h


int main(int argc, char *argv[]) 
{
  Rainbow rainbow;
}
Our problem is solved! However, note that //Unicorn.h was left in, because it was outside the include guard. It is absolutely critical that you put everything inside your include guard (ignoring comments), or it will either not work properly or be extremely inefficient.
//Rainbow.h

#include "Unicorn.h"

#ifndef __RAINBOW_H__ //WRONG WRONG WRONG WRONG WRONG
#define __RAINBOW_H__

class Rainbow
{
  Unicorn _unicorns[5]; // 5 unicorns dancing on rainbows
};

#endif
In this case, the code still compiles, because the include guards prevent duplicate definitions, but its very taxing on the preprocessor that will repeatedly attempt to include Unicorn.h only to discover that it must be skipped over anyway. The preprocessor may be powerful, but it is also very dumb and is easily crippled. The thing is slow enough as it is, so try to keep its workload to a minimum by putting your #include’s inside the include guard. Also, don’t put semicolons on preprocessor directives. Even though almost everything else in the entire language wants semicolons, semicolons in preprocessor directives will either be redundant or considered a syntax error.
//Rainbow.h

#ifndef __RAINBOW_H__
#define __RAINBOW_H__

#include "Unicorn.h" // SMILES EVERYWHERE!

class Rainbow
{
  Unicorn _unicorns[5]; // 5 unicorns dancing on rainbows
};

#endif
Ok, so now we know how to properly use header files, but not how they are used to declare classes. Let’s take a class declared in C#, and then transform it into an equivalent prototype in C++.
public class Pegasus : IComparable<Pegasus>
{
  private Rainbow rainbow;
  protected int magic;
  protected bool flying;

  const int ID=10;
  static int total=0;
  const string NAME="Pegasus";

  public Pegasus()
  {
    flying=false;
    magic=1;
    IncrementTotal();
  }
  ~Pegasus()
  {
    magic=0;
  }
  public void Fly()
  {
    flying=true;
  }
  private void Land()
  {
    flying=false;
  }
  public static string GetName()
  {
    return NAME;
  }
  private static void IncrementTotal()
  {
    ++total;
  }
  public int CompareTo(Pegasus other)
  {
    return 0;
  }
}
class Pegasus : public IComparable<Pegasus>
{
public:
  Pegasus();
  ~Pegasus();
  void Fly();
  virtual int CompareTo(Pegasus& other);
  
  static const int ID=10;
  static int total;
  static const char* NAME;

  inline static void IncrementTotal() { ++total; }

protected:
  int magic;
  bool flying;

private:
  void Land();
  
  Rainbow rainbow;
};
Immediately, we are introduced to C++’s method of dealing with public, protected and private. Instead of specifying it for each item, they are done in groups. The inheritance syntax is identical, and we’ve kept the static variables, but now only one of them is being initialized in the class. In C++, you cannot initialize a static variable inside a class unless it is a static const int (or any other integral type). Instead, we will have to initialize total and NAME when we get around to implementing the code for this class. In addition, while most of the functions do not have code, as expected, IncrementTotal does. As an aside, C# does not have static const because it considers it redundant - all constant values are static. C++, however, allows you to declare a const variable that isn’t static. While this would be useless in C#, there are certain situations where it is useful in C++.

If a given function’s code doesn’t have any dependencies unavailable in the header file the class is declared in, you can define that method in the class prototype itself. However, as I mentioned before, code in header files runs the danger of being compiled twice. While the compiler is usually good about properly instancing the class, it is usually a good idea to inline any functions defined in the header. Functions that are inline’d are embedded inside code that calls them instead of being explicitly called. That means instead of pushing arguments on to the stack and returning, the compiler simply embeds the function inside of the code that called it, like so:

#include "Pegasus.h"

// Before compilation
int main(int argc, char *argv[]) 
{
  Pegasus::IncrementTotal()
}

// After compilation
int main(int argc, char *argv[]) 
{
  ++Pegasus::total;
}
The consequence of this means that the function itself is never actually instantiated. In fact the function might as well not exist - you won’t be able to call it from a DLL because the function was simply embedded everywhere that it was used, kind of like a fancy macro. This neatly solves our issue with code in header files, and will be important later on. This also demonstrates how one accesses static variables and functions in a class. Just like before, the C# method of using . no longer works, you must use the Scope Resolution Operator (::) to access static members and functions of a class. This same operator is what allows us to declare the code elsewhere without confusing the compiler.
//Pegasus.cpp

#include "Pegasus.h"

int Pegasus::total = 0;
const char* Pegasus::NAME = "Pegasus";

Pegasus::Pegasus() : IComparable<Pegasus>(), magic(1), flying(false)
{
  IncrementTotal();
}

Pegasus::~Pegasus()
{
  magic=0;
}

void Pegasus::Fly()
{
  flying=true;
}

void Pegasus::Land()
{
  flying=false;
}

string Pegasus::GetName()
{
  return NAME;
}

int Pegasus::CompareTo(Pegasus other)
{
  return 0;
}
This looks similar to what our C# class looked like, except the functions aren’t in the class anymore. Pegasus:: tells the compiler what class the function you are defining belongs in, which allows it to assign the class function prototype to the correct implementation, just like it did with normal functions before. Notice that static is not used when defining GetName() - All function decorations (inline, static, virtual, explicit, etc.) are only allowed on the function prototype. Note that all these rules apply to static variable initialization as well; both total and NAME are resolved using Pegasus:: and don’t have the static decorator, only their type. Even though we’re using const char* instead of string, you can still initialize a constant value using = "string".

The biggest difference here is in the constructor. In C#, the only things you bother with in the constructor after the colon is either initializing a subclass or calling another constructor. In C++, you can initialize any subclasses you have along with any variables you have, including passing arguments to whatever constructors your variables might have. Most notably is the ability to initialize constant values, which means you can have a constant integer that is set to a value passed through the constructor, or based off a function call from somewhere else. Unfortunately, C++ traditionally does not allow initializing any variables in any sub-classes, nor does it allow calling any of your own constructors. C++0x partially resolves this problem, but it is not fully implemented in VC++ or other modern compilers. This blow, however, is mitigated by default arguments in functions (and by extension, constructors), which allows you to do more with fewer functions.

The order in which variables are constructed is occasionally important if there is an inter-dependency between them. While having such inter-dependencies are generally considered a bad idea, they are sometimes unavoidable, and you can take advantage of a compiler’s default behavior of initializing the values in a left to right order. While this behavior isn’t technically guaranteed, it is sufficiently reliable for you to take use of it in the occasional exceptional case, but always double-check that the compiler hasn’t done crazy optimization in the release version (usually, though, this will just blow the entire program up, so it’s pretty obvious).

Now, C# has another datatype, the struct. This is a limited datatype that cannot have a constructor and is restricted to value-types. It is also passed by-value through functions by default, unlike classes. This is very similar to how structs behaved in C, but have no relation to C++’s struct type. In C++, a struct is completely identical to a class in every way, save for one minor detail: all members of a class are private by default, while all members of a struct are public by default. That’s it. You can take any class and replace it with struct and the only thing that will change is the default access modifier.

Even though there is no direct analogue to C#’s struct, there is an implicit equivalent. If a class or struct (C++ really doesn’t care) meets the requirements of a traditional C struct (no constructor, only basic data types), then it’s treated as Plain Old Data, and you are then allowed to skip the constructor and initialize its contents using the special bracket initialization that was touched on before. Yes, you can initialize constant variables using that syntax too.

One thing I’ve skipped over is the virtual code decorator in the C++ prototype of Pegasus, which is not actually necessary, because the function is already attempting to override another virtual function declared in IComparable, which implicitly makes it virtual. However, in C#, IComparable is implemented as an interface, which is not present in C++. Of course, if you really think about it, an interface is kind of like a normal class, just with all abstract methods (ignore the inheritance issues with this for now). So, we could rewrite the C# implementation of IComparable as a class with abstract methods:

public class IComparable<T>
{
  public abstract int CompareTo(T other);
}
As it turns out, this has a direct C++ analogue:
template<class T>
class IComparable
{
public:
  virtual int CompareTo(T other)=0;
}
This virtual function, instead of being implemented, has an =0 on the end of it. That makes the function pure virtual, which is just another way of saying abstract. So the C++ version of abstract is a pure virtual function, and a C++ version of interfaces is just a class made entirely out of pure virtual functions. Just as C# prevents you from instantiating an abstract class or interface, C++ considers any class that either declares or inherits pure virtual functions without giving them code as an abstract class that cannot be instantiated. Unfortunately C++ does not have anything like sealed, override, etc., so you are on your own there. Keep in mind that public IComparable<T> could easily be replaced with protected or private for more control.

The reason C# has interfaces at all is because C# only allows you to inherit a single class, regardless of whether or not its abstract. If its got code, you can only inherit it once. Interfaces, however, have no code, and so C# lets you pile them on like candy. This isn’t done in C++, because C++ supports multiple inheritance. In C++ you can have any class inherit any other class, no matter what, but you can only instantiate a class if it provides implementations for all pure virtual functions somewhere along its inheritance line. Unfortunately, there are a lot of caveats about multiple inheritance, the most notorious being the Diamond Problem.

Let’s say you have a graphics engine that has an Image class, and that image class inherits from an abstract class that holds its position. Obviously, any image on the screen is going to have a position. Then, let’s take a physics engine, with a basic object that also inherits from an abstract class that holds its position. Obviously any physics object must have a position. So, what happens when you have a game object that is both an image and a physics object? Since the image and the physics object are in fact the same thing, both of them must have the same position at all times, but both inherit the abstract class storing position separately, resulting in two positions. Which one is the right position? When you call SetPosition, which position are you talking about?

Virtual inheritance was introduced as an attempt to solve this problem. It works by creating a single instance of a derived class for the entire inheritance change, such that both the physics object and the image share the same position, as they are supposed to. Unfortunately, it can’t resolve all the ambiguities, and it introduces a whole truckload of new problems. It has a nasty habit of being unable to resolve its own virtual functions properly and introducing all sorts of horrible weirdness. Most incredibly bizarre is a virtually inherited class’s constructor - it must be initialized in the last class in the inheritance chain, and is one of the first classes to get its constructor called, regardless of where it might be in the hierarchy. It’s destructor order is equally as bizarre. Virtual inheritance is sometimes useful for certain small utility classes that must be shared through a wide variety of situations, like a flag class. As a rule of thumb, you should only use virtual inheritance in a class that either relies on the default constructor or only offers a constructor that takes no arguments, and has no superclasses. This allows you to just slap the virtual keyword on and forget about all the wonky constructor details.

class Pegasus : virtual IComparable<Pegasus>
If you ever think you need to use virtual inheritance on something more complicated, your code is broken and you need to rethink your program’s architecture (and the compiler probably won’t be able to do it properly anyway). On a side-note, the constructors for any given object are called from the top down. That is, when your object’s constructor is called, it immediately calls all the constructors for all it’s superclasses, usually before even doing any variable initialization, and then those object constructors immediately call all their superclass constructors, and so on until the first line of code executed in your program is whatever the topmost class was. This then filters down until control is finally returned to your original constructor, such that any constructor code is only executed after all of its base classes have been constructed. The exact reverse happens for destructors, with the lowest class destructor being executed first, and after its finished, the destructors for all its base classes are called, such that a class destructor is always called while all of its base classes still exist.

Hopefully you are familiar with C#’s enum keyword. While it used to be far more limited, it has now been extended to such a degree it is identical to C++, even the syntax is the same. The only difference between the two is that the C++ version can’t be declared public, protected or private and needs to have a semicolon on the end (like everything else). Like in C#, enums, classes and structs can be embedded in classes, except in C++ they can also be embedded in structs (because structs are basically classes with a different name). Also, C++ allows you to declare an enum/class/etc. and a variable inside the class at the same time using the following syntax:

class Pegasus
{
  enum Count { Uno=2, Dos, Tres, Quatro, Cinco } variable;
  enum { Uno=2, Dos, Tres, Quatro, Cinco } var2; //When used to immediately declare a variable, enums can be anonymous
}

//Same as above
class Pegasus
{
  enum Count { Uno=2, Dos, Tres, Quatro, Cinco }; //cannot be anonymous

  Count variable;
  Count var2;
}
Unions are exclusive to C++, and are a special kind of data structure where each element occupies the same address. To understand what that means, let’s look at an example:
union //Unions are usually anonymous, but can be named
{
  struct { // The anonymity of this struct exposes its internal members.
    __int32 low;
    __int32 high;
  }
  __int64 full;
}
union
__int32 and __int64 are simply explicitly declaring 32-bit and 64-bit integers. This union allows us to either set an entire 64-bit integer, or to only set its low or high portion. This happens because the data structure is laid out as follows:

Integer Union Layout

Both low and full are mapped to the exact same place in memory. The only difference is that low is a 32-bit integer, so when you set that to 0, only the first four bytes are set to zero. high is pointing to a location in memory that is exactly 4 bytes in front of low and full. So, if low and full were located at 0x000F810, high would be located at 0x000F814. Setting high to zero sets the last four bytes to zero, but doesn’t touch the first four. Consequently, if you set high to 0, reading full would always return the same value as low, since it would essentially be constrained to a 32-bit integer. Unions, however, do not have to have matching memory layouts:

union //Unions are usually anonymous, but can be named
{
  char pink[5]
  __int32 fluffy;
  __int64 unicorns;
}
The layout of this union is:

Jagged Union Layout

Any unused space is simply ignored. This same rule would apply for any structs being used to group data. The size of the union is simply the size of its largest member. Setting all 5 elements of pink here would result in fluffy being equal to zero, and only the last 24-bits (or last 3 bytes) of unicorns be untouched. Likewise, setting fluffy to zero would zero out the first 4 elements in pink (indexes 0-3), leaving the 5th untouched. These unions are often used in performance critical areas where a single function must be able to recieve many kinds of data, but will only ever recieve a single group of data at a time, and so it would be more efficient to map all the possible memory configurations to a single data structure that is large enough to hold the largest group. Here is a real world example:

struct __declspec(dllexport) cGUIEvent
{
  cGUIEvent() { memset(this,0,sizeof(cGUIEvent)); }
  cGUIEvent(unsigned char _evt, const cVecT<int>* mousecoords, unsigned char _button, bool _pressed) : evt(_evt), subevt(0), mousecoords(mousecoords), button(_button), pressed(_pressed) {}
  cGUIEvent(unsigned char _evt, const cVecT<int>* mousecoords, unsigned short _scrolldelta) : evt(_evt), subevt(0), mousecoords(mousecoords), scrolldelta(_scrolldelta) {}
  union
 {
  struct
  {
   unsigned char evt;
   unsigned char subevt;
  };
  unsigned short realevt;
 };

  union
  {
    struct { const cVecT<int>* mousecoords; unsigned char button; bool pressed; };
    struct { const cVecT<int>* mousecoords; short scrolldelta; };
    struct { //the three ctrl/shift/alt bools (plus a held bool) here are compressed into a single byte
      bool down;
      unsigned char keycode; //only used by KEYDOWN/KEYUP
      char ascii; //Only used by KEYCHAR
      wchar_t unicode; //Only used by KEYCHAR
      char sigkeys;
    };
    struct { float value; short joyaxis; }; //JOYAXIS
    struct { bool down; short joybutton; }; //JOYBUTTON*
  };
};
Here, the GUI event is mapped to memory according to the needs of the event that it is representing, without the need for complex inheritance or wasteful memory usage. Unions are indispensable in such scenarios, and as a result are very common in any sort of message handling system.

One strange decorator that has gone unexplained in the above example is the __declspec(dllexport) class decorator. When creating a windows DLL, if you want anything to be usable by something inheriting the DLL, you have to export it. In VC++, this can be done with a module definition file (.def), which is useful if you’ll be using GetProcAddress manually, but if you are explicitly linking to a DLL, __declspec(dllexport) automatically exports the function for you when placed on a function. When placed on a class, it automatically exports the entire class. However, for anyone to utilize it, they have to have the header file. This arises to DLLs being distributed as DLLs, linker libraries (.lib), and sets of header files, usually in an “include” directory. In certain cases, only some portions of your DLL will be accessible to the outside, and so you’ll want two collections of header files - outside header files and internal ones that no one needs to know about. Consequently, utilizing a large number of C++ DLLs usually involves substantial organization of a whole lot of header files.

Due to the compiler-specific nature of DLL management, they will be covered in Part 6. For now, its on to operator overloading, copy semantics and move semantics!

Part 4: Operator Overload

If you were to write directly to the screen when drawing a bouncing circle, you would run into some problems. Because you don’t do any buffering, your user might end up with a quarter circle drawn for a frame. This can be solved through Double Buffering, which means you draw the circle on to a backbuffer, then “flip” (or copy) the completed image on to the screen. This means you will only ever send a completely drawn scene to the monitor, but you will still have tearing issues. These are caused by trying to update the monitor outside of its refresh rate, meaning you will have only finished drawing half of your new scene over the old scene in the monitor’s video buffer when it updates itself, resulting in half the scanlines on the screen having the new scene and half still having the old scene, which gives the impression of tearing.

This can be solved with Vsync, which only flips the backbuffer right before the screen refreshes, effectively locking your frames per second to the refresh rate (usually 60 Hz or 60 FPS). Unfortunately, Vsync with double buffering is implemented by simply locking up the entire program until the next refresh cycle. In DirectX, this problem is made even worse because the API locks up the program with a 100% CPU polling thread, sucking up an entire CPU core just waiting for the screen to enter a refresh cycle, often for almost 13 milliseconds. So your program sucks up an entire CPU core when 90% of the CPU isn’t actually doing anything but waiting around for the monitor.

This waiting introduces another issue - Input lag. By definition any input given during the current frame can only come up when the next frame is displayed. However, if you are using vsync and double buffering, the current frame on the screen was the LAST frame, and the CPU is now twiddling its thumbs until the monitor is ready to display the frame that you have already finished rendering. Because you already rendered the frame, the input now has to wait until the end of the frame being displayed on the screen, at which point the frame that was already rendered is flipped on to the screen and your program finally realizes that the mouse moved. It now renders yet another frame taking into account this movement, but because of Vsync that frame is blocked until the next refresh cycle. This means, if you were to press a key just as a frame was put up on the monitor, you would have two full frames of input lag, which at 60 FPS is 33 ms. I can ping a server 20 miles away with a ping of 21 ms. You might as well be in the next city with that much latency.

There is a solution to this - Triple Buffering. The idea is a standard flip mechanism commonly used in dual-thread lockless synchronization scenarios. With two backbuffers, the application can write to one and once its finished, tell the API and it will mark it for flipping to the front-buffer. Then the application starts drawing on the second, after waiting for any flipping operation to finish, and once its done, marks that for flipping to the front-buffer and starts drawing on the first again. This way, the application can draw 2000 frames a second, but only 60 of those frames actually get flipped on to the monitor using what is essentially a lockless flipping mechanism. Because the application is now effectively rendering 2000 frames per second, there is no more input lag. Problem Solved.

Except not, because DirectX implements Triple Buffering in the most useless manner possible. DirectX just treats the extra buffer as a chain, and rotates through the buffers as necessary. The only advantage this has is that it avoids waiting for the backbuffer copy operation to finish before writing again, which is completely useless in an era where said copy operation would have to be measured in microseconds. Instead, it simply ensures that vsync blocks the program, which doesn’t solve the input issue at all.

However, there is a flag, D3DPRESENT_DONOTWAIT, that forces vsync to simply return an error if the refresh cycle isn’t available. This would allow us to implement a hack resembling what triple buffering should be like by simply rolling our own polling loop and re-rendering things in the background on the second backbuffer. Problem solved!

Except not. It turns out the Nvidia and Intel don’t bother implementing this flag, forcing Vsync to block no matter what you do, and to make matters worse, this feature doesn’t have an entry in D3DCAPS9, meaning the DirectX9 API just assumes that it exists, and there is no way to check if it is supported. Of course, don’t complain about this to anyone, because of the 50% of people who asked about this who weren’t simply ignored, almost all of them were immediately accused of bad profiling, and that the Present() function couldn’t possibly be blocking with the flag on. I question the wisdom of people who ignore the fact that the code executed its main loop 2000 times with vsync off and 60 times with it on and somehow come to the conclusion that Present() isn’t blocking the code.

Either way, we’re kind of screwed now. Absolutely no feature in DirectX actually does what its supposed to do, so there doesn’t seem to be a way past this input lag.

There is, however, another option. Clever developers would note that to get around vsync’s tendency to eat up CPU cycles like a pig, one could introduce a Sleep() call. So long as you left enough time to render the frame, you could recover a large portion of the wasted CPU. A reliable way of doing this is figuring out how long the last frame took to render, then subtracting that from the FPS you want to enforce and sleep in the remaining time. By enforcing an FPS of something like 80, you give yourself a bit of breathing room, but end up finishing rendering the frame around the same time it would have been presented anyway.

By timing your updates very carefully, you can execute a Sleep() call, then update all the inputs, then render the scene. This allows you to cut down the additional lag time by nearly 50% in ideal conditions, almost completely eliminating excess input lag. Unfortunately, if your game is already rendering at or below 100 FPS, it takes you 10 milliseconds to render a frame, allowing you only 2.5 milliseconds of extra time to look for input, which is of limited usefulness. This illustrates why Intel and Nvidia are unlikely to care about D3DPRESENT_DONOTWAIT - modern games will never render fast enough for substantial input lag reduction.

Remember when implementing the Yield that the amount of time it takes to render the frame should be the time difference between the two render calls, minus the amount of time spent sleeping, minus the amount of time Present() was blocking.

As a composer, I have been on the receiving end of a lot of musical criticism - some useful, most ridiculous. I have given out quite a bit of criticism myself, but after discovering that most people aren’t interested in brutally honest opinions, I have since avoided it. However, one thing that continues to come up over and over again is someone complaining about Genres.

“This is too fast to be trance.”

“This isn’t real Drum’n’Bass.”

Sometimes people will even slam entire swathes of subgenres, like Ishkur’s rant on Epic Trance (and by extension almost anything related to it), literally accusing it as betraying the entire idea of trance: “There must be a word to describe the pain one feels when witnessing (or hearing, rather) something once pure and brilliant completely sold down the river. Sometime in the mid-90s trance decided to drop the technique of slowly introducing complicated layers and building adequate tension over long stretches, replacing them with cutesy little insta-melodies … The average attention span, way too ritalin-freaked to pay attention to the slow, brooding trance in its original form, liked the anthemic singalong tone of the NEW McTrance, and that’s why all you trance crackers are reading this right now. Not because you grew a taste for this super awesome underground music … But because trance reformed its sound and delivery to suit [YOU].”

This is repeated for something like half the listed subgenres of trance, and in fact the entire trance genre in his “Guide” is just one giant extended rant about how Trance sucks now and it used to be awesome and now we’ve all ruined it forever.

This kind of stuck-up, bigoted, brain-melting stupidity has grated against my nerves for years, half because I just don’t like stupid stuck-up dipshits, but mostly because it is simply wrong.

Genres do not define music. Genres were invented so people could find music similar to songs that they liked. That’s all. There are no rules for any genre other than “it should sound kind of like other songs in said genre”, and even then it’s commonplace to have songs associated with multiple genres. Genres are a categorization system, and nothing else. Many people try and justify their opinions by saying that they’re criticizing the classification of the song instead of the song itself, and suggesting that it should be put in some kind of subgenre instead. When the inevitable subgenre usually fails to exist because the composer is being creative like their supposed to, they’ll suggest something asinine, like “put it in Miscellaneous, that’s what its there for.”

Really? Put this obviously heavily drum’n’bass influenced song in Miscellaneous with a bunch of off-the-wall experimental stuff instead of songs that, you know, actually sound like it, just because it doesn’t conform to a bunch of imaginary rules you pulled out of your ass to “qualify” the song for the genre? Well why don’t we just invent another subgenre? We’ve only got like a couple hundred of them now, 80% of which are basically the same damn thing. People try to defend their perceived sanctity of genres, but the problem is that its all bullshit. Let’s remind ourselves, why do genres exist?

Genres exist so people can find songs that sound similar to music they like. If you have a bajillion subgenres, no one’s going to be able to accurately classify every single song into its own little niche, and what’s more infuriating is that this misses the point completely. The vast majority of people do not have laser-guided musical tastes. They just listen to whatever the heck music they like. If they’re looking for a song, they don’t want to have to filter through hundreds of meaningless subgenres, because all they’re really looking for is something like, Trance, or maybe Melodic Trance, and that’s about as qualifying as you can get while still being useful. Consequently if your song is weird, you are better off picking the closest well-known genre of music that it sounds like and slapping it in there.

And yet, it still doesn’t stop. People start throwing on ridiculous prescriptive rules like, a trance song has to be mixable, and to be club friendly you have to have 1 minute of intro with no bass, or it has to be between 116-148 BPM, or you have to use these types of instruments, or you have to do X, or X, or X. Music is art, god damn it, what matters is what a song feels like. If it feels like trance even though its flying along at 166 BPM, and a lot of people who like trance also like that song, then it belongs in trance no matter how much you complain about it. Maybe stick it in “Energy Trance”, it kinda gets the idea across, but its still Trance, so who cares, and even then this point is usually moot, because these arguments always come up on websites with either a set list of genres, or one that operates on keywords. In the former case, you can’t qualify your genre with anything more than “trance” because the only thing they offer is “Trance” and “Techno”. In the latter case, you’ll have to tag it with Trance no matter what you do because otherwise no one will ever know your song exists.

Attacking a song because of its perceived genre is the dumbest, most useless criticism you can ever give, unless the artist explicitly states that they are trying for a very specific sound, and even then its rarely a genre and usually more of an abstract concept used across several subgenres, in which case you should be referring to the idea, not the genre. People need to understand that if I slap a “Trance” label on to my song, it doesn’t automatically mean I am trying to make whatever anglicized version of “Trance” they have deluded themselves into thinking encapsulates the entire genre (which is completely different from everyone else’s), it is simply there to help them find the damn song.

[ 1 · 2 · 3 · 4 · 5 · 6 · 7 ]

We still have a lot of ground to cover on pointers, but before we do, we need to address certain conceptual frameworks missing from C# that one must be intimately familiar with when moving to C++.

Specifically, in C# you mostly work with the Heap. The heap is not difficult to understand - its a giant lump of memory that you take chunks out of to allocate space for your classes. Anything using the new keyword is allocated on the heap, which ends up being almost everything in a C# program. However, the heap isn’t the only source of memory - there is also the Stack. The Stack is best described as what your program lives inside of. I’ve said before that everything takes up memory, and yes, that includes your program. The thing is that the Heap is inherently dynamic, while the Stack is inherently fixed. Both can be re-purposed to do the opposite, but trying to get the Stack to do dynamic allocation is extremely dangerous and is almost guaranteed to open up a mile-wide security hole.

I’m going to assume that a C# programmer knows what a stack is. All you need to understand is that absolutely every single piece of data that isn’t allocated on the heap is pushed or popped off your program’s stack. That’s why most debuggers have a “stack” of functions that you can go up and down. Understanding the stack in terms of how many functions you’re inside of is ok, but in reality, there are also variables declared on the stack, including every single parameter passed to a function. It is important that you understand how variable scope works so you can take advantage of declaring things on the stack, and know when your stack variables will simply vanish into nothingness. This is where { and } come in.

int main(int argc, char *argv[])
{
  int bunny = 1;
  
  {
    int carrot=3;
    int lettuce=8;
    bunny = 2; // Legal
  }

  //carrot=2; //Compiler error: carrot does not exist
  int carrot = 3; //Legal, since the other carrot no longer exists
  
  {
    int lettuce = 0;

    { 
       //int carrot = 1; //Compiler error: carrot already defined
       int grass = 9;
       
       bunny = grass; //Still legal
       bunny = carrot; // Also legal
    }
    
    //bunny = grass; //Illegal
    bunny = lettuce; //Legal
  }
  
  //bunny = lettuce; //Illegal
}
{ and } define scope. Anything declared inside of them ceases to exist outside, but is still accessible to any additional layers of scope declared inside of them. This is a way to see your program’s stack in action. When bunny is declared, its pushed on to the stack. Then we enter our first scope area, where we push carrot and lettuce on to the stack and set bunny to 2, which is legal because bunny is still on the stack. When the scope is then closed, however, anything declared inside the scope is popped from the stack in the exact opposite order it was pushed on. Unfortunately, compiler optimization might change that order behind the scenes, so don’t rely on it, but it should be fairly consistent in debug builds. First lettuce is de-allocated (and its destructor called, if it has one), then carrot is de-allocated. Consequently, trying to set carrot to 2 outside of the scope will result in a compiler error, because it doesn’t exist anymore. This means we can now declare an entirely new integer variable that is also called carrot, without causing an error. If we visualize this as a stack, that means carrot is now directly above bunny. As we enter a new scope area, lettuce is then put on top of carrot, and then grass is put on top of lettuce. We can still assign either lettuce or carrot to bunny, since they are all on the stack, but once we leave this inner scope, grass is popped off the stack and no longer exists, so any attempt to use it causes an error. lettuce, however, is still there, so we can assign lettuce to bunny before the scope closes, which pops lettuce off the stack.

Now the only things on the stack are bunny and carrot, in that order (if the compiler hasn’t moved things around). We are about to leave the function, and the function is also surrounded by { and }. This is because a function is, itself, a scope, so that means all variables declared inside of that scope are also destroyed in the order they were declared in. First carrot is destroyed, then bunny is destroyed, and then the function’s parameters argc and argv are destroyed (however the compiler can push those on to the stack in whatever order it wants, so we don’t know the order they get popped off), until finally the function itself is popped off the stack, which returns program flow to whatever called it. In this case, the function was main, so program flow is returned to the parent operating system, which does cleanup and terminates the process.

You can declare anything that has a size determined at compile time on the stack. This means if you have an array that has a constant size, you can declare it on the stack:

int array[5]; //Array elements are not initialized and therefore are undefined!
int array[5] = {0,0,0,0,0}; //Elements all initialized to 0
//int array[5] = {0}; // Compiler error - your initialization must match the array size
You can also let the compiler infer the size of the array:

int array[] = {1,2,3,4}; //Declares an array of 4 ints on the stack initialized to 1,2,3,4
Not only that, but you can declare class instances and other objects on the stack.

Class instance(arg1, arg2); //Calls a constructor with 2 arguments
Class instance; //Used if there are no arguments for the constructor
//Class instance(); //Causes a compiler error! The compiler will think its a function.
In fact, if you have a very simple data structure that uses only default constructors, you can use a shortcut for initializing its members. I haven’t gone over classes and structs in C++ yet (See Part 3), but here is the syntax anyway:

struct Simple
{
  int a;
  int b;
  const char* str;
};

Simple instance = { 4, 5, "Sparkles" };
//instance.a is now 4
//instance.b is now 5
//instance.str is now "Sparkles"
All of these declare variables on the stack. C# actually does this with trivial datatypes like int and double that don’t require a new statement to allocate, but otherwise forces you to use the Heap so its garbage collector can do the work.

Wait a minute, stack variables automatically destroy themselves when they go out-of-scope, but how do you delete variables allocated from the Heap? In C#, you didn’t need to worry about this because of Garbage Collection, which everyone likes because it reduces memory leaks (but even I have still managed to cause a memory leak in C#). In C++, you must explicitly delete all your variables declared with the new keyword, and you must keep in mind which variables were declared as arrays and which ones weren’t. In both C# and C++, there are two uses of the new keyword - instantiating a single object, and instantiating an array. In C++, there are also two uses of the delete keyword - deleting a single object and deleting an array. You cannot mix up delete statements!

int* Fluffershy = new int();
int* ponies = new int[10];

delete Fluffershy; // Correct
//delete ponies; // WRONG, we should be using delete [] for ponies
delete [] ponies; // Just like this
//delete [] Fluffershy; // WRONG, we can't use delete [] on Fluffershy because we didn't
                        // allocate it as an array.

int* one = new int[1];

//delete one; // WRONG, just because an array only has one element doesn't mean you can
              // use the normal delete!
delete [] one; // You still must use delete [] because you used new [] to allocate it.
As you can see, it is much easier to deal with stack allocations, because they are automatically deallocated, even when the function terminates unexpectedly. [std::auto_ptr](http://www.cplusplus.com/reference/std/memory/auto_ptr/) takes advantage of this by taking ownership of a pointer and automatically deleting it when it is destroyed, so you can allocate the auto_ptr on the stack and benefit from the automatic destruction. However, in C++0x, this has been superseded by [std::unique_ptr](http://msdn.microsoft.com/en-us/library/ee410601.aspx), which operates in a similar manner but uses some complex move semantics introduced in the new standard. I won’t go into detail about how to use these here as its out of the scope of this tutorial. Har har har.

For those of you who like throwing exceptions, I should point out common causes of memory leaks. The most common is obviously just flat out forgetting to delete something, which is usually easily fixed. However, consider the following scenario:

void Kenny()
{
  int* kenny = new int();
  throw "BLARG";
  delete kenny; // Even if the above exception is caught, this line of code is never reached.
}

int main(int argc, char* argv[])
{
  try {
  Kenny();
  } catch(char * str) { 
    //Gotta catch'em all.
  }
  return 0; //We're leaking Kenny! o.O
}
Even this is fairly common:

int main(int argc, char* argv[])
{
  int* kitty = new int();

  *kitty=rand();
  if(*kitty==0)
    return 0; //LEAK
  
  delete kitty;
  return 0;
}
These situations seem obvious, but they will happen to you once the code becomes enormous. This is one reason you have to be careful when inside functions that are very large, because losing track of if statements may result in you forgetting what to delete. A good rule of thumb is to make sure you delete everything whenever you have a return statement. However, the opposite can also happen. If you are too vigilant about deleting everything, you might delete something you never allocated, which is just as bad:

int main(int argc, char* argv[])
{
  int* rarity = new int();
  int* spike;

  if(rarity==NULL)
  {
    spike=new int();
  }
  else
  {
    delete rarity;
    delete spike; // Suddenly, in an alternate dimension, earth ceased to exist
    return 0;
  }
  
  delete rarity; // Since this only happens if the allocation failed and returned a NULL
                 // pointer, this will also blow up.
  delete spike;
  return 0;
}
Clearly, one must be careful when dealing with allocating and destroying memory in C++. Its usually best to encapsulate as much as possible in classes that automate such things. But wait, what about that NULL pointer up there? Now that we’re familiar with memory management, we’re going to dig into pointers again, starting with the NULL pointer.

Since a pointer points to a piece of memory that’s somewhere between 0 and 4294967295, what happens if its pointing at 0? Any pointer to memory location 0 is always invalid. All you need to know is that the operating system does some magic voodoo to ensure that any attempted access of memory location 0 will always throw an error, no matter what. 1, 2, 3, and any other double or single digit low numbers are also always invalid. 0xfdfdfdfd is what the VC++ debugger sets uninitialized memory to, so that pointer location is also always invalid. A pointer set to 0 is called a Null Pointer, and is usually used to signify that a pointer is empty. Consequently if an allocation function fails, it tends to return a null pointer. Null pointers are returned when the operation failed and a valid pointer cannot be returned. Consequently, you may see this:

int main(int argc, char* argv[])
{
  int* blink = new int();
  if(blink!=0) delete blink;
  blink=0;
  return 0;
}
This is known as a safe deletion. It ensures that you only delete a pointer if it is valid, and once you delete the pointer you set the pointer to 0 to signify that it is invalid. Note that NULL is defined as 0 in the standard library, so you could also say blink = NULL.

Since pointers are just integers, we can do pointer arithmetic. What happens if you add 1 to a pointer? If you think of pointers as just integers, one would assume it would simply move the pointer forward a single byte.

Moving a Pointer 1 byte

This isn’t what happens. Adding 1 to a pointer of type integer results in the pointer moving forward 4 bytes.

Moving a Pointer 4 bytes

Adding or subtracting an integer $i$ from a pointer moves that pointer $i\cdot n$ bytes, where $n$ is the size, in bytes, of the pointer’s type. This results in an interesting parallel - adding or subtracting from a pointer is the same as treating the pointer as an array and accessing it via an index.

int main(int argc, char* argv[])
{
  int* kitties = new int[14];
  int* a = &kitties[7];
  int* b = kitties+7; //b is now the same as a
  int* c = &a[4];
  int* d = b+4; //d is now the same as c
  int* e = &kitties[11];
  int* f = kitties+11; 
  //c,d,e, and f now all point to the same location
}
So pointer arithmetic is identical to accessing a given index and taking the address. But what happens when you try to add two pointers together? Adding two pointers together is undefined because it tends to produce total nonsense. Subtracting two pointers, however, is defined, provided you subtract a smaller pointer from a larger one. The reason this is allowed is so you can do this:

int main(int argc, char* argv[])
{
  int* eggplants = new int[14];
  int* a = &eggplants[7];
  int* b = eggplants+10;
  int diff = b-a; // Diff is now equal to 3
  a += (diff*2); // adds 6 to a, making it point to eggplants[13]
  diff = a-b; // diff is again equal to 3
  diff = a-eggplants; //diff is now 13
  ++a; //The increment operator is valid on pointers, and operates the same way a += 1 would
  // So now a points to eggplants[14], which is not a valid location, but this is still
  // where the "end" of the array technically is.
  diff = a-eggplants; // Diff now equals 14, the size of the array
  --b; // Decrement works too
  diff = a-b; // a is pointing to index 14, b is pointing to 9, so 14-9 = 5. Diff is now 5.
  return 0;
}
There is a mistake in the code above, can you spot it? I used a signed integer to store the difference between the two pointers. What if one pointer was above 2147483647 and the other was at 0? The difference would overflow! Had I used an unsigned integer to store the difference, I’d have to be really damn sure that the left pointer was larger than the right pointer, or the negative value would also overflow. This complexity is why you have to goad windows into letting your program deal with pointer sizes over 2147483647.

In addition to arithmetic, one can compare two pointers. We already know we can use == and !=, but we can also use < > <= and >=. While you can get away with comparing two completely unrelated pointers, these comparison operators are usually used in a context like the following:

int main(int argc, char* argv[])
{
  int* teapots = new int[15];
  int* end = teapots+15;
  for(int* s = teapots; s<end; ++s)
    *s = 0;
  return 0;
}
Here the for loop increments the pointer itself rather than an index, until the pointer reaches the end, at which point it terminates. But, what if you had a pointer that didn’t have any type at all? void* is a legal pointer type, that any pointer type can be implicitly converted to. You can also explicitly cast void* to any pointer type you want, which is why you are allowed to explicitly cast any pointer type to another pointer type (int* p; short* q = (short*)p; is entirely legal). Doing so, however, is obviously dangerous. void* has its own problems, namely, how big is it? The answer is, you don’t know. Any attempt to use any kind of pointer arithmetic with a void* pointer will cause a compiler error. It is most often used when copying generic chunks of memory that only care about size in bytes, and not what is actually contained in the memory, like memcpy().

int main(int argc, char* argv[])
{
  int* teapots = new int[15];
  void* p = (void*)teapots;
  p++; // compiler error
  unsigned short* d = (unsigned short*)p;
  d++; // No compiler error, but you end up pointing to half an integer
  d = (unsigned short*)teapots; // Still valid
  return 0;
}
Now that we know all about pointer manipulation, we need to look at pointers to pointers, and to anchor this in a context that actually makes sense, we need to look at how C++ does multidimensional arrays. In C#, multidimensional arrays look like this:

int[,] table = new int[4,5];
C++ has a different, but fairly reasonable stack-based syntax. When you want to declare a multidimensional array on the heap, however, things start getting weird:

int unicorns[5][3]; // Well this seems perfectly reasonable, I wonder what-
  int (*cthulu)[50] = new int[10][50]; // OH GOD GET IT AWAY GET IT AWAAAAAY...!
  int c=5;
  int (*cthulu)[50] = new int[c][50]; // legal
  //int (*cthulu)[] = new int[10][c]; // Not legal. Only the leftmost parameter
                                      // can be variable
  //int (*cthulu)[] = new int[10][50]; // This is also illegal, the compiler is not allowed
                                       // to infer the constant length of the array.
Why isn’t the multidimensional array here just an int**? Clearly if int* x is equivalent to int x[], shouldn’t int** x be equivalent to int x[][]? Well, it is - just look at the main() function, its got a multidimensional array in there that can be declared as just char** argv. The problem is that there are two kinds of multidimensional arrays - square and jagged. While both are accessed in identical ways, how they work is fundamentally different.

Let’s look at how one would go about allocating a 3x5 square array. We can’t allocate a 3x5 chunk out of our computer’s memory, because memory isn’t 2-dimensional, its 1-dimensional. Its just freaking huge line of bytes. Here is how you squeeze a 2-dimensional array into a 1-dimensional line:

Allocating a 3x5 array

As you can see, we just allocate each row right after the other to create a 15-element array ($5\cdot 3 = 15$). But then, how do we access it? Well, if it has a width of 5, to access another “row” we’d just skip forward by 5. In general, if we have an $n$ by $m$ multidimensional array being represented as a one-dimensional array, the proper index for a coordinate $(x,y)$ is given by: array[x + (y*n)]. This can be extended to 3D and beyond but it gets a little messy. This is all the compiler is really doing with multidimensional array syntax - just automating this for you.

Now, if this is a square array (as evidenced by it being a square in 2D or a cube in 3D), a jagged array is one where each array is a different size, resulting in a “jagged” appearance:

Jagged array visualization

We can’t possibly allocate this in a single block of memory unless we did a lot of crazy ridiculous stuff that is totally unnecessary. However, given that arrays in C++ are just pointers to a block of memory, what if you had a pointer to a block of memory that was an array of pointers to more blocks of memory?

Jagged array pointers

Suddenly we have our jagged array that can be accessed just like our previous arrays. It should be pointed out that with this format, each inner-array can be in a totally random chunk of memory, so the last element could be at position 200 and the first at position 5 billion. Consequently, pointer arithmetic only makes sense within each column. Because this is an array of arrays, we declare it by creating an array of pointers. This, however, does not initialize the entire array; all we have now is an array of illegal pointers. Since each array could be a different size than the other arrays (this being the entire point of having a jagged array in the first place), the only possible way of initializing these arrays is individually, often by using a for loop. Luckily, the syntax for accessing jagged arrays is the exact same as with square arrays.

int main(int argc, char* argv[])
{
  int** jagged = new int*[5]; //Creates an array of 5 pointers to integers.
  for(int i = 0; i < 5; ++i)
  {
    jagged[i] = new int[3+i]; //Assigns each pointer to a new array of a unique size
  }
  jagged[4][1]=0; //Now we can assign values directly, or...
  int* second = jagged[2]; //Pull out one column, and
  second[0]=0; //manipulate it as a single array

  // The double-access works because of the order of operations. Since [] is just an
  // operator, it is evaluated from left to right, like any other operator. Here it is
  // again, but with the respective types that each operator resolves to in parenthesis.
  ( (int&) ( (int*&) jagged[4] ) [1] ) = 0;
}
As you can see above, just like we can have pointers to pointers, we can also have references to pointers, since pointers are just another data type. This allows you to re-assign pointer values inside jagged arrays, like so: jagged[2] = (int*)kitty. However, until C++0x, those references didn’t have any meaningful data type, so even though the compiler was using int*&, using that in your code will throw a compiler error in older compilers. If you need to make your code work in non-C++0x compilers, you can simply avoid using references to pointers and instead use a pointer to a pointer.
int* bunny;
int* value = new int[5];

int*& bunnyref = bunny; // Throws an error in old compilers
int** pbunny = &bunny; // Will always work
bunnyref = value; // This does the same exact thing as below.
*pbunny = value;

// bunny is now equal to value
This also demonstrates the other use of a pointer-to-pointer data type, allowing you to remotely manipulate a pointer just like a pointer allows you to remotely manipulate an integer or other value type. So obviously you can do pointers to pointers to pointers to pointers to an absurd degree of lunacy, but this is exceedingly rare so you shouldn’t need to worry about it. Now you should be strong in the art of pointer-fu, so our next tutorial will finally get into object-oriented techniques in C++ in comparison to C#. Part 3: Classes and Structs and Inheritance OH MY!

Radians are used in almost everything that involves computers, and often come up in mathematical equations. However, most people are used to measuring angles in degrees, even though degrees (unlike radians) are a completely arbitrary measurement. To understand Radians, you need to understand $$ \pi $$, or more precisely, why it sucks. Like a black hole, except black holes don’t actually suck, they just warp space-time so you fall into them OK BACK ON TOPIC:

$$ \pi $$ is the ratio of a circle’s diameter to its circumference. This is retarded. When was the last time you thought of a circle using its diameter for crying out loud? We define circles, and should intuitively think of circles using their radius, which is the distance from the center to any point on the edge of the circle.

Circle

source: wikimedia commons

So that means that the ratio of the radius to the circumference is actually $$ 2\cdot\pi $$. This is why the formula for the circumference of a circle is $$ 2\cdot\pi\cdot r $$. In fact, its why we end up using $$ 2\cdot\pi $$ almost everywhere, because we almost always define circles with the radius, but $$ \pi $$ is in relation to the diameter. Which is just stupid, and is in fact so stupid that some people are currently trying to define $$ \tau $$ (Tau) such that $$ \tau = 2\cdot\pi $$. Sadly, $$ 2\pi $$ still rules the world. I guess mathematicians really like pie…?

Either way, we must work within our constaints. So, keeping in mind that $$ 2\pi $$ is the ratio between a circle’s circumference and its radius, what happens if you have a unit circle (a circle with a radius of 1)? Well, that means it has a diameter of 2, so if you roll it out on the number line, you get this:

2 Pi unrolled
source: wikimedia commons

When we talk about rotation and angles in radians, we are using the following relation:

\[ 360^{\circ} = 2\pi\;rad \]
That is, in radians, or $$ rad $$ as it is commonly abbreviated, a full rotation is $$ 2\pi $$ because that’s the circumference of a circle with a radius of 1. Radius → Radians. We know why its $$ 2\pi $$ instead of just $$ pi $$, because $$ pi $$ is stupid. If you want, you can say that $$ \tau = 2\pi $$, so that $$ \tau $$ is then equal to the ratio between a circle’s radius and its circumference. Then we get the much nicer relation:
\[ 360^{\circ} = \tau\;rad \]
360° is just one rotation of a circle. A radian is simply how far around the circumference of a unit circle you want to go. So that means 180° is halfway around the circle, which is $$ \tau/2 $$ or just $$ \pi $$ radians.
DegreesRadians
360°$$2\pi$$
180°$$\pi$$
90°$$\frac{\pi}{2}$$
60°$$\frac{\pi}{3}$$
45°$$\frac{\pi}{4}$$
30°$$\frac{\pi}{6}$$
This gives rise to the conversion functions:
\[ \begin{aligned} rad = deg \cdot \left(\frac{\pi}{180}\right) \\ deg = rad \cdot \left(\frac{180}{\pi}\right) \end{aligned} \]
But these simply arise out of $$ 2\pi $$ being simplified:
\[ \begin{aligned} rad = deg \cdot \left(\frac{2\pi}{360}\right) \\ deg = rad \cdot \left(\frac{360}{2\pi}\right) \end{aligned} \]
So now we have an intuitive explanation of what radians are - the distance around the circumference of the unit circle.

[ 1 · 2 · 3 · 4 · 5 · 6 · 7 ]

When moving from C# to C++, one must have a very deep knowledge of what C# is actually doing when you run your program. Doing so allows you to recognize the close parallels between both languages, and why and how they are different. This tutorial will assume you have a fairly strong grasp of C#, but may not be familiar with some of its more arcane attributes.

In C#, everything is an object, or a static member of an object. You can’t have a function just floating around willy-nilly. However, like all programs, a C# program must have an entry-point. If you have primarily done GUI-based design, you probably aren’t aware of the entry-point that is automatically generated, but it is definitely there, and like everything else, it’s part of an object. C# actually allows you to change the entry point function, but a default C# project will automatically generate a Program.cs file that looks like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace ScheduleTimer
{
  static class Program
  {
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
      Application.EnableVisualStyles();
      Application.SetCompatibleTextRenderingDefault(true);
      Application.Run(new frmMain());
    }
  }
}
static void Main() is the real entry point for your application, which simply initializes visual styles and then immediately launches the form that most C# users are accustomed to working with. Now, we can compare this with a simple “Hello World” C++ program:

#include <iostream>

int main(int argc, char *argv[])
{
  std::cout << "Hello World";
  return 0;
}
This program, to a C# user, immediately looks foreign and possibly even outright hostile. However, almost everything in it has a direct analogue in C#, despite the rather inane syntax that is being used. The most glaring example here is the insertion operator, «, because almost no one ever uses it except for in streams and the fact that it’s in a C++ Hello World program creates an absurd amount of confusion. It’s just a fancy way of doing this:

#include <iostream>

int main(int argc, char *argv[])
{
  std::cout.write("Hello World",11);
  return 0;
}
Now, counting the number of bytes you are pumping into the stream is really annoying, and that’s what the insertion operator does for you; it properly formats everything automatically. That’s all. It’s not a demon from hell bent on destroying your life, its just weird syntax. I don’t know why they don’t also have this functionality in a much easier to understand overloaded function, but there are a lot of things that they don’t do, so we’ll just have to live with it.

The main() function here serves the same exact purpose as the Main() function in C#. Strict C++ requires you to have a main() function to serve as an entry point, but various operating systems modify it and, in the case of Windows, outright replace it. As such, you will notice that your “hello world” C++ program, when built, opens in a command line. You will learn later how to prevent this by using Windows’ proprietary entry function. For those of you familiar with C#, this is exactly the same as C#’s ability to change around the entry point of the application, and you can even make a command line application in C# too by properly changing the compiler settings. The same concept applies to C++, but unlike C#, which defaults to a GUI, C++ defaults to a command line. Changing the compiler settings properly will result in a C++ program that starts in a GUI, just like C# (although unlike C#, C++ doesn’t have any help, which turns GUI programming into a complete nightmare).

So now that we have a direct analogue between C# and C++ in terms of where our application starts, we need to deal with a conceptual difference in how C# and C++ handle dependencies. In C#, your class file is just Class.cs, your helper class is Helper.cs, and both of them can call the other one provided they are in the same namespace, or if you are inheriting someone else’s, using the correct using statements to resolve the code. If these concepts are not familiar to you, you should learn more about C# before delving further into C++.

C++, on the other hand, does not do behind-the-scenes magic to help you resolve your dependencies. To understand what C++ is doing, one must understand how any compiler resolves references inside code (including C#). When the C# compiler is compiling your project, it goes through each of your code files one by one and compiles everything to an intermediate object code that will later be compiled down into the machine code (or, in this case, bytecode, since C# is an interpreted language). But wait, what if it’s compiling Class.cs before Helper.cs even though Class instantiates a Helper object and calls some functions inside of it that then instantiate another Class object? Well, what if you compiled Helper.cs first… but Helper.cs needs Class.cs to be compiled first because its instantiating a Class object inside the function that the Class object is calling! That’s a circular dependency! THIS IS IMPOSSIBLE OH GOD WE’RE GOING TO DIE No, it’s actually quite simple to deal with. Enter prototypes. If you have the following C# class:

using System;

namespace FunFunBunBuns
{
  class Class
  {
    private int _yay;
    private int _bunnies;

    // Constructor
    public Class(int yay)
    {
      _yay = yay;
      _bunnies = 0; // :C
    }

    // Destructor
    public ~Class()
    {
      _yay = 0;
    }

    public void IncrementYay()
    {
      _yay++;
    }
    
    public int MakeBunnies(int num) // :D
    {
      _bunnies = _bunnies + num;
      return _bunnies;
    }
  }
}
Making “prototypes” of these functions (which C# doesn’t have so this will be invalid syntax) would be the following:

using System;

namespace FunFunBunBuns
{
  class Class
  {
    private int _yay;
    private int _bunnies;

    // Constructor
    public Class(int yay);
    // Destructor
    public ~Class();
    public void IncrementYay();
    public int MakeBunnies(int num);
  }
}
Notice the distinct lack of code - this is how circular references get resolved. It turns out that to properly compile your program, the compiler only has to know what a function takes in as arguments, and what it returns. By treating the function as a “black box” of sorts, the compiler can ignore whatever code is inside it. Notice that this applies to constructors and destructors as well - they are simply special functions inside the class. In this manner the entire class can be treated as a bunch of black-box functions that don’t actually have any code that needs to be compiled in them. What the C# compiler does is create a bunch of these prototypes behind the scenes and feed them in front of all your code files, so it first compiles Class.cs using a prototype of the Helper class, which allows it to instantiate and use any functions that Helper defines without actually knowing the code inside them. Then, it compiles Helper.cs, compiling assigning code to the previously empty black-box functions defined in the Helper prototype, using a prototype of Class so that it can also instantiate and call functions from Class. In this way, both Helper.cs and Class.cs can be compiled in any order.

But wait, what if Class inherits Helper? In reality, this changes nothing. An important lesson here is that, in C++, you will not be able to simply ignore the fact that everything is a function. Classes are just an abstraction - in reality, inheritance, constructors, deconstructors, operators, everything is just various special functions. Python’s class syntax is interesting because requires that all class functions explicitly define the self parameter (which is identical to the this reference in C++ and C#), even the class constructor. Both C++ and C# hide all this from you, so Constructors and Destructors and class functions all magically just work, even though underneath it all they’re just ordinary functions with a special parameter that’s hidden from view. This is, in fact, how one mimics class behavior in C, which does not have object-oriented features - simply build a struct and make a bunch of functions for it that take a “this” pointer, or a pointer to a specific struct on which the function operates. This behavior can be (needlessly) duplicated using C# - let’s transform our Class class to C-style function implementations, ignoring the slightly invalid C# syntax.

using System;

namespace FunFunBunBuns
{
  struct Class
  {
    private int _yay;
    private int _bunnies;
  };

  public Constructor(Class this, int yay)
  {
    this._yay = yay;
    this._bunnies = 0; // :C
  }

  public Destructor(Class this)
  {
    this._yay = 0;
  }

  public void IncrementYay(Class this)
  {
    this._yay++;
  }
    
  public int MakeBunnies(Class this, int num) // :D
  {
    this._bunnies = this._bunnies + num;
    return this._bunnies;
  }
}
Thankfully, we don’t have to worry about this, since thinking of class functions as functions that operate on the object is a lot more intuitive. However, one must be aware that even in inheritance scenarios, everything is just a function, or an overload of a virtual function, or something similar (if you do not know what virtual functions are, you need to learn more C# before proceeding). Consequently, our ability to declare function prototypes solves all the dependency issues, because everything is a function.

This is where we get into exactly what the #include directive is for. In C#, all your files are automatically accessible from every other file, and this isn’t a problem because compilation is nigh-instantaneous. C++ is much more intensive to compile, partially because it doesn’t have a precompiled 400 MB library of crap to work off of, and partially due to a much more complicated precompiler. That means in C++, if you want a given file to have access to another file, you have to #include that file. In our Hello World application, we are including iostream, which does not have a .h file extension on the end for stupid regulatory reasons. However, what about the file our code is in? Our code is not in a .h file, its in a .cpp file. This is where we get to a critical difference between C# and C++. While C# just has .cs files for code, C++ has two types of files: header files and code files.

.cpp == C++ (C-plus-plus) code file .h = C++ Header file

Header files contain class and function prototypes, and code files contain all the actual code. A C++ project is therefore defined entirely by a list of .cpp files that need to be compiled. Header files are just little helper files that make resolving dependencies easier. C# does this for you - C++ does not. Note that because these are technically arbitrary file distinctions, you can put whatever you want in either file type; nothing will stop you from doing #include "main.cpp", its just ridiculous and confusing. Both #include <> and #include "" are valid syntax for the #include directive, there is no real difference. Standard procedure, however, is that #include <> is used for any header files outside of your project, and #include "" is used for header files inside your project, or closely related to it.

So what we’re doing when we say #include <iostream> is that we’re including a bunch of prototypes for various input/output stream (i/o stream –> iostream) related classes defined in the standard library, which your compiler already has the corresponding .cpp implementations of built into it. So, the compiler links the application against this header file, and when you use std::cout, it just treats everything in it (including that ridiculously obtuse << operator, which is really just another function) as a black-box function.

Consequently, unless you know what your doing, you should keep code out of header files. C++ doesn’t prevent you from throwing functions that aren’t attached to classes all over the place, like C# does, so what would happen if you defined int ponies() { return 0; } in a header file that you include in two seperate .cpp files? The compiler will try to compile the function twice, and on the second time it will explode because the function it tried to put code into already had code in it, since it wasn’t a prototype! EVERYTHING DIES! So until you get to the more advanced areas of C++, don’t put code in your header files (unless you want to watch your compiler die, you monster).

At this point I want to clarify what std:: is, because it looks rather weird to a C# programmer. In C#, the . operator works on everything - you just have System.Forms.Whatever.Help.Im.Trapped.In.A.Universe.Factory.Your.Class.Member.Function() and its all good. In C++, that’s not going to work anymore. The :: operator is known as the Scope Resolution Operator. It’s a lot easier to explain if I first explain what the . operator has been demoted to. You can only use the . operator on a reference or value type of an instantiated object (basically everything you’ve ever worked with in C#). The important distinction here is that static functions cannot be accessed with the . operator anymore. This is because Static functions, along with namespaces and typedefs and everything else must use the Scope Resolution Operator. Consequently, you can think of the . operator as being demoted to just calling class functions, and everything else now uses the :: operator. So, std::cout just means that we’re access the cout class in the std namespace.

Now we just have one more hurdle to overcome with the “Hello World” application, that funky char* argv[] parameter in main(). Most C# programmers can correctly infer that it is probably an array of some sort, but we don’t know what type char* is, other than its clearly related to char.

char* is a pointer. Yes, the same scary pointers you hear about all the time. No, they aren’t really scary. In fact, you have been using similar concepts in C# all the time without actually realizing it. First, however, let’s take a hard look at what a pointer really is.

Everything in your entire program takes up memory. Since this tutorial is designed for people who know C# already, I really, really hope you already knew that. What you might not know is that all this memory has a specific location on the machine. In fact, on a 32-bit machine, every single possible location of a byte can be contained in an unsigned 32-bit integer. This is why we are currently moving to 64-bit CPUs, because an unsigned 32-bit integer can only hold up to 4294967295 possible byte locations, which amounts to 4.2 gigs of memory. That’s why you are limited to 4 gigs of RAM on a 32-bit machine, and windows has difficulty using more than 2 gigs because a lot of older programs assumed that a signed 32-bit integer was sufficient for all memory addresses, so windows has to do some funky memory paging techniques to get programs that ignore the last bit to use memory locations above 2147483647.

So, if you allocate a float, either on the stack or on the heap, it must exist somewhere within those 4294967295 possible byte locations. Consequently, lets say you want to call a function that modifies that float, but the function has to have a void return value for some arbitrary reason. If you know where in memory that float is, you can tell the function where to find the float and modify it to the desired value without ever returning a value. Here is an example C++ function doing just that (which is syntactically valid all by itself because C++ allows functions outside of classes):

void ModifyFloat(float* p)
{
  *p = 100.0;
}

int main(int argc, char* argv[])
{
  float x = 0; //x is equal to 0.0
  ModifyFloat( &x );
  // x is now equal to 100.0
}
What’s going on here? First, we have our ModifyFloat() function. This takes a pointer to a float, which is declared by adding a * to the desired type we want to make a pointer to. Remember that pointers are really just 32-bit integers (or 64-bit if you have a 64-bit operating system), but C++ assigns them a type so that if you try to assign a double to a pointer to a float, it throws an error instead of overflowing 4 extra bytes, causing a heap corruption and destroying the universe. So char* is a pointer to a char, a double* points to a double, and Helper* is a pointer to our own Helper class.

The next thing done in ModifyFloat() is *p. In this case, the * operator is the dereference operator. So unfortunately * is the multiply, pointer, and dereference operator in C++. Yes, this is retarded. I’m sorry. But what the heck does dereference even mean? It takes a pointer type and turns it into a reference. You already know what a reference is, even if you don’t realize it. In C#, you can pass a variable of your Helper class into a function, modify the class in the function, and the original variable will get modified too! This is because, by default, classes are passed by-reference in C#. That means, even though it looks identical to a variable passed by value, any changes made to the variable are in fact made to whatever variable it references. So, this idea of passing variables in by reference should be familiar to an experienced C# programmer. C++ has references too, I just haven’t gone over their syntax. Here’s a more explicit version of the function:

void ModifyFloat(float* p)
{
  float& ref_p = *p;
  ref_p = 100.0;
}
This is the exact same as the previous function, but here we can clearly see the reference. In C#, if you wanted a variable normally passed by value, like a struct, to get passed by reference, you had to override the default behavior by adding ref. In C++, a variable that is a reference to a given type is declared in a similar manner to a pointer. The & operator is used instead of *, so in this example, float& is a reference to a float. We assign it to the value produced by turning our pointer into a float reference. Then we just set our reference equal to 100.0 and it magically alters the original variable, just like it would in C#. In fact, here is the same function written in (slightly illegal) C#:

public static void ModifyFloat(ref float p)
{
  p=100.0;
}
This does the same thing, just without the pointer. In fact, we can totally ignore the pointer in C++ too, if we want (which I tend to prefer, when possible, because its a lot easier to work with):

void ModifyFloat(float& ref_p)
{
  ref_p = 100.0;
}
int main(int argc, char* argv[])
{
  float x = 0; //x is equal to 0.0
  ModifyFloat( x );
  // x is now equal to 100.0
}
Now, in this implementation, you will notice that our call to ModifyFloat is now equivalent to what it would be in C#, in that we just pass in the variable. What happened to that random & operator we had there before? The & operator is also known as the address-of operator, meaning when its applied to a variable as opposed to a type, it returns a pointer to that variable (yay, more context-dependent redundant operators). So, we could rewrite our function as follows to make it a bit more clear:

void ModifyFloat(float* p)
{
  float& ref_p = *p; //get a reference from the pointer
  ref_p = 100.0; //modify the reference
}
int main(int argc, char* argv[])
{
  float x = 0; //x is equal to 0.0
  float* p_x = &x; //get a pointer to x
  ModifyFloat( p_x ); //pass pointer into function
  // x is now equal to 100.0 
}
As we can see, pointers are just the underlying work behind references. If you ever go into Managed C++, you’ll find out that all C# references are really just pointers, but the language treats them as references so they’re hidden from you. In C++, you can have both pointers and references. It is important to note that you can only initialize a reference variable. Any subsequent operators will be applied to whatever variable its referencing, making it impossible to get the address of a reference variable or do anything to the reference variable itself - for all intents and purposes, it just is the variable it references. This is why pointers are handy - you CAN reassign the actual pointer variable while also accessing the variable its pointing to. Consequently, you can also get the address of a pointer variable, since just like any other variable, including the reference variable, it must occupy memory, and therefore has a location that you can get a pointer to (we’ll get to that syntax in a minute). But there’s one more thing…

What about arrays? In C#, arrays are actually a built-in class that has lots of fancy functions and whatnot. Interestingly, they are still of fixed size. C++ arrays are also fixed size, but they are manipulated as raw memory. Let’s compare initializing an array in C++ and initializing an array in C#:

int[] numbers = new int[5];
int* numbers = new int[5];
It should be pretty obvious at this point that arrays are pointers in C++. I can even rewrite the above in C++ using an empty array syntax, and it will be equally as valid:

int numbers[] = new int[5];
int *x*[] is identical to int* *x*. There is no difference. Observe the following modification of our original Hello World function:

int main(int argc, char** argv);
Same thing. In fact, if you watch your compiler output carefully, you might even see the compiler internally convert all the arrays to pointers when its resolving types. Now, as a C# programmer, you should already know what arrays are. You should probably also be at least dimly aware that each element of an array occupies memory directly after the element proceeding it. So, if you know where the address of the first element is, you know the second element is exactly x bytes afterwards, where x is the number of bytes your type takes up. This is why pointers have types associated with them - we know that float* points to an array of elements, and that each element takes up 4 bytes. To verify this, the sizeof() built-in function/operator/whatever will return the number of bytes a given type, class, or struct takes up. That’s the number of bytes we skip ahead to get to the next element in an array. This is all done transparently in C++ using the same array index operator as C# uses:

int main(int argc, char** argv)
{
  int* ponies = new int[5];
  ponies[0] = 1; //First element..
  ponies[1] = 2; //Second element...
}
So pointers can be treated as arrays that behave exactly the same way a C# array does. However, the astute C# programmer would ask, how do you know how long the array is?

YOU DON'T
Enter every single buffer overflow error that has been the bane of man since the beginning of time. YOU have to keep track of how long the array is, and you’d better be damn sure you don’t get it wrong. Consequently any function taking an array of variable size will also require a separate argument telling the function how many elements are in the array. Usually arrays are just constructed on the stack with a constant, known size, which is often harmless and pretty hard to screw up. If you start doing funky things with them, though, you might want to look up std::vector for an encapsulated dynamic array.

So C++ arrays are just like C# arrays, except they are pointers to the first element, and you don’t know how long they are (and they might cause the destruction of the universe if you screw up). You should already know that a string is an array, and consequently in C++ the standard string type is const char*, not string. You also can’t put them in switch() statements. Sorry.

There’s a lot of stuff about pointers that this tutorial hasn’t covered, like function pointers and pointer arithmetic, which we’ll get to next time.

Part 2: Pointers To Everything

Another website has been hacked. It seems almost routine now, with site after site getting demolished by hackers. The overwhelming public response to the catastrophe has been to ask, “can anything be made secure?” Security experts, naturally, are constantly attacking the companies in question for their dismal security practices, but what of the general public? They don’t know what a hash is. They don’t know what an SQL injection is. They have no reason to know these things and will never understand them. All they understand is that their company assured them they had good security, and then they were hacked, and somehow the good security wasn’t actually good. So then they’ll move to another company, and this time, they’re told, this company really does have good security. But nope, it got hacked too, guess that good security wasn’t actually good.

Can any security be good? A security expert knows why the companies were hacked and can answer that question - the average Joe probably won’t be able to. This is the crux of the problem - What is good security? How can an average person figure out what good security is? Good security used to be MD5 hashing. Then it was MD5 hashing with a seed. Now MD5 is cryptographically insecure, so we’re trying to move to SHA1, but even that might be crackable in the near future, so someone invented bcrypt, but now the bcrypt implementation has demonstrated some unnerving behavior, making its implementation unverified. Then there is SQL injection vulnerabilities and the long list of XSS attacks, along with cookiejacking made possible by unencrypted networks and Firesheep. Even now we are seeing weaknesses at the highest echelons of security - hacked RSA databases and even HTTPS certificates.

Answering our question of what good security is clearly isn’t easy. Of course, what if we assume that all security is broken? We would have to outlaw all hacking and seriously punish the offenders because there is nothing that can be done to lock up the system. This approach, however, is inherently flawed. For one, it is closely related to the drug war waged by the U.S. authorities, which has been astoundingly ineffective at stopping the drug trade. Not because it can’t shut down drug-rings (it’s very good at doing that), but simply because the business is so profitable that for every player you kill in the game, another one crops up to take their place. Lulzsec serves as a harbinger of that scenario, where hacking is cheap, and even if you throw everyone involved in jail, someone else will replace them.

However, even this scenario is being optimistic. If security is near impossible, computers become useless. The real world would turn into Hollywood, where electronics are easily bypassed. The problem is that if computer security is easily bypassed, people will stop using it. Online transactions die. The paper trail comes back. People refuse to put their personal details in anything that could be digitized. Everything that has enabled the technological explosion of today would get stuck in a tug-of-war between security and convenience. If history is anything to go by, the public would rather give up the last bits of their privacy just so they could use all the conveniences of electronics without having to worry about hackers. Suddenly we live in 1964.

This scenario may seem implausible to you because it is. Computer security can be effective, it simply needs to be done properly, which is not impossible. It may be difficult, but so is starting a successful company, and that doesn’t seem to stop any of the entrepreneurs. The problem we face is that the average customer has no way of discerning good security from bad security. If they could, market pressures would force companies to adapt the best security possible, or customers would take their data elsewhere. Security is crap because no one knows what security is other then the security experts.

We have building inspectors and elevator certifications and health inspectors… why not security inspectors? It doesn’t need to be government mandated, considering the government’s track record, it might be a lot better if a private company or group provided the service, but somehow, there needs to be a way to measure security in a verifiable manner. There are two ways I know of to do this (there may be others) - from the inside, and from the outside. An inside inspection is more reliable when done properly, but more likely to be corrupted and gamed. An outside inspection, however, doesn’t rely on the consent of a company to plaster a security rating on them. The downside is that an outside inspection requires pummeling the company’s product blindly, which will only catch the really stupid mistakes, and not the dangerous middle-ground between really bad security and really good security.

I’m not pretending I know how to solve this problem. I don’t, but I do know that someone needs to figure this out. If we are going to make any headway with security, the general public needs a friendly, easy, intuitive way to check the security rating of a company, instead of relying on the company’s insistence that it uses a “very sophisticated security system”. Only then will market pressures push for the resurgence of proper security.

She is fine and will make a full recovery.

About 3 weeks ago, on Thursday, May 19th, at approximately 6 PM, my mom went into ventricular fibrillation and collapsed while walking on a nearby trail. She was found by two walkers who called 911 and initiated CPR. After almost a half hour of CPR and 3 defibrillator attempts, she was stabilized and taken to the nearby hospital. She had no identification, so we didn’t know about it until after 2 hours of failed searching, at which point my dad called the local hospital.

As I was taken to see her while in critical condition, we didn’t know if she was going to survive, or if she did, if she would have serious brain damage. A lot of things went through my mind on that car ride, but the one that was the most striking was when I realized that my inability to achieve what I had been trying to do for so long could potentially mean the last thing my mom was mentally capable of processing would be a son who had simply tried to accomplish something. Who had tried very hard, but hadn’t actually managed to do anything of significance. My life was simply a lot of determination, a lot of talk, a lot of failures, and no results. I was still in college, I still didn’t have a company, I didn’t even have a job, and I still hadn’t brought any of my more spectacular ideas to fruition. I was almost 21 years old, my mom had almost died from a heart attack, and I hadn’t actually done anything.

The next day my dad called “just about everyone” to tell them what was going on, which indirectly resulted in me being reunited with one of my old friends. Due to my mom’s condition in the ICU, she had little to no short term memory, and so every day when I went to visit her I would tell her that my best friend from forever ago had visited, and every day (once the breathing tube was removed), she would react with surprise. She was very confused and kept asking about why she was in the hospital. It turns out this was a pretty good question.

They did a CT scan of her chest to see if she had any blockages or other potential threats to her heart, and discovered that her arteries were entirely devoid of plaque buildup, and she appeared to be almost perfect health, aside from the fact that her heart suddenly stopped working for what appeared to be no reason at all. The only connection we could find was that a similar event happened to my grandfather (her father) at almost the same age. While he also passed out, his episode was caused by atrial fibrillation. She has since had a miniature pacemaker of sorts installed that will automatically deliver a defibrillator shock if the event ever occurs again, but it raises questions about whether the condition is hereditary.

If this is some kind of strange genetic disorder, it carries the lovely news that even if I’m in perfect health in 30 years, my heart could get a random bad signal from my brain for absolutely no reason at all and I could keel over and die if no one happens to notice me pass out. Luckily I don’t have to worry about that until I have kids in elementary school.

Thankfully my mom is back home and, aside from some minor lingering medications and precautions, has fully recovered. Unfortunately, I still haven’t done anything.

I view religion as a symptom of humanity’s inability to operate as a rational agent. This statement will usually validate itself by being misinterpreted as an attack on religion, despite the statement itself simply stating that religion is irrational, not that it is a bad thing. Furthermore, we don’t know if irrationality is inherently bad or worse than rationality, although humanity in general seems to prefer thinking of itself as rational despite repeatedly acting in completely irrational ways, usually without knowing it.

Almost everyone nowadays has grown up with the advice that everyone is special. Most kids figured out around junior high that if everyone is special, no one is special, and some get all depressed over it (like I did). This is logically inconsistent if one examines people in terms of their unique perspectives. Every person on earth has a wholly unique outlook on life, and this is why a crowd of people will often have at least one person who can quickly and intuitively answer a question that stumps the rest of them. Their unique perspective allows them to arrive at a conclusion much faster and more accurately than the others, and so it is this perspective that makes everyone unique. This is also why perspectives are valuable: the more diverse a collection of perspectives, the more likely that one of them will figure out the solution to a given problem. This is especially important to society at large, because society by definition must confront an endless stream of problems from every imaginable background, including some backgrounds we don’t have names for yet.

The value of unique perspectives is exemplified by the Geth, a fictional race in the world of Mass Effect. Even though they were willing to destroy the Heretics for choosing a path that made it impossible for co-existence, they were reluctant to simply rewrite them so they would see their point of view because this resulted in a loss of perspective. In addition, the Geth opposed using borrowed technology because it would blind them to alternative paths. These different perspectives and possible solutions are what the Geth see as valuable. Even a perspective that is clearly wrong could potentially be valuable - the only time a perspective’s destruction can be justified is if the perspective calls for the destruction of other perspectives, which makes it incompatible with society.

On the other hand, teenage hormones also kick in during Junior High, solidifying the desire to fit in with other people, which is in direct conflict with the desire to be different and unique. The end result is that humans tend to fit in with certain social groups, and try to be different from others. These social groups meld perspectives together, so that the general result is that each social group will have its own general perspective on life that it strives to keep different from other social groups, where individual perspectives tend to meld themselves to be closer to the group. While the potential loss of unique perspectives is unfortunate, as long as there are many social groups, the end result is a diverse population of perspectives in society.

Religions, however, attempt to enforce very similar “bubbles” of perspective, which can grow very large. Monotheism, usually in the form of Christianity, is extremely common in the western world, and is so common in the United States that it has created an enormous bubble of very similar perspectives. To apply the laws of economics to the situation, Christianity is a monopoly on the capitalism of perspectives. Whereas the ideal scenario is a lot of small bubbles of perspectives “competing” with each other, a monopoly makes it much more difficult for smaller, radically different perspectives to gain hold, and actively attempts to make itself larger in any way possible. Just as a monopoly is considered a serious problem in a capitalistic economy, so is a religious monopoly on perspectives.

Some more tolerant views of religion hold that an individual should be free to worship God in whatever way they wish, so long as they are worshiping God. This has two problems, the first being that it often excludes polytheistic religions, but primarily because it always excludes atheism. Theists who believe that atheists are to be tolerated, but would prefer that they didn’t exist, are eliminating a perspective.

Consequently, atheists who simply tolerate religion are also eliminating a perspective. The simple fact is that both atheism and theism should always coexist so long as they are compatible with society and other perspectives. This means that the only rational opinion that one can have for religion is that it should be maintained as an entirely personal choice of perspective, and consequently valued as such. Of course, rationality itself is a perspective, so it would be more accurate to say that this is the only possible perspective that does not eliminate other perspectives (unless you can prove that one of the perspectives is sufficiently detrimental to society as a whole). The most valid perspectives, in general, are ones that tolerate other perspectives. Contact is on of my favorite movies, and it does a superb job of illustrating how both science and religion must coexist, and that it would be difficult for either to exist without the other. Science gives us technology, and religion gives us the faith that drives us to believe in potential discoveries before we have any actual evidence to believe them.

Differences in opinions are not problems, they are the manifestations of our unique perspective that make everyone valuable to society. Provided, of course, you aren’t screaming “DEATH TO THE INFIDELS”, because then you are trying to eliminate someone else’s perspective to the detriment of society. Because of this delicate balance between perspectives, it is up to society to decide which perspectives are too much of a danger to others. In doing so, however, we must always remember that Islam is not a single perspective, it is 1.5 billion perspectives.

So I’m rewriting my 2D culling kd-tree for my graphics engine, and a strange bug pops up. On release mode, one of the images vanished. Since it didn’t happen in debug mode, it was already a heisenbug. A heisenbug is defined as a bug that vanishes when you try to find it. It took me almost a day to trace the bug to the rebalance function. At first I thought the image had simply been removed from a node accidentally, but this wasn’t the case. It took another day to finally figure out that the numimages variable was getting set to 0, thus causing the node to think it was empty and resulted in it deleting itself and removing itself from the tree (which caused all sorts of other problems).

Unfortunately, I could not verify the tree. Any attempt that so much as touched the tree’s memory would wipe out the bug, or so I thought. Then I tried adding the verification function into an if statement that would only activate if the bug appeared - it did not. The act of adding a line of code that was never executed actually caused the bug to vanish.

I was absolutely stunned. This was completely insane. Following the advice of a friend, I was forced to assume the compiler somehow screwed something up, so I randomly disabled various optimizations in release mode. It turned out that disabling the Omit Frame Pointers optimization removed the bug. I didn’t actually know what frame pointers were, only that I had turned on this optimization in many other projects for the hell of it and it had never caused any problems (no optimizations ever should, for that matter). What I discovered was astonishing. Frame pointers couldn’t be omitted from a function if it got too complicated or needed to unwind the stack due to a possible exception. On a hunch, instead of adding the verification function to the chunk of code that was only executed if the error occurred, I instead added a vestigial 'throw "derp";' line.

The problem vanished.

I knew instantly that either the problem was caused by the omission of frame pointers, which would indicate a bug in the VC++ 2010 compiler (unlikely), or when the frame pointers were included, it masked the bug (much more likely). But I also had another piece of knowledge at my disposal - exactly how I could modify the function without masking the bug. I considered decompiling the function and forcing VC++ to use the flawed assembly, but that didn’t allow me to modify the assembly in any meaningful way. A bit more experimentation revealed that any access of the root node, or for that matter, the 'this' pointer itself (unless it was for calling a function) caused the inclusion of the frame pointer. I realized that a global variable would be exempt from this, and that I might be able to get by this limitation by assigning the address of whatever variable I needed to the global variable and passing that into the function instead.

This approach, however, failed. In fact most attempts to get around the frame pointer inclusion failed. I did, however, notice what appeared to be a separate bug in another part of the tree. A short investigation later revealed an unrelated bug in the tree caused by the solve function. However, what was causing this bug (duplicated parentC pointers) still threw up errors after solving the first bug, indicating that it was possible this mysterious insane compiler induced bug was just a symptom of a deeper one that would be easier to detect. After more hunting, a second unrelated bug was found. Clearly this tree was not nearly as stable as I had thought it was.

A third bug was eventually found, and I discovered the root cause of this bug to be an #NaN float value in the tree. This should never ever, ever happen, because it destabilizes the tree, but sure enough, I finally found the cause.

_totalremove(node->total,(const float (&)[4])currect);

Casting from a float* that was previous cast from a float[4] causes read errors at totally random times, despite this being completely valid under the circumstances. My only guess is that the compiler somehow interpreted this cast as undefined behavior and went crazy. I will never know. All I know is that I should never, ever, ever, ever, ever cast to that data type ever again, because guess what? After removing all my debug equipement and putting the cast back in, I was able to reliable reproduce the bug that started this whole mess, and removing the cast made the bug vanish.

This entire week long trek through hell was because the compiler fucked up on a goddamn variable cast. It wasn’t a memory leak, it wasn’t a buffer overrun, it was just a goddamn miscast variable.

Lesson: Re-validate every inch of your data structure the instant you realize you have a heisenbug, and make sure your validation function properly checks for all things that can screw things up.

A recent article by Jesse Stay describes how Twitter and Facebook are killing RSS. Many people point out that you don’t really need an RSS feed for either service, since the content they generate is not particularly conducive to an RSS feed. While this is strictly true if you are attempting to read the actual RSS feed, I don’t consider this the primary benefit of an RSS feed.

RSS feeds provide a way to broadcast data in a standard format, which then allows an application to be quickly constructed using an RSS parser to process that data. Since its an open standard, efficient, open-source RSS parsers propagate rapidly. This allows creative use of RSS feeds to comb vastly different types of media, and more importantly allows inter-site integration through a single API. That is, if you publish your blog on an RSS feed, scrapers on Last.fm can pick it up and display it on your artist page. The reason RSS is so valuable is because it provides a standard method of communicating contextualized data over the web.

An interesting consequence is that few people actually benefit from the human-readability of RSS. Hence, if there is ever an RSS 3.0, it would benefit greatly from a compressed machine version (perhaps utilizing something like Google’s protocol buffers) for fast and efficient data transfer. Proper caching is also important, so an RSS feed is only served up when its been updated. Being able to directly indicate data formats like video and mp3 would also help to enforce more global methods of parsing them (an example being the very useful RSS feed that Newgrounds provides on my audio page). This is a more general problem with XML based formats, however, and is best left for a separate debate.

Either way, while RSS as a standard publication method may be dying, the internet must strive to keep it available for API developers, because RSS promotes freedom of information by providing an easy way to process that information. The interconnectivity of the internet and the freedom of information that it experiences cannot be provided by a proprietary protocol. RSS hasn’t even gotten near its full potential and its already dying. Do your part to save RSS by making your website’s information accessible via RSS, even if its only in the metadata. The user interface to RSS may be facing extinction, but the information parsing it provides must not be allowed to die.

The reason I have been repeatedly rejected from the computer science major at my college is partly due to underfunded and crowded conditions, but primarily because they are letting in the wrong students. Apparently, had I gotten a 3.5 in all of my classes, I would have been in the major already. Because I instead got a 4.0 in one class and a 3.0 in another, they have rejected me. Why? Because when funding gets tight, they simply throw out anyone with inconsistent grades. Nevermind that half the time people with inconsistent grades are the ones actually passionate about something, while the people with rock solid consistent grades are simply good at getting rock solid consistent grades and don’t actually really know what they want to do, but heard that programming pays well.

Nevermind that Math 308 has been shown as the best indicator of success in computer science related math courses and I got a 3.9 in it, which is apparently very hard to do. Nevermind that the professor I talked to had tried to convince the committee to weigh student grades differently in an effort to improve the process but was ignored. Instead, I am to whore myself out to a bunch of grad students because no one wants to look at the paper I wrote until I help a bunch of other people with their papers.

Wow, this sounds familiar. It’s kind of like that academic ponzi scheme everyone’s been complaining about recently. I have to get involved in this just to get into a major to take some classes? Is this worth my time?

Sony can’t do basic security. Modern games are made of brown. User interfaces are rarely built in a user-centric fashion. Academic insistence that performance doesn’t matter dominates everything to the point that horrifically bad code is being put into production and customers are told to get new computers. These people have all gone to college, and this is the resulting mess?

I have seen many people defend academic rigor, but I believe there is a point where it becomes utterly stupid. When rigor only exists in theoretical thesis papers, the second some guy actually runs a company with a decent idea, and doesn’t screw it up, you end up with Google because they exploited an economic disparity worth hundreds of billions of dollars, created by this insane educational system that is too self-absorbed to figure out how utterly broken it is.

Google changed everything.

The theoretical papers, meanwhile, are still just papers.

I asked a non-technical friend of mine, who has been unable to play online with his PS3 recently due to the PSN outage, what he thought about practically all of his personal information being compromised due to an intrusion and questionable security. His perspective is not what I was expecting.

I'm just saying, they've been the target of hackers already, it just takes a couple members of Anonymous doing their own thing to get back in I imagine. If a hacker wants something, they usually wind up getting it somehow or other unless it's tucked in the Pentagon or some shit, or so it seems anymore. The 3DS was built to be unhackable and someone broke it in 48 hours. Nothing about any console maker told me they're the best bastions of defense. So no, it doesn't concern me one damn bit, because I've never considered anything I've ever had secure in the first place.

I have no idea what proper security is because I have no idea how that happens. I kinda cross my fingers that paypal isn’t absolute shit. It’s just not a good thing to put high hopes in when every console manufacturer has been trying to prevent hacking and piracy since such things became even remotely a problem, and have never succeeded. Thus, why expect any better from their servers. It’s also worth noting I live in a very old-fashioned part of the country, not like OLD SOUTH or anything, but enough so that nobody here has faith in security online, at all, and a lot of people still won’t order anything online because they don’t trust the sites to protect their information or not just outright steal it for themselves.

It makes it so when things like this happen, I don’t go having a little hissy over it and scolding Sony, boo hoo. Anonymous hacked the same network and a week later this happened. Nobody should be surprised, not this much, anyway. There wasn’t even much time to address the issue without it going down like this anyway, seeing as now they’ve taken down everything to rebuild the whole mess because it’s becoming a problem, obviously, but Sony fanboys will whine their brains out if the server is down at all, and Microsoft fanboys will continue to gloat that Live is better and use it as a sort of facial shit-rub. There is a lot of stigma against taking the network down, for any reason, due to the competition and entitlement of their fanbase and others, but honestly I’d have preferred this be the result after the Anonymous attack, even if everyone would’ve just bitched then too.

So there, I’m not the happiest with this, but I’m not freaking out or anything, because it doesn’t surprise me one bit, it’s just inconvinient for Portal and… well, the guy I wanted to play that with isn’t getting it anytime soon so co-op’s going to be me being an idiot with someone who’s done it 90 times by the time I get it working no matter what, so it kinda sucks anyway.

Naturally, he carries some misconceptions. Anonymous did not hack the network, it took it down with a DDoS attack. But, he didn’t even panic then even though he assumed it had been hacked and his credentials potentially stolen. He never panicked during any of this because he has never had any reason to believe that anything he is using is secure, although he hopes that PayPal has good enough security to keep him reasonably protected.

I see people in Hacker News lashing out at the video game fanboys as being clueless and only caring about being able to play their games, but the truth of the matter is that, in the perspective of a consumer, online security just flat out sucks. Its rarely implemented properly and even when it is it often fails eventually at some point, which of course everyone hears about. Sony happens to really suck at security, but its just another hacking incident to most of the PSN users. They simply never assumed that the network was secure in the first place. Even if they wanted to switch to say, Xbox Live, they can’t, because Sony has a monopoly on the games offered on the PS3. The fact that Sony still has a very large chunk of the market isn’t necessarily because consumers are stupid (although some of them clearly are), but because it has a monopoly on game selection. You can teach someone about why good security is important, but it won’t matter until they have an alternative platform on which to play their games.

So the real problem here is that, from an economic perspective, games should not be limited to a single console, because it creates a monopoly and prevents proper competition. If you want to blame something for this, blame the monopoly, not the customers. The real lesson here is not that Sony is terrible at security, but that we have allowed a dangerous monopoly to form. In a proper competitive environment, Sony would lose an absurd chunk of its customers after an incident like this. You can complain that the company is evil and the customers are stupid, but at the end of the day, its just economics.

In the past I’ve made several predictions that were dismissed, at the time, as ludicrous, but have in fact come to fruition, like the importance of having dynamic environments in games and graphics engines that can handle it. So, here I present a complete list of all the computer-related or economic predictions I currently have, along with justification:

Speed becomes paramount to all mature markets: People have been ignoring speed for as long as they can, because its apparently rather difficult for programmers to properly optimize programs. This is fine in emerging markets because no one knows how fast things can go. However, the more mature a market gets, the faster the consumer will notice speed problems - even little ones. People are really impatient, and a program that successfully combines both ease of use and extremely fast calculations will win over a bloated, slow, feature-filled one. This has become markedly apparent in the current cycle of web applications, and will soon spill over into just about everything that we use.

Arguments against this usually say that a faster processor will make slow programs go away, and that algorithms are the only things that make significant speed differences. There are a lot of technical reasons I could go into concerning why this is wrong, but there’s a much easier argument: Why have my programs gotten slower over the years as my processor speed has increased? Because programmers are getting too lazy. In fact, most of the speed increases over the years have been due to algorithmic optimizations, and yet… programs are still slow. The amount of speed you can now gain over properly building an architecture and optimizing your program is so incredibly large that it is noticeable even for comparatively large computational tasks, and hence represents an economic benefit that has yet to be exploited. It’s a little more complicated then simply making fast programs, however, involving a combination of user friendliness, speed, and avoiding feature bloat. The myth that speed doesn’t matter in programming, however, is about to start costing companies serious money if they continue to believe it.

Rasterization won’t get replaced by ray-tracing: Or rather, it won’t get replaced any time soon. There are a lot of incredibly annoying computational issues with raytracing, and a lot of them can actually be solved by combining both techniques. As a result, what will happen is a slow evolution, where ray-tracing will slowly work its way into rasterization pipelines, likely starting with variable density volumetric entities, until it eventually replaces rasterization altogether once we have more computational power then we know what to do with. This probably won’t happen for another 20 years, though.

A lot of people argue that we can do impressive amounts of raytracing even with modern computing power, and that the increased parallelism in CPUs 20 years from now will result in feasible realtime raytracing engines that can compete with modern rasterization very well. There are two problems with this: The first is that they are ignoring the fact that rasterization itself also benefits from parallelism, and as such it’s rendering quality will increase as computing power does. This usually leads into the second mistake: people argue that rasterization will simply hit a ceiling and be unable to get past it, and only raytracing can produce true photorealism. These people completely fail to understand just how much stuff can be efficiently accomplished using rasterization, and also do not understand how raytracing can be combined with rasterization to achieve almost the same amount of realism for a tiny fraction of the computing cost. Other people just don’t understand how computationally expensive the tiny nuances of photorealism are.

Low-level languages will become even more important: Lots of people want low-level languages to vanish, but due to the above speed concerns, that simply isn’t going to happen. However, business moves too fast for people to worry about low-level routines all the time, so what will happen is an increasing chasm between high speed low-level languages that are dependent on high-level languages to do complex tasks, while the high-level languages will be increasingly dependent on low-level libraries in order to deliver effective performance. Hence, language interoperability becomes incredibly important, because the programs of the future will likely be written in 2 or more languages. The ability to simply pick a language as a tool, choosing it based on what problem needs to be solved, will become invaluable. This is likely to happen very quickly, in just 5 or 10 years. At the same time, this increasingly wide division between high level and low level languages will create a vacuum that needs to be filled by…

Middle-level languages: A middle-level language will be a language that allows a programmer to quickly and efficiently write a method either in the style of low-level memory management, or high-level complexity management. This would likely be accomplished with something like D, where the programmer would be able to control and override the high-level garbage collectors and variable management whenever they desire, with little to no resistance from the language syntax. While many high-level languages today attempt to make some low-level functions available, it is often clumsy and far from complete. This language would act as an intermediate compromise between the necessary low level speed hogs and high level complexity management. This transition, however, is not going to happen for probably another 10 or 20 years, due to people needing to recognize that there is a schism in the first place, along with several engineering problems that must be confronted.

Education will soon fundamentally change: We’ve been using the same, outdated rote methods of teaching for almost 150 years, slapping on in-place attempts at more modern learning, trying to work such fundamentally incompatible methods into the existing framework that refuses to change. It is becoming so economically irrational for people to continue being schooled this way that the instant an alternative comes up, it will rapidly displace the existing system. This is already happening at a small level with Khan Academy, which I believe is precipitating a fundamental change in how we learn things. We aren’t there yet and we probably won’t be for say, 2-3 decades, but around that time we will see a huge shift in the educational paradigm.

Anti-authoritarianism becomes rampant: This one probably won’t happen for a good 50 years, but the inklings of its beginnings have already shown up, primarily in Anonymous and the multiple middle-east government coups. Anonymous will end up being one of the most important social movements in modern history, as it matures from a group of pranksters into something that unites a large portion of humanity together. Governments will be forced to become more transparent and accountable, and debates about the effectiveness of representative democracy will rage in internet forums or whatever the future equivalent is. Part of this change will likely be influenced by a changing educational system that becomes much more effective at promoting critical thinking and individualistic problem solving skills. Extreme anti-authoritarianism, including anarchy, will become far more vocal and possibly less ignored by the public, but by necessity will remain fringe groups.

The economy will become both more capitalistic and more socialist: This is not a contradiction. The huge disparity between the wealthy and the poor is reaching such an absurd level in the United States that it has created an economic disparity that can be taken advantage of. At the same time, the most successful companies are already beginning to realize that increasing competition and other capitalistic values inside their own corporations results in far more productivity and efficiency (just look at what Larry Page is doing at Google). That means that capitalistic values will become more pronounced at smaller and smaller economic tiers, while the economy at large takes on a more socialistic approach to even out the wealth distribution. I have no idea when this will happen, because it is dependent on the two arguing political parties in the united states to realize that they both want the same wealth distribution. They just have to stop arguing and come to a compromise to try and do something about it.

So there you have it, my predictions for the future. Some of them might be right, others might not, others might be influenced by me planning to directly instigate them, but hopefully this was an interesting read nonetheless.

While reconstructing my threaded Red-Black tree data structure, I naturally assumed that due to invalid branch predictions costing significant amounts of performance, by eliminating branching in low-level data structures, one can significant enhance the performance of your application. I did some profiling and was stunned to discover that my new, optimized Red Black tree was… SLOWER then the old one! This can’t be right, I eliminated several branches and streamlined the whole thing, how can it be SLOWER?! I tested again, and again, and again, but the results were clear - even with fluctuations of up to 5% in the results, the average speed for my new tree was roughly 7.5% larger then my old one (the following numbers are the average of 5 tests).

Old: 626699 ticks New: 674000 ticks

//Old
c = C(key, y->_key);
if(c==0) return y;
if(c<0) y=y->_left;
else y=y->_right;

//New
if(!(c=C(key,y->_key)))
return y;
else
y=y->_children[(++c)>>1];

Now, those of you familiar with CPU branching and other low-level optimizations might point out that the compiler may have optimized the old code path more effectively, leaving the new code path with extra instructions due to the extra increment and bitshift operations. Wrong. Both code paths have the exact same number of instructions. Furthermore, there are only FOUR instructions that are different between the two implementations (highlighted in red below).

New
00F72DE5  mov         esi,dword ptr [esp+38h]  
00F72DE9  mov         eax,dword ptr 
00F72DEE  cmp         esi,eax  
00F72DF0  je          main+315h (0F72E25h)  
00F72DF2  mov         edx,dword ptr [esp+ebx*4+4ECh]
00F72DF9  lea         esp,[esp]
00F72E00  mov         edi,dword ptr [esi+4]  
00F72E03  cmp         edx,edi  
00F72E05  jge         main+2FCh (0F72E0Ch)  
00F72E07  or          ecx,0FFFFFFFFh  
00F72E0A  jmp         main+303h (0F72E13h)  
00F72E0C  xor         ecx,ecx  
00F72E0E  cmp         edx,edi  
00F72E10  setne       cl  
00F72E13  movsx       ecx,cl  
00F72E16  test        ecx,ecx  
00F72E18  je          main+317h (0F72E27h)  
00F72E1A  inc         ecx  
00F72E1B  sar         ecx,1  

00F72E1D  mov         esi,dword ptr [esi+ecx*4+18h]  
00F72E21  cmp         esi,eax  
00F72E23  jne         main+2F0h (0F72E00h)  
00F72E25  xor         esi,esi  
00F72E27  mov         eax,dword ptr [esi]  
00F72E29  add         dword ptr [esp+1Ch],eax
Old
00F32DF0  mov         edi,dword ptr [esp+38h]  
00F32DF4  mov         ebx,dword ptr 
00F32DFA  cmp         edi,ebx  
00F32DFC  je          main+31Dh (0F32E2Dh)  
00F32DFE  mov         edx,dword ptr [esp+eax*4+4ECh]  

00F32E05  mov         esi,dword ptr [edi+4]  
00F32E08  cmp         edx,esi  
00F32E0A  jge         main+301h (0F32E11h)  
00F32E0C  or          ecx,0FFFFFFFFh  
00F32E0F  jmp         main+308h (0F32E18h)  
00F32E11  xor         ecx,ecx  
00F32E13  cmp         edx,esi  
00F32E15  setne       cl  
00F32E18  movsx       ecx,cl  
00F32E1B  test        ecx,ecx  
00F32E1D  je          main+31Fh (0F32E2Fh)  
00F32E1F  jns         main+316h (0F32E26h)  
00F32E21  mov         edi,dword ptr [edi+18h]  
00F32E24  jmp         main+319h (0F32E29h)  
00F32E26  mov         edi,dword ptr [edi+1Ch]  
00F32E29  cmp         edi,ebx  
00F32E2B  jne         main+2F5h (0F32E05h)  
00F32E2D  xor         edi,edi  
00F32E2F  mov         ecx,dword ptr [edi]  
00F32E31  add         dword ptr [esp+1Ch],ecx

I have no real explanation for this behavior, but I do have a hypothesis: The important instruction is the extra LEA in my new method that appears to be before the branch itself. As a result, it may be possible for the CPU to be doing branch prediction in such a way it shaves off one instruction, which gives it a significant advantage. It may also be that the branching is just faster then my increment and bitshift, although I find this highly unlikely. At this point I was wondering if anything I knew about optimization held any meaning in the real world, or if everything was just a lot of guesswork and profiling because what the fuck?! However, it then occurred to me that there was an optimization possible for the old version - Move the if(c==0) statement to the bottom so the CPU does the (c<0) and (c>0) comparisons first, since the c==0 comparison only happens once in the traversal. Naturally I was a bit skeptical of this having any effect on the assembly-rewriting, branch-predicting, impulsive teenage bitch that my CPU was at this point, but I tried it anyway.

It worked. There was a small but noticeable improvement in running time by using the old technique and rewriting the if statements as such:

c = C(key, y->_key);
if (c < 0)  y = y->_left;
else if(c > 0) y = y->_right;
else return y;

Optimized: 610161.8 Ticks

The total performance improvement over my failed optimization attempt and my more successful branch-manipulation technique is a whopping 63838.2 Ticks, or a ~10% improvement in speed, caused by simply rearranging 4 or 5 instructions. These tests were done on a randomized collection of 500000 integers, so that means the optimized version can pack in 10% more comparisons in the same period of time as the bad optimization. That’s 550000 vs 500000 elements, which seems to suggest that delicate optimization, even in modern CPUs, can have significant speed improvements. Those of you who say that toying around with low level code can’t infer significant performance increases should probably reconsider exactly what you’re claiming. This wouldn’t directly translate to 50000 extra players on your server, but a 10% increase in speed isn’t statistically insignificant.

I believe that at a young age, I was physically harassed a couple of times, but I have long since forgotten. What I haven’t forgotten is the intellectual bullying I was subjected to during 7th grade. There is not a day that goes by that my actions are not subtly influenced by when I misprounced “subtle” as “sub”-“tle” and was made a laughingstock in front of my honors class, several of whom told me that I was a hopeless idiot who couldn’t do anything right. This was reinforced about three years later after my inept social skills earned me an enormous tirade from someone whom I held in high regard who then told me I was a useless pile of shit whose attempts at being helpful had only slowed things down, and that after 14 months I had contributed absolutely nothing to the project that was actually going to be used.

Years later, memories of these moments would begin to haunt me in high school, where the bullying had largely stopped, or so I had thought. It wasn’t long before programmers started telling me how I should do things and what was the right thing to do. They told me that performance didn’t matter, that I should never learn C++, that interpreted languages are the future. I disagreed with them. I gave reasons for my disagreement, and I was ridiculed and laughed at. At one point I somehow ended up in a game development IRC channel and mentioned that I preferred C++ over .net, and when pressed for justification I explained how I had to sort 10000 images 60 times a second, which requires delicate memory management that is difficult to do in C#.

Naturally, they told me I should have just used Array.Sort(), because the time required to render the images was far greater then the sorting time. The utter stupidity of this answer astonished me; I was in a game development channel and they were obtusely disregarding the fact that games do things other then draw pictures on the screen, not to mention having to fill up an array with images every frame due to culling. I mentioned this to a friend of mine, who then admitted that he had been in the same channel a few months back, and they had instead ridiculed him for using C# instead of C++.

This is when I realized that the bullying never stopped - it just changed. Now the bullies are programmers who ridicule other programmers no matter what they do. They are patent trolls who sue everyone just because they can. They are huge companies that squash smaller ones just because they don’t like them, wiggle out of taxes and then get away with it because they’re the teacher’s pet. Except now, the teacher is the U.S. Government, and she’s accepting bribes.

The bullies never went away, they just changed. I know from 7th grade that bullies aren’t just brainless jocks, they’re stuck-up intellectual assholes who take advantage of other people just because they can. Now those assholes are in charge of $40 billion companies, have friends in the teacher’s lounge, and your parents aren’t there to help you anymore.

Some people argue that everyone is an adult now, and much more mature then a 7th grader. Yeah, right. We have people in Texas who decided to remove Thomas Jefferson from their history curriculum. We have the RIAA demanding $75 trillion from Limewire, which more then the total GDP of the entire world. We have Facebook suing someone because they didn’t get written permission to crawl publically accessible data. Anyone who thinks we’re more mature then a bunch of screaming toddlers who keep throwing a fit when someone steals a block from their block tower has apparently never dealt with the business world. Subtlety is only difference between adults and toddlers. At least the toddlers have someone to tell them how silly they’re being.

Now the bullies are running rampant and the teachers don’t care. High school never ends; the bullying never stops. If you don’t do what people expect you to do (like an entrepreneur), then you’d better be ready to deal with endless attacks from all sides from everyone who will hate you for absolutely no reason at all. You’re at war with ideas, and you are the battlefield. Are you ready?

This is completely insane. First, Microsoft has rendered its new Windows Live Messenger (previously MSN messenger) almost completely useless.

  • No more handwriting
  • No more setting your name to anything other then your first and last name.
  • All links you click on redirect you to a page from Microsoft warning you about the dangers of the internet, requiring you to click a link to proceed.
  • All photosharing is now incompatible with previous versions of messenger, and instead of actually just sending the file, it will instead fail completely.
  • Any youtube video, image, or any other link you copy paste into the window will automatically trigger a sharing session whether you like it or not.
  • It will, at times, randomly decide none of your messages are getting through.
  • You can no longer have a one-sided webcam session. WLM will simply leave your webcam as a giant, useless blank image underneath your conversation partner, demanding that you buy a webcam.
  • It’s new emoticons must have been influenced by H.R.Giger (you can’t turn them off and leave custom ones on).

Naturally I wasn’t able to put up with this for very long and moved to pidgin. Pidgin has many issues of its own, including an ass-backwards UI design and this really annoying tendency to create a new popup window to confirm every single file transfer, among other truly bizarre UI design elements. I was willing to put up with these, because honestly pidgin is designed for Linux and just happens to work on windows too, and their libpurple library is the basis of almost all open-source IM clients.

Pidgin, however, has now stopped working as well. It now spastically refuses to connect to the MSN service because the SSL certificate is invalid. I can appreciate it trying to protect my privacy, but there is no way to override this. So, pidgin is now out of the question.

Well, how about Trillian? During its installation, Trillian informed me that “The Adobe Flash 9.0 plugin for Internet Explorer could not be found. This plugin is required for some of Trillian’s features.”

Trillian is no longer on my computer.

After digging around on wikipedia, I came up with Miranda IM, which seemed to be my last hope for a multi-protocol service that didn’t suck total ass. It supported WLM, AIM, and… not google talk? Not XMPP, the most useful extensible open source protocol? Um, ok. Its UI design is more compact then Pidgin but arguably even worse, and it doesn’t support custom emoticons or hardly ANYTHING on the WLM protocol. It served its purpose by at least letting me log the fuck in like I wanted to, though.

This is driving me up the wall. If anything else happens, I’m going to snap and simply make time to work on my own IM client implementation that doesn’t have glaring design flaws like every single other one. Honestly, requiring the Internet Explorer flash plugin to run everything? What the fuck are they smoking? What the hell is wrong with these developers?!

If only D had a good development environment, then I could write my IM client in it.

…takes its place as one of my favorite movies of all time. The characters are brilliant, the story is superb, the music is divine, and the cinematography is breathtaking. It was so good it gave me the last bit of inspiration I needed to make this (WIP), and as a result my attempts at finishing CEGUI this weekend were thrown out the window. Tomorrow I’ll try a first draft of the drums and possible a couple of effects before extending the main chorus. These new samples are amazing - it’s like I can do everything I ever wanted. Now the hard part is figuring out what I want. I threw in a bunch of binaural sounds thanks to the free sound project, which has been added to my mental list of useful resource sites.

I finally got the entire CEGUI dependency chain statically recompiled and have wrapped everything into a giant megadll with no dependencies. I then discovered that for all this time, PlaneShader’s Release mode had been defaulting to __fastcall. I have no idea how it has even been compiling with my other projects; the reason I don’t change the calling convention is because it breaks absolutely everything. For good measure I threw a few extra BSS_FASTCALL into the really high traffic functions.

So, if it weren’t for my sudden musical inspiration, I’d be rebuilding the GUI in CEGUI, although I also need to figure out how the heck it renders text, because I need a text renderer, and I can’t just require CEGUI’s to be used. I need to build a very basic but supercrazyfast text renderer, because holy shit is directX bad at that.

After that I finalize a midpoint release of planeshader and move to reimplementing Decoherence’s GUI in CEGUI, then FINALLY get to those joints that were supposed to be done ages ago.

Of course, I also have a midterm wednesday. Fuck.

Due to Bandcamp’s sudden threat to turn all of my free downloads into paid ones, I decided to go ahead and start selling my music properly. Renascent is now available for $3, or about as much as a gallon of milk costs. It contains remastered, super high quality (lossless if you choose to download in FLAC format) versions of all 14 songs, in addition to the original FLP project files used to create them. If you have ever wondered how I made a particular song, this might be another incentive to purchase the album. Note that these FLPs are released under the Creative Commons Attribution-NonCommercial-NoDerivs 3.0 license, so you can’t go running off with them like free candy.

Track List:

  1. On The Edge (2:56)
  2. Renascent (4:06)
  3. The Boundless Sea (6:49)
  4. Duress (2:40)
  5. Seaside Lookout (4:54)
  6. Sapphire [Redux] (2:20)
  7. Absolutia (3:04)
  8. The Plea (3:46)
  9. Now (2:34)
  10. Alutia (4:10)
  11. Rite (5:20)
  12. Crystalline Cloudscape (4:04)
  13. All Alone (3:06)
  14. SunStorm (4:12)

Total Time: 56:44

Listen and Buy It Here

There is a documented bug in windows 7 that has pissed me off a few times and recently crippled a friend of mine, where a .wav file with corrupted metadata causes explorer.exe to go into an infinite loop. My friend has a large collection of wavs that somehow got corrupted, so I wrote this program to strip them of all metadata. Due to the nature of the bug, the program can’t delete them (you must use the command prompt to do that), but rather creates a folder called “safe” with all the stripped wav files inside of it.

Hosted in case anyone else has corrupted wav files they need to save. Just stick it inside a folder and run it - it’ll automatically strip all wav files in the same folder as the executable.

WavSaver

After beating World of Goo after stabilizing things in my game and renaming it, I wondered how easy it was to decompile C# applications and simultaneously thought this would be a great opportunity to get pixel perfect hit testing to work on my engine. So, I decompiled GearGOD’s composition example and quickly discovered that his method of detecting mouse messages was… well something completely different then his extremely bad attempt at explaining it to me had suggested.

Basically, he did not run into the window event issues that I was having because… he didn’t use them. XNA keeps track of the mouse coordinates in its own separate update function, most likely using its special input hook, and hence there is no mousemove to keep track of. Instead of occurring when the user moves the mouse, the hit tests occur every single frame.

Hence, once you have utilized WS_EX_TRANSPARENT|WS_EX_COMPOSITED|WS_EX_LAYERED to make your window click-through-able, you then simply do a hit test on a given pixel after everything has been drawn, and swap out WS_EX_TRANSPARENT depending on the value. GetCursorPos and ScreenToClient will get the mouse coordinates you need, although they can be off your app window entirely so check for that too.

if(_dxDriver->MouseHitTest(GetMouseExact()))
  SetWindowLong(_window,GWL_EXSTYLE,((GetWindowLong(_window,GWL_EXSTYLE))&(~WS_EX_TRANSPARENT)));
else
  SetWindowLong(_window,GWL_EXSTYLE,((GetWindowLong(_window,GWL_EXSTYLE))|WS_EX_TRANSPARENT));

To get the pixel value, its a bit trickier. You have two options - you can make a lockable render target, or you can copy the render target to a temporary texture and lock that instead. The DirectX docs said that locking a render target is so expensive you should just copy it over, but after GearGOD went and yelled at me I tested the lockable render target method, and it turns out to be significantly faster. Futher speed gains can be achieved by making a 1x1 lockable render target and simply copying a single pixel from the backbuffer into the lockable render target and testing that.

void cDirectX_real::ActivateMouseCheck()
{
  if(_mousehittest) _mousehittest->Release();
  DX3D_device->CreateRenderTarget(1,1,_holdparams.BackBufferFormat,D3DMULTISAMPLE_NONE,0,TRUE,&_mousehittest,NULL);
}
bool cDirectX_real::MouseHitTest(const cPositioni& mouse)
{
  RECT rect = { mouse.x,mouse.y,mouse.x+1,mouse.y+1 };
  DX3D_device->StretchRect(_backbuffer,&rect,_mousehittest,0,D3DTEXF_NONE);

  if(mouse.x<0 || mouse.y < 0 || mouse.x > (int)_width || mouse.y > (int)_height)
    return false; //off the stage
  D3DLOCKED_RECT desc = { 0,0 };
  if(FAILED(_mousehittest->LockRect(&desc, 0,D3DLOCK_READONLY)))
    return true;    

  unsigned char color = (*((unsigned long*)desc.pBits))>>24;
  _mousehittest->UnlockRect();
  return color>_alphacutoff;
}

Using this method, the performance hit is 620 FPS to 510 FPS at 1280x1024, which is fairly reasonable. However, my Planeshader SDK example is still at 0.9.71, which does not have this updated, fast version, so it will be using a much slower method to do it. The end result is the same though.

Someone linked me to this awesome webpage that uses HTML5 to do 8-bit palette color cycling using Mark Ferrari’s technique and