<commit_before>#! /usr/bin/env python
# -*- coding: utf-8 -*-
import math
import operator
from pycket import values
from pycket.error import SchemeException
from pycket.prims.expose import expose, default, unsafe
from rpython.rlib.rbigint import rbigint
from rpython.rlib         import jit
from rpython.rtyper.lltypesystem.lloperation import llop
from rpython.rtyper.lltypesystem.lltype import Signed, SignedLongLong, \
                                        UnsignedLongLong

# imported for side effects
from pycket import arithmetic

def make_cmp(name, op, con):
    from pycket.values import W_Number, W_Fixnum, W_Flonum, W_Bignum
    from rpython.rlib.rbigint import rbigint

    @expose(name, simple=True)
    @jit.unroll_safe
    def do(args):
        assert len(args) >= 2
        idx = 2
        truth = True
        while idx <= len(args):
            start = idx - 2
            assert start >= 0
            w_a, w_b = args[start], args[start + 1]
            assert isinstance(w_a, W_Number)
            assert isinstance(w_b, W_Number)
            idx += 1

            if isinstance(w_a, W_Fixnum) and isinstance(w_b, W_Fixnum):
                truth = truth and (getattr(operator, op)(w_a.value, w_b.value))
                continue
            if isinstance(w_a, W_Bignum) and isinstance(w_b, W_Bignum):
                truth = truth and (getattr(w_a.value, op)(w_b.value))
                continue
            if isinstance(w_a, W_Flonum) and isinstance(w_b, W_Flonum):
                truth = truth and (getattr(operator, op)(w_a.value, w_b.value))
                continue

            # Upcast float
            if isinstance(w_a, W_Fixnum) and isinstance(w_b, W_Flonum):
                a = float(w_a.value)
                truth = truth and (getattr(operator, op)(a, w_b.value))
                continue
            if isinstance(w_a, W_Flonum) and isinstance(w_b, W_Fixnum):
                b = float(w_b.value)
                truth = truth and (getattr(operator, op)(w_a.value, b))
                continue

            # Upcast bignum
            if isinstance(w_a, W_Bignum) and isinstance(w_b, W_Fixnum):
                b = rbigint.fromint(w_b.value)
                truth = truth and (getattr(w_a.value, op)(b))
                continue
            if isinstance(w_a, W_Fixnum) and isinstance(w_b, W_Bignum):
                a = rbigint.fromint(w_a.value)
                truth = truth and (getattr(a, op)(w_b.value))
                continue

            # Upcast bignum/float
            if isinstance(w_a, W_Bignum) and isinstance(w_b, W_Flonum):
                b = rbigint.fromfloat(w_b.value)
                truth = truth and (getattr(w_a.value, op)(b))
                continue
            if isinstance(w_a, W_Flonum) and isinstance(w_b, W_Bignum):
                a = rbigint.fromfloat(w_a.value)
                truth = truth and (getattr(a, op)(w_b.value))
                continue

            #FIXME: Complex. Rationals

            raise SchemeException("unsupported operation %s on %s %s" % (
                name, w_a.tostring(), w_b.tostring()))
        return con(truth)
    do.__name__ = op

for args in [
        ("=", "eq", values.W_Bool.make),
        ("<", "lt", values.W_Bool.make),
        (">", "gt", values.W_Bool.make),
        ("<=", "le", values.W_Bool.make),
        (">=", "ge", values.W_Bool.make),
        ]:
    make_cmp(*args)

@expose("integer?", [values.W_Object])
def integerp(n):
    return values.W_Bool.make(isinstance(n, values.W_Fixnum) or
                              isinstance(n, values.W_Bignum) or
                              isinstance(n, values.W_Flonum) and
                              math.floor(n.value) == n.value)


@expose("exact-integer?", [values.W_Object])
def exact_integerp(n):
    return values.W_Bool.make(isinstance(n, values.W_Fixnum) or
                              isinstance(n, values.W_Bignum))

@expose("exact-nonnegative-integer?", [values.W_Object])
def exact_nonneg_integerp(n):
    from rpython.rlib.rbigint import rbigint
    if isinstance(n, values.W_Fixnum):
        return values.W_Bool.make(n.value >= 0)
    if isinstance(n, values.W_Bignum):
        return values.W_Bool.make(n.value.ge(rbigint.fromint(0)))
    return values.w_false

@expose("exact-positive-integer?", [values.W_Object])
def exact_nonneg_integerp(n):
    from rpython.rlib.rbigint import rbigint
    if isinstance(n, values.W_Fixnum):
        return values.W_Bool.make(n.value > 0)
    if isinstance(n, values.W_Bignum):
        return values.W_Bool.make(n.value.gt(rbigint.fromint(0)))
    return values.w_false

