How do I use RSACryptoServiceProvider to decrypt, given that I only have p, q, d and u? - cryptography

I am creating a simple client app to experiment with Mega and I am having trouble wrapping my head around the way RSA is used. Let's take, for example, the decryption of the session ID - this is one of the first things that must be done in order to log in.
The API provides me the following RSA data:
p (1024 bits)
q (1024 bits)
d (2044 bits)
u (1024 bits)
To start with, I do not know what "u" stands for. I see from code that it is calculated by modinverse(p, q) - is this what is commonly referred to as qInverse?
This is considerably less RSA data for a private key than I have used previously, so I am not quite sure what to make of it. However, I am given to understand that some of the RSA data used by RSACryptoServiceProvider is just pre-calculated data for optimization purposes, so perhaps the rest is not needed?
Using this data, the site's JavaScript decrypts the session ID with the following function:
// Compute m**d mod p*q for RSA private key operations.
function RSAdecrypt(m, d, p, q, u)
{
var xp = bmodexp(bmod(m,p), bmod(d,bsub(p,[1])), p);
var xq = bmodexp(bmod(m,q), bmod(d,bsub(q,[1])), q);
var t=bsub(xq,xp);
if(t.length==0)
{
t=bsub(xp,xq);
t=bmod(bmul(t, u), q);
t=bsub(q,t);
}
else
{
t=bmod(bmul(t, u), q);
}
return badd(bmul(t,p), xp);
}
I would like to do this in .NET using RSACryptoServiceProvider but if I give it the 4 pieces of data I have (assuming u == qInverse), the key is rejected during import with a "Bad data" exception.
Should I be doing something more to the data? Is RSACryptoServiceProvider usable in this situation at all?
Example of the parameters and encrypted data I am testing with follows.
var p = Convert.FromBase64String("1AkMwy3SPbJtL/k2RUPNztBQKow0NX9LVr5/73+zR3cuwgUToYkVefKdzlTgeri9CAVUq/+jU6o+P7sUpPUN+V97quZa00m3GSIdonRMdaMrDDH5aHnkQgOsCjLJDWXU6+TQBqLumR3XMSat3VO09Dps+6NcMc+uMi5atC3tb+0=");
var q = Convert.FromBase64String("qtnlmPbATJajNdihw1K6cwSormySATp7g75vYfilYx6RXN3xpNCZR/i8zFbx/lDh+n1a2rdHy1nWyuaD3UmE26d1xUkmsPDfBc72WXt88UqWE/gF7NJjtgTxS2Ui+2GGKUCloi5UA/pOI7R5TBvGI8zna00SH78bctyE0dcAcwM=");
var d = Convert.FromBase64String("CFL4QPQ8zLzrf2bUzCVX8S2/eALzo/P2cvQsW9lft7uelHYfC1CvHP+z4RvQgXABpgT8YTdU+sgdMHrhHT1vxeUaDRkcQv9lV0IP6YtAcD+gk5jDQkXk4ruYztTUF3v4u8rlMuZ8kAKKWKw+JH6grLWD/vXjMv2RybxPqq3fKI6VJaj/Y/ZnDjD5HrQmJopnCbOrZrPysNb/rGrN3ad9ysaZwBvQtIE0/tQvmL+lsI+PfF9oGKeHkciIo0D4N2abOKT2fiazNm1U9LnrQih687ge0aeAlP2OO8c0h/nbEkMbNg83n1GGEt3DNojIWbT5uHaj12M6G81leS77mfLvSQ==");
var u = Convert.FromBase64String("CNlUzgCf6Ymd/qeWiv3ScCIXYCwjP3SNLHxRgozIbNg2JEKpJn2M3vO72qLI+FT34xckaAGIcKWMkmpoaKy6PYF4jsAz2atLEClLimbMEPvpWxK7b/I5yvXMT7i2r5hr0OjjplL0wFQYL1IS2M8DTrL99rd9zXCoCWg5Tax6zQM=");
var encryptedData = Convert.FromBase64String("CABt/Qp7ZODvweEk5RY9JNMXoyFfUwMnc53zbP5jB4jnwWXibLLvjc+Dv5CwQAtUYRme+vRd80++178BiWl0YSOKKhQaDQKoeOUONn3KbZVWyCtyWyQZNtASPoQfizay/Dw3yP5BKsJmDpEv47awdEZzh8IqTcTKeQbpHFL+3uL5EjIENpxMh15rJUsY9w+jq6Yax+379tq67EPMUON0aYkRQ3k1Rsp9fOL6qrgoqOPmOc0cIQgx76t6SFB9LmDySkyBhtK+vcEkdn9GwzZqc6n/Jqt9K8a+mbBv3K7eO3Pa37SDncsaxEzlyLwQ2om1+bK2QwauSQl+7QwQS1a9Ejb9");
var rsa = new RSACryptoServiceProvider();
// Throws exception saying "Bad data"
rsa.ImportParameters(new RSAParameters
{
D = d,
P = p,
Q = q,
InverseQ = u
});
Addendum February 2
I have dug around in the linked StackOverflow answers and have reached the point where I think I have determined how to generate the missing component. However, now I am getting a "Bad key" exception, which has me stumped.
I will write the code I am using to generate the missing components - perhaps you can spot an error somewhere?
I have also calculated InverseQ and D manually and the values match those in my input data. Below is my function for generating the required data based only on q, p and e.
private static RSAParameters CalculateRsaParameters(BigInteger p, BigInteger q, BigInteger e)
{
var modulus = BigInteger.Multiply(p, q);
var phi = BigInteger.Multiply(BigInteger.Subtract(p, BigInteger.One), BigInteger.Subtract(q, BigInteger.One));
BigInteger x, y;
// From http://www.codeproject.com/Articles/60108/BigInteger-Library
// Returns 1 with my test data.
ExtendedEuclidGcd(e, phi, out x, out y);
var d = BigInteger.Remainder(x, phi);
var dp = BigInteger.Remainder(d, BigInteger.Subtract(p, BigInteger.One));
var dq = BigInteger.Remainder(d, BigInteger.Subtract(q, BigInteger.One));
BigInteger x2, y2;
// Returns 1 with my test data.
ExtendedEuclidGcd(q, p, out x2, out y2);
// y2 since it matched the pre-generated inverseQ data I had and x2 was some negative value, so it did not seem to fit. I have no idea what the logic behind which to pick really is.
var qInverse = BigInteger.Remainder(y2, p);
return new RSAParameters
{
D = ToBigEndianByteArray(d, 256),
DP = ToBigEndianByteArray(dp, 128),
DQ = ToBigEndianByteArray(dq, 128),
InverseQ = ToBigEndianByteArray(qInverse, 128),
Exponent = ToBigEndianByteArray(e, 1),
Modulus = ToBigEndianByteArray(modulus, 256),
P = ToBigEndianByteArray(p, 128),
Q = ToBigEndianByteArray(q, 128)
};
}
My input data is:
e = 17
p = 148896287039501678969147386479458178246000691707699594019852371996225136011987881033904404601666619814302065310828663028471342954821076961960815187788626496609581811628527023262215778397482476920164511192915070597893567835708908996890192512834283979142025668876250608381744928577381330716218105191496818716653
q = 119975764355551220778509708561576785383941026741388506773912560292606151764383332427604710071170171329268379604135341015979284377183953677973647259809025842247294479469402755370769383988530082830904396657573472653613365794770434467132057189606171325505138499276437937752474437953713231209677228298628994462467
And here is how I make use of the generated structure:
var rsa = new RSACryptoServiceProvider(2048);
rsa.ImportParameters(CalculateRsaParameters(p, q, e));
The ImportParameters call throws an exception saying "Bad key". What am I doing wrong?
What happens if I switch Q and P?
Apparently, it makes RSACryptoServiceProvider accept the data! But what does this mean exactly?
I got the idea from the way I had to use ExtendedEuclidGcd in my generation code. Having to use different outputs for the two instances bothered me a lot, so I performed this experiment.
One thing is that u != qInverse - is this correct? I do not understand the math in the original JavaScript function, so I am not sure what the implications are. Am I right in guessing that the u value in the original is in fact some internal shortcut and not QInverse?
Further testing to follow (i.e. actual decryption of data). I will edit the question with any new developments once made.
Decryption fails with this parameter set
The encrypted test data I have is (base64-encoded):
/TYSvVZLEAztfglJrgZDtrL5tYnaELzI5UzEGsudg7Tf2nM73q7cb7CZvsYrfasm/6lzajbDRn92JMG9vtKGgUxK8mAufVBIeqvvMQghHM055uOoKLiq+uJ8fcpGNXlDEYlpdONQzEPsutr2++3HGqarow/3GEsla16HTJw2BDIS+eLe/lIc6QZ5ysRNKsKHc0Z0sLbjL5EOZsIqQf7INzz8sjaLH4Q+EtA2GSRbcivIVpVtyn02DuV4qAINGhQqiiNhdGmJAb/Xvk/zXfT6nhlhVAtAsJC/g8+N77Js4mXB54gHY/5s851zJwNTXyGjF9MkPRblJOHB7+Bkewr9bQ==
or
bf0Ke2Tg78HhJOUWPSTTF6MhX1MDJ3Od82z+YweI58Fl4myy743Pg7+QsEALVGEZnvr0XfNPvte/AYlpdGEjiioUGg0CqHjlDjZ9ym2VVsgrclskGTbQEj6EH4s2svw8N8j+QSrCZg6RL+O2sHRGc4fCKk3EynkG6RxS/t7i+RIyBDacTIdeayVLGPcPo6umGsft+/bauuxDzFDjdGmJEUN5NUbKfXzi+qq4KKjj5jnNHCEIMe+rekhQfS5g8kpMgYbSvr3BJHZ/RsM2anOp/yarfSvGvpmwb9yu3jtz2t+0g53LGsRM5ci8ENqJtfmytkMGrkkJfu0MEEtWvRI2/Q==
Two alternatives given since I am not sure of the byte order. It is the same data in both strings.
Decryption of both of these fails with an exception saying "Bad data" in the first case and "Not enough storage is available to process this command." in the second case (which MSDN claims might mean that the key does not match the encrypted data). I am telling RSACryptoServiceProvider that PKCS padding is used, though I also experimented with OAEP (which just gave an error about failing to decode padding).
The original JavaScript decrypts the data without a problem, though its "p" and "q" are switched around from mine.
Right now, my questions are:
Is the P and Q switch-around a valid operation to do?
Is my reasoning valid or have I made a mistake somewhere?
What should I do next to successfully decrypt my test data?

RsaParameters has eight fields. I think you need to initialize all of them when creating a private key.
Take a look at http://msdn.microsoft.com/en-us/library/system.security.cryptography.rsaparameters.aspx

There are a number of possible pitfalls that one can trip over in using .NET BigIntegers and RSA parameters. The two that are probably impacting you are endianness and leading zero suppression.
System.Numerics.BigInteger class, available starting in .NET 4.0, uses a litte-endian format for its ToByteArray() method and new BigInteger(byte []) constructor.
Unfortunately, the RSAParameters structure expects its byte array fields to be in big-endian order. There is also one other incompatibility that must be accounted for. A System.Numerics.BigInteger may be either positive or negative, and the ToByteArray() method accounts for this by using a variant of twos-complement representation. Effectively this means that a positive BigInteger whose byte array representation has a high-order byte >=
128 will have an additional zero byte placed in highest order position. However, the RSAParameter fields are assumed to be all positive, so a leading zero is gratuitously rejected with a "Bad Data" CryptographicException. You must delete these leading zeros where they occur.
The following is a simple example code fragment showing these operations:
static BigInteger ExtGCD(BigInteger a, BigInteger b, out BigInteger lastx, out BigInteger lasty)
{
var x = BigInteger.Zero;
lastx = BigInteger.One;
var y = BigInteger.One;
lasty = BigInteger.Zero;
while (!b.IsZero)
{
BigInteger remainder;
BigInteger q = BigInteger.DivRem(a, b, out remainder);
a = b;
b = remainder;
var t = x;
x = lastx - q * x;
lastx = t;
t = y;
y = lasty - q * y;
lasty = t;
}
return a;
}
static BigInteger inverse(BigInteger a, BigInteger n)
{
BigInteger d, x, y;
d = ExtGCD(a, n, out x, out y);
if (d.IsOne)
{
// Always return the least positive value
return (x + n) % n;
}
else
{
throw new ArgumentException("the arguments must be relatively prime, i.e. their gcd must be 1");
}
}
static byte[] ToByteArrayBE(BigInteger b)
{
var x = b.ToByteArray(); // x is little-endian
Array.Reverse(x); // now it is big-endian
if (x[0] == 0)
{
var newarray = new byte[x.Length - 1];
Array.Copy(x, 1, newarray, 0, newarray.Length);
return newarray;
} else
{
return x;
}
}
static RSAParameters CalculateRsaParameters(BigInteger p, BigInteger q, BigInteger e)
{
// Given p, q, and e (the RSA encryption exponent) compute the remaining parameters
var phi = (p - 1) * (q - 1);
var d = inverse(e, phi);
var dp = d % (p - 1);
var dq = d % (q - 1);
var qInv = inverse(q, p);
var RsaParams = new RSAParameters
{
Modulus = ToByteArrayBE(p * q),
Exponent = ToByteArrayBE(e),
P = ToByteArrayBE(p),
Q = ToByteArrayBE(q),
D = ToByteArrayBE(d),
DP = ToByteArrayBE(dp),
DQ = ToByteArrayBE(dq),
InverseQ = ToByteArrayBE(qInv)
};
return RsaParams;
}
static void Main(string[] args)
{
BigInteger p = BigInteger.Parse("148896287039501678969147386479458178246000691707699594019852371996225136011987881033904404601666619814302065310828663028471342954821076961960815187788626496609581811628527023262215778397482476920164511192915070597893567835708908996890192512834283979142025668876250608381744928577381330716218105191496818716653");
BigInteger q = BigInteger.Parse("119975764355551220778509708561576785383941026741388506773912560292606151764383332427604710071170171329268379604135341015979284377183953677973647259809025842247294479469402755370769383988530082830904396657573472653613365794770434467132057189606171325505138499276437937752474437953713231209677228298628994462467");
BigInteger e = new BigInteger(17);
RSAParameters RsaParams = CalculateRsaParameters(p, q, e);
var Rsa = new RSACryptoServiceProvider();
Rsa.ImportParameters(RsaParams);
}
}

