Skip to content

Instantly share code, notes, and snippets.

@asmeurer
Created October 29, 2011 18:16
Show Gist options
  • Save asmeurer/1324886 to your computer and use it in GitHub Desktop.
Save asmeurer/1324886 to your computer and use it in GitHub Desktop.
smichr/and as_numer_denom kernprof
Wrote profile results to t.py.lprof
Timer unit: 1e-06 s
File: sympy/core/add.py
Function: as_numer_denom at line 285
Total time: 17.2948 s
Line # Hits Time Per Hit % Time Line Contents
==============================================================
285 @profile
286 def as_numer_denom(self):
287 1 25 25.0 0.0 from sympy import gcd, cancel
288
289 10003 1552929 155.2 9.0 numers, denoms = [list(_) for _ in zip(*[f.as_numer_denom() for f in self.args])]
290 # for debugging
291 # no, do = self._as_numer_denom_expanded(numers, denoms)
292 1 4 4.0 0.0 g = G = S.One
293
294 # check for trivial case
295 1 4 4.0 0.0 denom = denoms[0]
296 1 54 54.0 0.0 if all(d == denom for d in denoms):
297 n, d = Add(*numers), denom
298 g, d = d.as_content_primitive()
299
300 # If all denoms are Number use the binary method: this doesn't lead to nesting
301 # because the Numbers auto-distribute on the nested terms
302 1 9 9.0 0.0 elif all(d.is_Number for d in denoms):
303 n, d = self._as_numer_denom_binary(numers, denoms)
304
305 else:
306 # simple gcd extraction (no factoring beyond primitive nor expanding)
307 10001 71604 7.2 0.4 denoms = [list(d.as_content_primitive()) for d in denoms]
308
309 1 3 3.0 0.0 g = G = S.Zero
310 1 4 4.0 0.0 hit = True
311 2 11 5.5 0.0 for i, d in enumerate(denoms):
312 2 1522 761.0 0.0 g = gcd(g, d[0])
313 6 86 14.3 0.0 c, nc = [Mul._from_args(list(w)) for w in d[1].args_cnc()]
314 2 12 6.0 0.0 denoms[i] = [d[0], c, nc]
315 2 3359 1679.5 0.0 G = gcd(c, G)
316 2 41 20.5 0.0 if g == G == S.One:
317 10000 31329 3.1 0.2 for i in range(i, len(denoms)):
318 9999 34333 3.4 0.2 denoms[i].append(S.One)
319 1 5 5.0 0.0 break
320 1 4 4.0 0.0 if g is not S.One:
321 for i, d in enumerate(denoms):
322 denoms[i][0] /= g
323 1 3 3.0 0.0 if G is not S.One:
324 for i, d in enumerate(denoms):
325 denoms[i][0] /= G
326 10001 402466 40.2 2.3 denoms = [Mul(*d) for d in denoms]
327 # make sure that there are no denominators introduced
328 1 7 7.0 0.0 if G is not S.One:
329 for i, d in enumerate(denoms):
330 for m in Mul.make_args(d):
331 if m.is_Pow and m.exp.is_Integer and m.exp < 0:
332 denoms[i] = cancel(d)
333 break
334
335 # collect common denominators
336 1 5 5.0 0.0 n = len(numers)
337 1 4 4.0 0.0 d = {}
338 10001 31554 3.2 0.2 for i in xrange(len(numers)):
339 10000 70223 7.0 0.4 d.setdefault(denoms[i], []).append(numers[i])
340 1 103 103.0 0.0 denoms = d.keys()
341 1001 222989 222.8 1.3 numers = [Add(*d[di]) for di in denoms]
342
343 # if a gcd was taken, check to see if the length of
344 # denoms is 1
345 1 4 4.0 0.0 if len(denoms) == 1:
346 n, d = numers[0], denoms[0]
347
348 # If the time needed to expand the nested numerator can be decreased then
349 # the elif-else would not be necessary: the binary method could always be used.
350 1 4 4.0 0.0 elif len(denoms) != n or \
351 any(d.is_Add or d.is_Mul and any(di.is_Add for di in d.args)
352 for d in denoms):
353 # use binary method because a) if we collected denoms, it is
354 # better to group them so we don't have to cancel common
355 # terms in numer and denom or b) there would have been nesting
356 # anyway if there was an Add present
357 1 4554898 4554898.0 26.3 n, d = self._as_numer_denom_binary(numers, denoms)
358 1 39 39.0 0.0 del numers, denoms # they've changed
359 else:
360 ## >>> n=300; num, den = [1]*n, [Dummy() for i in range(n)]
361 ## the following takes about 9 seconds (7 for numerator)
362 ## >>> ok=expand_mul(a._as_numer_denom_expanded(num, den)[0])
363 ## the following takes 16 seconds (but less than 1 for numerator)
364 ## >>> ok=expand_mul(a._as_numer_denom_binary(num, den)[0])
365 n, d = self._as_numer_denom_expanded(numers, denoms)
366
367 1 5 5.0 0.0 if d.is_Rational:
368 g *= d
369 else:
370 1 2766 2766.0 0.0 G *= d
371
372 # for debugging
373 # n1, d1 = n, g*G
374 # assert (no*d1-n1*do).expand() == 0
375
376 # expr -> n/(g*G) = (c*ni)/(g*G) = (c/g)*ni/G = (cn*ni)/(cd*G)
377 1 10313827 10313827.0 59.6 c, ni = n.as_content_primitive()
378 1 384 384.0 0.0 cn, cd = (c/g).as_numer_denom()
379 1 159 159.0 0.0 n, d = cn*ni, cd*G
380
381 # for debugging
382 # assert (no*d-n*do).expand() == 0
383
384 1 3 3.0 0.0 return n, d
File: sympy/core/add.py
Function: as_content_primitive at line 742
Total time: 7.6969 s
Line # Hits Time Per Hit % Time Line Contents
==============================================================
742 @profile
743 def as_content_primitive(self):
744 """Return the tuple (R, self/R) where R is the positive Rational
745 extracted from self.
746
747 **Example**
748 >>> from sympy import sqrt
749 >>> (3 + 3*sqrt(2)).as_content_primitive()
750 (3, 1 + sqrt(2))
751
752 See docstring of Expr.as_content_primitive for more examples.
753 """
754 1999 15500 7.8 0.2 from sympy import gcd
755 13997 229414 16.4 3.0 c_args = [a.as_content_primitive() for a in self.args]
756 13997 6338038 452.8 82.3 g = reduce(gcd, [c[0] for c in c_args])
757 1999 6080 3.0 0.1 if g is S.One:
758 13997 1064844 76.1 13.8 a = Add(*[c[0]*c[1] for c in c_args])
759 else:
760 a = Add(*[c[0]/g*c[1] for c in c_args])
761 1999 6850 3.4 0.1 c, ai = a.as_coeff_Mul()
762 1999 3565 1.8 0.0 if c.is_Rational:
763 1999 3032 1.5 0.0 if c.is_negative:
764 c = -c
765 ai = -ai
766 1999 24052 12.0 0.3 g *= c
767 1999 3046 1.5 0.0 a = ai
768 else:
769 a *= g
770 g = S.One
771 1999 2484 1.2 0.0 return g, a
Wrote profile results to t.py.lprof
Timer unit: 1e-06 s
File: sympy/core/add.py
Function: as_numer_denom at line 285
Total time: 12.7791 s
Line # Hits Time Per Hit % Time Line Contents
==============================================================
285 @profile
286 def as_numer_denom(self):
287 1 25 25.0 0.0 from sympy import gcd, cancel
288
289 10003 1446485 144.6 11.3 numers, denoms = [list(_) for _ in zip(*[f.as_numer_denom() for f in self.args])]
290 # for debugging
291 # no, do = self._as_numer_denom_expanded(numers, denoms)
292 1 3 3.0 0.0 g = G = S.One
293
294 # check for trivial case
295 1 4 4.0 0.0 denom = denoms[0]
296 1 41 41.0 0.0 if all(d == denom for d in denoms):
297 n, d = Add(*numers), denom
298 g, d = d.as_content_primitive()
299
300 # If all denoms are Number use the binary method: this doesn't lead to nesting
301 # because the Numbers auto-distribute on the nested terms
302 1 8 8.0 0.0 elif all(d.is_Number for d in denoms):
303 n, d = self._as_numer_denom_binary(numers, denoms)
304
305 else:
306 # simple gcd extraction (no factoring beyond primitive nor expanding)
307 10001 68835 6.9 0.5 denoms = [list(d.as_content_primitive()) for d in denoms]
308
309 1 4 4.0 0.0 g = G = S.Zero
310 1 3 3.0 0.0 hit = True
311 2 12 6.0 0.0 for i, d in enumerate(denoms):
312 2 1767 883.5 0.0 g = gcd(g, d[0])
313 6 90 15.0 0.0 c, nc = [Mul._from_args(list(w)) for w in d[1].args_cnc()]
314 2 8 4.0 0.0 denoms[i] = [d[0], c, nc]
315 2 3957 1978.5 0.0 G = gcd(c, G)
316 2 46 23.0 0.0 if g == G == S.One:
317 10000 35267 3.5 0.3 for i in range(i, len(denoms)):
318 9999 39438 3.9 0.3 denoms[i].append(S.One)
319 1 4 4.0 0.0 break
320 1 3 3.0 0.0 if g is not S.One:
321 for i, d in enumerate(denoms):
322 denoms[i][0] /= g
323 1 3 3.0 0.0 if G is not S.One:
324 for i, d in enumerate(denoms):
325 denoms[i][0] /= G
326 10001 438608 43.9 3.4 denoms = [Mul(*d) for d in denoms]
327 # make sure that there are no denominators introduced
328 1 5 5.0 0.0 if G is not S.One:
329 for i, d in enumerate(denoms):
330 for m in Mul.make_args(d):
331 if m.is_Pow and m.exp.is_Integer and m.exp < 0:
332 denoms[i] = cancel(d)
333 break
334
335 # collect common denominators
336 1 5 5.0 0.0 n = len(numers)
337 1 4 4.0 0.0 d = {}
338 10001 32258 3.2 0.3 for i in xrange(len(numers)):
339 10000 71519 7.2 0.6 d.setdefault(denoms[i], []).append(numers[i])
340 1 111 111.0 0.0 denoms = d.keys()
341 1001 221585 221.4 1.7 numers = [Add(*d[di]) for di in denoms]
342
343 # if a gcd was taken, check to see if the length of
344 # denoms is 1
345 1 4 4.0 0.0 if len(denoms) == 1:
346 n, d = numers[0], denoms[0]
347
348 # If the time needed to expand the nested numerator can be decreased then
349 # the elif-else would not be necessary: the binary method could always be used.
350 1 3 3.0 0.0 elif len(denoms) != n or \
351 any(d.is_Add or d.is_Mul and any(di.is_Add for di in d.args)
352 for d in denoms):
353 # use binary method because a) if we collected denoms, it is
354 # better to group them so we don't have to cancel common
355 # terms in numer and denom or b) there would have been nesting
356 # anyway if there was an Add present
357 1 5139208 5139208.0 40.2 n, d = self._as_numer_denom_binary(numers, denoms)
358 1 43 43.0 0.0 del numers, denoms # they've changed
359 else:
360 ## >>> n=300; num, den = [1]*n, [Dummy() for i in range(n)]
361 ## the following takes about 9 seconds (7 for numerator)
362 ## >>> ok=expand_mul(a._as_numer_denom_expanded(num, den)[0])
363 ## the following takes 16 seconds (but less than 1 for numerator)
364 ## >>> ok=expand_mul(a._as_numer_denom_binary(num, den)[0])
365 n, d = self._as_numer_denom_expanded(numers, denoms)
366
367 1 5 5.0 0.0 if d.is_Rational:
368 g *= d
369 else:
370 1 2243 2243.0 0.0 G *= d
371
372 # for debugging
373 # n1, d1 = n, g*G
374 # assert (no*d1-n1*do).expand() == 0
375
376 # expr -> n/(g*G) = (c*ni)/(g*G) = (c/g)*ni/G = (cn*ni)/(cd*G)
377 1 5277179 5277179.0 41.3 c, ni = n.as_content_primitive()
378 1 189 189.0 0.0 cn, cd = (c/g).as_numer_denom()
379 1 155 155.0 0.0 n, d = cn*ni, cd*G
380
381 # for debugging
382 # assert (no*d-n*do).expand() == 0
383
384 1 3 3.0 0.0 return n, d
File: sympy/core/add.py
Function: as_content_primitive at line 742
Total time: 2.02115 s
Line # Hits Time Per Hit % Time Line Contents
==============================================================
742 @profile
743 def as_content_primitive(self):
744 """Return the tuple (R, self/R) where R is the positive Rational
745 extracted from self.
746
747 **Example**
748 >>> from sympy import sqrt
749 >>> (3 + 3*sqrt(2)).as_content_primitive()
750 (3, 1 + sqrt(2))
751
752 See docstring of Expr.as_content_primitive for more examples.
753 """
754 1999 15486 7.7 0.8 from sympy import gcd_list
755 13997 278525 19.9 13.8 c_args = [a.as_content_primitive() for a in self.args]
756 13997 424152 30.3 21.0 g = gcd_list([c[0] for c in c_args])
757 1999 3555 1.8 0.2 if g is S.One:
758 13997 1232919 88.1 61.0 a = Add(*[c[0]*c[1] for c in c_args])
759 else:
760 a = Add(*[c[0]/g*c[1] for c in c_args])
761 1999 8043 4.0 0.4 c, ai = a.as_coeff_Mul()
762 1999 2851 1.4 0.1 if c.is_Rational:
763 1999 4413 2.2 0.2 if c.is_negative:
764 c = -c
765 ai = -ai
766 1999 44520 22.3 2.2 g *= c
767 1999 4107 2.1 0.2 a = ai
768 else:
769 a *= g
770 g = S.One
771 1999 2584 1.3 0.1 return g, a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment