profile
viewpoint

bluss/indexmap 614

A hash table with consistent order and fast iteration; access items by key or sequence index

bluss/either 166

The enum Either with variants Left and Right is a general purpose sum type with two cases.

agrover/froyo 59

A flexible and redundant long-term storage system for Linux, using DM and XFS

cuviper/alloc_geiger 36

A Rust allocator which makes sound when active, like a Geiger counter.

cuviper/autocfg 31

Automatic cfg for Rust compiler features

cuviper/android_device_htc_inc 2

WIP repo for CM Inc. Beware, this is where I break stuff...

cuviper/addr2line 0

A cross-platform `addr2line` clone written in Rust, using `gimli`

cuviper/alga 0

Abstract algebra for Rust.

cuviper/alphanumeric-sort 0

This crate can help you sort order for files and folders whose names contain numerals.

CommitCommentEvent

pull request commentrust-num/num-integer

Add optimized binary extended gcd algorithm

Much appreciation to @cuviper for their help/discussion about the impl on Zulip.

unseddd

comment created time in 8 hours

PR closed rust-num/num-bigint

Add optimized extended binary gcd algorithm

Since BigInt uses potentially very large numbers, implement the optimized extended binary gcd algorithm from the Handbook of Applied Cryptography.

Blocked on num-integer/#37

+100 -0

1 comment

1 changed file

unseddd

pr closed time in 8 hours

pull request commentrust-num/num-bigint

Add optimized extended binary gcd algorithm

Close in favor of num-integer/#38

unseddd

comment created time in 8 hours

PR closed rust-num/num-integer

Add Default implementation for ExtendedGcd

Allow users of the ExtendedGcd struct to build a default instance.

Allows for custom implementation of the extended_gcd function in other crates, without exposing the _hidden field.

+1 -1

1 comment

1 changed file

unseddd

pr closed time in 8 hours

pull request commentrust-num/num-integer

Add Default implementation for ExtendedGcd

Close in favor of #38

unseddd

comment created time in 8 hours

PR opened rust-num/num-integer

Add optimized binary extended gcd algorithm

Optimized to use cheap shifts and adds rather than multiplications and divisions for finding the greated common divisor and Bezout coefficients.

+146 -32

0 comment

1 changed file

pr created time in 8 hours

issue commentrayon-rs/rayon

FR: variant of reduce/fold to support case where Send is possible but expensive

I like your thread-id based approach! It's clever!

                    let t = rayon::current_thread_index().unwrap();
                    v[t].store(Some(Foo(s)));

With regards to my particular reduce op, here's the original problem in a little more depth, though I don't want to get too mired down in the details of the thread safety rules on our FFI wrapped C++ code: https://github.com/wasmerio/wasmer/blob/4378b22c9d544b56bd19a0218edc24167fda45cd/lib/compiler-llvm/src/compiler.rs#L160

I have three different things I map to LLVM IR Modules, then my reduce is merging these modules. LLVM's rule is that an LLVMContext is Send but not Sync and the user is responsible for locking it themselves, and all actions in LLVM require an LLVMContext (either directly or implicitly -- modules hold a pointer to their context). When converting from those three things into Modules in parallel, we create each one in their own LLVMContext. In LLVM you may not merge modules in different contexts, so we serialize out of one context and deserialize into another context.

Currently this means I'm doing serialize(merge(deserialize, deserialize)) in my reduce op.

