[HN Gopher] Subtraction is functionally complete ___________________________________________________________________ Subtraction is functionally complete Author : orlp Score : 184 points Date : 2023-10-07 08:35 UTC (14 hours ago) (HTM) web link (orlp.net) (TXT) w3m dump (orlp.net) | Recursing wrote: | Reminds me of this wonderful video: | https://www.youtube.com/watch?v=5TFDG-y-EHs , where he builds | computation using only IEEE-754 NaN and infinity | emilfihlman wrote: | "If both of the addends have the same sign, the output must have | that sign. However, for x-y that means if x and y have different | signs the output must have the sign of x." | | This is trivially wrong, or mixing two different meanings of | "signs". | | Given variables x and y with values 5 and 10, ie both having the | same positive sign, x-y will produce a result -5, that has | negative sign. | | Even if we assume that the sign of the y variable is actually | inverted, it's still trivial by choosing say -3 and -6, the | latter which has now inverted to 6, and the result is +3, which | has different sign than x. | [deleted] | jgrahamc wrote: | You've missed the word "different". Your examples talk about | the same sign. | emilfihlman wrote: | Direct your attention to the first line "If both of the | addends have the same sign, the output must have that sign" | | This is absolutely not true, as already shown. x=5 y=10 | z=x-y=-5, which has different sign from x. | | If we assume sign of y inverts because of the operation, then | direct your attention to the second line "However, for x-y | that means if x and y have different signs the output must | have the sign of x" x=-3 y=-6=>6 these now have different | sign, so result should have sign of x, but z=x+y=3, which | again has different sign from x. | orlp wrote: | > Given variables x and y with values 5 and 10, ie both having | the same positive sign, x-y will produce a result -5, that has | negative sign. | | If x and y both have a positive sign the condition "for x-y | that means if x and y have different signs" is not met. | | With -3 and -6, again, x and y both have the same sign and the | condition is not met for subtraction. | emilfihlman wrote: | Direct your attention to the first line "If both of the | addends have the same sign, the output must have that sign" | This is absolutely not true, as already shown. x=5 y=10 | z=x-y=-5, which has different sign from x. | | If we assume sign of y inverts because of the operation, then | direct your attention to the second line "However, for x-y | that means if x and y have different signs the output must | have the sign of x" x=-3 y=-6=>6 these now have different | sign, so result should have sign of x, but z=x+y=3, which | again has different sign from x. | orlp wrote: | > Direct your attention to the first line "If both of the | addends have the same sign, the output must have that sign" | This is absolutely not true, as already shown. x=5 y=10 | z=x-y=-5, which has different sign from x. | | The first sentence is referring to _addition_ , with | _addends_ , not subtraction. x - y is not an addition, it | is a subtraction, so the first sentence does not directly | apply. It _does_ apply however if you treat x - y as the | sum x + (-y), which the second sentence clarifies. | | In other words, the first sentence applies directly to | additions, and applies to subtractions if you flip the sign | of the second argument. The second sentence applies to | subtractions directly without any sign flips, but obviously | does not apply to additions. | | > If we assume sign of y inverts because of the operation, | then direct your attention to the second line "However, for | x-y that means if x and y have different signs the output | must have the sign of x" | | > x=-3 y=-6=>6 these now have different sign, so result | should have sign of x, but z=x+y=3, which again has | different sign from x. | | No, x=-3 and y=-6 both have the same sign, they're both | negative. | [deleted] | AgentOrange1234 wrote: | Cute. Next steps? If you fill out your soft-hardware instruction | set in the straightforward way, you could rig up a compiler to | target it. (There's probably no practical use beyond obfuscation | like hiding malware from decompilers.) | jeroenhd wrote: | This is the kind of weird (ab)use of floating point instructions | that I can imagine some DRM solution using as a means to | obfuscate a VM of some kind. | | The next step would be to use these properties to write a | compiler to run normal source code as floating point integers, | maybe with some kind of FFI to call regular OS APIs. | legobmw99 wrote: | Kind of like https://github.com/xoreaxeaxeax/movfuscator | [deleted] | LukeShu wrote: | You may be interested in | | - Using IEEE floating-point error for ML transfer functions | http://tom7.org/grad/ | | - Using IEEE NaN and infinity to build logic gates and a whole | CPU http://tom7.org/nand/ | bakuninsbart wrote: | Second one is possibly my favourite YouTube video of all | time. | kibwen wrote: | I'm certain that at least 20% of all the people who clicked | on this comments section did so specifically to post this | link. | teaearlgraycold wrote: | One day as we were getting coffee a coworker just casually | drops that his buddy from school made some programs called | learnfun and playfun for a YouTube video (which is my | favorite Tom7 video). Tech is a surprisingly small world. | RagnarD wrote: | If functionally complete means that any logic circuit can be | constructed, doesn't this imply that IEEE-754 floating point | subtraction is effectively Turing complete? (Or not?) | Epa095 wrote: | To quote someone from reddit (substitute NAND gates with | subtraction) | | > You can bulid a turing-complete machine out of NAND-gates, | but to say that a NAND-game is turing-complete is like saying | that you can live in a brick. You can't, but you can bulid a | house out of bricks and live in that. | SuchAnonMuchWow wrote: | No, functionally complete is mussing the looping functionality | to be Turing complete. | | Turing complete is often misused to say functionally complete, | either because people mistake the two or because it makes for a | more appealing blog post / article: | | - mov is in fact not turing complete: it needs a jmp | instruction (https://harrisonwl.github.io/assets/courses/malwar | e/spring20...) | | - homomorphic encryption systems are functionally complete but | not Turing complete (since looping leaks the number of | operations done, break the encryption) | uxp8u61q wrote: | You also need an infinite memory to be called "Turing | complete". It doesn't make sense to say that a bunch of | operations are or are not Turing complete. It's a property of | a whole machine, not just a set of operations. And no real | machine can possibly be Turing complete, because they don't | have infinite memory or time. | kweingar wrote: | > In computability theory, a system of data-manipulation | rules (such as a model of computation, a computer's | instruction set, a programming language, or a cellular | automaton) is said to be Turing-complete or computationally | universal if it can be used to simulate any Turing machine | (devised by English mathematician and computer scientist | Alan Turing). | | From https://en.wikipedia.org/wiki/Turing_completeness | Scarblac wrote: | And Turing machines have unbounded memory. That's usually | ignored when talking about Turing completeness, but it's | nevertheless true that physical computers cannot simulate | all Turing machines. | uxp8u61q wrote: | ... Yes? What are you trying to say? Did you go and | lookup what a Turing machine is? Or read the section | entitled "Non-mathematical usage"? | gdprrrr wrote: | You don't need jmp, a faulting mov works as well, like mov | CS, eax. | | https://github.com/xoreaxeaxeax/movfuscator#notes | mmarx wrote: | From the truth table, subtraction is clearly truth-preserving, so | it cannot actually be functionally complete. What am I missing? | johnday wrote: | Subtraction is truth preserving on the sign bit. It's not | truth-preserving in the actual subtractive bits. | | (I disagree with their claim that the subtractive bit is | functionally complete on its own - you're right, since it's | truth-preserving, it clearly is not functionally complete) | gliptic wrote: | The sign bit is the only bit involved here. What "subtractive | bits" are you referring to? | Epa095 wrote: | I dont really know what you mean by truth-preserving here, but | maybe a hint is thats its not ONLY subtraction which is | functionally complete, it's subtraction and the constant symbol | 0. From subtraction and 0 he makes false (as -0.0), and then he | has the functionally complete set found in wikipedia [1] as | {->, _|_ } (my attempt at rendering rightarrow and bottom). | | 1: https://en.wikipedia.org/wiki/Functional_completeness | Joker_vD wrote: | Truth-preserving means that it maps T to T. In fact, the | Wikipedia's article you link to has Post's theorem about five | Post's classes of Boolean functions with all of their | definitions: monotonic, affine (which has a funny definition | in this article: I was taught the definiton via ANF, "is just | a XOR of (some) of variables"), self-dual, truth- and false- | preserving. They're all closed but functionally incomplete | (in fact, they're functionally pre-complete: adding any | single function outside of a class to that class produces a | functionally complete set, -- and there are no other pre- | complete classes). | stavros wrote: | What does "truth-preserving" mean in this context? That it will | never produce false if either of the arguments is true? | gliptic wrote: | Why would truth preservation prevent it from being functionally | complete? How can you even tell a truth table is truth | preserving? A truth table is not a logical argument. | danbruc wrote: | Truth-preserving in this context means that the function | value is true if all function arguments are true. If you only | have truth-preserving functions available, then you can not | output false if all inputs are true, hence you can not build | all possible functions. An analog argument applies to | falsehood-preserving functions. | gliptic wrote: | I see. I wasn't familiar with that term in this context, | thanks. | tromp wrote: | Below the truth table for implication (with arguments reversed) | they claim | | > It turns out this truth table is functionally complete [1] | | yet the linked Wikipedia article clearly states that | | > every two-element set of connectives containing NOT and one | of { AND, OR, IMPLY } is a minimal functionally complete subset | of { NOT, AND, OR, IMPLY, IFF }. I.e. IMPLY by itself is not | functionally complete. | | [1] https://en.wikipedia.org/wiki/Functional_completeness | Epa095 wrote: | The article kind of took for granted that you could include | the number 0 as well, and with "-0" he got bottom, so its the | 2-element set {-->, _|_}. | gliptic wrote: | The unstated assumption is that you also have FALSE. | orlp wrote: | To be entirely precise, it is functionally complete in | combination with access to the constant false (-0.0). If not | given access to this constant it is not functionally complete, | unlike e.g. NAND which can produce false from any value. I | shall clarify that in the article. | | The point of the article was more to illustrate that using | nothing but signed zeros and floating point subtraction you can | simulate arbitrary circuits, and 'functionally complete' was | the most concise term for that I could think of, even if it is | bending the rules a little bit when strictly looking at the | truth table. | codeflo wrote: | It's a matter of definitions, but it always bothered me that | functional completeness is defined so that it only requires | the ability to produce any _non-nullary_ function, not any | function including nullary ones. That is, the set { NAND } is | considered functionally complete, even though it can only | produce a function that maps any input x to TRUE, and can 't | produce the value TRUE itself. As soon as you care about | constants, which I think you should, { NAND, FALSE } or | whatever isn't any more magical than { AND, NOT } or { XOR, | TRUE }. | thaumasiotes wrote: | > { NAND } is considered functionally complete, even though | it can only produce a function that maps any input x to | TRUE, and can't produce the value TRUE itself. | | When you're reducing formulas, those are the same thing. | p p [?] !p p !p [?] 1 !1 [?] 0 | | So then you're happy to say (p (p p)) | (p (p p)) [?] (p !p) (p !p) | [?] 1 1 [?] 0 | | The expression "(p (p p)) (p (p p))" is just a | particularly longwinded name for the constant "0". | | I don't see why you're comparing {NAND, FALSE} to {AND, | NOT} - how do you produce TRUE from {AND, NOT} by a | standard that {NAND} by itself doesn't also meet? The | normal way to produce TRUE from {AND, NOT} is | NOT (p AND (NOT p)) | | but you seem to have already rejected that? | codeflo wrote: | Yeah, listing {AND, NOT} was a mistake -- you're right, | you do need a constant. | | My problem with p !p [?] 1 is simply that you need some | (arbitrary) value p from somewhere. It's not 1, it's a | unary function that returns 1. That just bothers me. | deadbeeves wrote: | When I'm aiming for elegance, I like to define NAND as an | N-ary function: | | nand() = false | | nand(x, ...) = !(x && !nand(...)) | | That eliminates the problem of needing arbitrary | constants. | danbruc wrote: | If you want to be able to implement nullary functions, then | you need a nullary function to begin with. You are not | really implementing anything besides maybe negating the | constant you got. You would also have to extend { AND, NOT | } with a constant. The best you could do would change from | one binary function to one binary function and a constant. | pwdisswordfishc wrote: | So { -: F2 - F } is not functionally complete, but { -: F2 - | F, -0: F0 - F } is. | p4bl0 wrote: | Hey, not related to the post but since you're here: your | domain name has an AAAA IPv6 record but the server doesn't | respond to IPv6 requests. The problem most probably is that | the web server is not binded to the IPv6 address of the | system. | orlp wrote: | Thanks for letting me know. I just double-checked and the | AAAA IPv6 record does have the right IP, port 80 is open in | the VPS firewall for both IPv4 and v6 and my nginx config | does listen on both as well: listen 80; | listen [::]:80; | | I'm by no means a networking expert, so I'm a bit puzzled. | I'll investigate more in a couple of days, not particularly | excited to mess with the system while serving a post on the | front page. | p4bl0 wrote: | That's the HTTP config, but the website is served over | HTTPS and the HTTP version redirects to it. My bet would | be that the HTTPS settings does not bind to IPv6. | | Do you have: listen [::]:443 ssl; | | somewhere in the server {} block where the certificate is | declared? | | My mobile phone carrier uses IPv6 so I cannot access your | website from my phone (except if I connect to a wifi | network that uses IPv4). | orlp wrote: | Yep, I have listen [::]:443 ssl; | listen 443 ssl; | | in the server block. | p4bl0 wrote: | Maybe the second line should be "listen 443 ssl;" | (without the colon, like in the non-HTTPS version)? | That's how it is in my config. | | EDIT: orlp updated their comment above, this one is not | relevant anymore. | orlp wrote: | > Maybe the second line should be "listen 443 ssl;" | (without the colon, like in the non-HTTPS version)? | That's how it is in my config. | | That's a clerical error while copying to Hacker News, it | is without the colon in my config as well. I've edited | the post. | | I think I figured it out, Hetzner lists | 2a01:4f8:c012:175e::/64 as the IPv6 for my VPS, so I put | 2a01:4f8:c012:175e:: in the DNS record. However it seems | it only actually listens on 2a01:4f8:c012:175e::1. | Probably just me being an idiot and fundamentally | misunderstanding how IPv6 addresses work. I've updated | it, although it will probably take some time before the | DNS cache refreshes. | MayeulC wrote: | > Hetzner lists 2a01:4f8:c012:175e::/64 as the IPv6 for | my VPS | | Yup, that's the address prefix, 64 bit long as indicated | by the /64. Your VPS can therefore be configured with | 2^(128-64)=2^64 IP addresses, as long as they start with | that prefix. | | The actual IP is chosen by your VPS itself, so I guess it | has assigned itself prefix::1. You can see that address | with `ip -6 a`. And add new ones if you want: `ip -6 | address add 2a01:4f8:c012:175e::2 dev yournetworkcard0`. | You can technically add one IP address per service and | bypass the reverse proxy by having the services listen on | their dedicated IPs. That makes it easy to migrate | services to another host (change the AAAA record). | p4bl0 wrote: | It works! :) | mmarx wrote: | Ah, thanks, that was indeed what I was missing. | dzaima wrote: | Somewhat related: | https://dougallj.wordpress.com/2020/05/10/bitwise-conversion... | | That implements conversion from an IEEE-754 double to a pair of | two such doubles whose values are integers of the low and high 32 | bits of the bitwise representation of the argument double, | implemented only with double add/sub/mul. | valyagolev wrote: | > integer implementation done in software, using only floating | point ops | | so basically any attempt to use JavaScript 's number as int | DonHopkins wrote: | Why did it take mathematicians and logicians so long to figure | out their differences? | bitwize wrote: | Reminds me of how a single instruction -- "subtract and branch if | negative" -- is Turing complete. | Izkata wrote: | Abuse of the sign bit in similar ways was a major clue that a | true AI was loose in the wild in the short story _Coding | Machines_. | | https://www.teamten.com/lawrence/writings/coding-machines/ | dweekly wrote: | A wonderful story, though the concept was clearly heavily | borrowed from Ken Thompson's classic On Trusting Trust: | https://www.cs.cmu.edu/~rdriley/487/papers/Thompson_1984_Ref... | [deleted] ___________________________________________________________________ (page generated 2023-10-07 23:00 UTC)