[![License:0BSD](https://img.shields.io/badge/License-0BSD-brightgreen.svg)](https://opensource.org/licenses/FPL-1.0.0) ![Minimum Rust Version](https://img.shields.io/badge/Min%20Rust-1.36-green.svg) [![travis.ci](https://travis-ci.org/Lokathor/hektor.svg?branch=master)](https://travis-ci.org/Lokathor/hektor) [![AppVeyor](https://ci.appveyor.com/api/projects/status/7nh0q08kwngyi3mv/branch/master?svg=true)](https://ci.appveyor.com/project/Lokathor/hektor/branch/master) [![crates.io](https://img.shields.io/crates/v/hektor.svg)](https://crates.io/crates/hektor) [![docs.rs](https://docs.rs/hektor/badge.svg)](https://docs.rs/hektor/) CI coverage: * Builds on: `x86`, `x86_64`, `wasm32`, `armv7`, `aarch64`, `thumbv7neon` * Tests on: `x86`, `x86_64`, `wasm32` If you're a CI pro, please submit a PR that gives even more CI coverage! # hektor A library for hekkin vectors. Goals: * `f32` Vectors of dimension 2, 3, and 4. * `f32` Matrices with one vector per column (aka "column-major"). This is optimal for uploading into OpenGL or Vulkan with a GLSL shader. * `f32` Quaternions. **STATUS: NOT READY FOR USE** ## Code Organization Details Code is largely organized with one type per module. These modules are made part of the crate by having `lib.rs` do the following for each one: ```rust mod foo; pub use foo::*; ``` The combination of a private module and a `pub use` of the content of said module causes the outside world see all of the content of the `foo` module as being _directly_ within the crate's top level module. This is easiest on end users, without forcing us to literally put the entire crate in a single file. Tests are organized as one test file per operation group. This is a lot easier to keep track of when adding one operation at a time and checking that it's implemented for each appropriate type. ## Inline Policy * Any "accessor" and "view" style methods, as well as `new, are marked `#[inline(always)]`. * Most other methods are marked `#[inline]` by default. * Formatting methods are not even marked for inlining. * If it can be shown that insufficient inlines are the cause of a slowdown then we can upgrade a particular method to be `#[inline(always)]`, but there must first be some sort of benchmark demonstrating the issue. ## Contributing At the moment I'm using the adding of new operations to the library as a bit of a way to re-verify that I personally know how each thing works because it's sure been a bit since I had to do any of this. Accordingly, having other people add in large piles of functionality isn't something I'm super interested in. That said, there are plenty of places where people who want to contribute can help speed up the process: * **It's Not All Perfectly Fast:** Benchmark any potentially-slow operation that's already in the library, benchmark an alternate way of computing the same thing, and submit a PR if you've found an improvement. * **Math Research Is Hard:** Look up how an operation works and post the appropriate formulas and a source link into the issue for the operation in the issue tracker. This is particularly important for anything to do with Quaternions. * **Test Data Is Dull:** Based on the formula of an operation, write up some expected test cases and post them in the appropriate issue in the issue tracker so that I know what I'm targeting ahead of time. If there's already a test case written I'm a lot more likely to want to try and handle that first, since writing tests myself is very boring. * **Open New Issues:** If there's an operation, particularly one that `nalgebra-glm` handles, that isn't in the issue tracker then please add it to the issue tracker. * **Help My Dependencies:** I'm trying to stay `no_std` for as long as possible which means that I end up having to rely on the [libm](https://github.com/rust-lang-nursery/libm) crate, so you can always help out there. * **Do It Wide:** This is one of the hardest ones. With `Vec3`/`Vec4` we want to take advantage of the individual components being parts of a "f32x4" SIMD lane as much as we can. This means that we have to write _custom versions_ of some operations, particularly trigonometry, because normal branching code is far less helpful to us. For example, when there's a brach in SIMD you have execute _both_ branches and then combine the results with a mask, so branching to exit a function early is no help. This usually means that you have to re-think how to handle things. Properly wide versions of things like trig are essential to eventual good performance across the board. _This isn't a hard blocker_: when a wide version isn't available I just call the necessary `libm` function on each component individually, but that's about 4x as long to execute.