Related

How to optimize this code for speed, in F# and also why is a part executed twice?

The code is used to pack historical financial data in 16 bytes:
type PackedCandle =
struct
val H: single
val L: single
val C: single
val V: int
end
new(h: single, l: single, c: single, v: int) = { H = h; L = l; C = c; V = v }
member this.ToByteArray =
let a = Array.create 16 (byte 0)
let h = BitConverter.GetBytes(this.H)
let l = BitConverter.GetBytes(this.L)
let c = BitConverter.GetBytes(this.C)
let v = BitConverter.GetBytes(this.V)
a.[00] <- h.[0]; a.[01] <- h.[1]; a.[02] <- h.[2]; a.[03] <- h.[3]
a.[04] <- l.[0]; a.[05] <- l.[1]; a.[06] <- l.[2]; a.[07] <- l.[3]
a.[08] <- c.[0]; a.[09] <- c.[1]; a.[10] <- c.[2]; a.[11] <- c.[3]
a.[12] <- v.[0]; a.[13] <- v.[1]; a.[14] <- v.[2]; a.[15] <- v.[3]
printfn "!!" <- for the second part of the question
a
Arrays of these are sent across the network, so I need the data to be as small as possible, but since this is tracking about 80 tradable instruments at the same time, performance matters as well.
A tradeoff was made where clients are not getting historical data and then updates, but just getting chunks of the last 3 days minute by minute, resulting in the same data being sent over and over to simplify the client logic.. and I inherit the problem of making the inefficient design.. as efficient as possible. This is also done over rest polling which I'm converting to sockets right now to keep everything binary.
So my first question is:
how can I make this faster? in C where you can cast anything into anything, I can just take a float and write it straight into the array so there is nothing faster, but in F# it looks like I need to jump through hoops, getting the bytes and then copying them one by one instead of 4 by 4, etc. Is there a better way?
My second question is that since this was to be evaluated once, I made ToByteArray a property. I'm doing some test with random values in Jupyter Notebook but then I see that:
the property seems to be executed twice (indicated by the two "!!" lines). Why is that?
Assuming you have array to write to (generally you should use buffer for reading & writing when working with sockets), you can use System.Runtime.CompilerServices.Unsafe.As<TFrom, TTo> to cast memory from one type to another (same thing that you can do with C/C++)
type PackedCandle =
// omitting fields & consructor
override c.ToString() = $"%f{c.H} %f{c.L} %f{c.C} %d{c.V}" // debug purpose
static member ReadFrom(array: byte[], offset) =
// get managed(!) pointer
// cast pointer to another type
// same as *(PackedCandle*)(&array[offset]) but safe from GC
Unsafe.As<byte, PackedCandle> &array.[offset]
member c.WriteTo(array: byte[], offset: int) =
Unsafe.As<byte, PackedCandle> &array.[offset] <- c
Usage
let byteArray = Array.zeroCreate<byte> 100 // assume array come from different function
// writing
let mutable offset = 0
for i = 0 to 5 do
let candle = PackedCandle(float32 i, float32 i, float32 i, i)
candle.WriteTo(byteArray, offset)
offset <- offset + Unsafe.SizeOf<PackedCandle>() // "increment pointer"
// reading
let mutable offset = 0
for i = 0 to 5 do
let candle = PackedCandle.ReadFrom(byteArray, offset)
printfn "%O" candle
offset <- offset + Unsafe.SizeOf<PackedCandle>()
But do you really want to mess with pointers (even managed)? Have measured that this code is bottleneck?
Update
It's better to use MemoryMarshal instead of raw Unsafe because first checks out-of-range and enforces usage of unmanaged (see here or here) types at runtime
member c.WriteTo (array: byte[], offset: int) =
MemoryMarshal.Write(array.AsSpan(offset), &Unsafe.AsRef(&c))
static member ReadFrom (array: byte[], offset: int) =
MemoryMarshal.Read<PackedCandle>(ReadOnlySpan(array).Slice(offset))
My first question would be, why do you need the ToByteArray operation? In the comments, you say that you are sending arrays of these values over network, so I assume you plan to convert the data to a byte array so that you can write it to network stream.
I think it would be more efficient (and easier) to instead have a method that takes a StreamWriter and writes the data to the stream directly:
type PackedCandle =
struct
val H: single
val L: single
val C: single
val V: int
end
new(h: single, l: single, c: single, v: int) = { H = h; L = l; C = c; V = v }
member this.WriteTo(sw:StreamWriter) =
sw.Write(this.H)
sw.Write(this.L)
sw.Write(this.C)
sw.Write(this.V)
If you now have some code for the network communication, that will expose a stream and you'll need to write to that stream. Assuming this is stream, you can do just:
use writer = new StreamWriter(stream)
for a in packedCandles do a.WriteTo(writer)
Regarding your second question, I think this cannot be answered without a more complete code sample.

