Popularity
1.1
Growing
Activity
10.0
Stable
12
1
1

Programming language: C#
License: MIT License
Tags: Mathematics    

Jodo.Numerics alternatives and similar packages

Based on the "Mathematics" category.
Alternatively, view Jodo alternatives based on common mentions on social networks and blogs.

Do you think we are missing an alternative of Jodo.Numerics or a related project?

Add another 'Mathematics' Package

README

The Jodo Libraries

Contents

1. Introduction

2. Quickstart

3. About the project     3.1. Design goals     3.2. Roadmap     3.3. Contributing     3.4. Documentation     3.5. Releases     3.6. Changelog

4. Jodo.Numerics     4.1. Fixed-point numbers     4.2. Non-overflowing numbers     4.3. Framework for numbers     4.4. Structures     4.5. Random extensions     4.6. Performance considerations

5. Jodo.Geometry (preview)

6. Jodo.Collections (preview)

7. Jodo.Primitives     7.1. Random variants     7.2. Default providers     7.3. Shims     7.4. Stream extensions (preview)

* * *

1. Introduction

Welcome to Jodo, a project to make simple, reliable .NET libraries covering numerics, geometry and data structures.

This document describes the goals of the project, the features of each library, and steps for getting started.

[Back to top]

* * *

2. Quickstart

To use the Jodo libraries:

  1. Search "jodo" in the NuGet package manager.
  2. Select a library (e.g. Jodo.Numerics), and click Install (most versions of .NET are supported).
  3. Import the required namespace in your code files, e.g. "using Jodo.Numerics;".
  4. Use the newly-available types in your code (no configuration or dependency injection is required).

The features available are:

  • Jodo.Numerics - numeric utilities, custom number types, and a generic interface for defining numbers
  • Jodo.Geometry (preview) - geometric structs and utilities that support custom number types.
  • Jodo.Collections (preview) - Extra collection classes and interfaces to complement the .NET API
  • Jodo.Primitives - miscellaneous utilities used throughout the Jodo libraries

[Back to top]

* * *

3. About the project

The Jodo libraries started as a collection of reusable types from the personal projects of @JosephJShort. The types are being revamped to make them fit for public consumption.

This section describes the design goals, roadmap, and other details of the project.

[Back to top]

3.1. Design Goals

The table below summarizes the design goals of the project.

Item Description Simplicity The Jodo libraries are designed to provide simple data structures and algorithms to use as the building blocks for more comlpex applications. As a rule of thumb, nothing within the libraries should require configuration or dependency injection. A competent developer should be able to use the libraries intuitively, without needing to refer to documentation. The libraries adhere to the .NET Framework Design Guidelines to ensure ease-of-use and consistency with the .NET API. Compatibility
The Jodo libraries are designed to work with a wide array of programming languages and operating systems. .NET Standard 2.0 (netstandard2.0) and .NET Framework 4.6 (net461) targets are used in order to maximize cross-platform support, whilst additional targets such as .NET Standard 2.1 (netstandard2.1) are used to incorporate newer language features like default interface methods. No platform-dependant features are used. Publicly exposed types are marked as CLS compliant wherever possible, and language-agnostic naming conventions are used. This ensures that the libraries can be used in F# and Visual Basic as well as in their native language, C#. Care is taken to avoid name clashes with commonly-used types from the .NET API and popular NuGet packages. Semantic Versioning is used to ensure that version numbers convey the presence of breaking changes to the libraries, and package validation is used to ensure backwards compatibility within each major version. Reliability The Jodo libraries are designed to be dependable. Unit tests, benchmarks, and continuous integration tools are used to ensure they remain fit for purpose. Tests are designed to cover boundary conditions, edge-cases, and error scenarios—not just happy paths. Code coverage is used, but is not considered a definitive metric of adequate testing. The code coverage target is 90%. As part of pull request validation, tests are executed against multiple .NET targets and operating systems. Currently, this includes .NET Framework 4.8 (net48), .NET Core 2.1 (netcoreapp2.1), .NET 5 (net5.0), .NET 6 (net6.0), Windows, Ubuntu, and macOS. This helps to ensure that the libraries behave as intended and are unaffected by .NET implementation details. Maintainability The source code of the Jodo libraries is designed to be easy to understand and change. As part of pull request validation, SonarCloud and CodeFactor are used to detect code smells such as unused variables or overly complex functions. In the project configuration files, TreatWarningsAsErrors is set to True, WarningLevel is set to 4 and Rosyln analysers are enabled with maximum scope and severity. This helps to flag issues during development. Warnings are only suppressed in exceptional circumstances, and suppression tags are always accompanied by a justification message.