A theoretical API for Rayon could take three operators, one that converts A->B, one fold(B, A)->B and one fold(B, B)->B. The first one A->B is used for startup (run once per Rayon thread), the last one is used for shutdown (as each thread runs out of work to steal and now we need to merge them all the B's into one), and the fold(B, A)->B is the one that is run the most. It could look something like:

let merged_bitcode = all_bitcode.into_par_iter().reduce_with_peeling(
    |bc| {
        let ctx = Context::create();
        let membuf = MemoryBuffer::create_from_memory_range(&bc, "");
        Module::parse_bitcode_from_buffer(&membuf, &ctx).unwrap()
    },
    |m1, bc2| {
        let ctx = &m1.get_context();
        let membuf = MemoryBuffer::create_from_memory_range(&bc2, "");
        let m2 = Module::parse_bitcode_from_buffer(&membuf, &ctx).unwrap()
        m1.link_in_module(m2).unwrap()
    },
    |m1, m2| {
        let ctx = &m1.get_context();
        let bc2 = m2.write_bitcode_to_memory().as_slice().to_vec();
        let membuf = MemoryBuffer::create_from_memory_range(&bc2, "");
        let m2 = Module::parse_bitcode_from_buffer(&membuf, ctx).unwrap();
        m1.link_in_module(m2).unwrap()
    },
);

where "peeling" refers to the compiler optimization "loop peeling".

Note that the final number of runs of fold(B, B)->B could be done tournament-style rather than sequentially.

nlewycky

comment created time in 9 hours

pull request commentrust-num/num-integer

Implement more number theory functions

Extended GCD was already merged in #19, so this should now build on top of that if possible.

My implementation is not equivalent: It does not use Clone, but relies on NumRef and RefNum instead. It also consumes the input, instead of taking it by reference and forcing a clone.

The implementation currently part of Integer has some possibly redundant allocations, which are unavoidable without changing the signature of the method.

I don't know which of the two signatures is preferable. The one on master with Clone, or the one in this PR with NumRef and RefNum (which would be a breaking change)? This also affects the other functions (normalize, inverse and powm), which in their current implementation (in this PR) use NumRef and RefNum to avoid allocations.

vks

comment created time in 10 hours

PR opened cuviper/autocfg

Hide rustc output by default.

But add an environment variable to allow showing it, if wanted.

Fixes #30

+3 -0

0 comment

1 changed file

pr created time in 11 hours

fork emilio/autocfg

Automatic cfg for Rust compiler features

fork in 11 hours

issue commentrayon-rs/rayon

FR: variant of reduce/fold to support case where Send is possible but expensive

hi, it might be possible but tricky.

i quickly tried a little example here:

struct Foo(u32);
unsafe impl Send for Foo {}
use crossbeam::atomic::AtomicCell;
use rayon::prelude::*;

fn main() {
    let data: Vec<u32> = (0..10u32).collect();
    let pool = rayon::ThreadPoolBuilder::new().build().unwrap();
    let r = pool.install(|| {
        let v: Vec<_> = (0..rayon::current_num_threads())
            .map(|_| AtomicCell::new(None))
            .collect();
        data.par_chunks(3)
            .enumerate()
            .map(|(i, c)| (i + 4, c)) // because we have 4 blocks
            .map(|(i, c)| {
                let s = c.iter().sum::<u32>();
                if i % 2 == 0 {
                    // left: don't serialize, store localy
                    let t = rayon::current_thread_index().unwrap();
                    v[t].store(Some(Foo(s)));
                    (None, i / 2)
                } else {
                    // right: serialize and return
                    (Some(s), i / 2)
                }
            })
            .reduce_with(|_, (right_r, i)| {
                let t = rayon::current_thread_index().unwrap();
                let mut f = v[t].take().unwrap();
                f.0 += right_r.unwrap(); // reduce
                if i % 2 == 0 {
                    v[t].store(Some(f));
                    (None, i / 2)
                } else {
                    // right: serialize
                    (Some(f.0), i / 2)
                }
            })
            .unwrap()
    });
    println!("r: {:?}", r);
}

you have to realize that this is not a magic bullet.

  • when reducing left and right, only left is not serialized/deserialized.
  • we don't know what your reduction algorithm is and hence its cost. you have to keep in mind that the final reduction between two halves is sequential. if your cost is linear this will screw your speedup

there might be a better way to do it but we would need to know more about the reduce op

nlewycky

comment created time in 20 hours

issue openedrayon-rs/rayon

FR: variant of reduce/fold to support case where Send is possible but expensive

I have a vector of large data structure that is Send but not Sync which I need to reduce. Right now, I start with the vector in serialized form and my reduce_with OP parses both arguments, reduces, then serializes. The data grows with each reduce, so the serialize and parse keeps getting slower every step.

Instead I'd like to keep a single object per thread in deserialized form and reduce the other serialized buffers into it.

created time in a day

issue closedcuviper/autocfg

Can I probe for const generics support?

I'd like to probe support for (minimal) const generics by checking this code:

type A<const N: usize> = [(); N];

But this can't be done with probe_type and I'm not sure how else to do it (other than maybe probe_rustc_version which seems kind of awkward). Any workarounds?

closed time in a day

cole-miller

PR opened rust-num/num-bigint

Add optimized extended binary gcd algorithm

Since BigInt uses potentially very large numbers, implement the optimized extended binary gcd algorithm from the Handbook of Applied Cryptography.

Blocked on num-integer/#37

+100 -0

0 comment

1 changed file

pr created time in a day

PR opened rust-num/num-integer

Add Default implementation for ExtendedGcd

Allow users of the ExtendedGcd struct to build a default instance.

Allows for custom implementation of the extended_gcd function in other crates, without exposing the _hidden field.

+1 -1

0 comment

1 changed file

pr created time in a day

PR closed rust-num/num-integer

Add invmod API to Integer trait
+35 -0

4 comments

1 changed file

unseddd

pr closed time in 2 days

pull request commentrust-num/num-integer

Add invmod API to Integer trait

Closing in favor of an updated #10

unseddd

comment created time in 2 days

pull request commentrust-lang/llvm-project

[AArch64] Add support for the GNU ILP32 ABI

Yes, LLVM 11 doesn't have the isAArch64 overload that takes a pointer size argument. It's only used in Clang anyways.

Amanieu

comment created time in 2 days

PR opened rust-lang/llvm-project

[AArch64] Add support for the GNU ILP32 ABI

Differential Revision: https://reviews.llvm.org/D94143

+276 -78

0 comment

21 changed files

pr created time in 3 days

issue commentbluss/indexmap

OccupiedEntry::key() gives the new key instead of the old one

It is something that can have an observable effect, which did cause a bug for me in my case. I have these types:

// something with source code location attached
pub struct Spanned<T> {
    span: Span,   // not included in Eq/PartialEq/Hash. Used in diagnostics
    value: T,
}

pub enum Value {
    Array(Vec<Spanned<Value>>),
    Object(IndexMap<Spanned<Ident>, Spanned<Value>>),
    // other variants...
}

When deserializing the Value::Object variant and I encounter a duplicate key, I want to create an error pointing to both the duplicate and original items. So I was doing

let new_span = key.span;
match map.entry(key) {
    Entry::Vacant(entry) => { entry.insert(value); }
    Entry::Occupied(entry) => {
        // here I expected new_span to be the duplicate's span
        // and entry.key().span to be the original's span...
    }
}

But that also of course means that this would in some way be a breaking change. I'm not sure what the case would be for having it return the new key (at least in borrowed form; I do see a use for recovering ownership of the new key), I can't deny that there may be code somewhere out there depending on it.

ExpHP

comment created time in 3 days

pull request commentrust-num/num-bigint

Get/set n-th bit of `BigUint` and `BigInt`

@cuviper I have now updated the PR with a more efficient implementation of BigInt::set_bit. Basically, I have made sure that only the relevant digits will be iterated over instead of all of them, as you also pointed out. In a special benchmark it saved about 70% in runtime.

I have also implemented a special case for bit < trailing_zeros && value which also saves some runtime compared to the case bit == trailing_zeros && !value, but only about 5-10%. The two cases can be merged together to make the set_bit a bit shorter.

janmarthedal

comment created time in 4 days

issue commentbluss/indexmap

OccupiedEntry::key() gives the new key instead of the old one

Makes sense to change this. Did this cause a bug on your end or something (so that it's actually something some users would notice?)

ExpHP

comment created time in 4 days

issue commentcuviper/autocfg

Can I probe for const generics support?

Did you add A([]) to avoid unused warning spew?

No, it was just a reflex :P (I wasn't thinking about implicit () return). The unused warning doesn't bother me especially since it only shows up with -vv and this is the only thing in my build.rs currently.

cole-miller

comment created time in 4 days

issue openedbluss/indexmap

OccupiedEntry::key() gives the new key instead of the old one

struct Item { value: i32, id: &'static str }

impl PartialEq for Item {
    fn eq(&self, other: &Item) -> bool { self.value == other.value }
}
impl Eq for Item {}
impl std::hash::Hash for Item {
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
        self.value.hash(state);
    }
}


fn main() {
    use indexmap::map::{IndexMap as Map, Entry};

    let mut map = Map::new();
    map.insert(Item { value: 3, id: "old" }, 200);
    
    match map.entry(Item { value: 3, id: "new" }) {
        Entry::Vacant(e) => panic!(),
        Entry::Occupied(e) => println!("{}", e.key().id),
    }
}

output:

new

Whereas if you instead use std::collections::hash_map::{HashMap as Map, Entry}; then it prints old. This difference in behavior seems surprising.

created time in 4 days

pull request commentrust-num/num-integer

Add invmod API to Integer trait

I will update my PR this week.

On Mon, Jan 18, 2021, 21:05 Nym Seddon notifications@github.com wrote:

@cuviper https://github.com/cuviper I added the requested changes, let me know what you think. Will squash the fixup, if you approve.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/rust-num/num-integer/pull/36#issuecomment-762447756, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAAIFNF77J5Q7KWFNUICXHTS2SH63ANCNFSM4VM42JAA .

unseddd

comment created time in 4 days

pull request commentrust-num/num-integer

Add invmod API to Integer trait

@cuviper I added the requested changes, let me know what you think. Will squash the fixup, if you approve.

unseddd

comment created time in 4 days

pull request commentrust-num/num-integer

Add invmod API to Integer trait

@cuviper I added the requested changes, let me know what you think.

unseddd

comment created time in 4 days

pull request commentrust-num/num-integer

Add invmod API to Integer trait

This will need some unit tests, and testable doc-examples would be nice.

No problem, can update with unit tests, and try my hand at some doc-examples :)

This also overlaps with #10 -- if @vks responds I would give preference to their PR for coming first.

Didn't mean to step on any toes. Will definitely close, and give preference to @vks over this PR. Just wasn't sure if #10 was still relevant, since similar code exists in num-integer already (what's used by this PR).

unseddd

comment created time in 4 days

Pull request review commentrust-num/num-integer

Add invmod API to Integer trait

 pub trait Integer: Sized + Num + PartialOrd + Ord + Eq {         (self.extended_gcd(other), self.lcm(other))     } +    /// Inverse of the number modulo the modulus+    #[inline]+    fn invmod(&self, modulus: &Self) -> Self+    where+        Self: Clone,+    {+        let egcd = self.extended_gcd(modulus);+        assert!(egcd.gcd.is_one(), "no inverse, GCD(x, modulus) != 1");

For sure, wasn't sure what was preferred. Will change return to Option<Self>.

unseddd

comment created time in 4 days

more