# Path: autograd/tracer.py
# def trace(start_node, fun, x):
#     def __init__(self, value, fun, args, kwargs, parent_argnums, parents):
#     def initialize_root(self, *args, **kwargs):
#     def new_root(cls, *args, **kwargs):
# def primitive(f_raw):
#     def f_wrapped(*args, **kwargs):
# def register_notrace(trace_type, primitive_fun):
# def notrace_primitive(f_raw):
#     def f_wrapped(*args, **kwargs):
# def find_top_boxed_args(args):
#     def __init__(self):
#     def new_trace(self):
#     def __init__(self, value, trace, node):
#     def __bool__(self):
#     def __str__(self):
#     def register(cls, value_type):
# def new_box(value, trace, node):
# class Node(object):
# class TraceStack(object):
# class Box(object):
# 
# Path: autograd/util.py
# def func(f): return f
# 
# def subval(x, i, v):
#     x_ = list(x)
#     x_[i] = v
#     return tuple(x_)


from itertools import count
from functools import reduce
from .tracer import trace, primitive, toposort, Node, Box, isbox, getval
from .util import func, subval
import warnings
    defjvp_argnum(fun, lambda argnum, g, ans, args, kwargs:
                  fun(*subval(args, argnum, g), **kwargs))

# -------------------- vector behavior --------------------

def add_outgrads(prev_g_flagged, g):
    sparse = type(g) in sparse_object_types
    if prev_g_flagged:
        vs = vspace(g)
        prev_g, mutable = prev_g_flagged
        if mutable:
            if sparse:
                return sparse_add(vs, prev_g, g), True
            else:
                return vs.mut_add(prev_g, g), True
        else:
            if sparse:
                prev_g_mutable = vs.mut_add(None, prev_g)
                return sparse_add(vs, prev_g_mutable, g), True
            else:
                return vs.add(prev_g, g), True
    else:
        if sparse:
            return sparse_add(vspace(g), None, g), True
        else:
            return g, False

def sum_outgrads(gs):
    return reduce(add_outgrads, gs, None)[0]


# Path: autograd/tracer.py
# def trace(start_node, fun, x):
#     def __init__(self, value, fun, args, kwargs, parent_argnums, parents):
#     def initialize_root(self, *args, **kwargs):
#     def new_root(cls, *args, **kwargs):
# def primitive(f_raw):
#     def f_wrapped(*args, **kwargs):
# def register_notrace(trace_type, primitive_fun):
# def notrace_primitive(f_raw):
#     def f_wrapped(*args, **kwargs):
# def find_top_boxed_args(args):
#     def __init__(self):
#     def new_trace(self):
#     def __init__(self, value, trace, node):
#     def __bool__(self):
#     def __str__(self):
#     def register(cls, value_type):
# def new_box(value, trace, node):
# class Node(object):
# class TraceStack(object):
# class Box(object):
# 
# Path: autograd/util.py
# def func(f): return f
# 
# def subval(x, i, v):
#     x_ = list(x)
#     x_[i] = v
#     return tuple(x_)


# Path: autograd/core.py
from itertools import count
from functools import reduce
from .tracer import trace, primitive, toposort, Node, Box, isbox, getval
from .util import func, subval
import warnings

    defjvp_argnum(fun, lambda argnum, g, ans, args, kwargs:
                  fun(*subval(args, argnum, g), **kwargs))

# -------------------- vector behavior --------------------

def add_outgrads(prev_g_flagged, g):
    sparse = type(g) in sparse_object_types
    if prev_g_flagged:
        vs = vspace(g)
        prev_g, mutable = prev_g_flagged
        if mutable:
            if sparse:
                return sparse_add(vs, prev_g, g), True
            else:
                return vs.mut_add(prev_g, g), True
        else:
            if sparse:
                prev_g_mutable = vs.mut_add(None, prev_g)
                return sparse_add(vs, prev_g_mutable, g), True
            else:
                return vs.add(prev_g, g), True
    else:
        if sparse:
            return sparse_add(vspace(g), None, g), True
        else:
            return g, False

def sum_outgrads(gs):
    return reduce(add_outgrads, gs, None)[0]


@primitive