Is write_image atomic? Is it better to use atomic_max?

Full disclosure: I am cross-posting from the kronos opencl forums, since I have not received any reply there so far:
https://community.khronos.org/t/is-write-image-atomic-is-it-better-than-atomic-max/106418
I’m writing a connected components labelling algorithm for images (2d and 3d); I found no existing implementations and decided to write one based on pointer jumping and a “recollection step” (btw: if you are aware of an easy-to-use, production ready connected component labelling let me know).
The “recollection” step kernel pseudocode for 2d images is as follows:
1) global_id = (x,y)
2) read v from img[x,y], decode it to a pair (tx,ty)
3) read v1 from img[tx,ty]
4) do some calculations to extract a boolean value C and a target value T from v1, v, and the neighbours of (x,y) and (tx,ty)
5) *** IF ( C ) THEN WRITE T INTO (tx,ty).
Q1: all the kernels where “C” is true will compete for writing. Suppose it does not matter which one wins (writes last). I’ve done some tests on an intel GPU, and (with filtering disabled, and clamping enabled) there seems to be no issue at all, write_image seems to be atomic, there is a winning value and my algorithm converges very fast. Can I safely assume that write_image on “unfiltered” images is atomic?
Q2: What I really need is to write into (tx,ty) the maximum T obtained from each kernel. That would involve using buffers instead of images, do clamping myself (or use a larger buffer padded with zeroes), and ** using atomic_max in each kernel**. I did not do this yet out of laziness since I need to change my code to use a buffer just to test it, but I believe it would be far slower. Am I right?
For completeness, here is my actual kernel (to be optimized, any suggestions welcome!)
```
__kernel void color_components2(/* base image */ __read_only image2d_t image,
/* uint32 */ __read_only image2d_t inputImage1,
__write_only image2d_t outImage1) {
int2 gid = (int2)(get_global_id(0), get_global_id(1));
int x = gid.x;
int y = gid.y;
int lock = 0;
int2 size = get_image_dim(inputImage1);
const sampler_t sampler =
CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP | CLK_FILTER_NEAREST;
uint4 base = read_imageui(image, sampler, gid);
uint4 ui4a = read_imageui(inputImage1, sampler, gid);
int2 t = (int2)(ui4a[0] % size.x, ui4a[0] / size.x);
unsigned int m = ui4a[0];
unsigned int n = ui4a[0];
if (base[0] > 0) {
for (int a = -1; a <= 1; a++)
for (int b = -1; b <= 1; b++) {
uint4 tmpa =
read_imageui(inputImage1, sampler, (int2)(t.x + a, t.y + b));
m = max(tmpa[0], m);
uint4 tmpb = read_imageui(inputImage1, sampler, (int2)(x + a, y + b));
n = max(tmpb[0], n);
}
}
if(n > m) write_imageui(outImage1,t,(uint4)(n,0,0,0));
}
```

