Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

handful of bug fixes #76

Merged
merged 2 commits into from Feb 7, 2017
Merged

Conversation

ksajme
Copy link

@ksajme ksajme commented Feb 6, 2017

  • fixed select in roaring64map.hh not returning the upper 32 bits
  • fixed some incorrect printf format specifiers
  • made an impossible brance of an if possible
  • made compilation possible with DISABLE_X64 on MSVC 14.0
  • TODO: tests and benchmarks and ABM optmizations
  • removed .c file inline keyword

* fixed select in roaring64map.hh not returning the upper 32 bits
* fixed some incorrect printf format specifiers
* made an impossible brance of an if possible
* made compilation possible with DISABLE_X64 on MSVC 14.0
* TODO: tests and benchmarks and ABM optmizations
* removed .c file inline keyword
@@ -144,10 +144,10 @@ class Roaring64Map{
* Check if value x is present
*/
bool contains(uint32_t x) const {
return roarings.at(0).contains(x);
return roarings.count(0) == 0 ? false : roarings.at(0).contains(x);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rather big deal here, at() will throw an exception if we don't check count() first

for (const auto& map_entry : roarings) {
uint64_t sub_cardinality = (uint64_t)map_entry.second.cardinality();
if (rank < sub_cardinality) {
return map_entry.second.select(rank, element);
*element = ((uint64_t)map_entry.first) << 32;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

was ignoring the high-order bytes

@@ -27,11 +27,10 @@
#include <malloc.h> // this should never be needed but there are some reports that it is needed.
#endif

#if __SIZEOF_LONG_LONG__ != 8
#if defined(__SIZEOF_LONG_LONG__) && __SIZEOF_LONG_LONG__ != 8
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not defined at all on Windows

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ksajme Interesting issue. Looks like we do not need to check that long long is 8 bytes in Visual Studio, even when compiling a 32-bit binary.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's right, always 64

Copy link
Member

@lemire lemire Feb 6, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anyhow, I think that this check is only needed on GCC-like compilers due to the intrinsics. GCC has intrinsics for int, long and long long. If long long is only 4 bytes, then we have no intrinsic for 8-byte values...

Still, for Visual Studio, I suspect that the same problem will occur... right? If you are compiling a 32-bit binary, you will be missing some 64-bit intrinsics, won't you?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, in fact CMake will select 32 for a target by default. Caught me off-guard for this project. AFAIK there is no reliable way to force CMake to target 64 on Windows.

In 32-bit, compilation will fail while looking for built-ins. We could check for the existence of _WIN32 and the absence of _WIN64 if we wanted to print something friendlier.

Copy link
Member

@lemire lemire Feb 6, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ksajme Can you do it as part of your PR? I'd imagine something like

#if defined (_WIN32) && !defined(_WIN64)
#pragma message("You appear to be attempting a 32-bit build under Visual Studio. We recommend a 64-bit build instead.")
#endif 

General idea is to make a best-effort attempt at helping people.

Thoughts?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a good idea, especially since CMake makes it so easy to build as 32-bit by accident. I will move the defines around a bit so we don't catch MinGW or Clang on Windows.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, it's not possible for "long long" to be <8 bytes. Both the C and C++ standards require that "long long" must be equal to or (in some far-flung future) greater than 8 bytes long.

So, while it might be useful as documentation for this check to be there, there's no architecture existing today that I'm aware of where it will be false (it would require a 128bit computer or something... and even then it's not entirely clear that the compiler implementers on those systems will choose to make "long long" be 128bits).

https://en.wikipedia.org/wiki/C_data_types
http://en.cppreference.com/w/cpp/language/types

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@madscientist

As per your links, the "long long" specification comes from C99. Granted, that's what we expect, but it is not like this was built into the language decades ago. (For some reason, in C, C99 is still considered bleeding edge by some.)

So, while it might be useful as documentation for this check to be there, there's no architecture existing today that I'm aware of where it will be false

Ok. I am responsible for this check and it was indeed quite paranoid... but I am not sure it is harmful.

/* Microsoft C/C++-compatible compiler */
#include <intrin.h>

/* wrappers for Visual Studio built-ins that look like gcc built-ins */
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some faster versions of the built-ins used here which will function or be undefined depending on the processor features. Future work would be to identify the features and use the fancier built-ins

@@ -296,9 +296,9 @@ void array_container_printf_as_uint32_array(const array_container_t *v,
if (v->cardinality == 0) {
return;
}
printf("%d", v->array[0] + base);
printf("%u", v->array[0] + base);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gcc found these incorrect format specifiers

@@ -534,7 +534,7 @@ uint16_t bitset_container_minimum(const bitset_container_t *container) {
}

/* Returns the largest value (assumes not empty) */
inline uint16_t bitset_container_maximum(const bitset_container_t *container) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This inline in a .c file chokes Visual Studio. I don't think it's doing anything in other C/C++ compilers since the implementation is not in the .h file so I removed it. Another fix would be to add the keyword and the implementation to the .h file.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, I don't think that this "inline" was correct.

@@ -124,7 +124,7 @@ static roaring_bitmap_t *lazy_or_from_lazy_inputs(roaring_bitmap_t *x1,
void *c;

if ((container_type_2 == BITSET_CONTAINER_TYPE_CODE) &&
(container_type_2 != BITSET_CONTAINER_TYPE_CODE)) {
(container_type_1 != BITSET_CONTAINER_TYPE_CODE)) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gcc found this impossible branch. This is a total guess of what it's supposed to be checking. Please correct me if I'm wrong!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ksajme Yes, your fix is correct!

@@ -154,6 +154,12 @@ void test_example_cpp(bool copy_on_write) {

r2.printf();
printf("\n");

// test select
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might as well publish the unit tests for select I was using to diagnose the problem in the 64-bit map

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

@lemire
Copy link
Member

lemire commented Feb 6, 2017

This looks like a high quality PR.

@lemire
Copy link
Member

lemire commented Feb 7, 2017

Merging.

@lemire lemire merged commit ec9ae21 into RoaringBitmap:master Feb 7, 2017
@ksajme ksajme deleted the handfulOfBugFixes branch February 7, 2017 22:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants