How is division in Magma script done? - ethereum

The code below is a simplified implemation of the complete addition formulas for prime order elliptic curves in Magma script. The code was taken from the paper "Complete addition formulas for prime order elliptic curves" When i run this code in the Magma calculator, I get output XA, YA, and ZA. The acual output is the calculated by dividing XA and YA by ZA. The actual output is correct but i cannot figure out how the division is done in Magma so that i can implement it in another language (MATLAB, VHDL). For example you may get XA=13, YA=10, and ZA=8, Then you get XA/ZA=8, YA/ZA=14. The code may produce an error but just run again to get a valid point. Can someone please explain how this is possible? The Magma calcular can be found here.
ADD := function ( X1 , Y1 , Z1 , X2 , Y2 , Z2 , b3 )
t0 := X1 * X2 ; t1 := Y1 * Y2 ; t2 := Z1 * Z2 ;
t3 := X1 + Y1 ; t4 := X2 + Y2 ; t3 := t3 * t4 ;
t4 := t0 + t1 ; t3 := t3 - t4 ; t4 := Y1 + Z1 ;
X3 := Y2 + Z2 ; t4 := t4 * X3 ; X3 := t1 + t2 ;
t4 := t4 - X3 ; X3 := X1 + Z1 ; Y3 := X2 + Z2 ;
X3 := X3 * Y3 ; Y3 := t0 + t2 ; Y3 := X3 - Y3 ;
X3 := t0 + t0 ; t0 := X3 + t0 ; t2 := b3 * t2 ;
Z3 := t1 + t2 ; t1 := t1 - t2 ; Y3 := b3 * Y3 ;
X3 := t4 * Y3 ; t2 := t3 * t1 ; X3 := t2 - X3 ;
Y3 := Y3 * t0 ; t1 := t1 * Z3 ; Y3 := t1 + Y3 ;
t0 := t0 * t3 ; Z3 := Z3 * t4 ; Z3 := Z3 + t0 ;
return X3 , Y3 , Z3 ;
end function ;
p:=17;
printf"primeP ="; p;
b:=7;
Fp:=GF(p);
E:=EllipticCurve([Fp|0,b]);
b3:=3*b;
P:=Random(E);
Z:=1; Y:=Z*P[2]; X:=Z*P[1];
printf"X1, Y1, Z1 = "; P[1], P[2], Z;
assert E![X,Y,Z] eq P;
printf"====================\n";
Q:=Random(E);
ZZ:=1; YY:= ZZ*Q[2]; XX:=ZZ*Q[1];
printf"X2, Y2, Z2 = "; Q[1], Q[2], ZZ;
printf"====================\n";
XA,YA,ZA:=ADD(X,Y,Z,XX,YY,ZZ,b3);
printf"XA ="; XA;
printf"YA ="; YA;
printf"ZA ="; ZA;
printf"====================\n";
printf"XA/ZA ="; XA/ZA;
printf"YA/ZA ="; YA/ZA;
printf"ZA/ZA ="; ZA/ZA;
if E![XA,YA,ZA] eq (P+Q) then
"ADD work";
end if;
I tried writing down all the divisors and quotients to try and establish a connection.

Related

SQL hierarchical query performance issue

I have the following table 1 which depicts the relationships between each parent node and its immediate child nodes. For example, A->C, B->D, C->E etc.
TABLE 1 :
NAME
TYPE
NODE_NAME
NODE_TYPE
A
X1
C
X2
B
X1
D
X0
C
X2
E
X0
D
X0
NULL
NULL
E
X0
NULL
NULL
TABLE 2 :
NAME
TYPE
NODE_NAME
NODE_TYPE
A
X1
C
X2
A
X1
E
X0
B
X1
D
X0
C
X2
E
X0
I would like to transform table 1 -> table 2 as shown above.
Basically, it list all the child nodes of parent A (for example : A->C, A->E)
How can I optimize my code? It takes forever to run on 7600+ rows due to cycles i believe
Context : Mysql doesn't support NOCYCLE, what are my options?
SELECT
NAME,
TYPE,
CONNECT_BY_ROOT NODE_NAME,
CONNECT_BY_ROOT NODE_TYPE
FROM TABLE_1
CONNECT BY
NODE_NAME = PRIOR NAME
AND NODE_TYPE = PRIOR TYPE
AND PRIOR NODE_NAME <> NAME
AND PRIOR NODE_TYPE <> TYPE
ORDER BY NODE_TYPE)
;
You can use:
WITH RECURSIVE rcte (name, type, node_name, node_type) AS (
SELECT *
FROM TABLE1
WHERE node_name IS NOT NULL
AND node_type IS NOT NULL
UNION ALL
SELECT r.name, r.type, t.node_name, t.node_type
FROM rcte AS r
INNER JOIN TABLE1 t
ON (r.node_name = t.name AND r.node_type = t.type)
WHERE t.node_name IS NOT NULL
AND t.node_type IS NOT NULL
)
SELECT *
FROM rcte;
Which, for the sample data:
CREATE TABLE TABLE1(
NAME VARCHAR(1),
TYPE VARCHAR(2),
NODE_NAME VARCHAR(1) REFERENCES TABLE1(name),
NODE_TYPE VARCHAR(2) REFERENCES TABLE1(type)
);
INSERT INTO TABLE1 (name, type, node_name, node_type)
SELECT 'A', 'X1', 'C', 'X2' UNION ALL
SELECT 'B', 'X1', 'D', 'X0' UNION ALL
SELECT 'C', 'X2', 'E', 'X0' UNION ALL
SELECT 'D', 'X0', NULL, NULL UNION ALL
SELECT 'E', 'X0', NULL, NULL;
Outputs:
name
type
node_name
node_type
A
X1
C
X2
B
X1
D
X0
C
X2
E
X0
A
X1
E
X0
db<>fiddle here

