This is just to satisfy my own curiosity.
Is there an implementation of this:
float InvSqrt (float x)
{
float xhalf = 0.5f*x;
int i = *(int*)&x;
i = 0x5f3759df - (i>>1);
x = *(float*)&i;
x = x*(1.5f - xhalf*x*x);
return x;
}
in C#? If it exists, post the code.
I guess I should have mentioned I was looking for a "safe" implementation... Either way, the BitConverter code solves the problem. The union idea is interesting. I'll test it and post my results.
Edit:
As expected, the unsafe method is the quickest, followed by using a union (inside the function), followed by the BitConverter. The functions were executed 10000000 times, and the I used the System.Diagnostics.Stopwatch class for timing. The results of the calculations are show in brackets.
Input: 79.67
BitConverter Method: 00:00:01.2809018 (0.1120187)
Union Method: 00:00:00.6838758 (0.1120187)
Unsafe Method: 00:00:00.3376401 (0.1120187)
For completeness, I tested the built-in Math.Pow method, and the "naive" method (1/Sqrt(x)).
Math.Pow(x, -0.5): 00:00:01.7133228 (0.112034710535584)
1 / Math.Sqrt(x): 00:00:00.3757084 (0.1120347)
The difference between 1 / Math.Sqrt() is so small that I don't think one needs to resort to the Unsafe Fast InvSqrt() method in C# (or any other unsafe method). Unless one really needs to squeeze out that last bit of juice from the CPU... 1/Math.Sqrt() is also much more accurate.
You should be able to use the StructLayout and FieldOffset attributes to fake a union for plain old data like floats and ints.
[StructLayout(LayoutKind.Explicit, Size=4)]
private struct IntFloat {
[FieldOffset(0)]
public float floatValue;
[FieldOffset(0)]
public int intValue;
// redundant assignment to avoid any complaints about uninitialized members
IntFloat(int x) {
floatValue = 0;
intValue = x;
}
IntFloat(float x) {
intValue = 0;
floatValue = x;
}
public static explicit operator float (IntFloat x) {
return x.floatValue;
}
public static explicit operator int (IntFloat x) {
return x.intValue;
}
public static explicit operator IntFloat (int i) {
return new IntFloat(i);
}
public static explicit operator IntFloat (float f) {
return new IntFloat(f);
}
}
Then translating InvSqrt is easy.
Use BitConverter if you want to avoid unsafe code.
float InvSqrt(float x)
{
float xhalf = 0.5f * x;
int i = BitConverter.SingleToInt32Bits(x);
i = 0x5f3759df - (i >> 1);
x = BitConverter.Int32BitsToSingle(i);
x = x * (1.5f - xhalf * x * x);
return x;
}
The code above uses new methods introduced in .NET Core 2.0. For .NET Framework, you have to fall back to the following (which performs allocations):
float InvSqrt(float x)
{
float xhalf = 0.5f * x;
int i = BitConverter.ToInt32(BitConverter.GetBytes(x), 0);
i = 0x5f3759df - (i >> 1);
x = BitConverter.ToSingle(BitConverter.GetBytes(i), 0);
x = x * (1.5f - xhalf * x * x);
return x;
}
Otherwise, the C# code is exactly the same as the C code you gave, except that the method needs to be marked as unsafe:
unsafe float InvSqrt(float x) { ... }
Definitely possible in unsafe mode. Note that even though in the Quake 3 source code the constant 0x5f3759df was used, numerical research showed that the constant 0x5f375a86 actually yields better results for Newton Approximations.
I don't see why it wouldn't be possible using the unsafe compiler option.
Related
Suppose you have two structs that have exactly the same memory layout. Is it possible to do a very fast unchecked memory cast from one to the other in C#/.NET?
//my code base
[StructLayout(LayoutKind.Sequential)]
public struct VectorA
{
float x;
float y;
float z;
}
//defined by a third party library
[StructLayout(LayoutKind.Sequential)]
public struct VectorB
{
float a;
float b;
float c;
}
//somewhere else in my code
var vectorA = new VectorA();
//then calling a method from the library
MethodFromThirdPartyLibrary((VectorB)vectorA); //compiler error
Of course it should be faster as a method that assigns the data fields and creates a new copy in memory.
Also: The 3d vector is only an example, same problem for matrices which is 16 floats and Vector2, Vector4, ...
EDIT: Improved code with more comments and better usage example.
Why would it be faster? Would it be faster in C++ than writing the copy explicitly as in C#? Remember, you only have 3 x 32-bit numbers you want to copy from one place to another, so it's not exactly a good fit for vectorization.
It's likely if you had an array of these structures that you could get some speed up using vectorized load/stores in an unrolled loop in assembler. But you've not stated that in the question.
The main overhead here is probably the method call, rather than the assignment:
static void VecAToB(ref VectorA vectorA, ref VectorB vectorB)
{
vectorB.x = vectorA.a;
vectorB.y = vectorA.b;
vectorB.z = vectorA.c;
}
You might like to try:
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static void VecAToB(ref VectorA vectorA, ref VectorB vectorB)
{
vectorB.x = vectorA.a;
vectorB.y = vectorA.b;
vectorB.z = vectorA.c;
}
I have this code;
static int test = 100;
static int Test
{
get
{
return (int)(test * 0.01f);
}
}
output is : 0
But this code returns different
static int test = 100;
static int Test
{
get
{
var y = (test * 0.01f);
return (int)y;
}
}
output is : 1
Also I have this code
static int test = 100;
static int Test
{
get
{
return (int)(100 * 0.01f);
}
}
output is : 1
I look at IL output and I dont understand why C# doing this mathematical operation at compile time and output different?
What is difference of this two code? Why I decided to use variable result is changing?
Because the compiler tricks you. The compiler is smart enough to do some math already so it doesn't need to do that on run-time, which would be pointless. The expression 100 * .01f is calculated in the compiler, without the lack of precision on the float, which breaks you up on run-time.
To prove this, try to make the static test a const. You will see the compiler is able to do the math for you on compile time then too. It has nothing with writing to a variable first, as in your sample. Run-time vs. compile-time is.
Good day. I'm implementing the Complex class in C# with Mono under Ububntu 14.04. I have found some strange behaviors when I tied to implement the multiplication between a double and a Complex.
My Complex implementation is something like
using System;
namespace Mynamespace {
public class Complex {
public double re;//Real part
public double im;//Imaginary part
public Complex (double a, double b){
re = a;
im = b;
}
public static Complex operator *(double k, Complex x){
return new Complex (k * x.re, k * x.im);
}
}}
The test code is like
...
Complex a = new Complex (1, 1);
double b = 2.0;
Complex c = b * a;
...
The strange behavior is that the operator * returns the wrong result. I noticed that when * is called the argument of type double has the wrong value within the function (I pass b = 2 and I see that the argument k has a random value).
I have also tried to implement the function without using operators:
...
public Complex Multiply(double k){
return new Complex (k * re, k * im)
}
...
and also
...
public static Complex Multiply (double k, Complex x){
return new Complex (k * x.re, k * x.im)
}
...
but I obtain alwais the same behavior.
I have tried it under C# in .net (Windows7) and everything works perfectly.
Does anybody have any suggestion on how to fix it?
Best regards
Federico
I have solved the issue with something like
public static Complex operator *(object k, complex x){
return new ((double)k * x.re, (double)k * x.im);
}
Now everything works well. If you have any suggestion for understanding the problem I had, they are all welcomed.
Best regards
Federico
In C I will do this to convert float representation of number into DWORD. Take the value from the address and cast the content to DWORD.
dwordVal = *(DWORD*)&floatVal;
So for example 44.54321 will become 0x42322C3F.
How can I do the same in C#?
You can use the BitConverter class:
uint value = BitConverter.ToUInt32(BitConverter.GetBytes(44.54321F), 0);
Console.WriteLine("{0:x}", value); // 42322c3f
You could also do this more directly using an unsafe context:
float floatVal = 44.54321F;
uint value;
unsafe {
value = *((uint*)(&floatVal));
}
Console.WriteLine("{0:x}", value); // 42322c3f
However, I'd strongly recommend avoiding this. See Should you use pointers (unsafe code) in C#?
Use the BitConverter class:
float f = 44.54321f;
uint u = BitConverter.ToUInt32(BitConverter.GetBytes(f), 0);
System.Diagnostics.Debug.Assert(u == 0x42322C3F);
In .NET Core 2.0 you can use BitConverter.SingleToInt32Bits(). The reverse operation is BitConverter.Int32BitsToSingle()
.NET 6 added 2 more utilities:
BitConverter.UInt32BitsToSingle()
BitConverter.SingleToUInt32Bits()
bitconvert creates a new byte array on every call.
this is the solution:
unsafe public static float ToDecibel(this float x)
{
uint* y = (uint*)&x;
(*y) &= 0x7fffffff;
return (*y) * 7.17711438e-7f - 764.6161886f;
}
I know that blocks can be passed to a instance method and the method can be written as follow,
-(void)Method:((void) (^)(float)f)
{
f(0.5);
}
Also, this method is also a valid expression.
-(void)Method:((void) (*)(float)f)
{
f(0.5);
}
I want to know that what can i pass to this method? And what is the usage of this?
Besides, I want to know that is there any obj-c equivalent of the following c# code? Because I am wondering that obj-c has function pointer or not.
public static float Sum(float x, float y)
{
return x+y;
}
public delegate float Operation(float x, float y);
public static Main()
{
Operation dSum = Sum;
Console.WriteLine(dSum(0.5, 1.5));
}
Your second Objective-C method takes a C function pointer whose addressed function has a float as input and returns nothing. It's the same as with the block:
typedef void (^ BlockType)(float);
- (void)blockMethod: (BlockType)block {
block(1.0);
}
[obj blockMethod:aBlock];
vs.
typedef void (* FuncType)(float);
- (void)funcMethod: (FuncType)func {
func(1.0);
}
[obj funcMethod:aFunc];
The difference being that a function cannot capture its surrounding state (and that a function is a function, and a block is a block.)
This doesn't require Objective-C; what you're trying to do can be translated pretty easily to straight C:
static float sum(float x, float y)
{
return x + y;
}
typedef float (*Operation)(float x, float y);
int main(int argc, char **argv)
{
Operation dSum = sum;
printf("%f\n", dSum(0.5, 1.5));
return 0;
}
That should all look pretty recognizable.