Implement HighPrecision01 distribution - #372

Closed
pitdicker wants to merge 2 commits into
rust-random:masterfrom
pitdicker:highprecision01
Closed

Implement HighPrecision01 distribution#372
pitdicker wants to merge 2 commits into
rust-random:masterfrom
pitdicker:highprecision01

Conversation

@pitdicker

Copy link
Copy Markdown
Contributor

Re-opening #320.

pitdickerand others added 2 commits April 4, 2018 20:07
@dhardy

Copy link
Copy Markdown
Member

So if I recall correctly we want to try implementing HighPrecisionUniform (or some shorter name) based on this idea plus @pitdicker's previous split-around-zero trick to produce high-precision floats over arbitrary ranges.

This is thus a good addition but doesn't have to be done before 0.5.

@dhardydhardy added X-enhancement F-new-int Functionality: new, within Rand labels Apr 16, 2018
@vks

vks commented Apr 23, 2018

Copy link
Copy Markdown
Contributor

Instead of testing the average, I think it makes more sense to fill a histogram. With a sufficient number of samples, it should be possible to distinguish the biased Standard from the unbiased HighPrecision01 by looking at the lowest bins. However, it might take too many sample to be feasible as a test. In any case, even with lower samples a histogram would be preferable to just calculating the average.

I think it might make sense to expose LowPrecison01 in case we ever want to change Standard. Maybe Biased01 and Unbiased01 are better names?

@vks

vks commented Apr 23, 2018

Copy link
Copy Markdown
Contributor

