scijs / ndarray-blas-level2

BLAS Level 2 operations for ndarrays
MIT License
9 stars 2 forks source link

Added SBMV function and unit tests. #14

Open tab58 opened 8 years ago

tab58 commented 8 years ago

Referenced LAPACK library for logic: http://www.netlib.org/lapack/explore-html/d7/d15/group__double__blas__level2_ga5c7ca036c788c5fd42e04ade0dc92d44.html#ga5c7ca036c788c5fd42e04ade0dc92d44

rreusser commented 8 years ago

Added a couple notes. Overall LGTM. I support robustness first, followed by optimization.

One additional question: do you think we should throw errors if the dimensionality or dimension sizes are incompatible? I don't think we have so far, but I think it's the right move. The general conclusion before was to return false if the algorithm fails and throw an error if the operation is invalid. The actual amount of work involved is almost certainly negligible unless you're multiplying 2 x 2 matrices 10000000 times—which might not be that unrealistic but is probably a bad idea if it's actually the bottleneck.

tab58 commented 8 years ago

K, before we hit the big green button, I realized my test for this is terrible. I was having some rebase issues in Git, so I had to do some manual file moving and force pushes to my fork. The tests aren't right for this. Let me fix this before we merge.

tab58 commented 8 years ago

This should be fixed now. If this looks good to you @rreusser, hit the big green button. 😄

rreusser commented 8 years ago

Could you add a note on the storage format first? Coming to this library, I'd be unable to use the sbmv without either working through the code or locating another reference on the topic. We maybe don't need a whole code snippet, but we at least need to describe that the diagonal is in… row k of A? With superdiagonals above that? I'm not sure if that's correct, but we should at least describe it to the point that it's usable.

rreusser commented 8 years ago

Made a few comments. Hate to nitpick too much, but I think it's important to get the API and usage consistent and tight so that people don't have to worry about all the caveats and subtleties. Here's the things I'd like to tighten up in general, and I'm glad to help with the cleanup:

If that makes sense, let's merge this since it's a big step forward, then continue with building it out before publishing to npm.

And despite all that, please don't think I'm not grateful and excited that you're back to work on this!

tab58 commented 8 years ago

You're just fine with the nitpicks. It's good that you're asking questions cause that means you're analyzing my code. 😄 I would hate to commit something unusable. Let me address your comments:

tab58 commented 8 years ago

What are your feelings on using console.warn() for reasons the function failed, @rreusser?

rreusser commented 8 years ago

Hmm… based on past mistakes, let's avoid console.warn if we can. If you trap an error and choose to ignore it, you might still get tons of unwanted console output. Most people don't trap unexpected errors, so as long as you throw new Error('Useful message here'), it should show up in the console anyway.

tab58 commented 8 years ago

So we do want to throw errors instead of console.warn()? That's cool. I'll do that.

tab58 commented 8 years ago

But if we're throwing errors on argument mismatches, then why would we then want to return false?

rreusser commented 8 years ago

I like console.warn for things like a recursion limit reached where you might still get a meaningful answer but with caveats. And if you do that, I think the right way is to keep a module-global variable that counts how many times the error has been logged, and then omit further errors after some reasonable limit. Bottom line: except for that very specific case of true 'warnings' as opposed to errors or algorithm failures, it's a small bit of unpleasantness that I think is best avoided.

And as for errors, I think only throw errors on invalid input. So:

As opposed to:

rreusser commented 8 years ago

The downside being that it's difficult to handle multiple return values (e.g. a numerical result + true/false representing success/failure—which you can do but it's kinda overloading the meaning of the return value such that any additional details are getting to be a bit much for one return value). One approach I've taken with that is to accept an optional status object as a final object. If provided, then additional information about the result is computed and passed back. See complex-deriv-fornberg for an example. (This could also be accomplished with a callback. I'm not sure how I feel about that.)

rreusser commented 8 years ago

To answer your specific question though, this algorithm should never need to return false. A return true at the end should be sufficient. Sorry, I was speaking in more general terms.

tab58 commented 8 years ago

Added some things @rreusser. LMK if you have any issues with them.