{"id":21576341,"url":"https://github.com/sigurd4/custom_float","last_synced_at":"2025-06-15T14:10:54.811Z","repository":{"id":221557733,"uuid":"754708834","full_name":"sigurd4/custom_float","owner":"sigurd4","description":"Customizable floating point types, with all standard floating point operations implemented from scratch.","archived":false,"fork":false,"pushed_at":"2024-02-26T21:35:25.000Z","size":15885,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-24T14:13:59.170Z","etag":null,"topics":["bfloat16","float","floating-point","ieee754","tensorfloat"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/custom_float","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sigurd4.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2024-02-08T16:10:07.000Z","updated_at":"2024-02-24T11:32:00.000Z","dependencies_parsed_at":"2024-02-19T01:24:20.933Z","dependency_job_id":"efa76fc6-7d1f-4da7-9a8a-e2cc385815ec","html_url":"https://github.com/sigurd4/custom_float","commit_stats":null,"previous_names":["sigurd4/custom_float"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sigurd4%2Fcustom_float","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sigurd4%2Fcustom_float/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sigurd4%2Fcustom_float/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sigurd4%2Fcustom_float/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sigurd4","download_url":"https://codeload.github.com/sigurd4/custom_float/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248252691,"owners_count":21072701,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bfloat16","float","floating-point","ieee754","tensorfloat"],"created_at":"2024-11-24T12:16:14.189Z","updated_at":"2025-06-15T14:10:54.798Z","avatar_url":"https://github.com/sigurd4.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status (nightly)](https://github.com/sigurd4/custom_float/workflows/Build-nightly/badge.svg)](https://github.com/sigurd4/custom_float/actions/workflows/build-nightly.yml)\n[![Build Status (nightly, all features)](https://github.com/sigurd4/custom_float/workflows/Build-nightly-all-features/badge.svg)](https://github.com/sigurd4/custom_float/actions/workflows/build-nightly-all-features.yml)\n\n[![Build Status (stable)](https://github.com/sigurd4/custom_float/workflows/Build-stable/badge.svg)](https://github.com/sigurd4/custom_float/actions/workflows/build-stable.yml)\n[![Build Status (stable, all features)](https://github.com/sigurd4/custom_float/workflows/Build-stable-all-features/badge.svg)](https://github.com/sigurd4/custom_float/actions/workflows/build-stable-all-features.yml)\n\n[![Test Status](https://github.com/sigurd4/custom_float/workflows/Test/badge.svg)](https://github.com/sigurd4/custom_float/actions/workflows/test.yml)\n[![Lint Status](https://github.com/sigurd4/custom_float/workflows/Lint/badge.svg)](https://github.com/sigurd4/custom_float/actions/workflows/lint.yml)\n\n[![Latest Version](https://img.shields.io/crates/v/custom_float.svg)](https://crates.io/crates/custom_float)\n[![License:MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Documentation](https://img.shields.io/docsrs/custom_float)](https://docs.rs/custom_float)\n[![Coverage Status](https://img.shields.io/codecov/c/github/sigurd4/custom_float)](https://app.codecov.io/github/sigurd4/custom_float)\n\n# custom_float\n\nThis crate adds a custom floating point number type, `Fp\u003cU, SIGN_BIT, EXP_SIZE, INT_SIZE, FRAC_SIZE, EXP_BASE\u003e`, where the bit size of the exponent and mantissa can be set separately, as well as the base of the exponent (which is normally 2).\n\nThis allows simple implementation of special floating point types, such as TensorFloat, IEEE754 Decimals (decimal32, decimal64, etc.), Fp80, and BFloat16.\n\n## Composition\n\n`U` is the underlying unsigned integer type which is used to represent the number.\n\n`SIGN_BIT` is wether or not the number has a sign bit.\n\n`EXP_SIZE` is the size of the exponent in bits.\n\n`INT_SIZE` is the size of the integer part of the mantissa in bits. If zero, then the integer bit is implicit.\n\n`FRAC_SIZE` is the size of the fractional part of the mantissa in bits.\n\n`EXP_BASE` is the base of the exponent.\n\nThe total bit size of `U` must be greater or equal to `SIGN_BIT` + `EXP_SIZE` + `INT_SIZE` + `FRAC_SIZE` to contain the entire number.\n\nThe bit layout is as follows:\n```txt\nNo data: | Sign:      | Exponent:  | Integer:   | Fractional: |\n\u003c  ..  \u003e | \u003cSIGN_BIT\u003e | \u003cEXP_SIZE\u003e | \u003cINT_SIZE\u003e | \u003cFRAC_SIZE\u003e |\n```\n\nThe value of a real floating-point number is the following:\n```txt\nx = (-1)**sign*EXP_BASE**(exponent - bias)*mantissa\n```\n\nwhere the bias equals\n```txt\nbias = 2**(EXP_SIZE - 1) - 1\n```\n\nIf the exponent has the maximum value, the number is either infinity or NaN.\n\n## Features\n\nThis crate provides the type `Fp`, and not really anything else.\n\n### Traits\n\nAll `Fp`'s automatically implement `num::Float`, and supports all ordinary floating point operations you'd expect (`sin`, `cos`, `tanh`, `sqrt`, `exp`, `ln`, `powf`, etc. as well as operators `+`, `-`, `*`, `/`, `%`). I've also implemented some equivalents to some of the rational functions from `libm` (like `erf`, `erfc`, and bessel-functions `j0`, `y0`, etc.).\n\n### Size\n\nThe biggest integers in the standard library are 128-bit, so if you want floating point numbers with more bits than that, you have to provide your own 128-bit unsigned integer type, but in theory, it should be possible to have, say, 16384-bit floats, if you want to.\n\n### Conversion\n\nAll `Fp`'s can be converted into each other with `Fp::from_fp`. For now, due to trait-implementation conflicts, the `From` trait can't be used for this, because it would conflict with the implementation of `T: From\u003cT\u003e`.\n\nAll `Fp`'s implement `From` and `Into` for all standard-library numeric types (unsigned integers: `u8`, `u16`, `u32`, `u64`, `u128`, signed integers `i8`, `i16`, `i32`, `i64`, `i128`, and floats `f16`, `f32`, `f64`, `f128`).\n\nOf course, narrowing conversions will result in rounding-errors and unbounded values.\n\n### Aliases\n\nThere are a couple of pre-made aliases for floats available too. They're just type-aliases for `Fp`.\n\n### Compatability\n\nThe following types are bitwise interchangeable:\n- `f16` and `FpHalf`\n- `f32` and `FpSingle`\n- `f64` and `FpDouble`\n\nI've read that `binary128` may have an odd two-bit prefix in the exponent, that may work slightly different from the lesser IEEE754 binary floats. According to my tests, `f128` and `FpQuadruple` also seem to be interchangeable, even though i'm not sure if `f128`s always work like this on every compilation target. Please make a report if you notice problems with this!\n\n## Examples\n\n```rust\nuse custom_float::Fp;\n\n// This type is also available as `custom_float::ieee754::FpSingle`\ntype FpSingle = Fp\u003cu32, true, 8, 0, 23, 2\u003e;\n\nlet two = FpSingle::from(2);\nlet four = FpSingle::from(4);\n\nassert_eq!(two + two, four);\nassert_eq!(two * two, four);\nassert_eq!(two / four, two.recip());\nassert_eq!(four - two, two);\n```\n\n## Performance\n\nThis crate is obviously slower than the primitive floats in the standard library, because my implementations are not just LLVM-intrinisics. For nonstandard floating-point formats, you probably wont even find processors that can do these kinds of operations atomically. For base 2 floats that also match the primitive standard-library floats (f16, f32, f64, f128) in form, you can enable the feature `use_std_float` to convert them and do the operation natively instead, which may give a performance boost. This will only happen with floats that are trivially convertable with either f16, f32, f64 or f128.\n\nYou can see comparisons with this library's floats and the standard library's in the [plots/bench](https://github.com/sigurd4/custom_float/tree/master/plots/bench) folder. For some methods not found in `std`/`core`, i use `libm` instead as a comparison.\n\n## Accuracy\n\nThe accuracy is obviously dependent on the size of your float's mantissa and its base, and its range depends on the size of its exponent. But given a float with a (practically) infinite resolution, some functions on here still give an error. My goal is to make that error as small as possible. The accuracy of all of the floating point operations are not perfect, but work well enough to be usable.\n\nYou can see comparisons with this library's floats and the standard library's in the [plots](https://github.com/sigurd4/custom_float/tree/master/plots) folder, and error in the [plots/error](https://github.com/sigurd4/custom_float/tree/master/plots/error). For some methods not found in `std`/`core`, i use `libm` instead as a comparison.\n\n## Planned features\n\n- Make more and more of the functions work at compile-time.\n    - This is currently difficult because my code is very generic, and relies on traits from the `num-traits` crate (that are not const-traits, because those are experimental). Once rust's const-traits are a stable language-feature, you'll see more of this.\n- Stabilize large bases. Currently i mostly just test base 2 and 10. For large bases (say, 1000) you tend to get integer overflow.\n- Stabilize edge cases like unsigned floats, exponentless floats (fixed-point, really), and mantissaless floats (just exponentials?).\n- Bigfloats? (maybe for a separate crate)\n- Serde-integration\n- Proper (not convert-to-nearest-std-float) implementations of `Debug`, `Display`, and `FromStr`.\n- Use signaling NaN's correctly.\n- Make it run faster, of course!\n\nSuggestions are welcome.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsigurd4%2Fcustom_float","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsigurd4%2Fcustom_float","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsigurd4%2Fcustom_float/lists"}