MYSQL Moving Average calculation with precedence unbounded

I have a table with three columns : id, A, B. I would like to populate a column E with the calculations below.
** Cols C and D are non-existent in my table, they are subqueries that i hope to create and put into my query that will help me populate col E. As it seems,C and D is a moving average but there is not much examples around that can help with that.
Table followers
id A B C D E
_ _ _ _ _ _
0 1 2 A0/(AVG(A0)) #1/1 B0/(AVG(B0)) (C0+D0)/2
1 2 2 A1/(AVG(A1,A0)) #2/((2+1)/2) B1/(AVG(B1,B0)) (C1+D1)/2
2 3 2 A2/(AVG(A1,A2,A0)) #3/((3+2+1)/3) B2/(AVG(B1,B2,B0)) (C2+D2)/2
How can i write a query for this? I believe i will need a left outer join to itself.
I was thinking set the calculations for column C as one variable, calculations for column D as another variable.
So for column C this is my approach:
update followers f left outer join
followers f2...
Not sure how to continue as i dont know how i can do
f.id=f2.id where f2.id between f.id and f2.id+1.
I got some help to use this query but it didnt work:
UPDATE
f,
(
SELECT AVG(f.A)
FROM (
SELECT f.A
FROM f
WHERE f.id <= f.id
) as t
) as temp,
(
SELECT AVG(f.B)
FROM (
SELECT f.B
FROM f
WHERE f.id <= f.id
) as t2
) as temp2
SET
f.C =((f.A/temp) + (f.B/temp2))/2;
I would use subqueries for this
SELECT id, A, B, C, D, (C+D)/2 E FROM (
SELECT id, A, B,
(A/(SELECT AVG(A) FROM table t2 WHERE t2.id <= t1.id)) C,
(B/(SELECT AVG(B) FROM table t2 WHERE t2.id <= t1.id)) D
FROM table t1 ) t3
This query assumes that AVG(A) and AVG(B) are always > 0. If that's not true you'll need to use CASE so you don't end up dividing by 0.
Another version using JOIN, probably faster than using subqueries
SELECT t3.id, t3.A, t3.B,
(t3.A/t4.AVG_A) C, (t3.B/t4.AVG_B) D,
((t3.A/t4.AVG_A) + (t3.B/t4.AVG_B))/2 E
FROM table t3
JOIN (SELECT t1.id, AVG(t2.A) AVG_A, AVG(t2.B) AVG_B
FROM table t1
JOIN table t2 ON t2.id <= t1.id
GROUP BY t1.id) t4 ON t3.id = t4.id
I would approach this using variables.
select t.id, t.A, t.B,
(case when (#n := #n + 1) is null then null
when (#c := #c + a) is null then null
else t.A / (#c / #n)
end) as C,
(case when (#d := #d + b) is null then null
else t.B / (#d / #n)
end) as D,
(t.A / (#c / #n)) + (t.B / (#d / #n)) as E
from table t cross join
(select #c := 0, #d := 0, #n := 1) vars
order by id;
You can put this in an update statement using a join.
update table t join
(select t.id, t.A, t.B,
(case when (#n := #n + 1) is null then null
when (#c := #c + a) is null then null
else t.A / (#c / #n)
end) as C,
(case when (#d := #d + b) is null then null
else t.B / (#d / #n)
end) as D,
(t.A / (#c / #n)) + (t.B / (#d / #n)) as E
from table t cross join
(select #c := 0, #d := 0, #e := 0, #n := 1) vars
order by id
) newvals
on t.id = newvals.id
set t.C = newvals.C,
t.D = newvals.D,
t.E = newvals.E;

MySQL: how to sort rows by a field and assign another field a counter?

Imagine there's a table with the following contents:
x y z
aa 5 null
bb 2 null
cc 5 null
dd 1 null
I want to sort the rows by y and assign an auto-incremented field to z, so in this case the end result (the changed table) would be
x y z
dd 1 1
bb 2 2
aa 5 3
cc 5 4
or
x y z
aa 5 3
bb 2 2
cc 5 4
dd 1 1
How do I do that?
So to make it clear, I want to change the table, not get that stuff to code.
As requested, http://sqlfiddle.com/#!2/cd610/1
update your_table t1
inner join
(
select id, #rank := #rank + 1 as r
from your_table, (select #rank := 0) r
order by y
) t2 on t2.y = t.y
set z = r
SQLFiddle demo
This is what I might call the "painful" solution. It uses a subquery to calculate the rank for each row:
update t
set z = (select count(*) as cnt
from (select t.* from t) t2
where t2.y < t.y or t2.y = t.y and t2.x <= t.x
)
Note that MySQL generates an error when you use the target table in a subquery in update and delete. There is a way around this. Just embed the table in a subquery.
You can also do this using a variable with a join:
update t join
(select t.*, (#rank := #rank + 1) as seqnum
from t cross join (select #rank := 0) const
order by y
) t2
on t.x = t2.x
set t.z = t2.seqnum;
The subquery calculates the sequence number with the order by. The outer update then assigns the value to the appropriate row. This assumes that x uniquely identifies each row.

Calculating an Equation from a MySql Query

How can i select as result of an equation like this ( decimalnumber_1 / (100+decimalnumber_2) * 100 ) with a mysql query
decimalnumber_1 = //SELECT table_1.a_decimalnumber_1 AS decimalnumber_1 FROM table_1 WHERE table_1.another_coloumn_name = z
decimalnumber_2 = //SELECT table_2.a_decimalnumber_2 AS decimalnumber_2 FROM table_2 WHERE table_2.an_another_coloumn_name = x
result = //SELECT ( decimalnumber_1 / (100+decimalnumber_2) * 100 ) AS result
CREATE PROCEDURE #eqresult
#result int output
AS
DECLARE #decNum1 int,#decNum2 int
SET #decNum1=(SELECT table_1.a_decimalnumber_1 AS decimalnumber_1 FROM table_1
WHERE table_1.another_coloumn_name = z)
SET #decNum1=(SELECT table_2.a_decimalnumber_2 AS decimalnumber_2 FROM table_2
WHERE table_2.another_coloumn_name = x)
SET #result=( #decNum1 / (100+#decNum2) * 100 )
RETURN #result
Try
SELECT ( (SELECT table_1.a_decimalnumber_1 AS decimalnumber_1 FROM table_1 WHERE table_1.another_coloumn_name = z
)/ (100+(SELECT table_2.a_decimalnumber_2 AS decimalnumber_2 FROM table_2 WHERE table_2.an_another_coloumn_name = x
)) * 100 ) AS result

Implementation of NORMSINV function in MySQL

I need to use the inverse normal cumulative distribution function (what in Excel is NORMSINV function) in MySQL, but there is no such function there. Maybe any of you has an implementation of it for MySQL?
Many thanks for your time.
Well, I've finally found this. It's not perfect but a quite good aproximation. The code isn't mine, its author is Geoffrey C. Barnes. I've just transformed it from VB.NET to MySQL.
DROP FUNCTION IF EXISTS NORMSINV;
DELIMITER //
CREATE FUNCTION NORMSINV (p DOUBLE) RETURNS DOUBLE
BEGIN
DECLARE q, r DOUBLE;
DECLARE A1, A2, A3, A4, A5, A6 DOUBLE;
DECLARE B1, B2, B3, B4, B5 DOUBLE;
DECLARE C1, C2, C3, C4, C5, C6 DOUBLE;
DECLARE D1, D2, D3, D4 DOUBLE;
DECLARE P_LOW, P_HIGH DOUBLE;
/* coefficients in rational approximations */
SET A1 = -39.696830286653757;
SET A2 = 220.9460984245205;
SET A3 = -275.92851044696869;
SET A4 = 138.357751867269;
SET A5 = -30.66479806614716;
SET A6 = 2.5066282774592392;
SET B1 = -54.476098798224058;
SET B2 = 161.58583685804089;
SET B3 = -155.69897985988661;
SET B4 = 66.80131188771972;
SET B5 = -13.280681552885721;
SET C1 = -0.0077848940024302926;
SET C2 = -0.32239645804113648;
SET C3 = -2.4007582771618381;
SET C4 = -2.5497325393437338;
SET C5 = 4.3746641414649678;
SET C6 = 2.9381639826987831;
SET D1 = 0.0077846957090414622;
SET D2 = 0.32246712907003983;
SET D3 = 2.445134137142996;
SET D4 = 3.7544086619074162;
/* define break points */
SET P_LOW = 0.02425;
SET P_HIGH = 1 - P_LOW;
IF (p > 0 AND p < P_LOW) THEN
/* rational approximation for lower region */
SET q = SQRT(-2 * LOG(p));
RETURN (((((C1 * q + C2) * q + C3) * q + C4) * q + C5) * q + C6) /
((((D1 * q + D2) * q + D3) * q + D4) * q + 1);
ELSEIF (p >= P_LOW AND p <= P_HIGH) THEN
/* rational approximation for central region */
SET q = p - 0.5;
SET r = q * q;
RETURN (((((A1 * r + A2) * r + A3) * r + A4) * r + A5) * r + A6) * q /
(((((B1 * r + B2) * r + B3) * r + B4) * r + B5) * r + 1);
ELSEIF (p > P_HIGH AND p < 1) THEN
/* rational approximation for upper region */
SET q = SQRT(-2 * LOG(1 - p));
RETURN -(((((C1 * q + C2) * q + C3) * q + C4) * q + C5) * q + C6) /
((((D1 * q + D2) * q + D3) * q + D4) * q + 1);
/* on error returning 0 */
ELSE
RETURN 0;
END IF;
END//
DELIMITER ;
Below is an equivalence of Excel's NORMINV function.
CREATE FUNCTION NORMINV(p double, mu double, sigma double)
RETURNS decimal(20,6)
begin
declare q double;
declare r double;
declare val double;
BEGIN
IF p < 0 OR p > 1 THEN
signal sqlstate '20100' set message_text= 'The probality p must be bigger than 0 and smaller than 1';
END IF;
IF sigma < 0 THEN
signal sqlstate '20100' set message_text= 'The standard deviation sigma must be positive';
END IF;
IF p = 0 THEN
RETURN to_binary_double('-INF');
END IF;
IF p = 1 THEN
RETURN to_binary_double('INF');
END IF;
IF sigma = 0 THEN
RETURN mu;
END IF;
set q:= p - 0.5;
IF(ABS(q) <= .425) THEN
set r:= .180625 - q * q;
set val :=
q * (((((((r * 2509.0809287301226727 +
33430.575583588128105) * r + 67265.770927008700853) * r +
45921.953931549871457) * r + 13731.693765509461125) * r +
1971.5909503065514427) * r + 133.14166789178437745) * r +
3.387132872796366608)
/ (((((((r * 5226.495278852854561 +
28729.085735721942674) * r + 39307.89580009271061) * r +
21213.794301586595867) * r + 5394.1960214247511077) * r +
687.1870074920579083) * r + 42.313330701600911252) * r + 1);
ELSE
/* r = min(p, 1-p) < 0.075 */
IF q > 0 THEN
set r:= 1 - p;
ELSE
set r:= p;
END IF;
set r:= SQRT(-LN(r));
/* r = sqrt(-log(r)) <==> min(p, 1-p) = exp( - r^2 ) */
IF (r <= 5) THEN
set r:= r - 1.6;
set val := (((((((r * 7.7454501427834140764e-4 +
.0227238449892691845833) * r + .24178072517745061177) *
r + 1.27045825245236838258) * r +
3.64784832476320460504) * r + 5.7694972214606914055) *
r + 4.6303378461565452959) * r +
1.42343711074968357734)
/ (((((((r *
1.05075007164441684324e-9 + 5.475938084995344946e-4) *
r + .0151986665636164571966) * r +
.14810397642748007459) * r + .68976733498510000455) *
r + 1.6763848301838038494) * r +
2.05319162663775882187) * r + 1);
ELSE /* very close to 0 or 1 */
set r := r - 5;
set val := (((((((r * 2.01033439929228813265e-7 +
2.71155556874348757815e-5) * r +
.0012426609473880784386) * r + .026532189526576123093) *
r + .29656057182850489123) * r +
1.7848265399172913358) * r + 5.4637849111641143699) *
r + 6.6579046435011037772)
/ (((((((r *
2.04426310338993978564e-15 + 1.4215117583164458887e-7) *
r + 1.8463183175100546818e-5) * r +
7.868691311456132591e-4) * r + .0148753612908506148525)
* r + .13692988092273580531) * r +
.59983220655588793769) * r + 1);
END IF;
IF q < 0.0 THEN
set val := -val;
END IF;
END IF;
RETURN mu + sigma * val;
END;
END
It has been adapted from [https://forums.mysql.com/read.php?98,411441,411458#msg-411458] which is Oracle equivalence.
Have used it, so far so good.
Hope it assists someone.