[Back to top]

3.2. Roadmap

The following table summarizes the development goals for upcoming versions of the Jodo libraries.

Version Goals 1.1.0 Implement suggestions Add support for spans Add support for streaming Automate API documentation website and fill in major blanks 1.2.0 Create the first release of Jodo.Geometry 1.3.0 Implement suggestions Future Create the first release of Jodo.Geometry

[Back to top]

3.3. Contributing

Community contributions are welcome at https://github.com/JosephJShort/Jodo (the home of this repository). A list of reported issues can be found at https://github.com/JosephJShort/Jodo/issues. Contributors are requested to adhere to the code of conduct.

This work is licensed under the MIT License.

[Back to top]

3.4. Documentation

Work-in-progress API documentation is available at https://jodo.dev.

[Back to top]

3.5. Releases

Builds of this project are available as NuGet packages on NuGet.org (for help, see: "Quickstart: Install and use a package"). Binaries are available on GitHub.com at https://github.com/JosephJShort/Jodo/releases. The libraries can also be built from the source code in this repository using the appropriate .NET SDKs and any IDE that supports .NET, such as Visual Studio Community Edition.

[Back to top]

3.6. Changelog

The following table summarizes changes made to previous releases of the Jodo libraries:

Version Changes 1.0.0 The initial release of Jodo.Numerics and Jodo.Primitives Added cross-platform support Reached high level of test coverage Established code quality rules Created benchmarks

[Back to top]

* * *

4. Jodo.Numerics

Provides numeric utilities, custom number types, and a generic interface for defining numbers.

[Back to top]

4.1. Fixed-point numbers

Unlike floating-point numbers, fixed-point numbers maintain a constant degree of precision regardless of magnitude. This can be useful in situations where precision remains important whilst numbers grow. As a trade-off, fixed-point numbers have a much lower maximum magnitude than floating-point numbers of the same size.

Fix64 and UFix64 are number types that implement fixed-point arithmetic. As with all the number types provided by this library, they support a full range of math, operators, conversion, string parsing, etc (see §4.3. Framework for numbers).

using Jodo.Numerics; using System;

Fix64 x = 100; Fix64 y = 2 * MathN.Cos(x); Fix64 z = Fix64.Parse("1000000.123456"); Fix64 r = new Random(1).NextNumeric<Fix64>(100, 200); float f = ConvertN.ToSingle(z); byte[] bytes = BitConverterN.GetBytes(y);

Console.WriteLine(x); // output: 100 Console.WriteLine(y); // output: 1.724636 Console.WriteLine(z); // output: 1000000.123456 Console.WriteLine(r); // output: 124.866858 Console.WriteLine(f); // output: 1000000.1 Console.WriteLine(bytes.Length); // output: 8

The table belows summarizes the capabilities of these types.

Type Description readonly structFix64 Signed fixed-point number type with 6 decimal digits of precision, represented internally by a 64-bit integer. Supports a range of values from ±1.0 x 10−6 to ±9.2 x 1012. readonly structUFix64 Unsigned fixed-point number type with 6 decimal digits of precision, represented internally by a 64-bit integer. Supports a range of values from 1.0 x 10−6 to 1.8 x 1013. static classScaled Provides static methods for performing arithmetic and string conversion on integers with a scaling factor. Used to implement Fix64 and UFix64.

[Back to top]

4.2 Non-overflowing numbers

Number types in the Jodo.Numerics.Clamped namespace have built-in protection from overflow.

Operations that would normally error or overflow instead return MinValue, MaxValue or Zero.

