1#############################################################################
2##
3##  This file is part of GAP, a system for computational discrete algebra.
4##  This file's authors include Martin Schönert.
5##
6##  Copyright of GAP belongs to its developers, whose names are too numerous
7##  to list here. Please refer to the COPYRIGHT file for details.
8##
9##  SPDX-License-Identifier: GPL-2.0-or-later
10##
11##  This file contains function that should be in the kernel of GAP.
12##  Actually it now just contains some utilities needed very early in
13##  the bootstrap.
14##
15
16
17#############################################################################
18##
19#F  ADD_LIST_DEFAULT( <list>, <obj> ) . . . . . .  add an element to the list
20##
21##  <ManSection>
22##  <Func Name="ADD_LIST_DEFAULT" Arg='list, obj'/>
23##
24##  <Description>
25##  </Description>
26##  </ManSection>
27##
28ADD_LIST_DEFAULT := function ( list, obj )
29    list[ LEN_LIST(list)+1 ] := obj;
30end;
31
32
33
34#############################################################################
35##
36#F  AS_LIST_SORTED_LIST( <list> ) . . . . . . . . . . . . . . setify the list
37##
38##  <ManSection>
39##  <Func Name="AS_LIST_SORTED_LIST" Arg='list'/>
40##
41##  <Description>
42##  </Description>
43##  </ManSection>
44##
45AS_LIST_SORTED_LIST := function ( list )
46    local   new;
47    if not IS_MUTABLE_OBJ( list ) and IS_SSORT_LIST( list ) then
48        new := list;
49    else
50        new := IMMUTABLE_COPY_OBJ( LIST_SORTED_LIST( list ) );
51    fi;
52    return new;
53end;
54
55#############################################################################
56##
57#F  Ordinal( <n> )  . . . . . . . . . . . . . ordinal of an integer as string
58##
59##  <#GAPDoc Label="Ordinal">
60##  <ManSection>
61##  <Func Name="Ordinal" Arg='n'/>
62##
63##  <Description>
64##  returns the ordinal of the integer <A>n</A> as a string.
65##  <Example><![CDATA[
66##  gap> Ordinal(2);  Ordinal(21);  Ordinal(33);  Ordinal(-33);
67##  "2nd"
68##  "21st"
69##  "33rd"
70##  "-33rd"
71##  ]]></Example>
72##  </Description>
73##  </ManSection>
74##  <#/GAPDoc>
75##
76Ordinal := function ( n )
77    local   str;
78
79    str := SHALLOW_COPY_OBJ(STRING_INT(n));
80    if n < 0 then n := -n; fi;
81    if   n mod 10 = 1  and n mod 100 <> 11  then
82        APPEND_LIST_INTR( str, "st" );
83    elif n mod 10 = 2  and n mod 100 <> 12  then
84        APPEND_LIST_INTR( str, "nd" );
85    elif n mod 10 = 3  and n mod 100 <> 13  then
86        APPEND_LIST_INTR( str, "rd" );
87    else
88        APPEND_LIST_INTR( str, "th" );
89    fi;
90    return str;
91end;
92
93
94#############################################################################
95##
96#F  IS_SUBSTRING( <str>, <sub> )  . . . . . . . . .  check if <sub> is prefix
97##
98##  <ManSection>
99##  <Func Name="IS_SUBSTRING" Arg='str, sub'/>
100##
101##  <Description>
102##  </Description>
103##  </ManSection>
104##
105IS_SUBSTRING := function( str, sub )
106  if LEN_LIST(sub) > 0 and POSITION_SUBSTRING(str, sub, 0) = fail then
107    return false;
108  else
109    return true;
110  fi;
111end;
112
113
114#############################################################################
115##
116#F  STRING_LOWER( <str> ) . . . . . . . . . convert to lower, remove specials
117##
118##  <ManSection>
119##  <Func Name="STRING_LOWER" Arg='str'/>
120##
121##  <Description>
122##  <!-- seems obsolete now? (FL) -->
123##  </Description>
124##  </ManSection>
125##
126STRING_LOWER_TRANS := 0;
127
128STRING_LOWER := function( str )
129  local i, res;
130  if STRING_LOWER_TRANS = 0 then
131    STRING_LOWER_TRANS := "";
132    for i in [0..255] do
133      STRING_LOWER_TRANS[i+1] := CHAR_INT(i);
134    od;
135    STRING_LOWER_TRANS{1+[65..90]} := STRING_LOWER_TRANS{1+[97..122]};
136    STRING_LOWER_TRANS{1+[33,126]} := "  ";
137  fi;
138  res := SHALLOW_COPY_OBJ(str);
139  TranslateString(res, STRING_LOWER_TRANS);
140  return res;
141end;
142
143
144#############################################################################
145##
146#F  POSITION_NOT( <list>, <val> [,<from-minus-one>] ) . . . .  find not <val>
147##
148##  <ManSection>
149##  <Func Name="POSITION_NOT" Arg='list, val [,from-minus-one]'/>
150##
151##  <Description>
152##  </Description>
153##  </ManSection>
154##
155POSITION_NOT := function( arg )
156    local i;
157
158    if LENGTH(arg) = 2  then
159        for i  in [ 1 .. LENGTH(arg[1]) ]  do
160            if arg[1][i] <> arg[2] then
161                return i;
162            fi;
163        od;
164        return LENGTH(arg[1]) + 1;
165
166    elif LENGTH(arg) = 3 then
167        for i  in [ arg[3]+1 .. LENGTH(arg[1]) ]  do
168            if arg[1][i] <> arg[2] then
169                return i;
170            fi;
171        od;
172        if LENGTH( arg[1] ) <= arg[3] then
173          return arg[3] + 1;
174        else
175          return LENGTH(arg[1]) + 1;
176        fi;
177    else
178      Error( "usage: PositionNot( <list>, <val>[, <from>] )" );
179    fi;
180
181end;
182
183#############################################################################
184##
185#F  Runtimes() . . . . . . . . self-explaining version of result of RUNTIMES()
186##
187##  <ManSection>
188##  <Func Name="Runtimes" Arg=''/>
189##
190##  <Description>
191##  </Description>
192##  </ManSection>
193##
194Runtimes := function()
195  local res, rt, cmp, a, i;
196  res := rec();
197  rt := RUNTIMES();
198  cmp := ["user_time", "system_time",
199          "user_time_children", "system_time_children"];
200  if IS_INT(rt) then
201    for a in cmp do
202      res.(a) := fail;
203    od;
204    res.(cmp[1]) := rt;
205  else
206    for i in [1..4] do
207      res.(cmp[i]) := rt[i];
208    od;
209  fi;
210  return res;
211end;
212