JavaScript how to transform String into a function - javascript

I am doing a calculator for definite integrals, where I can add the function to integrate by using this interface.Calculator interface
The point is that once I call the function to integrate it recognizes it as a String and i cannot calculate over it. But if I add the function hardcoding it, it works perfectly fine.
prueba() {
//**** this.cadena is the function I add by using the interface
var sal = this.cadena;
console.log(sal);
var f = function (x) {
//**** The comented return works perfecly fine
//return 1/x;
return parseFloat(sal);
};
var integrada = this.integ(sal, 1, 2);
this.cadena = integrada;
this.imprime();
}
integ(f, a, b) {
var area = 0;
var dx = 0.001;
for (let x = a; x < b; x += dx) {
area += dx * f(x);
}
return area;
}

Can you try below line
var integrada = this.integ(parseFloat(sal), 1, 2);

Related

Point Doubling (P -> 2P) The Base Point of the Secp256k1 Elliptic Curve

as a learning exercise, I am trying to code the first point doubling (Base point P -> 2P) for the Secp256k1 Elliptic Curve. I am using Javascript, and the ethers package for BigNumber. Frustratingly, I am running into a problem where the result I am getting for 2P doesn't appear to lie on the curve. Can someone please help me determine where I am making a mistake?
The coordinates I'm getting as a result are:
X: 0xf1b9e9c77c87bf0ac622382b581826898cfc9232e025d86d904bfd33375faf1a
Y: 0x8162c7b446b54638e9181b71770b2d718e6953a360625a02392097c7db09c608
Which returns false from my isPointOnCurve() method. As a sanity check, I checked the base point in the isPointOnCurve() method, and that returns true (thankfully).
Please see my code below:
const { ethers, BigNumber } = require('ethers');
//variable initialization found from https://en.bitcoin.it/wiki/Secp256k1
bigZero = BigNumber.from(0);
bigTwo = BigNumber.from(2);
bigThree = BigNumber.from(3);
ellipticCurveB = BigNumber.from(7);
generatorPrime = BigNumber.from("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F");
order = BigNumber.from("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");
baseXCoord = BigNumber.from("0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798");
baseYCoord = BigNumber.from("0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8");
// slope = ( (3*x^2) * (2*y)^-1 ) mod order
// 2Px = slope^2 - 2*baseXCoord
// 2Py = slope * ( 2Px - baseXCoord ) - baseYCoord
m = (bigThree.mul(baseXCoord.pow(bigTwo)).mul(modinv(bigTwo.mul(baseYCoord), order))).mod(order);
TwoPx = (m.pow(bigTwo).sub(bigTwo.mul(baseXCoord))).mod(order);
TwoPy = ((m.mul(baseXCoord.sub(TwoPx))).sub(baseYCoord)).mod(order);
console.log(TwoPx);
console.log(TwoPy);
console.log(isPointOnCurve(TwoPx, TwoPy));
// Helper Functions:
// Check if point is on Curve, Calculate extended GCD, modular inverse
function isPointOnCurve(x,y){
b = ellipticCurveB;
p = generatorPrime;
rem = (y.pow(bigTwo).sub(x.pow(bigThree)).sub(b)).mod(p);
return rem.eq(bigZero);
}
function egcd(a, b) {
var s = BigNumber.from(0), t = BigNumber.from(1), u = BigNumber.from(1), v = BigNumber.from(0);
while (!a.eq(BigNumber.from(0))) {
var q = b.div(a) | BigNumber.from(0), r = b.mod(a);
var m = s.sub(u.mul(q)), n = t.sub(v.mul(q));
b = a;
a = r;
s = u;
t = v;
u = m;
v = n;
}
return [b, s, t];
}
function mod(x, y) {
return (x.mod(y).add(y)).mod(y);
}
function modinv(x, y) {
var tuple = egcd(x.mod(y), y);
if (!tuple[0].eq(BigNumber.from(1))) {
return null;
}
return mod(tuple[1], y);
}
As kelalaka pointed out in a comment on the original post, I was confusing the the order of the group and the finite field Fp. I was getting values modulo the Group Order, when I should've been using the values modulo prime p used to define the finite field.
The new and correct result I get is:
X: 0xc6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5
Y: 0x1ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a
If anyone would like to use this code, I've updated it to be correct, and cleaned it up to make it a little more readable:
bigZero = BigNumber.from(0);
bigTwo = BigNumber.from(2);
bigThree = BigNumber.from(3);
ellipticCurveB = BigNumber.from(7);
generatorPrime = BigNumber.from("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F");
baseXCoord = BigNumber.from("0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798");
baseYCoord = BigNumber.from("0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8");
// slope = ( (3*x^2) * (2*y)^-1 ) mod order
threeXSquared = bigThree.mul(baseXCoord.pow(bigTwo));
modInv2y = modinv(bigTwo.mul(baseYCoord), generatorPrime);
m = threeXSquared.mul(modInv2y).mod(generatorPrime);
// 2Px = slope^2 - 2*baseXCoord
mSquared = m.pow(bigTwo);
twoXbase = bigTwo.mul(baseXCoord);
TwoPx = (mSquared.sub(twoXbase)).mod(generatorPrime);
// 2Py = slope * ( 2Px - baseXCoord ) - baseYCoord
pointSlopeX = m.mul(baseXCoord.sub(TwoPx));
TwoPy = (pointSlopeX).sub(baseYCoord).mod(generatorPrime);
console.log(TwoPx);
console.log(TwoPy);
console.log(isPointOnCurve(TwoPx, TwoPy));
// Helper Functions:
// Check if point is on Curve, Calculate extended GCD, modular inverse
function isPointOnCurve(x,y){
b = ellipticCurveB;
p = generatorPrime;
rem = (y.pow(bigTwo).sub(x.pow(bigThree)).sub(b)).mod(p);
return rem.eq(bigZero);
}
function egcd(a, b) {
var s = BigNumber.from(0), t = BigNumber.from(1), u = BigNumber.from(1), v = BigNumber.from(0);
while (!a.eq(BigNumber.from(0))) {
var q = b.div(a) | BigNumber.from(0), r = b.mod(a);
var m = s.sub(u.mul(q)), n = t.sub(v.mul(q));
b = a;
a = r;
s = u;
t = v;
u = m;
v = n;
}
return [b, s, t];
}
function modulus(x, y) {
return (x.mod(y).add(y)).mod(y);
}
function modinv(x, y) {
var tuple = egcd(x.mod(y), y);
if (!tuple[0].eq(BigNumber.from(1))) {
return null;
}
return modulus(tuple[1], y);
}

