How to add elements to a Map? - dictionary

I have a node type like the following :
type position = float * float
type node = position
I wrote these modules to use nodes as keys in my Map :
module MyMap =
struct
type t = node
let compare n1 n2 =
if n1 = n2 then 1
else 0
end
module Dist = Map.Make(MyMap)
Then I created an empty Map :
let mapTest = Dist.empty;;
let mapTest = Dist.add (1.,1.) 1. mapTest;;
I get the length of the Map like this :
Dist.cardinal mapTest;;
- : int = 1
I try to add another element :
let mapTest = Dist.add (2.,2.) 2. mapTest;;
But then my Map is still of length 1 when I use Dist.cardinal mapTest
More surprising, when I run :
Dist.find (1.,1.) mapTest;;
- : float = 2.
So now I'm left clueless about what's going on or what I've done wrong.
My goal is to be able to use the Map, add bindings etc.
Any ideas?
Thanks

The compare function does not behave as expected : it is expected to return 0 when n1 and n2 are equals, otherwise 1 if n1 is greater than n2, -1 if not.
The following code shall fix the issue :
module MyMap =
struct
type t = node
let compare (a1,b1) (a2,b2) =
if a1 > a2 then 1
else if a1 < a2 then -1
else if b1 > b2 then 1
else if b1 < b2 then -1
else 0
end

let compare n1 n2 =
if n1 = n2 then 1
else 0
It looks like you've misunderstood how compare is supposed to behave. Here's the description of compare from the documentation of OrderedType:
This is a two-argument function f such that f e1 e2 is zero if the keys e1 and e2 are equal, f e1 e2 is strictly negative if e1 is smaller than e2, and f e1 e2 is strictly positive if e1 is greater than e2.
So the way you defined it, n1 would be considered greater than n2 if n1 = n2 and otherwise n1 would be considered equal to n2. This does not follow any of the rules you'd expect from a comparison function: a key isn't considered equal to itself and "n1 is greater than n2" can (and in fact always will) be true at the same time as "n2 is greater than n1". Consequently the map will not behave in a sensible way.
Assuming you want to consider one node equal to another if and only if they contain the same values in the same order, you can just define compare using Stdlib.compare.

That is not how you're supposed to write the compare function.
To quote the manual:
A total ordering function over the keys. This is a two-argument
function f such that f e1 e2 is zero if the keys e1 and e2 are equal,
f e1 e2 is strictly negative if e1 is smaller than e2, and f e1 e2 is
strictly positive if e1 is greater than e2. Example: a suitable
ordering function is the generic structural comparison function
compare.
So your compare function should be:
let compare n1 n2 =
if n1 < n2 then -1
else if n1 > n2 then 1
else 0
Note that on floating point numbers, comparison is weird. First, the rounding makes some numbers that seem equal to not be so. Second and even worse, the standard comparisons are not total (they all always return false on a NaN).
Thankfully, you can trust the standard compare function to solve the latter problem:
let compare (n1:t) n2 = Stdlib.compare n1 n2

Related

convert an R script to IDL: Array manipulation

I am an R and IDL beginner. Im trying to convert an R script to IDL.
R can do array manipulation with t1 (array[100000]) but IDL cannot.
ERROR: Array subscript for CZ must have same size as source expression
s1= 100000.
c1 = array[200000]
n1 = s1*2+2
t1 = array[100000]
————————————————————————————————
(function)
f03, c1, s1, n1
cz = fltarr(n1,3)
cz[0:((2*s1)-1),0] = c1
cz[1:(2*s1),1] = c1
cz[2:((2*1)+1),2] = c1
cr = cz[0:(n1-1),1] - cz[0:(n1-1),2]
cl = cz[0:(n1-1),1] - cz[0:(n1-1),0]
p1 = where(cr GE 0.0 AND cl GE 0.0 AND (cz[0:(n1-1),1]) GE 1.4)
n2 = n_elements(p1)
ct = fltarr(n2+1,2)
ct[0:n2-1,0] = p1
ct[1:n2,1] = p1
c2 = ct[*,0] - ct[*,1]
ip = where(c2 GT 2.)
ch = p1[ip]
return, ch
————————————————————————————————
p1 = f03(c1,s1,n1) ;;;;; function works here
f1 = f03(t1,s1,n1) ;;;;; error on array size
I used MATRIX and AS.MATRIX in R (for f03). Does FLTARR cause this error?
Your lines:
cz = fltarr(n1, 3)
cz[0:((2 * s1) - 1), 0] = c1
make sense when cz has a first dimension of size 2000002 and c1 is 200000 elements — the sizes on the left and right of the = sign match, i.e., 0:199999 is 2000000 elements just like the size of c1.
But in the second call, c1 only has 100000 elements, but the left side is still asking for 2000000 elements.
Also, define a function like:
function f03, c1, s1, n1
; a bunch of code goes here
return, ch
end

