[Question]
  [
I was at a friend's house for dinner and they suggested the idea of a "Prime-factor vector space". In this space the positive integers are expressed as a vector such that the **n**th element in the vector is the number of times the **n**th prime divides the number. (Note that this means that our vectors have an infinite number of terms.) For example **20** is
```
2 0 1 0 0 0 ...
```
Because its prime factorization is **2 \* 2 \* 5**.
Since prime factorization is unique each number corresponds to one vector.
We can add vectors by pairwise adding their entries. This is the same as multiplying the numbers they are associated with. We can also do scalar multiplication, which is akin to raising the associated number to a power.
The problem is that this space is not in fact a vector space because there are no inverses. If we go ahead and add the inverses and close the vector space we now have a way of expressing every positive rational number as a vector. If we keep the fact that vector addition represents multiplication. Then the inverse of a natural number is its reciprocal.
For example the number **20** had the vector 
```
2 0 1 0 0 0 ...
```
So the fraction **1/20** is its inverse
```
-2 0 -1 0 0 0 ...
```
If we wanted to find the vector associated with a fraction like **14/15** we would find **14**
```
1 0 0 1 0 0 ...
```
and **1/15**
```
0 -1 -1 0 0 0 ...
```
and multiply them by performing vector addition
```
1 -1 -1 1 0 0 ...
```
Now that we have a vector space we can modify it to form an inner product space by giving it an inner product. To do this we steal the inner product that vector spaces are given classically. The inner product of two vectors is defined as the sum of the pairwise multiplication of their terms. For example **20 · 14/15** would be calculated as follows
```
20    =  2  0  1  0  0  0 ...
14/15 =  1 -1 -1  1  0  0 ...
         2  0 -1  0  0  0 ...  -> 1
```
As another example the product **2/19 · 4/19**
```
2/19 = 1 0 0 0 0 0 0 -1 0 0 0 ...
4/19 = 2 0 0 0 0 0 0 -1 0 0 0 ...
       2 0 0 0 0 0 0  1 0 0 0 ... -> 3
```
Your task is to implement a program that performs this dot product. It should take two positive rational numbers via either a pair of positive integers (numerator and denominator) or a rational type (floats are not allowed, because they cause problems with precision and divisibility) and should output a integer representing the dot product of the two inputs.
This is [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'") so answers will be scored in bytes with fewer bytes being better.
## Test Cases
```
4 · 4 = 4
8 · 8 = 9
10 · 10 = 2
12 · 12 = 5
4 · 1/4 = -4
20 · 14/15 = 1
2/19 · 4/19 = 3
```
  
[Answer]
# [MATL](https://github.com/lmendo/MATL), 12 bytes
```
YF2:&Y)dwd*s
```
Input is an array `[num1 den1 num2 den2]`.
[Try it online!](https://tio.run/##y00syfn/P9LNyEotUjOlPEWr@P//aCMDBUMFQxMFQ9NYAA "MATL – Try It Online") Or [verify all test cases](https://tio.run/##y00syfmf8D/SzchKLVIzpTxFq/i/S8j/aBMFQwUgjuWKtgCyLMAsQwMgE0SA2EYgthGYDVILVA1kGYFVAPmmII6CoSXIDMtYAA).
### Explanation
Consider example input `[20 1 14 15]`.
```
YF      % Implicit input: array of 4 numbers. Exponents of prime factorization.
        % Gives a matrix, where each row corresponds to one of the numbers in
        % the input array. Each row may contain zeros for non-present factors
        % STACK: [2 0 1 0
                  0 0 0 0
                  1 0 0 1
                  0 1 1 0]
2:&Y)   % Push a submatrix with the first two rows, then a submatrix with the
        % other two rows
        % STACK: [2 0 1 0
                  0 0 0 0],
                 [1 0 0 1
                  0 1 1 0]
d       % Consecutive difference(s) along each column
        % STACK: [2 0 1 0
                  0 0 0 0],
                 [-1 1 -1 1]
wd      % Swap, and do the same for the other submatrix
        % STACK: [-1 1 -1 1]
                 [-2 0 -1 0]
*       % Element-wise product
        % STACK: [2 0 -1 0]
s       % Sum. Implicit display
        % STACK: 1
```
[Answer]
# [C (gcc)](https://gcc.gnu.org/), 99+32 = 131 bytes
* Using a compiler flag requiring 32 bytes, `-D=F(v,V,e)for(;v%p<1;V+=e)v/=p;`.
```
T,p,A,C;f(a,b,c,d){T=0;for(p=2;a+b+c+d>4;p++){A=C=0;F(a,A,1)F(b,A,~0)F(c,C,1)F(d,C,~0)T+=A*C;}a=T;}
```
[Try it online!](https://tio.run/##bZFNasMwEEbX7SlEICBVk9ojlIVRFDAuPoHJqhtbjkKgdURavDHu0etKdn/s0M08MdJjvkFmczJmGApwkEKmLC2hAgM16wodK3u5UqeFKnnFDa/3UjnOWZfqzF/m/m0KyHJaeX7E/mAgGxu1p28UXKcPmepLXah@eC3PDWXd/Z27npt3S1dERgTJI5mo92RdPzcrsJRIIAhjZUz9CRhPwsSZgHEQxroUxLcgbgUxCuJW@I2EEZH/RAqpFoL4iSQj3M4FMUWSgNvlBBFhMi3tOZ8gAJOwNCZB6IdPY1/K09uwedI5beEARxb@Q7Vrt0N14PrI2kg79QU "C (gcc) – Try It Online")
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), ~~12~~ 11 bytes
```
ÆEz0_2/€P€S
```
[Try it online!](https://tio.run/##y0rNyan8//9wm2uVQbyR/qOmNQFAHPz/cDuQivz/P5pLIdpER8FQRwFExuoAuRZgrgWMa2gA5oMpiIARRMAIJgDRDzICzDWCagAJm8ZyxQIA "Jelly – Try It Online")
[Answer]
# [Python 2](https://docs.python.org/2/), 110 bytes
```
l=input()
p=t=2
while~-max(l):r=i=0;exec"while l[i]%p<1:l[i]/=p;r+=1j**i\ni+=1\n"*4;t+=r*r;p+=1
print t.imag/2
```
[Try it online!](https://tio.run/##HY1BDoIwEEX3PQUhMYGCYhs2UuckwIKYRsaUMpmMETdeHavJW7y8v/j0lnmNdt8DYKSnFKUiELDqNWPwn@MybUUoOwaEs/Obv@X/IQs9jge6mu4nDZDjCsxDaxwiJhtirlsnFbBmRykoYoySyQmX6d6kv97WbW0uifEL "Python 2 – Try It Online")
Takes input like `[num1, num2, den1, den2]`. Uses a complex number `r` to store the entries for prime `p` for the two rationals, and `(r*r).imag/2` to extract their product `r.real*r.imag` within overall the sum `t`. Adding `1j**i` for `i=0,1,2,3` does each combination of incrementing or decrementing the real or imaginary part for the four input numbers.
*Bubbler saved 2 bytes combining the initial values `p=t=2`.* 
[Answer]
# [Wolfram Language (Mathematica)](https://www.wolfram.com/wolframscript/), 55 bytes
```
Dot@@PadRight[SparseArray[Rule@@@FactorInteger@#]&/@#]&
```
[Try it online!](https://tio.run/##HYvNCoMwEIRfZVHwlBIjFuyhsoVS6E3sMXhYbPyBqiXdHor47GniZeYbZmYiHsxEPLbkOjiDuy6MWNGzHvuB9eNN9mMu1tJP19@XQcQbtbzY@8ymNxbjJpFBXGXHmXUsIIJDCZGATsdNAwlIhHXNBeSbgLUQUARXqQCV7pR5ygL5jZL7KgttLtVxD1Kd/Nvrtrk/ "Wolfram Language (Mathematica) – Try It Online")
[Answer]
# [JavaScript (Node.js)](https://nodejs.org), ~~104~~ ... ~~100~~ 94 bytes
```
F=(A,i=2)=>A.some(x=>x>1)&&([a,b,c,d]=A.map(G=(x,j)=>x%i?0:1+G(A[j]/=i,j)),a-b)*(c-d)+F(A,i+1)
```
[Try it online!](https://tio.run/##bc7NDoIwDAfwu@8h6aQgWzQBzTC7wEMQDuMjZgQYEWP29nPzaHZoD/3903aSH7n3L7W9k1UPo7UVB4GKM8JLke56GcHw0pSURBE0EjvscWi5SBe5Qc3B4OSS5qge2Y3GNYhmas9cuSlBmXTkBH0ykLjyS2NK7L3X667nMZ31EypoLkjRVUvI4Z9yR3mYaObMtyAyjyyM/p67GCL2W@oC16AiLfynhUP7BQ "JavaScript (Node.js) – Try It Online")
Pass the numbers as an array of [Num1, Den1, Num2, Den2].
Thanks for Arnauld for fixing the missing `F=` with no extra bytes, and 2 more bytes less.
## Explanation & ungolfed
```
function F(A, i = 2) {                 // Main function, recursing from i = 2
 if (A.some(function(x) {              // If not all numbers became 1:
  return x > 1;
 })) {
  var B = A.map(G = function(x, j) {   // A recursion to calculate the multiplicity
   if (x % i)
    return 0;
   else
    return 1 + G(A[j] /= i, j);        // ...and strip off all powers of i
  });
  return (B[0] - B[1]) * (B[2] - B[3]) // Product at i
   + F(A, i + 1);                      // Proceed to next factor. All composite factors 
 }                                     // will be skipped effectively
 else 
  return 0;                            // Implied in the short-circuit &&
}
```
[Answer]
# [J](http://jsoftware.com/), 19 bytes
```
1#.*/@,:&([:-/_&q:)
```
[Try it online!](https://tio.run/##y/qvpKeepmBrpaCuoKNgoGAFxLp6Cs5BPm7/DZX1tPQddKzUNKKtdPXj1QqtNP9rcilwpSZn5CuYKBgqpIFICNcCzLWAcQ0NwHwQBRUwgggYwQQg@g0VTCBcI6gGoLApVETB0BJmhyUX138A "J – Try It Online")
## Explanation:
A dyadic verb, arguments are on both left hand and right hand side
```
         &(        ) - for both arguments (which are lists of 2 integers)
               _&q:  - decompose each number to a list of prime exponents
           [:-/      - and find the difference of these lists
       ,:            - laminate the resulting lists for both args (to have the same length)
   */@               - multiply them
1#.                  - add up 
```
[Answer]
# [Stax](https://github.com/tomtheisen/stax), 11 [bytes](https://github.com/tomtheisen/stax/blob/master/docs/packed.md#packed-stax)
```
ä÷ß½♂←√:=Ü]
```
[Run and debug it](https://staxlang.xyz/#c=%C3%A4%C3%B7%C3%9F%C2%BD%E2%99%82%E2%86%90%E2%88%9A%3A%3D%C3%9C%5D&i=%5B4%2C1%2C+4%2C1%5D%0A%5B8%2C1%2C+8%2C1%5D%0A%5B10%2C1%2C+10%2C1%5D%0A%5B12%2C1%2C+12%2C1%5D%0A%5B4%2C1%2C+1%2C4%5D%0A%5B20%2C1%2C+14%2C15%5D%0A%5B2%2C19%2C+4%2C19%5D&a=1&m=2)
The corresponding ascii representation of the same program is this.
```
{|nmMFE-~-,*+
```
Basically, it gets the prime factorization's exponents for each part. It takes the difference of each pair, then the product, and finally sums all the results.
[Answer]
# [Python 2](https://docs.python.org/2/), 133 127 bytes
```
a=input();s=0;p=2;P=lambda n,i=0:n%p and(n,i)or P(n/p,i+1)
while~-max(a):a,(w,x,y,z)=zip(*map(P,a));s+=(w-x)*(y-z);p+=1
print s
```
[Try it online!](https://tio.run/##Hc7BioMwEAbgu08xsCwmGlmTtWCUvIP30kO2Bhqo6dBajB766u7EwwzfDzPD4DrfHkHtLrprnue7NT7ge2a8f5m6R6P6wdzt9DdaCMKbugvfCDaMjBJ/PGFg4QeFLyXPlpu/u0812cgs76xgi4hiFRs3m0dWTBbZICyny6VhSxV5wdZq4z2WRmb49GGG104/QAFt9gUuorvObuygAU2l4ARVAxJ@93MjpKC6ZOeW1B7SJH1I1sTUklWyOpy2aI@kjgnKpxSE1OmavvwD "Python 2 – Try It Online")
Stole the loop condition from [xnor's submission](https://codegolf.stackexchange.com/a/156598/78410).
Thanks for the advice by @mathmandan to change the function into a program (Yes, it indeed saved some bytes).
Obsolete, incorrect solution (124 bytes):
```
lambda w,x,y,z:sum((P(w,p)-P(x,p))*(P(y,p)-P(z,p))for p in[2]+range(3,w+x+y+z,2))
P=lambda n,p,i=1:n%p and i or P(n/p,p,i+1)
```
[Answer]
# [Haskell](https://www.haskell.org/), 153 bytes
```
(2%)
n%m|all(<2)m=0|(k,[a,b,c,d])<-unzip[(,)=<<div x.max 1.(n*)$until((>0).mod x.(n^))(+1)1-1|x<-m]=(a-b)*(c-d)+[i|i<-[n..],all((>0).rem i)[2..i-1]]!!1%k
```
[Try it online!](https://tio.run/##LY1NTsMwEEb3PsUgUclubTdjUimREjaskbpEMkZymxasxqbqD6ognIs9ByPYSRcevzeez/Nmj7tN2/bb@rmnasJImPjOti2tFPN11tEd15av@Jo3hlXiHD7dXlPO6qpq3AdcpLcXQEnDlN2ew8m1lN5nTPr3Jr7R8MIYnSFDgd2lEt7U1IoVm9K1aNhMu85VQgcpDU8rh@Rh48ExraR0Ao25ucHJrvfWBajB2/0j0P3BhRNI2DLQBHTOkcdjeOQicnFlzKKkMppKpq6WMjE1sBrmYmcxKscy/VcaQ8iXIDn8/kAel@ekSFhELAlmiWOtQRFUg6goi3Ee5ykhcqLGuXyOi9hAouZYDh@mu4Y7Ir77v/W2ta/HXjw9LJf/ "Haskell – Try It Online") Example usage for `20 · 14/15`: `(2%) [20,1,14,15]`.
]