text:
from __future__ import print_function, division, absolute_import

import ast
import copy
from collections import OrderedDict
import linecache
import os
import sys
import numpy as np

import llvmlite.llvmpy.core as lc
import llvmlite.ir.values as liv

import numba
from .. import compiler, ir, types, six, cgutils, sigutils, lowering, parfor
from numba.ir_utils import (add_offset_to_labels, replace_var_names,
                            remove_dels, legalize_names, mk_unique_var,
                            rename_labels, get_name_var_table, visit_vars_inner,
                            get_definition, guard, find_callname,
                            get_call_table, is_pure, get_np_ufunc_typ,
                            get_unused_var_name, find_potential_aliases,
                            is_const_call)
from numba.analysis import (compute_use_defs, compute_live_map,
                            compute_dead_maps, compute_cfg_from_blocks)
from ..typing import signature
from numba import config
from numba.targets.cpu import ParallelOptions
from numba.six import exec_
from numba.parfor import print_wrapped, ensure_parallel_support
import types as pytypes

import warnings
from ..errors import NumbaParallelSafetyWarning

def _lower_parfor_parallel(lowerer, parfor):
    """Lowerer that handles LLVM code generation for parfor.
    This function lowers a parfor IR node to LLVM.
    The general approach is as follows:
    1) The code from the parfor's init block is lowered normally
       in the context of the current function.
    2) The body of the parfor is transformed into a gufunc function.
    3) Code is inserted into the main function that calls do_scheduling
       to divide the iteration space for each thread, allocates
       reduction arrays, calls the gufunc function, and then invokes
       the reduction function across the reduction arrays to produce
       the final reduction values.
    """
    from .parallel import get_thread_count

    ensure_parallel_support()
    typingctx = lowerer.context.typing_context
    targetctx = lowerer.context
    # We copy the typemap here because for race condition variable we'll
    # update their type to array so they can be updated by the gufunc.
    orig_typemap = lowerer.fndesc.typemap
    # replace original typemap with copy and restore the original at the end.
    lowerer.fndesc.typemap = copy.copy(orig_typemap)
    typemap = lowerer.fndesc.typemap
    varmap = lowerer.varmap

    if config.DEBUG_ARRAY_OPT:
        print("_lower_parfor_parallel")
        parfor.dump()

    loc = parfor.init_block.loc
    scope = parfor.init_block.scope

    # produce instructions for init_block
    if config.DEBUG_ARRAY_OPT:
        print("init_block = ", parfor.init_block, " ", type(parfor.init_block))
    for instr in parfor.init_block.body:
        if config.DEBUG_ARRAY_OPT:
            print("lower init_block instr = ", instr)
        lowerer.lower_inst(instr)

    for racevar in parfor.races:
        if racevar not in varmap:
            rvtyp = typemap[racevar]
            rv = ir.Var(scope, racevar, loc)
            lowerer._alloca_var(rv.name, rvtyp)

    alias_map = {}
    arg_aliases = {}
    numba.parfor.find_potential_aliases_parfor(parfor, parfor.params, typemap,
                                        lowerer.func_ir, alias_map, arg_aliases)
    if config.DEBUG_ARRAY_OPT:
        print("alias_map", alias_map)
        print("arg_aliases", arg_aliases)

    # run get_parfor_outputs() and get_parfor_reductions() before gufunc creation
    # since Jumps are modified so CFG of loop_body dict will become invalid
    assert parfor.params != None

    parfor_output_arrays = numba.parfor.get_parfor_outputs(
        parfor, parfor.params)
    parfor_redvars, parfor_reddict = numba.parfor.get_parfor_reductions(
        parfor, parfor.params, lowerer.fndesc.calltypes)

    # init reduction array allocation here.
    nredvars = len(parfor_redvars)
    redarrs = {}
    if nredvars > 0:
        # reduction arrays outer dimension equal to thread count
        thread_count = get_thread_count()
        scope = parfor.init_block.scope
        loc = parfor.init_block.loc

        # For each reduction variable...
        for i in range(nredvars):
            redvar_typ = lowerer.fndesc.typemap[parfor_redvars[i]]
            redvar = ir.Var(scope, parfor_redvars[i], loc)
            redarrvar_typ = redtyp_to_redarraytype(redvar_typ)
            reddtype = redarrvar_typ.dtype
            if config.DEBUG_ARRAY_OPT:
                print("redvar_typ", redvar_typ, redarrvar_typ, reddtype, types.DType(reddtype))

            # If this is reduction over an array,
            # the reduction array has just one added per-worker dimension.
            if isinstance(redvar_typ, types.npytypes.Array):
                redarrdim = redvar_typ.ndim + 1
            else:
                redarrdim = 1

            # Reduction array is created and initialized to the initial reduction value.

            # First create a var for the numpy empty ufunc.
            empty_func = ir.Var(scope, mk_unique_var("empty_func"), loc)
            ff_fnty = get_np_ufunc_typ(np.empty)
            ff_sig = typingctx.resolve_function_type(ff_fnty,
                                            (types.UniTuple(types.intp, redarrdim),
                                             types.DType(reddtype)), {})
            typemap[empty_func.name] = ff_fnty
            empty_assign = ir.Assign(ir.Global("empty", np.empty, loc=loc), empty_func, loc)
            lowerer.lower_inst(empty_assign)

            # Create var for outer dimension size of reduction array equal to number of threads.
            num_threads_var = ir.Var(scope, mk_unique_var("num_threads"), loc)
            num_threads_assign = ir.Assign(ir.Const(thread_count, loc), num_threads_var, loc)
            typemap[num_threads_var.name] = types.intp
            lowerer.lower_inst(num_threads_assign)

            # Empty call takes tuple of sizes.  Create here and fill in outer dimension (num threads).
            size_var = ir.Var(scope, mk_unique_var("tuple_size_var"), loc)
            typemap[size_var.name] = types.UniTuple(types.intp, redarrdim)
            size_var_list = [num_threads_var]

            # If this is a reduction over an array...
            if isinstance(redvar_typ, types.npytypes.Array):
                # Add code to get the shape of the array being reduced over.
                redshape_var = ir.Var(scope, mk_unique_var("redarr_shape"), loc)
                typemap[redshape_var.name] = types.UniTuple(types.intp, redvar_typ.ndim)
                redshape_getattr = ir.Expr.getattr(redvar, "shape", loc)
                redshape_assign = ir.Assign(redshape_getattr, redshape_var, loc)
                lowerer.lower_inst(redshape_assign)

                # Add the dimension sizes of the array being reduced over to the tuple of sizes pass to empty.
                for j in range(redvar_typ.ndim):
                    onedimvar = ir.Var(scope, mk_unique_var("redshapeonedim"), loc)
                    onedimgetitem = ir.Expr.static_getitem(redshape_var, j, None, loc)
                    typemap[onedimvar.name] = types.intp
                    onedimassign = ir.Assign(onedimgetitem, onedimvar, loc)
                    lowerer.lower_inst(onedimassign)
                    size_var_list += [onedimvar]

            size_call = ir.Expr.build_tuple(size_var_list, loc)
            size_assign = ir.Assign(size_call, size_var, loc)
            lowerer.lower_inst(size_assign)

            # Add call to empty passing the size var tuple.
            empty_call = ir.Expr.call(empty_func, [size_var], {}, loc=loc)
            redarr_var = ir.Var(scope, mk_unique_var("redarr"), loc)
            typemap[redarr_var.name] = redarrvar_typ
            empty_call_assign = ir.Assign(empty_call, redarr_var, loc)
            lowerer.fndesc.calltypes[empty_call] = ff_sig
            lowerer.lower_inst(empty_call_assign)

            # Remember mapping of original reduction array to the newly created per-worker reduction array.
            redarrs[redvar.name] = redarr_var

            init_val = parfor_reddict[parfor_redvars[i]][0]
            if init_val != None:
                if isinstance(redvar_typ, types.npytypes.Array):
                    # Create an array of identity values for the reduction.
                    # First, create a variable for np.full.
                    full_func = ir.Var(scope, mk_unique_var("full_func"), loc)
                    full_fnty = get_np_ufunc_typ(np.full)
                    full_sig = typingctx.resolve_function_type(full_fnty,
                               (types.UniTuple(types.intp, redvar_typ.ndim),
                                reddtype,
                                types.DType(reddtype)), {})
                    typemap[full_func.name] = full_fnty
                    full_assign = ir.Assign(ir.Global("full", np.full, loc=loc), full_func, loc)
                    lowerer.lower_inst(full_assign)

                    # Then create a var with the identify value.
                    init_val_var = ir.Var(scope, mk_unique_var("init_val"), loc)
                    init_val_assign = ir.Assign(ir.Const(init_val, loc), init_val_var, loc)
                    typemap[init_val_var.name] = reddtype
                    lowerer.lower_inst(init_val_assign)

                    # Then, call np.full with the shape of the reduction array and the identity value.
                    full_call = ir.Expr.call(full_func, [redshape_var, init_val_var], {}, loc=loc)
                    lowerer.fndesc.calltypes[full_call] = full_sig
                    redtoset = ir.Var(scope, mk_unique_var("redtoset"), loc)
                    redtoset_assign = ir.Assign(full_call, redtoset, loc)
                    typemap[redtoset.name] = redvar_typ
                    lowerer.lower_inst(redtoset_assign)
                else:
                    redtoset = ir.Var(scope, mk_unique_var("redtoset"), loc)
                    redtoset_assign = ir.Assign(ir.Const(init_val, loc), redtoset, loc)
                    typemap[redtoset.name] = reddtype
                    lowerer.lower_inst(redtoset_assign)
            else:
                redtoset = redvar

            # For each thread, initialize the per-worker reduction array to the current reduction array value.
            for j in range(get_thread_count()):
                index_var = ir.Var(scope, mk_unique_var("index_var"), loc)
                index_var_assign = ir.Assign(ir.Const(j, loc), index_var, loc)
                typemap[index_var.name] = types.uintp
                lowerer.lower_inst(index_var_assign)

                redsetitem = ir.SetItem(redarr_var, index_var, redtoset, loc)
                lowerer.fndesc.calltypes[redsetitem] = signature(types.none,
                        typemap[redarr_var.name], typemap[index_var.name], redvar_typ)
                lowerer.lower_inst(redsetitem)

    # compile parfor body as a separate function to be used with GUFuncWrapper
    flags = copy.copy(parfor.flags)
    flags.set('error_model', 'numpy')
    # Can't get here unless  flags.set('auto_parallel', ParallelOptions(True))
    index_var_typ = typemap[parfor.loop_nests[0].index_variable.name]
    # index variables should have the same type, check rest of indices
    for l in parfor.loop_nests[1:]:
        assert typemap[l.index_variable.name] == index_var_typ
    numba.parfor.sequential_parfor_lowering = True
    func, func_args, func_sig, redargstartdim, func_arg_types = _create_gufunc_for_parfor_body(
        lowerer, parfor, typemap, typingctx, targetctx, flags, {},
        bool(alias_map), index_var_typ, parfor.races)
    numba.parfor.sequential_parfor_lowering = False

    # get the shape signature
    func_args = ['sched'] + func_args
    num_reductions = len(parfor_redvars)
    num_inputs = len(func_args) - len(parfor_output_arrays) - num_reductions
    if config.DEBUG_ARRAY_OPT:
        print("func_args = ", func_args)
        print("num_inputs = ", num_inputs)
        print("parfor_outputs = ", parfor_output_arrays)
        print("parfor_redvars = ", parfor_redvars)
        print("num_reductions = ", num_reductions)
    gu_signature = _create_shape_signature(
        parfor.get_shape_classes,
        num_inputs,
        num_reductions,
        func_args,
        redargstartdim,
        func_sig,
        parfor.races,
        typemap)
    if config.DEBUG_ARRAY_OPT:
        print("gu_signature = ", gu_signature)

    # call the func in parallel by wrapping it with ParallelGUFuncBuilder
    loop_ranges = [(l.start, l.stop, l.step) for l in parfor.loop_nests]
    if config.DEBUG_ARRAY_OPT:
        print("loop_nests = ", parfor.loop_nests)
        print("loop_ranges = ", loop_ranges)
    call_parallel_gufunc(
        lowerer,
        func,
        gu_signature,
        func_sig,
        func_args,
        func_arg_types,
        loop_ranges,
        parfor_redvars,
        parfor_reddict,
        redarrs,
        parfor.init_block,
        index_var_typ,
        parfor.races)
    if config.DEBUG_ARRAY_OPT:
        sys.stdout.flush()

    if nredvars > 0:
        # Perform the final reduction across the reduction array created above.
        thread_count = get_thread_count()
        scope = parfor.init_block.scope
        loc = parfor.init_block.loc

        # For each reduction variable...
        for i in range(nredvars):
            name = parfor_redvars[i]
            redarr = redarrs[name]
            redvar_typ = lowerer.fndesc.typemap[name]

            if config.DEBUG_ARRAY_OPT_RUNTIME:
                res_print_str = "res_print"
                strconsttyp = types.StringLiteral(res_print_str)
                lhs = ir.Var(scope, mk_unique_var("str_const"), loc)
                assign_lhs = ir.Assign(value=ir.Const(value=res_print_str, loc=loc),
                                               target=lhs, loc=loc)
                typemap[lhs.name] = strconsttyp
                lowerer.lower_inst(assign_lhs)

                res_print = ir.Print(args=[lhs, redarr], vararg=None, loc=loc)
                lowerer.fndesc.calltypes[res_print] = signature(types.none,
                                                         typemap[lhs.name],
                                                         typemap[redarr.name])
                print("res_print", res_print)
                lowerer.lower_inst(res_print)

            # For each element in the reduction array created above.
            for j in range(get_thread_count()):
                # Create index var to access that element.
                index_var = ir.Var(scope, mk_unique_var("index_var"), loc)
                index_var_assign = ir.Assign(ir.Const(j, loc), index_var, loc)
                typemap[index_var.name] = types.uintp
                lowerer.lower_inst(index_var_assign)

                # Read that element from the array into oneelem.
                oneelem = ir.Var(scope, mk_unique_var("redelem"), loc)
                oneelemgetitem = ir.Expr.getitem(redarr, index_var, loc)
                typemap[oneelem.name] = redvar_typ
                lowerer.fndesc.calltypes[oneelemgetitem] = signature(redvar_typ,
                        typemap[redarr.name], typemap[index_var.name])
                oneelemassign = ir.Assign(oneelemgetitem, oneelem, loc)
                lowerer.lower_inst(oneelemassign)

                init_var = ir.Var(scope, name+"#init", loc)
                init_assign = ir.Assign(oneelem, init_var, loc)
                if name+"#init" not in typemap:
                    typemap[init_var.name] = redvar_typ
                lowerer.lower_inst(init_assign)

                if config.DEBUG_ARRAY_OPT_RUNTIME:
                    res_print_str = "one_res_print"
                    strconsttyp = types.StringLiteral(res_print_str)
                    lhs = ir.Var(scope, mk_unique_var("str_const"), loc)
                    assign_lhs = ir.Assign(value=ir.Const(value=res_print_str, loc=loc),
                                               target=lhs, loc=loc)
                    typemap[lhs.name] = strconsttyp
                    lowerer.lower_inst(assign_lhs)

                    res_print = ir.Print(args=[lhs, index_var, oneelem, init_var],
                                         vararg=None, loc=loc)
                    lowerer.fndesc.calltypes[res_print] = signature(types.none,
                                                             typemap[lhs.name],
                                                             typemap[index_var.name],
                                                             typemap[oneelem.name],
                                                             typemap[init_var.name])
                    print("res_print", res_print)
                    lowerer.lower_inst(res_print)

                # generate code for combining reduction variable with thread output
                for inst in parfor_reddict[name][1]:
                    # If we have a case where a parfor body has an array reduction like A += B
                    # and A and B have different data types then the reduction in the parallel
                    # region will operate on those differeing types.  However, here, after the
                    # parallel region, we are summing across the reduction array and that is
                    # guaranteed to have the same data type so we need to change the reduction
                    # nodes so that the right-hand sides have a type equal to the reduction-type
                    # and therefore the left-hand side.
                    if isinstance(inst, ir.Assign):
                        rhs = inst.value
                        # We probably need to generalize this since it only does substitutions in
                        # inplace_ginops.
                        if isinstance(rhs, ir.Expr) and rhs.op == 'inplace_binop' and rhs.rhs.name == init_var.name:
                            # Get calltype of rhs.
                            ct = lowerer.fndesc.calltypes[rhs]
                            assert(len(ct.args) == 2)
                            # Create new arg types replace the second arg type with the reduction var type.
                            ctargs = (ct.args[0], redvar_typ)
                            # Update the signature of the call.
                            ct = ct.replace(args=ctargs)
                            # Remove so we can re-insrt since calltypes is unique dict.
                            lowerer.fndesc.calltypes.pop(rhs)
                            # Add calltype back in for the expr with updated signature.
                            lowerer.fndesc.calltypes[rhs] = ct
                    lowerer.lower_inst(inst)

    # Restore the original typemap of the function that was replaced temporarily at the
    # Beginning of this function.
    lowerer.fndesc.typemap = orig_typemap