How can one find a plaintext, given n, e, and ciphertext (using RSA)?

I've looked into the RSA algorithms but it doesn't seem to be possible? I've only seen one other post like this and there were no answers provided.
Though this may not be correct or it is just taking a very long time (likely from a huge n), I found this (using Java for its BigInteger);
Given: n = big number, e = 3, c = big number (ciphertext)
Find: m (plaintext)
We know m = (c^d)mod(n) and ed mod(phi) = 1, so we can derive the following (using BigInteger notation):
First of all, we know that Euler made the Totient Function, so by implementing the code from HotJar, we will be able to make this:
BigInteger m = c.modPow(e.modInverse(phi(n)), n); //This is in BigInteger Notation
From HotJar, but changed by me to fit the data-typing:
public static BigInteger gcd(BigInteger a, BigInteger b)
{
if (a.equals(new BigInteger("0")))
return b;
return gcd(b.mod(a), a);
}
// A simple method to evaluate
// Euler Totient Function
public static BigInteger phi(BigInteger n)
{
BigInteger result = new BigInteger("1");
for(BigInteger i = new BigInteger("2"); i.compareTo(n) == (-1); i = i.add(new BigInteger("1")))
if(gcd(i, n).equals(new BigInteger("1")))
result = result.add(new BigInteger("1"));
return result;
}
Since e is the encryption key, the short answer, you cannot break RSA if there is no weakness on the parameters.
Here an example for some attack that might interest you;
If the message space is small, and there is no padding, you can perform searching by encrypting all possible plaintext and comparing them with the ciphertext.
here a more complete list;

