Coder Social home page Coder Social logo

fixedmath.net's Introduction

This library implements "Fix64", a 64 bit fixed point 31.32 numeric type and transcendent operations on it (square root, trig, etc). It is well covered by unit tests. However, it is still missing some operations; in particular, Tangent is not well tested yet.

In the unit tests you'll find implementations for Int32-based (Q15.16) and Byte-based (Q3.4) numeric types. These were used for exploration of boundary conditions etc., but I'm keeping the code there only for reference.

This project started as a port of libfixmath (http://code.google.com/p/libfixmath/).

Note that the type requires explicit casts to convert to floating point and this is intentional, the difference between fixed point and floating point math is as important as the one between floating point and integral math.

fixedmath.net's People

Contributors

asik avatar jjcat avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fixedmath.net's Issues

Could you add Pow()?

First off, thank you so much for this library. It's the only one that I've found that I've gotten working for my application.

The one thing that it's missing that I really need is to be able to calculate fractional powers, the same as Mathf.Pow() does. I've found at least one library that seems to do it in 32bit (https://github.com/jpernst/FixedPointy/blob/master/FixMath.cs) but I lack the mathematical/bit manipulation skill to add it to your library. I think the place where I get tripped up in the FixedPointy implementation is it uses long to get enough space when calculating Pow(), so I'm not sure what to do to add it to your library.

Seems to be possible to convert into hardware implementation

FixedMath.Net seems to be almost completely possible to convert into an FPGA-based hardware implementation with our Hastlayer project. Hastlayer can automatically convert a subset of .NET into hardware implementations, providing significantly better performance in massively parallelizable compute-bound algorithms with lower power consumption.

And fixed point is very efficient with FPGAs.

Would be quite cool. What do you think?

Function Pow bug report

public static Fix64 Pow(Fix64 b, Fix64 exp)
if b is negative, Log2 will Throw exception.
bool isNeg = false;
if (b.m_rawValue < 0)
{
isNeg = true;
}
Fix64 log2 = isNeg ? Log2(-b) : Log2(b);

FixedMath.Net with Net 3.5 (Unity3D)

I'm trying to use the Fix64 in a Unity game project. Unity supports only .NET 2.0/3.5 era functionality. So I changed the project to .NET 3.5. After commented out unused "using System.Numerics" and "using System.Threading.Tasks" it was only "MethodImplOptions.AggressiveInlining" which was not available for .NET 3.5. After running the tests only the Sin() of Fix8 failed. So Fix64 seems to be working on .NET 3.5.

Do you think there might be any problems even the tests run through? Will the missing "MethodImplOptions.AggressiveInlining" be a big performance issue?

Thanks for your work! I keep you updated on the progress if your interested :-)

Cheers,
Markus

Debugging Determinism? (discussion)

This isn't an issue with FixedMath.Net, but I'm running out of places to ask about this.

My game has been built to use deterministic lockstep for networked multiplayer. Relatively recently I finally got online games to last more than five minutes before desyncing. The game is now at a point where things are desyncing inconsistently, in a way that is difficult to reproduce reliably. Until now, I have been using checksums, dumping readable gameplay data to file, and other tedious methods of debugging. (Sometimes resulting in 3+mb text files)

My question is... are there tools or methods to more easily debug this sort of thing?

Someone suggested I create a bot to automatically do the same action over and over until a desync occurs. This would help rule out certain weapons/actions, but it still has issues and is tedious. I thought about maybe some kind of memory dump? I really have no idea how I would do that though, and even then it would pose its own problems...

This game has been quite a trek for me. Any insights much appreciated. :)

Determinism

Is this library deterministic across processor architectures (aside from perhaps the floating point conversions)?

Using Math. for Fix32

Hello, I currently write my own version of a 32bit integer fixed-point math.

I only have square root left to do, and all these custom sqrt algorithms seem to be still slower than just performing the regular Math.Sqrt and cast it to int. The Dijkstras Square Root you seem to use is for example ~10 times slower than using+casting Math.Sqrt.

So I wonder if I just should do that. Rounding errors, which you try to avoid by using Fix math, are no matter here as the raw number has no point anyway, after which the machine-dependent rounding errors occurs.

Would like to hear your opinion on this. This is not really an "issue" but I am not sure how else to ask on Github.

Is changing "Fractional_Places" supported?

For my project, I would much prefer to have more integer places than decimal places. (I'm thinking maybe 5 or 8 decimal places)

If I change "const int FRACTIONAL_PLACES = 32;" to a lower value will everything still work correctly? Or do more changes need to be made or is it just plain unsupported?

Also, I'll probably be making a few extensions for this, like Vector2 or Vector3. They probably won't be that in depth, but would you be interested in something like this?

It's been hard to find any good libraries out there, and I'm not so great at the heavy math stuff, so thank you for your efforts! :)

request for Fixed32 too

I am working on imaging stuff, like triangle rasterization, etc, where I need fast, fixed point arithmetics within small range sizes (typically between -10000 to 10000) for fast line/triangle gradient calculation on images. Fixed64 is probably too big, but Fixed32 would be more than enough.

Performance wise, I don't know if on modern CPUs a Fixed32 would be faster than Fixed64... but if it is, it could be worth having a Fixed32 type.