# A work-around to prevent circular imports
lowering.lower_extensions[parfor.Parfor] = _lower_parfor_parallel

def _create_shape_signature(
        get_shape_classes,
        num_inputs,
        num_reductions,
        args,
        redargstartdim,
        func_sig,
        races,
        typemap):
    '''Create shape signature for GUFunc
    '''
    if config.DEBUG_ARRAY_OPT:
        print("_create_shape_signature", num_inputs, num_reductions, args, redargstartdim)
        for i in args[1:]:
            print("argument", i, type(i), get_shape_classes(i, typemap=typemap))

    num_inouts = len(args) - num_reductions
    # maximum class number for array shapes
    classes = [get_shape_classes(var, typemap=typemap) if var not in races else (-1,) for var in args[1:]]
    class_set = set()
    for _class in classes:
        if _class:
            for i in _class:
                class_set.add(i)
    max_class = max(class_set) + 1 if class_set else 0
    classes.insert(0, (max_class,)) # force set the class of 'sched' argument
    class_set.add(max_class)
    class_map = {}
    # TODO: use prefix + class number instead of single char
    alphabet = ord('a')
    for n in class_set:
       if n >= 0:
           class_map[n] = chr(alphabet)
           alphabet += 1

    alpha_dict = {'latest_alpha' : alphabet}

    def bump_alpha(c, class_map):
        if c >= 0:
            return class_map[c]
        else:
            alpha_dict['latest_alpha'] += 1
            return chr(alpha_dict['latest_alpha'])

    gu_sin = []
    gu_sout = []
    count = 0
    syms_sin = ()
    if config.DEBUG_ARRAY_OPT:
        print("args", args)
        print("classes", classes)
    for cls, arg in zip(classes, args):
        count = count + 1
        if cls:
            dim_syms = tuple(bump_alpha(c, class_map) for c in cls)
        else:
            dim_syms = ()
        if (count > num_inouts):
            # Strip the first symbol corresponding to the number of workers
            # so that guvectorize will parallelize across the reduction.
            gu_sin.append(dim_syms[redargstartdim[arg]:])
        else:
            gu_sin.append(dim_syms)
            syms_sin += dim_syms
    return (gu_sin, gu_sout)

def _print_block(block):
    for i, inst in enumerate(block.body):
        print("    ", i, " ", inst)

def _print_body(body_dict):
    '''Pretty-print a set of IR blocks.
    '''
    for label, block in body_dict.items():
        print("label: ", label)
        _print_block(block)

def wrap_loop_body(loop_body):
    blocks = loop_body.copy()  # shallow copy is enough
    first_label = min(blocks.keys())
    last_label = max(blocks.keys())
    loc = blocks[last_label].loc
    blocks[last_label].body.append(ir.Jump(first_label, loc))
    return blocks

def unwrap_loop_body(loop_body):
    last_label = max(loop_body.keys())
    loop_body[last_label].body = loop_body[last_label].body[:-1]

def add_to_def_once_sets(a_def, def_once, def_more):
    '''If the variable is already defined more than once, do nothing.
       Else if defined exactly once previously then transition this
       variable to the defined more than once set (remove it from
       def_once set and add to def_more set).
       Else this must be the first time we've seen this variable defined
       so add to def_once set.
    '''
    if a_def in def_more:
        pass
    elif a_def in def_once:
        def_more.add(a_def)
        def_once.remove(a_def)
    else:
        def_once.add(a_def)

def compute_def_once_block(block, def_once, def_more, getattr_taken, typemap, module_assigns):
    '''Effect changes to the set of variables defined once or more than once
       for a single block.
       block - the block to process
       def_once - set of variable names known to be defined exactly once
       def_more - set of variable names known to be defined more than once
       getattr_taken - dict mapping variable name to tuple of object and attribute taken
       module_assigns - dict mapping variable name to the Global that they came from
    '''
    # The only "defs" occur in assignments, so find such instructions.
    assignments = block.find_insts(ir.Assign)
    # For each assignment...
    for one_assign in assignments:
        # Get the LHS/target of the assignment.
        a_def = one_assign.target.name
        # Add variable to def sets.
        add_to_def_once_sets(a_def, def_once, def_more)

        rhs = one_assign.value
        if isinstance(rhs, ir.Global):
            # Remember assignments of the form "a = Global(...)"
            # Is this a module?
            if isinstance(rhs.value, pytypes.ModuleType):
                module_assigns[a_def] = rhs.value.__name__
        if isinstance(rhs, ir.Expr) and rhs.op == 'getattr' and rhs.value.name in def_once:
            # Remember assignments of the form "a = b.c"
            getattr_taken[a_def] = (rhs.value.name, rhs.attr)
        if isinstance(rhs, ir.Expr) and rhs.op == 'call' and rhs.func.name in getattr_taken:
            # If "a" is being called then lookup the getattr definition of "a"
            # as above, getting the module variable "b" (base_obj)
            # and the attribute "c" (base_attr).
            base_obj, base_attr = getattr_taken[rhs.func.name]
            if base_obj in module_assigns:
                # If we know the definition of the module variable then get the module
                # name from module_assigns.
                base_mod_name = module_assigns[base_obj]
                if not is_const_call(base_mod_name, base_attr):
                    # Calling a method on an object could modify the object and is thus
                    # like a def of that object.  We call is_const_call to see if this module/attribute
                    # combination is known to not modify the module state.  If we don't know that
                    # the combination is safe then we have to assume there could be a modification to
                    # the module and thus add the module variable as defined more than once.
                    add_to_def_once_sets(base_obj, def_once, def_more)
            else:
                # Assume the worst and say that base_obj could be modified by the call.
                add_to_def_once_sets(base_obj, def_once, def_more)
        if isinstance(rhs, ir.Expr) and rhs.op == 'call':
            # If a mutable object is passed to a function, then it may be changed and
            # therefore can't be hoisted.
            # For each argument to the function...
            for argvar in rhs.args:
                # Get the argument's type.
                if isinstance(argvar, ir.Var):
                    argvar = argvar.name
                avtype = typemap[argvar]
                # If that type doesn't have a mutable attribute or it does and it's set to
                # not mutable then this usage is safe for hoisting.
                if getattr(avtype, 'mutable', False):
                    # Here we have a mutable variable passed to a function so add this variable
                    # to the def lists.
                    add_to_def_once_sets(argvar, def_once, def_more)