One caveat (from http://xoroshiro.di.unimi.it/) that should probably be addressed in the documentation:

Interestingly, these are not the only notions of “uniformity” you can come up with. Another possibility is that of generating 1074-bit integers, normalize and return the nearest value representable as a 64-bit double (this is the theory—in practice, you will almost never use more than two integers per double as the remaining bits would not be representable). This approach guarantees that all representable doubles could be in principle generated, albeit not every returned double will appear with the same probability. A reference implementation can be found here. Note that unless your generator has at least 1074 bits of state and suitable equidistribution properties, the code above will not do what you expect (e.g., it might never return zero).

@dhardydhardy mentioned this pull request May 24, 2018
@sicking

sicking commented Jun 4, 2018

Copy link
Copy Markdown
Contributor

Is there still interest in this?

I wrote a generator a while back for values in the [0, 1) range using maximum precision here.

What the algorithm effectively does is that it picks a random, but perfectly unbiased, point on the continuous line between 0 and 1. It then rounds that down to the nearest point that can be represented as a f32/f64.

This means that all values in the [0, 1) range that can be represented by an f32/f64 can be returned by the algorithm. However not all values are equally likely since f32/f64 has many more values close to 0 than close to 1, and so likelyhood of rounding to a particular value close to 0 is smaller, than a particular value close to 1.

Happy to adapt this to rand if there's interest?

There's also code in the same file which uses the same approach to generate values between two arbitrary, finite, f32/f64. I.e. it picks an random unbiased point on the continuous line between the start and end and then rounds to the closest f32/f64 below the picked point. However it relies on the num_bigint crate so would require more work to port.

@sicking

Copy link
Copy Markdown
Contributor

I should also mention that the code for high-precision sampling for an arbitrary range is quite slow. I mainly wrote it for funsies to see what it'd look like.

However the code for high-precision sampling in [0, 1) has more reasonable performance. Though obviously slower than the Standard implementation.

@dhardy

Copy link
Copy Markdown
Member

IIRC this implementation works fine and has reasonable performance, but we were considering going with arbitrary ranges. On the other hand, if that's not easy to do it might not be a good option.

We were planning on adding distributions::HighPrecision which is just the full-precision equivalent of Uniform.

@sicking

sicking commented Jun 5, 2018

Copy link
Copy Markdown
Contributor

Cool, the existing implementation here does seem faster than the one I wrote, so I think we should go with this one.

Happy to port the arbitrary-range full-precision implementation that I wrote if there's a interest? The current code is here.

Would there be any perf goals in mind?

@sicking

Copy link
Copy Markdown
Contributor

FWIW, i benchmarked my full-precision-arbitrary-range implementation and it's about 50-100x slower than the low-precision version, which is similar to what's in Uniform<f32/64>.

It's not been perf optimized much, so I'm sure that can be lowered some. But it's pretty darn slow.

@sicking

Copy link
Copy Markdown
Contributor

I'm working on a more performant implementation here. Still doesn't work, so can't get perf numbers yet.

@sicking

Copy link
Copy Markdown
Contributor

The implementation over here is now working and benchmarked. It's looking about 6-9x slower than the current Uniform implementation which seems viable? I'm sure some more performance can be squeezed out as well.

@dhardy

Copy link
Copy Markdown
Member

Good work. I think with that performance it is probably worth including this somehow, though obviously not as the default option. I guess we may also want a different implementation for high-precision Standard?

I would say open a PR, but it probably makes sense to resolve #494 first.

@sickingsicking mentioned this pull request Jun 27, 2018
@pitdicker

Copy link
Copy Markdown
ContributorAuthor

Closing in favor of #531

@dhardy

Copy link
Copy Markdown
Member

Why? As I understand this has better performance, but only works over [0, 1), so they seem to be mutually exclusive.

@dhardydhardy reopened this Jul 18, 2018
@sicking

Copy link
Copy Markdown
Contributor

The PR in #531 includes the commits here, but updated to compile on master. #531 contains both HighPrecision01 and HighPrecision distributions.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

F-new-intFunctionality: new, within Rand

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@pitdicker@dhardy@vks@sicking
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Implement HighPrecision01 distribution - #372

Closed
pitdicker wants to merge 2 commits into
rust-random:masterfrom
pitdicker:highprecision01
Closed

Implement HighPrecision01 distribution#372
pitdicker wants to merge 2 commits into
rust-random:masterfrom
pitdicker:highprecision01

Conversation

@pitdicker

Copy link
Copy Markdown
Contributor

Re-opening #320.

pitdickerand others added 2 commits April 4, 2018 20:07
@dhardy

Copy link
Copy Markdown
Member

So if I recall correctly we want to try implementing HighPrecisionUniform (or some shorter name) based on this idea plus @pitdicker's previous split-around-zero trick to produce high-precision floats over arbitrary ranges.

This is thus a good addition but doesn't have to be done before 0.5.

@dhardydhardy added X-enhancement F-new-int Functionality: new, within Rand labels Apr 16, 2018
@vks

vks commented Apr 23, 2018

Copy link
Copy Markdown
Contributor

Instead of testing the average, I think it makes more sense to fill a histogram. With a sufficient number of samples, it should be possible to distinguish the biased Standard from the unbiased HighPrecision01 by looking at the lowest bins. However, it might take too many sample to be feasible as a test. In any case, even with lower samples a histogram would be preferable to just calculating the average.

I think it might make sense to expose LowPrecison01 in case we ever want to change Standard. Maybe Biased01 and Unbiased01 are better names?

@vks

vks commented Apr 23, 2018

Copy link
Copy Markdown
Contributor

One caveat (from http://xoroshiro.di.unimi.it/) that should probably be addressed in the documentation:

Interestingly, these are not the only notions of “uniformity” you can come up with. Another possibility is that of generating 1074-bit integers, normalize and return the nearest value representable as a 64-bit double (this is the theory—in practice, you will almost never use more than two integers per double as the remaining bits would not be representable). This approach guarantees that all representable doubles could be in principle generated, albeit not every returned double will appear with the same probability. A reference implementation can be found here. Note that unless your generator has at least 1074 bits of state and suitable equidistribution properties, the code above will not do what you expect (e.g., it might never return zero).

@dhardydhardy mentioned this pull request May 24, 2018
@sicking

sicking commented Jun 4, 2018

Copy link
Copy Markdown
Contributor

Is there still interest in this?

I wrote a generator a while back for values in the [0, 1) range using maximum precision here.

What the algorithm effectively does is that it picks a random, but perfectly unbiased, point on the continuous line between 0 and 1. It then rounds that down to the nearest point that can be represented as a f32/f64.

This means that all values in the [0, 1) range that can be represented by an f32/f64 can be returned by the algorithm. However not all values are equally likely since f32/f64 has many more values close to 0 than close to 1, and so likelyhood of rounding to a particular value close to 0 is smaller, than a particular value close to 1.

Happy to adapt this to rand if there's interest?

There's also code in the same file which uses the same approach to generate values between two arbitrary, finite, f32/f64. I.e. it picks an random unbiased point on the continuous line between the start and end and then rounds to the closest f32/f64 below the picked point. However it relies on the num_bigint crate so would require more work to port.

@sicking

Copy link
Copy Markdown
Contributor

I should also mention that the code for high-precision sampling for an arbitrary range is quite slow. I mainly wrote it for funsies to see what it'd look like.

However the code for high-precision sampling in [0, 1) has more reasonable performance. Though obviously slower than the Standard implementation.

@dhardy

Copy link
Copy Markdown
Member

IIRC this implementation works fine and has reasonable performance, but we were considering going with arbitrary ranges. On the other hand, if that's not easy to do it might not be a good option.

We were planning on adding distributions::HighPrecision which is just the full-precision equivalent of Uniform.

@sicking

sicking commented Jun 5, 2018

Copy link
Copy Markdown
Contributor

Cool, the existing implementation here does seem faster than the one I wrote, so I think we should go with this one.

Happy to port the arbitrary-range full-precision implementation that I wrote if there's a interest? The current code is here.

Would there be any perf goals in mind?

@sicking

Copy link
Copy Markdown
Contributor

FWIW, i benchmarked my full-precision-arbitrary-range implementation and it's about 50-100x slower than the low-precision version, which is similar to what's in Uniform<f32/64>.

It's not been perf optimized much, so I'm sure that can be lowered some. But it's pretty darn slow.

@sicking

Copy link
Copy Markdown
Contributor

I'm working on a more performant implementation here. Still doesn't work, so can't get perf numbers yet.

@sicking

Copy link
Copy Markdown
Contributor

The implementation over here is now working and benchmarked. It's looking about 6-9x slower than the current Uniform implementation which seems viable? I'm sure some more performance can be squeezed out as well.

@dhardy

Copy link
Copy Markdown
Member

Good work. I think with that performance it is probably worth including this somehow, though obviously not as the default option. I guess we may also want a different implementation for high-precision Standard?

I would say open a PR, but it probably makes sense to resolve #494 first.

@sickingsicking mentioned this pull request Jun 27, 2018
@pitdicker

Copy link
Copy Markdown
ContributorAuthor

Closing in favor of #531

@dhardy

Copy link
Copy Markdown
Member

Why? As I understand this has better performance, but only works over [0, 1), so they seem to be mutually exclusive.

@dhardydhardy reopened this Jul 18, 2018
@sicking

Copy link
Copy Markdown
Contributor

The PR in #531 includes the commits here, but updated to compile on master. #531 contains both HighPrecision01 and HighPrecision distributions.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

F-new-intFunctionality: new, within Rand

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@pitdicker@dhardy@vks@sicking
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Implement HighPrecision01 distribution - #372

Closed
pitdicker wants to merge 2 commits into
rust-random:masterfrom
pitdicker:highprecision01
Closed

Implement HighPrecision01 distribution#372
pitdicker wants to merge 2 commits into
rust-random:masterfrom
pitdicker:highprecision01

Conversation

@pitdicker

Copy link
Copy Markdown
Contributor

Re-opening #320.

pitdickerand others added 2 commits April 4, 2018 20:07
@dhardy

Copy link
Copy Markdown
Member

So if I recall correctly we want to try implementing HighPrecisionUniform (or some shorter name) based on this idea plus @pitdicker's previous split-around-zero trick to produce high-precision floats over arbitrary ranges.

This is thus a good addition but doesn't have to be done before 0.5.

@dhardydhardy added X-enhancement F-new-int Functionality: new, within Rand labels Apr 16, 2018
@vks

vks commented Apr 23, 2018

Copy link
Copy Markdown
Contributor

Instead of testing the average, I think it makes more sense to fill a histogram. With a sufficient number of samples, it should be possible to distinguish the biased Standard from the unbiased HighPrecision01 by looking at the lowest bins. However, it might take too many sample to be feasible as a test. In any case, even with lower samples a histogram would be preferable to just calculating the average.

I think it might make sense to expose LowPrecison01 in case we ever want to change Standard. Maybe Biased01 and Unbiased01 are better names?

@vks

vks commented Apr 23, 2018

Copy link
Copy Markdown
Contributor

One caveat (from http://xoroshiro.di.unimi.it/) that should probably be addressed in the documentation:

Interestingly, these are not the only notions of “uniformity” you can come up with. Another possibility is that of generating 1074-bit integers, normalize and return the nearest value representable as a 64-bit double (this is the theory—in practice, you will almost never use more than two integers per double as the remaining bits would not be representable). This approach guarantees that all representable doubles could be in principle generated, albeit not every returned double will appear with the same probability. A reference implementation can be found here. Note that unless your generator has at least 1074 bits of state and suitable equidistribution properties, the code above will not do what you expect (e.g., it might never return zero).

@dhardydhardy mentioned this pull request May 24, 2018
@sicking

sicking commented Jun 4, 2018

Copy link
Copy Markdown
Contributor

Is there still interest in this?

I wrote a generator a while back for values in the [0, 1) range using maximum precision here.

What the algorithm effectively does is that it picks a random, but perfectly unbiased, point on the continuous line between 0 and 1. It then rounds that down to the nearest point that can be represented as a f32/f64.

This means that all values in the [0, 1) range that can be represented by an f32/f64 can be returned by the algorithm. However not all values are equally likely since f32/f64 has many more values close to 0 than close to 1, and so likelyhood of rounding to a particular value close to 0 is smaller, than a particular value close to 1.

Happy to adapt this to rand if there's interest?

There's also code in the same file which uses the same approach to generate values between two arbitrary, finite, f32/f64. I.e. it picks an random unbiased point on the continuous line between the start and end and then rounds to the closest f32/f64 below the picked point. However it relies on the num_bigint crate so would require more work to port.

@sicking

Copy link
Copy Markdown
Contributor

I should also mention that the code for high-precision sampling for an arbitrary range is quite slow. I mainly wrote it for funsies to see what it'd look like.

However the code for high-precision sampling in [0, 1) has more reasonable performance. Though obviously slower than the Standard implementation.

@dhardy

Copy link
Copy Markdown
Member

IIRC this implementation works fine and has reasonable performance, but we were considering going with arbitrary ranges. On the other hand, if that's not easy to do it might not be a good option.

We were planning on adding distributions::HighPrecision which is just the full-precision equivalent of Uniform.

@sicking

sicking commented Jun 5, 2018

Copy link
Copy Markdown
Contributor

Cool, the existing implementation here does seem faster than the one I wrote, so I think we should go with this one.

Happy to port the arbitrary-range full-precision implementation that I wrote if there's a interest? The current code is here.

Would there be any perf goals in mind?

@sicking

Copy link
Copy Markdown
Contributor

FWIW, i benchmarked my full-precision-arbitrary-range implementation and it's about 50-100x slower than the low-precision version, which is similar to what's in Uniform<f32/64>.

It's not been perf optimized much, so I'm sure that can be lowered some. But it's pretty darn slow.

@sicking

Copy link
Copy Markdown
Contributor

I'm working on a more performant implementation here. Still doesn't work, so can't get perf numbers yet.

@sicking

Copy link
Copy Markdown
Contributor

The implementation over here is now working and benchmarked. It's looking about 6-9x slower than the current Uniform implementation which seems viable? I'm sure some more performance can be squeezed out as well.

@dhardy

Copy link
Copy Markdown
Member

Good work. I think with that performance it is probably worth including this somehow, though obviously not as the default option. I guess we may also want a different implementation for high-precision Standard?

I would say open a PR, but it probably makes sense to resolve #494 first.

@sickingsicking mentioned this pull request Jun 27, 2018
@pitdicker

Copy link
Copy Markdown
ContributorAuthor

Closing in favor of #531

@dhardy

Copy link
Copy Markdown
Member

Why? As I understand this has better performance, but only works over [0, 1), so they seem to be mutually exclusive.

@dhardydhardy reopened this Jul 18, 2018
@sicking

Copy link
Copy Markdown
Contributor

The PR in #531 includes the commits here, but updated to compile on master. #531 contains both HighPrecision01 and HighPrecision distributions.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

F-new-intFunctionality: new, within Rand

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@pitdicker@dhardy@vks@sicking
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Implement HighPrecision01 distribution - #372

Closed
pitdicker wants to merge 2 commits into
rust-random:masterfrom
pitdicker:highprecision01
Closed

Implement HighPrecision01 distribution#372
pitdicker wants to merge 2 commits into
rust-random:masterfrom
pitdicker:highprecision01

Conversation

@pitdicker

Copy link
Copy Markdown
Contributor

Re-opening #320.

pitdickerand others added 2 commits April 4, 2018 20:07
@dhardy

Copy link
Copy Markdown
Member

So if I recall correctly we want to try implementing HighPrecisionUniform (or some shorter name) based on this idea plus @pitdicker's previous split-around-zero trick to produce high-precision floats over arbitrary ranges.

This is thus a good addition but doesn't have to be done before 0.5.

@dhardydhardy added X-enhancement F-new-int Functionality: new, within Rand labels Apr 16, 2018
@vks

vks commented Apr 23, 2018

Copy link
Copy Markdown
Contributor

Instead of testing the average, I think it makes more sense to fill a histogram. With a sufficient number of samples, it should be possible to distinguish the biased Standard from the unbiased HighPrecision01 by looking at the lowest bins. However, it might take too many sample to be feasible as a test. In any case, even with lower samples a histogram would be preferable to just calculating the average.

I think it might make sense to expose LowPrecison01 in case we ever want to change Standard. Maybe Biased01 and Unbiased01 are better names?

@vks

vks commented Apr 23, 2018

Copy link
Copy Markdown
Contributor

One caveat (from http://xoroshiro.di.unimi.it/) that should probably be addressed in the documentation:

Interestingly, these are not the only notions of “uniformity” you can come up with. Another possibility is that of generating 1074-bit integers, normalize and return the nearest value representable as a 64-bit double (this is the theory—in practice, you will almost never use more than two integers per double as the remaining bits would not be representable). This approach guarantees that all representable doubles could be in principle generated, albeit not every returned double will appear with the same probability. A reference implementation can be found here. Note that unless your generator has at least 1074 bits of state and suitable equidistribution properties, the code above will not do what you expect (e.g., it might never return zero).

@dhardydhardy mentioned this pull request May 24, 2018
@sicking

sicking commented Jun 4, 2018

Copy link
Copy Markdown
Contributor

Is there still interest in this?

I wrote a generator a while back for values in the [0, 1) range using maximum precision here.

What the algorithm effectively does is that it picks a random, but perfectly unbiased, point on the continuous line between 0 and 1. It then rounds that down to the nearest point that can be represented as a f32/f64.

This means that all values in the [0, 1) range that can be represented by an f32/f64 can be returned by the algorithm. However not all values are equally likely since f32/f64 has many more values close to 0 than close to 1, and so likelyhood of rounding to a particular value close to 0 is smaller, than a particular value close to 1.

Happy to adapt this to rand if there's interest?

There's also code in the same file which uses the same approach to generate values between two arbitrary, finite, f32/f64. I.e. it picks an random unbiased point on the continuous line between the start and end and then rounds to the closest f32/f64 below the picked point. However it relies on the num_bigint crate so would require more work to port.

@sicking

Copy link
Copy Markdown
Contributor

I should also mention that the code for high-precision sampling for an arbitrary range is quite slow. I mainly wrote it for funsies to see what it'd look like.

However the code for high-precision sampling in [0, 1) has more reasonable performance. Though obviously slower than the Standard implementation.

@dhardy

Copy link
Copy Markdown
Member

IIRC this implementation works fine and has reasonable performance, but we were considering going with arbitrary ranges. On the other hand, if that's not easy to do it might not be a good option.

We were planning on adding distributions::HighPrecision which is just the full-precision equivalent of Uniform.

@sicking

sicking commented Jun 5, 2018

Copy link
Copy Markdown
Contributor

Cool, the existing implementation here does seem faster than the one I wrote, so I think we should go with this one.

Happy to port the arbitrary-range full-precision implementation that I wrote if there's a interest? The current code is here.

Would there be any perf goals in mind?

@sicking

Copy link
Copy Markdown
Contributor

FWIW, i benchmarked my full-precision-arbitrary-range implementation and it's about 50-100x slower than the low-precision version, which is similar to what's in Uniform<f32/64>.

It's not been perf optimized much, so I'm sure that can be lowered some. But it's pretty darn slow.

@sicking

Copy link
Copy Markdown
Contributor

I'm working on a more performant implementation here. Still doesn't work, so can't get perf numbers yet.

@sicking

Copy link
Copy Markdown
Contributor

The implementation over here is now working and benchmarked. It's looking about 6-9x slower than the current Uniform implementation which seems viable? I'm sure some more performance can be squeezed out as well.

@dhardy

Copy link
Copy Markdown
Member

Good work. I think with that performance it is probably worth including this somehow, though obviously not as the default option. I guess we may also want a different implementation for high-precision Standard?

I would say open a PR, but it probably makes sense to resolve #494 first.

@sickingsicking mentioned this pull request Jun 27, 2018
@pitdicker

Copy link
Copy Markdown
ContributorAuthor

Closing in favor of #531

@dhardy

Copy link
Copy Markdown
Member

Why? As I understand this has better performance, but only works over [0, 1), so they seem to be mutually exclusive.

@dhardydhardy reopened this Jul 18, 2018
@sicking

Copy link
Copy Markdown
Contributor

The PR in #531 includes the commits here, but updated to compile on master. #531 contains both HighPrecision01 and HighPrecision distributions.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

F-new-intFunctionality: new, within Rand

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@pitdicker@dhardy@vks@sicking
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Implement HighPrecision01 distribution - #372

Closed
pitdicker wants to merge 2 commits into
rust-random:masterfrom
pitdicker:highprecision01
Closed

Implement HighPrecision01 distribution#372
pitdicker wants to merge 2 commits into
rust-random:masterfrom
pitdicker:highprecision01

Conversation

@pitdicker

Copy link
Copy Markdown
Contributor

Re-opening #320.

pitdickerand others added 2 commits April 4, 2018 20:07
@dhardy

Copy link
Copy Markdown
Member

So if I recall correctly we want to try implementing HighPrecisionUniform (or some shorter name) based on this idea plus @pitdicker's previous split-around-zero trick to produce high-precision floats over arbitrary ranges.

This is thus a good addition but doesn't have to be done before 0.5.

@dhardydhardy added X-enhancement F-new-int Functionality: new, within Rand labels Apr 16, 2018
@vks

vks commented Apr 23, 2018

Copy link
Copy Markdown
Contributor

Instead of testing the average, I think it makes more sense to fill a histogram. With a sufficient number of samples, it should be possible to distinguish the biased Standard from the unbiased HighPrecision01 by looking at the lowest bins. However, it might take too many sample to be feasible as a test. In any case, even with lower samples a histogram would be preferable to just calculating the average.

I think it might make sense to expose LowPrecison01 in case we ever want to change Standard. Maybe Biased01 and Unbiased01 are better names?

@vks

vks commented Apr 23, 2018

Copy link
Copy Markdown
Contributor

One caveat (from http://xoroshiro.di.unimi.it/) that should probably be addressed in the documentation:

Interestingly, these are not the only notions of “uniformity” you can come up with. Another possibility is that of generating 1074-bit integers, normalize and return the nearest value representable as a 64-bit double (this is the theory—in practice, you will almost never use more than two integers per double as the remaining bits would not be representable). This approach guarantees that all representable doubles could be in principle generated, albeit not every returned double will appear with the same probability. A reference implementation can be found here. Note that unless your generator has at least 1074 bits of state and suitable equidistribution properties, the code above will not do what you expect (e.g., it might never return zero).

@dhardydhardy mentioned this pull request May 24, 2018
@sicking

sicking commented Jun 4, 2018

Copy link
Copy Markdown
Contributor

Is there still interest in this?

I wrote a generator a while back for values in the [0, 1) range using maximum precision here.

What the algorithm effectively does is that it picks a random, but perfectly unbiased, point on the continuous line between 0 and 1. It then rounds that down to the nearest point that can be represented as a f32/f64.

This means that all values in the [0, 1) range that can be represented by an f32/f64 can be returned by the algorithm. However not all values are equally likely since f32/f64 has many more values close to 0 than close to 1, and so likelyhood of rounding to a particular value close to 0 is smaller, than a particular value close to 1.

Happy to adapt this to rand if there's interest?

There's also code in the same file which uses the same approach to generate values between two arbitrary, finite, f32/f64. I.e. it picks an random unbiased point on the continuous line between the start and end and then rounds to the closest f32/f64 below the picked point. However it relies on the num_bigint crate so would require more work to port.

@sicking

Copy link
Copy Markdown
Contributor

I should also mention that the code for high-precision sampling for an arbitrary range is quite slow. I mainly wrote it for funsies to see what it'd look like.

However the code for high-precision sampling in [0, 1) has more reasonable performance. Though obviously slower than the Standard implementation.

@dhardy

Copy link
Copy Markdown
Member

IIRC this implementation works fine and has reasonable performance, but we were considering going with arbitrary ranges. On the other hand, if that's not easy to do it might not be a good option.

We were planning on adding distributions::HighPrecision which is just the full-precision equivalent of Uniform.

@sicking

sicking commented Jun 5, 2018

Copy link
Copy Markdown
Contributor

Cool, the existing implementation here does seem faster than the one I wrote, so I think we should go with this one.

Happy to port the arbitrary-range full-precision implementation that I wrote if there's a interest? The current code is here.

Would there be any perf goals in mind?

@sicking

Copy link
Copy Markdown
Contributor

FWIW, i benchmarked my full-precision-arbitrary-range implementation and it's about 50-100x slower than the low-precision version, which is similar to what's in Uniform<f32/64>.

It's not been perf optimized much, so I'm sure that can be lowered some. But it's pretty darn slow.

@sicking

Copy link
Copy Markdown
Contributor

I'm working on a more performant implementation here. Still doesn't work, so can't get perf numbers yet.

@sicking

Copy link
Copy Markdown
Contributor

The implementation over here is now working and benchmarked. It's looking about 6-9x slower than the current Uniform implementation which seems viable? I'm sure some more performance can be squeezed out as well.

@dhardy

Copy link
Copy Markdown
Member

Good work. I think with that performance it is probably worth including this somehow, though obviously not as the default option. I guess we may also want a different implementation for high-precision Standard?

I would say open a PR, but it probably makes sense to resolve #494 first.

@sickingsicking mentioned this pull request Jun 27, 2018
@pitdicker

Copy link
Copy Markdown
ContributorAuthor

Closing in favor of #531

@dhardy

Copy link
Copy Markdown
Member

Why? As I understand this has better performance, but only works over [0, 1), so they seem to be mutually exclusive.

@dhardydhardy reopened this Jul 18, 2018
@sicking

Copy link
Copy Markdown
Contributor

The PR in #531 includes the commits here, but updated to compile on master. #531 contains both HighPrecision01 and HighPrecision distributions.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

F-new-intFunctionality: new, within Rand

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@pitdicker@dhardy@vks@sicking
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Implement HighPrecision01 distribution - #372

Closed
pitdicker wants to merge 2 commits into
rust-random:masterfrom
pitdicker:highprecision01
Closed

Implement HighPrecision01 distribution#372
pitdicker wants to merge 2 commits into
rust-random:masterfrom
pitdicker:highprecision01

Conversation

@pitdicker

Copy link
Copy Markdown
Contributor

Re-opening #320.

pitdickerand others added 2 commits April 4, 2018 20:07
@dhardy

Copy link
Copy Markdown
Member

So if I recall correctly we want to try implementing HighPrecisionUniform (or some shorter name) based on this idea plus @pitdicker's previous split-around-zero trick to produce high-precision floats over arbitrary ranges.

This is thus a good addition but doesn't have to be done before 0.5.

@dhardydhardy added X-enhancement F-new-int Functionality: new, within Rand labels Apr 16, 2018
@vks

vks commented Apr 23, 2018

Copy link
Copy Markdown
Contributor

Instead of testing the average, I think it makes more sense to fill a histogram. With a sufficient number of samples, it should be possible to distinguish the biased Standard from the unbiased HighPrecision01 by looking at the lowest bins. However, it might take too many sample to be feasible as a test. In any case, even with lower samples a histogram would be preferable to just calculating the average.

I think it might make sense to expose LowPrecison01 in case we ever want to change Standard. Maybe Biased01 and Unbiased01 are better names?

@vks

vks commented Apr 23, 2018

Copy link
Copy Markdown
Contributor

One caveat (from http://xoroshiro.di.unimi.it/) that should probably be addressed in the documentation:

Interestingly, these are not the only notions of “uniformity” you can come up with. Another possibility is that of generating 1074-bit integers, normalize and return the nearest value representable as a 64-bit double (this is the theory—in practice, you will almost never use more than two integers per double as the remaining bits would not be representable). This approach guarantees that all representable doubles could be in principle generated, albeit not every returned double will appear with the same probability. A reference implementation can be found here. Note that unless your generator has at least 1074 bits of state and suitable equidistribution properties, the code above will not do what you expect (e.g., it might never return zero).

@dhardydhardy mentioned this pull request May 24, 2018
@sicking

sicking commented Jun 4, 2018

Copy link
Copy Markdown
Contributor

Is there still interest in this?

I wrote a generator a while back for values in the [0, 1) range using maximum precision here.

What the algorithm effectively does is that it picks a random, but perfectly unbiased, point on the continuous line between 0 and 1. It then rounds that down to the nearest point that can be represented as a f32/f64.

This means that all values in the [0, 1) range that can be represented by an f32/f64 can be returned by the algorithm. However not all values are equally likely since f32/f64 has many more values close to 0 than close to 1, and so likelyhood of rounding to a particular value close to 0 is smaller, than a particular value close to 1.

Happy to adapt this to rand if there's interest?

There's also code in the same file which uses the same approach to generate values between two arbitrary, finite, f32/f64. I.e. it picks an random unbiased point on the continuous line between the start and end and then rounds to the closest f32/f64 below the picked point. However it relies on the num_bigint crate so would require more work to port.

@sicking

Copy link
Copy Markdown
Contributor

I should also mention that the code for high-precision sampling for an arbitrary range is quite slow. I mainly wrote it for funsies to see what it'd look like.

However the code for high-precision sampling in [0, 1) has more reasonable performance. Though obviously slower than the Standard implementation.

@dhardy

Copy link
Copy Markdown
Member

IIRC this implementation works fine and has reasonable performance, but we were considering going with arbitrary ranges. On the other hand, if that's not easy to do it might not be a good option.

We were planning on adding distributions::HighPrecision which is just the full-precision equivalent of Uniform.

@sicking

sicking commented Jun 5, 2018

Copy link
Copy Markdown
Contributor

Cool, the existing implementation here does seem faster than the one I wrote, so I think we should go with this one.

Happy to port the arbitrary-range full-precision implementation that I wrote if there's a interest? The current code is here.

Would there be any perf goals in mind?

@sicking

Copy link
Copy Markdown
Contributor

FWIW, i benchmarked my full-precision-arbitrary-range implementation and it's about 50-100x slower than the low-precision version, which is similar to what's in Uniform<f32/64>.

It's not been perf optimized much, so I'm sure that can be lowered some. But it's pretty darn slow.

@sicking

Copy link
Copy Markdown
Contributor

I'm working on a more performant implementation here. Still doesn't work, so can't get perf numbers yet.

@sicking

Copy link
Copy Markdown
Contributor

The implementation over here is now working and benchmarked. It's looking about 6-9x slower than the current Uniform implementation which seems viable? I'm sure some more performance can be squeezed out as well.

@dhardy

Copy link
Copy Markdown
Member

Good work. I think with that performance it is probably worth including this somehow, though obviously not as the default option. I guess we may also want a different implementation for high-precision Standard?

I would say open a PR, but it probably makes sense to resolve #494 first.

@sickingsicking mentioned this pull request Jun 27, 2018
@pitdicker

Copy link
Copy Markdown
ContributorAuthor

Closing in favor of #531

@dhardy

Copy link
Copy Markdown
Member

Why? As I understand this has better performance, but only works over [0, 1), so they seem to be mutually exclusive.

@dhardydhardy reopened this Jul 18, 2018
@sicking

Copy link
Copy Markdown
Contributor

The PR in #531 includes the commits here, but updated to compile on master. #531 contains both HighPrecision01 and HighPrecision distributions.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

F-new-intFunctionality: new, within Rand

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@pitdicker@dhardy@vks@sicking
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Implement HighPrecision01 distribution - #372

Closed
pitdicker wants to merge 2 commits into
rust-random:masterfrom
pitdicker:highprecision01
Closed

Implement HighPrecision01 distribution#372
pitdicker wants to merge 2 commits into
rust-random:masterfrom
pitdicker:highprecision01

Conversation

@pitdicker

Copy link
Copy Markdown
Contributor

Re-opening #320.

pitdickerand others added 2 commits April 4, 2018 20:07
@dhardy

Copy link
Copy Markdown
Member

So if I recall correctly we want to try implementing HighPrecisionUniform (or some shorter name) based on this idea plus @pitdicker's previous split-around-zero trick to produce high-precision floats over arbitrary ranges.

This is thus a good addition but doesn't have to be done before 0.5.

@dhardydhardy added X-enhancement F-new-int Functionality: new, within Rand labels Apr 16, 2018
@vks

vks commented Apr 23, 2018

Copy link
Copy Markdown
Contributor

Instead of testing the average, I think it makes more sense to fill a histogram. With a sufficient number of samples, it should be possible to distinguish the biased Standard from the unbiased HighPrecision01 by looking at the lowest bins. However, it might take too many sample to be feasible as a test. In any case, even with lower samples a histogram would be preferable to just calculating the average.

I think it might make sense to expose LowPrecison01 in case we ever want to change Standard. Maybe Biased01 and Unbiased01 are better names?

@vks

vks commented Apr 23, 2018

Copy link
Copy Markdown
Contributor

One caveat (from http://xoroshiro.di.unimi.it/) that should probably be addressed in the documentation:

Interestingly, these are not the only notions of “uniformity” you can come up with. Another possibility is that of generating 1074-bit integers, normalize and return the nearest value representable as a 64-bit double (this is the theory—in practice, you will almost never use more than two integers per double as the remaining bits would not be representable). This approach guarantees that all representable doubles could be in principle generated, albeit not every returned double will appear with the same probability. A reference implementation can be found here. Note that unless your generator has at least 1074 bits of state and suitable equidistribution properties, the code above will not do what you expect (e.g., it might never return zero).

@dhardydhardy mentioned this pull request May 24, 2018
@sicking

sicking commented Jun 4, 2018

Copy link
Copy Markdown
Contributor

Is there still interest in this?

I wrote a generator a while back for values in the [0, 1) range using maximum precision here.

What the algorithm effectively does is that it picks a random, but perfectly unbiased, point on the continuous line between 0 and 1. It then rounds that down to the nearest point that can be represented as a f32/f64.

This means that all values in the [0, 1) range that can be represented by an f32/f64 can be returned by the algorithm. However not all values are equally likely since f32/f64 has many more values close to 0 than close to 1, and so likelyhood of rounding to a particular value close to 0 is smaller, than a particular value close to 1.

Happy to adapt this to rand if there's interest?

There's also code in the same file which uses the same approach to generate values between two arbitrary, finite, f32/f64. I.e. it picks an random unbiased point on the continuous line between the start and end and then rounds to the closest f32/f64 below the picked point. However it relies on the num_bigint crate so would require more work to port.

@sicking

Copy link
Copy Markdown
Contributor

I should also mention that the code for high-precision sampling for an arbitrary range is quite slow. I mainly wrote it for funsies to see what it'd look like.

However the code for high-precision sampling in [0, 1) has more reasonable performance. Though obviously slower than the Standard implementation.

@dhardy

Copy link
Copy Markdown
Member

IIRC this implementation works fine and has reasonable performance, but we were considering going with arbitrary ranges. On the other hand, if that's not easy to do it might not be a good option.

We were planning on adding distributions::HighPrecision which is just the full-precision equivalent of Uniform.

@sicking

sicking commented Jun 5, 2018

Copy link
Copy Markdown
Contributor

Cool, the existing implementation here does seem faster than the one I wrote, so I think we should go with this one.

Happy to port the arbitrary-range full-precision implementation that I wrote if there's a interest? The current code is here.

Would there be any perf goals in mind?

@sicking

Copy link
Copy Markdown
Contributor

FWIW, i benchmarked my full-precision-arbitrary-range implementation and it's about 50-100x slower than the low-precision version, which is similar to what's in Uniform<f32/64>.

It's not been perf optimized much, so I'm sure that can be lowered some. But it's pretty darn slow.

@sicking

Copy link
Copy Markdown
Contributor

I'm working on a more performant implementation here. Still doesn't work, so can't get perf numbers yet.

@sicking

Copy link
Copy Markdown
Contributor

The implementation over here is now working and benchmarked. It's looking about 6-9x slower than the current Uniform implementation which seems viable? I'm sure some more performance can be squeezed out as well.

@dhardy

Copy link
Copy Markdown
Member

Good work. I think with that performance it is probably worth including this somehow, though obviously not as the default option. I guess we may also want a different implementation for high-precision Standard?

I would say open a PR, but it probably makes sense to resolve #494 first.

@sickingsicking mentioned this pull request Jun 27, 2018
@pitdicker

Copy link
Copy Markdown
ContributorAuthor

Closing in favor of #531

@dhardy

Copy link
Copy Markdown
Member

Why? As I understand this has better performance, but only works over [0, 1), so they seem to be mutually exclusive.

@dhardydhardy reopened this Jul 18, 2018
@sicking

Copy link
Copy Markdown
Contributor

The PR in #531 includes the commits here, but updated to compile on master. #531 contains both HighPrecision01 and HighPrecision distributions.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

F-new-intFunctionality: new, within Rand

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@pitdicker@dhardy@vks@sicking
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Implement HighPrecision01 distribution - #372

Closed
pitdicker wants to merge 2 commits into
rust-random:masterfrom
pitdicker:highprecision01
Closed

Implement HighPrecision01 distribution#372
pitdicker wants to merge 2 commits into
rust-random:masterfrom
pitdicker:highprecision01

Conversation

@pitdicker

Copy link
Copy Markdown
Contributor

Re-opening #320.

pitdickerand others added 2 commits April 4, 2018 20:07
@dhardy

Copy link
Copy Markdown
Member

So if I recall correctly we want to try implementing HighPrecisionUniform (or some shorter name) based on this idea plus @pitdicker's previous split-around-zero trick to produce high-precision floats over arbitrary ranges.

This is thus a good addition but doesn't have to be done before 0.5.

@dhardydhardy added X-enhancement F-new-int Functionality: new, within Rand labels Apr 16, 2018
@vks

vks commented Apr 23, 2018

Copy link
Copy Markdown
Contributor

Instead of testing the average, I think it makes more sense to fill a histogram. With a sufficient number of samples, it should be possible to distinguish the biased Standard from the unbiased HighPrecision01 by looking at the lowest bins. However, it might take too many sample to be feasible as a test. In any case, even with lower samples a histogram would be preferable to just calculating the average.

I think it might make sense to expose LowPrecison01 in case we ever want to change Standard. Maybe Biased01 and Unbiased01 are better names?

@vks

vks commented Apr 23, 2018

Copy link
Copy Markdown
Contributor

One caveat (from http://xoroshiro.di.unimi.it/) that should probably be addressed in the documentation:

Interestingly, these are not the only notions of “uniformity” you can come up with. Another possibility is that of generating 1074-bit integers, normalize and return the nearest value representable as a 64-bit double (this is the theory—in practice, you will almost never use more than two integers per double as the remaining bits would not be representable). This approach guarantees that all representable doubles could be in principle generated, albeit not every returned double will appear with the same probability. A reference implementation can be found here. Note that unless your generator has at least 1074 bits of state and suitable equidistribution properties, the code above will not do what you expect (e.g., it might never return zero).

@dhardydhardy mentioned this pull request May 24, 2018
@sicking

sicking commented Jun 4, 2018

Copy link
Copy Markdown
Contributor

Is there still interest in this?

I wrote a generator a while back for values in the [0, 1) range using maximum precision here.

What the algorithm effectively does is that it picks a random, but perfectly unbiased, point on the continuous line between 0 and 1. It then rounds that down to the nearest point that can be represented as a f32/f64.

This means that all values in the [0, 1) range that can be represented by an f32/f64 can be returned by the algorithm. However not all values are equally likely since f32/f64 has many more values close to 0 than close to 1, and so likelyhood of rounding to a particular value close to 0 is smaller, than a particular value close to 1.

Happy to adapt this to rand if there's interest?

There's also code in the same file which uses the same approach to generate values between two arbitrary, finite, f32/f64. I.e. it picks an random unbiased point on the continuous line between the start and end and then rounds to the closest f32/f64 below the picked point. However it relies on the num_bigint crate so would require more work to port.

@sicking

Copy link
Copy Markdown
Contributor

I should also mention that the code for high-precision sampling for an arbitrary range is quite slow. I mainly wrote it for funsies to see what it'd look like.

However the code for high-precision sampling in [0, 1) has more reasonable performance. Though obviously slower than the Standard implementation.

@dhardy

Copy link
Copy Markdown
Member

IIRC this implementation works fine and has reasonable performance, but we were considering going with arbitrary ranges. On the other hand, if that's not easy to do it might not be a good option.

We were planning on adding distributions::HighPrecision which is just the full-precision equivalent of Uniform.

@sicking

sicking commented Jun 5, 2018

Copy link
Copy Markdown
Contributor

Cool, the existing implementation here does seem faster than the one I wrote, so I think we should go with this one.

Happy to port the arbitrary-range full-precision implementation that I wrote if there's a interest? The current code is here.

Would there be any perf goals in mind?

@sicking

Copy link
Copy Markdown
Contributor

FWIW, i benchmarked my full-precision-arbitrary-range implementation and it's about 50-100x slower than the low-precision version, which is similar to what's in Uniform<f32/64>.

It's not been perf optimized much, so I'm sure that can be lowered some. But it's pretty darn slow.

@sicking

Copy link
Copy Markdown
Contributor

I'm working on a more performant implementation here. Still doesn't work, so can't get perf numbers yet.

@sicking

Copy link
Copy Markdown
Contributor

The implementation over here is now working and benchmarked. It's looking about 6-9x slower than the current Uniform implementation which seems viable? I'm sure some more performance can be squeezed out as well.

@dhardy

Copy link
Copy Markdown
Member

Good work. I think with that performance it is probably worth including this somehow, though obviously not as the default option. I guess we may also want a different implementation for high-precision Standard?

I would say open a PR, but it probably makes sense to resolve #494 first.

@sickingsicking mentioned this pull request Jun 27, 2018
@pitdicker

Copy link
Copy Markdown
ContributorAuthor

Closing in favor of #531

@dhardy

Copy link
Copy Markdown
Member

Why? As I understand this has better performance, but only works over [0, 1), so they seem to be mutually exclusive.

@dhardydhardy reopened this Jul 18, 2018
@sicking

Copy link
Copy Markdown
Contributor

The PR in #531 includes the commits here, but updated to compile on master. #531 contains both HighPrecision01 and HighPrecision distributions.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

F-new-intFunctionality: new, within Rand

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@pitdicker@dhardy@vks@sicking