@@ -1346,39 +1346,79 @@ sub_t(a,b) = promote_symtype(-, symtype(a), symtype(b))
1346
1346
sub_t (a) = promote_symtype (- , symtype (a))
1347
1347
1348
1348
import Base: (+ ), (- ), (* ), (// ), (/ ), (\ ), (^ )
1349
- function + (a:: SN , b:: SN )
1350
- ! issafecanon (+ , a,b) && return term (+ , a, b) # Don't flatten if args have metadata
1351
- if isadd (a) && isadd (b)
1352
- return Add (add_t (a,b),
1353
- a. coeff + b. coeff,
1354
- _merge (+ , a. dict, b. dict, filter= _iszero))
1355
- elseif isadd (a)
1356
- coeff, dict = makeadd (1 , 0 , b)
1357
- return Add (add_t (a,b), a. coeff + coeff, _merge (+ , a. dict, dict, filter= _iszero))
1358
- elseif isadd (b)
1359
- return b + a
1360
- end
1361
- coeff, dict = makeadd (1 , 0 , a, b)
1362
- Add (add_t (a,b), coeff, dict)
1363
- end
1364
-
1365
- function + (a:: Number , b:: SN )
1366
- tmp = unwrap (a)
1367
- if tmp != = a
1368
- return tmp + b
1349
+
1350
+ function + (a:: SN , bs:: SN... )
1351
+ isempty (bs) && return a
1352
+ # entries where `!issafecanon`
1353
+ unsafes = SmallV {Any} ()
1354
+ # coeff and dict of the `Add`
1355
+ coeff = 0
1356
+ dict = sdict ()
1357
+ # type of the `Add`
1358
+ T = symtype (a)
1359
+
1360
+ # handle `a` separately
1361
+ if issafecanon (+ , a)
1362
+ if isadd (a)
1363
+ coeff = a. coeff
1364
+ dict = copy (a. dict)
1365
+ elseif ismul (a)
1366
+ v = a. coeff
1367
+ a′ = Mul (symtype (a), 1 , copy (a. dict); metadata = a. metadata)
1368
+ dict[a′] = v
1369
+ else
1370
+ dict[a] = 1
1371
+ end
1372
+ else
1373
+ push! (unsafes, a)
1374
+ end
1375
+
1376
+ for b in bs
1377
+ T = promote_symtype (+ , T, symtype (b))
1378
+ if ! issafecanon (+ , b)
1379
+ push! (unsafes, b)
1380
+ continue
1381
+ end
1382
+ if isadd (b)
1383
+ coeff += b. coeff
1384
+ for (k, v) in b. dict
1385
+ dict[k] = get (dict, k, 0 ) + v
1386
+ end
1387
+ elseif ismul (b)
1388
+ v = b. coeff
1389
+ b′ = Mul (symtype (b), 1 , copy (b. dict); metadata = b. metadata)
1390
+ dict[b′] = get (dict, b′, 0 ) + v
1391
+ else
1392
+ dict[b] = get (dict, b, 0 ) + 1
1393
+ end
1394
+ end
1395
+ # remove entries multiplied by zero
1396
+ filter! (dict) do kvp
1397
+ ! iszero (kvp[2 ])
1398
+ end
1399
+
1400
+ result = isempty (dict) ? coeff : Add (T, coeff, dict)
1401
+ if ! isempty (unsafes)
1402
+ push! (unsafes, result)
1403
+ result = Term {T} (+ , unsafes)
1369
1404
end
1370
- ! issafecanon (+ , b) && return term (+ , a, b) # Don't flatten if args have metadata
1405
+ return result
1406
+ end
1407
+
1408
+ function + (a:: Number , b:: SN , bs:: SN... )
1409
+ b = + (b, bs... )
1410
+ issafecanon (+ , b) || return term (+ , a, b)
1371
1411
iszero (a) && return b
1372
1412
if isadd (b)
1373
- Add (add_t (a,b), a + b. coeff, b. dict)
1413
+ Add (add_t (a, b), a + b. coeff, b. dict)
1374
1414
else
1375
- Add (add_t (a,b), makeadd (1 , a, b)... )
1415
+ Add (add_t (a, b), makeadd (1 , a, b)... )
1376
1416
end
1377
1417
end
1378
1418
1379
- + (a:: SN , b:: Number ) = b + a
1380
-
1381
- + (a :: SN ) = a
1419
+ function + (a:: SN , b:: Number , bs :: SN... )
1420
+ return + (b, a, bs ... )
1421
+ end
1382
1422
1383
1423
function - (a:: SN )
1384
1424
! issafecanon (* , a) && return term (- , a)
0 commit comments