Is there a linspace() like method in Math.Net

Is there function in Math.Net like (MatLab/Octave/numpy)'s linspace() which takes 3 parameters (min, max, length) and creates an vector/array of evenly spaced values between min and max? It is not hard to implement but if there was a function already I would prefer to use that.
There is none exactly like linspace, but the signal generator comes quite close and creates an array:
SignalGenerator.EquidistantInterval(x => x, min, max, len)
I'm not fresh on the VB.net syntax, but I guess it's very close to C#.
In case you need a vector:
new DenseVector(SignalGenerator.EquidistantInterval(x => x, min, max, len))
Or you could implement it e.g. using the static Create function (in practice you may want to precompute the step):
DenseVector.Create(len, i => min + i*(max-min)/(len - 1.0))
Update 2013-12-14:
Since v3.0.0-alpha7 this is covered by two new functions:
Generate.LinearSpaced(length, a, b) -> MATLAB linspace(a, b, length)
Generate.LinearRange(a, [step], b) -> MATLAB a:step:b
I used this C# code to replicate the functionality of linspace (how numpy does it), feel free to use it.
public static float[] linspace(float startval, float endval, int steps)
{
float interval = (endval / MathF.Abs(endval)) * MathF.Abs(endval - startval) / (steps - 1);
return (from val in Enumerable.Range(0,steps)
select startval + (val * interval)).ToArray();
}
Here is the VB Translation I made.
Public Function linspace(startval As Single, endval As Single, Steps As Integer) As Single()
Dim interval As Single = (endval / Math.Abs(endval)) *(Math.Abs(endval - startval)) / (Steps - 1)
Return (From val In Enumerable.Range(0, Steps) Select startval + (val * interval)).ToArray()
End Function
Use examples;
C#
float[] arr = linspace(-4,4,5)
VB
Dim arr as Single() = linspace(-4,4,5)
Result:
-4,-2,0,2,4
I checked the result from the code shown below and MATLAB linspace, it exactly matches. I myself use it for my research work in Monte Carlo implementations.
Below is the code image and the actual code.
static double[] LINSPACE(double StartValue, double EndValue, int numberofpoints)
{
double[] parameterVals = new double[numberofpoints];
double increment = Math.Abs(StartValue - EndValue) / Convert.ToDouble(numberofpoints - 1);
int j = 0; //will keep a track of the numbers
double nextValue = StartValue;
for (int i = 0; i < numberofpoints; i++)
{
parameterVals.SetValue(nextValue, j);
j++;
if (j > numberofpoints)
{
throw new IndexOutOfRangeException();
}
nextValue = nextValue + increment;
}
return parameterVals;
}
Code for creating a linspace function in C#

