mirror of
https://github.com/stevenrobertson/cuburn.git
synced 2025-02-05 11:40:04 -05:00
Fix an interpolation code-gen issue.
A bug in the hacky use of OrderedDict to function as an OrderedSet meant that any value acceessed in a precalculation function which had already been accessed from another precalculation function would use an incorrect index.
This commit is contained in:
parent
44a826508a
commit
3a6490825b
@ -1,4 +1,3 @@
|
|||||||
from collections import OrderedDict
|
|
||||||
from itertools import cycle
|
from itertools import cycle
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
@ -7,10 +6,26 @@ from cuburn.genome.util import resolve_spec
|
|||||||
from cuburn.genome.use import Wrapper, SplineEval
|
from cuburn.genome.use import Wrapper, SplineEval
|
||||||
|
|
||||||
import util
|
import util
|
||||||
from util import Template, assemble_code, devlib, binsearchlib, ringbuflib
|
from util import Template, assemble_code, devlib, binsearchlib, ringbuflib, snd
|
||||||
from color import yuvlib
|
from color import yuvlib
|
||||||
from mwc import mwclib
|
from mwc import mwclib
|
||||||
|
|
||||||
|
class _OrderedSet(object):
|
||||||
|
"""
|
||||||
|
A set that tracks the order in which items are added to it. Items cannot
|
||||||
|
be removed. Iterating over the set returns items in order of addition.
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
self._vals = {}
|
||||||
|
def add(self, val):
|
||||||
|
return self._vals.setdefault(val, len(self._vals))
|
||||||
|
def __iter__(self):
|
||||||
|
return (k for k, v in sorted(self._vals.items(), key=snd))
|
||||||
|
def __len__(self):
|
||||||
|
return len(self._vals)
|
||||||
|
def __contains__(self, val):
|
||||||
|
return val in self._vals
|
||||||
|
|
||||||
class PackerWrapper(Wrapper):
|
class PackerWrapper(Wrapper):
|
||||||
"""
|
"""
|
||||||
Obtain accessors in generated code.
|
Obtain accessors in generated code.
|
||||||
@ -123,13 +138,12 @@ class GenomePacker(object):
|
|||||||
# to be able to treat the direct stuff as a list so this function
|
# to be able to treat the direct stuff as a list so this function
|
||||||
# doesn't unroll any more than it has to. So we separate things into
|
# doesn't unroll any more than it has to. So we separate things into
|
||||||
# direct requests, and those that need precalculation.
|
# direct requests, and those that need precalculation.
|
||||||
# Values of OrderedDict are unused; basically, it's just OrderedSet.
|
self.packed_direct = _OrderedSet()
|
||||||
self.packed_direct = OrderedDict()
|
|
||||||
# Feel kind of bad about this, but it's just under the threshold of
|
# Feel kind of bad about this, but it's just under the threshold of
|
||||||
# being worth refactoring to be agnostic to interpolation types
|
# being worth refactoring to be agnostic to interpolation types
|
||||||
self.packed_direct_mag = OrderedDict()
|
self.packed_direct_mag = _OrderedSet()
|
||||||
self.genome_precalc = OrderedDict()
|
self.genome_precalc = _OrderedSet()
|
||||||
self.packed_precalc = OrderedDict()
|
self.packed_precalc = _OrderedSet()
|
||||||
self.precalc_code = []
|
self.precalc_code = []
|
||||||
|
|
||||||
self._len = None
|
self._len = None
|
||||||
@ -155,19 +169,18 @@ class GenomePacker(object):
|
|||||||
must be available during interpolation.
|
must be available during interpolation.
|
||||||
"""
|
"""
|
||||||
if spec.interp == 'mag':
|
if spec.interp == 'mag':
|
||||||
self.packed_direct_mag[path] = None
|
self.packed_direct_mag.add(path)
|
||||||
else:
|
else:
|
||||||
self.packed_direct[path] = None
|
self.packed_direct.add(path)
|
||||||
return self.devname(path)
|
return self.devname(path)
|
||||||
|
|
||||||
def _require_pre(self, spec, path):
|
def _require_pre(self, spec, path):
|
||||||
i = len(self.genome_precalc) << self.search_rounds
|
i = self.genome_precalc.add(path) << self.search_rounds
|
||||||
self.genome_precalc[path] = None
|
|
||||||
func = 'catmull_rom_mag' if spec.interp == 'mag' else 'catmull_rom'
|
func = 'catmull_rom_mag' if spec.interp == 'mag' else 'catmull_rom'
|
||||||
return '%s(×[%d], &knots[%d], time)' % (func, i, i)
|
return '%s(×[%d], &knots[%d], time)' % (func, i, i)
|
||||||
|
|
||||||
def _pre_alloc(self, path):
|
def _pre_alloc(self, path):
|
||||||
self.packed_precalc[path] = None
|
self.packed_precalc.add(path)
|
||||||
return '%s->%s' % (self.ptr_name, '_'.join(path))
|
return '%s->%s' % (self.ptr_name, '_'.join(path))
|
||||||
|
|
||||||
def devname(self, path):
|
def devname(self, path):
|
||||||
@ -180,9 +193,9 @@ class GenomePacker(object):
|
|||||||
# At the risk of packing a few things more than once, we don't
|
# At the risk of packing a few things more than once, we don't
|
||||||
# uniquify the overall precalc order, sparing us the need to implement
|
# uniquify the overall precalc order, sparing us the need to implement
|
||||||
# recursive code generation
|
# recursive code generation
|
||||||
direct = self.packed_direct.keys() + self.packed_direct_mag.keys()
|
direct = list(self.packed_direct) + list(self.packed_direct_mag)
|
||||||
self.packed = direct + self.packed_precalc.keys()
|
self.packed = direct + list(self.packed_precalc)
|
||||||
self.genome = direct + self.genome_precalc.keys()
|
self.genome = direct + list(self.genome_precalc)
|
||||||
|
|
||||||
self._len = len(self.packed)
|
self._len = len(self.packed)
|
||||||
|
|
||||||
|
@ -10,6 +10,9 @@ import pycuda.compiler
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import tempita
|
import tempita
|
||||||
|
|
||||||
|
fst = lambda (a,b): a
|
||||||
|
snd = lambda (a,b): b
|
||||||
|
|
||||||
def argset(obj, **kwargs):
|
def argset(obj, **kwargs):
|
||||||
"""
|
"""
|
||||||
Allow an object with many properties to be set using one call.
|
Allow an object with many properties to be set using one call.
|
||||||
|
Loading…
Reference in New Issue
Block a user