I'm implementing RSA encryption and need to generate random 1024-bit primes.
I can't use INTEGER signals because of the limit, and so I'm using STD_LOGIC_VECTOR and convert it to UNSIGNED when I need to perform arithmetic operations.
I began by using UNIFORM to generate 32 random 32-bit numbers which I then copy over into a 1024-bit STD_LOGIC_VECTOR.
I then set the most significant and least significant bits to '1' to ensure it is 1024-bits and odd.
I then check for primality using an implementation of the Miller Rabin algorithm, which is where my problem lies.
This is where I generate the random primes:
function GEN_1024_PRIME return STD_LOGIC_VECTOR is
VARIABLE s1, s2 : POSITIVE;
VARIABLE random : REAL;
VARIABLE small_random : STD_LOGIC_VECTOR (31 downto 0);
VARIABLE large_random : STD_LOGIC_VECTOR (1023 downto 0);
VARIABLE prime : STD_LOGIC := '0';
begin
while prime /= '1' loop
for I in 0 to 31 loop
UNIFORM(s1, s2, random);
small_random := STD_LOGIC_VECTOR(to_unsigned(INTEGER(TRUNC(random * REAL(2147483647))), 32));
large_random (I*32 + 31 downto I*32) := small_random;
end loop;
large_random(0) := '1';
large_random(1023) := '1';
prime := MILLER_RABIN (large_random);
end loop;
return large_random;
end function;
And my implementation of Miller Rabin:
function MILLER_RABIN (prime : STD_LOGIC_VECTOR (1023 downto 0)) return STD_LOGIC is
VARIABLE t : INTEGER := 4;
VARIABLE temp, r, a, x, j, n: UNSIGNED (1023 downto 0);
VARIABLE small_random : UNSIGNED (31 downto 0);
VARIABLE large_random : UNSIGNED (1023 downto 0);
VARIABLE s1, s2 : POSITIVE;
VARIABLE random : REAL;
begin
n := UNSIGNED(prime);
if n MOD 2 = 0 OR n MOD 3 = 0 then
return '0';
else
-- calculate n - 1 = 2^s * r such that r is odd
r := n - 1;
while r MOD 2 = 0 loop
r := r / 2;
end loop;
for I in 1 to t loop
-- choose random a, 2 <= a <= n-2
for I in 0 to 31 loop
UNIFORM(s1, s2, random);
small_random := to_unsigned(INTEGER(TRUNC(random * REAL(2147483647))), 32);
large_random (I*32 + 31 downto I*32) := small_random;
end loop;
a := large_random;
temp := r;
x := MOD_3(a, temp, n);
while (temp /= (n - 1) AND x /= 1 AND x /= (n - 1)) loop
x := (x * x) MOD n;
temp := temp * 2;
end loop;
if x /= (n - 1) AND temp MOD 2 = 0 then
return '0';
end if;
end loop;
return '1';
end if;
end function;
function MOD_3 (a, b, c : UNSIGNED (1023 downto 0)) return UNSIGNED is
VARIABLE x : UNSIGNED (1023 downto 0) := TO_UNSIGNED(1, 1024);
VARIABLE y : UNSIGNED (1023 downto 0) := a;
VARIABLE b_temp : UNSIGNED (1023 downto 0) := b;
begin
while b_temp > 0 loop
if b_temp MOD 2 = 1 then
x := (x * y) MOD c;
end if;
y := (y * y) MOD c;
b_temp := b_temp / 2;
end loop;
return x MOD c;
end function;
I convert the input to UNSIGNED in order to perform arithmetic operations, which seemed like it would work until I realized there will be instances in which the product of 2 values will be larger than 1024 bits. For example, in this while loop:
while (temp /= (n - 1) AND x /= 1 AND x /= (n - 1)) loop
x := (x * x) MOD n;
temp := temp * 2;
end loop;
The resultant of temp := temp * 2; is 2048 bits.
I feel like I could get this to work by messing around with the sizes of my UNSIGNED variables, but I think it is getting messier than it needs to be, so I'm wondering if I am approaching this the wrong way? Is there a simpler way to generate 1024-bit primes? Is there another primality test that would be better suited for my problem?
Related
I'M TRYIN TO CREATE A PROGRAM USING MAPLE FOR GAUSSING ELIMINATION BUT I KEEP GETTING THIS ERROR
Gauss := proc (n::posint, A::matrix, c::Vector)
local a, i, k, j, p;
with(MTM):
n := linalg[rowdim](A);
if det(A) = 0 then print('matrice*doit*etre*caree')
else if det(A) <> 0
then a := `<|>`(A, c);
for k to n-1 do
for i from k+1 to n do
if a[i, i] = 0 then swaprow(a, k, i)
else p = a[i, k]/a[k, k];
for j from k+1 to n+1 do a[i, j] = a[i, j]-p*a[k, j]
end do;
end if;
end do;
end do;
else print('rien')
end if; end if; end proc;
Error, (in Gauss) illegal use of a formal parameter
restart;
Gauss := proc(A::Matrix, c::Vector)
local a, i, k, j, m, n, p;
n := linalg[rowdim](A);
m := linalg[coldim](A);
if m <> n then
print("matrice doit etre caree");
else
a := `<|>`(A, c);
for k to n-1 do
for i from k+1 to n do
if a[i, i] = 0 then
a := linalg[swaprow](a, k, i);
else
p := a[i, k]/a[k, k];
for j from k to n+1 do
a[i, j] := a[i, j]-p*a[k, j];
end do;
end if;
end do;
end do;
end if;
return a;
end proc:
c := Vector([2, 3, 4]);
A := Matrix(3, 3, [4, 1, 2, 3, 6, 5, 2, 1, 9]);
Gauss(A, c);
LinearAlgebra:-LUDecomposition(<A|c>, output=U);
There were quite a few mistakes, so let's hope I get most of them.
I didn't bother doing 7. You should do it.
You cannot use with inside a procedure.
Your code uses commands from thelinalg
package, not the MTM package.
Ideally you'd use Matrix&Vector&LinearAlgebra
(instead of your mix of matrix&Vector&linalg(.
Your procedure has n as one of its
parameters, but inside it you also try to
assign a value to n, the argument for which
you passed in as the number 3. That's where
your error message is coming from. You can't
do that.
Several of you lines have just = instead of
:= for assignments. The = does nothing.
The test against det(A)=0 is wrong is wrong
in several ways. I'll just say that it doesn't
actually test whether the A is square.
Compare the row & column dimensions if you
want to test that A is square.
You should be using LinearAlgebra
equivalents instead of the linalg commands
commands swaprow, coldim.
You forgot to have your procedure actually
return the Matrix a.
When your code calls swaprow is was not
actually updating a. It was just throwing
way the result.
It's a sin to not indent your code. It will
lead you to overlook mistakes.
How is it going guys ?
I've written a program that "draws" diamond in the command line (it's a part of my homework). For spaces inside the diamond I was given a formula "1 + 2(k-2) or 2k -3 , where k is line number", but I don't understand how this formula was created. Could anyone explain it ?
program diamond;
var
n, k, h, i: integer;
begin
repeat
write('Enter the diamond''s height (positive odd): ');
readln(h);
until (h > 0) and (h mod 2 = 1);
n := h div 2;
for k := 1 to n + 1 do
begin
for i := 1 to n + 1 - k do
write(' ');
write('*');
if k > 1 then
begin
for i := 1 to 2*k - 3 do
write(' ');
write('*')
end;
writeln
end;
for k := n downto 1 do
begin
for i := 1 to n + 1 - k do
write(' ');
write('*');
if k > 1 then
begin
for i := 1 to 2*k - 3 do
write(' ');
write('*')
end;
writeln
end
end.
I've already figured it out. It's a simple, but modified arithmetic progression An=A1-d(n-2). Usually we would use (n-1), but because we need to substract 2 stars from each line (starting from the second one, as this formula works for k>1), we use (n-2)
Please help me to convert this PL/SQL into PostgreSQL. Thank you very much.
Prime Numbers
CREATE TABLE n (n NUMBER);<br/>
CREATE OR REPLACE PROCEDURE prime_number (n NUMBER)<br/>
IS <br/>
prime_count NUMBER := 0;<br/>
y VARCHAR2 (1) := 'N';<br/>
BEGIN<br/>
IF n >= 1
THEN
prime_count := 1;
INSERT INTO n
VALUES (2);
END IF;
IF n >= 2
THEN
prime_count := 2;
INSERT INTO n
VALUES (2);
END IF;
IF n >= 3
THEN
FOR i IN 4 .. n * n * n
LOOP
y := 'N';
FOR j IN 2 .. CEIL (SQRT (i))
LOOP
IF (MOD (i, j) = 0)
THEN
y := 'Y';
EXIT;
END IF;
END LOOP;
IF (y = 'N')
THEN
INSERT INTO n
VALUES (i);
COMMIT;
prime_count := prime_count + 1;
EXIT WHEN prime_count = n;
END IF;
END LOOP;
END IF;<br/>
END;
BEGIN<br/>
prime_number (1000000);<br/>
END;
(note: not the same as this other question since the OP never explicitly specified rounding towards 0 or -Infinity)
JLS 15.17.2 says that integer division rounds towards zero. If I want floor()-like behavior for positive divisors (I don't care about the behavior for negative divisors), what's the simplest way to achieve this that is numerically correct for all inputs?
int ifloor(int n, int d)
{
/* returns q such that n = d*q + r where 0 <= r < d
* for all integer n, d where d > 0
*
* d = 0 should have the same behavior as `n/d`
*
* nice-to-have behaviors for d < 0:
* option (a). same as above:
* returns q such that n = d*q + r where 0 <= r < -d
* option (b). rounds towards +infinity:
* returns q such that n = d*q + r where d < r <= 0
*/
}
long lfloor(long n, long d)
{
/* same behavior as ifloor, except for long integers */
}
(update: I want to have a solution both for int and long arithmetic.)
If you can use third-party libraries, Guava has this: IntMath.divide(int, int, RoundingMode.FLOOR) and LongMath.divide(int, int, RoundingMode.FLOOR). (Disclosure: I contribute to Guava.)
If you don't want to use a third-party library for this, you can still look at the implementation.
(I'm doing everything for longs since the answer for ints is the same, just substitute int for every long and Integer for every Long.)
You could just Math.floor a double division result, otherwise...
Original answer:
return n/d - ( ( n % d != 0 ) && ( (n<0) ^ (d<0) ) ? 1 : 0 );
Optimized answer:
public static long lfloordiv( long n, long d ) {
long q = n/d;
if( q*d == n ) return q;
return q - ((n^d) >>> (Long.SIZE-1));
}
(For completeness, using a BigDecimal with a ROUND_FLOOR rounding mode is also an option.)
New edit: Now I'm just trying to see how far it can be optimized for fun. Using Mark's answer the best I have so far is:
public static long lfloordiv2( long n, long d ){
if( d >= 0 ){
n = -n;
d = -d;
}
long tweak = (n >>> (Long.SIZE-1) ) - 1;
return (n + tweak) / d + tweak;
}
(Uses cheaper operations than the above, but slightly longer bytecode (29 vs. 26)).
There's a rather neat formula for this that works when n < 0 and d > 0: take the bitwise complement of n, do the division, and then take the bitwise complement of the result.
int ifloordiv(int n, int d)
{
if (n >= 0)
return n / d;
else
return ~(~n / d);
}
For the remainder, a similar construction works (compatible with ifloordiv in the sense that the usual invariant ifloordiv(n, d) * d + ifloormod(n, d) == n is satisfied) giving a result that's always in the range [0, d).
int ifloormod(int n, int d)
{
if (n >= 0)
return n % d;
else
return d + ~(~n % d);
}
For negative divisors, the formulas aren't quite so neat. Here are expanded versions of ifloordiv and ifloormod that follow your 'nice-to-have' behavior option (b) for negative divisors.
int ifloordiv(int n, int d)
{
if (d >= 0)
return n >= 0 ? n / d : ~(~n / d);
else
return n <= 0 ? n / d : (n - 1) / d - 1;
}
int ifloormod(int n, int d)
{
if (d >= 0)
return n >= 0 ? n % d : d + ~(~n % d);
else
return n <= 0 ? n % d : d + 1 + (n - 1) % d;
}
For d < 0, there's an unavoidable problem case when d == -1 and n is Integer.MIN_VALUE, since then the mathematical result overflows the type. In that case, the formula above returns the wrapped result, just as the usual Java division does. As far as I'm aware, this is the only corner case where we silently get 'wrong' results.
return BigDecimal.valueOf(n).divide(BigDecimal.valueOf(d), RoundingMode.FLOOR).longValue();
I am searching for a macro, constant or attribute, whatever it is, replaces "(x downto y)". To explain in detail for example complex numbers,
there is a generic value WIDTH,
signal num : std_logic_vector(2*WIDTH downto 0);
**pseudo**
re = 2*WIDTH-1 downto WIDTH;
im = WIDTH-1 downto 0;
**pseudo**
x <= num(re);
y <= num(im); etc
also it could be some attribute like range. eg
x <= num(num're);
y <= num(num'im);
I use it a lot and it should be great for better readability and writing clean code
A subtype can be used to declare an integer range like:
-- **pseudo** re = 2*WIDTH-1 downto WIDTH; im = WIDTH-1 downto 0; **pseudo**
subtype re is natural range 2*WIDTH-1 downto WIDTH;
subtype im is natural range WIDTH-1 downto 0;
Then it is possible to do:
x <= num(re);
y <= num(im);
With x and y declared as std_logic_vector(WIDTH-1 downto 0), or std_logic_vector(re) and std_logic_vector(im).
Btw. num should probably have highest index as 2*WIDTH-1, and not 2*WIDTH (off-by-one error).
Maybe not exactly what you had in mind, but a VHDL record would seem to be a good fit for what you are trying to do.
You define your record type:
type mycomplex_t is record
re : std_logic_vector(WIDTH-1 downto 0);
im : std_logic_vector(WIDTH-1 downto 0);
end record;
Then, you declare your signal to be of this type:
signal num : mycomplex_t;
And you use it as such:
x <= num.re;
y <= num.im;
You can also assign it like this :
num <= (re => x2, im => y2);
Or, like this:
num.re <= x2;
num.im <= y2;
Or all at once from another signal of the same type:
signal other_complex : mycomplex_t;
-- (...)
num <= other_complex;