HN user

amavect

93 karma
Posts0
Comments87
View on HN
No posts found.

Cool!! I really like how the overflow condition reads. "When the source and destination have the same sign, but the result a different sign, then signed addition overflows."

x86 has SETC/SETNC and SETO/SETNO to pull the carry/overflow bits out of the status register.

  u+: ADD then SETNC
  u-: CMP then SETNC
  s+: ADD then SETNO
  s-: CMP then SETNO
C23 adds checked arithmetic, and gcc implements them as built-in, generating SETO/SETNO. I can't find a way to generate SETNO otherwise. https://godbolt.org/z/4EjecdW1d
  #include <stdint.h>
  #include <stdckdint.h>

  int add_u(unsigned x, unsigned y){
    return x <= ~y;
  }
  int sub_u(unsigned x, unsigned y) {
    return x <= y;
  }
  int add_u2(unsigned x, unsigned y){
    return !ckd_add(&x, x, y);
  }
  int sub_u2(unsigned x, unsigned y) {
    return !ckd_sub(&x, x, y);
  }
  int add_s(int x, int y){
    return !ckd_add(&x, x, y);
  }
  int sub_s(int x, int y) {
    return !ckd_sub(&x, x, y);
  }
Now, I the difficulty you talk about goes deeper than high level language semantics. Math and predicate logic can't easily talk about a carry flag or an overflow flag. Math equivocates unsigned comparisons with signed comparisons: unsigned < means carry flag, signed < means sign flag != overflow flag. Thus, by coincidence, unsigned < can talk about carry, but < cannot talk about only overflow (without the sign flag). Furthermore, a theorem-proving language wants to prove that overflow cannot happen before attempting to calculate it.

So, despite you clearly showing that carry and overflow have the same calculation cost, I don't know how to represent those predicates in a usual math language with equal symbol length or complexity.

You sound like you believe in philosophical skepticism. Tell me: can a map ever properly describe the territory? When would a map properly describe the territory? (Can a theory ever properly describe reality? What does a theory need to properly describe reality?)

We know that universal Turing machines can emulate other Turing machines. Weirdos like Wolfram believe that a universal Turing machine can emulate reality. In a quick skim of this lecture series, the presenter doesn't talk about that, rather he just calls computation a scientific principal (universal and fundamental in the sense of physical laws, not fundamental in the sense of emulating reality on a computer).

I included that to try to explain the symbol soup that correctly encodes the preconditions (the ∀ lines). I intended that to mean "I need to make sure that y+x doesn't overflow", even that unsigned arithmetic cannot express that precondition in that way, as you point out. From there, derive y ≤ INT_MAX-x as the actual precondition for unsigned addition. I forgot that "ensure" actually means something in some programming languages, sorry for the confusion.

More simply put, unsigned addition needs to check that y+x doesn't overflow, while signed addition needs to check that y+x doesn't overflow and doesn't underflow. So, unsigned arithmetic has a simpler precondition that would win a technical debate on whether to use signed or unsigned arithmetic, but since most programming languages lack theorem proving, signed arithmetic wins on the small integer assumption.

Pedantically, that doesn't properly invert post-increment in the loop step. It decrements one extra time. If I need to use the loop index after the loop, then decrementing in the condition would cause problems.

  size_t i = size;
  while(i-- > 0){
    // loop body, possibly break
  }
  use(i); // i wraps below 0

  size_t i = size;
  while(i > 0){
    i--;
    // loop body, possibly break
  }
  use(i); // i doesn't wrap
Practically, i leaves the for-loop scope, so most never encounter this problem.

I believe the main issue lies in most programming languages lacking theorem proving capabilities to prove the safety of integer operations.

The safety conditions for unsigned arithmetic:

  Ensure y+x ≤ INT_MAX.
  If x ≤ UINT_MAX-y, then x+y evaluates correctly:
  ∀x∀y(x ≤ UINT_MAX-y → ∃z(z = y+x))

  Ensure y-x ≤ INT_MAX.
  If x≤y, then y-x evaluates correctly:
  ∀x∀y(x≤y → ∃z(z = y-x))
