I've been using the 1M window at work through our enterprise plan as I'm beginning to adopt AI in my development workflow (via Cline). It seems to have been holding up pretty well until about 700k+. Sometimes it would continue to do okay past that, sometimes it started getting a bit dumb around there.
(Note that I'm using it in more of a hands-on pair-programming mode, and not in a fully-automated vibecoding mode.)
My take as a graphics programmer is that angles are perfectly fine as inputs. Bring 'em! And we'll use the trig to turn those into matrices/quaternions/whatever to do the linear algebra. Not a problem.
I'm a trig-avoider too, but see it more as about not wiggling back and forth. You don't want to be computing angle -> linear algebra -> angle -> linear algebra... (I.e., once you've computed derived values from angles, you can usually stay in the derived values realm.)
Pro-tip I once learned from Eric Haines (https://erich.realtimerendering.com/) at a conference: angles should be represented in degrees until you have to convert them to radians to do the trig. That way, user-friendly angles like 90, 45, 30, 60, 180 are all exact and you can add and subtract and multiply them without floating-point drift. I.e., 90.0f is exactly representable in FP32, pi/2 is not. 1000 full revolutions of 360.0f degrees is exact, 1000 full revolutions of float(2*pi) is not.
Hah. I think we're and the author of both articles on the same page about this. (I had to review my implementations to be sure). I'm a fan of all angles are radians for consistency, and it's more intuitive to me. I.e. a full rot is τ. 1/2 rot is 1/2 τ etc. Pi is standard but makes me do extra mental math, and degrees has the risk of mixing up units, and doesn't have that neat rotation mapping.
Very good tip about the degrees mapping neatly to fp... I had not considered that in my reasoning.
If you want consistency, you should measure all angles in cycles, not in radians.
Degrees are better than radians, but usually they lead to more complications than using consistently only cycles as the unit of measure for angles (i.e. to plenty of unnecessary multiplications or divisions, the only advantage of degrees of being able to express exactly the angle of 30 degrees and its multiples is not worth in comparison with the disadvantages).
The use of radians introduces additional rounding errors that can be great at each trigonometric function evaluation, and it also wastes time. When the angles are measured in cycles, the reduction of the input range for the function arguments is done exactly and very fast (by just taking the fractional part), unlike with the case when angles are measured in radians.
The use of radians is useful only for certain problems that are solved symbolically with pen on paper, because the use of radians removes the proportionality constant from the integration and derivation formulae for trigonometric function. However this is a mistake, because those formulae are applied seldom, while the use of radians does not eliminate the proportionality constant (2*Pi), but it moves the constant into each function evaluation, with much worse overhead.
Because of this, even in the 19th century, when the use of radians became widespread for symbolic computations, whenever they did numeric computations, not symbolic, the same authors used sexagesimal degrees, not radians.
The use of radians with digital computers has always been a mistake, caused by people who have been taught in school to use radians, because there they were doing mostly symbolic computations, not numeric, and they have passed this habit to computer programs, without ever questioning whether this is the appropriate method for numeric computations.
Unfortunately, IEEE Std 754 contains a huge mistake, which has been followed by some standard libraries for programming languages.
As an alternative to the trigonometric functions with arguments measured in radians, it recommends a set of functions with arguments measured in half-cycles: sinPi, cosPi, atanPi, atan2Pi and so on.
I do not who is guilty for this, because I have never ever encountered a case when you want to measure angles in half-cycles. There are cases when it would be more convenient to measure angles in right angles (i.e. quarters of a cycle), but half-cycles are always worse than both cycles and right angles. An example where measuring angles in cycles is optimal is when you deal with Fourier series or Fourier transforms. When the unit is the cycle that deletes a proportionality constant from the Fourier formulae, and that constant is always present when any other unit is used, e.g. the radian, the degree or the half-cycle.
Due to this mistake in the standard, it is more likely to find a standard library that includes these functions with angles measured in half-cycles than a library with the corresponding functions for cycles. Half-cycles are still better than radians, by producing more accurate results and being faster, but it may be hard to avoid some scalings by two. However, usually it is not necessary to do a scaling at every invocation, but there are chances that the scalings can be moved outside of loops.
Such functions written for angles measured in half-cycles can be easily modified to work with arguments measured in cycles, but if one does not want to touch a standard library, they may be used as they are.
When one uses consistently the cycle as the unit of angle, which is consistent with measuring frequencies in Hertz, i.e. cycle per second, instead of measuring them in radian per second, one must pay attention to the fact that a lot of formulae from most handbooks of physics are incorrect. Despite the claim that those formulae are written in a form that is independent of the system of units, this claim is false because many formulae are written in a form that is valid only when the unit of angle is the radian.
For example, all formulae for quantities related to rotation movements, as they are written in modern handbooks contain the "radius". This use of the "radius" creates a wrong mental model of the rotational quantities, both for students and also even for many experienced physicists.
In reality, in all those formulae, e.g. in the definition of the angular momentum, in order to obtain the correct formulae one must replace the "radius" with the inverse of the curvature of the trajectory of the movement. Thus the angular momentum is not the product of the linear momentum by the radius, but it is the ratio between the linear momentum and the curvature.
Then one must use the correct definition for the curvature. Most handbooks define the curvature as the inverse of the radius. This is a wrong definition, which is based on the non-explicit assumption that angles are measured in radians.
The correct definition of the curvature is as the ratio between rotation angle and length, for the movement, i.e. more precisely it is the derivative of the rotation angle as a function of the length of the curve on which something moves. When angles are measured in radians, the curvature is the inverse of the radius. When angles are measured in cycles, the curvature is the inverse of the perimeter. Thus with angles measured in cycles the angular momentum is defined as the product between the linear momentum and perimeter. Similarly for the other rotational quantities, like angular velocity and acceleration, moment of inertia and so on.
Great's great info on curvature! Also don't see the use of the half cycle, although obviously see use of cycle. (As was thinking in terms of them anyway, just with a tau term to convert to radians.)
Author here. I have a JavaScript port of my automated test suite (https://github.com/a-e-k/canvas_ity/blob/main/test/test.html) that I used to compare my library against browser <canvas> implementations. I was surprised by all of the browser quirks that I found!
But compiling to WASM and running side-by-side on that page is definitely something that I've thought about to make the comparison easier. (For now, I just have my test suite write out PNGs and compare them in an image viewer split-screen with the browser.)
Author here. There's no AI-generated code in this. But yes, security hardening this has not been a priority of mine (though I do have some ideas about fuzz testing it), so for now - like with many small libraries of this nature - it's convenient but best used only with trusted inputs if that's a concern.
Author here. No vibe-coding, all human-written. Are you thinking of my use of GitHub emoji on the section headings in the README? I just found they helped my eye pick out the headings a little more easily and I'd seen some other nice READMEs at the time do that sort of thing when I went looking for examples to pattern it off of. I swear I'd had no idea it would become an LLM thing!
I'd originally started with a different version control system and was still getting used to Git and GitHub at the time that I'd released this. (I was a latecomer to Git just because I hated the CLI so much.) It was easiest for me just to drop the whole thing as a snapshot in a single commit.
But my private repo for it actually started in May 2017, and it had 320 commits leading up to its release, all human-written.
For the v2.0 that I have in mind, I'm thinking of force-pushing to migrate the full development history to the public repo.
And finally I'll add that I'm a graphics engineer by education and career. Where would the fun be in vibe-coding this? :-) Oh, and this compiles down to just ~36KiB of object code on x86-64 last I checked. Good luck vibe-coding that constraint.
2. Why a single header with `#define CANVAS_ITY_IMPLEMENTATION`?
I was inspired by the STB header ibraries (https://github.com/nothings/stb) and by libraries inspired by those, all of which I've found very convenient. In particular, I like their convenience for small utilities written in a single .cpp file where I can just `g++ -O3 -o prog prog.cpp` or such to compile without even bothering with a makefile or CMake.
Since the implementation here is all within a single #ifdef block, I had figured that anyone who truly preferred separate .cpp and .h files could easily split it themselves in just a few minutes.
But anyway, I thought this would be a fun way of "giving back" to the STB header ecosystem and filling what looked to me like an obvious gap among the available header libraries. It started as something that I'd wished I'd had before, for doing some lightweight drawing on top of images, and it just kind of grew from there. (Yes, there was Skia and Cairo, but both seemed way heavier weight than they ought to be, and even just building Skia was an annoying chore.)
----
Since I mentioned a v2.0, I do have a roadmap in mind with a few things for it: beside the small upgrades mentioned in the GitHub issues to support parts of newer <canvas> API specs (alternate fill rules, conic gradients, elliptical arcs, round rectangles) and text kerning, I'm thinking about porting it to a newer C++ standard such as C++20 (I intentionally limited v1.0 to C++03 so that it could be used in as many places as possible), possibly including a small optional library on top of it to parse and rasterize a subset of SVG, and an optional Python binding.
Not to mention if that if somebody needs to come over, the proper thing to do is signal first. Then I'm happy to politely ease off a bit and open more space for them to come over safely.
It's the people who aggressively slide right over just a few feet in front of me (cutting off nearly all of my safety buffer) without so much as a signal that really drive me nuts.
In Austin too, and probably just caused a driver to think the same thing. They were in the left lane on a frontage road which was suddenly turning left even though there was an entire lane opposite the intersection blocked off by those plastic things that seem popular to randomly place in the road these days. I saw them hesitate and figured they wanted to merge right, so i decelerated a bit to add another car length or or so, at maybe 10-15mph. They had plenty of space, flipped on their blinker, and instead of just merging started slowing down, to which I decided I wasn't going to brake more to allow them to block myself and everyone else from rolling through the intersection. They basically stopped in their lane, and beeped as I rolled by, to which someone behind them beeped at them for blocking the lane.
In Austin if you want to merge, decide if you can, blink and then merge.
Don't expect people to stomp on their brakes and stop to let you in, especially if your already traveling slower than the lane you are trying to get into and decide to further slow yourself.
And if you can't merge, deal with it, exit, or miss your exit and go around. Next time you will be more prepared or you will learn how to properly merge.
My experience driving in MA and NY was similar, but so often it was because a rusted out shitbox was trying to merge in that would slow down traffic significantly, and not only put me at risk of rear ending them, but being rear ended myself.
When flows merge, there's turbulence. There's less turbulence if the flows are more closely matched, including speed.
In the UK we are taught that you should not signal until you are ready to manoeuvre. If you follow the rules exactly this can put you in the unfortunate position of being penned in behind shower traffic.
Unless I'm the last car in a line and there's plenty of open space behind me. Then you should just wait until after I've passed before merging, because otherwise you create a little ripple in the flow. A few ripples and you got a wave, and that's how you get traffic.
So for the love of gods, if you're merging, even if you signal, match speeds for merging. If you're too slow to match speed, then suck it up buttercup, and hang out in the right lane until there's an opening.
One thing to consider is that this version is a new architecture, so it’ll take time for Llama CPP to get updated. Similar to how it was with Qwen Next.
(Note that I'm using it in more of a hands-on pair-programming mode, and not in a fully-automated vibecoding mode.)
reply