1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
/*
* Copyright © 1988-2004 Keith Packard and Bart Massey.
* All Rights Reserved. See the file COPYING in this directory
* for licensing information.
*/
/*
* math.c
*
* provide builtin functions for the Math namespace
*/
#include <ctype.h>
#include <strings.h>
#include <time.h>
#include "builtin.h"
NamespacePtr MathNamespace;
void
import_Math_namespace()
{
ENTER ();
static const struct fbuiltin_1 funcs_1[] = {
{ do_Math_popcount, "popcount", "i", "i", "\n"
" int popcount (int i)\n"
"\n"
" Return the number of '1' bits in 'i'.\n" },
{ do_Math_factorial, "factorial", "i", "i", "\n"
" int factorial (int i)\n"
"\n"
" Return the factorial of 'i'.\n" },
{ 0 }
};
static const struct fbuiltin_2 funcs_2[] = {
{ do_Math_assignpow, "assign_pow", "n", "*Ri", "\n"
" real assign_pow (*real a, int b)\n"
"\n"
" Return *a ** b, also storing that result back in *a.\n" },
{ do_Math_pow, "pow", "n", "Ri", "\n"
" real pow (real a, int b)\n"
"\n"
" Return a ** b.\n" },
{ 0 }
};
MathNamespace = BuiltinNamespace (/*parent*/ 0, "Math")->namespace.namespace;
BuiltinFuncs1 (&MathNamespace, funcs_1);
BuiltinFuncs2 (&MathNamespace, funcs_2);
EXIT ();
}
Value
do_Math_pow (Value a, Value b)
{
ENTER ();
RETURN (Pow (a, b));
}
Value
do_Math_assignpow (Value a, Value b)
{
ENTER ();
Value ret;
ret = Pow (RefValueGet(a), b);
RefValueSet (a, ret);
RETURN (ret);
}
static unsigned count_bits (unsigned n) {
unsigned c3 = 0x0f0f0f0f;
unsigned c2 = c3 ^ (c3 << 2); /* c2 == 0x33333333 */
unsigned c1 = c2 ^ (c2 << 1); /* c1 == 0x55555555 */
unsigned left = (n >> 1) & c1;
n = left + (n & c1);
left = (n >> 2) & c2;
n = left + (n & c2);
left = (n >> 4) & c3;
n = left + (n & c3);
n += (n >> 8);
n += (n >> 16);
return (n & 0xff);
}
Value
Popcount (Value av)
{
ENTER ();
Natural *i;
Value ret;
digit *d;
int n;
unsigned part;
if (!Integralp (ValueTag(av)))
{
RaiseStandardException (exception_invalid_argument, 3,
NewStrString ("Math::popcount: not an integer"),
av, Void);
RETURN (Void);
}
if (Negativep (av))
{
RaiseStandardException (exception_invalid_argument, 3,
NewStrString ("Math::popcount: negative argument"),
av, Void);
RETURN (Void);
}
switch (ValueTag(av)) {
case rep_int:
ret = NewInt (count_bits (ValueInt(av)));
break;
case rep_integer:
i = IntegerMag (av);
n = i->length;
d = NaturalDigits(i);
part = 0;
ret = Zero;
while (n--)
{
if (part >= MAX_NICKLE_INT - 32)
{
ret = Plus (ret, NewInt (part));
part = 0;
if (aborting)
break;
}
part += count_bits (*d++);
}
if (ret == Zero)
ret = NewInt (part);
else
ret = Plus (ret, NewInt (part));
break;
default:
RaiseStandardException (exception_invalid_argument, 3,
NewStrString ("Math::popcount: not an integer"),
av, Void);
RETURN (Void);
}
RETURN (ret);
}
Value
do_Math_popcount(Value v) {
ENTER ();
RETURN (Popcount (v));
}
Value
do_Math_factorial(Value v) {
ENTER ();
RETURN (Factorial (v));
}
|