Replace a variable in a function with the value in javascript

I am looking for a way to replace a variable in a function with its actual value. I am going to convert this function into a string and send via a HTTP request and thus need to convert the variables inside the function with their values.
let x = Math.random();
let funcString = function () {
let y = x + 10;
return y;
}.toString();
// Send funcString as a parameter
For eg. in the above code if I send funcString as it is, whoever receiving it will have no idea what is the value of x.
Since I am ultimately sending a string I would like to send
"function () {let y = 0.53 + 10; return y;}" (assuming
Math.random() produced 0.53 at runtime).
Is there any way to do this?
I am doing this in a nodejs project so a npm module would be fine by me too.
Well if you are returning this function as a string, just use String#replace() method to replace x occurrence with its value.
This is how you should use it:
funcString.replace('x', x)
Demo:
let x = Math.random();
let funcString = function () {
let y = x + 10;
return y;
}.toString();
console.log(funcString.replace('x', x));
Edit:
If your variable has many occurrences and can be part of other variables just use a regex with replace method.
funcString.replace(/\bx\b/g, x)
Demo:
let x = Math.random();
let funcString = function () {
let y = x + 10;
let fix ='true';
let z = x * 2;
return y;
}.toString();
console.log(funcString.replace(/\bx\b/g, x));
use replace with regex, g will search all x-es
let x = Math.random();
let funcString = function () {
let y = x + 10;
let a = x + 10;
let b = x + 10;
return y;
}.toString().replace(/x/g, x);
console.log(funcString);

QuadEdge dual edge coordinate's always the origin