This is useful in systems where overflow is expected

As with all the number types provided by this library, these types support a full range of math, operators, conversion, string parsing, etc (see §4.3. Framework for numbers).

Usage is the same as with built-in numeric types but yields different results in cases of overflow.

var i = Int32M.MaxValue + 1;
Console.WriteLine(i);  // output: 2147483647

var f = (SingleM)4 / 0;
Console.WriteLine(f);  // output: 3.402823E+38

The table below summarizes the clamped number types and utilities provided.

Type Description readonly struct ByteM, SByteM, Int16M, UInt16M, Int32M, UInt32M, Int64M, UInt64M, DecimalM Operations that would normally overflow from positive to negative instead return MaxValue. Operations that would normally overflow from negative to positive instead return MinValue. Division by zero does NOT throw a System.DivideByZeroException but returns MaxValue. readonly struct SingleM, DoubleM Operations that would normally return PositiveInfinity instead return MaxValue. Operations that would normally return NegativeInfinity instead return MinValue. Operations that would normally return NaN instead return 0. readonly struct Fix64M, UFix64M Non-overflowing fixed-point numbers (see §4.1. Fixed-point numbers). Operations that would overflow instead return MinValue or MaxValue depending on the direction of the overflow. Division by zero does NOT throw a DivideByZeroException but returns MaxValue. static class Clamped Provides static methods for performing non-overflowing arithmetic.

[Back to top]

4.3. Framework for numbers

The INumeric<TSelf> interface defines a contract for number types with support for operators, maths, conversion, string-parsing, random generation, and more.

Static utility classes, such as MathN and ConvertN, expose these features in a way that is familiar to users of the .NET API.

using Jodo.Numerics; using System;

MyNumberType fromLiteral = 3.123; MyNumberType usingOperators = (fromLiteral + 1) % 2; MyNumberType usingMath = MathN.Pow(fromLiteral, 2); MyNumberType fromRandom = new Random(1).NextNumeric<MyNumberType>(10, 20); MyNumberType fromString = MyNumberType.Parse("-7.4E+5"); short conversion = ConvertN.ToInt16(usingMath); string stringFormat = $"{fromLiteral:N3}"; byte[] asBytes = BitConverterN.GetBytes(usingMath);

The table below gives a full list of features supported by number types that implement INumeric<TSelf>.

Feature Description static classMathN Provides equivalent methods to System.Math for types that implement INumeric<TSelf>, e.g. Log(N), Acosh(N) and Round(N, int). var result = MathN.Log10(1000 * MathN.PI<MyNumberType>()); static classBitConverterN Provides equivalent methods to System.BitConverter for types that implement INumeric<TSelf>, allowing conversion to and from byte arrays. byte[] result = BitConverterN.GetBytes((MyNumberType)256.512); static classConvertN Provides equivalent methods to System.Convert for types that implement INumeric<TSelf> (e.g. ToBoolean(N) and ToDecimal(N)). Overloads are provided to support alternative modes of conversion, e.g. Default, Cast and Clamp. var defaultResult = ConvertN.ToNumeric<ByteN>(199.956, Conversion.Default); var castResult = ConvertN.ToNumeric<ByteN>(199.956, Conversion.Cast); static classNumeric Provides access to constants and static methods for number types in a generic context. public void ExampleMethod<T>() where T : struct, INumeric { var zero = Numeric.Zero<T>(); var parsed = Numeric.Parse<T>("1.2"); var isFinite = Numeric.IsFinite(parsed); } Overloaded operators All the number types in this library have a full suite of overloaded operators, including: Equality operators (==, !=) Comparison operators (<, >, <=, >=) Arithmetic operators (++, --, , /, %, +, -) Bitwise and shift operators (~, <<, >>, &, |, ) Conversion operators to/from the built-in numeric types Additionally, INumeric<TSelf> defines overloads for <, >, <=, >=, ++, --, , /, %, +, -, ~, <<, >>, &, | and , allowing for limited expressions in a generic context (note that equality and conversion operators are not supported on interfaces). Note: The bitwise and shift operators are overloaded for non-integral types. These operators perform the correct bitwise operations, but are unlikely to produce useful results. String formatting All the number types in this library can be used with numeric format strings, as in the following code sample: var var1 = (MyNumberType)1023; var var2 = (MyNumberType)99.54322f;