def compute_def_once_internal(loop_body, def_once, def_more, getattr_taken, typemap, module_assigns):
    '''Compute the set of variables defined exactly once in the given set of blocks
       and use the given sets for storing which variables are defined once, more than
       once and which have had a getattr call on them.
    '''
    # For each block...
    for label, block in loop_body.items():
        # Scan this block and effect changes to def_once, def_more, and getattr_taken
        # based on the instructions in that block.
        compute_def_once_block(block, def_once, def_more, getattr_taken, typemap, module_assigns)
        # Have to recursively process parfors manually here.
        for inst in block.body:
            if isinstance(inst, parfor.Parfor):
                # Recursively compute for the parfor's init block.
                compute_def_once_block(inst.init_block, def_once, def_more, getattr_taken, typemap, module_assigns)
                # Recursively compute for the parfor's loop body.
                compute_def_once_internal(inst.loop_body, def_once, def_more, getattr_taken, typemap, module_assigns)

def compute_def_once(loop_body, typemap):
    '''Compute the set of variables defined exactly once in the given set of blocks.
    '''
    def_once = set()   # set to hold variables defined exactly once
    def_more = set()   # set to hold variables defined more than once
    getattr_taken = {}
    module_assigns = {}
    compute_def_once_internal(loop_body, def_once, def_more, getattr_taken, typemap, module_assigns)
    return def_once

def find_vars(var, varset):
    assert isinstance(var, ir.Var)
    varset.add(var.name)
    return var

def _hoist_internal(inst, dep_on_param, call_table, hoisted, not_hoisted,
                    typemap):
    uses = set()
    visit_vars_inner(inst.value, find_vars, uses)
    diff = uses.difference(dep_on_param)
    if len(diff) == 0 and is_pure(inst.value, None, call_table):
        if config.DEBUG_ARRAY_OPT >= 1:
            print("Will hoist instruction", inst)
        hoisted.append(inst)
        if not isinstance(typemap[inst.target.name], types.npytypes.Array):
            dep_on_param += [inst.target.name]
        return True
    else:
        if len(diff) > 0:
            not_hoisted.append((inst, "dependency"))
            if config.DEBUG_ARRAY_OPT >= 1:
                print("Instruction", inst, " could not be hoisted because of a dependency.")
        else:
            not_hoisted.append((inst, "not pure"))
            if config.DEBUG_ARRAY_OPT >= 1:
                print("Instruction", inst, " could not be hoisted because it isn't pure.")
    return False

def find_setitems_block(setitems, block):
    for inst in block.body:
        if isinstance(inst, ir.StaticSetItem) or isinstance(inst, ir.SetItem):
            setitems.add(inst.target.name)
        elif isinstance(inst, parfor.Parfor):
            find_setitems_block(setitems, inst.init_block)
            find_setitems_body(setitems, inst.loop_body)

def find_setitems_body(setitems, loop_body):
    for label, block in loop_body.items():
        find_setitems_block(setitems, block)

def hoist(parfor_params, loop_body, typemap, wrapped_blocks):
    dep_on_param = copy.copy(parfor_params)
    hoisted = []
    not_hoisted = []

    # Compute the set of variable defined exactly once in the loop body.
    def_once = compute_def_once(loop_body, typemap)
    (call_table, reverse_call_table) = get_call_table(wrapped_blocks)

    setitems = set()
    find_setitems_body(setitems, loop_body)
    dep_on_param = list(set(dep_on_param).difference(setitems))

    for label, block in loop_body.items():
        new_block = []
        for inst in block.body:
            if isinstance(inst, ir.Assign) and inst.target.name in def_once:
                if _hoist_internal(inst, dep_on_param, call_table,
                                   hoisted, not_hoisted, typemap):
                    # don't add this instruction to the block since it is
                    # hoisted
                    continue
            elif isinstance(inst, parfor.Parfor):
                new_init_block = []
                if config.DEBUG_ARRAY_OPT >= 1:
                    print("parfor")
                    inst.dump()
                for ib_inst in inst.init_block.body:
                    if (isinstance(ib_inst, ir.Assign) and
                        ib_inst.target.name in def_once):
                        if _hoist_internal(ib_inst, dep_on_param, call_table,
                                           hoisted, not_hoisted, typemap):
                            # don't add this instuction to the block since it is hoisted
                            continue
                    new_init_block.append(ib_inst)
                inst.init_block.body = new_init_block

            new_block.append(inst)
        block.body = new_block
    return hoisted, not_hoisted

def redtyp_is_scalar(redtype):
    return not isinstance(redtype, types.npytypes.Array)

def redtyp_to_redarraytype(redtyp):
    """Go from a reducation variable type to a reduction array type used to hold
       per-worker results.
    """
    redarrdim = 1
    # If the reduction type is an array then allocate reduction array with ndim+1 dimensions.
    if isinstance(redtyp, types.npytypes.Array):
        redarrdim += redtyp.ndim
        # We don't create array of array but multi-dimensional reduciton array with same dtype.
        redtyp = redtyp.dtype
    return types.npytypes.Array(redtyp, redarrdim, "C")

def redarraytype_to_sig(redarraytyp):
    """Given a reduction array type, find the type of the reduction argument to the gufunc.
       Scalar and 1D array reduction both end up with 1D gufunc param type since scalars have to
       be passed as arrays.
    """
    assert isinstance(redarraytyp, types.npytypes.Array)
    return types.npytypes.Array(redarraytyp.dtype, max(1, redarraytyp.ndim - 1), redarraytyp.layout)

def legalize_names_with_typemap(names, typemap):
    """ We use ir_utils.legalize_names to replace internal IR variable names
        containing illegal characters (e.g. period) with a legal character
        (underscore) so as to create legal variable names.
        The original variable names are in the typemap so we also
        need to add the legalized name to the typemap as well.
    """
    outdict = legalize_names(names)
    # For each pair in the dict of legalized names...
    for x, y in outdict.items():
        # If the name had some legalization change to it...
        if x != y:
            # Set the type of the new name the same as the type of the old name.
            typemap[y] = typemap[x]
    return outdict