Fortran reshape - N-dimensional transpose

I'm trying to write some code in Fortran which requires the re-ordering of an n-dimensional array. I thought the reshape intrinsic combined with the order argument should allow this, however I'm running into difficulties.
Consider the following minimal example
program test
implicit none
real, dimension(:,:,:,:,:), allocatable :: matA, matB
integer, parameter :: n1=3, n2=5, n3=7, n4=11, n5=13
integer :: i1, i2, i3, i4, i5
allocate(matA(n1,n2,n3,n4,n5)) !Source array
allocate(matB(n3,n2,n4,n1,n5)) !Reshaped array
!Populate matA
do i5=1, n5
do i4=1, n4
do i3=1, n3
do i2=1, n2
do i1=1, n1
matA(i1,i2,i3,i4,i5) = i1+i2*10+i3*100+i4*10000+i5*1000000
enddo
enddo
enddo
enddo
enddo
print*,"Ad1 : ",matA(:,1,1,1,1),shape(matA)
matB = reshape(matA, shape(matB), order = [3,2,4,1,5])
print*,"Bd4 : ",matB(1,1,1,:,1),shape(matB) !Leading dimension of A is the fourth dimension of B
end program test
I would expect this to result in
Ad1 : 1010111.00 1010112.00 1010113.00 3 5 7 11 13
Bd4 : 1010111.00 1010112.00 1010113.00 7 5 11 3 13
But instead I find:
Ad1 : 1010111.00 1010112.00 1010113.00 3 5 7 11 13
Bd4 : 1010111.00 1010442.00 1020123.00 7 5 11 3 13
I've tried this with gfortran (4.8.3 and 4.9) and ifort (11.0) and find the same results, so it's likely that I am simply misunderstanding something about how reshape works.
Can anybody shed any light on where I'm going wrong and how I can achieve my goal?
Because I also feel the behavior of order for multi-dimensional arrays is quite non-intuitive, I made some code comparison below to make the situation even clear (in addition to the already complete #francescalus' answer). First, in a simple case, reshape() with and without order gives the following:
mat = reshape( [1,2,3,4,5,6,7,8], [2,4] )
=> [ 1 3 5 7 ;
2 4 6 8 ]
mat = reshape( [1,2,3,4,5,6,7,8], [2,4], order=[2,1] )
=> [ 1 2 3 4 ;
5 6 7 8 ]
This example shows that without order the elements are filled in the usual column-major way, while with order=[2,1] the 2nd dimension runs faster and so the elements are filled row-wise. The key point here is that the order specifies which dimension of the LHS (rather than the source array) runs faster (as emphasized in the above answer).
Now we apply the same mechanism to higher-dimensional cases. First, reshape() of the 5-dimensional array without order
matB = reshape( matA, [n3,n2,n4,n1,n5] )
corresponds to the explicit loops
k = 0
do i5 = 1, n5 !! (5)-th dimension of LHS
do i1 = 1, n1 !! (4)
do i4 = 1, n4 !! (3)
do i2 = 1, n2 !! (2)
do i3 = 1, n3 !! (1)-st dimension of LHS
k = k + 1
matB( i3, i2, i4, i1, i5 ) = matA_seq( k )
enddo;enddo;enddo;enddo;enddo
where matA_seq is a sequential view of matA
real, pointer :: matA_seq(:)
matA_seq( 1 : n1*n2*n3*n4*n5 ) => matA(:,:,:,:,:)
Now attaching order=[3,2,4,1,5] to reshape(),
matB = reshape( matA, [n3,n2,n4,n1,n5], order = [3,2,4,1,5] )
then the order of DO-loops is changed such that
k = 0
do i5 = 1, n5 !! (5)-th dim of LHS
do i3 = 1, n3 !! (1)
do i1 = 1, n1 !! (4)
do i2 = 1, n2 !! (2)
do i4 = 1, n4 !! (3)-rd dim of LHS
k = k + 1
matB( i3, i2, i4, i1, i5 ) = matA_seq( k )
enddo;enddo;enddo;enddo;enddo
This means that the 3rd dimension of matB (and thus i4) runs fastest (which corresponds to the second line in the above Answer). But what is desired by OP is
k = 0
do i5 = 1, n5 !! (5)-th dim of LHS
do i4 = 1, n4 !! (3)
do i3 = 1, n3 !! (1)
do i2 = 1, n2 !! (2)
do i1 = 1, n1 !! (4)-th dim of LHS
k = k + 1
matB( i3, i2, i4, i1, i5 ) = matA_seq( k )
enddo;enddo;enddo;enddo;enddo
which corresponds to
matB = reshape( matA, [n3,n2,n4,n1,n5], order = [4,2,1,3,5] )
i.e., the final line of the francescalus' answer.
Hope this comparison further clarifies the situation...
When order= is specified in reshape the elements of the result taken with permuted subscript order correspond to the elements of the source array. That probably isn't entirely clear. The Fortran 2008 standard states this as (ignoring the part about pad=)
The elements of the result, taken in permuted subscript order ORDER (1), ..., ORDER (n), are those of SOURCE in normal array element order ..
What this means is that from your example with order=[3,2,4,1,5] there is the mapping to
matA(1,1,1,1,1), matA(2,1,1,1,1), matA(3,1,1,1,1), matA(1,2,1,1,1), ...
of
matB(1,1,1,1,1), matB(1,1,2,1,1), matB(1,1,3,1,1), matB(1,1,4,1,1), ...
with offset changing most rapidly in the third index of matB corresponding to most rapidly varying in the first of matA. The next fastest varying in matB being dimension 2, then 4, and so on.
So, it's the elements matB(1,1,1:3,1,1) that correspond the matA(:,1,1,1,1).
I've been explicit in the extent of that matB slice because you've a problem with the shape of matB: you want the shape of matB to be the inverse of the permutation given by the order= specifier.
You could write your example as
implicit none
integer, parameter :: n1=3, n2=5, n3=7, n4=11, n5=13
integer matA(n1,n2,n3,n4,n5)
integer matB(n4,n2,n1,n3,n5) ! Inverse of permutation (3 2 4 1 5)
integer i1, i2, i3, i4, i5
forall (i1=1:n1, i2=1:n2, i3=1:n3, i4=1:n4, i5=1:n5) &
matA(i1,i2,i3,i4,i5)=i1+i2*10+i3*100+i4*10000+i5*1000000
print*,"Ad1 : ",matA(:,1,1,1,1),shape(matA)
matB = reshape(matA, shape(matB), order = [3,2,4,1,5])
print*,"Bd3 : ",matB(1,1,:,1,1),shape(matB)
end
Alternatively, if it's the shape of matB that you want, then it's the order permutation that wants inverting:
matB = reshape(matA, shape(matB), order = [4,2,1,3,5])
At first glance, it may be natural to view the order relating to the dimensions of the source. However, the following may clarify: the result of the reshaping is the same regardless of the shape of source (what is used are the elements of the array in natural order); the order= value has size equal to that of the shape= value. For the first of these, if the source were, say [1,2,3,4,5,6] (recall how we construct rank-2 arrays), then order= could never have any effect (it would have to be [1]) if it were used on the source.

How to find d, given p, q, and e in RSA?

I know I need to use the extended euclidean algorithm, but I'm not sure exactly what calculations I need to do. I have huge numbers. Thanks
Well, d is chosen such that d * e == 1 modulo (p-1)(q-1), so you could use the Euclidean algorithm for that (finding the modular multiplicative inverse).
If you are not interested in understanding the algorithm, you can just call BigInteger#modInverse directly.
d = e.modInverse(p_1.multiply(q_1))
Given that, p=11, q=7, e =17, n=77, φ (n) = 60 and d=?
First substitute values from the formula:-
ed mod φ (n) =1
17 d mod 60 = 1
The next step: – take the totient of n, which is 60 to your left hand side and [e] to your right hand side.
60 = 17
3rd step: – ask how many times 17 goes to 60. That is 3.5….. Ignore the remainder and take 3.
60 = 3(17)
Step 4: – now you need to balance this equation 60 = 3(17) such that left hand side equals to right hand side. How?
60 = 3(17) + 9 <== if you multiply 3 by 17 you get 51 then plus 9, that is 60. Which means both sides are now equal.
Step 5: – Now take 17 to your left hand side and 9 to your right hand side.
17 = 9
Step 6:- ask how many times 9 goes to 17. That is 1.8…….
17 = 1(9)
Step 7:- Step 4: – now you need to balance this 17 = 1(9)
17 = 1(9) + 8 <== if you multiply 1 by 9 you get 9 then plus 8, that is 17. Which means both sides are now equal.
Step 8:- again take 9 to your left hand side and 8 to your right hand side.
9 = 1(8)
9 = 1(8) + 1 <== once you reached +1 to balance your equation, you may stop and start doing back substitution.
Step A:-Last equation in step 8 which is 9 = 1(8) + 1 can be written as follows:
1.= 9 – 1(8)
Step B:-We know what is (8) by simple saying 8 = 17 – 1(9) from step 7. Now we can re-write step A as:-
1=9 -1(17 – 1(9)) <== here since 9=1(9) we can re-write as:-
1=1(9)-1(17) +1(9) <== group similar terms. In this case you add 1(9) with 1(9) – that is 2(9).
1=2(9)-1(17)
Step C: – We know what is (9) by simple saying 9 = 60 – 3(17) from step 4. Now we can re-write step B as:-
1=2(60-3(17) -1(17)
1=2(60)-6(17) -1(17) <== group similar terms. In this case you add 6(17) with 1(17) – that is 7(17).
1=2(60)-7(17) <== at this stage we can stop, nothing more to substitute, therefore take the value next 17. That is 7. Subtract it with the totient.
60-7=d
Then therefore the value of d= 53.
I just want to augment the Sidudozo's answer and clarify some important points.
First of all, what should we pass to Extended Euclidean Algorthim to compute d ?
Remember that ed mod φ(n) = 1 and cgd(e, φ(n)) = 1.
Knowing that the Extended Euclidean Algorthim is based on the formula cgd(a,b) = as + bt, hence cgd(e, φ(n)) = es + φ(n)t = 1, where d should be equal to s + φ(n) in order to satisfy the
ed mod φ(n) = 1 condition.
So, given the e=17 and φ(n)=60 (borrowed from the Sidudozo's answer), we substitute the corresponding values in the formula mentioned above:
cgd(e, φ(n)) = es + φ(n)t = 1 ⇔ 17s + 60t = 1.
At the end of the Sidudozo's answer we obtain s = -7. Thus d = s + φ(n) ⇔ d = -7 + 60 ⇒ d = 53.
Let's verify the results. The condition was ed mod φ(n) = 1.
Look 17 * 53 mod 60 = 1. Correct!
The approved answer by Thilo is incorrect as it uses Euler's totient function instead of Carmichael's totient function to find d. While the original method of RSA key generation uses Euler's function, d is typically derived using Carmichael's function instead for reasons I won't get into. The math needed to find the private exponent d given p q and e without any fancy notation would be as follows:
d = e^-1*mod(((p-1)/GCD(p-1,q-1))(q-1))
Why is this? Because d is defined in the relationship
de = 1*mod(λ(n))
Where λ(n) is Carmichael's function which is
λ(n)=lcm(p-1,q-1)
Which can be expanded to
λ(n)=((p-1)/GCD(p-1,q-1))(q-1)
So inserting this into the original expression that defines d we get
de = 1*mod(((p-1)/GCD(p-1,q-1))(q-1))
And just rearrange that to the final formula
d = e^-1*mod(((p-1)/GCD(p-1,q-1))(q-1))
More related information can be found here.
Here's the code for it, in python:
def inverse(a, n):
t, newt = 0, 1
r, newr = n, a
while newr:
quotient = r // newr # floor division
t, newt = newt, t - quotient * newt
r, newr = newr, r - quotient * newr
if r > 1:
return None # there's no solution
if t < 0:
t = t + n
return t
inverse(17, 60) # returns 53
adapted from pseudocode found in wiki: https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm#Pseudocode
Simply use this formula,
d = (1+K(phi))/e. (Very useful when e and phi are small numbers)
Lets say, e = 3 and phi = 40
we assume K = 0, 1, 2... until your d value is not a decimal
assume K = 0, then
d = (1+0(40))/3 = 0. (if it is a decimal increase the K value, don't bother finding the exact value of the decimal)
assume K = 2, then
d = (1+2(40)/3) = 81/3 = 27
d = 27.
Assuming K will become exponentially easy with practice.
Taken the values p=7, q=11 and e=17.
then the value of n=p*q=77 and f(n)=(p-1)(q-1)=60.
Therefore, our public key pair is,(e,n)=(7,77)
Now for calvulating the value of d we have the constraint,
e*d == 1 mod (f(n)), [here "==" represents the **congruent symbol**].
17*d == 1 mod 60
(17*53)*d == 53 mod 60, [7*53=901, which gives modulus value 1]
1*d == 53 mod 60
hence,this gives the value of d=53.
Therefore our private key pair will be, (d,n)=(53,77).
Hope this help. Thank you!

Line of intersection between two planes

How can I find the line of intersection between two planes?
I know the mathematics idea, and I did the cross product between the the planes normal vectors
but how to get the line from the resulted vector programmatically
The equation of the plane is ax + by + cz + d = 0, where (a,b,c) is the plane's normal, and d is the distance to the origin. This means that every point (x,y,z) that satisfies that equation is a member of the plane.
Given two planes:
P1: a1x + b1y + c1z + d1 = 0
P2: a2x + b2y + c2z + d2 = 0
The intersection between the two is the set of points that verifies both equations. To find points along this line, you can simply pick a value for x, any value, and then solve the equations for y and z.
y = (-c1z -a1x -d1) / b1
z = ((b2/b1)*(a1x+d1) -a2x -d2)/(c2 - c1*b2/b1)
If you make x=0, this gets simpler:
y = (-c1z -d1) / b1
z = ((b2/b1)*d1 -d2)/(c2 - c1*b2/b1)
Finding the line between two planes can be calculated using a simplified version of the 3-plane intersection algorithm.
The 2'nd, "more robust method" from bobobobo's answer references the 3-plane intersection.
While this works well for 2 planes (where the 3rd plane can be calculated using the cross product of the first two), the problem can be further reduced for the 2-plane version.
No need to use a 3x3 matrix determinant,instead we can use the squared length of the cross product between the first and second plane (which is the direction of the 3'rd plane).
No need to include the 3rd planes distance,(calculating the final location).
No need to negate the distances.Save some cpu-cycles by swapping the cross product order instead.
Including this code-example, since it may not be immediately obvious.
// Intersection of 2-planes: a variation based on the 3-plane version.
// see: Graphics Gems 1 pg 305
//
// Note that the 'normal' components of the planes need not be unit length
bool isect_plane_plane_to_normal_ray(
const Plane& p1, const Plane& p2,
// output args
Vector3f& r_point, Vector3f& r_normal)
{
// logically the 3rd plane, but we only use the normal component.
const Vector3f p3_normal = p1.normal.cross(p2.normal);
const float det = p3_normal.length_squared();
// If the determinant is 0, that means parallel planes, no intersection.
// note: you may want to check against an epsilon value here.
if (det != 0.0) {
// calculate the final (point, normal)
r_point = ((p3_normal.cross(p2.normal) * p1.d) +
(p1.normal.cross(p3_normal) * p2.d)) / det;
r_normal = p3_normal;
return true;
}
else {
return false;
}
}
Adding this answer for completeness, since at time of writing, none of the answers here contain a working code-example which directly addresses the question.
Though other answers here already covered the principles.
Finding a point on the line
To get the intersection of 2 planes, you need a point on the line and the direction of that line.
Finding the direction of that line is really easy, just cross the 2 normals of the 2 planes that are intersecting.
lineDir = n1 × n2
But that line passes through the origin, and the line that runs along your plane intersections might not. So, Martinho's answer provides a great start to finding a point on the line of intersection (basically any point that is on both planes).
In case you wanted to see the derivation for how to solve this, here's the math behind it:
First let x=0. Now we have 2 unknowns in 2 equations instead of 3 unknowns in 2 equations (we arbitrarily chose one of the unknowns).
Then the plane equations are (A terms were eliminated since we chose x=0):
B1y + C1z + D1 = 0
B2y + C2z + D2 = 0
We want y and z such that those equations are both solved correctly (=0) for the B1, C1 given.
So, just multiply the top eq by (-B2/B1) to get
-B2y + (-B2/B1)*C1z + (-B2/B1)*D1 = 0
B2y + C2z + D2 = 0
Add the eqs to get
z = ( (-B2/B1)*D1 - D2 ) / (C2 * B2/B1)*C1)
Throw the z you find into the 1st equation now to find y as
y = (-D1 - C1z) / B1
Note the best variable to make 0 is the one with the lowest coefficients, because it carries no information anyway. So if C1 and C2 were both 0, choosing z=0 (instead of x=0) would be a better choice.
The above solution can still screw up if B1=0 (which isn't that unlikely). You could add in some if statements that check if B1=0, and if it is, be sure to solve for one of the other variables instead.
Solution using intersection of 3 planes
From user's answer, a closed form solution for the intersection of 3 planes was actually in Graphics Gems 1. The formula is:
P_intersection = (( point_on1 • n1 )( n2 × n3 ) + ( point_on2 • n2 )( n3 × n1 ) + ( point_on3 • n3 )( n1 × n2 )) / det(n1,n2,n3)
Actually point_on1 • n1 = -d1 (assuming you write your planes Ax + By + Cz + D=0, and not =-D). So, you could rewrite it as:
P_intersection = (( -d1 )( n2 × n3 ) + ( -d2 )( n3 × n1 ) + ( -d3 )( n1 × n2 )) / det(n1,n2,n3)
A function that intersects 3 planes:
// Intersection of 3 planes, Graphics Gems 1 pg 305
static Vector3f getIntersection( const Plane& plane1, const Plane& plane2, const Plane& plane3 )
{
float det = Matrix3f::det( plane1.normal, plane2.normal, plane3.normal ) ;
// If the determinant is 0, that means parallel planes, no intn.
if( det == 0.f ) return 0 ; //could return inf or whatever
return ( plane2.normal.cross( plane3.normal )*-plane1.d +
plane3.normal.cross( plane1.normal )*-plane2.d +
plane1.normal.cross( plane2.normal )*-plane3.d ) / det ;
}
Proof it works (yellow dot is intersection of rgb planes here)
Getting the line
Once you have a point of intersection common to the 2 planes, the line just goes
P + t*d
Where P is the point of intersection, t can go from (-inf, inf), and d is the direction vector that is the cross product of the normals of the two original planes.
The line of intersection between the red and blue planes looks like this
Efficiency and stability
The "robust" (2nd way) takes 48 elementary ops by my count, vs the 36 elementary ops that the 1st way (isolation of x,y) uses. There is a trade off between stability and # computations between these 2 ways.
It'd be pretty catastrophic to get (0,inf,inf) back from a call to the 1st way in the case that B1 was 0 and you didn't check. So adding in if statements and making sure not to divide by 0 to the 1st way may give you the stability at the cost of code bloat, and the added branching (which might be quite expensive). The 3 plane intersection method is almost branchless and won't give you infinities.
This method avoids division by zero as long as the two planes are not parallel.
If these are the planes:
A1*x + B1*y + C1*z + D1 = 0
A2*x + B2*y + C2*z + D2 = 0
1) Find a vector parallel to the line of intersection. This is also the normal of a 3rd plane which is perpendicular to the other two planes:
(A3,B3,C3) = (A1,B1,C1) cross (A2,B2,C2)
2) Form a system of 3 equations. These describe 3 planes which intersect at a point:
A1*x1 + B1*y1 + C1*z1 + D1 = 0
A2*x1 + B2*y1 + C2*z1 + D2 = 0
A3*x1 + B3*y1 + C3*z1 = 0
3) Solve them to find x1,y1,z1. This is a point on the line of intersection.
4) The parametric equations of the line of intersection are:
x = x1 + A3 * t
y = y1 + B3 * t
z = z1 + C3 * t
The determinant-based approach is neat, but it's hard to follow why it works.
Here's another way that's more intuitive.
The idea is to first go from the origin to the closest point on the first plane (p1), and then from there go to the closest point on the line of intersection of the two planes. (Along a vector that I'm calling v below.)
Given
=====
First plane: n1 • r = k1
Second plane: n2 • r = k2
Working
=======
dir = n1 × n2
p1 = (k1 / (n1 • n1)) * n1
v = n1 × dir
pt = LineIntersectPlane(line = (p1, v), plane = (n2, k2))
LineIntersectPlane
==================
#We have n2 • (p1 + lambda * v) = k2
lambda = (k2 - n2 • p1) / (n2 • v)
Return p1 + lambda * v
Output
======
Line where two planes intersect: (pt, dir)
This should give the same point as the determinant-based approach. There's almost certainly a link between the two. At least the denominator, n2 • v, is the same, if we apply the "scalar triple product" rule. So these methods are probably similar as far as condition numbers go.
Don't forget to check for (almost) parallel planes. For example: if (dir • dir < 1e-8) should work well if unit normals are used.
You can find the formula for the intersection line of two planes in this link.
P1: a1x + b1y + c1z = d1
P2: a2x + b2y + c2z = d2
n1=(a1,b1,c1); n2=(a2,b2,c2); n12=Norm[Cross[n1,n2]]^2
If n12 != 0
a1 = (d1*Norm[n2]^2 - d2*n1.n2)/n12;
a2 = (d2*Norm[n1]^2 - d1*n1.n2)/n12;
P = a1 n1 + a2 n2;
(*formula for the intersection line*)
Li[t_] := P + t*Cross[n1, n2];
The cross product of the line is the direction of the intersection line. Now you need a point in the intersection.
You can do this by taking a point on the cross product, then subtracting Normal of plane A * distance to plane A and Normal of plane B * distance to plane b. Cleaner:
p = Point on cross product
intersection point = ([p] - ([Normal of plane A] * [distance from p to plane A]) - ([Normal of plane B] * [distance from p to plane B]))
Edit:
You have two planes with two normals:
N1 and N2
The cross product is the direction of the Intersection Line:
C = N1 x N2
The class above has a function to calculate the distance between a point and a plane. Use it to get the distance of some point p on C to both planes:
p = C //p = 1 times C to get a point on C
d1 = plane1.getDistance(p)
d2 = plane2.getDistance(p)
Intersection line:
resultPoint1 = (p - (d1 * N1) - (d2 * N2))
resultPoint2 = resultPoint1 + C

Creating an Exclusive Or from two Deterministic Finite Automatons (Deterministic Finite-State Machines)

Two DFAs (Deterministic Finite Automaton or Deterministic Fininte-State Machines - Which will be called DFAs from here on)
Defined over the set
DFA 1: L1 = {Q1, E, D1, s1, F}
DFA 2: L2 = {Q2, E, D2, s2, F}
Q is the list of states. Ex 1, 2, 3, 4 or a, b, c, d
E is the the language Ex. 0, 1
D is the transition set Ex. {(a,0,b)} state a goes to b on a 0
s is the starting state
F is the final state
How would you take and exclusive-or of two DFAs L1 and L2
Here are a few broad hints to get you started...
You'll probably want to build another DFA whose states Q3 are identified with
elements of the Cartesian product of Q1 and Q2. From s1 and s2, it should be
pretty obvious which element of Q3 should be designated as the start state.
Then, given any node (n1 in Q1, n2 in Q2) in Q3, it should be pretty easy to
figure out where the edges need to go for each input. And F3 will a set of states
(n1, n2) where (n1 in F1 XOR n2 in F2) holds.
Q = Q1 X Q2;
E = E;
D is all transitions that agree from both systems;
s = S1 intersect S2;
F = F1 XOR F2

Resources