@expose("real?", [values.W_Object])
def realp(n):
    return values.W_Bool.make(isinstance(n, values.W_Fixnum) or
                              isinstance(n, values.W_Bignum) or
                              isinstance(n, values.W_Flonum))

@expose("inexact-real?", [values.W_Object])
def inexact_real(n):
    return values.W_Bool.make(isinstance(n, values.W_Flonum))

@expose("single-flonum?", [values.W_Object])
def single_flonum(n):
    return values.w_false

@expose("double-flonum?", [values.W_Object])
def double_flonum(n):
    return values.W_Bool.make(isinstance(n, values.W_Flonum))

@expose("rational?", [values.W_Object])
def rationalp(n):
    if isinstance(n, values.W_Fixnum) or isinstance(n, values.W_Bignum):
        return values.w_true
    if isinstance(n, values.W_Flonum):
        v = n.value
        return values.W_Bool.make(not (math.isnan(v) or math.isinf(v)))

@expose("exact?", [values.W_Object])
def exactp(n):
    return values.W_Bool.make(isinstance(n, values.W_Fixnum) or
                              isinstance(n, values.W_Bignum))

@expose("inexact?", [values.W_Object])
def inexactp(n):
    return values.W_Bool.make(isinstance(n, values.W_Flonum))

@expose("quotient/remainder", [values.W_Integer, values.W_Integer])
def quotient_remainder(a, b):
    return values.Values.make([a.arith_quotient(b), values.W_Fixnum(0)]) #FIXME

def make_binary_arith(name, methname):
    @expose(name, [values.W_Number, values.W_Number], simple=True)
    def do(a, b):
        return getattr(a, methname)(b)
    do.__name__ = methname

for args in [
        ("quotient", "arith_quotient"),
        ("remainder", "arith_mod"), # FIXME
        ("modulo",   "arith_mod"),
        ("expt",     "arith_pow"),
        ]:
    make_binary_arith(*args)


def make_arith(name, neutral_element, methname, supports_zero_args):
    @expose(name, simple=True)
    @jit.unroll_safe
    def do(args):
        # XXX so far (+ '()) returns '(). need better type checking here
        if not args:
            if not supports_zero_args:
                raise SchemeException("expected at least 1 argument to %s" % name)
            return neutral_element
        if len(args) == 1:<commit_msg>Improve quotient/remainder. See issue #51.<commit_after>#! /usr/bin/env python
# -*- coding: utf-8 -*-
import math
import operator
from pycket import values
from pycket.error import SchemeException
from pycket.prims.expose import expose, default, unsafe
from rpython.rlib.rbigint import rbigint
from rpython.rlib         import jit
from rpython.rtyper.lltypesystem.lloperation import llop
from rpython.rtyper.lltypesystem.lltype import Signed, SignedLongLong, \
                                        UnsignedLongLong

# imported for side effects
from pycket import arithmetic

def make_cmp(name, op, con):
    from pycket.values import W_Number, W_Fixnum, W_Flonum, W_Bignum
    from rpython.rlib.rbigint import rbigint

    @expose(name, simple=True)
    @jit.unroll_safe
    def do(args):
        assert len(args) >= 2
        idx = 2
        truth = True
        while idx <= len(args):
            start = idx - 2
            assert start >= 0
            w_a, w_b = args[start], args[start + 1]
            assert isinstance(w_a, W_Number)
            assert isinstance(w_b, W_Number)
            idx += 1

            if isinstance(w_a, W_Fixnum) and isinstance(w_b, W_Fixnum):
                truth = truth and (getattr(operator, op)(w_a.value, w_b.value))
                continue
            if isinstance(w_a, W_Bignum) and isinstance(w_b, W_Bignum):
                truth = truth and (getattr(w_a.value, op)(w_b.value))
                continue
            if isinstance(w_a, W_Flonum) and isinstance(w_b, W_Flonum):
                truth = truth and (getattr(operator, op)(w_a.value, w_b.value))
                continue

            # Upcast float
            if isinstance(w_a, W_Fixnum) and isinstance(w_b, W_Flonum):
                a = float(w_a.value)
                truth = truth and (getattr(operator, op)(a, w_b.value))
                continue
            if isinstance(w_a, W_Flonum) and isinstance(w_b, W_Fixnum):
                b = float(w_b.value)
                truth = truth and (getattr(operator, op)(w_a.value, b))
                continue

            # Upcast bignum
            if isinstance(w_a, W_Bignum) and isinstance(w_b, W_Fixnum):
                b = rbigint.fromint(w_b.value)
                truth = truth and (getattr(w_a.value, op)(b))
                continue
            if isinstance(w_a, W_Fixnum) and isinstance(w_b, W_Bignum):
                a = rbigint.fromint(w_a.value)
                truth = truth and (getattr(a, op)(w_b.value))
                continue

            # Upcast bignum/float
            if isinstance(w_a, W_Bignum) and isinstance(w_b, W_Flonum):
                b = rbigint.fromfloat(w_b.value)
                truth = truth and (getattr(w_a.value, op)(b))
                continue
            if isinstance(w_a, W_Flonum) and isinstance(w_b, W_Bignum):
                a = rbigint.fromfloat(w_a.value)
                truth = truth and (getattr(a, op)(w_b.value))
                continue

            #FIXME: Complex. Rationals

            raise SchemeException("unsupported operation %s on %s %s" % (
                name, w_a.tostring(), w_b.tostring()))
        return con(truth)
    do.__name__ = op