def _create_gufunc_for_parfor_body(
        lowerer,
        parfor,
        typemap,
        typingctx,
        targetctx,
        flags,
        locals,
        has_aliases,
        index_var_typ,
        races):
    '''
    Takes a parfor and creates a gufunc function for its body.
    There are two parts to this function.
    1) Code to iterate across the iteration space as defined by the schedule.
    2) The parfor body that does the work for a single point in the iteration space.
    Part 1 is created as Python text for simplicity with a sentinel assignment to mark the point
    in the IR where the parfor body should be added.
    This Python text is 'exec'ed into existence and its IR retrieved with run_frontend.
    The IR is scanned for the sentinel assignment where that basic block is split and the IR
    for the parfor body inserted.
    '''

    loc = parfor.init_block.loc

    # The parfor body and the main function body share ir.Var nodes.
    # We have to do some replacements of Var names in the parfor body to make them
    # legal parameter names.  If we don't copy then the Vars in the main function also
    # would incorrectly change their name.
    loop_body = copy.copy(parfor.loop_body)
    remove_dels(loop_body)

    parfor_dim = len(parfor.loop_nests)
    loop_indices = [l.index_variable.name for l in parfor.loop_nests]

    # Get all the parfor params.
    parfor_params = parfor.params
    # Get just the outputs of the parfor.
    parfor_outputs = numba.parfor.get_parfor_outputs(parfor, parfor_params)
    # Get all parfor reduction vars, and operators.
    typemap = lowerer.fndesc.typemap
    parfor_redvars, parfor_reddict = numba.parfor.get_parfor_reductions(
        parfor, parfor_params, lowerer.fndesc.calltypes)
    # Compute just the parfor inputs as a set difference.
    parfor_inputs = sorted(
        list(
            set(parfor_params) -
            set(parfor_outputs) -
            set(parfor_redvars)))

    races = races.difference(set(parfor_redvars))
    for race in races:
        msg = ("Variable %s used in parallel loop may be written "
               "to simultaneously by multiple workers and may result "
               "in non-deterministic or unintended results." % race)
        warnings.warn(NumbaParallelSafetyWarning(msg, loc))
    replace_var_with_array(races, loop_body, typemap, lowerer.fndesc.calltypes)

    if config.DEBUG_ARRAY_OPT >= 1:
        print("parfor_params = ", parfor_params, " ", type(parfor_params))
        print("parfor_outputs = ", parfor_outputs, " ", type(parfor_outputs))
        print("parfor_inputs = ", parfor_inputs, " ", type(parfor_inputs))
        print("parfor_redvars = ", parfor_redvars, " ", type(parfor_redvars))

    # Reduction variables are represented as arrays, so they go under
    # different names.
    parfor_redarrs = []
    parfor_red_arg_types = []
    for var in parfor_redvars:
        arr = var + "_arr"
        parfor_redarrs.append(arr)
        redarraytype = redtyp_to_redarraytype(typemap[var])
        parfor_red_arg_types.append(redarraytype)
        redarrsig = redarraytype_to_sig(redarraytype)
        if arr in typemap:
            assert(typemap[arr] == redarrsig)
        else:
            typemap[arr] = redarrsig

    # Reorder all the params so that inputs go first then outputs.
    parfor_params = parfor_inputs + parfor_outputs + parfor_redarrs

    if config.DEBUG_ARRAY_OPT >= 1:
        print("parfor_params = ", parfor_params, " ", type(parfor_params))
        print("loop_indices = ", loop_indices, " ", type(loop_indices))
        print("loop_body = ", loop_body, " ", type(loop_body))
        _print_body(loop_body)

    # Some Var are not legal parameter names so create a dict of potentially illegal
    # param name to guaranteed legal name.
    param_dict = legalize_names_with_typemap(parfor_params + parfor_redvars, typemap)
    if config.DEBUG_ARRAY_OPT >= 1:
        print(
            "param_dict = ",
            sorted(
                param_dict.items()),
            " ",
            type(param_dict))

    # Some loop_indices are not legal parameter names so create a dict of potentially illegal
    # loop index to guaranteed legal name.
    ind_dict = legalize_names_with_typemap(loop_indices, typemap)
    # Compute a new list of legal loop index names.
    legal_loop_indices = [ind_dict[v] for v in loop_indices]
    if config.DEBUG_ARRAY_OPT >= 1:
        print("ind_dict = ", sorted(ind_dict.items()), " ", type(ind_dict))
        print(
            "legal_loop_indices = ",
            legal_loop_indices,
            " ",
            type(legal_loop_indices))
        for pd in parfor_params:
            print("pd = ", pd)
            print("pd type = ", typemap[pd], " ", type(typemap[pd]))

    # Get the types of each parameter.
    param_types = [typemap[v] for v in parfor_params]
    # Calculate types of args passed to gufunc.
    func_arg_types = [typemap[v] for v in (parfor_inputs + parfor_outputs)] + parfor_red_arg_types

    # Replace illegal parameter names in the loop body with legal ones.
    replace_var_names(loop_body, param_dict)
    # remember the name before legalizing as the actual arguments
    parfor_args = parfor_params
    # Change parfor_params to be legal names.
    parfor_params = [param_dict[v] for v in parfor_params]
    parfor_params_orig = parfor_params

    parfor_params = []
    ascontig = False
    for pindex in range(len(parfor_params_orig)):
        if (ascontig and
            pindex < len(parfor_inputs) and
            isinstance(param_types[pindex], types.npytypes.Array)):
            parfor_params.append(parfor_params_orig[pindex]+"param")
        else:
            parfor_params.append(parfor_params_orig[pindex])

    # Change parfor body to replace illegal loop index vars with legal ones.
    replace_var_names(loop_body, ind_dict)
    loop_body_var_table = get_name_var_table(loop_body)
    sentinel_name = get_unused_var_name("__sentinel__", loop_body_var_table)

    if config.DEBUG_ARRAY_OPT >= 1:
        print(
            "legal parfor_params = ",
            parfor_params,
            " ",
            type(parfor_params))

    # Determine the unique names of the scheduling and gufunc functions.
    # sched_func_name = "__numba_parfor_sched_%s" % (hex(hash(parfor)).replace("-", "_"))
    gufunc_name = "__numba_parfor_gufunc_%s" % (
        hex(hash(parfor)).replace("-", "_"))
    if config.DEBUG_ARRAY_OPT:
        # print("sched_func_name ", type(sched_func_name), " ", sched_func_name)
        print("gufunc_name ", type(gufunc_name), " ", gufunc_name)

    gufunc_txt = ""

    # Create the gufunc function.
    gufunc_txt += "def " + gufunc_name + \
        "(sched, " + (", ".join(parfor_params)) + "):\n"

    for pindex in range(len(parfor_inputs)):
        if ascontig and isinstance(param_types[pindex], types.npytypes.Array):
            gufunc_txt += ("    " + parfor_params_orig[pindex]
                + " = np.ascontiguousarray(" + parfor_params[pindex] + ")\n")

    # Add initialization of reduction variables
    for arr, var in zip(parfor_redarrs, parfor_redvars):
        # If reduction variable is a scalar then save current value to
        # temp and accumulate on that temp to prevent false sharing.
        if redtyp_is_scalar(typemap[var]):
            gufunc_txt += "    " + param_dict[var] + \
                 "=" + param_dict[arr] + "[0]\n"
        else:
            # The reduction variable is an array so np.copy it to a temp.
            gufunc_txt += "    " + param_dict[var] + \
                 "=np.copy(" + param_dict[arr] + ")\n"

    # For each dimension of the parfor, create a for loop in the generated gufunc function.
    # Iterate across the proper values extracted from the schedule.
    # The form of the schedule is start_dim0, start_dim1, ..., start_dimN, end_dim0,
    # end_dim1, ..., end_dimN
    for eachdim in range(parfor_dim):
        for indent in range(eachdim + 1):
            gufunc_txt += "    "
        sched_dim = eachdim
        gufunc_txt += ("for " +
                       legal_loop_indices[eachdim] +
                       " in range(sched[" +
                       str(sched_dim) +
                       "], sched[" +
                       str(sched_dim +
                           parfor_dim) +
                       "] + np.uint8(1)):\n")

    if config.DEBUG_ARRAY_OPT_RUNTIME:
        for indent in range(parfor_dim + 1):
            gufunc_txt += "    "
        gufunc_txt += "print("
        for eachdim in range(parfor_dim):
            gufunc_txt += "\"" + legal_loop_indices[eachdim] + "\"," + legal_loop_indices[eachdim] + ","
        gufunc_txt += ")\n"

    # Add the sentinel assignment so that we can find the loop body position
    # in the IR.
    for indent in range(parfor_dim + 1):
        gufunc_txt += "    "
    gufunc_txt += sentinel_name + " = 0\n"
    # Add assignments of reduction variables (for returning the value)
    redargstartdim = {}
    for arr, var in zip(parfor_redarrs, parfor_redvars):
        # After the gufunc loops, copy the accumulated temp value back to reduction array.
        if redtyp_is_scalar(typemap[var]):
            gufunc_txt += "    " + param_dict[arr] + \
                "[0] = " + param_dict[var] + "\n"
            redargstartdim[arr] = 1
        else:
            # After the gufunc loops, copy the accumulated temp array back to reduction array with ":"
            gufunc_txt += "    " + param_dict[arr] + \
                "[:] = " + param_dict[var] + "[:]\n"
            redargstartdim[arr] = 0
    gufunc_txt += "    return None\n"

    if config.DEBUG_ARRAY_OPT:
        print("gufunc_txt = ", type(gufunc_txt), "\n", gufunc_txt)
    # Force gufunc outline into existence.
    globls = {"np": np}
    locls = {}
    exec_(gufunc_txt, globls, locls)
    gufunc_func = locls[gufunc_name]

    if config.DEBUG_ARRAY_OPT:
        print("gufunc_func = ", type(gufunc_func), "\n", gufunc_func)
    # Get the IR for the gufunc outline.
    gufunc_ir = compiler.run_frontend(gufunc_func)

    if config.DEBUG_ARRAY_OPT:
        print("gufunc_ir dump ", type(gufunc_ir))
        gufunc_ir.dump()
        print("loop_body dump ", type(loop_body))
        _print_body(loop_body)

    # rename all variables in gufunc_ir afresh
    var_table = get_name_var_table(gufunc_ir.blocks)
    new_var_dict = {}
    reserved_names = [sentinel_name] + \
        list(param_dict.values()) + legal_loop_indices
    for name, var in var_table.items():
        if not (name in reserved_names):
            new_var_dict[name] = mk_unique_var(name)
    replace_var_names(gufunc_ir.blocks, new_var_dict)
    if config.DEBUG_ARRAY_OPT:
        print("gufunc_ir dump after renaming ")
        gufunc_ir.dump()

    gufunc_param_types = [
        numba.types.npytypes.Array(
            index_var_typ, 1, "C")] + param_types
    if config.DEBUG_ARRAY_OPT:
        print(
            "gufunc_param_types = ",
            type(gufunc_param_types),
            "\n",
            gufunc_param_types)

    gufunc_stub_last_label = max(gufunc_ir.blocks.keys()) + 1

    # Add gufunc stub last label to each parfor.loop_body label to prevent
    # label conflicts.
    loop_body = add_offset_to_labels(loop_body, gufunc_stub_last_label)
    # new label for splitting sentinel block
    new_label = max(loop_body.keys()) + 1

    # If enabled, add a print statement after every assignment.
    if config.DEBUG_ARRAY_OPT_RUNTIME:
        for label, block in loop_body.items():
            new_block = block.copy()
            new_block.clear()
            loc = block.loc
            scope = block.scope
            for inst in block.body:
                new_block.append(inst)
                # Append print after assignment
                if isinstance(inst, ir.Assign):
                    # Only apply to numbers
                    if typemap[inst.target.name] not in types.number_domain:
                        continue

                    # Make constant string
                    strval = "{} =".format(inst.target.name)
                    strconsttyp = types.StringLiteral(strval)

                    lhs = ir.Var(scope, mk_unique_var("str_const"), loc)
                    assign_lhs = ir.Assign(value=ir.Const(value=strval, loc=loc),
                                           target=lhs, loc=loc)
                    typemap[lhs.name] = strconsttyp
                    new_block.append(assign_lhs)

                    # Make print node
                    print_node = ir.Print(args=[lhs, inst.target], vararg=None, loc=loc)
                    new_block.append(print_node)
                    sig = numba.typing.signature(types.none,
                                           typemap[lhs.name],
                                           typemap[inst.target.name])
                    lowerer.fndesc.calltypes[print_node] = sig
            loop_body[label] = new_block

    if config.DEBUG_ARRAY_OPT:
        print("parfor loop body")
        _print_body(loop_body)

    wrapped_blocks = wrap_loop_body(loop_body)
    hoisted, not_hoisted = hoist(parfor_params, loop_body, typemap, wrapped_blocks)
    start_block = gufunc_ir.blocks[min(gufunc_ir.blocks.keys())]
    start_block.body = start_block.body[:-1] + hoisted + [start_block.body[-1]]
    unwrap_loop_body(loop_body)

    # store hoisted into diagnostics
    diagnostics = lowerer.metadata['parfor_diagnostics']
    diagnostics.hoist_info[parfor.id] = {'hoisted': hoisted,
                                         'not_hoisted': not_hoisted}

    if config.DEBUG_ARRAY_OPT:
        print("After hoisting")
        _print_body(loop_body)

    # Search all the block in the gufunc outline for the sentinel assignment.
    for label, block in gufunc_ir.blocks.items():
        for i, inst in enumerate(block.body):
            if isinstance(
                    inst,
                    ir.Assign) and inst.target.name == sentinel_name:
                # We found the sentinel assignment.
                loc = inst.loc
                scope = block.scope
                # split block across __sentinel__
                # A new block is allocated for the statements prior to the sentinel
                # but the new block maintains the current block label.
                prev_block = ir.Block(scope, loc)
                prev_block.body = block.body[:i]
                # The current block is used for statements after the sentinel.
                block.body = block.body[i + 1:]
                # But the current block gets a new label.
                body_first_label = min(loop_body.keys())

                # The previous block jumps to the minimum labelled block of the
                # parfor body.
                prev_block.append(ir.Jump(body_first_label, loc))
                # Add all the parfor loop body blocks to the gufunc function's
                # IR.
                for (l, b) in loop_body.items():
                    gufunc_ir.blocks[l] = b
                body_last_label = max(loop_body.keys())
                gufunc_ir.blocks[new_label] = block
                gufunc_ir.blocks[label] = prev_block
                # Add a jump from the last parfor body block to the block containing
                # statements after the sentinel.
                gufunc_ir.blocks[body_last_label].append(
                    ir.Jump(new_label, loc))
                break
        else:
            continue
        break

    if config.DEBUG_ARRAY_OPT:
        print("gufunc_ir last dump before renaming")
        gufunc_ir.dump()

    gufunc_ir.blocks = rename_labels(gufunc_ir.blocks)
    remove_dels(gufunc_ir.blocks)

    if config.DEBUG_ARRAY_OPT:
        print("gufunc_ir last dump")
        gufunc_ir.dump()
        print("flags", flags)
        print("typemap", typemap)

    old_alias = flags.noalias
    if not has_aliases:
        if config.DEBUG_ARRAY_OPT:
            print("No aliases found so adding noalias flag.")
        flags.noalias = True
    kernel_func = compiler.compile_ir(
        typingctx,
        targetctx,
        gufunc_ir,
        gufunc_param_types,
        types.none,
        flags,
        locals)

    flags.noalias = old_alias

    kernel_sig = signature(types.none, *gufunc_param_types)
    if config.DEBUG_ARRAY_OPT:
        print("kernel_sig = ", kernel_sig)

    return kernel_func, parfor_args, kernel_sig, redargstartdim, func_arg_types