Console.WriteLine($"{var1:N}"); // outputs: 1,023.00 Console.WriteLine($"{var1:X}"); // outputs: 3FF Console.WriteLine($"{var2:E}"); // outputs: 9.954322E+001 Console.WriteLine($"{var2:000.000}"); // outputs: 099.543 Random generation Extension methods on System.Random provide randomly generated values. Values can be generated between bounds or without bounds. var var1 = Random.NextNumeric<MyNumberType>(); var var2 = Random.NextNumeric<MyNumberType>(100, 120);

Console.WriteLine(var1); // outputs: 0.405808417991177 (example) Console.WriteLine(var2); // outputs: 102.85086051826445 (example)

Commonly-used abstractions All the number types in this library implement System.IComparable, System.IComparable<T>, System.IConvertible, System.IEquatable<T>, System.IFormattable and System.ISerializable. They also override Equals(object), GetHashCode() and ToString(), and have the DebuggerDisplay attribute. readonly struct ByteN, SByteN, Int16N, UInt16N, Int32N, UInt32N, Int64N, UInt64N, SingleN, DoubleN, DecimalN Wrappers for the built-in numeric types that implement INumeric<TSelf>, allowing them to be used in a generic context.

[Back to top]

4.4. Structures

Numeric structures, such as vectors, are provided for use in mathematical applications. These structures are generic on number type, supporting any implementation of INumeric<TSelf> (see §4.3. Framework for numbers). The table below summarizes the available structs and accompanying utilities.

Type Description readonly structUnitN<TNumeric> A wrapper for numeric types that clamps values between -1 and 1 (or 0 and 1 when unsigned). readonly structVector2N<TNumeric> A collection of two numeric values, X and Y, with extensive interface and operator support. readonly structVector3N<TNumeric> A collection of three numeric values, X, Y and Z, with extensive interface and operator support. static classVector2N Provides static methods for performing vector-based mathematics on instances of Vector2N<TNumeric>, such as dot product. static classVector3N Provides static methods for performing vector-based mathematics on instances of Vector3N<TNumeric>, such as dot product.

[Back to top]

4.5. Random extensions

Extension methods for System.Random add support for generating every built-in number type and types that implement INumeric<TSelf> (see §4.3. Framework for numbers).

Overloads are provided that allow greater flexibility with bounds via the Generation enum:

Generation.Default Uses the conventions established System.Random. Generation.Extended Bounds are inclusive, and can be specified in any order.

using Jodo.Numerics;
using System;

var value1 = new Random().NextDouble(double.MinValue, double.MaxValue); // Returns any finite double.
var value2 = new Random().NextUInt64(200, 100, Generation.Extended); // Returns a ulong between 100 and 200 (inclusive).

[Back to top]

4.6 Performance considerations

The number types provided by this library are structs that wrap built-in types and operations. Therefore they require additional memory and CPU time compared to using the built-in types alone.

Additionally, the number types within the Jodo.Numerics.Clamped namespace make use of the checked keyword for conversion and arithmetic. This further increases CPU time compared to using unchecked operations, especially in cases of overflow.

If developing a performance-sensitive application, use a profiler to assess the impact of introducing these types. Generally speaking, the impact is likely to be acceptable unless CPU-bound arithmetic is already on the hot path for the given application (e.g. in machine learning or 3D physics applications).

Benchmarks are provided to facilitate comparison with the built-in number types. To run the benchmarks, clone this repository then build and run Jodo.Numerics.Benchmarks in RELEASE mode (without a attaching a debugger).

Sample output can be seen below:

Jodo.Numerics.Benchmarks - Results from 2022-09-28 07:58:50Z

  • Processor: 11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz
  • Architecture: x64-based processor
  • .NET Version: .NET 5.0.17
  • Architecture: X64
  • OS: win10-x64
  • Seconds per Benchmark: 60.0