The safety conditions for signed arithmetic:
  Ensure INT_MIN ≤ y+x and y+x ≤ INT_MAX.
  To avoid overflow or underflow, first compare x to 0.
  In the case x≤0, INT_MIN-x cannot underflow, and y+x cannot overflow. If y compares greater than INT_MIN-x, then y+x evaluates correctly.
  In the case 0≤x, then INT_MAX-x cannot overflow, and y+x cannot underflow. And if y compares less than INT_MAX-x, then y+x evaluates correctly.
  ∀x∀y((x≤0 ∧ INT_MIN-x≤y)∨(0≤x ∧ y≤INT_MAX-x) → ∃z(z = y-x))

  Ensure INT_MIN ≤ y-x and y-x ≤ INT_MAX.
  To avoid overflow or underflow, first compare x to 0.
  In the case 0≤x, INT_MIN+x cannot underflow, and y-x cannot overflow. If y compares greater than INT_MIN+x, then y-x evaluates correctly.
  In the case x≤0, INT_MAX+x cannot overflow, and y-x cannot underflow. If y compares less than INT_MAX+x, then y-x evaluates correctly.
  ∀x∀y((0≤x ∧ INT_MIN-x≤y)∨(x≤0 ∧ y≤INT_MAX+x) → ∃z(z = y-x))
The programmers that prefer unsigned arithmetic intuitively feel the greater simplicity compared to signed integers, but without any theorem proving, I agree that your assumption of small integers strongly supports signed integers.

Post-increment inverts to pre-decrement, but for-loops don't support proper syntax sugar for pre-decrement.

  for(size_t i = 0; i < size; i++){
    // loop body
  }
  for(size_t i = size; i > 0;){ i--;
    // loop body
  }

Hah, I can use this to give decibels an actual unit.

  dB_P = log(10)/10
  dB_F = log(10)/20
  log(10*V) = log(V) + 20*dB_F  // the level of 10 V equals 20 dB more than the power level of 1 V.

  SPL = 20*10^-6 * Pa
  hearing_damage = log(SPL) + 90*dB_F  // hearing damage occurs over 90 dB_F above SPL (neglecting A-weighting)
  pow(hearing_damage) = pow(log(SPL) + 90*dB_F))
  pow(hearing_damage) = pow(log(SPL) + 90*log(10)/20))
  pow(hearing_damage) = SPL*pow(90*log(10)/20))
  pow(hearing_damage) = SPL*31622.7766  // the pressure of hearing damage occurs above 31622 times SPL
  pow(hearing_damage) = 0.632455532 Pa  // the pressure of hearing damage occurs above 0.632 Pa
Very helpful!! Imagine combining the goofy list of decibel suffixes into a uniform notation. Write the logarithm first so the + or - stays in the same spot.
  log(reference_unit) + value*dB_F (or dB_P)
  log(reference_unit) - value*dB_F (or dB_P)
https://en.wikipedia.org/wiki/Decibel#List_of_suffixes

You might ask: if we have a baseless logarithm log(N), do we also have a “baseless exponential”?

Sure we can, with some naive algebra. If we can take log(x,base) and drop the base, then we can also take pow(base,x) and drop the base. Since bits=log(2), then pow(bits)=2. You can probably connect it to the reverse of things, like integrals.

Also, for fun, I'll play with some notation tricks.

  log(freq) = pitch
  freq = pow(pitch)
  octave = log(2)

  400*Hz = 100*Hz*4  // the frequency 400 Hz equals 4 times 100 Hz
  log(400*Hz) = log(100*Hz) + log(4)
  log(400*Hz) = log(100*Hz) + 2*log(2)
  log(400*Hz) = log(100*Hz) + 2*octave
  log(400*Hz) = log(100*Hz) + 2*octave  // the pitch of 400 Hz equals 2 octaves above the pitch of 100 Hz

  cent = log(2)/1200
  A4 = log(440*Hz)
  B4 = A4 + 200*cent  // the pitch B4 equals 200 cents above A4
  B4 = log(440*Hz) + 200*log(2)/1200
  B4 = log(440*Hz) + log(2^(2/12))
  B4 = log(440*Hz * 2^(2/12))
  pow(B4) = 493.883 Hz  // the frequency of B4 equals 493.883 Hz
I like the intuition that baseless logarithm notation gives, and it also avoids needing to choose a specific reference point. I can also directly calculate by choosing an arbitrary base:
  pow(log(440*Hz) + 200*log(2)/1200)
  exp(ln(440) + 200*ln(2)/1200)

The tone is generated using two sawtooth oscillators

I interpreted "acoustically-accurate" to mean physically modeled in some way. Filtered sawtooth makes a simple brass-like timbre, but 80% still sounds synthetic.

Really neat anyways, thanks for sharing.

I agree. Additionally, both 0.0 and 1.0 don't really exist for dithered signals, so a byte should map to [0.5, 255.5] before division by 256. This also solves the signed integer asymmetry, as a signed byte maps to [-127.5, 127.5] before division by 128. I wonder if audio DSP folks have done this already.

I have an axe to grind. Radix economy makes a shallow argument when calculating the wrong per-digit information cost.