Optimizing division/exponential calculation

I've inherited a Visual Studio/VB.Net numerical simulation project that has a likely inefficient calculation. Profiling indicates that the function is called a lot (1 million times plus) and spends about 50% of the overall calculation within this function. Here is the problematic portion
Result = (A * (E ^ C)) / (D ^ C * B) (where A-C are local double variables and D & E global double variables)
Result is then compared to a threshold which might have additional improvements as well, but I'll leave them another day
any thoughts or help would be appreciated
Steve
The exponent operator (Math.Pow) isn't very fast, there is no dedicated CPU instruction for calculating it. You mentioned that D and E are global variables. That offers a glimmer of hope to get it faster, if you can isolate their changes. Rewriting the equation using logarithms:
log(r) = log((a x e^c) / (b x d^c))
= log(a x e^c) - log (b x d^c)
= log(a) + log(e^c) - log(b) - log(d^c)
= log(a) + c*log(e) - log(b) - c*log(d)
= log(a) - log(b) + c x (log(e) - log(d))
result = exp(r)
Which provides this function to calculate the result:
Function calculate(ByVal a As Double, ByVal b As Double, ByVal c As Double, ByVal d As Double, ByVal e As Double) As Double
Dim logRes = Math.Log(a) - Math.Log(b) + c * (Math.Log(e) - Math.Log(d))
Return Math.Exp(logRes)
End Function
I timed it with the StopWatch class, it is exactly as fast as your original expression. Not a coincidence of course. You'll get ahead by somehow being able to pre-calculate the Math.Log(e) - Math.Log(d) term.
One easy speed up is that
Result = (A/B) * (E/D)^C
At least you are doing one less exponent.
Depending on what C is, there might be faster ways. Like if C is a small integer.
edit:
adding proof to show this is faster
public static void main(String[] args) {
StopWatch sw = new StopWatch();
float e = 1.123F;
float d = 4.456F;
float c = 453;
sw.start();
int max = 5000;
double result = 0;
for (int a = 1; a < max; a++) {
for (float b = 1; b < max; b++) {
result = (a * (Math.pow(e, c))) / (Math.pow(d, c) * b);
}
}
sw.split();
System.out.println("slow: " + sw.getSplitTime() + " result: " + result);
sw.stop();
sw.reset();
sw.start();
result = 0;
for (int a = 1; a < max; a++) {
for (float b = 1; b < max; b++) {
result = a / b * Math.pow(e/d, c);
}
}
sw.split();
System.out.println("fast: " + sw.getSplitTime() + " result: " + result);
sw.stop();
sw.reset();
}
This is the output
slow: 26062 result: 7.077390271736578E-272
fast: 12661 result: 7.077392136525382E-272
There is some skew in the numbers. I would think that the faster version is more exact (but that's just a feeling since i can't think of exactly why).
Well done for profiling. I would also check that A-C are different on every call. In other words, is it possible the caller is actually calculating the same value over and over again? If so, change it so it caches the answer.
For Math.Floor() function, visit:
http://bitsbyta.blogspot.com/2010/12/math-floor-function-vbnet.html
All functions of math library in vb.net is available at:
http://www.bitsbyta.blogspot.com/