/* $Header$ */ /* * 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 #include #include #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" }, { 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 (RefValue (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, "Math::popcount: not an integer", 2, av, Void); RETURN (Void); } if (Negativep (av)) { RaiseStandardException (exception_invalid_argument, "Math::popcount: negative argument", 2, 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, "Math::popcount: not an integer", 2, av, Void); RETURN (Void); } RETURN (ret); } Value do_Math_popcount(Value v) { ENTER (); RETURN (Popcount (v)); }