Dot product
Create a function/use an in-built function, to compute the dot product, also known as the scalar product of two vectors. If possible, make the vectors of arbitrary length.
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
You are encouraged to solve this task according to the task description, using any language you may know.
As an example, compute the dot product of the vectors [1, 3, -5]
and [4, -2, -1]
.
If implementing the dot product of two vectors directly, each vector must be the same length; multiply corresponding terms from each vector then sum the results to produce the answer.
ActionScript
<lang ActionScript>function dotProduct(v1:Vector.<Number>, v2:Vector.<Number>):Number { if(v1.length != v2.length) return NaN; var sum:Number = 0; for(var i:uint = 0; i < v1.length; i++) sum += v1[i]*v2[i]; return sum; } trace(dotProduct(Vector.<Number>([1,3,-5]),Vector.<Number>([4,-2,-1])));</lang>
ALGOL 68
<lang algol68>MODE DOTFIELD = REAL; MODE DOTVEC = [1:0]DOTFIELD;
- The "Spread Sheet" way of doing a dot product:
o Assume bounds are equal, and start at 1 o Ignore round off error
PRIO SSDOT = 7; OP SSDOT = (DOTVEC a,b)DOTFIELD: (
DOTFIELD sum := 0; FOR i TO UPB a DO sum +:= a[i]*b[i] OD; sum
);
- An improved dot-product version:
o Handles sparse vectors o Improves summation by gathering round off error with no additional multiplication - or LONG - operations.
OP * = (DOTVEC a,b)DOTFIELD: (
DOTFIELD sum := 0, round off error:= 0; FOR i
- Assume bounds may not be equal, empty members are zero (sparse) #
FROM LWB (LWB a > LWB b | a | b ) TO UPB (UPB a < UPB b | a | b ) DO DOTFIELD org = sum, prod = a[i]*b[i]; sum +:= prod; round off error +:= sum - org - prod OD; sum - round off error
);
- Test: #
DOTVEC a=(1,3,-5), b=(4,-2,-1);
print(("a SSDOT b = ",fixed(a SSDOT b,0,real width), new line)); print(("a * b = ",fixed(a * b,0,real width), new line))</lang> Output:
a SSDOT b = 3.000000000000000 a * b = 3.000000000000000
C
<lang c>#include <stdio.h>
- include <stdlib.h>
int dot_product(int *, int *, size_t);
int main(void) {
int a[3] = {1, 3, -5}; int b[3] = {4, -2, -1};
printf("%d\n", dot_product(a, b, sizeof(a) / sizeof(a[0])));
return EXIT_SUCCESS;
}
int dot_product(int *a, int *b, size_t n) {
int sum = 0; size_t i;
for (i = 0; i < n; i++) { sum += a[i] * b[i]; }
return sum;
}</lang> Output: <lang>3</lang>
C++
<lang cpp>#include <iostream>
- include <numeric>
int main() {
int a[] = { 1, 3, -5 }; int b[] = { 4, -2, -1 };
std::cout << std::inner_product(a, a + sizeof(a) / sizeof(a[0]), b, 0) << std::endl;
return 0;
}</lang> Output: <lang>3</lang>
Clojure
Preconditions are new in 1.1. The actual code also works in older Clojure versions.
<lang clojure>(defn dot-product [c1 c2]
{:pre [(== (count c1) (count c2))]} (reduce + (map * c1 c2)) )
(println (dot-product [1 3 -5] [4 -2 -1]))</lang>
Factor
The built-in word v.
is used to compute the dot product. It doesn't enforce that the vectors are of the same length, so here's a wrapper.
<lang factor>USING: kernel math.vectors sequences ;
- dot-product ( u v -- w )
2dup [ length ] bi@ = [ v. ] [ "Vector lengths must be equal" throw ] if ;</lang>
( scratchpad ) { 1 3 -5 } { 4 -2 -1 } dot-product . 3
Forth
<lang forth>: vector create cells allot ;
- th cells + ;
3 constant /vector /vector vector a /vector vector b
- dotproduct ( a1 a2 -- n)
0 tuck ?do -rot over i th @ over i th @ * >r rot r> + loop nip nip
- vector! cells over + swap ?do i ! 1 cells +loop ;
-5 3 1 a /vector vector! -1 -2 4 b /vector vector!
a b /vector dotproduct . 3 ok</lang>
Fortran
<lang fortran>program test_dot_product
write (*, '(i0)') dot_product ((/1, 3, -5/), (/4, -2, -1/))
end program test_dot_product</lang> Output: <lang>3</lang>
Haskell
<lang haskell>dotp a b | length a == length b = sum (zipWith (*) a b)
| otherwise = error "Vector sizes must match"
main = print $ dotp [1, 3, -5] [4, -2, -1] -- prints 3</lang>
J
<lang j> 1 3 _5 +/ . * 4 _2 _1 3
dotp=: +/ . * NB. Or defined as a verb (function) 1 3 _5 dotp 4 _2 _1
3</lang>
The conjunction .
applies generally to matricies and arrays of higher dimensions and can be used with verbs (functions) other than sum ( +/
) and product ( *
).
Java
<lang java> public class DotProduct {
public static void main(String[] args) { double[] a = {1, 3, -5}; double[] b = {4, -2, -1};
System.out.println(dotProd(a,b)); }
public static double dotProd(double[] a, double[] b){ if(a.length != b.length){ throw new IllegalArgumentException("The dimensions have to be equal!"); } double sum = 0; for(int i = 0; i < a.length; i++){ sum += a[i] * b[i]; } return sum; } }
</lang>
Output: <lang>3.0</lang>
Logo
<lang logo>to dotprod :a :b
output apply "sum (map "product :a :b)
end
show dotprod [1 3 -5] [4 -2 -1] ; 3</lang>
Lua
<lang lua>function dotprod(a, b)
local ret = 0 for i = 1, #a do ret = ret + a[i] * b[i] end return ret
end
print(dotprod({1, 3, -5}, {4, -2, 1}))</lang>
MATLAB
<lang> function c=DotPro(a,b) c=a.*b; end </lang>
OCaml
<lang ocaml>let dot a b =
let n = Array.length a in if n <> Array.length b then failwith "arrays are not the same length"; let rec g s = function | 0 -> s | i -> g (s +. a.(i-1)*.b.(i-1)) (i-1) in g 0.0 n
dot [| 1.0; 3.0; -5.0 |] [| 4.0; -2.0; -1.0 |];; (* - : float = 3. *)</lang>
Oz
Vectors are represented as lists in this example. <lang oz>declare
fun {DotProduct Xs Ys} {Length Xs} = {Length Ys} %% assert {List.foldL {List.zip Xs Ys Number.'*'} Number.'+' 0} end
in
{Show {DotProduct [1 3 ~5] [4 ~2 ~1]}}</lang>
Perl
<lang perl>sub dotprod (\@\@) {
my($vec_a, $vec_b) = @_; die "they must have the same size\n" unless @$vec_a == @$vec_b; my $sum = 0; $sum += $vec_a->[$_]*$vec_b->[$_] for 0..$#$vec_a; return $sum;
}
my @vec_a = (1,3,-5); my @vec_b = (4,-2,-1);
print dotprod(@vec_a,@vec_b), "\n"; # 3</lang>
Perl 6
Computing the dot product with Perl6 meta operators:
<lang perl6>sub dotProduct( @a, @b ) returns Int { [+] ( @a <<*>> @b ) }
print dotProduct( (1,3,-5), (4,-2,-1) );</lang>
PL/I
<lang PL/I> get (n); begin;
declare (A(n), B(n)) float; declare dot_product float;
get list (A); get list (B); dot_product = sum(a*b); put (dot_product);
end; </lang>
PureBasic
<lang PureBasic>Procedure dotProduct(Array a.i(1), Array b.i(1), length.i)
Protected result.i, i.i For i = 0 To length - 1 result + a(i) * b(i) Next ProcedureReturn result
EndProcedure
Dim a.i(2) a(0) = 1 : a(1) = 3 : a(2) = -5 Dim b.i(2) b(0) = 4 : b(1) = -2 : b(2) = -1
Debug dotProduct(a(), b(), 3) </lang>
Python
<lang python>def dotp(a,b):
assert len(a) == len(b), 'Vector sizes must match' return sum(aterm * bterm for aterm,bterm in zip(a, b))
if __name__ == '__main__':
a, b = [1, 3, -5], [4, -2, -1] assert dotp(a,b) == 3</lang>
R
Here are several ways to do the task.
<lang R> x <- c(1, 3, -5) y <- c(4, -2, -1)
sum(x*y) # compute products, then do the sum x %*% y # inner product
- loop implementation
dotp <- function(x, y) { n <- length(x) if(length(y) != n) stop("invalid argument") s <- 0 for(i in 1:n) s <- s + x[i]*y[i] s }
dotp(x, y) </lang>
Ruby
<lang ruby>class Array
def dot_product(other) raise "not the same size!" if self.length != other.length self.zip(other).inject(0) {|dp, (a, b)| dp += a*b} end
end
p [1, 3, -5].dot_product [4, -2, -1] # => 3</lang>
Scheme
<lang scheme>(define (dot-product a b)
(apply + (map * a b)))
(display (dot-product (list 1 3 -5) (list 4 -2 -1))) (newline)</lang> Output: <lang>3</lang>
Smalltalk
<lang smalltalk>Array extend [
* anotherArray [ |acc| acc := 0. self with: anotherArray collect: [ :a :b | acc := acc + ( a * b ) ]. ^acc ]
]
( #(1 3 -5) * #(4 -2 -1 ) ) printNl.</lang>
SNOBOL4
<lang snobol4> define("dotp(a,b)sum,i") :(dotp_end) dotp i = 1; sum = 0 loop sum = sum + (a * b)
i = i + 1 ?a :s(loop) dotp = sum :(return)
dotp_end
a = array(3); a<1> = 1; a<2> = 3; a<3> = -5; b = array(3); b<1> = 4; b<2> = -2; b<3> = -1; output = dotp(a,b)
end</lang>
Tcl
<lang tcl>package require math::linearalgebra
set a {1 3 -5} set b {4 -2 -1} set dotp [::math::linearalgebra::dotproduct $a $b] proc pp vec {return \[[join $vec ,]\]} puts "[pp $a] \u2219 [pp $b] = $dotp"</lang> Output:
[1,3,-5] ∙ [4,-2,-1] = 3.0
TI-89 BASIC
dotP([1, 3, –5], [4, –2, –1]) 3
Ursala
A standard library function for dot products of floating point numbers exists, but a new one can be defined for integers as shown using the map operator (*
) with the zip suffix (p
) to construct a "zipwith" operator (*p
), which operates on the integer product
function. A catchable exception is thrown if the list lengths are unequal. This function is then composed (+
) with a cumulative summation function, which is constructed from the binary sum
function, and the reduction operator (:-
) with 0
specified for the vacuous sum.
<lang Ursala>#import int
dot = sum:-0+ product*p
- cast %z
test = dot(<1,3,-5>,<4,-2,-1>)</lang> output:
3