< Return to Video

Arithmetic algorithms (13 min)

  • 0:00 - 0:05
    The next thing we're going to look at is
    how to compute modular large integers. So
  • 0:05 - 0:09
    the first question is how do we represent
    large integers in a computer? So that's
  • 0:09 - 0:14
    actually fairly straightforward. So
    imagine we're on a 64 bit machine, what we
  • 0:14 - 0:18
    would do is we would break the number we
    want to represent, into 32 bit buckets And
  • 0:18 - 0:23
    then, we will basically have these n/32 bit buckets, and together they will
  • 0:23 - 0:27
    represent the number that we want to store
    on the computer. Now, I should mention
  • 0:27 - 0:31
    that I'm only giving 64 bit registers as
    an example. In fact, many modern
  • 0:31 - 0:35
    processors have 128 bit registers or more,
    and you can even do multiplications on
  • 0:35 - 0:39
    them. So normally you would actually use
    much larger blocks than just 32 bits. The
  • 0:39 - 0:43
    reason, by the way, you want to limit
    yourself to 32 bits is so that you can
  • 0:43 - 0:47
    multiply two blocks together, and the
    result will still be less than 64 bits,
  • 0:47 - 0:51
    less than the word size on the machine. So
    now let's look at particular arithmetic
  • 0:51 - 0:55
    operations and see how long each one
    takes. So addition and subtraction
  • 0:55 - 0:59
    basically what you would do is that
    addition would carry or subtraction would
  • 0:59 - 1:03
    borrow and those are basically linear time
    operations. In other words, if you want to
  • 1:03 - 1:07
    add or subtract two n bit integers the
    running time is basically
  • 1:07 - 1:13
    linear in n. Multiplication
    naively will take quadratic time. In fact,
  • 1:13 - 1:17
    this is what's called the high school
    algorithm. This is what you kind of
  • 1:17 - 1:21
    learned in school, where if you think
    about this for a minute you'll see that,
  • 1:21 - 1:26
    that algorithm basically is quadratic in
    the length of the numbers that are being
  • 1:26 - 1:30
    multiplied. So a big surprise in the 1960s
    was an algorithm due to Karatsuba that
  • 1:30 - 1:34
    actually achieves much better than
    quadratic time in fact, it achieved a
  • 1:34 - 1:39
    running time of n to the 1.585. And
    there's actually no point in me showing
  • 1:39 - 1:43
    you how the algorithm actually worked,
    I'll just mention the main idea What
  • 1:43 - 1:48
    Karatsuba realized, is that in fact when
    you want to multiply two numbers, you can
  • 1:48 - 1:53
    write them as, you can take the first
    number x, write it as 2 to the b times
  • 1:53 - 1:58
    x2 plus x1. Where x2 and x1 are roughly
    the size of the square root of x. Okay, so
  • 1:58 - 2:03
    we can kind of break the number x into the
    left part of x and the right part of x.
  • 2:03 - 2:08
    And basically, you're writing x as if it
    was written base 2 to the b. So it's got
  • 2:08 - 2:12
    two digits base 2 to the b. And you do
    the same thing with, y. You write y base
  • 2:12 - 2:17
    2 to the b. Again, you would write it
    as, the sum of the left half plus the
  • 2:17 - 2:22
    right half, And then, normally, if you try
    to do this multiplication, when you open
  • 2:22 - 2:27
    up the parentheses. You see that, this
    would require 4 multiplications, right?
  • 2:27 - 2:33
    It would require x2 times y2, x2 times y1,
    x1 times y2, and x1 times y1. What
  • 2:33 - 2:40
    Karatsuba realized is there's a way to do
    this multiplication of x by y using only
  • 2:40 - 2:46
    three multiplications of x1 x2 y1 y2. So it's just a big multiplication of x times y
  • 2:46 - 2:50
    only it takes three little multiplications. You can now recursively
  • 2:50 - 2:55
    apply exactly the same procedure to
    multiplying x2 by y2, and x2 by y1, and so
  • 2:55 - 3:00
    on and so forth. And you would get this
    recursive algorithm. And if you do the
  • 3:00 - 3:05
    recursive analysis, you will see that
    basically, you get a running time of n to the 1.585.
  • 3:05 - 3:14
    This number is basically, the 1.585 is basically, log of 3 base 2.
  • 3:14 - 3:18
    Surprisingly, it turns out that Karatsuba
    isn't even the best multiplication
  • 3:18 - 3:24
    algorithm out there. It turns out that, in fact, you can do multiplication in about n*log(n) time.
  • 3:24 - 3:29
    So you can do multiplication in almost linear time. However, this is an extremely asymptotic results.
  • 3:29 - 3:31
    The big O here hides very big constants. And as a
  • 3:31 - 3:35
    result, this algorithm only becomes
    practical when the numbers are absolutely
  • 3:35 - 3:39
    enormous. And so this algorithm is
    actually not used very often. But
  • 3:39 - 3:43
    Karatsuba's algorithm is very practical.
    And in fact, most crypto-libraries
  • 3:43 - 3:48
    implement Karatsuba's algorithm for
    multiplication. However, for simplicity
  • 3:48 - 3:52
    here, I'm just gonna ignore Karatsuba's
    algorithm, and just for simplicity, I'm
  • 3:52 - 3:56
    gonna assume that multiplication runs in
    quadratic time. But in your mind, you
  • 3:56 - 4:00
    should always be thinking all multiplication really is a little bit faster than quadratic.
  • 4:00 - 4:05
    And then the next question after multiplication is what about
  • 4:05 - 4:10
    division with remainder and it turns out
    that's also a quadratic time algorithm.
  • 4:10 - 4:15
    So the main operation that remains, and one
    that we've used many times so far, and
  • 4:15 - 4:20
    I've never, actually never, ever told you
    how to actually compute it, is this
  • 4:20 - 4:26
    question of exponentiation. So let's solve
    this exponentiation problem a bit more
  • 4:26 - 4:32
    abstractly. So imagine we have a finite
    cyclic group G. All this means is that
  • 4:32 - 4:37
    this group is generated from the powers of
    some generator little g. So for example
  • 4:37 - 4:43
    think of this group as simply ZP*, and think of little g as some generator of
  • 4:43 - 4:49
    big G. The reason I'm sitting in this way,
    is I'm, I want you to start getting used
  • 4:49 - 4:54
    to this abstraction where we deal with a
    generic group G and ZP* really is just
  • 4:54 - 4:59
    one example of such a group. But, in fact,
    there are many other examples of finite
  • 4:59 - 5:03
    cyclic groups. And again I want to
    emphasis basically that group G, all it
  • 5:03 - 5:08
    is, it's simply this powers of this
    generator up to the order of the group.
  • 5:08 - 5:15
    I'll write it as G to the Q. So our goal
    now is given this element g, and some
  • 5:15 - 5:21
    exponent x, our goal is to compute the
    value of g to the x. Now normally what you
  • 5:21 - 5:25
    would say is, you would think well, you
    know, if x is equal to 3 then I'm
  • 5:25 - 5:29
    gonna compute you know, g cubed. Well,
    there's really nothing to do. All I do is
  • 5:29 - 5:33
    I just do g times g times g and I get g
    cubed, which is what I wanted. So that's
  • 5:33 - 5:37
    actually pretty easy. But in fact, that's
    not the case that we're interested in. In
  • 5:37 - 5:41
    our case, our exponents are gonna be
    enormous. And so if you try, you know,
  • 5:41 - 5:46
    think of like a 500-bit number and so if
    you try to compute g to the power of a
  • 5:46 - 5:51
    500-bit number simply by multiplying g by
    g by g by g this is gonna take quite a
  • 5:51 - 5:56
    while. In fact it will take exponential
    time which is not something that we want
  • 5:56 - 6:01
    to do. So the question is whether even
    though x is enormous, can we still compute
  • 6:01 - 6:06
    g to the x relatively fast and the answer
    is yes and the algorithm that does that
  • 6:06 - 6:11
    is called a repeated squaring algorithm.
    And so let me show you how repeated
  • 6:11 - 6:16
    squaring works. So let's take as an
    example, 53. Naively you would have to do
  • 6:16 - 6:20
    53 multiplications of g by g by g by g
    until you get to g by the 53 but I want to
  • 6:20 - 6:25
    show you how you can do it very quickly.
    So what we'll do is we'll write 53 in
  • 6:25 - 6:30
    binary. So here this is the binary
    representation of 53. And all that means
  • 6:30 - 6:36
    is, you notice this one corresponds to 32,
    this one corresponds to 16, this one
  • 6:36 - 6:41
    corresponds to 4, and this one
    corresponds to 1. So really 53 is 32
  • 6:41 - 6:47
    plus 16 plus 4 plus 1. But what
    that means is that g to the power of 53 is
  • 6:47 - 6:52
    g to the power of 32+16+4+1. And we can
    break that up, using again, the rules of
  • 6:52 - 6:57
    exponentiation. We can break that up as g
    to the 32 times g to the 16 times g to the
  • 6:57 - 7:03
    4 times g to the 1, Now that should start
    giving you an idea for how to compute g to
  • 7:03 - 7:07
    the 53 very quickly. What we'll do is,
    simply, we'll take g and we'll start
  • 7:07 - 7:11
    squaring it. So what square wants, g wants
    to get g squared. We square it again to
  • 7:11 - 7:16
    get g to the 4, turn g to the 8.
    Turn g to the 16, g to the 32. So
  • 7:16 - 7:21
    we've computed all these squares of g. And
    now, what we're gonna do is we're simply
  • 7:21 - 7:26
    gonna multiply the appropriate powers to
    give us the g to the 53. So this is g to
  • 7:26 - 7:30
    the one times g to the 4 times g to the 16 times g to the 32, is basically
  • 7:30 - 7:35
    gonna give us the value that we want,
    which is g to the 53. So here you see that
  • 7:35 - 7:40
    all we had to do was just compute, let's
    see, we had to do one, two, three, four,
  • 7:40 - 7:49
    five squaring, plus four more multiplications
    so with 9 multiplications we computed g
  • 7:49 - 7:54
    to the 53. Okay so that's pretty
    interesting. And it turns out this is a
  • 7:54 - 7:58
    general phenomena that allows us to raise
    g to very, very high powers and do it very
  • 7:58 - 8:03
    quickly. So let me show you the algorithm,
    as I said this is called the repeated
  • 8:03 - 8:06
    squaring algorithm. So the input to the
    algorithm is the element g and the
  • 8:06 - 8:11
    exponent x. And the output is g to the x.
    So what we're gonna do is we're gonna
  • 8:11 - 8:15
    write x in binary notation. So let's say
    that x has n bits. And this is the actual
  • 8:15 - 8:20
    bit representation of x as a binary
    number. And then what we'll do is the
  • 8:20 - 8:24
    following. We'll have these two registers.
    y is gonna be a register that's constantly
  • 8:24 - 8:28
    squared. And then z is gonna be an
    accumulator that multiplies in the
  • 8:28 - 8:33
    appropriate powers of g as needed. So all
    we do is the following we loop through the
  • 8:33 - 8:37
    bits of x starting from the least
    significant bits, And then we do the
  • 8:37 - 8:41
    following: in every iteration we're simply
    gonna square y. Okay, so y just keeps on
  • 8:41 - 8:46
    squaring at every iteration. And then
    whenever the corresponding bit of the
  • 8:46 - 8:51
    exponent x happens to be one, we simply
    accumulate the current value of y into
  • 8:51 - 8:55
    this accumulator z and then at the end, we
    simply output z. That's it. That's the
  • 8:55 - 9:00
    whole algorithm, and that's the repeated
    squaring algorithm. So, let's see an
  • 9:00 - 9:04
    example with G to the 53. So,
    you can see the two columns. y is one
  • 9:04 - 9:08
    column, as it evolves through the
    iterations, and z is another column, again
  • 9:08 - 9:13
    as it evolves through the iterations. So,
    y is not very interesting. Basically, all
  • 9:13 - 9:17
    that happens to y is that at every
    iteration, it simply gets squared. And so
  • 9:17 - 9:22
    it just walks through the powers of two
    and the exponents and that's it. z is the
  • 9:22 - 9:27
    more interesting register where what it
    does is it accumulates the appropriate
  • 9:27 - 9:32
    powers of g whenever the corresponding bit
    to the exponent is one. So for example the
  • 9:32 - 9:36
    first bit of the exponent is one,
    therefore, the, at the end of the first
  • 9:36 - 9:41
    iteration the value of z is simply equal to
    g. The second bit of the exponent is zero
  • 9:41 - 9:46
    so the value of z doesn't change after the
    second iteration. And at the end of the
  • 9:46 - 9:52
    third iteration well the third bit of the
    exponent is one so we accumulate g to the
  • 9:52 - 9:57
    fourth into z. The next bit of the
    exponent is zero so z doesn't change. The
  • 9:57 - 10:02
    next bit of the exponent is one and so now
    we're supposed to accumulate the previous
  • 10:02 - 10:07
    value of y into the accumulator z so let
    me ask you so what's gonna be the value of z?
  • 10:11 - 10:14
    Well, we simply accumulate g to the
    16 into z and so we simply compute the sum
  • 10:14 - 10:20
    of 16 and 5 we get g to the 21.
    Finally, the last bit is also set to one
  • 10:20 - 10:25
    so we accumulate it into z, we do 32 plus 21 and we get the finally output g to the 53.
  • 10:25 - 10:30
    Okay, so this gives you an idea of how
    this repeated squaring algorithm works.
  • 10:30 - 10:36
    It's is quite an interesting algorithm and
    it allows us to compute enormous powers of
  • 10:36 - 10:41
    g very, very, very quickly. So the number
    of iterations here, essentially, would be
  • 10:41 - 10:46
    log base 2 of x. Okay. You notice the
    number of iterations simply depends on the
  • 10:46 - 10:52
    number of digits of x, which is basically
    the log base 2 of x. So even if x is a
  • 10:52 - 10:57
    500 bit number in 500 multiplication,
    well, 500 iterations, really 1,000
  • 10:57 - 11:02
    multiplications because we have to square
    and we have to accumulate. So in 1,000
  • 11:02 - 11:07
    multiplications we'll be able to raise g
    to the power of a 500 bit exponent.
  • 11:07 - 11:13
    Okay so now we can summarize kind of the running times so suppose we
  • 11:13 - 11:18
    have an N bit modulus capital N as we
    said addition and subtraction in ZN takes
  • 11:18 - 11:22
    linear time. Multiplication of just, you
    know, as I said, Karatsuba's actually makes this
  • 11:22 - 11:27
    more efficient, but for simplicity we'll
    just say that it takes quadratic time. And
  • 11:27 - 11:32
    then exponentiation, as I said, basically
    takes log of x iterations, and at each
  • 11:32 - 11:36
    iteration we basically do two
    multiplications. So it's O(log (x))
  • 11:36 - 11:40
    times the time to multiply. And let's say
    that the time to multiply is quadratic. So
  • 11:40 - 11:45
    the running time would be, really, N
    squared log x. And since x is always gonna
  • 11:45 - 11:49
    be less than N, by Fermat's theorem
    there's no point in raising g to a power
  • 11:49 - 11:54
    that's larger than the modulus. So x is
    gonna be less than N. Let's suppose that x
  • 11:54 - 11:59
    is also an N-bit integer, then, really
    exponentiation is a cubic-time algorithm.
  • 11:59 - 12:03
    Okay so that's what I wanted you to
    remember, that exponentiation is actually
  • 12:03 - 12:07
    a relatively slow. These days, it actually
    takes a few microseconds on a modern
  • 12:07 - 12:11
    computer. But still, microseconds for a,
    for a, say a four gigahertz processor is
  • 12:11 - 12:15
    quite a bit of work. And so just keep in
    mind that all the exponentiation
  • 12:15 - 12:20
    operations we talked about. For example,
    for determining if a number is a quadratic
  • 12:20 - 12:24
    residue or not, All those, all those
    exponentiations basically take cubic time.
  • 12:25 - 12:30
    Okay, so that completes our discussion of
    arithmetic algorithms, and then in the
  • 12:30 - 12:34
    next segment we'll start talking about
    hard problems, modulo, primes and composites.
Title:
Arithmetic algorithms (13 min)
Video Language:
English

English subtitles

Revisions