def replace_var_with_array_in_block(vars, block, typemap, calltypes):
    new_block = []
    for inst in block.body:
        if isinstance(inst, ir.Assign) and inst.target.name in vars:
            const_node = ir.Const(0, inst.loc)
            const_var = ir.Var(inst.target.scope, mk_unique_var("$const_ind_0"), inst.loc)
            typemap[const_var.name] = types.uintp
            const_assign = ir.Assign(const_node, const_var, inst.loc)
            new_block.append(const_assign)

            setitem_node = ir.SetItem(inst.target, const_var, inst.value, inst.loc)
            calltypes[setitem_node] = signature(
                types.none, types.npytypes.Array(typemap[inst.target.name], 1, "C"), types.intp, typemap[inst.target.name])
            new_block.append(setitem_node)
            continue
        elif isinstance(inst, parfor.Parfor):
            replace_var_with_array_internal(vars, {0: inst.init_block}, typemap, calltypes)
            replace_var_with_array_internal(vars, inst.loop_body, typemap, calltypes)

        new_block.append(inst)
    return new_block

def replace_var_with_array_internal(vars, loop_body, typemap, calltypes):
    for label, block in loop_body.items():
        block.body = replace_var_with_array_in_block(vars, block, typemap, calltypes)

def replace_var_with_array(vars, loop_body, typemap, calltypes):
    replace_var_with_array_internal(vars, loop_body, typemap, calltypes)
    for v in vars:
        el_typ = typemap[v]
        typemap.pop(v, None)
        typemap[v] = types.npytypes.Array(el_typ, 1, "C")

def call_parallel_gufunc(lowerer, cres, gu_signature, outer_sig, expr_args, expr_arg_types,
                         loop_ranges, redvars, reddict, redarrdict, init_block, index_var_typ, races):
    '''
    Adds the call to the gufunc function from the main function.
    '''
    context = lowerer.context
    builder = lowerer.builder

    from .parallel import (build_gufunc_wrapper,
                           get_thread_count,
                           _launch_threads)

    if config.DEBUG_ARRAY_OPT:
        print("make_parallel_loop")
        print("args = ", expr_args)
        print("outer_sig = ", outer_sig.args, outer_sig.return_type,
              outer_sig.recvr, outer_sig.pysig)
        print("loop_ranges = ", loop_ranges)
        print("expr_args", expr_args)
        print("expr_arg_types", expr_arg_types)
        print("gu_signature", gu_signature)

    # Build the wrapper for GUFunc
    args, return_type = sigutils.normalize_signature(outer_sig)
    llvm_func = cres.library.get_function(cres.fndesc.llvm_func_name)
    sin, sout = gu_signature

    # These are necessary for build_gufunc_wrapper to find external symbols
    _launch_threads()

    info = build_gufunc_wrapper(llvm_func, cres, sin, sout,
                                cache=False, is_parfors=True)
    wrapper_name = info.name
    cres.library._ensure_finalized()

    if config.DEBUG_ARRAY_OPT:
        print("parallel function = ", wrapper_name, cres)

    # loadvars for loop_ranges
    def load_range(v):
        if isinstance(v, ir.Var):
            return lowerer.loadvar(v.name)
        else:
            return context.get_constant(types.uintp, v)

    num_dim = len(loop_ranges)
    for i in range(num_dim):
        start, stop, step = loop_ranges[i]
        start = load_range(start)
        stop = load_range(stop)
        assert(step == 1)  # We do not support loop steps other than 1
        step = load_range(step)
        loop_ranges[i] = (start, stop, step)

        if config.DEBUG_ARRAY_OPT:
            print("call_parallel_gufunc loop_ranges[{}] = ".format(i), start,
                  stop, step)
            cgutils.printf(builder, "loop range[{}]: %d %d (%d)\n".format(i),
                           start, stop, step)

    # Commonly used LLVM types and constants
    byte_t = lc.Type.int(8)
    byte_ptr_t = lc.Type.pointer(byte_t)
    byte_ptr_ptr_t = lc.Type.pointer(byte_ptr_t)
    intp_t = context.get_value_type(types.intp)
    uintp_t = context.get_value_type(types.uintp)
    intp_ptr_t = lc.Type.pointer(intp_t)
    uintp_ptr_t = lc.Type.pointer(uintp_t)
    zero = context.get_constant(types.uintp, 0)
    one = context.get_constant(types.uintp, 1)
    one_type = one.type
    sizeof_intp = context.get_abi_sizeof(intp_t)

    # Prepare sched, first pop it out of expr_args, outer_sig, and gu_signature
    expr_args.pop(0)
    sched_sig = sin.pop(0)

    if config.DEBUG_ARRAY_OPT:
        print("Parfor has potentially negative start", index_var_typ.signed)

    if index_var_typ.signed:
        sched_type = intp_t
        sched_ptr_type = intp_ptr_t
    else:
        sched_type = uintp_t
        sched_ptr_type = uintp_ptr_t

    # Call do_scheduling with appropriate arguments
    dim_starts = cgutils.alloca_once(
        builder, sched_type, size=context.get_constant(
            types.uintp, num_dim), name="dims")
    dim_stops = cgutils.alloca_once(
        builder, sched_type, size=context.get_constant(
            types.uintp, num_dim), name="dims")
    for i in range(num_dim):
        start, stop, step = loop_ranges[i]
        if start.type != one_type:
            start = builder.sext(start, one_type)
        if stop.type != one_type:
            stop = builder.sext(stop, one_type)
        if step.type != one_type:
            step = builder.sext(step, one_type)
        # substract 1 because do-scheduling takes inclusive ranges
        stop = builder.sub(stop, one)
        builder.store(
            start, builder.gep(
                dim_starts, [
                    context.get_constant(
                        types.uintp, i)]))
        builder.store(stop, builder.gep(dim_stops,
                                        [context.get_constant(types.uintp, i)]))

    sched_size = get_thread_count() * num_dim * 2
    sched = cgutils.alloca_once(
        builder, sched_type, size=context.get_constant(
            types.uintp, sched_size), name="sched")
    debug_flag = 1 if config.DEBUG_ARRAY_OPT else 0
    scheduling_fnty = lc.Type.function(
        intp_ptr_t, [uintp_t, sched_ptr_type, sched_ptr_type, uintp_t, sched_ptr_type, intp_t])
    if index_var_typ.signed:
        do_scheduling = builder.module.get_or_insert_function(scheduling_fnty,
                                                          name="do_scheduling_signed")
    else:
        do_scheduling = builder.module.get_or_insert_function(scheduling_fnty,
                                                          name="do_scheduling_unsigned")

    builder.call(
        do_scheduling, [
            context.get_constant(
                types.uintp, num_dim), dim_starts, dim_stops, context.get_constant(
                types.uintp, get_thread_count()), sched, context.get_constant(
                    types.intp, debug_flag)])

    # Get the LLVM vars for the Numba IR reduction array vars.
    redarrs = [lowerer.loadvar(redarrdict[x].name) for x in redvars]

    nredvars = len(redvars)
    ninouts = len(expr_args) - nredvars

    if config.DEBUG_ARRAY_OPT:
        for i in range(get_thread_count()):
            cgutils.printf(builder, "sched[" + str(i) + "] = ")
            for j in range(num_dim * 2):
                cgutils.printf(
                    builder, "%d ", builder.load(
                        builder.gep(
                            sched, [
                                context.get_constant(
                                    types.intp, i * num_dim * 2 + j)])))
            cgutils.printf(builder, "\n")

    # ----------------------------------------------------------------------------
    # Prepare arguments: args, shapes, steps, data
    all_args = [lowerer.loadvar(x) for x in expr_args[:ninouts]] + redarrs
    num_args = len(all_args)
    num_inps = len(sin) + 1
    args = cgutils.alloca_once(
        builder,
        byte_ptr_t,
        size=context.get_constant(
            types.intp,
            1 + num_args),
        name="pargs")
    array_strides = []
    # sched goes first
    builder.store(builder.bitcast(sched, byte_ptr_t), args)
    array_strides.append(context.get_constant(types.intp, sizeof_intp))
    red_shapes = {}
    rv_to_arg_dict = {}
    # followed by other arguments
    for i in range(num_args):
        arg = all_args[i]
        var = expr_args[i]
        aty = expr_arg_types[i]
        dst = builder.gep(args, [context.get_constant(types.intp, i + 1)])
        if i >= ninouts:  # reduction variables
            ary = context.make_array(aty)(context, builder, arg)
            strides = cgutils.unpack_tuple(builder, ary.strides, aty.ndim)
            ary_shapes = cgutils.unpack_tuple(builder, ary.shape, aty.ndim)
            # Start from 1 because we skip the first dimension of length num_threads just like sched.
            for j in range(1, len(strides)):
                array_strides.append(strides[j])
            red_shapes[i] = ary_shapes[1:]
            builder.store(builder.bitcast(ary.data, byte_ptr_t), dst)
        elif isinstance(aty, types.ArrayCompatible):
            if var in races:
                typ = context.get_data_type(
                    aty.dtype) if aty.dtype != types.boolean else lc.Type.int(1)

                rv_arg = cgutils.alloca_once(builder, typ)
                builder.store(arg, rv_arg)
                builder.store(builder.bitcast(rv_arg, byte_ptr_t), dst)
                rv_to_arg_dict[var] = (arg, rv_arg)

                array_strides.append(context.get_constant(types.intp, context.get_abi_sizeof(typ)))
            else:
                ary = context.make_array(aty)(context, builder, arg)
                strides = cgutils.unpack_tuple(builder, ary.strides, aty.ndim)
                for j in range(len(strides)):
                    array_strides.append(strides[j])
                builder.store(builder.bitcast(ary.data, byte_ptr_t), dst)
        else:
            if i < num_inps:
                # Scalar input, need to store the value in an array of size 1
                typ = context.get_data_type(
                    aty) if aty != types.boolean else lc.Type.int(1)
                ptr = cgutils.alloca_once(builder, typ)
                builder.store(arg, ptr)
            else:
                # Scalar output, must allocate
                typ = context.get_data_type(
                    aty) if aty != types.boolean else lc.Type.int(1)
                ptr = cgutils.alloca_once(builder, typ)
            builder.store(builder.bitcast(ptr, byte_ptr_t), dst)

    # ----------------------------------------------------------------------------
    # Next, we prepare the individual dimension info recorded in gu_signature
    sig_dim_dict = {}
    occurances = []
    occurances = [sched_sig[0]]
    sig_dim_dict[sched_sig[0]] = context.get_constant(types.intp, 2 * num_dim)
    assert len(expr_args) == len(all_args)
    assert len(expr_args) == len(expr_arg_types)
    assert len(expr_args) == len(sin + sout)
    assert len(expr_args) == len(outer_sig.args[1:])
    for var, arg, aty, gu_sig in zip(expr_args, all_args,
                                     expr_arg_types, sin + sout):
        if isinstance(aty, types.npytypes.Array):
            i = aty.ndim - len(gu_sig)
        else:
            i = 0
        if config.DEBUG_ARRAY_OPT:
            print("var =", var, "gu_sig =", gu_sig, "type =", aty, "i =", i)

        for dim_sym in gu_sig:
            if config.DEBUG_ARRAY_OPT:
                print("var = ", var, " type = ", aty)
            if var in races:
                sig_dim_dict[dim_sym] = context.get_constant(types.intp, 1)
            else:
                ary = context.make_array(aty)(context, builder, arg)
                shapes = cgutils.unpack_tuple(builder, ary.shape, aty.ndim)
                sig_dim_dict[dim_sym] = shapes[i]

            if not (dim_sym in occurances):
                if config.DEBUG_ARRAY_OPT:
                    print("dim_sym = ", dim_sym, ", i = ", i)
                    cgutils.printf(builder, dim_sym + " = %d\n", sig_dim_dict[dim_sym])
                occurances.append(dim_sym)
            i = i + 1

    # ----------------------------------------------------------------------------
    # Prepare shapes, which is a single number (outer loop size), followed by
    # the size of individual shape variables.
    nshapes = len(sig_dim_dict) + 1
    shapes = cgutils.alloca_once(builder, intp_t, size=nshapes, name="pshape")
    # For now, outer loop size is the same as number of threads
    builder.store(context.get_constant(types.intp, get_thread_count()), shapes)
    # Individual shape variables go next
    i = 1
    for dim_sym in occurances:
        if config.DEBUG_ARRAY_OPT:
            cgutils.printf(builder, dim_sym + " = %d\n", sig_dim_dict[dim_sym])
        builder.store(
            sig_dim_dict[dim_sym], builder.gep(
                shapes, [
                    context.get_constant(
                        types.intp, i)]))
        i = i + 1

    # ----------------------------------------------------------------------------
    # Prepare steps for each argument. Note that all steps are counted in
    # bytes.
    num_steps = num_args + 1 + len(array_strides)
    steps = cgutils.alloca_once(
        builder, intp_t, size=context.get_constant(
            types.intp, num_steps), name="psteps")
    # First goes the step size for sched, which is 2 * num_dim
    builder.store(context.get_constant(types.intp, 2 * num_dim * sizeof_intp),
                  steps)
    # The steps for all others are 0, except for reduction results.
    for i in range(num_args):
        if i >= ninouts:  # steps for reduction vars are abi_sizeof(typ)
            j = i - ninouts
            # Get the base dtype of the reduction array.
            redtyp = lowerer.fndesc.typemap[redvars[j]]
            red_stride = None
            if isinstance(redtyp, types.npytypes.Array):
                redtyp = redtyp.dtype
                red_stride = red_shapes[i]
            typ = context.get_value_type(redtyp)
            sizeof = context.get_abi_sizeof(typ)
            # Set stepsize to the size of that dtype.
            stepsize = context.get_constant(types.intp, sizeof)
            if red_stride is not None:
                for rs in red_stride:
                    stepsize = builder.mul(stepsize, rs)
        else:
            # steps are strides
            stepsize = zero
        dst = builder.gep(steps, [context.get_constant(types.intp, 1 + i)])
        builder.store(stepsize, dst)
    for j in range(len(array_strides)):
        dst = builder.gep(
            steps, [
                context.get_constant(
                    types.intp, 1 + num_args + j)])
        builder.store(array_strides[j], dst)

    # ----------------------------------------------------------------------------
    # prepare data
    data = cgutils.get_null_value(byte_ptr_t)

    fnty = lc.Type.function(lc.Type.void(), [byte_ptr_ptr_t, intp_ptr_t,
                                             intp_ptr_t, byte_ptr_t])

    fn = builder.module.get_or_insert_function(fnty, name=wrapper_name)
    context.active_code_library.add_linking_library(info.library)

    if config.DEBUG_ARRAY_OPT:
        cgutils.printf(builder, "before calling kernel %p\n", fn)
    builder.call(fn, [args, shapes, steps, data])
    if config.DEBUG_ARRAY_OPT:
        cgutils.printf(builder, "after calling kernel %p\n", fn)

    for k, v in rv_to_arg_dict.items():
        arg, rv_arg = v
        only_elem_ptr = builder.gep(rv_arg, [context.get_constant(types.intp, 0)])
        builder.store(builder.load(only_elem_ptr), lowerer.getvar(k))

    context.active_code_library.add_linking_library(cres.library)