for args in [
        ("=", "eq", values.W_Bool.make),
        ("<", "lt", values.W_Bool.make),
        (">", "gt", values.W_Bool.make),
        ("<=", "le", values.W_Bool.make),
        (">=", "ge", values.W_Bool.make),
        ]:
    make_cmp(*args)

@expose("integer?", [values.W_Object])
def integerp(n):
    return values.W_Bool.make(isinstance(n, values.W_Fixnum) or
                              isinstance(n, values.W_Bignum) or
                              isinstance(n, values.W_Flonum) and
                              math.floor(n.value) == n.value)


@expose("exact-integer?", [values.W_Object])
def exact_integerp(n):
    return values.W_Bool.make(isinstance(n, values.W_Fixnum) or
                              isinstance(n, values.W_Bignum))

@expose("exact-nonnegative-integer?", [values.W_Object])
def exact_nonneg_integerp(n):
    from rpython.rlib.rbigint import rbigint
    if isinstance(n, values.W_Fixnum):
        return values.W_Bool.make(n.value >= 0)
    if isinstance(n, values.W_Bignum):
        return values.W_Bool.make(n.value.ge(rbigint.fromint(0)))
    return values.w_false

@expose("exact-positive-integer?", [values.W_Object])
def exact_nonneg_integerp(n):
    from rpython.rlib.rbigint import rbigint
    if isinstance(n, values.W_Fixnum):
        return values.W_Bool.make(n.value > 0)
    if isinstance(n, values.W_Bignum):
        return values.W_Bool.make(n.value.gt(rbigint.fromint(0)))
    return values.w_false

@expose("real?", [values.W_Object])
def realp(n):
    return values.W_Bool.make(isinstance(n, values.W_Fixnum) or
                              isinstance(n, values.W_Bignum) or
                              isinstance(n, values.W_Flonum))

@expose("inexact-real?", [values.W_Object])
def inexact_real(n):
    return values.W_Bool.make(isinstance(n, values.W_Flonum))

@expose("single-flonum?", [values.W_Object])
def single_flonum(n):
    return values.w_false

@expose("double-flonum?", [values.W_Object])
def double_flonum(n):
    return values.W_Bool.make(isinstance(n, values.W_Flonum))

@expose("rational?", [values.W_Object])
def rationalp(n):
    if isinstance(n, values.W_Fixnum) or isinstance(n, values.W_Bignum):
        return values.w_true
    if isinstance(n, values.W_Flonum):
        v = n.value
        return values.W_Bool.make(not (math.isnan(v) or math.isinf(v)))

@expose("exact?", [values.W_Object])
def exactp(n):
    return values.W_Bool.make(isinstance(n, values.W_Fixnum) or
                              isinstance(n, values.W_Bignum))

@expose("inexact?", [values.W_Object])
def inexactp(n):
    return values.W_Bool.make(isinstance(n, values.W_Flonum))

@expose("quotient/remainder", [values.W_Integer, values.W_Integer])
def quotient_remainder(a, b):
    return values.Values.make([a.arith_quotient(b), a.arith_mod(b)]) #FIXME

def make_binary_arith(name, methname):
    @expose(name, [values.W_Number, values.W_Number], simple=True)
    def do(a, b):
        return getattr(a, methname)(b)
    do.__name__ = methname

for args in [
        ("quotient", "arith_quotient"),
        ("remainder", "arith_mod"), # FIXME
        ("modulo",   "arith_mod"),
        ("expt",     "arith_pow"),
        ]:
    make_binary_arith(*args)


def make_arith(name, neutral_element, methname, supports_zero_args):
    @expose(name, simple=True)
    @jit.unroll_safe
    def do(args):
        # XXX so far (+ '()) returns '(). need better type checking here
        if not args:
            if not supports_zero_args:
                raise SchemeException("expected at least 1 argument to %s" % name)
            return neutral_element
        if len(args) == 1:
{'fraction_non_alphanumeric': 0.12179534268713729, 'fraction_numerical': 0.002130316609123632, 'mean_word_length': 2.378163771712159, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5865362', 'n_tokens_mistral': 4682, 'n_tokens_neox': 4551, 'n_words': 955}