I am trying to implement, in Javascript, a divide and conquer algorithm to calculate a Delanay triangulation, in order to obtain a Voronoi diagram. The coded is based on the C++ implementation described in Graphic Gems IV which, in turn, is based on the famous Guibas and Stolfi paper from 1985. It uses a Quad-Edge data structure.
The algorithm divides the set of points in half; then, it triangulates those parts separately; lastly it proceeds to "marry" the two halves.
The problem is that, well, it does not work. It gets stuck in a infinite recursion when "marrying" the two halves. I think the problem might be in the Quad-Edge structure itself, because the first edge's and its destination edge have the same coordinates and its dual and inverted rotation edge point to (0, 0).
Here is the code (the translation from C++ is not 100 %, I asked for help since I am still a JS noob):
//The data structure starts here.
var Edge = function (num, qe) {
var _this = this;
this.num = num;
this.qe = qe;
this.coord = new paper.Point();
this.sym = function () {
return (_this.num < 2) ? _this.qe[_this.num + 2] : this.qe[_this.num - 2];
};
this.oNext = function () {
return this.next;
};
this.setNext = function (next) {
this.next = next
};
this.rot = function () {
return (this.num < 3) ? _this.qe[_this.num + 1] : _this.qe[_this.num - 3];
};
this.invRot = function () {
return (_this.num > 0) ? _this.qe[_this.num - 1] : _this.qe[_this.num + 3];
};
this.oPrev = function () {
return _this.rot().oNext().rot();
};
this.dNext = function () {
return _this.sym().next.sym();
};
this.dPrev = function () {
return _this.invRot().oNext().invRot();
};
this.lNext = function () {
return _this.invRot().oNext().rot();
};
this.lPrev = function () {
return _this.oNext().sym();
};
this.rNext = function () {
return _this.rot().oNext().invRot();
};
this.rPrev = function () {
return _this.sym().oNext();
};
this.dest = function () {
return _this.sym().coord;
};
this.endPoints = function (or, de) {
this.coord = or;
this.sym().coord = de;
};
};
//The first edge always points to itself
//as in edge.oNext().coord === edge.coord
var QuadEdge = function () {
this.edges = new Array(4);
for (var i = 0; i < 4; i++) {
this.edges[i] = new Edge(i, this.edges);
}
this.edges[0].setNext(this.edges[0]);
this.edges[1].setNext(this.edges[3]);
this.edges[2].setNext(this.edges[2]);
this.edges[3].setNext(this.edges[1]);
};
//Constructs and returns a new QuadEdge.
function makeEdge() {
var qe = new QuadEdge();
return qe.edges[0];
}
//Helper function, returns twice of the area of the triangle formed
//by a, b and c. Negative if the triangle is clockwise.
function triArea(a, b, c) {
return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);
}
//Tests if the point d is inside the circumcircle of the triangle formed by
//a, b, and c. As described by Guibas and Stolfi in their paper.
function inCircle(a, b, c, d) {
return (Math.pow(a.x, 2) + Math.pow(a.y, 2)) * triArea(b, c, d) -
(Math.pow(b.x, 2) + Math.pow(b.y, 2)) * triArea(a, c, d) +
(Math.pow(c.x, 2) + Math.pow(c.y, 2)) * triArea(a, b, d) -
(Math.pow(d.x, 2) + Math.pow(d.y, 2)) * triArea(a, b, d) > 0;
}
//Tests if triangle is in counterclockwise order.
function cClockwise(a, b, c) {
return triArea(a, b, c) > 0;
}
//Tests if point is left of the provided edge.
function leftOf(point, edge) {
return cClockwise(point, edge.coord, edge.dest());
}
//Tests if point is right of the provided edge.
function rightOf(point, edge) {
return cClockwise(point, edge.dest(), edge.coord);
}
//If a and b are distinct, splice will combine them; if not, it will
//separate them in two.
function splice(a, b) {
var alpha = a.oNext().rot();
var beta = b.oNext().rot();
var t1 = b.oNext();
var t2 = a.oNext();
var t3 = beta.oNext();
var t4 = alpha.oNext();
a.setNext(t1);
b.setNext(t2);
alpha.setNext(t3);
beta.setNext(t4);
}
function deleteEdge(e) {
splice(e, e.oPrev());
splice(e.sym(), e.sym().oPrev());
}
function connect(e1, e2) {
var e = makeEdge();
e.endPoints(e1.dest(), e2.coord);
splice(e, e1.lNext());
splice(e.sym(), e2);
return e;
}
//Fixed thanks to: http://www.rpenalva.com/blog/?p=74
function valid(e, basel) {
return rightOf(e.dest(), basel);
}
//This is the actual algorithm.
function divideAndConquer(vertices) {
if (vertices.length === 2) {
var a = makeEdge();
a.coord = vertices[0];
a.sym().coord = vertices[1];
return {right: a, left: a.sym()};
}
else if (vertices.length === 3) {
var a = makeEdge(), b = makeEdge();
splice(a.sym(), b);
a.coord = vertices[0];
b.coord = vertices[1];
a.sym().coord = b.coord;
b.sym().coord = vertices[2];
if (cClockwise(vertices[0], vertices[1], vertices[2])) {
connect(b, a);
return {right: a, left: b.sym()};
}
else if (cClockwise(vertices[0], vertices[2], vertices[1])) {
var c = connect(b, a);
return {right: c.sym(), left: c};
}
else
return {right: a, left: b.sym()};
}
else if (vertices.length >= 4) {
var half = Math.floor(vertices.length / 2);
var lObjects = divideAndConquer(vertices.slice(0, half));
var rObjects = divideAndConquer(vertices.slice(half, vertices.length));
var ldo = lObjects.right, ldi = lObjects.left;
var rdi = rObjects.right, rdo = rObjects.left;
while (true) {
if (leftOf(rdi.coord, ldi))
ldi = ldi.lNext();
else if (rightOf(ldi.coord, rdi))
rdi = rdi.rPrev();
else
break;
}
var basel = connect(rdi.sym(), ldi);
if (ldi.coord === ldo.coord)
ldo = basel.sym();
if (rdi.coord === rdo.coord)
rdo = basel;
while (true) {
var lcand = basel.sym().oNext();
if (valid(lcand, basel)) {
while (inCircle(basel.dest(), basel.coord, lcand.dest(), lcand.oPrev().dest())) {
var t = lcand.oNext();
deleteEdge(lcand);
lcand = t;
}
}
var rcand = basel.oPrev();
if (valid(rcand, basel)) {
while (inCircle(basel.dest(), basel.coord, rcand.dest(), rcand.oPrev().dest())) {
var t = rcand.oPrev();
deleteEdge(rcand);
rcand = t;
}
}
//This is the part where it gets stuck,
//it never reaches this condition.
if (!valid(lcand, basel) && !valid(rcand, basel)) {
break;
}
if (!valid(lcand, basel) || (valid(rcand, basel) && inCircle(lcand.dest(), lcand.coord, rcand.coord, rcand.dest()))) {
basel = connect(rcand, basel.sym());
}
else {
basel = connect(basel.sym(), lcand.sym());
}
}
return {right: ldo, left: rdo};
}
}
The point class is from PaperJS.
EDIT: set up a Codepen illustrating the problem; click in the output window to add the points. The recursions happens when the fourth point is added.
EDIT 2: fixed the infinite recursion, caused by the valid function, thanks to code found on Ruben Penalva's blog. But, the problem of the dual edge pointing to the origin still persists. That is:
edge.rot().coord === (0, 0)
That makes me think even more that the problem is with the QuadEdge structure itself.
EDIT 3: reading the code carefully for the nth time, I realized that the coordinates for the rotation and inversed rotation edge are never set. So I tried setting them by rotating the original edge. The output now draws something, though I'm pretty sure thats not a Delaunay triangulation. I updated the Codepen example with the progress.