text:
Marc Almond and Foetus
In Music Reviews
Boy, if you want to clear the house, this will do it. Of course, this shouldn't be a surprise to anyone familiar with Foetus and his various collaborations over, what is it now, fifteen years? This one's with Marc Almond, who I remember from Soft Cell and "Tainted Love."
Apparently, Slut was originally released more than ten years ago in Europe, with the band listed as "Flesh Volcano." Catchy…
As one would expect, the music is generally a schizophrenic mish-mash of tribal drums, grunts, free-verse, and the occasional harpsichord. The title track sounds as though it was recorded in a jungle during a fertility ritual ("Slut! Slut!"), or maybe an anthem to loose women… Regardless, it's way the heck out there in avant garde land. "The Universal Cess Pool" and "Bruise N Chain" sound as though they were performed with kitchen utensils and sung through aluminum funnels. If you aren't familiar with the anti-music that characterizes any Foetus collaboration, what I'm saying is this: this gets as close as possible to the edge of the fence separating noise from music.
However, there are two treats on Slut — "A Million Manias" sounds like a classic Raymond Scott manic mechanical jazz tune, and "Beat Out the Rhythm on a Drum" is simply Marc Almond singing "Beat Out the Rhythm on a Drum" over and over again to the tune of a well-known light opera song I can't recall, but I know I've heard it before! For you Foetus purists, come and get it. For the rest of you, this is a very disturbing record. For real Reagan-era bohemians only. Thirsty Ear Recordings, 274 Madison Ave., Suite 804, New York, NY 10016;
David Lee Beowülf
David Lee Beowulf
PJ Olsson
Interview by Gail Worley
One Day I'll Be on Time (Tiger Style). Review by Marcel Feldmar.
Wasteland (In The Red). Review by Julius C. Lacking.
White Witch (Capricorn). Review by David Lee Beowülf
Jets To Brazil
Interview by Andrew Chadwick
Broadway Calls
Broadway Calls (Adeline). Review by Carl F Gauze.
The Waybacks
Burger After Church (Fiddling Cricket). Review by David Whited.
Wylie and the Wild West
Total Yodel! (Rounder). Review by Mark Chester
The Beat Assassinated (Inflammable/Globetrotter/Sony). Review by Carole Jaszewski
Sing This to Yourself and Other Suggestions for a Personal Apocalypse (Charnel Grounds). Review by P. McEver.
The Aquavelvets
Guitar Noir (Milan/BMG). Review by David Lee Beowülf
Naughty Appliances III
Various Artists (Hippo). Review by J.R. Toadwomen

redpajama_set_name: RedPajamaCommonCrawl


Number 125160524 has 9 digits. Number 125160524 can be formatted as 125,160,524 or 125.160.524 or 125 160 524 or in case this was a phone number 125-160-524 or 12-516-0524 to be easier to read. Number 125160524 in English words is "one hundred and twenty-five million, one hundred and sixty thousand, five hundred and twenty-four". Number 125160524 can be read by triplets (groups of 3 digits) as "one hundred and twenty-five, one hundred and sixty, five hundred and twenty-four". Number 125160524 can be read digit by digit as "one two five one six zero five two four". Number 125160524 is even. Number 125160524 is divisible by: two, four. Number 125160524 is a composite number (non-prime number).
Number 125160524 in binary code is 111011101011100110001001100. Number 125160524 in octal code is: 735346114. Number 125160524 in hexadecimal (hexa): 775cc4c.
The sum of all digits of this number is 26. The digital root (repeated digital sum until you get single-digit number) is 8. Number 125160524 divided by two (halved) equals 62580262. Number 125160524 multiplied by two (doubled) equals 250321048. Number 125160524 multiplied by ten equals 1251605240. Number 125160524 raised to the power of 2 equals 1.5665156767955E+16. Number 125160524 raised to the power of 3 equals 1.9606592296193E+24. The square root (sqrt) of 125160524 is 11187.516435742. The sine (sin) of 125160524 degree is 0.69465837043816. The cosine (cos) of 125160524 degree is 0.71933980035878. The base-10 logarithm of 125160524 equals 8.0974673727055. The natural logarithm of 125160524 equals 18.645107663397. The number 125160524 can be encoded to characters as ABEAFJEBD. The number 125160524 can be encrypted to chemical element names as hydrogen, helium, boron, hydrogen, carbon, neon, boron, helium, beryllium.
626041037, 5274880905, 606613079, 570076970, 657600167, 606243693, 610523964, 835712830, 1869908277, 10615048, 696326091, 670695613, 437240744, 292220361, 758924232, 734127901, 703761371, 209757721, 555710125, 246762508, 5426130774, 870535257, 4586650202, 362830580, 446383511, 947409345, 1826719185, 379468924, 5101553755, 384599472, 373234670, 2879812596, 3803433659, 387370493, 277573674, 149363785, 487139203, 9733237945, 726147131, 591460071, 7096000039, 315240247.


Paper Train - Level Pack is provided to you by GamingCloud and is categorized into the simulation games, and traffic management games. This game was played 1,257 times and currently has a rating of 3.25 out of 5.00. GamingCloud.com is your first source on the Internet regarding Flash, HTML5, Unity and online games. Find new online games everyday and play them with your favorite web browser.
Have fun with Paper Train - Level Pack!
The cloud of online games on the Internet. Thousands of flash games free to play organized by category (action, sport, adventure, fight, simulation, shoot, ...).
We try to add the best games. We attach great importance to their quality. Each game comes with a description and when it is possible with a help topic.


Do you feel GTA V did a good job recreating the world of Los Angeles?
I don't know -- I didn't see any homeless people cursing at people or engaging in other anti-social behavior.
Iirc there are homeless people throughout the game's city, and there's actually a mod that puts crazy homeless people everywhere, rampaging the city.
Seriously? If that's true, I need a new computer and gaming card so I can try this.


