ground = "gnd"
do
  __fnl_global__node_2dtable = {}
  __fnl_global__node_2dtable["__index"] = __fnl_global__node_2dtable
  local function _0_(cls_0_, ...)
    local inst_0_ = {}
    local function _1_(cls, self)
      assert((nil ~= self), ("Missing argument %s on %s:%s"):format("self", "sources/mods/electricity/sim.fnl", 5))
      assert((nil ~= cls), ("Missing argument %s on %s:%s"):format("cls", "sources/mods/electricity/sim.fnl", 5))
      self.nodes, self["node-count"], self.components = {}, 0, 0
      return nil
    end
    _1_(cls_0_, inst_0_, ...)
    setmetatable(inst_0_, cls_0_)
    return inst_0_
  end
  setmetatable(__fnl_global__node_2dtable, {__call = _0_})
end
__fnl_global__node_2dtable["add-to-nodes"] = function(self, node_str)
  if (self.nodes[node_str] == nil) then
    self.nodes[node_str] = self["node-count"]
    self["node-count"] = (self["node-count"] + 1)
  end
  return self.nodes[node_str]
end
local function map_nodes(circ)
  local tbl = __fnl_global__node_2dtable()
  tbl["add-to-nodes"](tbl, ground)
  for _, elem in ipairs(circ) do
    tbl.components = (tbl.components + 1)
    tbl[elem.type] = ((tbl[elem.type] or 0) + 1)
    elem.high = tbl["add-to-nodes"](tbl, elem["pos-node"])
    elem.low = tbl["add-to-nodes"](tbl, elem["neg-node"])
  end
  return tbl
end
local function calculate_consumer(A, b, elem, g2_index)
  local G = (1 / elem.value)
  if (elem.high ~= 0) then
    A:set(elem.high, elem.high, (A:get(elem.high, elem.high) + G))
  end
  if (elem.low ~= 0) then
    A:set(elem.low, elem.low, (A:get(elem.low, elem.low) + G))
  end
  if ((elem.high ~= 0) and (elem.low ~= 0)) then
    A:set(elem.high, elem.low, (A:get(elem.high, elem.low) - G))
    return A:set(elem.low, elem.high, (A:get(elem.low, elem.high) - G))
  end
end
local function calculate_voltage(A, b, elem, g2_index)
  if (elem.high ~= 0) then
    A:set(elem.high, g2_index, (A:get(elem.high, g2_index) + 1))
    A:set(g2_index, elem.high, (A:get(g2_index, elem.high) + 1))
  end
  if (elem.low ~= 0) then
    A:set(elem.low, g2_index, (A:get(elem.low, g2_index) - 1))
    A:set(g2_index, elem.low, (A:get(g2_index, elem.low) - 1))
  end
  b:set(g2_index, 1, elem.value)
  return (g2_index + 1)
end
local function calculate_current(A, b, elem, g2_index)
  if (elem.high ~= 0) then
    b:set(elem.high, 1, (b:get(elem.high, 1) - elem.value))
  end
  if (elem.low ~= 0) then
    return b:set(elem.low, 1, (b:get(elem.low, 1) + elem.value))
  end
end
local circuit_elems = {consumer = calculate_consumer, current = calculate_current, voltage = calculate_voltage}
local function solve_aux(tbl, circ)
  local g2_count = (tbl.voltage + (tbl.inductor or 0))
  local matrix_size = (tbl["node-count"] + g2_count + -1)
  local A = matrix(matrix_size, matrix_size)
  local b = matrix(matrix_size, 1)
  local g2_index = (matrix_size - g2_count - -1)
  for id, elem in ipairs(circ) do
    local func = circuit_elems[elem.type]
    local maybe_g2_index = func(A, b, elem, g2_index)
    if (maybe_g2_index ~= nil) then
      g2_index = maybe_g2_index
      elem["current-index"] = (maybe_g2_index - 1)
    end
  end
  local solution = linsolve(A, b)
  local res = {currents = {}, voltages = {}}
  for name, pin in pairs(tbl.nodes) do
    local v = (solution:get(pin, 1) or real(0))
    res.voltages[name] = v
  end
  res.voltages[ground] = real(0)
  for id, elem in ipairs(circ) do
    if (elem["current-index"] ~= nil) then
      res.currents[elem.name] = solution:get(elem["current-index"], 1)
    end
  end
  return res
end
local function _0_(circ)
  return solve_aux(map_nodes(circ), circ)
end
circsolve = _0_
return nil