Subjects "(1)_Versus_(2)" Operations Per Second (1) Operations Per Second (2) Average Time (1) Average Time (2) Relative Speed (1) Relative Speed (2)
Fix64Logarithm_Versus_DoubleLogarithm 7.789E+06 5.183E+07 <1μs <1μs 0.15 6.65
Fix64Rounding_Versus_DoubleRounding 3.846E+07 3.637E+07 <1μs <1μs 1.06 0.95
Fix64StringParsing_Versus_DoubleStringParsing 1.842E+07 1.973E+07 <1μs <1μs 0.93 1.07
Fix64Random_Versus_DoubleRandom 2.4E+07 3.995E+07 <1μs <1μs 0.60 1.66
Fix64ToByteArray_Versus_DoubleToByteArray 4.831E+07 4.876E+07 <1μs <1μs 0.99 1.01
Fix64FromByteArray_Versus_DoubleFromByteArray 5.29E+07 5.225E+07 <1μs <1μs 1.01 0.99
Int32NArithmetic_Versus_Int32Arithmetic 5.03E+07 5.282E+07 <1μs <1μs 0.95 1.05
Int32MArithmetic_Versus_Int32Arithmetic 4.425E+07 5.215E+07 <1μs <1μs 0.85 1.18
SingleNArithmetic_Versus_SingleArithmetic 4.122E+07 5.623E+07 <1μs <1μs 0.73 1.36
SingleMArithmetic_Versus_SingleArithmetic 3.418E+07 5.634E+07 <1μs <1μs 0.61 1.65
DoubleNArithmetic_Versus_DoubleArithmetic 4.129E+07 5.565E+07 <1μs <1μs 0.74 1.35
DoubleMArithmetic_Versus_DoubleArithmetic 3.402E+07 5.527E+07 <1μs <1μs 0.62 1.62
DoubleNDivision_Versus_DoubleDivision 4.833E+07 5.392E+07 <1μs <1μs 0.90 1.12
DoubleNLogarithm_Versus_DoubleLogarithm 4.913E+07 5.244E+07 <1μs <1μs 0.94 1.07
DoubleNRounding_Versus_DoubleRounding 3.396E+07 3.597E+07 <1μs <1μs 0.94 1.06

[Back to top]

* * *

5. Jodo.Geometry (preview)

Provides geometric structs and utilities that support custom number types.

Coming soon (see section 2.2. "Roadmap")

[Back to top]

* * *

6. Jodo.Collections (preview)

Provides extra collection classes and interfaces to complement the .NET API.

Coming soon (see section 2.2. "Roadmap")

[Back to top]

7. Jodo.Primitives

Provides utilities and abstractions that are used throughout the Jodo libraries.

[Back to top]

7.1. Random variants

Provides a specification for randomly generating objects based on variants (categories). This feature is used extensively by the Jodo unit testing libraries to ensure that tests cover a variety of scenarios. Although the exact definition of each variant is left to the implementor, the following table serves as a guide:

Variant Description Defaults Null, zero, or any other default state for a given object. LowMagnitude Small values and values with reduced significance. AnyMagnitude Any value from the set of all possible values, excluding errors. Boundaries Minimum and maximum values. Errors Values that are typical of error scenarios, or values intended to elicit errors. All Encompasses all variants. NonError Encompasses all variants, except for errors.

Extension methods for System.Random allow for objects to be generated within these categories.

var random = new Random(); short num1 = random.NextVariant<Int16N>(Variants.LowMagnitude); short num2 = random.NextVariant<Int16N>(Variants.Defaults | Variants.Boundaries);

Console.WriteLine(num1); // output: 24 (example) Console.WriteLine(num2); // output: -32768 (example)

[Back to top]

7.2. Default providers

Documentation tbc

[Back to top]

7.3. Shims

Documentation tbc

[Back to top]

7.4. Stream extensions (preview)

Documentation tbc

[Back to top]

* * *


*Note that all licence references and agreements mentioned in the Jodo.Numerics README section above are relevant to that project's source code only.