text:
Home › SECActions › WILL REOGRANIZATION REVITALIZE SEC ENFORCEMENT?
WILL REOGRANIZATION REVITALIZE SEC ENFORCEMENT?
T. GormanPosted on July 08, 2009 Posted in SECActions
The SEC Enforcement Division is about to be reorganized in an effort to revitalize the once highly respected program. The focus of the reorganization, according to a report from Bloomberg, is to streamline operations and add efficiency. The question is, will it revitalize the Enforcement Division?
The reorganization, billed as the largest in three decades, will eliminate supervisory positions and excess layers of management to create more front line investigators while adding expertise. Overall there will be five specialist teams focused on particularly difficult areas of the market, according to the report. In addition, Enforcement Director Robert Khuzami, recently brought in by Chairman Schapiro, has hired Lorin Reisner as his deputy. Mr. Reisner is a former prosecutor who has been in private practice.
More front line investigators are critical to effectively carrying out the mission of the Enforcement Division. It should permit the Division to return to basics, beginning with better case intake and a more critical evaluation of evidence done on a first hand basis by experienced investigators. This is clearly preferable to the current system which evidence is evaluated by layers of supervisory staff based largely on summaries from junior attorneys.
Investigations and an evaluation of evidence to determine if there are possible violations of the federal securities laws are the key focus of the Enforcement Division after all. They are designed to protect investors and ensure the integrity of the markets. Critical to that mission is the discovery of a possible violation at the earliest possible time. This has been highlighted recently by the Madoff debacle. Clearly, the SEC cannot stop someone like Mr. Madoff at inception. Equally clear however, is the fact that Mr. Madoff could have been stopped at a much earlier point. Moving the point of detection as close as possible to the time the improper conduct begins maximizes investor protection. It also can help prevent future violations by creating the aura of an effective cop on the beat. If the reorganization puts more investigators to work sifting the evidence, it should serve as a good beginning to revitalizing the Division.
While the precise structure of the reorganization is unclear, it is not critical. Regardless of whether the current structure is used or some other model or organization chart, the critical point is to have more front line investigators working the investigations and evaluating the evidence. This focus should also help speed the work of the Division because it necessarily implies less layers of supervision and reporting which can bog down the inquiry.
Finally, while the Division can no doubt benefit from additional expertise, before looking outside the agency, the Enforcement Director would do well to evaluate the manner in which the Enforcement staff works with other divisions of the staff. The Commission's staff has many talented professionals with significant expertise in the operation of the securities markets. A critical step in rejuvenating Enforcement is to make sure that the Division draws on and utilizes that expertise. If that expertise is fully utilized, and Enforcement focuses on having more front line investigators sifting evidence and evaluating possible cases, the Division will have a sound foundation from which to move forward toward once again being Wall Street's top cop and the protector of investors and the markets.
‹ PART I: PLEADING REQUIRMENTS UNDER DURA — INTRODUCTION
AUDITORS UNCOVER FRAUD ›


Septime's little sister Clamato is another place where I could easily eat everyday. Incredibly fresh fish, fantastic flavors and perhaps the best service that I had on this trip.
Definitely go at opening to the Little Red Door. What an incredibly cute bar and I absolutely loved the architecture based menu concept.
With a fitting name meaning 'beautiful mess' in Hebrew, Balagan is certainly un-Parisian aside from being part of the Experimental Group. While quite a scene, it is incredibly energetic and I couldn't help but have an amazing time. And the food was amazing…that pictured as well as a few extras that I didn't photograph.


This image gallery named as C21 Cheap Price Purple Chaise Lounge Furniture Buy might be ideal solution for your decoration. As the author has insert this image into Purple Chaise Lounge post section, would ease you to find the perfect match of you decor desire.
Now, the modern chaise longue has also been united with other elements to impress the modern-classic design. This type of c21 cheap price purple chaise lounge furniture buy also arrive in many forms such as settee bed chaise lounge, lazy chair cushions, wide chaise lounge, etc. The substances for earning a couch chaise sofa have become varied, such as for example timber, wire, iron, steel, etc.. Chaise chair may be 1 among the most obvious elements to beautify your own room. In addition to its function which can function like a chair and also bed, in addition, it acts as a room decoration. In the event you are interested in purchasing one, then you are suggested select the one which includes a delicate coating feel, so which you could take a break about it professionally.
The dining room is one of those important room from the house. It is a space where all the relatives eventually become romantic after a very long day of work or activity from ingestion with each other. So, deciding on a c21 cheap price purple chaise lounge furniture buy to your dining table room must have achieved in a mindful manner. In case the assignment style chair is used for uncomplicated tasting dwelling, you then may want to go for an antique or official kind of chair these as for example purple chase lounge in case your house features Language model or old style. By choosing this type of chair, the stylish vibe and aura will undoubtedly be replenishing the Diningroom. Ordinarily, this type of dining room can be used if there's an official dinner with colleagues or having friends . Effectively, regardless of the sort of chairs you decide on, it's necessary for you to meet them along with your house style so it's not going to feel weird or out of position.
The development of art, sciencetechnology, accompanied by the growth of various ideological moves straight affected the c21 cheap price purple chaise lounge furniture buy specifically, and are considered being a brand new production of industrialized art. This makes the modern chairs do not merely become the tool to assist seats, nevertheless they also become items that represent your characteristics, preferences, fashions, and maybe lessons. However, once selecting modern day chairs on your house, stability also has to be noticed, between your chair as well as the interior-design that you simply apply, so it will create a beautiful look. In addition, you have to adjust how big this wide chaise lounge which you select. Otherwise, they will get your space feel more crowded. In the event you pick the right layout, measurement, and color of your modern chairs, the visitors who come to your house will surely feel comfortable residing within the place to get a very long time. The most unique and innovative layout of your new chairs means nothing should they fail to supply an appropriate seating experience to you and your visitors.
If people are able to work by sitting on the correct c21 cheap price purple chaise lounge furniture buy, this usually means that they can keep their own productivity. At an identical timethey will also be in a position to avoid the dropped hours caused by injuries. To stop the accident notably the spine accident, they have to select the cozy chair completed with all the fullback. The rankings should also find a way to adjust together with recline, peak, and lumbar aid preferences. The purple chase lounge should have the Water fall in the front of the seat. It is helpful in order that they will not be caught from the seat behind your own knees. The contoured seat pan should be found as well for even distribution of fat and relaxation.


PARIS (Reuters) - A Paris gallery is offering visitors the chance to immerse themselves in the colourscapes of Vincent Van Gogh like never before.
Conveying at different stages the illusion of water rippling in the light and raindrops falling, the show is accompanied by a rich soundtrack.
"Obviously, we have "The Starry Night," we have the sunflowers, we have the irises," gallery director Michael Couzigou told Reuters TV.
"Van Gogh, La Nuit Etoilée", which opens on Friday and runs until Dec 31, is the gallery's second immersive art project, following a Gustav Klimt show in 2018.


Dr. Lim is Great! He has given me the smile of my dreams! I've been going to his practice since I was a kid and I've always felt comfortable and at home there. His staff and himself offer the best care to their patients and act in our best interest. I just love them! Thanks for everything Dr. Lim!