Javascript: Creating an array of arrays

I am trying to create an array of four arrays.
Each of this four arrays consists of three numbers, two of them are randomly assigned from a set of numbers.
When I run the following code I don't get an error, but I also don't get a result.
What am I missing?
I don't really need the print out in console.log, this is just to check if the array is constructed correctly
var x = -2;
function createEnemy(){
var yArray = [60,145,230];
var speedArray = [30,45,55,60];
var randY = Math.floor(Math.random() * yArray.length);
var randSpeed = Math.floor(Math.random() * speedArray.length);
var enemy = [yArray[randY], speedArray[randSpeed], x];
}
function printEnemies()
{
var allEnemies = [];
(function setEnemies()
{
allEnemies.push(createEnemy());
allEnemies.push(createEnemy());
allEnemies.push(createEnemy());
allEnemies.push(createEnemy());
}());
for(var j in allEnemies)
{
for(var p in allEnemies[j] )
{
for(var i = 0; i < allEnemies[j][p].length; i++ )
{
console.log(allEnemies[j][p][i]);
}
}
}
}
printEnemies();
You forgot to return your enemy :)
function createEnemy() {
var yArray = [60,145,230];
var speedArray = [30,45,55,60];
var randY = Math.floor(Math.random() * yArray.length);
var randSpeed = Math.floor(Math.random() * speedArray.length);
var enemy = [yArray[randY], speedArray[randSpeed], x];
return enemy;
}
Make sure you return something from createEnemy:
return [yArray[randY], speedArray[randSpeed], x];
Also, you might prefer something like this loop to the nested one you've implemented:
allEnemies.forEach(function (arr) {
console.log(arr[0], arr[1], arr[2]);
});
Looks like you're missing a 'return enemy' from the createEnemy function and you have an unnecessary tertiary level loop. Here's some modified lines (with some indentation updates for readability).
CODE:
var x = -2;
function createEnemy() {
var yArray = [60,145,230];
var speedArray = [30,45,55,60];
var randY = Math.floor( Math.random() * yArray.length );
var randSpeed = Math.floor( Math.random() * speedArray.length );
var enemy = [yArray[randY], speedArray[randSpeed], x];
return enemy; // Added a return of the enemy.
}
function printEnemies() {
var allEnemies = [];
( function setEnemies() {
allEnemies.push(createEnemy());
allEnemies.push(createEnemy());
allEnemies.push(createEnemy());
allEnemies.push(createEnemy());
}()
);
for(var j in allEnemies) {
for(var p in allEnemies[j] ) {
console.log (allEnemies [j][p] ); // Removed additional depth of loop
}
}
}
printEnemies();

