############################################################################# ## ## This file is part of GAP, a system for computational discrete algebra. ## This file's authors include Steve Linton, Laurent Bartholdi. ## ## Copyright of GAP belongs to its developers, whose names are too numerous ## to list here. Please refer to the COPYRIGHT file for details. ## ## SPDX-License-Identifier: GPL-2.0-or-later ## ## This file deals with floats, and sets up a default interface, within GAP, ## to deal with floateans. ##
############################################################################# ## a category describing the "fields" of floating-point numbers ## we must put it here, because float.gd is read too early for "IsAlgebra" ## this is used mainly to create polynomials
DeclareCategory("IsFloatPseudoField", IsAlgebra);
## these things should also be in float.gd, but require IsRationalFunction
DeclareCategory("IsFloatRationalFunction", IsRationalFunction);
DeclareSynonym("IsFloatPolynomial", IsFloatRationalFunction and IsPolynomial);
DeclareSynonym("IsFloatUnivariatePolynomial", IsFloatRationalFunction and IsUnivariatePolynomial);
DeclareOperation("Value", [IsFloatRationalFunction,IsFloat]);
DeclareOperation("ValueInterval", [IsFloatRationalFunction,IsFloat]); #############################################################################
MAX_FLOAT_LITERAL_CACHE_SIZE := 0; # cache all float literals by default.
FLOAT_DEFAULT_REP := fail;
FLOAT_STRING := fail;
FLOAT_PSEUDOFIELD := fail;
FLOAT := fail; # holds the constants if IsHPCGAP then
BindGlobal("EAGER_FLOAT_LITERAL_CONVERTERS", AtomicRecord()); else
BindGlobal("EAGER_FLOAT_LITERAL_CONVERTERS", rec()); fi;
InstallGlobalFunction(SetFloats, function(arg)
local i, r, prec, install;
r := fail;
prec := fail;
install := true; for i in [1..Length(arg)] do if IsRecord(arg[i]) and i=1then
r := arg[1]; elif IsBool(arg[i]) then
install := arg[i]; elif IsPosInt(arg[i]) then
prec := arg[i]; else
r := fail;
break; fi;
od; while r=fail do
Error("SetFloats requires a record, and optional precision(posint) and install(bool), not ",arg);
od;
if install then if IsBound(r.filter) then
FLOAT_DEFAULT_REP := r.filter; fi; if IsBound(r.constants) then
FLOAT := r.constants; fi; if IsBound(r.creator) then
FLOAT_STRING := r.creator; fi; if IsBound(r.field) then
FLOAT_PSEUDOFIELD := r.field; fi; fi;
if IsBound(r.creator) and IsBound(r.eager) then
EAGER_FLOAT_LITERAL_CONVERTERS.([r.eager]) := r.creator; fi;
FLUSH_FLOAT_LITERAL_CACHE();
if prec<>fail then
r.constants.MANT_DIG := prec; if IsBound(r.constants.recompute) then
r.constants.recompute(r.constants,prec); fi; fi; end);
################################################################ # creators ################################################################
InstallGlobalFunction(Float, function(obj) if not IsString(obj) and IsList(obj) then
return List(obj,Float); else
return NewFloat(FLOAT_DEFAULT_REP,obj); fi; end);
BindGlobal("INSTALLFLOATCONSTRUCTORS", function(arg)
local filter, float, constants, i;
if IsRecord(arg[1]) then
filter := arg[1].filter; else
filter := arg[1]; fi;
# we intentionally provide no default method for converting rationals, as # implementing this accurately depends a lot on the specific floatean type
InstallMethod(MakeFloat, [filter,filter], -1, function(filter,obj)
return obj; # floats are immutable, no harm to return the same one end);
if IsRecord(arg[1]) and IsBound(arg[1].constants) then
float := arg[1].constants;
constants := [["E","2.7182818284590452354"],
["LOG2E", "1.4426950408889634074"],
["LOG10E", "0.43429448190325182765"],
["LN2", "0.69314718055994530942"],
["LN10", "2.30258509299404568402"],
["PI", "3.14159265358979323846"],
["2PI", "6.28318530717958647692"],
["PI_2", "1.57079632679489661923"],
["PI_4", "0.78539816339744830962"],
["1_PI", "0.31830988618379067154"],
["2_PI", "0.63661977236758134308"],
["2_SQRTPI", "1.12837916709551257390"],
["SQRT2", "1.41421356237309504880"],
["SQRT1_2", "0.70710678118654752440"]]; for i in constants do if not IsBound(float.(i[1])) then
float.(i[1]) := NewFloat(filter,i[2]); fi;
od; fi; end); ################################################################ # inner converter from string to float ################################################################
BindGlobal("CONVERT_FLOAT_LITERAL", function(s)
local i,f,s1;
f:= FLOAT_STRING(s); if f<>fail then return f; fi;
s1 := ""; for i in [1..LENGTH(s)] do if s[i] in ".0123456789eE+-"then
s1[i] := s[i]; elif s[i] in "dDqQ"then
s1[i] := 'e'; else
s1 := fail; break; fi;
od; if s1<>fail then
f := FLOAT_STRING(s1); if f<>fail then return f; fi; fi;
return fail; # conversion failure; signal the kernel that something went wrong end);
BindGlobal("CONVERT_FLOAT_LITERAL_EAGER", function(s,mark)
local f; if mark = '\000'then
return CONVERT_FLOAT_LITERAL(s); else if not IsBound(EAGER_FLOAT_LITERAL_CONVERTERS.([mark])) then
Error("Unknown float literal conversion ",mark); else
f := EAGER_FLOAT_LITERAL_CONVERTERS.([mark]); if not IsFunction(f) then
Error("Float literal conversion for ",mark," bound to non-function"); fi;
return f(s); fi; fi; end);
################################################################ # zeros ################################################################
InstallGlobalFunction(RootsFloat, function(arg)
local l; if Length(arg)=1 and IsList(arg[1]) then
l := arg[1]; elif ForAll(arg,IsFloat) then
l := arg; elif Length(arg)=1 and IsUnivariatePolynomial(arg[1]) then
l := CoefficientsOfUnivariatePolynomial(arg[1]); else
Error("RootsFloat: expected coefficients, a list of coefficients, or a polynomial, not ",arg); fi; if Length(l)=0then return []; fi;
return RootsFloatOp(l,l[1]); end);
############################################################################# ## Default methods ## ## These methods have priority -1, because they are inefficient. ## Hopefully every float implementation implements them better. #############################################################################
InstallMethod( Diameter, "for a float interval", [ IsFloatInterval ],
AbsoluteDiameter );
InstallMethod( AbsoluteValue, "for real floats", [ IsRealFloat ], -1, function ( x ) if x < Zero(x) then return -x; else return x; fi; end );
InstallMethod( Norm, "for real floats", [ IsRealFloat ], -1, function ( x )
return x*x; end );
InstallMethod( SignFloat, "for real floats", [ IsRealFloat ], -1, function ( x ) if IsZero( x ) then
return 0; elif x < Zero( x ) then
return -1; else
return 1; fi; end );
InstallMethod( Exp2, "for floats", [ IsFloat ], -1, function ( x )
return Exp(Log(MakeFloat(x,2))*x); end );
InstallMethod( Exp10, "for floats", [ IsFloat ], -1, function ( x )
return Exp(Log(MakeFloat(x,10))*x); end );
InstallMethod( Expm1, "for floats", [ IsFloat ], -1, function ( x )
return Exp(x)-MakeFloat(x,1); end );
InstallMethod( Log2, "for floats", [ IsFloat ], -1, function ( x )
return Log(x) / Log(MakeFloat(x,2)); end );
InstallMethod( Log10, "for floats", [ IsFloat ], -1, function ( x )
return Log(x) / Log(MakeFloat(x,10)); end );
InstallMethod( Log1p, "for floats", [ IsFloat ], -1, function ( x )
return Log(MakeFloat(x,1)+x); end );
InstallMethod( Sec, "for floats", [ IsFloat ], -1, function ( x )
return Inverse(Cos(x)); end );
InstallMethod( Csc, "for floats", [ IsFloat ], -1, function ( x )
return Inverse(Sin(x)); end );
InstallMethod( Cot, "for floats", [ IsFloat ], -1, function ( x )
return Inverse(Tan(x)); end );
InstallMethod( Sech, "for floats", [ IsFloat ], -1, function ( x )
return Inverse(Cosh(x)); end );
InstallMethod( Csch, "for floats", [ IsFloat ], -1, function ( x )
return Inverse(Sinh(x)); end );
InstallMethod( Coth, "for floats", [ IsFloat ], -1, function ( x )
return Inverse(Tanh(x)); end );
InstallMethod( CubeRoot, "for floats", [ IsFloat ], -1, function ( x ) if x>Zero(x) then
return Exp(Log(x)/3); elif IsZero(x) then
return x; else
return -Exp(Log(-x)/3); fi; end );
InstallMethod( Square, "for floats", [ IsFloat ], -1, function ( x )
return x*x; end );
InstallMethod( Hypothenuse, "for floats", [ IsFloat, IsFloat ], -1, function ( x, y )
return Sqrt(x*x+y*y); end );
InstallMethod( Ceil, "for real floats", [ IsRealFloat ], -1, function ( x )
return -Floor(-x); end );
# this is disabled because it's so bad... it loses an ulp in fringe cases. #InstallMethod( Round, "for floats", [ IsFloat ], -1, # function ( x ) # return Floor(x+MakeFloat(x,1/2)); #end );
InstallMethod( Trunc, "for real floats", [ IsRealFloat ], -1, function ( x ) if x>Zero(x) then
return Floor(x); else
return -Floor(-x); fi; end );
InstallMethod( Frac, "for floats", [ IsFloat ], -1, function ( x )
return x-Floor(x); end );
InstallMethod( SinCos, "for floats", [ IsFloat ], -1, function ( x )
return [Sin(x), Cos(x)]; end );
InstallMethod( Hypothenuse, "for floats", [ IsFloat, IsFloat ], -1, function ( x, y )
return Sqrt(x*x+y*y); end );
InstallMethod( FrExp, "for floats", [ IsFloat ], -1, function(obj)
local m, e; if IsZero(obj) then return [0,0]; fi; if obj<=Zero(obj) then obj := -obj; fi;
e := Int(Log2(obj))+1;
m := obj/2^e;
return [m,e]; end);
if not IsFinite(x) then
Error("cannot convert float ", x, " to rational"); fi;
i := 0; M := [[1,0],[0,1]];
maxdenom := ValueOption("maxdenom");
maxpartial := ValueOption("maxpartial"); if maxpartial=fail then maxpartial := 10000; fi; if maxdenom=fail then maxdenom := 10^QuoInt(FLOAT.DECIMAL_DIG,2); fi;
if x < Zero(x) then sign := -1; x := -x; else sign := 1; fi;
repeat
a_i := Int(x); if i >= 1 and a_i > maxpartial then break; fi;
M := M * [[a_i,1],[1,0]]; if x = Float(a_i) then break; fi;
x := One(x) / (x - a_i);
i := i+1;
until M[2][1] > maxdenom;
return sign * M[1][1]/M[2][1]; end );
InstallOtherMethod( Rat, "for float intervals", [ IsFloatInterval ], function ( x )
local M, a;
if x < Zero(x) then
M := [[-1,0],[0,1]]; x := -x; else
M := [[1,0],[0,1]]; fi;
repeat
a := Int(Sup(x));
M := M * [[a,1],[1,0]];
x := x-a; if Zero(x) in x then break; fi;
x := Inverse(x);
until AbsoluteDiameter(x) >= One(x);
return M[1][1]/M[2][1]; end);
BindGlobal("CYC_FLOAT_DEGREE", function(x,n,prec)
local i, m, b, phi;
phi := Phi(n);
m := IdentityMat(phi+1);
b := []; for i in [1..phi] do
Add(m[i],Int(LdExp(Cos(FLOAT.2PI*(i-1)/n),prec)));
Add(m[i],Int(LdExp(Sin(FLOAT.2PI*(i-1)/n),prec)));
b[i] := E(n)^(i-1);
od;
Add(m[phi+1],Int(LdExp(RealPart(x),prec)));
Add(m[phi+1],Int(LdExp(ImaginaryPart(x),prec)));
m := First(LLLReducedBasis(m).basis,r->r[phi+1]<>0);
return -b*m{[1..phi]}/m[phi+1]; end);
BindGlobal("CYC_FLOAT", function(x,prec)
local n, len, e, minlen, minn, mine;
n := 2;
minlen := infinity;
repeat
e := CYC_FLOAT_DEGREE(x,n,prec);
len := n*Norm(DenominatorCyc(e)*e)^2; if len < minlen then
Info(InfoWarning,2,"Degree ",n,": ",e);
minlen := len;
minn := n;
mine := e; fi;
n := n+1;
until n > 2*minn+4;
return mine; end);
InstallMethod( MinimalPolynomial, "for floats", [ IsRationals, IsFloat, IsPosInt ], function(ring,x,ind)
local n, len, p, lastlen, lastp, prec;
prec := ValueOption("bits"); if not IsPosInt(prec) then
prec := PrecisionFloat(x); if IsFloatInterval(x) then
p := AbsoluteDiameter(x); if not IsZero(x) then
prec := 1+LogInt(1+Int(Inverse(p)),2); fi; fi; fi; if IsFloatInterval(x) then
x := Mid(x); fi;
n := ValueOption("degree"); if IsPosInt(n) then
return FLOAT_MINIMALPOLYNOMIAL(x,n+1,ind,prec); fi;
n := 1;
len := infinity;
p := fail;
repeat
lastlen := len;
lastp := p;
p := FLOAT_MINIMALPOLYNOMIAL(x,n+1,ind,prec);
len := (CoefficientsOfUnivariatePolynomial(p)^2)^n;
n := n+1;
until len > lastlen;
return lastp; end);
################################################################ # rational functions ################################################################ # we need a new method, so that we keep track of the 0 and 1 of the # specific pseudofield
InstallOtherMethod(RationalFunctionsFamily, "floats pseudofield",
[IsFloatPseudoField], function(pf)
local fam;
# create a new family in the category <IsRationalFunctionsFamily>
fam := NewFamily("RationalFunctionsFamily(...)",
IsPolynomialFunction and IsPolynomialFunctionsFamilyElement
and IsFloatRationalFunction and IsRationalFunctionsFamilyElement,
CanEasilySortElements,
IsPolynomialFunctionsFamily and CanEasilySortElements and
IsRationalFunctionsFamily);
# default type for polynomials
fam!.defaultPolynomialType := NewType( fam,
IsPolynomial and IsPolynomialDefaultRep and
HasExtRepPolynomialRatFun);
# default type for univariate laurent polynomials
fam!.threeLaurentPolynomialTypes :=
[ NewType( fam,
IsLaurentPolynomial
and IsLaurentPolynomialDefaultRep and
HasIndeterminateNumberOfLaurentPolynomial and
HasCoefficientsOfLaurentPolynomial),
NewType( fam,
IsLaurentPolynomial
and IsLaurentPolynomialDefaultRep and
HasIndeterminateNumberOfLaurentPolynomial and
HasCoefficientsOfLaurentPolynomial and
IsConstantRationalFunction and IsUnivariatePolynomial),
NewType( fam,
IsLaurentPolynomial and IsLaurentPolynomialDefaultRep and
HasIndeterminateNumberOfLaurentPolynomial and
HasCoefficientsOfLaurentPolynomial and
IsUnivariatePolynomial)];
# default type for univariate rational functions
fam!.univariateRatfunType := NewType( fam,
IsUnivariateRationalFunctionDefaultRep and
HasIndeterminateNumberOfLaurentPolynomial and
HasCoefficientsOfUnivariateRationalFunction);
fam!.defaultRatFunType := NewType( fam,
IsRationalFunctionDefaultRep and
HasExtRepNumeratorRatFun and HasExtRepDenominatorRatFun);
# set the one and zero coefficient
fam!.zeroCoefficient := Zero(pf);
fam!.oneCoefficient := One(pf);
fam!.oneCoefflist := Immutable([fam!.oneCoefficient]);
# set the coefficients
SetCoefficientsFamily( fam, FamilyObj(fam!.zeroCoefficient) );
SetCharacteristic( fam, 0 );
# and set one and zero
SetZero( fam, PolynomialByExtRepNC(fam,[]));
SetOne( fam, PolynomialByExtRepNC(fam,[[],fam!.oneCoefficient]));
# we will store separate `one's for univariate polynomials. This will # allow to keep univariate calculations in this one indeterminate.
fam!.univariateOnePolynomials:=[];
fam!.univariateZeroPolynomials:=[];
# assign a names list
fam!.namesIndets := [];
# and return
return fam; end);
InstallOtherMethod( UnivariatePolynomialByCoefficients, "ring",
[IsFloatPseudoField,IsList,IsInt], function(r,cofs,ind)
return LaurentPolynomialByCoefficients(r,cofs,0,ind); end );
InstallOtherMethod( LaurentPolynomialByCoefficients, "ring",
[IsFloatPseudoField,IsList,IsInt,IsInt], function(r,cofs,val,ind)
local lc, fam;
lc := Length(cofs);
fam := RationalFunctionsFamily(r); if lc > 0 and (IsZero( cofs[1] ) or IsZero( cofs[lc] )) then
cofs := ShallowCopy( cofs );
val := val + RemoveOuterCoeffs( cofs, fam!.zeroCoefficient ); fi;
return LaurentPolynomialByExtRepNC( fam, cofs, val, ind ); end );
InstallOtherMethod( UnivariateRationalFunctionByCoefficients, "ring",
[IsFloatPseudoField,IsList,IsList,IsInt], function(r,ncof,dcof,val)
return UnivariateRationalFunctionByCoefficients(r,ncof,dcof,val,1); end );
InstallOtherMethod( UnivariateRationalFunctionByCoefficients, "ring",
[IsFloatPseudoField,IsList,IsList,IsInt,IsInt], function(r,ncof,dcof,val,ind)
local fam;
fam := RationalFunctionsFamily( r ); if Length( ncof ) > 0 and (IsZero( ncof[1] ) or IsZero( Last( ncof ) )) then if not IsMutable( ncof ) then
ncof := ShallowCopy( ncof ); fi;
val := val + RemoveOuterCoeffs( ncof, fam!.zeroCoefficient ); fi; if Length( dcof ) > 0 and (IsZero( dcof[1] ) or IsZero( Last( dcof ) )) then if not IsMutable( dcof ) then
dcof := ShallowCopy( dcof ); fi;
val := val - RemoveOuterCoeffs( dcof, fam!.zeroCoefficient ); fi;
return UnivariateRationalFunctionByExtRepNC( fam, ncof, dcof, val, ind ); end );
InstallMethod( PolynomialRing,"indetlist", true, [ IsFloatPseudoField, IsList ], 1, function( r, n )
local rfun, zero, one, ind, i, type, prng;
if IsPolynomialFunctionCollection(n) and ForAll(n,IsLaurentPolynomial) then
n:=List(n,IndeterminateNumberOfLaurentPolynomial); fi; if IsEmpty(n) or not IsInt(n[1]) then
TryNextMethod(); fi;
# get the rational functions of the elements family
rfun := RationalFunctionsFamily(r);
# cache univariate rings - they might be created often if not IsBound(r!.univariateRings) then
r!.univariateRings:=[]; fi;
if Length(n)=1 # some bozo might put in a ridiculous number
and n[1]<10000 # only cache for the prime field
and IsField(r)
and IsBound(r!.univariateRings[n[1]]) then
return r!.univariateRings[n[1]]; fi;
# first the indeterminates
zero := Zero(r);
one := One(r);
ind := []; for i in n do
Add( ind, LaurentPolynomialByCoefficients(r,[one],1,i) );
od;
# construct a polynomial ring
type := IsPolynomialRing and IsAttributeStoringRep and IsFreeLeftModule and IsAlgebraWithOne;
if Length(n) = 1then
type := type and IsUnivariatePolynomialRing and IsEuclideanRing; #and IsAlgebraWithOne; # done above already fi;
prng := Objectify( NewType( CollectionsFamily(rfun), type ), rec() );
# set the left acting domain
SetLeftActingDomain( prng, r );
# set the indeterminates
SetIndeterminatesOfPolynomialRing( prng, ind );
# set known properties
SetIsFinite( prng, false );
SetIsFiniteDimensional( prng, false );
SetSize( prng, infinity );
# set the coefficients ring
SetCoefficientsRing( prng, r );
# set one and zero
SetOne( prng, ind[1]^0 );
SetZero( prng, ind[1]*zero );
# set the generators left operator ring-with-one if the rank is one if IsRingWithOne(r) then
SetGeneratorsOfLeftOperatorRingWithOne( prng, ind ); fi;
if Length(n)=1 and n[1]<10000 # only cache for the prime field
and IsField(r) then
r!.univariateRings[n[1]]:=prng; fi;
# and return
return prng; end );
InstallOtherMethod( Indeterminate, [IsFloatFamily,IsPosInt], function(fam,ind)
Error("`Indeterminate(<family>,<ind>)' cannot be used with floats; use `Indeterminate(<float pseudofield>,<ind>)'"); end);
InstallOtherMethod( Indeterminate,"number, avoid", true, [ IsFloatPseudoField,IsList ],0, function( r,a ) if not IsRationalFunction(a[1]) then
TryNextMethod(); fi;
return LaurentPolynomialByCoefficients(r,[One(r)],1,
GiveNumbersNIndeterminates(RationalFunctionsFamily(r),1,[],a)[1]); end);
InstallOtherMethod( Indeterminate,"number, name", true, [ IsFloatPseudoField,IsString ],0, function( r,n ) if not IsString(n) then
TryNextMethod(); fi;
return LaurentPolynomialByCoefficients(r,[One(r)],1,
GiveNumbersNIndeterminates(RationalFunctionsFamily(r),1,[n],[])[1]); end);
InstallOtherMethod( Indeterminate,"number, name, avoid",true,
[ IsFloatPseudoField,IsString,IsList ],0, function( r,n,a ) if not IsString(n) then
TryNextMethod(); fi;
return LaurentPolynomialByCoefficients(r,[One(r)],1,
GiveNumbersNIndeterminates(RationalFunctionsFamily(r),1,[n],a)[1]); end);
# we must avoid over/underflow here; hence the specific method
InstallOtherMethod(ReduceCoeffs, "for float vectors",
[IsFloatCollection, IsInt, IsFloatCollection, IsInt], function (l1, n1, l2, n2)
local l, q, i, x; if0 = n2 then
Error("<l2> must be non-zero"); elif0 = n1 then
return n1; fi; while0 < n2 and IsZero(l2[n2]) do n2 := n2 - 1; od; if0 = n2 then
Error("<l2> must be non-zero"); fi; while0 < n1 and IsZero(l1[n1]) do n1 := n1 - 1; od; while n1 >= n2 do
q := l1[n1] / l2[n2];
l := n1-n2; for i in [ n1-n2+1 .. n1 ] do
x := l1[i] - q * l2[i-n1+n2]; if i=n1 or l1[i] - x/2 = l1[i] then# epsilon-small value
l1[i] := Zero(l1[i]); else
l1[i] := x;
l := i; fi;
od;
n1 := l;
od;
return n1; end);
InstallMethod( Derivative, "for float laurent polynomial",
[IsFloatRationalFunction and IsUnivariateRationalFunction and IsLaurentPolynomial], function(f)
local c, d, e, i, ind, fam;
ind := IndeterminateNumberOfUnivariateRationalFunction( f );
fam := FamilyObj(f);
e := CoefficientsOfLaurentPolynomial( f );
c := e[1]; if Length( c ) = 0then
return f; fi;
e := e[2];
d := [ ]; for i in [ 1 .. Length(c) ] do
d[i] := (i + e - 1) * c[i];
od;
e := e-1 + RemoveOuterCoeffs(d, fam!.zeroCoefficient);
return LaurentPolynomialByExtRepNC( fam, d, e, ind ); end );
############################################################################# ## #M \<, \+, ... for float and rat ##
# we say that all floateans are after all rationals, to sort them
BindGlobal("COMPARE_FLOAT_ANY", function(x,y)
local z; if IsFloat(x) then z := y; else z := x; fi;
Error("Comparison of float and ",z," is not supported. Please refer to the manual section on floats for details"); end);
InstallMethod( \+, "for rational and float", ReturnTrue, [ IsRat, IsFloat ], -1, function ( x, y ) return MakeFloat(y,x) + y; end );
InstallMethod( \+, "for float and rational", ReturnTrue, [ IsFloat, IsRat ], -1, function ( x, y ) return x + MakeFloat(x,y); end );
InstallMethod( \+, "for floats", ReturnTrue, [ IsFloat, IsFloat ], -1, function ( x, y ) return x + MakeFloat(x,y); end );
InstallMethod( \-, "for rational and float", ReturnTrue, [ IsRat, IsFloat ], -1, function ( x, y ) return MakeFloat(y,x) - y; end );
InstallMethod( \-, "for float and rational", ReturnTrue, [ IsFloat, IsRat ], -1, function ( x, y ) return x - MakeFloat(x,y); end );
InstallMethod( \-, "for floats", ReturnTrue, [ IsFloat, IsFloat ], -1, function ( x, y ) return x - MakeFloat(x,y); end );
InstallMethod( \*, "for rational and float", ReturnTrue, [ IsRat, IsFloat ], -1, function ( x, y ) return MakeFloat(y,x) * y; end );
InstallMethod( \*, "for float and rational", ReturnTrue, [ IsFloat, IsRat ], -1, function ( x, y ) return x * MakeFloat(x,y); end );
InstallMethod( \*, "for floats", ReturnTrue, [ IsFloat, IsFloat ], -1, function ( x, y ) return x * MakeFloat(x,y); end );
InstallMethod( \/, "for rational and float", ReturnTrue, [ IsRat, IsFloat ], -1, function ( x, y ) return MakeFloat(y,x) / y; end );
InstallMethod( \/, "for float and rational", ReturnTrue, [ IsFloat, IsRat ], -1, function ( x, y ) return x / MakeFloat(x,y); end );
InstallMethod( \/, "for floats", ReturnTrue, [ IsFloat, IsFloat ], -1, function ( x, y ) return x / MakeFloat(x,y); end );
InstallMethod( LQUO, "for rational and float", ReturnTrue, [ IsRat, IsFloat ], -1, function ( x, y ) return LQUO(MakeFloat(y,x),y); end );
InstallMethod( LQUO, "for float and rational", ReturnTrue, [ IsFloat, IsRat ], -1, function ( x, y ) return LQUO(x,MakeFloat(x,y)); end );
InstallMethod( LQUO, "for floats", ReturnTrue, [ IsFloat, IsFloat ], -1, function ( x, y ) return LQUO(x,MakeFloat(x,y)); end );
InstallOtherMethod( \/, "for empty list", [ IsEmpty, IsFloat ], function ( x, y ) return x; end );
InstallMethod( \^, "for rational and float", ReturnTrue, [ IsRat, IsFloat ], -1, function ( x, y ) return MakeFloat(y,x) ^ y; end );
InstallMethod( \^, "for float and rational", ReturnTrue, [ IsFloat, IsRat ], -1, function ( x, y ) if IsInt(y) then TryNextMethod(); fi;
return x ^ MakeFloat(x,y); end );
InstallMethod( \^, "for floats", ReturnTrue, [ IsFloat, IsFloat ], -1, function ( x, y ) return x ^ MakeFloat(x,y); end );
InstallMethod( IsGeneratorsOfMagmaWithInverses, "for a collection of floats (return false)",
[ IsFloatCollection ],
SUM_FLAGS, # override everything else function( gens )
Info( InfoWarning, 1, "no groups of floats allowed because of incompatible ^" );
return false; end );
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.13Bemerkung:
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.