I need some functions to show what I mean. Calculate logarithms, calculate the number of digits, and convert a base-n unit of information into base-2 units of information. Finally, calculate the information cost: the number of digits, times the information needed per digit.

  import ln, floor
  define log := (num,base) -> ln(num) / ln(base)
  define digits := (num,base) -> floor(log(num,base) + 1)
  define tobits := (base) -> log(base,2)
  define infocost := (num,base) -> digits(num,base) * tobits(base)
  define infocost_wikipedia := (num,base) -> digits(num,base) * base
  define infocost_tbwtc := (num, base) -> (digits(num,base) - 1) * tobits(base) + tobits(base- 1)
https://www.desmos.com/calculator/1wfdtsuaav

I define a logarithmic per-digit information cost, following information theory. For example, 1 trit = log(3,2) bits. This results in no advantage for any base (in which case, choose base 2).

Wikipedia uses a linear per-digit information cost equal to the base. This holds when communicating options takes linear time (Wikipedia's example of a phone menu). This results in advantage for base e (in which case, choose base 3).

The video "The Best Way To Count" uses the logarithmic digit cost, and also notes that the leading digit carries less information (it excludes 0, like a IEEE floating point mantissa). This results in advantage for base 2.

Therefore, know the context to apply the right cost analysis!

https://en.wikipedia.org/wiki/Optimal_radix_choice

https://en.wikipedia.org/wiki/Talk:Optimal_radix_choice#Why_...?

https://en.wikipedia.org/wiki/Talk:Optimal_radix_choice#Bina...

https://youtu.be/rDDaEVcwIJM?t=701 timestamp 11:41

I imagine an OS where the system remembers to keep permanent permission for a program to manage its own files. An app data folder would work. The system should pass the capability on program start.

I also imagine a system where graphical programs must call a trusted system file picker to receive a fd. Receiving the capability grants permission. Ideally, Chrome could export browser history to a file, but we live in a fallen world. In any case, an alternative browser must request access through the system file picker, selecting an exported file or selecting the Chrome app data folder. It trades automatic import with user selection. The user has ultimate power, and programs make noise when doing such requests.

Please forgive me that I don't know Android system architecture. Searching tells me something about the Storage Access Framework, but I don't know if that truly meets what I describe.

I too would like an OS where called programs don't need to call open() on strings. The shell already has <input >output redirection, but hamstrung so few ever use them. So many programs recreate the functionality with -i -o in some manner to make up for the flaws (read multiple inputs, avoid creating a file on error). Graphical programs could request a fd from a trusted file picker instead of requesting a string to call open() immediately after. That just scratches the surface, so much security and convenience to gain.

thanks for continuing this interesting conversation!

Cheers!

Money does not determine resource allocation. But spending money does!

Very good point. Investors have some say as to where the money goes, but you're right. Often said that the economy runs on debt.

They spend only a tiny fraction of it – and invest the rest.

Well said. I suppose their wealth only represents a potential for resource allocation.

If we forced them to spend that wealth, much of the economy’s resources would be redirected to provide goods and services to the top 1% of people.

Under most theories of value, this extreme demand and labor would cause the price of such luxury goods and services to skyrocket! The money would quickly distribute to the hands of those who provided such goods. Then the masses can spend the money.

I now see our discussion as a classic debate of supply-side vs demand-side economics. I'll steal "the unity of means and ends" from the anarchists for this: I fully believe that the masses must have the resource allocation potential in order to achieve greater wealth for all. That exists in a positive feedback loop with businesses, increasing technology and production, and increasing the general standard of living. But, investing gives the resource allocation power to the businesses. With enough wealth and power, large businesses can keep the investment cycle flowing between businesses and owners, underpaying the workers and buying out competitors. At the most extreme result, a vertically closed system where the workers must meet the needs of the business (company towns).

These are not easily adapted to produce things that regular people need.

So many goods start out as expensive luxury goods. Refrigeration, commercial airlines, air conditioning, computers, HDTVs, cell phones...

When a small number of people can, in effect, buy the government with pocket change, that’s not good.

Then they morph government policy towards further enriching themselves, hurting the masses in the process. Very bad!

Would you advocate for a 0% capital gains tax? Or a capital gains tax-break? How would you calculate the ideal number? (I would place capital gains tax included in income tax.)

Very interesting perspective. Let me try and repeat it back. Resource allocation is a zero-sum game within any given year, resource production increases yearly as technology increases, technology increases more as capital increases, so a low capital gains tax will increase resource production more than a high capital gains tax.

If I got that right, here's my best shot at a contradiction. If resource allocation is a zero-sum game, money (liquid assets) determines resource allocation, and low capital gains tax further concentrates money to the wealthy (I would need to prove this, and in recent years the distribution of wealth has increased towards the wealthy), then the wealthy gain a greater share of resource allocation next year.

This might not result in problems, as historically the increases in resource production have increased regular people's resource allocation in absolute terms, but I see no necessity in this trend. I might argue that the poor can lose resource allocation in the zero-sum game, but I'd need to prove that (something like, inflation hurts poor people more than the rich? incomplete thoughts). I could also argue that currents trends place financial assets (intangible) above production assets (tangible), slowing the benefit to regular people.

I claim that if the wealthy were to put their money in luxuries (things that don't give capital gains), they would control more allocation in a given year, but then they would decrease their share of resource allocation the next year. I also claim that resource production would increase just fine, as technology initially benefiting luxury production expands toward general production.

[and, more importantly, providing goods and services that are beneficial to society as a whole].

I think enshittification, cost externalization, and rent-seeking behavior cancel this out, muddying the connection towards meeting the needs of regular people. For example, we needed cap-and-trade to internalize the costs of acid rain back onto power plants.

These claims are demonstrably false. Paper assets provide no tangible benefits.

I think my rhetorical bait worked: you seem to agree with incentivizing luxury spending on real goods and services (instead of incentivizing capital gains)? Adam Smith argues to take that vanity and drive it towards public recognition. For example, many universities put the names of rich donors on the opulent buildings they donate to build. That's good! (My college's music building was amazing!)

In other words, doesn't that policy incentivize wealthy people to consume less and, therefore, claim a reduced share of economic benefits? Consequently, doesn't an increased share of economic benefits go to "regular people"?

I thought trade doesn't make a zero-sum game? Money supply is a zero-sum game (I think), and I want money sinks to spread the money. We want them to spend their stored money to generate more tangible wealth for all. Luxury goods often push the limits to what can be done, advancing technology and generating wealth while also depleting their money stores. But while investments and venture capital might also advance technology and generate wealth, they continue to concentrate the money supply to the rich. Not good!

Low capital gains tax incentivizes investment and venture capital, so the rich can grow their wealth faster than the poor, while creating a job market. Compare that to spending wealth on luxuries, a money sink that also creates a job market and grows the economy (people have to make the luxuries). The former creates more liquid assets (stock) with no clear connection towards meeting the needs of regular people. The latter creates more solid assets with no clear connection towards meeting the needs of regular people.

I vaguely remember Adam Smith talking about directing the vanity of the rich towards spending great amounts of money on proper objects in exchange for recognition. 4:00 https://www.youtube.com/watch?v=ejJRhn53X2M

I also started doing this. I feel that "b = expr(a); a++;" expresses what I mean better than "b = expr(a++)": store expr(a) in b, then store a+1 in a. Any good compiler will optimize the same.

After separating a++ onto its own line, replacing a++ with a+=1 or a=a+1 comes down to personal taste in syntax sugar. I vote for a+=1.

You say all of these things and claim "there is a ton of science", but I ask for scholarly links to learn more. I don't trust anyone's word at face value on empirical topics, and I also don't know where to begin looking. "There are studies related to this out on PubMed." Show me! Phrases like this annoy me greatly.

You posted links earlier, which suffices.

Please post specific articles for others to critique. I find poor quality studies. Low sample size, self-reported questionnaires, low effect sizes.

https://pmc.ncbi.nlm.nih.gov/articles/PMC10675414/

https://pmc.ncbi.nlm.nih.gov/articles/PMC12018234/

https://pubmed.ncbi.nlm.nih.gov/20834180/ I smell P-hacking.

Note that none of these address neural regeneration (after concussions, as claimed by oneshtein) because I'll leave that for the supporters to demonstrate.

Some napkin math, then. About 25–50 μg 7-DHC / cm2 skin (Wiki). About 1.5 m^2 human skin area (google AI summary). About 35% skin exposed (R. Kift, linked earlier). 1.5 * 100 * 100 * 25 * .35 = 131250 μg. Need 50-250 μg of colecalciferol (2000-10000 IU). Anyone would likely get sunburn before running out of 7-DHC (excepting a low 7-DHC condition, or me getting the wrong numbers).

https://en.wikipedia.org/wiki/7-Dehydrocholesterol

This study says "Findings include that small UV doses on a regular basis are more efficient for vitamin D synthesis than larger sub-erythemal doses", using a logarithmic model for blood calcifediol as a function of exposure.

https://pmc.ncbi.nlm.nih.gov/articles/PMC8558903/

But it doesn't address colecalciferol production and storage. Fat stores colecalciferol, and I don't know of any way to measure that directly. I would guess that further UVB exposure linearly produces colecalciferol (with linear DNA damage, minus DNA repair with time), but the liver and kidneys logarithmically produce calcifediol and calcitriol. Just a guess. Still more questions :)