Exemplo n.º 1
0
def elliptic_curve_search(info, query):
    parse_rational(info,query,'jinv','j-invariant')
    parse_ints(info,query,'conductor')
    parse_ints(info,query,'torsion','torsion order')
    parse_ints(info,query,'rank')
    parse_ints(info,query,'sha','analytic order of Ш')
    parse_bracketed_posints(info,query,'torsion_structure',maxlength=2,check_divisibility='increasing')
    # speed up slow torsion_structure searches by also setting torsion
    #if 'torsion_structure' in query and not 'torsion' in query:
    #    query['torsion'] = reduce(mul,[int(n) for n in query['torsion_structure']],1)
    if 'include_cm' in info:
        if info['include_cm'] == 'exclude':
            query['cm'] = 0
        elif info['include_cm'] == 'only':
            query['cm'] = {'$ne' : 0}
    parse_element_of(info,query,field='isodeg',qfield='isogeny_degrees',split_interval=1000)
    #parse_ints(info,query,field='isodeg',qfield='isogeny_degrees')
    parse_primes(info, query, 'surj_primes', name='maximal primes',
                 qfield='nonmax_primes', mode='complement')
    if info.get('surj_quantifier') == 'exactly':
        mode = 'exact'
    else:
        mode = 'append'
    parse_primes(info, query, 'nonsurj_primes', name='non-maximal primes',
                 qfield='nonmax_primes',mode=mode, radical='nonmax_rad')
    if 'optimal' in info and info['optimal'] == 'on':
        # fails on 990h3
        query['number'] = 1

    info['curve_url'] = lambda dbc: url_for(".by_triple_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1], number=dbc['lmfdb_number'])
    info['iso_url'] = lambda dbc: url_for(".by_double_iso_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1])
Exemplo n.º 2
0
Arquivo: main.py Projeto: koffie/lmfdb
def artin_representation_search(info, query):
    query['Hide'] = 0
    info['sign_code'] = 0
    parse_primes(info,
                 query,
                 "unramified",
                 name="Unramified primes",
                 qfield="BadPrimes",
                 mode="complement")
    parse_primes(info,
                 query,
                 "ramified",
                 name="Ramified primes",
                 qfield="BadPrimes",
                 mode="append")
    parse_element_of(info, query, "root_number", qfield="GalConjSigns")
    parse_restricted(info,
                     query,
                     "frobenius_schur_indicator",
                     qfield="Indicator",
                     allowed=[1, 0, -1],
                     process=int)
    parse_container(info,
                    query,
                    'container',
                    qfield='Container',
                    name="Smallest permutation representation")
    parse_galgrp(info, query, "group", name="Group", qfield=("Galn", "Galt"))
    parse_ints(info, query, 'dimension', qfield='Dim')
    parse_ints(info, query, 'conductor', qfield='Conductor')
Exemplo n.º 3
0
def common_parse(info, query):
    parse_ints(info, query, 'weight', name="Weight")
    if 'weight_parity' in info:
        parity = info['weight_parity']
        if parity == 'even':
            query['odd_weight'] = False
        elif parity == 'odd':
            query['odd_weight'] = True
    if 'char_parity' in info:
        parity = info['char_parity']
        if parity == 'even':
            query['char_parity'] = 1
        elif parity == 'odd':
            query['char_parity'] = -1
    parse_ints(info, query, 'level', name="Level")
    parse_floats(info, query, 'analytic_conductor', name="Analytic conductor")
    parse_character(info, query, 'char_label', qfield='char_orbit_index')
    parse_character(info,
                    query,
                    'prim_label',
                    qfield='prim_orbit_index',
                    level_field='char_conductor',
                    conrey_field=None)
    parse_ints(info, query, 'char_order', name="Character order")
    prime_mode = info['prime_quantifier'] = info.get('prime_quantifier',
                                                     'exact')
    parse_primes(info,
                 query,
                 'level_primes',
                 name='Primes dividing level',
                 mode=prime_mode,
                 radical='level_radical')
Exemplo n.º 4
0
def artin_representation_search(**args):
    info = to_dict(args)
    if 'natural' in info:
        label = info['natural']
        # test if it is ok
        try:
            label = parse_artin_label(label)
        except ValueError as err:
            flash(Markup("Error: %s" % (err)), "error")
            bread = get_bread([('Search results','')])
            return search_input_error({'err':''}, bread)
        return render_artin_representation_webpage(label)

    title = 'Artin representation search results'
    bread = [('Artin representation', url_for(".index")), ('Search results', ' ')]
    sign_code = 0
    query = {'Hide': 0}
    try:
        parse_primes(info,query,"unramified",name="Unramified primes",
                     qfield="BadPrimes",mode="complement",to_string=True)
        parse_primes(info,query,"ramified",name="Ramified primes",
                     qfield="BadPrimes",mode="append",to_string=True)
        parse_restricted(info,query,"root_number",qfield="GaloisConjugates.Sign",
                         allowed=[1,-1],process=int)
        parse_restricted(info,query,"frobenius_schur_indicator",qfield="Indicator",
                         allowed=[1,0,-1],process=int)
        parse_galgrp(info,query,"group",name="Group",qfield="Galois_nt",use_bson=False)
        parse_ints(info,query,'dimension',qfield='Dim')
        parse_ints(info,query,'conductor',qfield='Conductor_key', parse_singleton=make_cond_key)
        #parse_paired_fields(info,query,field1='conductor',qfield1='Conductor_key',parse1=parse_ints,kwds1={'parse_singleton':make_cond_key},
                                       #field2='dimension',qfield2='Dim', parse2=parse_ints)
    except ValueError:
        return search_input_error(info, bread)

    count = parse_count(info,10)
    start = parse_start(info)

    data = ArtinRepresentation.collection().find(query).sort([("Dim", ASC), ("Conductor_key", ASC)])
    nres = data.count()
    data = data.skip(start).limit(count)

    if(start >= nres):
        start -= (1 + (start - nres) / count) * count
    if(start < 0):
        start = 0
    if nres == 1:
        report = 'unique match'
    else:
        if nres > count or start != 0:
            report = 'displaying matches %s-%s of %s' % (start + 1, min(nres, start + count), nres)
        else:
            report = 'displaying all %s matches' % nres
    if nres == 0:
        report = 'no matches'


    initfunc = ArtinRepresentation

    return render_template("artin-representation-search.html", req=info, data=data, title=title, bread=bread, query=query, start=start, report=report, nres=nres, initfunc=initfunc, sign_code=sign_code)
Exemplo n.º 5
0
def elliptic_curve_search(info, query):
    parse_rational(info, query, 'jinv', 'j-invariant')
    parse_ints(info, query, 'conductor')
    parse_ints(info, query, 'torsion', 'torsion order')
    parse_ints(info, query, 'rank')
    parse_ints(info, query, 'sha', 'analytic order of &#1064;')
    parse_bracketed_posints(info,
                            query,
                            'torsion_structure',
                            maxlength=2,
                            check_divisibility='increasing')
    # speed up slow torsion_structure searches by also setting torsion
    #if 'torsion_structure' in query and not 'torsion' in query:
    #    query['torsion'] = reduce(mul,[int(n) for n in query['torsion_structure']],1)
    if 'include_cm' in info:
        if info['include_cm'] == 'exclude':
            query['cm'] = 0
        elif info['include_cm'] == 'only':
            query['cm'] = {'$ne': 0}
    parse_element_of(info,
                     query,
                     field='isodeg',
                     qfield='isogeny_degrees',
                     split_interval=1000)
    #parse_ints(info,query,field='isodeg',qfield='isogeny_degrees')
    parse_primes(info,
                 query,
                 'surj_primes',
                 name='maximal primes',
                 qfield='nonmax_primes',
                 mode='complement')
    if info.get('surj_quantifier') == 'exactly':
        mode = 'exact'
    else:
        mode = 'append'
    parse_primes(info,
                 query,
                 'nonsurj_primes',
                 name='non-maximal primes',
                 qfield='nonmax_primes',
                 mode=mode,
                 radical='nonmax_rad')
    if 'optimal' in info and info['optimal'] == 'on':
        # fails on 990h3
        query['number'] = 1

    info['curve_url'] = lambda dbc: url_for(".by_triple_label",
                                            conductor=dbc['conductor'],
                                            iso_label=split_lmfdb_label(dbc[
                                                'lmfdb_iso'])[1],
                                            number=dbc['lmfdb_number'])
    info['iso_url'] = lambda dbc: url_for(".by_double_iso_label",
                                          conductor=dbc['conductor'],
                                          iso_label=split_lmfdb_label(dbc[
                                              'lmfdb_iso'])[1])
Exemplo n.º 6
0
def artin_representation_search(info, query):
    query['Hide'] = 0
    info['sign_code'] = 0
    parse_primes(info,query,"unramified",name="Unramified primes",
                 qfield="BadPrimes",mode="complement")
    parse_primes(info,query,"ramified",name="Ramified primes",
                 qfield="BadPrimes",mode="append")
    parse_element_of(info,query,"root_number",qfield="GalConjSigns")
    parse_restricted(info,query,"frobenius_schur_indicator",qfield="Indicator",
                     allowed=[1,0,-1],process=int)
    parse_container(info,query, 'container',qfield='Container', name="Smallest permutation representation")
    parse_galgrp(info,query,"group",name="Group",qfield=("Galn","Galt"))
    parse_ints(info,query,'dimension',qfield='Dim')
    parse_ints(info,query,'conductor',qfield='Conductor')
Exemplo n.º 7
0
def number_field_search(info, query):
    parse_ints(info, query, 'degree')
    parse_galgrp(info, query, qfield=('degree', 'galt'))
    parse_bracketed_posints(info,
                            query,
                            'signature',
                            qfield=('degree', 'r2'),
                            exactlength=2,
                            extractor=lambda L: (L[0] + 2 * L[1], L[1]))
    parse_signed_ints(info,
                      query,
                      'discriminant',
                      qfield=('disc_sign', 'disc_abs'))
    parse_ints(info, query, 'class_number')
    parse_bracketed_posints(info,
                            query,
                            'class_group',
                            check_divisibility='increasing',
                            process=int)
    parse_primes(info,
                 query,
                 'ur_primes',
                 name='Unramified primes',
                 qfield='ramps',
                 mode='complement')
    # modes are now contained (in), exactly, include
    if 'ram_quantifier' in info and str(info['ram_quantifier']) == 'include':
        mode = 'append'
    elif 'ram_quantifier' in info and str(
            info['ram_quantifier']) == 'contained':
        mode = 'subsets'
    else:
        mode = 'exact'
    parse_primes(info,
                 query,
                 'ram_primes',
                 name='Ramified primes',
                 qfield='ramps',
                 mode=mode,
                 radical='disc_rad')
    ## This seems not to be used
    #if 'lucky' in info:
    #    label = db.nf_fields.lucky(query, 0)
    #    if label:
    #        return redirect(url_for(".by_label", label=clean_input(label)))
    info['wnf'] = WebNumberField.from_data
Exemplo n.º 8
0
def number_field_search(info, query):
    parse_ints(info,query,'degree')
    parse_galgrp(info,query, qfield=('degree', 'galt'))
    parse_bracketed_posints(info,query,'signature',qfield=('degree','r2'),exactlength=2,extractor=lambda L: (L[0]+2*L[1],L[1]))
    parse_signed_ints(info,query,'discriminant',qfield=('disc_sign','disc_abs'))
    parse_ints(info,query,'class_number')
    parse_bracketed_posints(info,query,'class_group',check_divisibility='increasing',process=int)
    parse_primes(info,query,'ur_primes',name='Unramified primes',
                 qfield='ramps',mode='complement')
    # modes are now contained (in), exactly, include
    if 'ram_quantifier' in info and str(info['ram_quantifier']) == 'include':
        mode='append'
    elif 'ram_quantifier' in info and str(info['ram_quantifier']) == 'contained':
        mode='subsets'
    else:
        mode='exact'
    parse_primes(info,query,'ram_primes',name='Ramified primes',
                 qfield='ramps',mode=mode,radical='disc_rad')
    ## This seems not to be used
    #if 'lucky' in info:
    #    label = db.nf_fields.lucky(query, 0)
    #    if label:
    #        return redirect(url_for(".by_label", label=clean_input(label)))
    info['wnf'] = WebNumberField.from_data
Exemplo n.º 9
0
def elliptic_curve_search(info):

    if info.get('download') == '1' and info.get('Submit') and info.get('query'):
        return download_search(info)

    if 'SearchAgain' in info:
        return rational_elliptic_curves()

    query = {}
    bread = info.get('bread',[('Elliptic Curves', url_for("ecnf.index")), ('$\Q$', url_for(".rational_elliptic_curves")), ('Search Results', '.')])

    if 'jump' in info:
        label = info.get('label', '').replace(" ", "")
        m = match_lmfdb_label(label)
        if m:
            try:
                return by_ec_label(label)
            except ValueError:
                return elliptic_curve_jump_error(label, info, wellformed_label=True)
        elif label.startswith("Cremona:"):
            label = label[8:]
            m = match_cremona_label(label)
            if m:
                try:
                    return by_ec_label(label)
                except ValueError:
                    return elliptic_curve_jump_error(label, info, wellformed_label=True)
        elif match_cremona_label(label):
            return elliptic_curve_jump_error(label, info, cremona_label=True)
        elif label:
            # Try to parse a string like [1,0,3,2,4] as valid
            # Weistrass coefficients:
            lab = re.sub(r'\s','',label)
            lab = re.sub(r'^\[','',lab)
            lab = re.sub(r']$','',lab)
            try:
                labvec = lab.split(',')
                labvec = [QQ(str(z)) for z in labvec] # Rationals allowed
                E = EllipticCurve(labvec)
                # Now we do have a valid curve over Q, but it might
                # not be in the database.
                ainvs = [str(c) for c in E.minimal_model().ainvs()]
                xainvs = ''.join(['[',','.join(ainvs),']'])
                data = db_ec().find_one({'xainvs': xainvs})
                if data is None:
                    data = db_ec().find_one({'ainvs': ainvs})
                    if data is None:
                        info['conductor'] = E.conductor()
                        return elliptic_curve_jump_error(label, info, missing_curve=True)
                return by_ec_label(data['lmfdb_label'])
            except (TypeError, ValueError, ArithmeticError):
                return elliptic_curve_jump_error(label, info)
        else:
            query['label'] = ''

    try:
        parse_rational(info,query,'jinv','j-invariant')
        parse_ints(info,query,'conductor')
        parse_ints(info,query,'torsion','torsion order')
        parse_ints(info,query,'rank')
        parse_ints(info,query,'sha','analytic order of &#1064;')
        parse_bracketed_posints(info,query,'torsion_structure',maxlength=2,process=str,check_divisibility='increasing')
        # speed up slow torsion_structure searches by also setting torsion
        if 'torsion_structure' in query and not 'torsion' in query:
            query['torsion'] = reduce(mul,[int(n) for n in query['torsion_structure']],1)
        if 'include_cm' in info:
            if info['include_cm'] == 'exclude':
                query['cm'] = 0
            elif info['include_cm'] == 'only':
                query['cm'] = {'$ne' : 0}

        parse_ints(info,query,field='isodeg',qfield='isogeny_degrees')

        parse_primes(info, query, 'surj_primes', name='surjective primes',
                     qfield='non-maximal_primes', mode='complement')
        if info.get('surj_quantifier') == 'exactly':
            mode = 'exact'
        else:
            mode = 'append'
        parse_primes(info, query, 'nonsurj_primes', name='non-surjective primes',
                     qfield='non-maximal_primes',mode=mode)
    except ValueError as err:
        info['err'] = str(err)
        return search_input_error(info, bread)

    count = parse_count(info,100)
    start = parse_start(info)

    if 'optimal' in info and info['optimal'] == 'on':
        # fails on 990h3
        query['number'] = 1

    info['query'] = query
    cursor = db_ec().find(query)
    nres = cursor.count()
    if(start >= nres):
        start -= (1 + (start - nres) / count) * count
    if(start < 0):
        start = 0
    res = cursor.sort([('conductor', ASCENDING), ('iso_nlabel', ASCENDING),
                       ('lmfdb_number', ASCENDING)]).skip(start).limit(count)
    info['curves'] = res
    info['format_ainvs'] = format_ainvs
    info['curve_url'] = lambda dbc: url_for(".by_triple_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1], number=dbc['lmfdb_number'])
    info['iso_url'] = lambda dbc: url_for(".by_double_iso_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1])
    info['number'] = nres
    info['start'] = start
    info['count'] = count
    info['more'] = int(start + count < nres)

    
    if nres == 1:
        info['report'] = 'unique match'
    elif nres == 2: 
        info['report'] = 'displaying both matches'
    else:
        if nres > count or start != 0:
            info['report'] = 'displaying matches %s-%s of %s' % (start + 1, min(nres, start + count), nres)
        else:
            info['report'] = 'displaying all %s matches' % nres
    #credit = 'John Cremona'
    #if 'non-surjective_primes' in query or 'non-maximal_primes' in query:
    #    credit += ' and Andrew Sutherland'

    t = info.get('title','Elliptic Curves search results')
    return render_template("ec-search-results.html", info=info, credit=ec_credit(), bread=bread, title=t)
Exemplo n.º 10
0
def number_field_search(info):

    info['learnmore'] = [
        ('Global number field labels', url_for(".render_labels_page")),
        ('Galois group labels', url_for(".render_groups_page")),
        (Completename, url_for(".render_discriminants_page")),
        ('Quadratic imaginary class groups',
         url_for(".render_class_group_data"))
    ]
    t = 'Global Number Field search results'
    bread = [('Global Number Fields', url_for(".number_field_render_webpage")),
             ('Search results', ' ')]

    if 'natural' in info:
        query = {'label_orig': info['natural']}
        try:
            parse_nf_string(info,
                            query,
                            'natural',
                            name="Label",
                            qfield='label')
            return redirect(
                url_for(".by_label", label=clean_input(query['label_orig'])))
        except ValueError:
            query['err'] = info['err']
            return search_input_error(query, bread)

    if 'algebra' in info:
        fields = info['algebra'].split('_')
        fields2 = [WebNumberField.from_coeffs(a) for a in fields]
        for j in range(len(fields)):
            if fields2[j] is None:
                fields2[j] = WebNumberField.fakenf(fields[j])
        t = 'Number field algebra'
        info = {}
        info = {'fields': fields2}
        return render_template("number_field_algebra.html",
                               info=info,
                               title=t,
                               bread=bread)

    query = {}
    try:
        parse_galgrp(info, query, qfield='galois')
        parse_ints(info, query, 'degree')
        parse_bracketed_posints(info,
                                query,
                                'signature',
                                split=False,
                                exactlength=2)
        parse_signed_ints(info,
                          query,
                          'discriminant',
                          qfield=('disc_sign', 'disc_abs_key'),
                          parse_one=make_disc_key)
        parse_ints(info, query, 'class_number')
        parse_bracketed_posints(info,
                                query,
                                'class_group',
                                split=False,
                                check_divisibility='increasing')
        parse_primes(info,
                     query,
                     'ur_primes',
                     name='Unramified primes',
                     qfield='ramps',
                     mode='complement',
                     to_string=True)
        # modes are now contained (in), exactly, include
        if 'ram_quantifier' in info and str(
                info['ram_quantifier']) == 'include':
            mode = 'append'
            parse_primes(info,
                         query,
                         'ram_primes',
                         'ramified primes',
                         'ramps',
                         mode,
                         to_string=True)
        elif 'ram_quantifier' in info and str(
                info['ram_quantifier']) == 'contained':
            parse_primes(info,
                         query,
                         'ram_primes',
                         'ramified primes',
                         'ramps_all',
                         'subsets',
                         to_string=False)
            pass  # build list
        else:
            mode = 'liststring'
            parse_primes(info, query, 'ram_primes', 'ramified primes',
                         'ramps_all', mode)
    except ValueError:
        return search_input_error(info, bread)
    count = parse_count(info)
    start = parse_start(info)

    # nf_logger.debug(query)
    info['query'] = dict(query)
    if 'lucky' in info:
        one = nfdb().find_one(query)
        if one:
            label = one['label']
            return redirect(url_for(".by_label", label=clean_input(label)))

    fields = nfdb()

    res = fields.find(query)
    res = res.sort([('degree', ASC), ('disc_abs_key', ASC),
                    ('disc_sign', ASC)])

    if 'download' in info and info['download'] != '0':
        return download_search(info, res)

    nres = res.count()
    res = res.skip(start).limit(count)

    if (start >= nres):
        start -= (1 + (start - nres) / count) * count
    if (start < 0):
        start = 0

    info['fields'] = res
    info['number'] = nres
    info['start'] = start
    if nres == 1:
        info['report'] = 'unique match'
    else:
        if nres > count or start != 0:
            info['report'] = 'displaying matches %s-%s of %s' % (
                start + 1, min(nres, start + count), nres)
        else:
            info['report'] = 'displaying all %s matches' % nres

    info['wnf'] = WebNumberField.from_data
    return render_template("number_field_search.html",
                           info=info,
                           title=t,
                           bread=bread)
Exemplo n.º 11
0
def elliptic_curve_search(**args):
    info = to_dict(args)

    if 'download' in info and info['download'] != '0':
        return download_search(info)

    query = {}
    bread = [('Elliptic Curves', url_for("ecnf.index")),
             ('$\Q$', url_for(".rational_elliptic_curves")),
             ('Search Results', '.')]
    if 'SearchAgain' in args:
        return rational_elliptic_curves()

    if 'jump' in args:
        label = info.get('label', '').replace(" ", "")
        m = match_lmfdb_label(label)
        if m:
            try:
                return by_ec_label(label)
            except ValueError:
                return elliptic_curve_jump_error(label, info, wellformed_label=True)
        elif label.startswith("Cremona:"):
            label = label[8:]
            m = match_cremona_label(label)
            if m:
                try:
                    return by_ec_label(label)
                except ValueError:
                    return elliptic_curve_jump_error(label, info, wellformed_label=True)
        elif match_cremona_label(label):
            return elliptic_curve_jump_error(label, info, cremona_label=True)
        elif label:
            # Try to parse a string like [1,0,3,2,4] as valid
            # Weistrass coefficients:
            lab = re.sub(r'\s','',label)
            lab = re.sub(r'^\[','',lab)
            lab = re.sub(r']$','',lab)
            try:
                labvec = lab.split(',')
                labvec = [QQ(str(z)) for z in labvec] # Rationals allowed
                E = EllipticCurve(labvec)
                # Now we do have a valid curve over Q, but it might
                # not be in the database.
                ainvs = [str(c) for c in E.minimal_model().ainvs()]
                data = db_ec().find_one({'ainvs': ainvs})
                if data is None:
                    info['conductor'] = E.conductor()
                    return elliptic_curve_jump_error(label, info, missing_curve=True)
                return by_ec_label(data['lmfdb_label'])
            except (TypeError, ValueError, ArithmeticError):
                return elliptic_curve_jump_error(label, info)
        else:
            query['label'] = ''

    try:
        parse_rational(info,query,'jinv','j-invariant')
        parse_ints(info,query,'conductor')
        parse_ints(info,query,'torsion','torsion order')
        parse_ints(info,query,'rank')
        parse_ints(info,query,'sha','analytic order of &#1064;')
        parse_bracketed_posints(info,query,'torsion_structure',maxlength=2,process=str,check_divisibility='increasing')
        if 'include_cm' in info:
            if info['include_cm'] == 'exclude':
                query['cm'] = 0
            elif info['include_cm'] == 'only':
                query['cm'] = {'$ne' : 0}

        parse_primes(info, query, 'surj_primes', name='surjective primes',
                     qfield='non-surjective_primes', mode='complement')
        if info.get('surj_quantifier') == 'exactly':
            mode = 'exact'
        else:
            mode = 'append'
        parse_primes(info, query, 'nonsurj_primes', name='non-surjective primes',
                     qfield='non-surjective_primes',mode=mode)
    except ValueError as err:
        info['err'] = str(err)
        return search_input_error(info, bread)

    count = parse_count(info,100)
    start = parse_start(info)

    if 'optimal' in info and info['optimal'] == 'on':
        # fails on 990h3
        query['number'] = 1

    info['query'] = query
    cursor = db_ec().find(query)
    nres = cursor.count()
    if(start >= nres):
        start -= (1 + (start - nres) / count) * count
    if(start < 0):
        start = 0
    res = cursor.sort([('conductor', ASCENDING), ('iso_nlabel', ASCENDING),
                       ('lmfdb_number', ASCENDING)]).skip(start).limit(count)
    info['curves'] = res
    info['format_ainvs'] = format_ainvs
    info['curve_url'] = lambda dbc: url_for(".by_triple_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1], number=dbc['lmfdb_number'])
    info['iso_url'] = lambda dbc: url_for(".by_double_iso_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1])
    info['number'] = nres
    info['start'] = start
    info['count'] = count
    info['more'] = int(start + count < nres)

    
    if nres == 1:
        info['report'] = 'unique match'
    elif nres == 2: 
        info['report'] = 'displaying both matches'
    else:
        if nres > count or start != 0:
            info['report'] = 'displaying matches %s-%s of %s' % (start + 1, min(nres, start + count), nres)
        else:
            info['report'] = 'displaying all %s matches' % nres
    credit = 'John Cremona'
    if 'non-surjective_primes' in query:
        credit += 'and Andrew Sutherland'
    t = 'Elliptic Curves search results'
    return render_template("search_results.html", info=info, credit=credit, bread=bread, title=t)
Exemplo n.º 12
0
def number_field_search(info):

    info['learnmore'] = [('Global number field labels', url_for(".render_labels_page")), ('Galois group labels', url_for(".render_groups_page")), (Completename, url_for(".render_discriminants_page")), ('Quadratic imaginary class groups', url_for(".render_class_group_data"))]
    t = 'Global Number Field search results'
    bread = [('Global Number Fields', url_for(".number_field_render_webpage")), ('Search Results', ' ')]

    if 'natural' in info:
        query = {'label_orig': info['natural']}
        try:
            parse_nf_string(info,query,'natural',name="Label",qfield='label')
            return redirect(url_for(".by_label", label=query['label']))
        except ValueError:
            query['err'] = info['err']
            return search_input_error(query, bread)

    if 'algebra' in info:
        fields=info['algebra'].split('_')
        fields2=[WebNumberField.from_coeffs(a) for a in fields]
        for j in range(len(fields)):
            if fields2[j] is None:
                fields2[j] = WebNumberField.fakenf(fields[j])
        t = 'Number field algebra'
        info = {}
        info = {'fields': fields2}
        return render_template("number_field_algebra.html", info=info, title=t, bread=bread)



    query = {}
    try:
        parse_galgrp(info,query, qfield='galois')
        parse_ints(info,query,'degree')
        parse_bracketed_posints(info,query,'signature',split=False,exactlength=2)
        parse_signed_ints(info,query,'discriminant',qfield=('disc_sign','disc_abs_key'),parse_one=make_disc_key)
        parse_ints(info,query,'class_number')
        parse_bracketed_posints(info,query,'class_group',split=False,check_divisibility='increasing')
        parse_primes(info,query,'ur_primes',name='Unramified primes',qfield='ramps',mode='complement',to_string=True)
        # modes are now contained (in), exactly, include
        if 'ram_quantifier' in info and str(info['ram_quantifier']) == 'include':
            mode = 'append'
            parse_primes(info,query,'ram_primes','ramified primes','ramps',mode,to_string=True)
        elif 'ram_quantifier' in info and str(info['ram_quantifier']) == 'contained':
            parse_primes(info,query,'ram_primes','ramified primes','ramps_all','subsets',to_string=False)
            pass # build list
        else:
            mode = 'liststring'
            parse_primes(info,query,'ram_primes','ramified primes','ramps_all',mode)
    except ValueError:
        return search_input_error(info, bread)
    count = parse_count(info)
    start = parse_start(info)

    # nf_logger.debug(query)
    info['query'] = dict(query)
    if 'lucky' in info:
        one = nfdb().find_one(query)
        if one:
            label = one['label']
            return redirect(url_for(".by_label", label=clean_input(label)))

    fields = nfdb()

    res = fields.find(query)
    res = res.sort([('degree', ASC), ('disc_abs_key', ASC),('disc_sign', ASC)])

    if 'download' in info and info['download'] != '0':
        return download_search(info, res)

    # equivalent to
    # nres = res.count()
    #if(start >= nres):
    #    start -= (1 + (start - nres) / count) * count
    #if(start < 0):
    #    start = 0
    # res = res.skip(start).limit(count)
    try:
        start, nres, res = search_cursor_timeout_decorator(res, start, count);
    except ValueError as err:
        info['err'] = err;
        return search_input_error(info, bread)


    info['fields'] = res
    info['number'] = nres
    info['start'] = start
    if nres == 1:
        info['report'] = 'unique match'
    else:
        if nres > count or start != 0:
            info['report'] = 'displaying matches %s-%s of %s' % (start + 1, min(nres, start + count), nres)
        else:
            info['report'] = 'displaying all %s matches' % nres

    info['wnf'] = WebNumberField.from_data
    return render_template("number_field_search.html", info=info, title=t, bread=bread)
Exemplo n.º 13
0
def number_field_search(**args):
    info = to_dict(args)

    info['learnmore'] = [('Global number field labels', url_for(".render_labels_page")), ('Galois group labels', url_for(".render_groups_page")), (Completename, url_for(".render_discriminants_page")), ('Quadratic imaginary class groups', url_for(".render_class_group_data"))]
    t = 'Global Number Field search results'
    bread = [('Global Number Fields', url_for(".number_field_render_webpage")), ('Search results', ' ')]

    # for k in info.keys():
    #  nf_logger.debug(str(k) + ' ---> ' + str(info[k]))
    # nf_logger.debug('******************* '+ str(info['search']))

    if 'natural' in info:
        query = {'label_orig': info['natural']}
        try:
            parse_nf_string(info,query,'natural',name="Label",qfield='label')
            return redirect(url_for(".by_label", label= clean_input(query['label'])))
        except ValueError:
            query['err'] = info['err']
            return search_input_error(query, bread)

    query = {}
    try:
        parse_galgrp(info,query, qfield='galois')
        parse_ints(info,query,'degree')
        parse_bracketed_posints(info,query,'signature',split=False,exactlength=2)
        parse_signed_ints(info,query,'discriminant',qfield=('disc_sign','disc_abs_key'),parse_one=make_disc_key)
        parse_ints(info,query,'class_number')
        parse_bracketed_posints(info,query,'class_group',split=False,check_divisibility='increasing')
        parse_primes(info,query,'ur_primes',name='Unramified primes',qfield='ramps',mode='complement',to_string=True)
        if 'ram_quantifier' in info and str(info['ram_quantifier']) == 'some':
            mode = 'append'
        else:
            mode = 'exact'
        parse_primes(info,query,'ram_primes','ramified primes','ramps',mode,to_string=True)
    except ValueError:
        return search_input_error(info, bread)
    count = parse_count(info)
    start = parse_start(info)

    if info.get('paging'):
        try:
            paging = int(info['paging'])
            if paging == 0:
                start = 0
        except:
            pass

    C = base.getDBConnection()
    # nf_logger.debug(query)
    info['query'] = dict(query)
    if 'lucky' in args:
        one = C.numberfields.fields.find_one(query)
        if one:
            label = one['label']
            return redirect(url_for(".by_label", clean_input(label)))

    fields = C.numberfields.fields

    res = fields.find(query)

    if 'download' in info and info['download'] != '0':
        return download_search(info, res)

    res = res.sort([('degree', ASC), ('disc_abs_key', ASC),('disc_sign', ASC)])
    nres = res.count()
    res = res.skip(start).limit(count)

    if(start >= nres):
        start -= (1 + (start - nres) / count) * count
    if(start < 0):
        start = 0

    info['fields'] = res
    info['number'] = nres
    info['start'] = start
    if nres == 1:
        info['report'] = 'unique match'
    else:
        if nres > count or start != 0:
            info['report'] = 'displaying matches %s-%s of %s' % (start + 1, min(nres, start + count), nres)
        else:
            info['report'] = 'displaying all %s matches' % nres

    info['wnf'] = WebNumberField.from_data
    return render_template("number_field_search.html", info=info, title=t, bread=bread)
Exemplo n.º 14
0
def number_field_search(**args):
    info = to_dict(args)

    info["learnmore"] = [
        ("Global number field labels", url_for(".render_labels_page")),
        ("Galois group labels", url_for(".render_groups_page")),
        (Completename, url_for(".render_discriminants_page")),
        ("Quadratic imaginary class groups", url_for(".render_class_group_data")),
    ]
    t = "Global Number Field search results"
    bread = [("Global Number Fields", url_for(".number_field_render_webpage")), ("Search results", " ")]

    # for k in info.keys():
    #  nf_logger.debug(str(k) + ' ---> ' + str(info[k]))
    # nf_logger.debug('******************* '+ str(info['search']))

    if "natural" in info:
        query = {"label_orig": info["natural"]}
        try:
            parse_nf_string(info, query, "natural", name="Label", qfield="label")
            return redirect(url_for(".by_label", label=clean_input(query["label"])))
        except ValueError:
            query["err"] = info["err"]
            return search_input_error(query, bread)

    query = {}
    try:
        parse_galgrp(info, query, qfield="galois")
        parse_ints(info, query, "degree")
        parse_bracketed_posints(info, query, "signature", split=False, exactlength=2)
        parse_signed_ints(info, query, "discriminant", qfield=("disc_sign", "disc_abs_key"), parse_one=make_disc_key)
        parse_ints(info, query, "class_number")
        parse_bracketed_posints(info, query, "class_group", split=False, check_divisibility="increasing")
        parse_primes(
            info, query, "ur_primes", name="Unramified primes", qfield="ramps", mode="complement", to_string=True
        )
        if "ram_quantifier" in info and str(info["ram_quantifier"]) == "some":
            mode = "append"
        else:
            mode = "exact"
        parse_primes(info, query, "ram_primes", "ramified primes", "ramps", mode, to_string=True)
    except ValueError:
        return search_input_error(info, bread)
    count = parse_count(info)
    start = parse_start(info)

    if info.get("paging"):
        try:
            paging = int(info["paging"])
            if paging == 0:
                start = 0
        except:
            pass

    C = base.getDBConnection()
    # nf_logger.debug(query)
    info["query"] = dict(query)
    if "lucky" in args:
        one = C.numberfields.fields.find_one(query)
        if one:
            label = one["label"]
            return redirect(url_for(".by_label", clean_input(label)))

    fields = C.numberfields.fields

    res = fields.find(query)

    if "download" in info and info["download"] != "0":
        return download_search(info, res)

    res = res.sort([("degree", ASC), ("disc_abs_key", ASC), ("disc_sign", ASC)])
    nres = res.count()
    res = res.skip(start).limit(count)

    if start >= nres:
        start -= (1 + (start - nres) / count) * count
    if start < 0:
        start = 0

    info["fields"] = res
    info["number"] = nres
    info["start"] = start
    if nres == 1:
        info["report"] = "unique match"
    else:
        if nres > count or start != 0:
            info["report"] = "displaying matches %s-%s of %s" % (start + 1, min(nres, start + count), nres)
        else:
            info["report"] = "displaying all %s matches" % nres

    info["wnf"] = WebNumberField.from_data
    return render_template("number_field_search.html", info=info, title=t, bread=bread)
Exemplo n.º 15
0
def elliptic_curve_search(info):

    if info.get('download') == '1' and info.get('Submit') and info.get('query'):
        return download_search(info)

    if 'SearchAgain' in info:
        return rational_elliptic_curves()

    query = {}
    bread = info.get('bread',[('Elliptic Curves', url_for("ecnf.index")), ('$\Q$', url_for(".rational_elliptic_curves")), ('Search Results', '.')])

    if 'jump' in info:
        label = info.get('label', '').replace(" ", "")
        m = match_lmfdb_label(label)
        if m:
            try:
                return by_ec_label(label)
            except ValueError:
                return elliptic_curve_jump_error(label, info, wellformed_label=True)
        elif label.startswith("Cremona:"):
            label = label[8:]
            m = match_cremona_label(label)
            if m:
                try:
                    return by_ec_label(label)
                except ValueError:
                    return elliptic_curve_jump_error(label, info, wellformed_label=True)
        elif match_cremona_label(label):
            return elliptic_curve_jump_error(label, info, cremona_label=True)
        elif label:
            # Try to parse a string like [1,0,3,2,4] as valid
            # Weistrass coefficients:
            lab = re.sub(r'\s','',label)
            lab = re.sub(r'^\[','',lab)
            lab = re.sub(r']$','',lab)
            try:
                labvec = lab.split(',')
                labvec = [QQ(str(z)) for z in labvec] # Rationals allowed
                E = EllipticCurve(labvec).minimal_model()
                # Now we do have a valid curve over Q, but it might
                # not be in the database.
                data = db_ec().find_one({'xainvs': EC_ainvs(E)})
                if data is None:
                    info['conductor'] = E.conductor()
                    return elliptic_curve_jump_error(label, info, missing_curve=True)
                return by_ec_label(data['lmfdb_label'])
            except (TypeError, ValueError, ArithmeticError):
                return elliptic_curve_jump_error(label, info)
        else:
            query['label'] = ''

    try:
        parse_rational(info,query,'jinv','j-invariant')
        parse_ints(info,query,'conductor')
        parse_ints(info,query,'torsion','torsion order')
        parse_ints(info,query,'rank')
        parse_ints(info,query,'sha','analytic order of &#1064;')
        parse_bracketed_posints(info,query,'torsion_structure',maxlength=2,process=str,check_divisibility='increasing')
        # speed up slow torsion_structure searches by also setting torsion
        if 'torsion_structure' in query and not 'torsion' in query:
            query['torsion'] = reduce(mul,[int(n) for n in query['torsion_structure']],1)
        if 'include_cm' in info:
            if info['include_cm'] == 'exclude':
                query['cm'] = 0
            elif info['include_cm'] == 'only':
                query['cm'] = {'$ne' : 0}

        parse_ints(info,query,field='isodeg',qfield='isogeny_degrees')

        parse_primes(info, query, 'surj_primes', name='surjective primes',
                     qfield='non-maximal_primes', mode='complement')
        if info.get('surj_quantifier') == 'exactly':
            mode = 'exact'
        else:
            mode = 'append'
        parse_primes(info, query, 'nonsurj_primes', name='non-surjective primes',
                     qfield='non-maximal_primes',mode=mode)
    except ValueError as err:
        info['err'] = str(err)
        return search_input_error(info, bread)

    count = parse_count(info,100)
    start = parse_start(info)

    if 'optimal' in info and info['optimal'] == 'on':
        # fails on 990h3
        query['number'] = 1

    info['query'] = query
    cursor = db_ec().find(query);
    cursor = cursor.sort([('conductor', ASCENDING), ('iso_nlabel', ASCENDING),
                       ('lmfdb_number', ASCENDING)]);
    # equivalent to
    # cursor = res
    # nres = res.count()
    # if(start >= nres):
    #     start -= (1 + (start - nres) / count) * count
    # if(start < 0):
    #    start = 0
    # res = res.skip(start).limit(count)
    try:
        start, nres, res = search_cursor_timeout_decorator(cursor, start, count);
    except ValueError as err:
        info['err'] = err;
        return search_input_error(info, bread)

    info['curves'] = res
    info['curve_url'] = lambda dbc: url_for(".by_triple_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1], number=dbc['lmfdb_number'])
    info['iso_url'] = lambda dbc: url_for(".by_double_iso_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1])
    info['number'] = nres
    info['start'] = start
    info['count'] = count
    info['more'] = int(start + count < nres)

    if nres == 1:
        info['report'] = 'unique match'
    elif nres == 2: 
        info['report'] = 'displaying both matches'
    else:
        if nres > count or start != 0:
            info['report'] = 'displaying matches %s-%s of %s' % (start + 1, min(nres, start + count), nres)
        else:
            info['report'] = 'displaying all %s matches' % nres

    t = info.get('title','Elliptic Curves search results')
    return render_template("ec-search-results.html", info=info, credit=ec_credit(), bread=bread, title=t)
Exemplo n.º 16
0
def number_field_search(**args):
    info = to_dict(args)

    info['learnmore'] = [('Global number field labels', url_for(".render_labels_page")), ('Galois group labels', url_for(".render_groups_page")), (Completename, url_for(".render_discriminants_page")), ('Quadratic imaginary class groups', url_for(".render_class_group_data"))]
    t = 'Global Number Field search results'
    bread = [('Global Number Fields', url_for(".number_field_render_webpage")), ('Search results', ' ')]

    # for k in info.keys():
    #  nf_logger.debug(str(k) + ' ---> ' + str(info[k]))
    # nf_logger.debug('******************* '+ str(info['search']))

    if 'natural' in info:
        query = {'label_orig': info['natural']}
        try:
            parse_nf_string(info,query,'natural',name="Label",qfield='label')
            return redirect(url_for(".by_label", label= clean_input(query['label_orig'])))
        except ValueError:
            query['err'] = info['err']
            return search_input_error(query, bread)

    query = {}
    try:
        parse_galgrp(info,query, qfield='galois')
        parse_ints(info,query,'degree')
        parse_bracketed_posints(info,query,'signature',split=False,exactlength=2)
        parse_signed_ints(info,query,'discriminant',qfield=('disc_sign','disc_abs_key'),parse_one=make_disc_key)
        parse_ints(info,query,'class_number')
        parse_bracketed_posints(info,query,'class_group',split=False,check_divisibility='increasing')
        parse_primes(info,query,'ur_primes',name='Unramified primes',qfield='ramps',mode='complement',to_string=True)
        # modes are now contained (in), exactly, include
        if 'ram_quantifier' in info and str(info['ram_quantifier']) == 'include':
            mode = 'append'
            parse_primes(info,query,'ram_primes','ramified primes','ramps',mode,to_string=True)
        elif 'ram_quantifier' in info and str(info['ram_quantifier']) == 'contained':
            parse_primes(info,query,'ram_primes','ramified primes','ramps_all','subsets',to_string=False)
            pass # build list
        else:
            mode = 'liststring'
            parse_primes(info,query,'ram_primes','ramified primes','ramps_all',mode)
    except ValueError:
        return search_input_error(info, bread)
    count = parse_count(info)
    start = parse_start(info)

    if info.get('paging'):
        try:
            paging = int(info['paging'])
            if paging == 0:
                start = 0
        except:
            pass

    C = base.getDBConnection()
    # nf_logger.debug(query)
    info['query'] = dict(query)
    if 'lucky' in args:
        one = C.numberfields.fields.find_one(query)
        if one:
            label = one['label']
            return redirect(url_for(".by_label", label=clean_input(label)))

    fields = C.numberfields.fields

    res = fields.find(query)
    res = res.sort([('degree', ASC), ('disc_abs_key', ASC),('disc_sign', ASC)])

    if 'download' in info and info['download'] != '0':
        return download_search(info, res)

    nres = res.count()
    res = res.skip(start).limit(count)

    if(start >= nres):
        start -= (1 + (start - nres) / count) * count
    if(start < 0):
        start = 0

    info['fields'] = res
    info['number'] = nres
    info['start'] = start
    if nres == 1:
        info['report'] = 'unique match'
    else:
        if nres > count or start != 0:
            info['report'] = 'displaying matches %s-%s of %s' % (start + 1, min(nres, start + count), nres)
        else:
            info['report'] = 'displaying all %s matches' % nres

    info['wnf'] = WebNumberField.from_data
    return render_template("number_field_search.html", info=info, title=t, bread=bread)
Exemplo n.º 17
0
def artin_representation_search(**args):
    info = to_dict(args)
    if 'natural' in info:
        label = info['natural']
        # test if it is ok
        try:
            label = parse_artin_label(label)
        except ValueError as err:
            flash(Markup("Error: %s" % (err)), "error")
            bread = get_bread([('Search results', '')])
            return search_input_error({'err': ''}, bread)
        return render_artin_representation_webpage(label)

    title = 'Artin representation search results'
    bread = [('Artin representation', url_for(".index")),
             ('Search results', ' ')]
    sign_code = 0
    query = {'Hide': 0}
    try:
        parse_primes(info,
                     query,
                     "unramified",
                     name="Unramified primes",
                     qfield="BadPrimes",
                     mode="complement",
                     to_string=True)
        parse_primes(info,
                     query,
                     "ramified",
                     name="Ramified primes",
                     qfield="BadPrimes",
                     mode="append",
                     to_string=True)
        parse_restricted(info,
                         query,
                         "root_number",
                         qfield="GaloisConjugates.Sign",
                         allowed=[1, -1],
                         process=int)
        parse_restricted(info,
                         query,
                         "frobenius_schur_indicator",
                         qfield="Indicator",
                         allowed=[1, 0, -1],
                         process=int)
        parse_galgrp(info,
                     query,
                     "group",
                     name="Group",
                     qfield="Galois_nt",
                     use_bson=False)
        parse_ints(info, query, 'dimension', qfield='Dim')
        parse_ints(info,
                   query,
                   'conductor',
                   qfield='Conductor_key',
                   parse_singleton=make_cond_key)
        #parse_paired_fields(info,query,field1='conductor',qfield1='Conductor_key',parse1=parse_ints,kwds1={'parse_singleton':make_cond_key},
        #field2='dimension',qfield2='Dim', parse2=parse_ints)
    except ValueError:
        return search_input_error(info, bread)

    count = parse_count(info, 10)
    start = parse_start(info)

    data = ArtinRepresentation.collection().find(query).sort([("Dim", ASC),
                                                              ("Conductor_key",
                                                               ASC)])
    nres = data.count()
    data = data.skip(start).limit(count)

    if (start >= nres):
        start -= (1 + (start - nres) / count) * count
    if (start < 0):
        start = 0
    if nres == 1:
        report = 'unique match'
    else:
        if nres > count or start != 0:
            report = 'displaying matches %s-%s of %s' % (
                start + 1, min(nres, start + count), nres)
        else:
            report = 'displaying all %s matches' % nres
    if nres == 0:
        report = 'no matches'

    initfunc = ArtinRepresentation

    return render_template("artin-representation-search.html",
                           req=info,
                           data=data,
                           title=title,
                           bread=bread,
                           query=query,
                           start=start,
                           report=report,
                           nres=nres,
                           initfunc=initfunc,
                           sign_code=sign_code)
Exemplo n.º 18
0
def elliptic_curve_search(**args):
    info = to_dict(args)

    if "download" in info and info["download"] != "0":
        return download_search(info)

    query = {}
    bread = [
        ("Elliptic Curves", url_for("ecnf.index")),
        ("$\Q$", url_for(".rational_elliptic_curves")),
        ("Search Results", "."),
    ]
    if "SearchAgain" in args:
        return rational_elliptic_curves()

    if "jump" in args:
        label = info.get("label", "").replace(" ", "")
        m = match_lmfdb_label(label)
        if m:
            try:
                return by_ec_label(label)
            except ValueError:
                return elliptic_curve_jump_error(label, info, wellformed_label=True)
        elif label.startswith("Cremona:"):
            label = label[8:]
            m = match_cremona_label(label)
            if m:
                try:
                    return by_ec_label(label)
                except ValueError:
                    return elliptic_curve_jump_error(label, info, wellformed_label=True)
        elif match_cremona_label(label):
            return elliptic_curve_jump_error(label, info, cremona_label=True)
        elif label:
            # Try to parse a string like [1,0,3,2,4] as valid
            # Weistrass coefficients:
            lab = re.sub(r"\s", "", label)
            lab = re.sub(r"^\[", "", lab)
            lab = re.sub(r"]$", "", lab)
            try:
                labvec = lab.split(",")
                labvec = [QQ(str(z)) for z in labvec]  # Rationals allowed
                E = EllipticCurve(labvec)
                # Now we do have a valid curve over Q, but it might
                # not be in the database.
                ainvs = [str(c) for c in E.minimal_model().ainvs()]
                data = db_ec().find_one({"ainvs": ainvs})
                if data is None:
                    info["conductor"] = E.conductor()
                    return elliptic_curve_jump_error(label, info, missing_curve=True)
                return by_ec_label(data["lmfdb_label"])
            except (TypeError, ValueError, ArithmeticError):
                return elliptic_curve_jump_error(label, info)
        else:
            query["label"] = ""

    try:
        parse_rational(info, query, "jinv", "j-invariant")
        parse_ints(info, query, "conductor")
        parse_ints(info, query, "torsion", "torsion order")
        parse_ints(info, query, "rank")
        parse_ints(info, query, "sha", "analytic order of &#1064;")
        parse_bracketed_posints(
            info, query, "torsion_structure", maxlength=2, process=str, check_divisibility="increasing"
        )
        parse_primes(
            info, query, "surj_primes", name="surjective primes", qfield="non-surjective_primes", mode="complement"
        )
        if info.get("surj_quantifier") == "exactly":
            mode = "exact"
        else:
            mode = "append"
        parse_primes(
            info, query, "nonsurj_primes", name="non-surjective primes", qfield="non-surjective_primes", mode=mode
        )
    except ValueError as err:
        info["err"] = str(err)
        return search_input_error(info, bread)

    count = parse_count(info, 100)
    start = parse_start(info)

    if "optimal" in info and info["optimal"] == "on":
        # fails on 990h3
        query["number"] = 1

    info["query"] = query
    cursor = db_ec().find(query)
    nres = cursor.count()
    if start >= nres:
        start -= (1 + (start - nres) / count) * count
    if start < 0:
        start = 0
    res = (
        cursor.sort([("conductor", ASCENDING), ("iso_nlabel", ASCENDING), ("lmfdb_number", ASCENDING)])
        .skip(start)
        .limit(count)
    )
    info["curves"] = res
    info["format_ainvs"] = format_ainvs
    info["curve_url"] = lambda dbc: url_for(
        ".by_triple_label",
        conductor=dbc["conductor"],
        iso_label=split_lmfdb_label(dbc["lmfdb_iso"])[1],
        number=dbc["lmfdb_number"],
    )
    info["iso_url"] = lambda dbc: url_for(
        ".by_double_iso_label", conductor=dbc["conductor"], iso_label=split_lmfdb_label(dbc["lmfdb_iso"])[1]
    )
    info["number"] = nres
    info["start"] = start
    info["count"] = count
    info["more"] = int(start + count < nres)

    if nres == 1:
        info["report"] = "unique match"
    elif nres == 2:
        info["report"] = "displaying both matches"
    else:
        if nres > count or start != 0:
            info["report"] = "displaying matches %s-%s of %s" % (start + 1, min(nres, start + count), nres)
        else:
            info["report"] = "displaying all %s matches" % nres
    credit = "John Cremona"
    if "non-surjective_primes" in query:
        credit += "and Andrew Sutherland"
    t = "Elliptic Curves search results"
    return render_template("search_results.html", info=info, credit=credit, bread=bread, title=t)