Passing arguments down to nested functions Google Maps v3

Sorry for the newb question here, but Im new to javascript. Ideally I would like to call for myLoop(latLong); but unless I make the variables outside of the function, I can't seem to have .setPosition() recognize the variable.
var x = 0;
var y = 0;
var z = 0;
var v = 0;
function xy(a,b,c,d) {
var longDistance = Math.abs(a-d);
var longTime = longDistance/0.1*0.5;
var latDistance = b-c;
var latRate = latDistance/longTime*0.5;
x = a; //origin long
y = b; //oringin lat
z = latRate;
w = d; //destination long
v = c; //destination lat
}
function myLoop () {
setTimeout(function () {
var latLong = new google.maps.LatLng(y,x);
marker.setPosition(latLong);
x = x + 0.1;
y = y - z;
if (x < w && y < v) {
myLoop();
} else {
alert('finished');
}
}, 0.5)
}
xy(-118,33,40,-73);
myLoop();
You simply need to pass the latLong variable into the myLoop() function recursively.
To do this, you can create your first latLong variable outside of the function, then call the function (passing in the first latLong variable), then within the latLong function, check for your conditions, and if you need to call the myLoop function again, update the latLong variable and then call the myLoop function again.
Here is what your recursive code would look like:
var x = 0;
var y = 0;
var z = 0;
var v = 0;
// Your first latLong
var latLong = new google.maps.LatLng(y,x);
function xy(a,b,c,d) {
// ...
}
// Pass in the latLong variable
function myLoop (latLong) {
setTimeout(function () {
marker.setPosition(latLong);
x = x + 0.1;
y = y - z;
if (x < w && y < v) {
// now create a new latLong, and pass it
// back into this function recursively
latLong = new google.maps.LatLng(y,x);
myLoop(latLong);
} else {
alert('finished');
}
}, 0.5)
}
xy(-118,33,40,-73);
// Now call the myLoop function to get the recursion started
myLoop(latLong);
Alternatively, you can wrap all the code up into one function
Using the revealing module pattern, you can wrap up all your loop functionality in one place (within a function object called latLongGenerator), allowing for a nice separation in your code logic, but still giving you a clean interface to use. The restructured "revealing module" code would look like this:
var latLongGenerator = (function () {
var x = 0;
var y = 0;
var z = 0;
var v = 0;
var latLong;
function setXY(a,b,c,d) {
var longDistance = Math.abs(a-d);
var longTime = longDistance/0.1*0.5;
var latDistance = b-c;
var latRate = latDistance/longTime*0.5;
x = a; //origin long
y = b; //oringin lat
z = latRate;
w = d; //destination long
v = c; //destination lat
// pass in the initial latLong to myLoop(latLong) from here
latLong = new google.maps.LatLng(y,x);
myLoop(latLong);
}
// This is the only function that will
// be exposed publicly on this function
// Example usage: latLongGenerator.startLoopWith(0,0,0,0);
function startLoopWith(a,b,c,d){
setXY(a,b,c,d);
}
function myLoop (latLong) {
setTimeout(function () {
marker.setPosition(latLong);
x = x + 0.1;
y = y - z;
if (x < w && y < v) {
// recursively call the loop from here
latLong = new google.maps.LatLng(y,x);
myLoop(latLong);
} else {
alert('finished');
}
}, 0.5);
}
return {
startLoopWith:startLoopWith
};
})();
// Finally, you can start your loop by passing in
// your initial values to latLongGenerator.startLoopWith(...)
latLongGenerator.startLoopWith(-118,33,40,-73);
This structure gives you a clean way of encapsulating all your calculation logic, while also giving you a nice, clean entry point. Using this new refactor, you can get your loop started with one line:
latLongGenerator.startLoopWith(-118,33,40,-73);
I haven't tested this code, but it should help you get on the right track.
Hope this helps!

Categories