#4446: New module complex_mpc using lib mpc for complex multiprecision 
arithmetic
-----------------------------------------------------------------+----------
   Reporter:  thevenyp                                           |       Owner: 
 mabshoff       
       Type:  enhancement                                        |      Status: 
 positive_review
   Priority:  major                                              |   Milestone: 
 sage-4.6       
  Component:  basic arithmetic                                   |    Keywords: 
                
     Author:  Philippe Theveny, Alex Ghitza, Yann Laigle-Chapuy  |    Upstream: 
 N/A            
   Reviewer:  William Stein, David Kirkby, Paul Zimmermann       |      Merged: 
                
Work_issues:                                                     |  
-----------------------------------------------------------------+----------
Changes (by zimmerma):

  * status:  needs_review => positive_review
  * reviewer:  William Stein, David Kirkby => William Stein, David Kirkby,
               Paul Zimmermann


Comment:

 Replying to [comment:52 was]:
 > I'm "out there".   Is it necessary and not slower than what is in Sage
 already?  I'm willing to take your (=Paul's) word for it, assuming you say
 you've done some benchmarks.   Also, rounding might be (vastly) better in
 mpc, which would be another point in its favor.

 William, here are some results of benchmarks I've done on my Core 2 Duo
 laptop, with Sage 4.5.3,
 with Yann latest patch and the associate spkg. Efficiency:
 {{{
 sage: K = MPComplexField(53)
 sage: a = K(3.3902384+1.23456789*i)
 sage: b = CC(3.3902384+1.23456789*i)
 sage: timeit('a*a')
 625 loops, best of 3: 1.03 µs per loop
 sage: timeit('b*b')
 625 loops, best of 3: 1.08 µs per loop # CC is slower
 sage: timeit('a+a')
 625 loops, best of 3: 566 ns per loop
 sage: timeit('b+b')
 625 loops, best of 3: 571 ns per loop # CC is slower

 sage: K=MPComplexField(1000)
 sage: a = K(3.3902384,9203483)
 sage: b = ComplexField(1000)(3.3902384,9203483)
 sage: timeit('a*a')
 625 loops, best of 3: 3.26 µs per loop
 sage: timeit('b*b')
 625 loops, best of 3: 2.99 µs per loop # CC is slightly faster
 sage: timeit('a+a')
 625 loops, best of 3: 680 ns per loop
 sage: timeit('b+b')
 625 loops, best of 3: 694 ns per loop # CC is slower
 sage: timeit('a.sin()')
 625 loops, best of 3: 294 µs per loop
 sage: timeit('b.sin()')
 625 loops, best of 3: 343 µs per loop # CC is slower

 sage: timeit('a+17')
 625 loops, best of 3: 2.56 µs per loop
 sage: timeit('b+17')
 625 loops, best of 3: 3.02 µs per loop # CC is slower

 sage: a2=a+17
 sage: b2=b+17
 sage: timeit('a/a2')
 625 loops, best of 3: 30.3 µs per loop
 sage: timeit('b/b2')
 625 loops, best of 3: 14.6 µs per loop

 sage: timeit('a.real()')
 625 loops, best of 3: 854 ns per loop
 sage: timeit('b.real()')
 625 loops, best of 3: 5.13 µs per loop

 sage: timeit('a.conjugate()')
 625 loops, best of 3: 736 ns per loop
 sage: timeit('b.conjugate()')
 625 loops, best of 3: 750 ns per loop
 sage: timeit('a.argument()')
 625 loops, best of 3: 146 µs per loop
 sage: timeit('b.argument()')
 625 loops, best of 3: 155 µs per loop

 sage: timeit('a**12345')
 625 loops, best of 3: 126 µs per loop
 sage: timeit('b**12345')
 625 loops, best of 3: 176 µs per loop

 sage: timeit('a.log()')
 625 loops, best of 3: 315 µs per loop
 sage: timeit('b.log()')
 625 loops, best of 3: 400 µs per loop

 sage: timeit('a.exp()')
 625 loops, best of 3: 221 µs per loop
 sage: timeit('b.exp()')
 625 loops, best of 3: 211 µs per loop
 }}}
 For the accuracy, I've computed the maximal relative error on the real or
 imaginary part after
 1000 random tries for several operations. My program also prints the
 inputs that give the
 corresponding maximal error:
 {{{
 multiplication:
 sage: foo(53) # 53 bits
 MPC:  1.09250136812570e-16 (-0.199676992382071 - 0.194223361415138*I,
 0.9413020\
 06592817 + 0.645200777306369*I)
 CC:   1.32263143752823e-14 (0.834168924383086 - 0.525629438090125*I,
 -0.4766533\
 42074290 + 0.752454804563813*I)
 sage: foo(100) # 100 bits
 MPC:  7.83034842148009e-31 (-0.43034701147206399980669837638 -
 0.81582963965013\
 399110093432939*I, -0.83969050263610625199834532314 +
 0.17390362688794167984134\
 423048*I)
 CC:   9.28509698731955e-29 (-0.36479911591428496460512307920 +
 0.22548928494028\
 018164534780632*I, -0.49018610148599010061638163259 -
 0.30229330441199619133786\
 980680*I)

 division:
 sage: foo(53)
 MPC:  1.08485488717363e-16 (0.906903106647522 + 0.991328300040510*I,
 0.26885465\
 0418765 - 0.188551687646414*I)
 CC:   4.27558190140949e-13 (-0.947451505768202 - 0.424071772860430*I,
 -0.499313\
 865619141 - 0.223444662259920*I)
 sage: foo(100)
 MPC:  7.66357970552281e-31 (0.92755016191057837385980632404 -
 0.004266231128213\
 8322794515257916*I, 0.14072961243734751540073515895 -
 0.21101836467335963334809\
 014965*I)
 CC:   1.06937889944401e-27 (-0.41008840630275384495897016614 +
 0.43420284734725\
 368743056683764*I, -0.61829368333881933443455346326 -
 0.58354470182146315365872\
 353144*I)

 sqrt:
 sage: foo(53)
 MPC:  1.09880191814582e-16 (-0.621894659027438 - 0.0246731753089378*I,
 0.823805\
 504837539 - 0.981310087843700*I)
 CC:   2.08688816342048e-16 (0.968316682679636 + 0.637686286592402*I,
 -0.2999297\
 58140749 + 0.680399103485303*I)
 sage: foo(100)
 MPC:  7.83762497864303e-31 (0.87484855451536280543412317489 +
 0.744936094843967\
 94278935970162*I, -0.93716227305934196720704783450 -
 0.765294741452728993051615\
 69068*I)
 CC:   1.59191232901277e-30 (0.22724304905610094307701469163 +
 0.290884560229311\
 05826353325335*I, -0.44728415428244253958062250934 +
 0.959404399673905010209671\
 68949*I)

 exp:
 sage: foo(53)
 MPC:  1.08513702552684e-16 (0.801188951612012 - 0.440834327392402*I,
 -0.6487549\
 15945509 - 0.558408459317570*I)
 CC:   2.56306731927053e-16 (-0.534146492930164 - 0.126305922104917*I,
 -0.525552\
 199671560 + 0.0746660767007601*I)
 sage: foo(100)
 MPC:  7.85000220770852e-31 (-0.25871533881495460870167038331 +
 0.70802010475507\
 807939080332669*I, 0.99833000148645085071979336755 +
 0.103046934118108408058895\
 43882*I)
 CC:   2.02731881365962e-30 (0.033507794108965175610485564405 +
 0.53119476356929\
 639125934355035*I, 0.46545588987697950055582059300 +
 0.896373882394705924442797\
 08331*I)

 log:
 sage: foo(53)
 MPC:  1.09778133774750e-16 (-0.391618732071762 + 0.824073966701766*I,
 0.3486864\
 59442427 - 0.191201122946134*I)
 CC:   6.10819034602284e-14 (0.306684274970498 + 0.953229884394732*I,
 0.69862405\
 1151183 + 0.276699733597418*I)
 sage: foo(100)
 MPC:  7.78374256155462e-31 (0.50154056740914466911692379172 +
 0.796641256036122\
 24316946320184*I, -0.76918900642484651661867461393 -
 0.286514343536794358035934\
 91438*I)
 CC:   6.82825438431515e-28 (-0.13721125119514449776575251187 +
 0.99010163436560\
 678238821778034*I, 0.92169332492985590698251634723 +
 0.433132422276759879534575\
 89642*I)

 sin:
 sage: foo(53)
 MPC:  1.08720457020742e-16 (-0.369315245123802 + 0.854572675318644*I,
 0.8169569\
 42853907 - 0.383919250130617*I)
 CC:   2.59601650874087e-16 (-0.546197856444743 - 0.534628610514192*I,
 0.3036961\
 63087668 - 0.231790426712382*I)
 sage: foo(100)
 MPC:  7.55871247471999e-31 (0.20947476591320905500539204843 -
 0.626588978693616\
 08926271268655*I, -0.55364821811403565597840750754 +
 0.743341403117384889712851\
 11372*I)
 CC:   1.72458459418951e-30 (0.42758001678856166974028750611 -
 0.923412131000390\
 51795327859750*I, -0.99149234221470907346167026703 -
 0.690427397584128136419461\
 37603*I)

 cos:
 sage: foo(53)
 MPC:  1.08584899379431e-16 (0.0646782540849349 - 0.111085748624151*I,
 0.4701880\
 86702821 + 0.252843262283133*I)
 CC:   2.85959441825441e-16 (0.0850486257569383 - 0.330860565935531*I,
 0.0564130\
 612472886 + 0.0847664237260943*I)
 sage: foo(100)
 MPC:  7.78394156732906e-31 (0.93946166432029710121550615978 -
 0.592139906105641\
 30050851821134*I, 0.53601265027477876871715914306 -
 0.1322166340317310632649551\
 5769*I)
 CC:   1.94260689254542e-30 (-0.55385187621901359297440670364 +
 0.50415610417338\
 788296133563973*I, -0.13371850315082336799522666801 -
 0.96241946806142646000989\
 112726*I)
 }}}
 I used the following programs:
 {{{
 def check(res,ref):
    if ref.real() == 0.0:
       if res.real() <> 0.0:
          err_real = +Infinity
       else:
          err_real = 0.0
    else:
       err_real = RR((res.real()-ref.real()).abs()/ref.real().abs())
    if ref.imag() == 0.0:
       if res.imag() <> 0.0:
          err_imag = +Infinity
       else:
          err_imag = 0.0
    else:
       err_imag = RR((res.imag()-ref.imag()).abs()/ref.imag().abs())
    return max(err_real,err_imag)

 def foo(p):
    K=MPComplexField(p)
    L=ComplexField(p)
    K2=MPComplexField(p+20)
    L2=ComplexField(p+20)
    max_erra = 0
    max_errb = 0
    ina = 0
    inb = 0
    for i in range(10^3):
       b = L.random_element()
       br = b.real()
       bi = b.imag()
       a = K(b)
       c = L.random_element()
       cr = b.real()
       ci = b.imag()
       d = K(c)
       aa=cos(a) # change to a*d for multiplication
       bb=cos(b) # change to b*c for multiplication
       ref = cos(K2(a)) # change to K2(a)*K2(d) for multiplication
       erra = check(K2(aa),ref)
       errb = check(K2(bb),ref)
       if erra > max_erra:
          max_erra = erra
          ina = a, d
       if errb > max_errb:
          max_errb = errb
          inb = b, c
    print "MPC: ", max_erra, ina
    print "CC:  ", max_errb, inb
 }}}
 The conclusion is that MPC is in the majority of the cases faster than
 ComplexField (the only
 exception being the division) and always more accurate, with a ratio of a
 factor up to
 3941 (i.e., about 12 bits) for the 53-bit division.

 For MPC we observe that the maximal relative error is --- as guaranteed by
 MPC --- always less than 1/2 ulp (unit in last place) which corresponds to
 a relative error of 2**(-p), i.e., 1.12e-16 for p=53 and 7.89e-31 for
 p=100.

 I thus give a positive review to Yann's patch.

 Paul

-- 
Ticket URL: <http://trac.sagemath.org/sage_trac/ticket/4446#comment:53>
Sage <http://www.sagemath.org>
Sage: Creating a Viable Open Source Alternative to Magma, Maple, Mathematica, 
and MATLAB

-- 
You received this message because you are subscribed to the Google Groups 
"sage-trac" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/sage-trac?hl=en.

Reply via email to