HNHacker News
TopNewBestAskShowJobs

thelema314

104 karma · joined February 11, 2009

submissionscomments
thelema314··on Parsing bitstreams with Nom
I have to note ocaml-bitmatch/bitstring. Example code: https://bitstring.software/documentation/#matching-bitstring...

This was extremely convenient for me in the past.

thelema314··on Build Observable Systems
TL;DR: use probabilistic logging (x% chance of logging, with x chosen by dev for each log statement) instead of importance levels (ERROR, WARN, INFO, etc) to keep common events from flooding log files. Is that it?

edit: misclick

thelema314··on Writing Performance Sensitive OCaml Code
This is correct; OCaml integers are tagged with their LSB being 1 to indicate they're not a pointer. This means that the integer n is stored as 2n+1, and adding 1 requires modifying the stored value by 2.
thelema314··on Sort an array using only one local variable
> When using a signed integer variable to represent an index, there is an entire range of negative numbers that are not useful at all. Let's make use of them, then.

If you have "local variable" with more bits than log(# elements to be sorted), then yes, this trick works, but with sufficient extra bits, you can pack multiple indexes into a single variable by shifting and 'or'ing.

An even sneakier way of hiding this extra bit is to use the program counter to store it:

  a:
    int i = 0
    FOR (; i < # elems-1; ++i)
         IF pair(i, i+1) is out of order
             swap pair; goto b
    RETURN
  b:
    FOR (; i < # elems-1; ++i)
         IF pair(i, i+1) is out of order
             swap pair
    GOTO a
If the program is running the "b" loop, some pair has been swapped, so when it finishes the loop, it knows to re-run the "a" loop. If the program completes the "a" loop, it knows no pair was swapped, and can finish.

Edit: formatting

thelema314··on Under the hood of C++ lambdas and std::function
I kind of wish this article had gotten into some details of how various compilers implement std::function; while it was nice to see some details of clang++'s 32-byte size of all std::function to remove the need for dynamic memory for many function objects, I'm still wishing I had more details on efficiency/cost of using std::function vs. plain lambdas or function pointers or other solutions.
thelema314··on What's in a Build Tool?
To depend on compiler flags, I do this:

## compiler_flags file keeps a copy of the compile flags $(builddir)/compiler_flags: force mkdir -p $(builddir) echo '$(CPPFLAGS) $(CFLAGS)' | cmp -s - $@ || echo '$(CPPFLAGS) $(CFLAGS)' > $@

##rebuild all objects if compile flags change $(LIBOBJECTS) $(RTLLIBOBJECTS) $(OPTLIBOBJECTS) $(TESTOBJECTS) $(builddir)/init_qt_workdir: $(builddir)/compiler_flags

I"m pretty happy with the results.

thelema314··on Complete Enumeration Arguments Deemed Harmful
The most succinct informal description I have for NP-complete problems is lack of optimal substructure; that is, given a solution to part of the problem, it's possible for that to not help at all for solving the whole problem.

For Traveling Salesman, this means that given the best tour for an N-city graph, the best tour for the same graph augmented by a single vertex could be entirely different.

thelema314··on Complete Enumeration Arguments Deemed Harmful
> Given any two cities, a and b out of N, we do not know which one is visited first in the shortest path, and we certainly don't know what a's successor will be in the solution. Even verifying a solution to the problem (Is this sequence of cities the shortest path?) cannot be done in polynomial time.

Usually, the problem is simplified to a threshold test, like: Does this tour have path length < X? These kind of problems are equivalently difficult to produce solutions for in the general case, but are straightforward to verify.

thelema314··on Rainbow, Binary, Debt Friendship Bracelets
I found the redundancy of having the same number stored on both also unnecessary, and a scheme that just reorganized where the bracelets are seems better. The "friendship" component of having identical bracelets is lost, but information density is certainly improved. Instead of considering this as one's complement, just give the right bracelet sum to one person and all the rest of the bracelets to the other.
thelema314··on Ask HN: Who is hiring? (October 2015)
NetSpeed Systems (http://www.netspeedsystems.com) | Full-time | ONSITE | San Jose, CA

We build software that designs and simulates Network on Chip interconnects along with the hardware to implement that interconnect in our customers' chips. We need more software people to write C++ code that generates the Verilog implementation of the interconnect and to improve the built-in performance models of our components.

See http://netspeedsystems.com/careers for some more specifics, although we're interested in more variety than just what that page indicates.

thelema314··on Patent Owner Insists the “Integers” Do Not Include the Number One
It seems clear that they used the word "integer" to clarify that only whole number multiples were allowed, and not 1.5, 2.7, etc. As to whether 1 is allowed, that's not determined one way or the other by the use of the word "integer".

As to the patent owner originally accusing n=1 being part of the infringing apparatus/method, I agree that they shouldn't have done this if n=1 doesn't make sense in the context of their patent. That's more likely the mistake then the current CC.

thelema314··on Patent Owner Insists the “Integers” Do Not Include the Number One
This is quite exaggerated; looking at the actual document [1], it's clear that they're claiming that in the context of the specification, "integer multiple of transmission time interval" doesn't include negative multiples, or 0 or even 1 * transmission time interval. As much as I don't like patent trolls, I see pretty clearly that the intent is 2, 3, 4, etc. times the transmission time interval.

[1] https://www.eff.org/files/2015/09/24/core_wireless_claim_con...

thelema314··on The Limitations of the Ethernet CRC and TCP/IP Checksums for Error Detection
The suggestion at the end to use zip compression to protect your files seems funny; when we're talking about extremely rare errors, CRC32 seems insufficient to really protect.
thelema314··on Human generated semi-random binary stream
My first thought along these lines is to also dump a whitened version of the provided entropy that might be more useful than the raw bits.
thelema314··on GistDeck – turn markdown gist into slide
I see a problem with code syntax highlighting on slide 13; anyone else?
thelema314··on Bitcoin Is Fundamentally Flawed
I expect this will cause little problem; if 1M bitcoins are lost, the system will just work as if there were only 20M bitcoins created instead of 21M bitcoins. Everything would be a little less expensive because bitcoins would each be worth about 5% more.
thelema314··on A worthy Ultrabook appears: the ThinkPad X1 Carbon reviewed
VGA ports are too tall to fit in ultra-slim laptops. RJ45 is a bit smaller, but must also be sacrificed for slimness.
thelema314··on Sal Khan explains SOPA / PIPA
A very nice video, except the particular passage referred to has the clause "designed for..., has only limited purpose or use other than, or is marketed for..." violating various laws. I don't think any of his examples would fall under any of these categories.
thelema314··on "DIY Dropbox" or "2-way directory (r)sync with proper deletion"
Unison anyone? http://www.cis.upenn.edu/~bcpierce/unison/
thelema314··on Try OCaml in Your Browser
1) Strict yet expressive typing. Find errors at compile time rather than runtime, while still allowing a very flexible set of values to be described. (tuples, sets, lists, hashtables, maps, arrays, records, objects, etc.)

2) Efficiency. Python, perl, ruby are all... slow. OCaml compiles to very efficient native code. Xavier Leroy's accomplishment is a high level language that's within 2x the speed of C.

thelema314··on C++11 multithreading tutorial
> - Use std::vector instead of C Array

What about std::array?

thelema314··on How to create a biased coin and prove it with math
Granted. But in either case, there's no proof - only a probability that you haven't reached an incorrect conclusion. I associate the concept of proof with logical certainty, and no statistical method will give you that.
thelema314··on How to create a biased coin and prove it with math
I have a problem with the idea behind this - there's no proof that the coin is biased; even flipping it a hundred times and getting the same result is possible with an unbiased coin. All that statistics gives you is the probability of having a result at least this extreme with an unbiased coin. If this probability is low enough (often 1 in 20 or 1 in 100, but sometimes as low as 1 in 5), the "hypothesis" of the coin being unbiased is rejected, but this rejection will happen erroneously 1 in 20 or 100 or 5 times. As exemplified by the XKCD cartoon: http://xkcd.com/882/
thelema314··on Paypal gives FBI the list of IP Address of 1,000 Anomymous hackers
3678 packets / 2.5 hours = One packet every 2.44 seconds * 1500 byte MTU = 3.5KB/s Yup, a 4800 baud modem.
thelema314··on A “perfect” voting system
The entire point of this system is to produce a voting system that does not discourage people voting per their conscience. All deterministic systems so far have flaws that encourage people to vote "strategically" to improve the chances of their candidate being elected or other flaws.
thelema314··on Throw away the keys: Easy, Minimal Perfect Hashing
Article Text:

In part 1 of this series, I described how to find the closest match in a dictionary of words using a Trie. Such searches are useful because users often mistype queries. But tries can take a lot of memory -- so much that they may not even fit in the 2 to 4 GB limit imposed by 32-bit operating systems.

In part 2, I described how to build a MA-FSA (also known as a DAWG). The MA-FSA greatly reduces the number of nodes needed to store the same information as a trie. They are quick to build, and you can safely substitute an MA-FSA for a trie in the fuzzy search algorithm.

There is a problem. Since the last node in a word is shared with other words, it is not possible to store data in it. We can use the MA-FSA to check if a word (or a close match) is in the dictionary, but we cannot look up any other information about the word!

If we need extra information about the words, we can use an additional data structure along with the MA-FSA. We can store it in a hash table. Here's an example of a hash table that uses separate chaining. To look up a word, we run it through a hash function, H() which returns a number. We then look at all the items in that "bucket" to find the data. Since there should be only a small number of words in each bucket, the search is very fast.

Notice that the table needs to store the keys (the words that we want to look up) as well as the data associated with them. It needs them to resolve collisions -- when two words hash to the same bucket. Sometimes these keys take up too much storage space. For example, you might be storing information about all of the URLs on the entire Internet, or parts of the human genome. In our case, we already store the words in the MA-FSA, and it is redundant to duplicate them in the hash table as well. If we could guarantee that there were no collisions, we could throw away the keys of the hash table.

Minimal perfect hashing Perfect hashing is a technique for building a hash table with no collisions. It is only possible to build one when we know all of the keys in advance. Minimal perfect hashing implies that the resulting table contains one entry for each key, and no empty slots.

We use two levels of hash functions. The first one, H(key), gets a position in an intermediate array, G. The second function, F(d, key), uses the extra information from G to find the unique position for the key. The scheme will always returns a value, so it works as long as we know for sure that what we are searching for is in the table. Otherwise, it will return bad information. Fortunately, our MA-FSA can tell us whether a value is in the table. If we did not have this information, then we could also store the keys with the values in the value table.

In the example below, the words "blue" and "cat" both hash to the same position using the H() function. However, the second level hash, F, combined with the d-value, puts them into different slots.

How do we find the intermediate table, G? By trial and error. But don't worry, if we do it carefully, according to this paper, it only takes linear time. In step 1, we place the keys into buckets according to the first hash function, H.

In step 2, we process the buckets largest first and try to place all the keys it contains in an empty slot using F(d=1, key). If that is unsuccessful, we keep trying with successively larger values of d. It sounds like it would take a long time, but in reality it doesn't. Since we try to find the d value for the buckets with the most items early, they are likely to find empty spots. When we get to buckets with just one item, we can simply place them into the next unoccopied spot.

Here's some python code to demonstrate the technique. In it, we use H = F(0, key) to simplify things.

<SNIP>

Experimental Results I prepared separate lists of randomly selected words to test whether the runtime is really linear as claimed. Number of items Time (s) 100000 2.24 200000 4.48 300000 6.68 400000 9.27 500000 11.71 600000 13.81 700000 16.72 800000 18.78 900000 21.12 1000000 24.816 Here's a pretty chart.

CMPH CMPH is an LGPL library that contains a really fast implementation of several perfect hash function algorithms. In addition, it compresses the G array so that it can still be used without decompressing it. It was created by the authors of the paper that I cited. Botelho's thesis is a great introduction to perfect hashing theory and algorithms. gperf Gperf is another open source solution. However, it is designed to work with small sets of keys, not large dictionaries of millions of words. It expects you to embed the resulting tables directly in your C source files.

thelema314··on In what cases is Java faster than C++?
Actually, OCaml never generates objects like this on the stack - value creation is always taken literally. The OCaml compiler is really allocating all those records. It's just that their lifetime is almost zero, so the cost to clean them up is zero (as none get promoted from the minor heap to the major heap). And the cost to create them is almost zero, just a += and a compare.
thelema314··on Binggate is Bullshit
I don't think either google nor bing searches for the term in wikimedia. I think google spent time finding this misspelling, and bing is sitting on the shoulders of a giant, capturing the same effect with their clickstream analysis.
thelema314··on Is The Chinese Supercomputer Our Sputnik?
The Chinese CPU is junk, and the chinese supercomputer is built out of US parts - I wouldn't be too apocalyptic about technological superiority for some years yet.
thelema314··on A beginners guide to OCaml internals
I've enjoyed these first two - they're a good summary of how things are laid out, without getting into too many of the messy details. I miss an explanation of closures, but that'd require lots of messy details, I'm sure.
Page 1 of 2Next →