15dfecf96Smrg/*
25dfecf96Smrg * Copyright (c) 2001 by The XFree86 Project, Inc.
35dfecf96Smrg *
45dfecf96Smrg * Permission is hereby granted, free of charge, to any person obtaining a
55dfecf96Smrg * copy of this software and associated documentation files (the "Software"),
65dfecf96Smrg * to deal in the Software without restriction, including without limitation
75dfecf96Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
85dfecf96Smrg * and/or sell copies of the Software, and to permit persons to whom the
95dfecf96Smrg * Software is furnished to do so, subject to the following conditions:
105dfecf96Smrg *
115dfecf96Smrg * The above copyright notice and this permission notice shall be included in
125dfecf96Smrg * all copies or substantial portions of the Software.
135dfecf96Smrg *
145dfecf96Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
155dfecf96Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
165dfecf96Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
175dfecf96Smrg * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
185dfecf96Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
195dfecf96Smrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
205dfecf96Smrg * SOFTWARE.
215dfecf96Smrg *
225dfecf96Smrg * Except as contained in this notice, the name of the XFree86 Project shall
235dfecf96Smrg * not be used in advertising or otherwise to promote the sale, use or other
245dfecf96Smrg * dealings in this Software without prior written authorization from the
255dfecf96Smrg * XFree86 Project.
265dfecf96Smrg *
275dfecf96Smrg * Author: Paulo César Pereira de Andrade
285dfecf96Smrg */
295dfecf96Smrg
305dfecf96Smrg/* $XFree86: xc/programs/xedit/lisp/math.c,v 1.23tsi Exp $ */
315dfecf96Smrg
325dfecf96Smrg#include "lisp/math.h"
335dfecf96Smrg#include "lisp/private.h"
345dfecf96Smrg
35c2cbb186Smrg#ifdef __APPLE__
365dfecf96Smrg# define finite(x) isfinite(x)
375dfecf96Smrg#endif
385dfecf96Smrg
395dfecf96Smrg/*
405dfecf96Smrg * Prototypes
415dfecf96Smrg */
425dfecf96Smrgstatic LispObj *LispDivide(LispBuiltin*, int, int);
435dfecf96Smrg
445dfecf96Smrg/*
455dfecf96Smrg * Initialization
465dfecf96Smrg */
475dfecf96Smrgstatic LispObj *obj_zero, *obj_one;
485dfecf96SmrgLispObj *Ocomplex, *Oequal_;
495dfecf96Smrg
505dfecf96SmrgLispObj *Oshort_float, *Osingle_float, *Odouble_float, *Olong_float;
515dfecf96Smrg
525dfecf96SmrgAtom_id Sdefault_float_format;
535dfecf96Smrg
545dfecf96Smrg/*
555dfecf96Smrg * Implementation
565dfecf96Smrg */
575dfecf96Smrg#include "lisp/mathimp.c"
585dfecf96Smrg
595dfecf96Smrgvoid
605dfecf96SmrgLispMathInit(void)
615dfecf96Smrg{
625dfecf96Smrg    LispObj *object, *result;
635dfecf96Smrg
645dfecf96Smrg    mp_set_malloc(LispMalloc);
655dfecf96Smrg    mp_set_calloc(LispCalloc);
665dfecf96Smrg    mp_set_realloc(LispRealloc);
675dfecf96Smrg    mp_set_free(LispFree);
685dfecf96Smrg
695dfecf96Smrg    number_init();
705dfecf96Smrg    obj_zero = FIXNUM(0);
715dfecf96Smrg    obj_one = FIXNUM(1);
725dfecf96Smrg
735dfecf96Smrg    Oequal_		= STATIC_ATOM("=");
74f14f4646Smrg    Ocomplex		= STATIC_ATOM(Scomplex->value);
755dfecf96Smrg    Oshort_float	= STATIC_ATOM("SHORT-FLOAT");
765dfecf96Smrg    LispExportSymbol(Oshort_float);
775dfecf96Smrg    Osingle_float	= STATIC_ATOM("SINGLE-FLOAT");
785dfecf96Smrg    LispExportSymbol(Osingle_float);
795dfecf96Smrg    Odouble_float	= STATIC_ATOM("DOUBLE-FLOAT");
805dfecf96Smrg    LispExportSymbol(Odouble_float);
815dfecf96Smrg    Olong_float		= STATIC_ATOM("LONG-FLOAT");
825dfecf96Smrg    LispExportSymbol(Olong_float);
835dfecf96Smrg
845dfecf96Smrg    object		= STATIC_ATOM("*DEFAULT-FLOAT-FORMAT*");
855dfecf96Smrg    LispProclaimSpecial(object, Odouble_float, NIL);
865dfecf96Smrg    LispExportSymbol(object);
875dfecf96Smrg    Sdefault_float_format = ATOMID(object);
885dfecf96Smrg
895dfecf96Smrg    object		= STATIC_ATOM("PI");
905dfecf96Smrg    result = number_pi();
915dfecf96Smrg    LispProclaimSpecial(object, result, NIL);
925dfecf96Smrg    LispExportSymbol(object);
935dfecf96Smrg
945dfecf96Smrg    object		= STATIC_ATOM("MOST-POSITIVE-FIXNUM");
955dfecf96Smrg    LispDefconstant(object, FIXNUM(MOST_POSITIVE_FIXNUM), NIL);
965dfecf96Smrg    LispExportSymbol(object);
975dfecf96Smrg
985dfecf96Smrg    object		= STATIC_ATOM("MOST-NEGATIVE-FIXNUM");
995dfecf96Smrg    LispDefconstant(object, FIXNUM(MOST_NEGATIVE_FIXNUM), NIL);
1005dfecf96Smrg    LispExportSymbol(object);
1015dfecf96Smrg}
1025dfecf96Smrg
1035dfecf96SmrgLispObj *
1045dfecf96SmrgLisp_Mul(LispBuiltin *builtin)
1055dfecf96Smrg/*
1065dfecf96Smrg * &rest numbers
1075dfecf96Smrg */
1085dfecf96Smrg{
1095dfecf96Smrg    n_number num;
1105dfecf96Smrg    LispObj *number, *numbers;
1115dfecf96Smrg
1125dfecf96Smrg    numbers = ARGUMENT(0);
1135dfecf96Smrg
1145dfecf96Smrg    if (CONSP(numbers)) {
1155dfecf96Smrg	number = CAR(numbers);
1165dfecf96Smrg
1175dfecf96Smrg	numbers = CDR(numbers);
1185dfecf96Smrg	if (!CONSP(numbers)) {
1195dfecf96Smrg	    CHECK_NUMBER(number);
1205dfecf96Smrg	    return (number);
1215dfecf96Smrg	}
1225dfecf96Smrg    }
1235dfecf96Smrg    else
1245dfecf96Smrg	return (FIXNUM(1));
1255dfecf96Smrg
1265dfecf96Smrg    set_number_object(&num, number);
1275dfecf96Smrg    do {
1285dfecf96Smrg	mul_number_object(&num, CAR(numbers));
1295dfecf96Smrg	numbers = CDR(numbers);
1305dfecf96Smrg    } while (CONSP(numbers));
1315dfecf96Smrg
1325dfecf96Smrg    return (make_number_object(&num));
1335dfecf96Smrg}
1345dfecf96Smrg
1355dfecf96SmrgLispObj *
1365dfecf96SmrgLisp_Plus(LispBuiltin *builtin)
1375dfecf96Smrg/*
1385dfecf96Smrg + &rest numbers
1395dfecf96Smrg */
1405dfecf96Smrg{
1415dfecf96Smrg    n_number num;
1425dfecf96Smrg    LispObj *number, *numbers;
1435dfecf96Smrg
1445dfecf96Smrg    numbers = ARGUMENT(0);
1455dfecf96Smrg
1465dfecf96Smrg    if (CONSP(numbers)) {
1475dfecf96Smrg	number = CAR(numbers);
1485dfecf96Smrg
1495dfecf96Smrg	numbers = CDR(numbers);
1505dfecf96Smrg	if (!CONSP(numbers)) {
1515dfecf96Smrg	    CHECK_NUMBER(number);
1525dfecf96Smrg	    return (number);
1535dfecf96Smrg	}
1545dfecf96Smrg    }
1555dfecf96Smrg    else
1565dfecf96Smrg	return (FIXNUM(0));
1575dfecf96Smrg
1585dfecf96Smrg    set_number_object(&num, number);
1595dfecf96Smrg    do {
1605dfecf96Smrg	add_number_object(&num, CAR(numbers));
1615dfecf96Smrg	numbers = CDR(numbers);
1625dfecf96Smrg    } while (CONSP(numbers));
1635dfecf96Smrg
1645dfecf96Smrg    return (make_number_object(&num));
1655dfecf96Smrg}
1665dfecf96Smrg
1675dfecf96SmrgLispObj *
1685dfecf96SmrgLisp_Minus(LispBuiltin *builtin)
1695dfecf96Smrg/*
1705dfecf96Smrg - number &rest more_numbers
1715dfecf96Smrg */
1725dfecf96Smrg{
1735dfecf96Smrg    n_number num;
1745dfecf96Smrg    LispObj *number, *more_numbers;
1755dfecf96Smrg
1765dfecf96Smrg    more_numbers = ARGUMENT(1);
1775dfecf96Smrg    number = ARGUMENT(0);
1785dfecf96Smrg
1795dfecf96Smrg    set_number_object(&num, number);
1805dfecf96Smrg    if (!CONSP(more_numbers)) {
1815dfecf96Smrg	neg_number(&num);
1825dfecf96Smrg
1835dfecf96Smrg	return (make_number_object(&num));
1845dfecf96Smrg    }
1855dfecf96Smrg    do {
1865dfecf96Smrg	sub_number_object(&num, CAR(more_numbers));
1875dfecf96Smrg	more_numbers = CDR(more_numbers);
1885dfecf96Smrg    } while (CONSP(more_numbers));
1895dfecf96Smrg
1905dfecf96Smrg    return (make_number_object(&num));
1915dfecf96Smrg}
1925dfecf96Smrg
1935dfecf96SmrgLispObj *
1945dfecf96SmrgLisp_Div(LispBuiltin *builtin)
1955dfecf96Smrg/*
1965dfecf96Smrg / number &rest more_numbers
1975dfecf96Smrg */
1985dfecf96Smrg{
1995dfecf96Smrg    n_number num;
2005dfecf96Smrg    LispObj *number, *more_numbers;
2015dfecf96Smrg
2025dfecf96Smrg    more_numbers = ARGUMENT(1);
2035dfecf96Smrg    number = ARGUMENT(0);
2045dfecf96Smrg
2055dfecf96Smrg    if (CONSP(more_numbers))
2065dfecf96Smrg	set_number_object(&num, number);
2075dfecf96Smrg    else {
2085dfecf96Smrg	num.complex = 0;
2095dfecf96Smrg	num.real.type = N_FIXNUM;
2105dfecf96Smrg	num.real.data.fixnum = 1;
2115dfecf96Smrg	goto div_one_argument;
2125dfecf96Smrg    }
2135dfecf96Smrg
2145dfecf96Smrg    for (;;) {
2155dfecf96Smrg	number = CAR(more_numbers);
2165dfecf96Smrg	more_numbers = CDR(more_numbers);
2175dfecf96Smrg
2185dfecf96Smrgdiv_one_argument:
2195dfecf96Smrg	div_number_object(&num, number);
2205dfecf96Smrg	if (!CONSP(more_numbers))
2215dfecf96Smrg	    break;
2225dfecf96Smrg    }
2235dfecf96Smrg
2245dfecf96Smrg    return (make_number_object(&num));
2255dfecf96Smrg}
2265dfecf96Smrg
2275dfecf96SmrgLispObj *
2285dfecf96SmrgLisp_OnePlus(LispBuiltin *builtin)
2295dfecf96Smrg/*
2305dfecf96Smrg 1+ number
2315dfecf96Smrg */
2325dfecf96Smrg{
2335dfecf96Smrg    n_number num;
2345dfecf96Smrg    LispObj *number;
2355dfecf96Smrg
2365dfecf96Smrg    number = ARGUMENT(0);
2375dfecf96Smrg    num.complex = 0;
2385dfecf96Smrg    num.real.type = N_FIXNUM;
2395dfecf96Smrg    num.real.data.fixnum = 1;
2405dfecf96Smrg    add_number_object(&num, number);
2415dfecf96Smrg
2425dfecf96Smrg    return (make_number_object(&num));
2435dfecf96Smrg}
2445dfecf96Smrg
2455dfecf96SmrgLispObj *
2465dfecf96SmrgLisp_OneMinus(LispBuiltin *builtin)
2475dfecf96Smrg/*
2485dfecf96Smrg 1- number
2495dfecf96Smrg */
2505dfecf96Smrg{
2515dfecf96Smrg    n_number num;
2525dfecf96Smrg    LispObj *number;
2535dfecf96Smrg
2545dfecf96Smrg    number = ARGUMENT(0);
2555dfecf96Smrg    num.complex = 0;
2565dfecf96Smrg    num.real.type = N_FIXNUM;
2575dfecf96Smrg    num.real.data.fixnum = -1;
2585dfecf96Smrg    add_number_object(&num, number);
2595dfecf96Smrg
2605dfecf96Smrg    return (make_number_object(&num));
2615dfecf96Smrg}
2625dfecf96Smrg
2635dfecf96SmrgLispObj *
2645dfecf96SmrgLisp_Less(LispBuiltin *builtin)
2655dfecf96Smrg/*
2665dfecf96Smrg < number &rest more-numbers
2675dfecf96Smrg */
2685dfecf96Smrg{
2695dfecf96Smrg    LispObj *compare, *number, *more_numbers;
2705dfecf96Smrg
2715dfecf96Smrg    more_numbers = ARGUMENT(1);
2725dfecf96Smrg    compare = ARGUMENT(0);
2735dfecf96Smrg
2745dfecf96Smrg    if (CONSP(more_numbers)) {
2755dfecf96Smrg	do {
2765dfecf96Smrg	    number = CAR(more_numbers);
2775dfecf96Smrg	    if (cmp_object_object(compare, number, 1) >= 0)
2785dfecf96Smrg		return (NIL);
2795dfecf96Smrg	    compare = number;
2805dfecf96Smrg	    more_numbers = CDR(more_numbers);
2815dfecf96Smrg	} while (CONSP(more_numbers));
2825dfecf96Smrg    }
2835dfecf96Smrg    else {
2845dfecf96Smrg	CHECK_REAL(compare);
2855dfecf96Smrg    }
2865dfecf96Smrg
2875dfecf96Smrg    return (T);
2885dfecf96Smrg}
2895dfecf96Smrg
2905dfecf96SmrgLispObj *
2915dfecf96SmrgLisp_LessEqual(LispBuiltin *builtin)
2925dfecf96Smrg/*
2935dfecf96Smrg <= number &rest more-numbers
2945dfecf96Smrg */
2955dfecf96Smrg{
2965dfecf96Smrg    LispObj *compare, *number, *more_numbers;
2975dfecf96Smrg
2985dfecf96Smrg    more_numbers = ARGUMENT(1);
2995dfecf96Smrg    compare = ARGUMENT(0);
3005dfecf96Smrg
3015dfecf96Smrg    if (CONSP(more_numbers)) {
3025dfecf96Smrg	do {
3035dfecf96Smrg	    number = CAR(more_numbers);
3045dfecf96Smrg	    if (cmp_object_object(compare, number, 1) > 0)
3055dfecf96Smrg		return (NIL);
3065dfecf96Smrg	    compare = number;
3075dfecf96Smrg	    more_numbers = CDR(more_numbers);
3085dfecf96Smrg	} while (CONSP(more_numbers));
3095dfecf96Smrg    }
3105dfecf96Smrg    else {
3115dfecf96Smrg	CHECK_REAL(compare);
3125dfecf96Smrg    }
3135dfecf96Smrg
3145dfecf96Smrg    return (T);
3155dfecf96Smrg}
3165dfecf96Smrg
3175dfecf96SmrgLispObj *
3185dfecf96SmrgLisp_Equal_(LispBuiltin *builtin)
3195dfecf96Smrg/*
3205dfecf96Smrg = number &rest more-numbers
3215dfecf96Smrg */
3225dfecf96Smrg{
3235dfecf96Smrg    LispObj *compare, *number, *more_numbers;
3245dfecf96Smrg
3255dfecf96Smrg    more_numbers = ARGUMENT(1);
3265dfecf96Smrg    compare = ARGUMENT(0);
3275dfecf96Smrg
3285dfecf96Smrg    if (CONSP(more_numbers)) {
3295dfecf96Smrg	do {
3305dfecf96Smrg	    number = CAR(more_numbers);
3315dfecf96Smrg	    if (cmp_object_object(compare, number, 0) != 0)
3325dfecf96Smrg		return (NIL);
3335dfecf96Smrg	    compare = number;
3345dfecf96Smrg	    more_numbers = CDR(more_numbers);
3355dfecf96Smrg	} while (CONSP(more_numbers));
3365dfecf96Smrg    }
3375dfecf96Smrg    else {
3385dfecf96Smrg	CHECK_REAL(compare);
3395dfecf96Smrg    }
3405dfecf96Smrg
3415dfecf96Smrg    return (T);
3425dfecf96Smrg}
3435dfecf96Smrg
3445dfecf96SmrgLispObj *
3455dfecf96SmrgLisp_Greater(LispBuiltin *builtin)
3465dfecf96Smrg/*
3475dfecf96Smrg > number &rest more-numbers
3485dfecf96Smrg */
3495dfecf96Smrg{
3505dfecf96Smrg    LispObj *compare, *number, *more_numbers;
3515dfecf96Smrg
3525dfecf96Smrg    more_numbers = ARGUMENT(1);
3535dfecf96Smrg    compare = ARGUMENT(0);
3545dfecf96Smrg
3555dfecf96Smrg    if (CONSP(more_numbers)) {
3565dfecf96Smrg	do {
3575dfecf96Smrg	    number = CAR(more_numbers);
3585dfecf96Smrg	    if (cmp_object_object(compare, number, 1) <= 0)
3595dfecf96Smrg		return (NIL);
3605dfecf96Smrg	    compare = number;
3615dfecf96Smrg	    more_numbers = CDR(more_numbers);
3625dfecf96Smrg	} while (CONSP(more_numbers));
3635dfecf96Smrg    }
3645dfecf96Smrg    else {
3655dfecf96Smrg	CHECK_REAL(compare);
3665dfecf96Smrg    }
3675dfecf96Smrg
3685dfecf96Smrg    return (T);
3695dfecf96Smrg}
3705dfecf96Smrg
3715dfecf96SmrgLispObj *
3725dfecf96SmrgLisp_GreaterEqual(LispBuiltin *builtin)
3735dfecf96Smrg/*
3745dfecf96Smrg >= number &rest more-numbers
3755dfecf96Smrg */
3765dfecf96Smrg{
3775dfecf96Smrg    LispObj *compare, *number, *more_numbers;
3785dfecf96Smrg
3795dfecf96Smrg    more_numbers = ARGUMENT(1);
3805dfecf96Smrg    compare = ARGUMENT(0);
3815dfecf96Smrg
3825dfecf96Smrg    if (CONSP(more_numbers)) {
3835dfecf96Smrg	do {
3845dfecf96Smrg	    number = CAR(more_numbers);
3855dfecf96Smrg	    if (cmp_object_object(compare, number, 1) < 0)
3865dfecf96Smrg		return (NIL);
3875dfecf96Smrg	    compare = number;
3885dfecf96Smrg	    more_numbers = CDR(more_numbers);
3895dfecf96Smrg	} while (CONSP(more_numbers));
3905dfecf96Smrg    }
3915dfecf96Smrg    else {
3925dfecf96Smrg	CHECK_REAL(compare);
3935dfecf96Smrg    }
3945dfecf96Smrg
3955dfecf96Smrg    return (T);
3965dfecf96Smrg}
3975dfecf96Smrg
3985dfecf96SmrgLispObj *
3995dfecf96SmrgLisp_NotEqual(LispBuiltin *builtin)
4005dfecf96Smrg/*
4015dfecf96Smrg /= number &rest more-numbers
4025dfecf96Smrg */
4035dfecf96Smrg{
4045dfecf96Smrg    LispObj *object, *compare, *number, *more_numbers;
4055dfecf96Smrg
4065dfecf96Smrg    more_numbers = ARGUMENT(1);
4075dfecf96Smrg    number = ARGUMENT(0);
4085dfecf96Smrg
4095dfecf96Smrg    if (!CONSP(more_numbers)) {
4105dfecf96Smrg	CHECK_REAL(number);
4115dfecf96Smrg
4125dfecf96Smrg	return (T);
4135dfecf96Smrg    }
4145dfecf96Smrg
4155dfecf96Smrg    /* compare all numbers */
4165dfecf96Smrg    while (1) {
4175dfecf96Smrg	compare = number;
4185dfecf96Smrg	for (object = more_numbers; CONSP(object); object = CDR(object)) {
4195dfecf96Smrg	    number = CAR(object);
4205dfecf96Smrg
4215dfecf96Smrg	    if (cmp_object_object(compare, number, 0) == 0)
4225dfecf96Smrg		return (NIL);
4235dfecf96Smrg	}
4245dfecf96Smrg	if (CONSP(more_numbers)) {
4255dfecf96Smrg	    number = CAR(more_numbers);
4265dfecf96Smrg	    more_numbers = CDR(more_numbers);
4275dfecf96Smrg	}
4285dfecf96Smrg	else
4295dfecf96Smrg	    break;
4305dfecf96Smrg    }
4315dfecf96Smrg
4325dfecf96Smrg    return (T);
4335dfecf96Smrg}
4345dfecf96Smrg
4355dfecf96SmrgLispObj *
4365dfecf96SmrgLisp_Min(LispBuiltin *builtin)
4375dfecf96Smrg/*
4385dfecf96Smrg min number &rest more-numbers
4395dfecf96Smrg */
4405dfecf96Smrg{
4415dfecf96Smrg    LispObj *result, *number, *more_numbers;
4425dfecf96Smrg
4435dfecf96Smrg    more_numbers = ARGUMENT(1);
4445dfecf96Smrg    result = ARGUMENT(0);
4455dfecf96Smrg
4465dfecf96Smrg    if (CONSP(more_numbers)) {
4475dfecf96Smrg	do {
4485dfecf96Smrg	    number = CAR(more_numbers);
4495dfecf96Smrg	    if (cmp_object_object(result, number, 1) > 0)
4505dfecf96Smrg		result = number;
4515dfecf96Smrg	    more_numbers = CDR(more_numbers);
4525dfecf96Smrg	} while (CONSP(more_numbers));
4535dfecf96Smrg    }
4545dfecf96Smrg    else {
4555dfecf96Smrg	CHECK_REAL(result);
4565dfecf96Smrg    }
4575dfecf96Smrg
4585dfecf96Smrg    return (result);
4595dfecf96Smrg}
4605dfecf96Smrg
4615dfecf96SmrgLispObj *
4625dfecf96SmrgLisp_Max(LispBuiltin *builtin)
4635dfecf96Smrg/*
4645dfecf96Smrg max number &rest more-numbers
4655dfecf96Smrg */
4665dfecf96Smrg{
4675dfecf96Smrg    LispObj *result, *number, *more_numbers;
4685dfecf96Smrg
4695dfecf96Smrg    more_numbers = ARGUMENT(1);
4705dfecf96Smrg    result = ARGUMENT(0);
4715dfecf96Smrg
4725dfecf96Smrg    if (CONSP(more_numbers)) {
4735dfecf96Smrg	do {
4745dfecf96Smrg	    number = CAR(more_numbers);
4755dfecf96Smrg	    if (cmp_object_object(result, number, 1) < 0)
4765dfecf96Smrg		result = number;
4775dfecf96Smrg	    more_numbers = CDR(more_numbers);
4785dfecf96Smrg	} while (CONSP(more_numbers));
4795dfecf96Smrg    }
4805dfecf96Smrg    else {
4815dfecf96Smrg	CHECK_REAL(result);
4825dfecf96Smrg    }
4835dfecf96Smrg
4845dfecf96Smrg    return (result);
4855dfecf96Smrg}
4865dfecf96Smrg
4875dfecf96SmrgLispObj *
4885dfecf96SmrgLisp_Abs(LispBuiltin *builtin)
4895dfecf96Smrg/*
4905dfecf96Smrg abs number
4915dfecf96Smrg */
4925dfecf96Smrg{
4935dfecf96Smrg    LispObj *result, *number;
4945dfecf96Smrg
4955dfecf96Smrg    result = number = ARGUMENT(0);
4965dfecf96Smrg
4975dfecf96Smrg    switch (OBJECT_TYPE(number)) {
4985dfecf96Smrg	case LispFixnum_t:
4995dfecf96Smrg	case LispInteger_t:
5005dfecf96Smrg	case LispBignum_t:
5015dfecf96Smrg	case LispDFloat_t:
5025dfecf96Smrg	case LispRatio_t:
5035dfecf96Smrg	case LispBigratio_t:
5045dfecf96Smrg	    if (cmp_real_object(&zero, number) > 0) {
5055dfecf96Smrg		n_real real;
5065dfecf96Smrg
5075dfecf96Smrg		set_real_object(&real, number);
5085dfecf96Smrg		neg_real(&real);
5095dfecf96Smrg		result = make_real_object(&real);
5105dfecf96Smrg	    }
5115dfecf96Smrg	    break;
5125dfecf96Smrg	case LispComplex_t: {
5135dfecf96Smrg	    n_number num;
5145dfecf96Smrg
5155dfecf96Smrg	    set_number_object(&num, number);
5165dfecf96Smrg	    abs_number(&num);
5175dfecf96Smrg	    result = make_number_object(&num);
5185dfecf96Smrg	}   break;
5195dfecf96Smrg	default:
5205dfecf96Smrg	    fatal_builtin_object_error(builtin, number, NOT_A_NUMBER);
5215dfecf96Smrg	    break;
5225dfecf96Smrg    }
5235dfecf96Smrg
5245dfecf96Smrg    return (result);
5255dfecf96Smrg}
5265dfecf96Smrg
5275dfecf96SmrgLispObj *
5285dfecf96SmrgLisp_Complex(LispBuiltin *builtin)
5295dfecf96Smrg/*
5305dfecf96Smrg complex realpart &optional imagpart
5315dfecf96Smrg */
5325dfecf96Smrg{
5335dfecf96Smrg    LispObj *realpart, *imagpart;
5345dfecf96Smrg
5355dfecf96Smrg    imagpart = ARGUMENT(1);
5365dfecf96Smrg    realpart = ARGUMENT(0);
5375dfecf96Smrg
5385dfecf96Smrg    CHECK_REAL(realpart);
5395dfecf96Smrg
5405dfecf96Smrg    if (imagpart == UNSPEC)
5415dfecf96Smrg	return (realpart);
5425dfecf96Smrg    else {
5435dfecf96Smrg	CHECK_REAL(imagpart);
5445dfecf96Smrg    }
5455dfecf96Smrg    if (!FLOATP(imagpart) && cmp_real_object(&zero, imagpart) == 0)
5465dfecf96Smrg	return (realpart);
5475dfecf96Smrg
5485dfecf96Smrg    return (COMPLEX(realpart, imagpart));
5495dfecf96Smrg}
5505dfecf96Smrg
5515dfecf96SmrgLispObj *
5525dfecf96SmrgLisp_Complexp(LispBuiltin *builtin)
5535dfecf96Smrg/*
5545dfecf96Smrg complexp object
5555dfecf96Smrg */
5565dfecf96Smrg{
5575dfecf96Smrg    LispObj *object;
5585dfecf96Smrg
5595dfecf96Smrg    object = ARGUMENT(0);
5605dfecf96Smrg
5615dfecf96Smrg    return (COMPLEXP(object) ? T : NIL);
5625dfecf96Smrg}
5635dfecf96Smrg
5645dfecf96SmrgLispObj *
5655dfecf96SmrgLisp_Conjugate(LispBuiltin *builtin)
5665dfecf96Smrg/*
5675dfecf96Smrg conjugate number
5685dfecf96Smrg */
5695dfecf96Smrg{
5705dfecf96Smrg    n_number num;
5715dfecf96Smrg    LispObj *number, *realpart, *imagpart;
5725dfecf96Smrg
5735dfecf96Smrg    number = ARGUMENT(0);
5745dfecf96Smrg
5755dfecf96Smrg    CHECK_NUMBER(number);
5765dfecf96Smrg
5775dfecf96Smrg    if (REALP(number))
5785dfecf96Smrg	return (number);
5795dfecf96Smrg
5805dfecf96Smrg    realpart = OCXR(number);
5815dfecf96Smrg    num.complex = 0;
5825dfecf96Smrg    num.real.type = N_FIXNUM;
5835dfecf96Smrg    num.real.data.fixnum = -1;
5845dfecf96Smrg    mul_number_object(&num, OCXI(number));
5855dfecf96Smrg    imagpart = make_number_object(&num);
5865dfecf96Smrg
5875dfecf96Smrg    return (COMPLEX(realpart, imagpart));
5885dfecf96Smrg}
5895dfecf96Smrg
5905dfecf96SmrgLispObj *
5915dfecf96SmrgLisp_Decf(LispBuiltin *builtin)
5925dfecf96Smrg/*
5935dfecf96Smrg decf place &optional delta
5945dfecf96Smrg */
5955dfecf96Smrg{
5965dfecf96Smrg    n_number num;
5975dfecf96Smrg    LispObj *place, *delta, *number;
5985dfecf96Smrg
5995dfecf96Smrg    delta = ARGUMENT(1);
6005dfecf96Smrg    place = ARGUMENT(0);
6015dfecf96Smrg
6025dfecf96Smrg    if (SYMBOLP(place)) {
6035dfecf96Smrg	number = LispGetVar(place);
6045dfecf96Smrg	if (number == NULL)
6055dfecf96Smrg	    LispDestroy("EVAL: the variable %s is unbound", STROBJ(place));
6065dfecf96Smrg    }
6075dfecf96Smrg    else
6085dfecf96Smrg	number = EVAL(place);
6095dfecf96Smrg
6105dfecf96Smrg    if (delta != UNSPEC) {
6115dfecf96Smrg	LispObj *operand;
6125dfecf96Smrg
6135dfecf96Smrg	operand = EVAL(delta);
6145dfecf96Smrg	set_number_object(&num, number);
6155dfecf96Smrg	sub_number_object(&num, operand);
6165dfecf96Smrg	number = make_number_object(&num);
6175dfecf96Smrg    }
6185dfecf96Smrg    else {
6195dfecf96Smrg	num.complex = 0;
6205dfecf96Smrg	num.real.type = N_FIXNUM;
6215dfecf96Smrg	num.real.data.fixnum = -1;
6225dfecf96Smrg	add_number_object(&num, number);
6235dfecf96Smrg	number = make_number_object(&num);
6245dfecf96Smrg    }
6255dfecf96Smrg
6265dfecf96Smrg    if (SYMBOLP(place)) {
6275dfecf96Smrg	CHECK_CONSTANT(place);
6285dfecf96Smrg	LispSetVar(place, number);
6295dfecf96Smrg    }
6305dfecf96Smrg    else {
6315dfecf96Smrg	GC_ENTER();
6325dfecf96Smrg
6335dfecf96Smrg	GC_PROTECT(number);
6345dfecf96Smrg	(void)APPLY2(Osetf, place, number);
6355dfecf96Smrg	GC_LEAVE();
6365dfecf96Smrg    }
6375dfecf96Smrg
6385dfecf96Smrg    return (number);
6395dfecf96Smrg}
6405dfecf96Smrg
6415dfecf96SmrgLispObj *
6425dfecf96SmrgLisp_Denominator(LispBuiltin *builtin)
6435dfecf96Smrg/*
6445dfecf96Smrg denominator rational
6455dfecf96Smrg */
6465dfecf96Smrg{
6475dfecf96Smrg    LispObj *result, *rational;
6485dfecf96Smrg
6495dfecf96Smrg    rational = ARGUMENT(0);
6505dfecf96Smrg
6515dfecf96Smrg    switch (OBJECT_TYPE(rational)) {
6525dfecf96Smrg	case LispFixnum_t:
6535dfecf96Smrg	case LispInteger_t:
6545dfecf96Smrg	case LispBignum_t:
6555dfecf96Smrg	    result = FIXNUM(1);
6565dfecf96Smrg	    break;
6575dfecf96Smrg	case LispRatio_t:
6585dfecf96Smrg	    result = INTEGER(OFRD(rational));
6595dfecf96Smrg	    break;
6605dfecf96Smrg	case LispBigratio_t:
6615dfecf96Smrg	    if (mpi_fiti(OBRD(rational)))
6625dfecf96Smrg		result = INTEGER(mpi_geti(OBRD(rational)));
6635dfecf96Smrg	    else {
6645dfecf96Smrg		mpi *den = XALLOC(mpi);
6655dfecf96Smrg
6665dfecf96Smrg		mpi_init(den);
6675dfecf96Smrg		mpi_set(den, OBRD(rational));
6685dfecf96Smrg		result = BIGNUM(den);
6695dfecf96Smrg	    }
6705dfecf96Smrg	    break;
6715dfecf96Smrg	default:
6725dfecf96Smrg	    LispDestroy("%s: %s is not a rational number",
6735dfecf96Smrg			STRFUN(builtin), STROBJ(rational));
6745dfecf96Smrg	    /*NOTREACHED*/
6755dfecf96Smrg	    result = NIL;
6765dfecf96Smrg    }
6775dfecf96Smrg
6785dfecf96Smrg    return (result);
6795dfecf96Smrg}
6805dfecf96Smrg
6815dfecf96SmrgLispObj *
6825dfecf96SmrgLisp_Evenp(LispBuiltin *builtin)
6835dfecf96Smrg/*
6845dfecf96Smrg evenp integer
6855dfecf96Smrg */
6865dfecf96Smrg{
6875dfecf96Smrg    LispObj *result, *integer;
6885dfecf96Smrg
6895dfecf96Smrg    integer = ARGUMENT(0);
6905dfecf96Smrg
6915dfecf96Smrg    switch (OBJECT_TYPE(integer)) {
6925dfecf96Smrg	case LispFixnum_t:
6935dfecf96Smrg	    result = FIXNUM_VALUE(integer) % 2 ? NIL : T;
6945dfecf96Smrg	    break;
6955dfecf96Smrg	case LispInteger_t:
6965dfecf96Smrg	    result = INT_VALUE(integer) % 2 ? NIL : T;
6975dfecf96Smrg	    break;
6985dfecf96Smrg	case LispBignum_t:
6995dfecf96Smrg	    result = mpi_remi(OBI(integer), 2) ? NIL : T;
7005dfecf96Smrg	    break;
7015dfecf96Smrg	default:
7025dfecf96Smrg	    fatal_builtin_object_error(builtin, integer, NOT_AN_INTEGER);
7035dfecf96Smrg	    /*NOTREACHED*/
7045dfecf96Smrg	    result = NIL;
7055dfecf96Smrg    }
7065dfecf96Smrg
7075dfecf96Smrg    return (result);
7085dfecf96Smrg}
7095dfecf96Smrg
7105dfecf96Smrg/* only one float format */
7115dfecf96SmrgLispObj *
7125dfecf96SmrgLisp_Float(LispBuiltin *builtin)
7135dfecf96Smrg/*
7145dfecf96Smrg float number &optional other
7155dfecf96Smrg */
7165dfecf96Smrg{
7175dfecf96Smrg    LispObj *number, *other;
7185dfecf96Smrg
7195dfecf96Smrg    other = ARGUMENT(1);
7205dfecf96Smrg    number = ARGUMENT(0);
7215dfecf96Smrg
7225dfecf96Smrg    if (other != UNSPEC) {
7235dfecf96Smrg	CHECK_DFLOAT(other);
7245dfecf96Smrg    }
7255dfecf96Smrg
7265dfecf96Smrg    return (LispFloatCoerce(builtin, number));
7275dfecf96Smrg}
7285dfecf96Smrg
7295dfecf96SmrgLispObj *
7305dfecf96SmrgLispFloatCoerce(LispBuiltin *builtin, LispObj *number)
7315dfecf96Smrg{
7325dfecf96Smrg    double value;
7335dfecf96Smrg
7345dfecf96Smrg    switch (OBJECT_TYPE(number)) {
7355dfecf96Smrg	case LispFixnum_t:
7365dfecf96Smrg	    value = FIXNUM_VALUE(number);
7375dfecf96Smrg	    break;
7385dfecf96Smrg	case LispInteger_t:
7395dfecf96Smrg	    value = INT_VALUE(number);
7405dfecf96Smrg	    break;
7415dfecf96Smrg	case LispBignum_t:
7425dfecf96Smrg	    value = mpi_getd(OBI(number));
7435dfecf96Smrg	    break;
7445dfecf96Smrg	case LispDFloat_t:
7455dfecf96Smrg	    return (number);
7465dfecf96Smrg	case LispRatio_t:
7475dfecf96Smrg	    value = (double)OFRN(number) / (double)OFRD(number);
7485dfecf96Smrg	    break;
7495dfecf96Smrg	case LispBigratio_t:
7505dfecf96Smrg	    value = mpr_getd(OBR(number));
7515dfecf96Smrg	    break;
7525dfecf96Smrg	default:
7535dfecf96Smrg	    value = 0.0;
7545dfecf96Smrg	    fatal_builtin_object_error(builtin, number, NOT_A_REAL_NUMBER);
7555dfecf96Smrg	    break;
7565dfecf96Smrg    }
7575dfecf96Smrg
7585dfecf96Smrg    if (!finite(value))
7595dfecf96Smrg	fatal_error(FLOATING_POINT_OVERFLOW);
7605dfecf96Smrg
7615dfecf96Smrg    return (DFLOAT(value));
7625dfecf96Smrg}
7635dfecf96Smrg
7645dfecf96SmrgLispObj *
7655dfecf96SmrgLisp_Floatp(LispBuiltin *builtin)
7665dfecf96Smrg/*
7675dfecf96Smrg floatp object
7685dfecf96Smrg */
7695dfecf96Smrg{
7705dfecf96Smrg    LispObj *object;
7715dfecf96Smrg
7725dfecf96Smrg    object = ARGUMENT(0);
7735dfecf96Smrg
7745dfecf96Smrg    return (FLOATP(object) ? T : NIL);
7755dfecf96Smrg}
7765dfecf96Smrg
7775dfecf96SmrgLispObj *
7785dfecf96SmrgLisp_Gcd(LispBuiltin *builtin)
7795dfecf96Smrg/*
7805dfecf96Smrg gcd &rest integers
7815dfecf96Smrg */
7825dfecf96Smrg{
7835dfecf96Smrg    n_real real;
7845dfecf96Smrg    LispObj *integers, *integer, *operand;
7855dfecf96Smrg
7865dfecf96Smrg    integers = ARGUMENT(0);
7875dfecf96Smrg
7885dfecf96Smrg    if (!CONSP(integers))
7895dfecf96Smrg	return (FIXNUM(0));
7905dfecf96Smrg
7915dfecf96Smrg    integer = CAR(integers);
7925dfecf96Smrg
7935dfecf96Smrg    CHECK_INTEGER(integer);
7945dfecf96Smrg    set_real_object(&real, integer);
7955dfecf96Smrg    integers = CDR(integers);
7965dfecf96Smrg
7975dfecf96Smrg    for (; CONSP(integers); integers = CDR(integers)) {
7985dfecf96Smrg	operand = CAR(integers);
7995dfecf96Smrg	gcd_real_object(&real, operand);
8005dfecf96Smrg    }
8015dfecf96Smrg    abs_real(&real);
8025dfecf96Smrg
8035dfecf96Smrg    return (make_real_object(&real));
8045dfecf96Smrg}
8055dfecf96Smrg
8065dfecf96SmrgLispObj *
8075dfecf96SmrgLisp_Imagpart(LispBuiltin *builtin)
8085dfecf96Smrg/*
8095dfecf96Smrg imagpart number
8105dfecf96Smrg */
8115dfecf96Smrg{
8125dfecf96Smrg    LispObj *number;
8135dfecf96Smrg
8145dfecf96Smrg    number = ARGUMENT(0);
8155dfecf96Smrg
8165dfecf96Smrg    if (COMPLEXP(number))
8175dfecf96Smrg	return (OCXI(number));
8185dfecf96Smrg    else {
8195dfecf96Smrg	CHECK_REAL(number);
8205dfecf96Smrg    }
8215dfecf96Smrg
8225dfecf96Smrg    return (FIXNUM(0));
8235dfecf96Smrg}
8245dfecf96Smrg
8255dfecf96SmrgLispObj *
8265dfecf96SmrgLisp_Incf(LispBuiltin *builtin)
8275dfecf96Smrg/*
8285dfecf96Smrg incf place &optional delta
8295dfecf96Smrg */
8305dfecf96Smrg{
8315dfecf96Smrg    n_number num;
8325dfecf96Smrg    LispObj *place, *delta, *number;
8335dfecf96Smrg
8345dfecf96Smrg    delta = ARGUMENT(1);
8355dfecf96Smrg    place = ARGUMENT(0);
8365dfecf96Smrg
8375dfecf96Smrg    if (SYMBOLP(place)) {
8385dfecf96Smrg	number = LispGetVar(place);
8395dfecf96Smrg	if (number == NULL)
8405dfecf96Smrg	    LispDestroy("EVAL: the variable %s is unbound", STROBJ(place));
8415dfecf96Smrg    }
8425dfecf96Smrg    else
8435dfecf96Smrg	number = EVAL(place);
8445dfecf96Smrg
8455dfecf96Smrg    if (delta != UNSPEC) {
8465dfecf96Smrg	LispObj *operand;
8475dfecf96Smrg
8485dfecf96Smrg	operand = EVAL(delta);
8495dfecf96Smrg	set_number_object(&num, number);
8505dfecf96Smrg	add_number_object(&num, operand);
8515dfecf96Smrg	number = make_number_object(&num);
8525dfecf96Smrg    }
8535dfecf96Smrg    else {
8545dfecf96Smrg	num.complex = 0;
8555dfecf96Smrg	num.real.type = N_FIXNUM;
8565dfecf96Smrg	num.real.data.fixnum = 1;
8575dfecf96Smrg	add_number_object(&num, number);
8585dfecf96Smrg	number = make_number_object(&num);
8595dfecf96Smrg    }
8605dfecf96Smrg
8615dfecf96Smrg    if (SYMBOLP(place)) {
8625dfecf96Smrg	CHECK_CONSTANT(place);
8635dfecf96Smrg	LispSetVar(place, number);
8645dfecf96Smrg    }
8655dfecf96Smrg    else {
8665dfecf96Smrg	GC_ENTER();
8675dfecf96Smrg
8685dfecf96Smrg	GC_PROTECT(number);
8695dfecf96Smrg	(void)APPLY2(Osetf, place, number);
8705dfecf96Smrg	GC_LEAVE();
8715dfecf96Smrg    }
8725dfecf96Smrg
8735dfecf96Smrg    return (number);
8745dfecf96Smrg}
8755dfecf96Smrg
8765dfecf96SmrgLispObj *
8775dfecf96SmrgLisp_Integerp(LispBuiltin *builtin)
8785dfecf96Smrg/*
8795dfecf96Smrg integerp object
8805dfecf96Smrg */
8815dfecf96Smrg{
8825dfecf96Smrg    LispObj *object;
8835dfecf96Smrg
8845dfecf96Smrg    object = ARGUMENT(0);
8855dfecf96Smrg
8865dfecf96Smrg    return (INTEGERP(object) ? T : NIL);
8875dfecf96Smrg}
8885dfecf96Smrg
8895dfecf96SmrgLispObj *
8905dfecf96SmrgLisp_Isqrt(LispBuiltin *builtin)
8915dfecf96Smrg/*
8925dfecf96Smrg isqrt natural
8935dfecf96Smrg */
8945dfecf96Smrg{
8955dfecf96Smrg    LispObj *natural, *result;
8965dfecf96Smrg
8975dfecf96Smrg    natural = ARGUMENT(0);
8985dfecf96Smrg
8995dfecf96Smrg    if (cmp_object_object(natural, obj_zero, 1) < 0)
9005dfecf96Smrg	goto not_a_natural_number;
9015dfecf96Smrg
9025dfecf96Smrg    switch (OBJECT_TYPE(natural)) {
9035dfecf96Smrg	case LispFixnum_t:
9045dfecf96Smrg	    result = FIXNUM((long)floor(sqrt(FIXNUM_VALUE(natural))));
9055dfecf96Smrg	    break;
9065dfecf96Smrg	case LispInteger_t:
9075dfecf96Smrg	    result = INTEGER((long)floor(sqrt(INT_VALUE(natural))));
9085dfecf96Smrg	    break;
9095dfecf96Smrg	case LispBignum_t: {
9105dfecf96Smrg	    mpi *bigi;
9115dfecf96Smrg
9125dfecf96Smrg	    bigi = XALLOC(mpi);
9135dfecf96Smrg	    mpi_init(bigi);
9145dfecf96Smrg	    mpi_sqrt(bigi, OBI(natural));
9155dfecf96Smrg	    if (mpi_fiti(bigi)) {
9165dfecf96Smrg		result = INTEGER(mpi_geti(bigi));
9175dfecf96Smrg		mpi_clear(bigi);
9185dfecf96Smrg		XFREE(bigi);
9195dfecf96Smrg	    }
9205dfecf96Smrg	    else
9215dfecf96Smrg		result = BIGNUM(bigi);
9225dfecf96Smrg	}   break;
9235dfecf96Smrg	default:
9245dfecf96Smrg	    goto not_a_natural_number;
9255dfecf96Smrg    }
9265dfecf96Smrg
9275dfecf96Smrg    return (result);
9285dfecf96Smrg
9295dfecf96Smrgnot_a_natural_number:
9305dfecf96Smrg    LispDestroy("%s: %s is not a natural number",
9315dfecf96Smrg		STRFUN(builtin), STROBJ(natural));
9325dfecf96Smrg    /*NOTREACHED*/
9335dfecf96Smrg    return (NIL);
9345dfecf96Smrg}
9355dfecf96Smrg
9365dfecf96SmrgLispObj *
9375dfecf96SmrgLisp_Lcm(LispBuiltin *builtin)
9385dfecf96Smrg/*
9395dfecf96Smrg lcm &rest integers
9405dfecf96Smrg */
9415dfecf96Smrg{
9425dfecf96Smrg    n_real real, gcd;
9435dfecf96Smrg    LispObj *integers, *operand;
9445dfecf96Smrg
9455dfecf96Smrg    integers = ARGUMENT(0);
9465dfecf96Smrg
9475dfecf96Smrg    if (!CONSP(integers))
9485dfecf96Smrg	return (FIXNUM(1));
9495dfecf96Smrg
9505dfecf96Smrg    operand = CAR(integers);
9515dfecf96Smrg
9525dfecf96Smrg    CHECK_INTEGER(operand);
9535dfecf96Smrg    set_real_object(&real, operand);
9545dfecf96Smrg    integers = CDR(integers);
9555dfecf96Smrg
9565dfecf96Smrg    gcd.type = N_FIXNUM;
9575dfecf96Smrg    gcd.data.fixnum = 0;
9585dfecf96Smrg
9595dfecf96Smrg    for (; CONSP(integers); integers = CDR(integers)) {
9605dfecf96Smrg	operand = CAR(integers);
9615dfecf96Smrg
9625dfecf96Smrg	if (real.type == N_FIXNUM && real.data.fixnum == 0)
9635dfecf96Smrg	    break;
9645dfecf96Smrg
9655dfecf96Smrg	/* calculate gcd before changing integer */
9665dfecf96Smrg	clear_real(&gcd);
9675dfecf96Smrg	set_real_real(&gcd, &real);
9685dfecf96Smrg	gcd_real_object(&gcd, operand);
9695dfecf96Smrg
9705dfecf96Smrg	/* calculate lcm */
9715dfecf96Smrg	mul_real_object(&real, operand);
9725dfecf96Smrg	div_real_real(&real, &gcd);
9735dfecf96Smrg    }
9745dfecf96Smrg    clear_real(&gcd);
9755dfecf96Smrg    abs_real(&real);
9765dfecf96Smrg
9775dfecf96Smrg    return (make_real_object(&real));
9785dfecf96Smrg}
9795dfecf96Smrg
9805dfecf96SmrgLispObj *
9815dfecf96SmrgLisp_Logand(LispBuiltin *builtin)
9825dfecf96Smrg/*
9835dfecf96Smrg logand &rest integers
9845dfecf96Smrg */
9855dfecf96Smrg{
9865dfecf96Smrg    n_real real;
9875dfecf96Smrg
9885dfecf96Smrg    LispObj *integers;
9895dfecf96Smrg
9905dfecf96Smrg    integers = ARGUMENT(0);
9915dfecf96Smrg
9925dfecf96Smrg    real.type = N_FIXNUM;
9935dfecf96Smrg    real.data.fixnum = -1;
9945dfecf96Smrg
9955dfecf96Smrg    for (; CONSP(integers); integers = CDR(integers))
9965dfecf96Smrg	and_real_object(&real, CAR(integers));
9975dfecf96Smrg
9985dfecf96Smrg    return (make_real_object(&real));
9995dfecf96Smrg}
10005dfecf96Smrg
10015dfecf96SmrgLispObj *
10025dfecf96SmrgLisp_Logeqv(LispBuiltin *builtin)
10035dfecf96Smrg/*
10045dfecf96Smrg logeqv &rest integers
10055dfecf96Smrg */
10065dfecf96Smrg{
10075dfecf96Smrg    n_real real;
10085dfecf96Smrg
10095dfecf96Smrg    LispObj *integers;
10105dfecf96Smrg
10115dfecf96Smrg    integers = ARGUMENT(0);
10125dfecf96Smrg
10135dfecf96Smrg    real.type = N_FIXNUM;
10145dfecf96Smrg    real.data.fixnum = -1;
10155dfecf96Smrg
10165dfecf96Smrg    for (; CONSP(integers); integers = CDR(integers))
10175dfecf96Smrg	eqv_real_object(&real, CAR(integers));
10185dfecf96Smrg
10195dfecf96Smrg    return (make_real_object(&real));
10205dfecf96Smrg}
10215dfecf96Smrg
10225dfecf96SmrgLispObj *
10235dfecf96SmrgLisp_Logior(LispBuiltin *builtin)
10245dfecf96Smrg/*
10255dfecf96Smrg logior &rest integers
10265dfecf96Smrg */
10275dfecf96Smrg{
10285dfecf96Smrg    n_real real;
10295dfecf96Smrg
10305dfecf96Smrg    LispObj *integers;
10315dfecf96Smrg
10325dfecf96Smrg    integers = ARGUMENT(0);
10335dfecf96Smrg
10345dfecf96Smrg    real.type = N_FIXNUM;
10355dfecf96Smrg    real.data.fixnum = 0;
10365dfecf96Smrg
10375dfecf96Smrg    for (; CONSP(integers); integers = CDR(integers))
10385dfecf96Smrg	ior_real_object(&real, CAR(integers));
10395dfecf96Smrg
10405dfecf96Smrg    return (make_real_object(&real));
10415dfecf96Smrg}
10425dfecf96Smrg
10435dfecf96SmrgLispObj *
10445dfecf96SmrgLisp_Lognot(LispBuiltin *builtin)
10455dfecf96Smrg/*
10465dfecf96Smrg lognot integer
10475dfecf96Smrg */
10485dfecf96Smrg{
10495dfecf96Smrg    n_real real;
10505dfecf96Smrg
10515dfecf96Smrg    LispObj *integer;
10525dfecf96Smrg
10535dfecf96Smrg    integer = ARGUMENT(0);
10545dfecf96Smrg
10555dfecf96Smrg    CHECK_INTEGER(integer);
10565dfecf96Smrg
10575dfecf96Smrg    set_real_object(&real, integer);
10585dfecf96Smrg    not_real(&real);
10595dfecf96Smrg
10605dfecf96Smrg    return (make_real_object(&real));
10615dfecf96Smrg}
10625dfecf96Smrg
10635dfecf96SmrgLispObj *
10645dfecf96SmrgLisp_Logxor(LispBuiltin *builtin)
10655dfecf96Smrg/*
10665dfecf96Smrg logxor &rest integers
10675dfecf96Smrg */
10685dfecf96Smrg{
10695dfecf96Smrg    n_real real;
10705dfecf96Smrg
10715dfecf96Smrg    LispObj *integers;
10725dfecf96Smrg
10735dfecf96Smrg    integers = ARGUMENT(0);
10745dfecf96Smrg
10755dfecf96Smrg    real.type = N_FIXNUM;
10765dfecf96Smrg    real.data.fixnum = 0;
10775dfecf96Smrg
10785dfecf96Smrg    for (; CONSP(integers); integers = CDR(integers))
10795dfecf96Smrg	xor_real_object(&real, CAR(integers));
10805dfecf96Smrg
10815dfecf96Smrg    return (make_real_object(&real));
10825dfecf96Smrg}
10835dfecf96Smrg
10845dfecf96SmrgLispObj *
10855dfecf96SmrgLisp_Minusp(LispBuiltin *builtin)
10865dfecf96Smrg/*
10875dfecf96Smrg minusp number
10885dfecf96Smrg */
10895dfecf96Smrg{
10905dfecf96Smrg    LispObj *number;
10915dfecf96Smrg
10925dfecf96Smrg    number = ARGUMENT(0);
10935dfecf96Smrg
10945dfecf96Smrg    CHECK_REAL(number);
10955dfecf96Smrg
10965dfecf96Smrg    return (cmp_real_object(&zero, number) > 0 ? T : NIL);
10975dfecf96Smrg}
10985dfecf96Smrg
10995dfecf96SmrgLispObj *
11005dfecf96SmrgLisp_Mod(LispBuiltin *builtin)
11015dfecf96Smrg/*
11025dfecf96Smrg mod number divisor
11035dfecf96Smrg */
11045dfecf96Smrg{
11055dfecf96Smrg    LispObj *result;
11065dfecf96Smrg
11075dfecf96Smrg    LispObj *number, *divisor;
11085dfecf96Smrg
11095dfecf96Smrg    divisor = ARGUMENT(1);
11105dfecf96Smrg    number = ARGUMENT(0);
11115dfecf96Smrg
11125dfecf96Smrg    if (INTEGERP(number) && INTEGERP(divisor)) {
11135dfecf96Smrg	n_real real;
11145dfecf96Smrg
11155dfecf96Smrg	set_real_object(&real, number);
11165dfecf96Smrg	mod_real_object(&real, divisor);
11175dfecf96Smrg	result = make_real_object(&real);
11185dfecf96Smrg    }
11195dfecf96Smrg    else {
11205dfecf96Smrg	n_number num;
11215dfecf96Smrg
11225dfecf96Smrg	set_number_object(&num, number);
11235dfecf96Smrg	divide_number_object(&num, divisor, NDIVIDE_FLOOR, 0);
11245dfecf96Smrg	result = make_real_object(&(num.imag));
11255dfecf96Smrg	clear_real(&(num.real));
11265dfecf96Smrg    }
11275dfecf96Smrg
11285dfecf96Smrg    return (result);
11295dfecf96Smrg}
11305dfecf96Smrg
11315dfecf96SmrgLispObj *
11325dfecf96SmrgLisp_Numberp(LispBuiltin *builtin)
11335dfecf96Smrg/*
11345dfecf96Smrg numberp object
11355dfecf96Smrg */
11365dfecf96Smrg{
11375dfecf96Smrg    LispObj *object;
11385dfecf96Smrg
11395dfecf96Smrg    object = ARGUMENT(0);
11405dfecf96Smrg
11415dfecf96Smrg    return (NUMBERP(object) ? T : NIL);
11425dfecf96Smrg}
11435dfecf96Smrg
11445dfecf96SmrgLispObj *
11455dfecf96SmrgLisp_Numerator(LispBuiltin *builtin)
11465dfecf96Smrg/*
11475dfecf96Smrg numerator rational
11485dfecf96Smrg */
11495dfecf96Smrg{
11505dfecf96Smrg    LispObj *result, *rational;
11515dfecf96Smrg
11525dfecf96Smrg    rational = ARGUMENT(0);
11535dfecf96Smrg
11545dfecf96Smrg    switch (OBJECT_TYPE(rational)) {
11555dfecf96Smrg	case LispFixnum_t:
11565dfecf96Smrg	case LispInteger_t:
11575dfecf96Smrg	case LispBignum_t:
11585dfecf96Smrg	    result = rational;
11595dfecf96Smrg	    break;
11605dfecf96Smrg	case LispRatio_t:
11615dfecf96Smrg	    result = INTEGER(OFRN(rational));
11625dfecf96Smrg	    break;
11635dfecf96Smrg	case LispBigratio_t:
11645dfecf96Smrg	    if (mpi_fiti(OBRN(rational)))
11655dfecf96Smrg		result = INTEGER(mpi_geti(OBRN(rational)));
11665dfecf96Smrg	    else {
11675dfecf96Smrg		mpi *num = XALLOC(mpi);
11685dfecf96Smrg
11695dfecf96Smrg		mpi_init(num);
11705dfecf96Smrg		mpi_set(num, OBRN(rational));
11715dfecf96Smrg		result = BIGNUM(num);
11725dfecf96Smrg	    }
11735dfecf96Smrg	    break;
11745dfecf96Smrg	default:
11755dfecf96Smrg	    LispDestroy("%s: %s is not a rational number",
11765dfecf96Smrg			STRFUN(builtin), STROBJ(rational));
11775dfecf96Smrg	    /*NOTREACHED*/
11785dfecf96Smrg	    result = NIL;
11795dfecf96Smrg    }
11805dfecf96Smrg
11815dfecf96Smrg    return (result);
11825dfecf96Smrg}
11835dfecf96Smrg
11845dfecf96SmrgLispObj *
11855dfecf96SmrgLisp_Oddp(LispBuiltin *builtin)
11865dfecf96Smrg/*
11875dfecf96Smrg oddp integer
11885dfecf96Smrg */
11895dfecf96Smrg{
11905dfecf96Smrg    LispObj *result, *integer;
11915dfecf96Smrg
11925dfecf96Smrg    integer = ARGUMENT(0);
11935dfecf96Smrg
11945dfecf96Smrg    switch (OBJECT_TYPE(integer)) {
11955dfecf96Smrg	case LispFixnum_t:
11965dfecf96Smrg	    result = FIXNUM_VALUE(integer) % 2 ? T : NIL;
11975dfecf96Smrg	    break;
11985dfecf96Smrg	case LispInteger_t:
11995dfecf96Smrg	    result = INT_VALUE(integer) % 2 ? T : NIL;
12005dfecf96Smrg	    break;
12015dfecf96Smrg	case LispBignum_t:
12025dfecf96Smrg	    result = mpi_remi(OBI(integer), 2) ? T : NIL;
12035dfecf96Smrg	    break;
12045dfecf96Smrg	default:
12055dfecf96Smrg	    fatal_builtin_object_error(builtin, integer, NOT_AN_INTEGER);
12065dfecf96Smrg	    /*NOTREACHED*/
12075dfecf96Smrg	    result = NIL;
12085dfecf96Smrg    }
12095dfecf96Smrg
12105dfecf96Smrg    return (result);
12115dfecf96Smrg}
12125dfecf96Smrg
12135dfecf96SmrgLispObj *
12145dfecf96SmrgLisp_Plusp(LispBuiltin *builtin)
12155dfecf96Smrg/*
12165dfecf96Smrg plusp number
12175dfecf96Smrg */
12185dfecf96Smrg{
12195dfecf96Smrg    LispObj *number;
12205dfecf96Smrg
12215dfecf96Smrg    number = ARGUMENT(0);
12225dfecf96Smrg
12235dfecf96Smrg    CHECK_REAL(number);
12245dfecf96Smrg
12255dfecf96Smrg    return (cmp_real_object(&zero, number) < 0 ? T : NIL);
12265dfecf96Smrg}
12275dfecf96Smrg
12285dfecf96SmrgLispObj *
12295dfecf96SmrgLisp_Rational(LispBuiltin *builtin)
12305dfecf96Smrg/*
12315dfecf96Smrg rational number
12325dfecf96Smrg */
12335dfecf96Smrg{
12345dfecf96Smrg    LispObj *number;
12355dfecf96Smrg
12365dfecf96Smrg    number = ARGUMENT(0);
12375dfecf96Smrg
12385dfecf96Smrg    if (DFLOATP(number)) {
12395dfecf96Smrg	double numerator = ODF(number);
12405dfecf96Smrg
12415dfecf96Smrg	if ((long)numerator == numerator)
12425dfecf96Smrg	    number = INTEGER(numerator);
12435dfecf96Smrg	else {
12445dfecf96Smrg	    n_real real;
12455dfecf96Smrg	    mpr *bigr = XALLOC(mpr);
12465dfecf96Smrg
12475dfecf96Smrg	    mpr_init(bigr);
12485dfecf96Smrg	    mpr_setd(bigr, numerator);
12495dfecf96Smrg	    real.type = N_BIGRATIO;
12505dfecf96Smrg	    real.data.bigratio = bigr;
12515dfecf96Smrg	    rbr_canonicalize(&real);
12525dfecf96Smrg	    number = make_real_object(&real);
12535dfecf96Smrg	}
12545dfecf96Smrg    }
12555dfecf96Smrg    else {
12565dfecf96Smrg	CHECK_REAL(number);
12575dfecf96Smrg    }
12585dfecf96Smrg
12595dfecf96Smrg    return (number);
12605dfecf96Smrg}
12615dfecf96Smrg
12625dfecf96SmrgLispObj *
12635dfecf96SmrgLisp_Rationalp(LispBuiltin *builtin)
12645dfecf96Smrg/*
12655dfecf96Smrg rationalp object
12665dfecf96Smrg */
12675dfecf96Smrg{
12685dfecf96Smrg    LispObj *object;
12695dfecf96Smrg
12705dfecf96Smrg    object = ARGUMENT(0);
12715dfecf96Smrg
12725dfecf96Smrg    return (RATIONALP(object) ? T : NIL);
12735dfecf96Smrg}
12745dfecf96Smrg
12755dfecf96SmrgLispObj *
12765dfecf96SmrgLisp_Realpart(LispBuiltin *builtin)
12775dfecf96Smrg/*
12785dfecf96Smrg realpart number
12795dfecf96Smrg */
12805dfecf96Smrg{
12815dfecf96Smrg    LispObj *number;
12825dfecf96Smrg
12835dfecf96Smrg    number = ARGUMENT(0);
12845dfecf96Smrg
12855dfecf96Smrg    if (COMPLEXP(number))
12865dfecf96Smrg	return (OCXR(number));
12875dfecf96Smrg    else {
12885dfecf96Smrg	CHECK_REAL(number);
12895dfecf96Smrg    }
12905dfecf96Smrg
12915dfecf96Smrg    return (number);
12925dfecf96Smrg}
12935dfecf96Smrg
12945dfecf96SmrgLispObj *
12955dfecf96SmrgLisp_Rem(LispBuiltin *builtin)
12965dfecf96Smrg/*
12975dfecf96Smrg rem number divisor
12985dfecf96Smrg */
12995dfecf96Smrg{
13005dfecf96Smrg    LispObj *result;
13015dfecf96Smrg
13025dfecf96Smrg    LispObj *number, *divisor;
13035dfecf96Smrg
13045dfecf96Smrg    divisor = ARGUMENT(1);
13055dfecf96Smrg    number = ARGUMENT(0);
13065dfecf96Smrg
13075dfecf96Smrg    if (INTEGERP(number) && INTEGERP(divisor)) {
13085dfecf96Smrg	n_real real;
13095dfecf96Smrg
13105dfecf96Smrg	set_real_object(&real, number);
13115dfecf96Smrg	rem_real_object(&real, divisor);
13125dfecf96Smrg	result = make_real_object(&real);
13135dfecf96Smrg    }
13145dfecf96Smrg    else {
13155dfecf96Smrg	n_number num;
13165dfecf96Smrg
13175dfecf96Smrg	set_number_object(&num, number);
13185dfecf96Smrg	divide_number_object(&num, divisor, NDIVIDE_TRUNC, 0);
13195dfecf96Smrg	result = make_real_object(&(num.imag));
13205dfecf96Smrg	clear_real(&(num.real));
13215dfecf96Smrg    }
13225dfecf96Smrg
13235dfecf96Smrg    return (result);
13245dfecf96Smrg}
13255dfecf96Smrg
13265dfecf96SmrgLispObj *
13275dfecf96SmrgLisp_Sqrt(LispBuiltin *builtin)
13285dfecf96Smrg/*
13295dfecf96Smrg sqrt number
13305dfecf96Smrg */
13315dfecf96Smrg{
13325dfecf96Smrg    n_number num;
13335dfecf96Smrg    LispObj *number;
13345dfecf96Smrg
13355dfecf96Smrg    number = ARGUMENT(0);
13365dfecf96Smrg
13375dfecf96Smrg    set_number_object(&num, number);
13385dfecf96Smrg    sqrt_number(&num);
13395dfecf96Smrg
13405dfecf96Smrg    return (make_number_object(&num));
13415dfecf96Smrg}
13425dfecf96Smrg
13435dfecf96SmrgLispObj *
13445dfecf96SmrgLisp_Zerop(LispBuiltin *builtin)
13455dfecf96Smrg/*
13465dfecf96Smrg zerop number
13475dfecf96Smrg */
13485dfecf96Smrg{
13495dfecf96Smrg    LispObj *result, *number;
13505dfecf96Smrg
13515dfecf96Smrg    number = ARGUMENT(0);
13525dfecf96Smrg
13535dfecf96Smrg    switch (OBJECT_TYPE(number)) {
13545dfecf96Smrg	case LispFixnum_t:
13555dfecf96Smrg	case LispInteger_t:
13565dfecf96Smrg	case LispBignum_t:
13575dfecf96Smrg	case LispDFloat_t:
13585dfecf96Smrg	case LispRatio_t:
13595dfecf96Smrg	case LispBigratio_t:
13605dfecf96Smrg	    result = cmp_real_object(&zero, number) == 0 ? T : NIL;
13615dfecf96Smrg	    break;
13625dfecf96Smrg	case LispComplex_t:
13635dfecf96Smrg	    result = cmp_real_object(&zero, OCXR(number)) == 0 &&
13645dfecf96Smrg		     cmp_real_object(&zero, OCXI(number)) == 0 ? T : NIL;
13655dfecf96Smrg	    break;
13665dfecf96Smrg	default:
13675dfecf96Smrg	    fatal_builtin_object_error(builtin, number, NOT_A_NUMBER);
13685dfecf96Smrg	    /*NOTREACHED*/
13695dfecf96Smrg	    result = NIL;
13705dfecf96Smrg    }
13715dfecf96Smrg
13725dfecf96Smrg    return (result);
13735dfecf96Smrg}
13745dfecf96Smrg
13755dfecf96Smrgstatic LispObj *
13765dfecf96SmrgLispDivide(LispBuiltin *builtin, int fun, int flo)
13775dfecf96Smrg{
13785dfecf96Smrg    n_number num;
13795dfecf96Smrg    LispObj *number, *divisor;
13805dfecf96Smrg
13815dfecf96Smrg    divisor = ARGUMENT(1);
13825dfecf96Smrg    number = ARGUMENT(0);
13835dfecf96Smrg
13845dfecf96Smrg    RETURN_COUNT = 1;
13855dfecf96Smrg
13865dfecf96Smrg    if (cmp_real_object(&zero, number) == 0) {
13875dfecf96Smrg	if (divisor != NIL) {
13885dfecf96Smrg	    CHECK_REAL(divisor);
13895dfecf96Smrg	}
13905dfecf96Smrg
13915dfecf96Smrg	return (RETURN(0) = obj_zero);
13925dfecf96Smrg    }
13935dfecf96Smrg
13945dfecf96Smrg    if (divisor == UNSPEC)
13955dfecf96Smrg	divisor = obj_one;
13965dfecf96Smrg
13975dfecf96Smrg    set_number_object(&num, number);
13985dfecf96Smrg    if (num.complex)
13995dfecf96Smrg	fatal_builtin_object_error(builtin, divisor, NOT_A_REAL_NUMBER);
14005dfecf96Smrg
14015dfecf96Smrg    divide_number_object(&num, divisor, fun, flo);
14025dfecf96Smrg    RETURN(0) = make_real_object(&(num.imag));
14035dfecf96Smrg
14045dfecf96Smrg    return (make_real_object(&(num.real)));
14055dfecf96Smrg}
14065dfecf96Smrg
14075dfecf96SmrgLispObj *
14085dfecf96SmrgLisp_Ceiling(LispBuiltin *builtin)
14095dfecf96Smrg/*
14105dfecf96Smrg ceiling number &optional divisor
14115dfecf96Smrg */
14125dfecf96Smrg{
14135dfecf96Smrg    return (LispDivide(builtin, NDIVIDE_CEIL, 0));
14145dfecf96Smrg}
14155dfecf96Smrg
14165dfecf96SmrgLispObj *
14175dfecf96SmrgLisp_Fceiling(LispBuiltin *builtin)
14185dfecf96Smrg/*
14195dfecf96Smrg fceiling number &optional divisor
14205dfecf96Smrg */
14215dfecf96Smrg{
14225dfecf96Smrg    return (LispDivide(builtin, NDIVIDE_CEIL, 1));
14235dfecf96Smrg}
14245dfecf96Smrg
14255dfecf96SmrgLispObj *
14265dfecf96SmrgLisp_Floor(LispBuiltin *builtin)
14275dfecf96Smrg/*
14285dfecf96Smrg floor number &optional divisor
14295dfecf96Smrg */
14305dfecf96Smrg{
14315dfecf96Smrg    return (LispDivide(builtin, NDIVIDE_FLOOR, 0));
14325dfecf96Smrg}
14335dfecf96Smrg
14345dfecf96SmrgLispObj *
14355dfecf96SmrgLisp_Ffloor(LispBuiltin *builtin)
14365dfecf96Smrg/*
14375dfecf96Smrg ffloor number &optional divisor
14385dfecf96Smrg */
14395dfecf96Smrg{
14405dfecf96Smrg    return (LispDivide(builtin, NDIVIDE_FLOOR, 1));
14415dfecf96Smrg}
14425dfecf96Smrg
14435dfecf96SmrgLispObj *
14445dfecf96SmrgLisp_Round(LispBuiltin *builtin)
14455dfecf96Smrg/*
14465dfecf96Smrg round number &optional divisor
14475dfecf96Smrg */
14485dfecf96Smrg{
14495dfecf96Smrg    return (LispDivide(builtin, NDIVIDE_ROUND, 0));
14505dfecf96Smrg}
14515dfecf96Smrg
14525dfecf96SmrgLispObj *
14535dfecf96SmrgLisp_Fround(LispBuiltin *builtin)
14545dfecf96Smrg/*
14555dfecf96Smrg fround number &optional divisor
14565dfecf96Smrg */
14575dfecf96Smrg{
14585dfecf96Smrg    return (LispDivide(builtin, NDIVIDE_ROUND, 1));
14595dfecf96Smrg}
14605dfecf96Smrg
14615dfecf96SmrgLispObj *
14625dfecf96SmrgLisp_Truncate(LispBuiltin *builtin)
14635dfecf96Smrg/*
14645dfecf96Smrg truncate number &optional divisor
14655dfecf96Smrg */
14665dfecf96Smrg{
14675dfecf96Smrg    return (LispDivide(builtin, NDIVIDE_TRUNC, 0));
14685dfecf96Smrg}
14695dfecf96Smrg
14705dfecf96SmrgLispObj *
14715dfecf96SmrgLisp_Ftruncate(LispBuiltin *builtin)
14725dfecf96Smrg/*
14735dfecf96Smrg ftruncate number &optional divisor
14745dfecf96Smrg */
14755dfecf96Smrg{
14765dfecf96Smrg    return (LispDivide(builtin, NDIVIDE_TRUNC, 1));
14775dfecf96Smrg}
1478