Exploring the current code of Fixed64, I've found some details that I think could be improved:

  • Some constants could be predefined like INTEGER_MASK=0xffffffff00000000; and FRACTIONAL_MASK = 0x00000000ffffffff; that would definitely help porting Fixed64 to other sizes.
  • Instead of using long and ulong, you could declare aliases like this: using RAWSIGNED = long; and using RAWUNSIGNED = ulong; and use the aliases along the code, again, for the sake of porting to other sizes.
  • there's a new struct feature for c# 7.2 which is declaring a public readonly struct { } which enforces the struct to be inmutable; apparently this gives a lot of performance benefits, more here
  • Missing Fix64 Min(Fix64 a, Fix64 b); and Fix64 Max(Fix64 a, Fix64 b); functions

Any plans to make all conversions deterministic?

Hi,

conversions from/to double & float are using floating point multiplication/division which is not deterministic across platforms. Is there any chance to make them deterministic?

Thanks for you work!

Suggestion: need profiling.

Great work! Nice to have a profiling report comparing to float/double on different platforms, including desktops and mobiles, etc.

Is this library correct in terms of Base10 calculations?

I am exploring to use this library in a financial application where base 10 calculations must be correct within 10 decimal paces.

System.Decimal provides correct base 10 math within its precision range, I believe 28 decimal places.

This library is very exciting because many applications can benefit from a faster, yet correct numeric data type.

How does this library compare to System.Decimal in terms of correctness?

A bug when use Acos() to 2 normalized vector

It throw out exception "Must between -FP.One and FP.One"

The demo is as follow:

FP x1 = FP.FromRaw(3492999344);
FP y1 = FP.FromRaw(2499139782);
FP x2 = FP.FromRaw(-3492914803);
FP y2 = FP.FromRaw(-2499256617);
Debug.Log("x1: " + x1 + " y1: " + y1 + " x2: " + x2 + " y2: " + y2);  
// x1: 0.8132773 y1: 0.5818763 x2: -0.8132576 y2: -0.5819035

FP x1_normalized = x1 / FP.Sqrt(x1 * x1 + y1 * y1);
FP y1_normalized = y1 / FP.Sqrt(x1 * x1 + y1 * y1);
Debug.Log("normalized vector1 x: " + x1_normalized + " y: " + y1_normalized);
// normalized vector1 x: 0.8132773 y: 0.5818763

FP x2_normalized = x2 / FP.Sqrt(x2 * x2 + y2 * y2);
FP y2_normalized = y2 / FP.Sqrt(x2 * x2 + y2 * y2);
Debug.Log("normalized vector2 x: " + x2_normalized + " y: " + y2_normalized); 
// normalized vector2 x: -0.8132578 y: -0.5819036

FP dot = x1_normalized * x2_normalized + y1_normalized * y2_normalized;
Debug.Log("Dot of vector1 and vector2: " + dot); 
// Dot of vector1 and vector2: -1
            
FP.Acos(dot); 
// ArgumentOutOfRangeException: x 
// Parameter name: Must between -FP.One and FP.One 

The code of Fix64:

        /// <summary>
        /// Returns the arccos of of the specified number, calculated using Atan and Sqrt
        /// This function has at least 7 decimals of accuracy.
        /// </summary>
        public static FP Acos(FP x)
        {
            if (x < -One || x > One)
            {
                throw new ArgumentOutOfRangeException("Must between -FP.One and FP.One", "x");
            }

            if (x.RawValue == 0) return PiOver2;

            var result = Atan(Sqrt(One - x * x) / x);
            return x.RawValue < 0 ? result + Pi : result;
        }

Problem: Sqrt() for Q48.15 format implementation

Good Repo!
I have met a problem to the sqrt for Q48.15 format fixed point. I try to modify your sqrt code, but can not get the correct answer. Is your sqrt only available on Q31.32 format? Code below is my version, I use NUM_BITS /4 - 1 to represent number 15. I would also glad if you can list the detail comments of the fixed point sqrt implementation.

public static Fix64 Sqrt(Fix64 x) {
    var xl = x.m_rawValue;
    if (xl < 0) {
        // We cannot represent infinities like Single and Double, and Sqrt is
        // mathematically undefined for x < 0. So we just throw an exception.
        throw new ArgumentException("Negative value passed to Sqrt", "x");
    }

    var num = (ulong)xl;
    var result = 0UL;

    // second-to-top bit
    var bit = 1UL << (NUM_BITS - 2);

    while (bit > num) {
        bit >>= 2;
    }

    // The main part is executed twice, in order to avoid
    // using 128 bit values in computations.
    for (var i = 0; i < 2; ++i) {
        // First we get the top 48 bits of the answer.
        while (bit != 0) {
            if (num >= result + bit) {
                num -= result + bit;
                result = (result >> 1) + bit;
            }
            else {
                result = result >> 1;
            }
            bit >>= 2;
        }

        if (i == 0) {
            // Then process it again to get the lowest 16 bits.
            if (num > (1UL << (NUM_BITS / 4 - 1)) - 1) {
                // The remainder 'num' is too large to be shifted left
                // by 32, so we have to add 1 to result manually and
                // adjust 'num' accordingly.
                // num = a - (result + 0.5)^2
                //       = num + result^2 - (result + 0.5)^2
                //       = num - result - 0.5
                num -= result;
                num = (num << (NUM_BITS / 4 - 1)) - 0x4000UL;
                result = (result << (NUM_BITS / 4 - 1)) + 0x4000UL;
            }
            else {
                num <<= (NUM_BITS / 4 - 1);
                result <<= (NUM_BITS / 4 - 1);
            }

            bit = 1UL << (NUM_BITS / 4 - 2 - 1);
        }
    }
    // Finally, if next bit would have been 1, round the result upwards.
    if (num > result) {
        ++result;
    }
    return new Fix64((long)result);
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.