Three recent cartoons in my feed that depend on their readers supplying crucial bits of background cultural information: a Rhymes With Orange from the 1st (the eating habits of Japanese movie monsters); a Mother Goose and Grimm from the 1st (the His Master's Voice dog); and today's Bizarro/Wayno collab (clergy visiting parishioners).
In each case, the cartoon shows some situation from everyday life (which you have to know about) juxtaposed with, or translated into, another more remarkable world (which you also need to know details of).
Rhymes: workers feeding creatures on lunch break, the appetities of Japanese movie monsters.
The everyday situation is workers having their lunches, out of doors if possible, on benches, in a park if there's one close by.
Anywhere out of doors, they're importuned by creatures (pigeons, but especially cheeky squirrels) for bits of food.
#1 maps the lunch-break world into the world of kaiju, Japanese monsters, especially in the movies.
MGG: finicky audiophiles, Nipper the phonograph dog (and the dogs Grimm and Ralph).
The everyday situation is a complaint about the passion of some men for audio perfection, especially over the superiority of recordings on vinyl disks — records — over later media. All of that has been translated into the world of dogs: the talking (and generally very anthropomorphic) dogs Grimm and Ralph from MGG, as they view their audiophile companion, who you have to recognize as the dog advertising various phonograph / grammophone companies.
Nipper (1884–1895) was a dog from Bristol, England, who served as the model for a painting by Francis Barraud titled "His Master's Voice". This image was the basis for the dog-and-gramophone commercial logo, one of the world's most famous used by several audio recording and associated company brands, including Berliner Gramophone and its various successors, affiliates, and successors, including Berliner's German subsidiary Deutsche Grammophon; Berliner's American successor the Victor Talking Machine Co. (later known as RCA Victor and then RCA Records); Victor's Bluebird label; Zonophone; Berliner's (and later Victor's) British affiliate the Gramophone Co. Ltd. (informally known as His Master's Voice) and its successors EMI and HMV Retail Ltd.; the Gramophone Co.'s German subsidiary Electrola; Zonophone; and onetime Victor subsidiary the Japan Victor Company (JVC).
Bizarro/Wayno: a clergical visit for a meal, the life of dogs.
You need to recognize the situation: a young couple, presumably husband and wife, are standing at the front door of their house (you might reflect on what signals that interpretation), facing a clergyman, who is thanking them for having him in their house (he says that) and giving him a meal (that's not quite what he says). Here you need to recognize the things that pick him out as a clergyman who's just had a meal with the couple.
A clerical collar, clergy collar, or Roman collar, is an item of Christian clerical clothing. The collar closes at the back of the neck, presenting a seamless front. The shirt may have the collar built in. The clerical tab is almost always white and was originally made of cotton or linen but is now frequently made of plastic. Sometimes it is attached with a collaret or collarino that covers the white collar almost completely, except for a small white square at the base of the throat, and sometimes with the top edge of the collar exposed to mimic the collar of a cassock. It may simply be a detachable tab of white in the front of the clerical shirt. The clerical shirt is traditionally black (or another color appropriate to a person's ministry rank, such as purple for Anglican bishops), but today is available in a variety of colors depending on the wearer's preference. Once the clerical collar is removed the garment is indistinguishable from any other shirt. When clergy are delivering sermons, they sometimes attach preaching bands to their clerical collar.
… Invented in the Presbyterian Church [1840-1880], the clerical collar was adopted by other Christian denominations, including Anglican Church, Methodist churches, Eastern Orthodox Church, Baptist churches, Lutheran churches, and the Roman Catholic Church. Prior to the Second Vatican Council (1962-1965) the practice of Roman Catholic clergy wearing the clerical collar as street-dress tended to be found only in those countries where Catholicism was the minority religion. It was mandatory for U.S. Catholic priests starting in 1884. In the 1960s, many clergy who lived in countries where Catholicism was the dominant religion also began to wear the clerical collar rather than the soutane or cassock.
P1. to break bread: (a) to break it for one's own mouthfuls; hence to eat or partake of bread or food; (b) (from the New Testament) to break it for distribution to others, to dispense bread, or fig. the bread of life; also to break the sacramental bread in the Communion of the Lord's Supper, to administer or join in the Communion.
Lamentations 4:4: The tongue of the sucking child cleaveth to the roof of his mouth for thirst: the young children ask bread, and no man breaketh it unto them.
Mark 14:22: And as they did eat, Jesus took bread, and blessed, and brake it, and gave to them, and said, Take, eat: this is my body.
So, in #9, a scene of a cleric with two of his parishoners is translated into a canine equivalent, with break biscuits (dog biscuits) replacing break bread.
This entry was posted on August 4, 2018 at 4:16 pm and is filed under Clothing, Comic conventions, Language and animals, Linguistics in the comics, Movies and tv, Slang, Understanding comics.	You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.


Exclusive to Bed Bath N' Table, we house the full range of Morgan & Finch bed linen.
The Morgan & Finch label spans across all homewares categories. The beautiful designs and exceptional quality are featured across all of our Bed Bath N' Table bed linen, bathroom and tabletop ranges.
New bed linen and homewares ranges are developed each season and coordinate with all of our popular classics and favourites.
Opulent textiles and refined finishes are the essence of the Morgan & Finch White Label collection. The premium label delivers the highest quality fabrics complemented by higher thread counts, complex stitching techniques and detailed finishes that shape this truly luxurious collection. The superior fabrics of Egyptian cotton, French flax linen and pure Australian wool span across all homewares categories to create a complete collection.
Cotton House exudes a casual, comfortable elegance – designed in Australia to specifically fit within the lifestyle.
Known for its contemporary quilt cover, sheet set and beach towel designs, Cotton House is designed and developed in-house by our brilliant team – always with the continual vision of simple, relaxed, Australian style.
Adding a vibrant design style to our range of quilt covers & bed linen, Harlequin Design Studio brings an energetic spectrum of patterns, textures and colours.
An eclectic fusion of classic mixed with contemporary, the Harlequin range features stunningly detailed designs and enduring quality.
Founded in 1860, Sanderson has been an internationally renowned name in interior design and decorating for over 150 years.
Introducing some of the quintessentially English interior designs into an exceptionally luxurious range of bed linen, our Sanderson range is of the highest quality in both style and construction.
William Morris (1834 - 1896), artist, philospher & political theorist, was one of the most outstanding and influencial designers of the Art & Crafts Movement and through his company, Morris & Co., he produced some of the most fashionable and exciting textiles & wallpapers of his era.
His legacy continues today with Morris & Co. producing authentic versions of his original designs alonside new interpretations to create up to date fabrics and wallpapers with timeless appeal.


text:
These People Can Trace Themselves to Adam
Posted on October 17, 2012 by Tammy Hepps
Today begins International Jewish Genealogy Month! This past Sabbath appropriately happened to be the week synagogues around the world recited the world's earliest genealogy in Genesis Chapter 5. When my friend M. listened to the reading, he heard the earliest ancestors on his family tree:
Excerpted generations from Adam to Noah at the end of M.'s tree. (Hebrew spelling of Biblical names used. At times this tree uses "descended from" to span large periods of time, hence the surprisingly low generation numbers.)
M. is not my only friend whose family tree connects him to Biblical figures. The earliest ancestor on Dan Smokler's family tree is King David!
The earliest generations of Dan's tree. King David is listed next to the star.
How can these people make these claims?!, I wondered, when these friends told me about their remarkable trees. Thus was I introduced to a fascinating subset of Rabbinic genealogy focused on descent from King David. It turns out there are five so-called primary families who are traditionally considered to have descended from the Davidic royal family. Both M.'s and Dan's families are descended from Rashi, an 11th c. French rabbi whose writings remain well-known today. Other such families include the descendants of Judah Lowe, the 15th c. Elder of Prague, whose great-great-grandson, Judah Lowe, the Maharal, is said to have created the Golem, and the Abravanel family, known best for descendant Isaac Abarbanel, who advised Ferdinand II and Isabella of Spain until he failed to stop their expulsion of the Jews in 1492.
Compared to their counterparts in non-Jewish genealogy ranging from royalty to Mayflower descendants, these prominent, rabbinic families are a very rare example of published genealogies of Jewish families well-documented for centuries, comprising multiple sub-dynasties themselves. So, the work of family historians is to trace back not 500 or 1000 years to one of those primary families, but a much shorter distance to one of the derivative lines. In Dan's case, a distant cousin in Israel reached out to his family to explain their connection to Rabbi Pinchas of Koretz (1728-1790), the famous Chassidic rabbi who is Dan's eighth great-grandfather!
It took two 10′ tables to unfold Dan's entire tree! His family is in the bottom-left, Rabbi Pinchas of Koretz is bottom-center of the top sheet, and Rashi and King David are at the very top. Click to enlarge the image to make out the various family groups.
As this enormous tree documents, Rabbi Pinchas of Koretz descended from Nathan Neta Spira (1585-1633), a prominent Polish rabbi. And here's how we make the subsequent leaps:
Derivative to primary: The Spira/Shapira family traces back to Shmuel Shapira (b.1345), who descended from Rashi's grandson, Isaac (1090-1130), better known as the Ribam, another famous rabbi whose works are still studied.
Primary to Hillel: Isaac's grandfather, Rashi (1040-1105), is traced 38 generations over 1100 years back to Rabbi Hillel the Great (110 BCE-10 CE), who lived in Jerusalem during the time of King Herod and Emperor Augustus and whose teachings are recorded in the Talmud and studied to this day.
Hillel to David: Jewish tradition connects Hillel back 35 generations to King David's son, Shephatiah.
David to Adam: The Bible documents the 32 generations between King David (1043-973 BCE) and Adam. Done!
The other primary families follow different routes back to David. The Abravanels, for example, are descended from the Davidic Babylonian exilarchs, the hereditary leaders of the exiled Jewish community founded in 586 BCE after the destruction of the First Temple. Their dynasty lasted until the time of Rashi.
At this point you must be dying to know how we know all of this?! As you might expect, the sources become sparser as we go further back in time. We start with the genealogical sources most often cited today, published starting in the late 18th c., that trace derivative families back to primary families (#1 above). They are generally considered reliable, though there are sometimes gaps between generations.
These more recent sources were based on earlier sources that only rarely survive. In the case of Rashi, there was a genealogical record going back to Hillel's great x 3 grandson (covering the period of #2 above) which was destroyed in the Swabian War of 1499. "Johanan Luria mourned the loss of his genealogy more than the material goods he was robbed of," wrote Abraham Epstein in his early 20th c. work, Mishpachat Luria. What genealogist would not weep with him?
To get from Hillel to David (#3 above), the source here is more modern than you might expect, a 10th. century work by a prominent Babylonian gaon (leader), based on a work purportedly from 68 CE, just after the Second Temple was destroyed. The Talmud also reports that Hillel descended from Shephatiah. But in the case of the Abravanels, who descended from the exilarchs, there is a chronicle from the 9th c., which extends a 2nd c. source to trace the exilarchs back to Adam through the first exilarch, Jeconiah, who is mentioned not only in the Hebrew Bible, but also in cuneiform tablets excavated in Iraq!
Certainly we are now well beyond the territory of trustworthy historical sources. And even the more recent sources can't entirely meet a genealogical standard of proof. Personally, I view these sources in the context of the unbroken line of religious teachings passed down faithfully by people like the authors of these works, who believed they had a holy obligation to do so. In both genealogy and religious instruction — and there's an overlap between the two that starts with Genesis and continues through many traditional Jewish sources — oral tradition only belatedly became written texts, and while a tension between preserving truth and embellishing may have come into play, I suspect truth won far more often given the mindset of the authors, steeped in a tradition-obsessed culture, who dedicated their lives to its preservation.
So now you understand how my friends M. and Dan can trace themselves back to Adam, but what about me? I have no connection to these rabbinical dynasties that I know of. But when I found my great-grandmother's tombstone a couple years ago, I discovered that her father was a Kohen, a member of the priestly class patrilineally descended directly from Moses' brother, Aaron. Only 26 generations from him to Adam…
Does any of this matter if we can't be sure? There is proof, the work of genealogists, and then there is meaning, a goal of more casual family historians. Learning his family tree did not make Dan a genealogist, but he was so moved by the knowledge that he named his first-born after Rabbi Pinchas of Koretz in the hope that he would emulate his pious ancestor's virtues. At the close of the circumcision ceremony, Dan inscribed his son's name on the family tree in front of all the gathered friends and family, the second of what I'm sure will be many ways in which he will raise his son with an awareness of his illustrious lineage and the example set by his ancestors. Whether the entirety of their enormous tree meets a genealogical standard of proof is irrelevant if it helps to raise a boy to be kind and good.
This entry was posted in Personal Stories by Tammy Hepps. Bookmark the permalink.
24 thoughts on "These People Can Trace Themselves to Adam"
SHF on October 18, 2012 at 1:25 PM said:
Great post! For what it's worth, don't feel jealous: you may not have the details, but I think you can be relatively certain your family goes back to Adam and Chava, too!
Tammy on October 18, 2012 at 2:20 PM said:
Now how about Lucy?
Donna דונה on October 18, 2012 at 9:33 PM said:
This is wonderful!
!תודה רבה
François Guyard on October 23, 2012 at 4:21 PM said:
Judah Lowe, the Maharal is an ancestor of the 16th generation of Joseph Ratzinger, papa Benedictus XVI
Now I've heard everything! How fascinating! Thanks for sharing this fun fact.
Schelly Talalay Dardashti on April 10, 2014 at 9:31 PM said:
We had all those documents also, but we lost them in the Great Flood! 🙂
Tammy Hepps on April 10, 2014 at 10:09 PM said:
Hahaha, Schelley! BTW, I mean one day to do an update on this post incorporating the information you shared with my about some of the Syrian lineages.
Esther on April 25, 2014 at 2:00 AM said:
Hi! Ireally enjoyed this article =)
I am a descendant of R. Nathan Neta Spira too!
Is there any way that I'd be able to contact Dan to get a copy of that huge family tree??? It would be fascinating to see my family's genealogy so clear like that!
Rob Spira on July 3, 2014 at 12:37 AM said:
I think perhaps that you and I may be related Esther, because I am descended from the Spira lineage of Krakow, Poland which is probably descended from Nathan Neta Spira. My father was born in Krakow in 1908.
Ruth Stern on October 18, 2018 at 9:27 PM said:
probable is not genealogical proof.
Brandi on July 28, 2014 at 4:21 PM said:
David is my ancestor
Pingback: Has a modern genealogy been traced back to a biblical person? | CL-UAT
Ken Grey on February 6, 2015 at 4:31 PM said:
Please Folks,Does anyone here have any info or connection with the line into which the French Count of Toulouse married in the middle ages? The Jewish spouse descended from the Babylonian Exhilach.
Tammy Hepps on February 24, 2015 at 1:59 PM said:
Hi Ken, this isn't something I know much about, but perhaps try posting this question in the "Tracing the Tribe" group on Facebook? Good luck.
Elyssa Juni on March 18, 2015 at 11:15 AM said:
Hello, Hare Krishna!
I have been recently researching my own family lineage with my aunt, who discovered that we connect to the Shor line, from Joseph ben Isaac Bechor-Shor. I was wondering whether you knew anything about his lineage?
Thank you very much for your help,
Mādhavī dāsī/Elyssa Rivka Juni
Jason Martin on January 17, 2018 at 12:32 PM said:
Cool post. How many generations have there been from now to Adam?
Quentin on November 23, 2020 at 11:16 AM said:
about 140 generations
he is my 139th great grand father
Eilene on August 21, 2018 at 12:30 PM said:
this is all so interesting.. do you have any information on Golub…my fathers last name and he is gone never giving much information in his life time. Our older generations all deceased. Any information of the Golub name would be appreciated.
Eilene
David Adams on December 5, 2018 at 2:58 AM said:
How do anwer this there were people before preadenica race before first flood
ruth stern on December 5, 2018 at 1:04 PM said:
How about writing your question in English, rather than gobbledy-gook? Punctuation and spelling might be helpful.
Rabbi Segbene on March 20, 2019 at 7:00 AM said:
I am the 97th descendant of Adam:
See below our Genealogy:
https://segbeneonline.wordpress.com/2018/12/23/rabbi-segbene-genealogy-from-adam/
Whatsapp contact:
Mikaela Vicuña on March 16, 2021 at 5:21 PM said:
This is cool king david is my 97th great grandpa I only found out when I got dna tested and said I had Jewish dna so started building my family tree and there he was 🙂