Does d3.js have reverse ease functions? - d3.js

With d3.js we can achieve eased time out of normalized time t, typically in the range [0,1]
For example:
d3.easeCubic(0.25) = 0.0625
How can we reverse that, how can we find x given known y ?
d3.easeCubic(X) = 0.0625,
X ???
The answer here is cubic root, but still.
The problem is in reusability, ease function can change to d3.easeExpIn, or `d3.easeCircleOut, or any other, do you need to invent reverse functions on your own, or are they hidden anywhere ?

Firstly, your math is wrong. d3.easeCubic(0.25) will give you 0.0625:
var easy = d3.easeCubic(0.25);
console.log(easy);
<script src="https://d3js.org/d3.v4.min.js"></script>
Now, back to your question:
How can we reverse that, how can we find x given known y?
There is no native solution, but we can create our own function to find X given a known Y. The problem, of course, is that we have to invert the math for each specific easing... But, since you asked about d3.easeCubic, which is the same of d3.easeCubicInOut, let's try to create an inverted function for that particular easing.
First step, let's have a look at the source code:
export function cubicInOut(t) {
return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2;
}
You can easily see that this is the correct function, giving us the same value as the first snippet:
function cubicInOut(t) {
return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2;
}
console.log(cubicInOut(0.25))
Now, let's try to invert it.
The math here is somehow complicated, but for values less than 1, here is the function:
function inverseEaseCubic(t){
return Math.cbrt(t * 2) / 2;
}
And here is the demo. We pass 0.0625 to the function, and it returns 0.25:
function inverseEaseCubic(t){
return Math.cbrt(t * 2) / 2;
}
console.log(inverseEaseCubic(0.0625))
If you want to deal with numbers bigger than 1, this is the complete function:
function InverseEaseCubic(t){
return t <= 1 ? Math.cbrt(t * 2) / 2 : (Math.cbrt(2 * t - 2) + 2) / 2;
}
PS: In his comment, #altocumulus just reminded us that, sometimes, it's even impossible to find the value. Here is a very simple example. Suppose this function:
function exponentiation(a){
return a*a;
}
Now imagine that, when called with an unknown argument, the function returned 4. What's the argument? Can we find out? Impossible to determine, because second degree equations, like this one, have 2 roots:
console.log(exponentiation(2))//returns 4
console.log(exponentiation(-2))//also returns 4

I used the #Gerardo Furtado answer but the inverse function didn't work well so I wrote another
function cubicInOut(t) {
return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2;
}
function inverseEaseCubic(x) {
return x < .5 ? Math.cbrt(x / 4) : (2 - Math.cbrt(2 - 2 * x)) / 2;
}
console.log(inverseEaseCubic(cubicInOut(1)) === 1);
console.log(inverseEaseCubic(cubicInOut(0.6)) === 0.6);
console.log(inverseEaseCubic(cubicInOut(0.4)) === 0.4);
console.log(inverseEaseCubic(cubicInOut(0.1)) === 0.1);
console.log(inverseEaseCubic(cubicInOut(0)) === 0);

Related

Finite difference method for solving the Klein-Gordon equation in Matlab

I am trying to numerically solve the Klein-Gordon equation that can be found here. To make sure I solved it correctly, I am comparing it with an analytical solution that can be found on the same link. I am using the finite difference method and Matlab. The initial spatial conditions are known, not the initial time conditions.
I start off by initializing the constants and the space-time coordinate system:
close all
clear
clc
%% Constant parameters
A = 2;
B = 3;
lambda = 2;
mu = 3;
a = 4;
b = - (lambda^2 / a^2) + mu^2;
%% Coordinate system
number_of_discrete_time_steps = 300;
t = linspace(0, 2, number_of_discrete_time_steps);
dt = t(2) - t(1);
number_of_discrete_space_steps = 100;
x = transpose( linspace(0, 1, number_of_discrete_space_steps) );
dx = x(2) - x(1);
Next, I define and plot the analitical solution:
%% Analitical solution
Wa = cos(lambda * x) * ( A * cos(mu * t) + B * sin(mu * t) );
figure('Name', 'Analitical solution');
surface(t, x, Wa, 'edgecolor', 'none');
colormap(jet(256));
colorbar;
xlabel('t');
ylabel('x');
title('Wa(x, t) - analitical solution');
The plot of the analytical solution is shown here.
In the end, I define the initial spatial conditions, execute the finite difference method algorithm and plot the solution:
%% Numerical solution
Wn = zeros(number_of_discrete_space_steps, number_of_discrete_time_steps);
Wn(1, :) = Wa(1, :);
Wn(2, :) = Wa(2, :);
for j = 2 : (number_of_discrete_time_steps - 1)
for i = 2 : (number_of_discrete_space_steps - 1)
Wn(i + 1, j) = dx^2 / a^2 ...
* ( ( Wn(i, j + 1) - 2 * Wn(i, j) + Wn(i, j - 1) ) / dt^2 + b * Wn(i - 1, j - 1) ) ...
+ 2 * Wn(i, j) - Wn(i - 1, j);
end
end
figure('Name', 'Numerical solution');
surface(t, x, Wn, 'edgecolor', 'none');
colormap(jet(256));
colorbar;
xlabel('t');
ylabel('x');
title('Wn(x, t) - numerical solution');
The plot of the numerical solution is shown here.
The two plotted graphs are not the same, which is proof that I did something wrong in the algorithm. The problem is, I can't find the errors. Please help me find them.
To summarize, please help me change the code so that the two plotted graphs become approximately the same. Thank you for your time.
The finite difference discretization of w_tt = a^2 * w_xx - b*w is
( w(i,j+1) - 2*w(i,j) + w(i,j-1) ) / dt^2
= a^2 * ( w(i+1,j) - 2*w(i,j) + w(i-1,j) ) / dx^2 - b*w(i,j)
In your order this gives the recursion equation
w(i,j+1) = dt^2 * ( (a/dx)^2 * ( w(i+1,j) - 2*w(i,j) + w(i-1,j) ) - b*w(i,j) )
+2*w(i,j) - w(i,j-1)
The stability condition is that at least a*dt/dx < 1. For the present parameters this is not satisfied, they give this ratio as 2.6. Increasing the time discretization to 1000 points is sufficient.
Next up is the boundary conditions. Besides the two leading columns for times 0 and dt one also needs to set the values at the boundaries for x=0 and x=1. Copy also them from the exact solution.
Wn(:,1:2) = Wa(:,1:2);
Wn(1,:)=Wa(1,:);
Wn(end,:)=Wa(end,:);
Then also correct the definition (and use) of b to that in the source
b = - (lambda^2 * a^2) + mu^2;
and the resulting numerical image looks identical to the analytical image in the color plot. The difference plot confirms the closeness

Which Lua function is better to use?

I took two ways to round numbers to decimals. First function just rounds the number:
function round(num)
local under = math.floor(num)
local over = math.floor(num) + 1
local underV = -(under - num)
local overV = over - num
if overV > underV then
return under
else
return over
end
end
The next two functions use this function to round a number to decimals:
function roundf(num, dec)
return round(num * (1 * dec)) / (1 * dec)
end
function roundf_alt(num, dec)
local r = math.exp(1 * math.log(dec));
return round(r * num) / r;
end
Why not simply
function round(num)
return num >= 0 and math.floor(num+0.5) or math.ceil(num-0.5)
end
Instead of math.floor(num) + 1 you can simply use math.ceil(num) btw.
Why do you multiply with 1 multiple times?
There are many things to consider when rounding numbers. Please do some research on how to handle special cases.

Take exact root of value

I'd like to know how you can take the exact n-th root of a number (in any programming language). When I use a physical calculator, I can type something like sqrt(12) (nicely formatted of course) and get as a result 2 sqrt(3). How can I achieve this not only with square roots but any type of root when representing a number as numerator and denominator. Of course, I would have to use another representation, but I don't have any idea how this works in general.
Thanks in advance.
I doubt this is an efficient way, but it would work. Assuming you want to take the nth root of some number m:
Calculate the prime factorization m = p1a1 * p2a2 * ... * pxax.
For each 1 <= i <= x let ki = ai div n and ri = ai mod n.
The part that gets factored out is then p1k1 * p2k2 * ... * pxkx.
The part that remains "under the root" is p1r1 * p2r2 * ... * pxrx.
The first step is the only tricky one. Once you have found all prime factors of m it is just a matter of looping over those factors and dividing out the multiples of n.
To simplify the n-th root of a number, the algorithm shouldn't do prime factorisation, but rather "n-th power factorisation", i.e. look for the largest n-th power inside the root, which you can then move outside the root. For example: the 3rd root of 250 equals the third root of 2 x 125; since 125 is the third power of 5, you can move it out of the root and get: 5 times the third root of 2.
Algorithm: take the floating-point n-th root of the number, and round it down, then check this and all smaller integers until you find the largest integer whose n-th power divides the number; then divide the number by the n-th power and move the integer out of the root.
This javascript example shows a basic implementation; you could clean it up further by printing 11/root simply as 1; further optimisation is undoubtedly possible.
function integerRoot(number, root) {
var base = number, factor = 1;
var max = Math.floor(Math.pow(base, 1/root));
for (var i = max; i > 1; i--) {
var power = Math.pow(i, root);
if (base % power == 0) {
base /= power;
factor *= i;
break;
}
}
document.write(number + "<SUP>1/" + root + "</SUP> = " +
factor + " × " + base + "<SUP>1/" + root + "</SUP><BR>");
}
integerRoot(25, 3);
integerRoot(27, 3);
integerRoot(81, 3);
integerRoot(135, 3);
integerRoot(375, 3);
integerRoot(8*27*64*17, 3);
UPDATE: This is a more efficient version; I haven't yet taken negative numbers into account, though, so there's definitely room for further improvement.
function simplifyRoot(radicand, degree) {
var factor = 1, base = 1, power;
while ((power = Math.pow(++base, degree)) <= radicand) {
while (radicand % power == 0) {
factor *= base;
radicand /= power;
}
}
return {factor: factor, radicand: radicand, degree: degree};
}
var radicand = 8*27*36*64*125*216, degree = 3;
var simplified = simplifyRoot(radicand, degree);
document.write(radicand + "<SUP>1/" + degree + "</SUP> = " +
simplified.factor + " × " + simplified.radicand + "<SUP>1/" + simplified.degree + "</SUP><BR>");

Exponentiation program

I am trying to do a fast exponentiation. But the result does not seem to produce the correct result. Any help would be appreciated.
EDIT: Manage to solve it thanks for all the help.
if (content[i] == '1')
s1 = (int)(po1 * (Math.pow(po1, 2)));
else
s1 = po1 * po1;
final_result *= temp;
Check out this Exponation by squaring
You probably want to bit-shift right and square your base each time you encounter a 1 bit in the exponent
int pow(int base, int e)
{
int retVal = 1;
while (e)
{
if (e % 2 == 1)//i.e. last bit of exponent is 1
retVal *= base;
e >>= 1; //bitshift exponent to the right.
base *= base; // square base since we shifted 1 bit in our exponent
}
return retVal ;
}
A good way of thinking about it is that your exponent is being broken down: say, 6^7 (exponent in bits is 1, 1, 1) = 6^1 * 6^2 * 6^4 = 6 * 36 * 36^2 = 6 * 36 * 1296. Your base is always squaring itself.
temp = (int)(g1 * (Math.pow(g1, 2)));
This basically just boils down to g13. I'm not familiar with this algorithm but this can't be right.
Also, as a side note, don't ever call Math.pow(<var>, 2), just write <var> * <var>.
There are several problems with your code, starting with the fact that you are reading the exp string in the wrong direction, adding extra multiplications by the base, and not considering the rank of the 1 when raising the powers of 2.
Here is a python quick sketch of what you are trying to achieve:
a = int(raw_input("base"))
b = "{0:b}".format(int(raw_input("exp")))
res = 1
for index, i in enumerate(b[::-1]):
if i == '1':
res *= a**(2**index)
print res
Alternatively, you could square a at every iteration instead:
for index, i in enumerate(b[::-1]):
if i == '1':
res *= a
a *= a

Rounding to nearest 100

First number needs to be rounded to nearest second number. There are many ways of doing this, but whats the best and shortest algorithm? Anyone up for a challenge :-)
1244->1200
1254->1300
123->100
178->200
1576->1600
1449->1400
123456->123500
654321->654300
23->00
83->100
Ruby's round method can consume negative precisions:
n.round(-2)
In this case -2 gets you rounding to the nearest hundred.
For input n:
(n + 50) / 100 * 100
using integer division.
Note that many languages/libraries already have functions to do this.
100 * round(n/100.0)
I know it's late in the game, but here's something I generally set up when I'm dealing with having to round things up to the nearest nTh:
Number.prototype.roundTo = function(nTo) {
nTo = nTo || 10;
return Math.round(this * (1 / nTo) ) * nTo;
}
console.log("roundto ", (925.50).roundTo(100));
Number.prototype.ceilTo = function(nTo) {
nTo = nTo || 10;
return Math.ceil(this * (1 / nTo) ) * nTo;
}
console.log("ceilTo ", (925.50).ceilTo(100));
Number.prototype.floorTo = function(nTo) {
nTo = nTo || 10;
return Math.floor(this * (1 / nTo) ) * nTo;
}
console.log("floorTo ", (925.50).floorTo(100));
I find myself using Number.ceilTo(..) because I'm working with Canvas and trying to get out to determine how far out to scale.
This will do it, given you're using integer math:
n = (n + 50) / 100 * 100
Of course, you didn't specify the behavior of e.g., 1350 and 1450, so I've elected to round up. If you need round-to-even, that'll not work.
As per Pawan Pillai's comment above, rounding to nearest 100th in Javascript:
100 * Math.floor((foo + 50) / 100);
Is this homework?
Generally, mod 100, then if >50 add else subtract.

Resources