1# Copyright (c) 2011-2012, Thomas Paviot (tpaviot@gmail.com) 2# All rights reserved. 3 4# This file is part of the StepClassLibrary (SCL). 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions are met: 8# 9# Redistributions of source code must retain the above copyright notice, 10# this list of conditions and the following disclaimer. 11# 12# Redistributions in binary form must reproduce the above copyright notice, 13# this list of conditions and the following disclaimer in the documentation 14# and/or other materials provided with the distribution. 15# 16# Neither the name of the <ORGANIZATION> nor the names of its contributors may 17# be used to endorse or promote products derived from this software without 18# specific prior written permission. 19 20# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23# ARE DISCLAIMED. 24# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY 25# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 28# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 32__doc__ = "This module defines EXPRESS built in constants and functions" 33import math 34 35from SimpleDataTypes import * 36from BaseType import Aggregate 37from AggregationDataTypes import * 38 39SCL_float_epsilon = 1e-7 40# Builtin constants 41 42# EXPRESS definition: 43# =================== 44#14.1 CONST_E is a REAL constant representing the mathematical value e, the base of the natural 45#logarithm function (ln). 46CONST_E = REAL(math.pi) 47 48# EXPRESS definition: 49# =================== 50#14.2 Indeterminate 51#The indeterminate symbol (?) stands for an ambiguous value. It is compatible with all data 52#types. 53#NOTE - The most common use of indeterminate (?) is as the upper bound specication of a bag, 54#list or set. This usage represents the notion that the size of the aggregate value dened by the 55#aggregation data type is unbounded. 56# python note: indeterminate value is mapped to None in aggregate bounds 57 58# EXPRESS definition: 59# =================== 60#14.3 False 61#false is a logical constant representing the logical notion of falsehood. It is compatible with 62#the boolean and logical data types. 63FALSE = False 64 65# EXPRESS definition: 66# =================== 67#14.4 Pi 68#PI is a REAL constant representing the mathematical value , the ratio of a circle's circumference 69#to its diameter. 70PI = REAL(math.pi) 71 72# EXPRESS definition: 73# =================== 74#14.5 Self 75#SELF refers to the current entity instance or type value. self may appear within an entity 76#declaration, a type declaration or an entity constructor. 77#NOTE - sSELF is not a constant, but behaves as one in every context in which it can appear. 78# python note: SELF is not mapped to any constant, but is mapper to self 79 80# EXPRESS definition: 81# =================== 82#14.6 True 83#true is a logical constant representing the logical notion of truth. It is compatible with the 84#boolean and logical data types. 85TRUE = True 86 87# EXPRESS definition: 88# =================== 89#14.7 Unknown 90#unknown is a logical constant representing that there is insucient information available to 91#be able to evaluate a logical condition. It is compatible with the logical data type, but not 92#with the boolean data type. 93# @TODO: define UNKNOWN in python 94 95# 96# Builtin Functions 97#15 Built-in functions 98#All functions (and mathematical operations in general) are assumed to evaluate to exact results. 99#The prototype for each of the built-in functions is given to show the type of the formal parameters 100#and the result. 101# 102 103# EXPRESS definition: 104# =================== 105#15.1 Abs - arithmetic function 106#FUNCTION ABS ( V:NUMBER ) : NUMBER; 107#The abs function returns the absolute value of a number. 108#Parameters : V is a number. 109#Result : The absolute value of V. The returned data type is identical to the data type of V. 110#EXAMPLE 125 { ABS ( -10 ) --> 10 111# Python definition: 112# ================== 113# ABS is mapped to python abs builtin function 114def ABS(V): 115 if not isinstance(V,NUMBER): 116 raise TypeError("ABS function takes a NUMBER parameter") 117 return type(V)(abs(V)) 118 119# EXPRESS definition: 120# =================== 121#15.2 ACos - arithmetic function 122#FUNCTION ACOS ( V:NUMBER ) : REAL; 123#The acos function returns the angle given a cosine value. 124#Parameters : V is a number which is the cosine of an angle. 125#Result : The angle in radians (0 result ) whose cosine is V. 126#Conditions : -1.0=<V<=1.0 127#EXAMPLE 126 { ACOS ( 0.3 ) --> 1.266103... 128# Python definition: 129# ================== 130# ACOS is mapped to python math.acos builtin function 131def ACOS(V): 132 if not isinstance(V,NUMBER): 133 raise TypeError("ACOS function takes a NUMBER parameter") 134 return REAL(math.acos(V)) 135 136# it's the same for ASIN and ATAN 137def ASIN(V): 138 if not isinstance(V,NUMBER): 139 raise TypeError("ASIN function takes a NUMBER parameter") 140 return REAL(math.asin(V)) 141 142# EXPRESS definition: 143# =================== 144# 15.3 ATan - arithmetic function 145#FUNCTION ATAN ( V1:NUMBER; V2:NUMBER ) : REAL; 146#The atan function returns the angle given a tangent value of V , where V is given by the 147#expression V = V1/V2. 148#Parameters : 149#a) V1 is a number. 150#b) V2 is a number. 151#Result : The angle in radians (-pi/2<=result<=pi/2) whose tangent is V. If V2 is zero, the result 152#is pi/2 or -pi/2 depending on the sign of V1. 153#Conditions : Both V1 and V2 shall not be zero. 154#EXAMPLE 128 { ATAN ( -5.5, 3.0 ) --> -1.071449... 155def ATAN(V1,V2): 156 if not isinstance(V1,NUMBER) and not isinstance(V2,NUMBER): 157 raise TypeError("ATAN function takes 2 NUMBER parameters") 158 if V2 == 0: 159 if V1>0: 160 return REAL(math.pi/2) 161 elif V1<0: 162 return REAL(-math.pi/2) 163 else: 164 raise ValueError("ATAN parameters can be both equal to zero") 165 else: 166 return REAL(math.atan(float(V1)/float(V2))) 167 168# EXPRESS definition: 169# =================== 170#15.5 BLength - binary function 171#FUNCTION BLENGTH ( V:BINARY ) : INTEGER; 172#The blength function returns the number of bits in a binary. 173#Parameters : V is a binary value. 174#Result : The returned value is the actual number of bits in the binary value passed. 175#EXAMPLE 129 176#LOCAL 177#n : NUMBER; 178#x : BINARY := %01010010 ; 179#END_LOCAL; 180#... 181#n := BLENGTH ( x ); -- n is assigned the value 8 182def BLENGTH(V): 183 if not isinstance(V,BINARY): 184 raise TypeError("BLENGTH function takes one BINARY parameter") 185 return INTEGER(len(V)) 186 187# EXPRESS definition: 188# =================== 189#15.6 Cos - arithmetic function 190#FUNCTION COS ( V:NUMBER ) : REAL; 191#The cos function returns the cosine of an angle. 192#Parameters : V is a number which is an angle in radians. 193#Result : The cosine of V (-1.0<=result<=1.0). 194#EXAMPLE 130 { COS ( 0.5 ) --> 8.77582...E-1 195# 196#15.21 Sin - arithmetic function 197#FUNCTION SIN ( V:NUMBER ) : REAL; 198#The sin function returns the sine of an angle. 199#Parameters : V is a number representing an angle expressed in radians. 200#Result : The sine of V (-1.0 result 1.0). 201#EXAMPLE 144 { SIN ( PI ) --> 0.0 202# 203def COS(V): 204 if not isinstance(V,NUMBER): 205 raise TypeError("COS function takes a NUMBER parameter") 206 return REAL(math.cos(V)) 207def SIN(V): 208 if not isinstance(V,NUMBER): 209 raise TypeError("SIN function takes a NUMBER parameter") 210 return REAL(math.sin(V)) 211 212# EXPRESS definition: 213# =================== 214#15.7 Exists - general function 215#FUNCTION EXISTS ( V:GENERIC ) : BOOLEAN; 216#The exists function returns true if a value exists for the input parameter, or false if no value 217#exists for it. The exists function is useful for checking if values have been given to optional 218#attributes, or if variables have been initialized. 219#Parameters : V is an expression which results in any type. 220#Result : true or false depending on whether V has an actual or indeterminate (?) value. 221#EXAMPLE 131 { IF EXISTS ( a ) THEN ... 222def EXISTS(V): 223 if V==None: 224 return False 225 else: 226 return True 227 228# EXPRESS definition: 229# =================== 230#15.8 Exp - arithmetic function 231#FUNCTION EXP ( V:NUMBER ) : REAL; 232#The exp function returns e (the base of the natural logarithm system) raised to the power V. 233#Parameters : V is a number. 234#Result : The value eV . 235#EXAMPLE 132 { EXP ( 10 ) --> 2.202646...E+4 236def EXP(V): 237 if not isinstance(V,NUMBER): 238 raise TypeError("EXP function takes a NUMBER parameter") 239 return REAL(math.exp(V)) 240 241# EXPRESS definition: 242# =================== 243#15.9 Format - general function 244#FUNCTION FORMAT(N:NUMBER; F:STRING):STRING; 245#The format returns a formatted string representation of a number. 246#Parameters : 247#a) N is a number (integer or real). 248#b) F is a string containing formatting commands. 249#Result : A string representation of N formatted according to F. Rounding is applied to the 250#string representation if necessary. 251#The formatting string contains special characters to indicate the appearance of the result. The 252#formatting string can be written in three ways: 253#a) The formatting string can give a symbolic description of the output representation. 254#b) The formatting string can give a picture description of the output representation. 255#c) When the formatting string is empty, a standard output representation is produced. 256# Table 20: 257#Number Format Display Comment 258#10 +7I ' +10' Zero suppression 259#10 +07I '+000010' Zeros not suppressed 260#10 10.3E ' 1.000E+01' 261#123.456789 8.2F ' 123.46' 262#123.456789 8.2E '1.23E+02' 263#123.456789 08.2E '0.12E+02' Preceding zero forced 264#9.876E123 8.2E '9.88E+123' Exponent part is 3 characters 265#and width ignored 266#32.777 6I ' 33' Rounded 267# Python definition 268# ================= 269# python string formatting is obtained from the val function 270# @TODO: implement a safe eval or provide another implementation 271# that avoids unsafe eval python builtin function. 272def FORMAT(N,F): 273 if not isinstance(N,NUMBER): 274 raise TypeError("FORMAT function takes a NUMBER parameter") 275 if not isinstance(F,STRING): 276 raise TypeError("FORMAT function takes a NUMBER parameter") 277 py_formatting = F.lower() 278 string_to_evaluate = "'%" 279 string_to_evaluate += "%s'"%py_formatting 280 string_to_evaluate += "%" 281 string_to_evaluate += "%s"%N 282 result = eval(string_to_evaluate).upper() 283 return STRING(result) 284 285# EXPRESS definition: 286# =================== 287#15.10 HiBound - arithmetic function 288#FUNCTION HIBOUND ( V:AGGREGATE OF GENERIC ) : INTEGER; 289#The hibound function returns the declared upper index of an array or the declared upper 290#bound of a bag, list or set. 291#Parameters : V is an aggregate value. 292#Result : 293#a) When V is an array the returned value is the declared upper index. 294#b) When V is a bag, list or set the returned value is the declared upper bound; if there 295#are no bounds declared or the upper bound is declared to be indeterminate (?) indeterminate 296#(?) is returned. 297#EXAMPLE 133 { Usage of hibound function on nested aggregate values. 298#LOCAL 299#a : ARRAY[-3:19] OF SET[2:4] OF LIST[0:?] OF INTEGER; 300#h1, h2, h3 : INTEGER; 301#END_LOCAL; 302#... 303#a[-3][1][1] := 2; -- places a value in the list 304#... 305#h1 := HIBOUND(a); -- =19 (upper bound of array) 306#h2 := HIBOUND(a[-3]); -- = 4 (upper bound of set) 307#h3 := HIBOUND(a[-3][1]); -- = ? (upper bound of list (unbounded)) 308def HIBOUND(V): 309 if not isinstance(V,Aggregate): 310 raise TypeError("HIBOUND takes an aggregate of generic") 311 return V.get_hibound() 312 313# EXPRESS definition: 314# =================== 315#15.11 HiIndex - arithmetic function 316#FUNCTION HIINDEX ( V:AGGREGATE OF GENERIC ) : INTEGER; 317#The hiindex function returns the upper index of an array or the number of elements in a bag, 318#list or set 319#Parameters : V is an aggregate value. 320#Result : 321#a) When V is an array, the returned value is the declared upper index. 322#b) When V is a bag, list or set, the returned value is the actual number of elements in 323#the aggregate value. 324#EXAMPLE 134 { Usage of hiindex function on nested aggregate values. 325#LOCAL 326#a : ARRAY[-3:19] OF SET[2:4] OF LIST[0:?] OF INTEGER; 327#h1, h2, h3 : INTEGER; 328#END_LOCAL; 329#a[-3][1][1] := 2; -- places a value in the list 330#h1 := HIINDEX(a); -- = 19 (upper bound of array) 331#h2 := HIINDEX(a[-3]); -- = 1 (size of set) -- this is invalid with respect 332#-- to the bounds on the SET 333#h3 := HIINDEX(a[-3][1]); -- = 1 (size of list) 334def HIINDEX(V): 335 if not isinstance(V,Aggregate): 336 raise TypeError("HIINDEX takes an aggregate of generic") 337 return V.get_hiindex() 338 339# EXPRESS definition: 340# =================== 341#15.12 Length - string function 342#FUNCTION LENGTH ( V:STRING ) : INTEGER; 343#The length function returns the number of characters in a string. 344#Parameters : V is a string value. 345#Result : The returned value is the number of characters in the string and shall be greater than 346#or equal to zero. 347#EXAMPLE 135 - Usage of the length function. 348#LOCAL 349#n : NUMBER; 350#x1 : STRING := 'abc'; 351#x2 : STRING := "000025FF000101B5; 352#END_LOCAL; 353#... 354#n := LENGTH ( x1 ); -- n is assigned the value 3 355#n := LENGTH ( x2 ); -- n is assigned the value 2 356def LENGTH(V): 357 if not isinstance(V,STRING): 358 raise TypeError("LENGTH take a STRING parameter") 359 return INTEGER(len(V)) 360 361# EXPRESS definition: 362# =================== 363#15.13 LoBound - arithmetic function 364#FUNCTION LOBOUND ( V:AGGREGATE OF GENERIC ) : INTEGER; 365#The lobound function returns the declared lower index of an array, or the declared lower 366#bound of a bag, list or set. 367#Parameters : V is an aggregate value. 368#Result : 369#a) When V is an array the returned value is the declared lower index. 370#b) When V is a bag, list or set the returned value is the declared lower bound; if no 371#lower bound is declared, zero (0) is returned. 372#EXAMPLE 136 { Usage of lobound function on nested aggregate values. 373#LOCAL 374#a : ARRAY[-3:19] OF SET[2:4] OF LIST[0:?] OF INTEGER; 375#h1, h2, h3 : INTEGER; 376#END_LOCAL; 377#... 378#h1 := LOBOUND(a); -- =-3 (lower index of array) 379#h2 := LOBOUND(a[-3]); -- = 2 (lower bound of set) 380#h3 := LOBOUND(a[-3][1]); -- = 0 (lower bound of list) 381def LOBOUND(V): 382 if not isinstance(V,Aggregate): 383 raise TypeError("HIBOUND takes an aggregate of generic") 384 return V.get_lobound() 385 386# EXPRESS definition: 387# =================== 388#15.14 Log - arithmetic function 389#FUNCTION LOG ( V:NUMBER ) : REAL; 390#The log function returns the natural logarithm of a number. 391#Parameters : V is a number. 392#Result : A real number which is the natural logarithm of V. 393#Conditions : V > 0:0 394#EXAMPLE 137 { LOG ( 4.5 ) --> 1.504077...E0 395#15.15 Log2 - arithmetic function 396#FUNCTION LOG2 ( V:NUMBER ) : REAL; 397#The log2 function returns the base two logarithm of a number. 398#Parameters : V is a number. 399#Result : A real number which is the base two logarithm of V. 400#Conditions : V > 0:0 401#EXAMPLE 138 { LOG2 ( 8 ) --> 3.00...E0 402#15.16 Log10 - arithmetic function 403#FUNCTION LOG10 ( V:NUMBER ) : REAL; 404#The log10 function returns the base ten logarithm of a number. 405#Parameters : V is a number. 406#Result : A real number which is the base ten logarithm of V. 407#Conditions : V > 0:0 408#EXAMPLE 139 { LOG10 ( 10 ) --> 1.00...E0 409def LOG(V): 410 if not isinstance(V,NUMBER): 411 raise TypeError("LOG function takes a NUMBER parameter") 412 return REAL(math.log(V)) 413def LOG2(V): 414 if not isinstance(V,NUMBER): 415 raise TypeError("LOG2 function takes a NUMBER parameter") 416 return REAL(math.log(V,2)) 417def LOG10(V): 418 if not isinstance(V,NUMBER): 419 raise TypeError("LOG10 function takes a NUMBER parameter") 420 return REAL(math.log10(V)) 421 422# EXPRESS definition: 423# =================== 424#15.17 LoIndex - arithmetic function 425#FUNCTION LOINDEX ( V:AGGREGATE OF GENERIC ) : INTEGER; 426#The loindex function returns the lower index of an aggregate value. 427#Parameters : V is an aggregate value. 428#Result : 429#a) When V is an array the returned value is the declared lower index. 430#b) When V is a bag, list or set, the returned value is 1 (one). 431#EXAMPLE 140 { Usage of loindex function on nested aggregate values. 432#LOCAL 433#a : ARRAY[-3:19] OF SET[2:4] OF LIST[0:?] OF INTEGER; 434#h1, h2, h3 : INTEGER; 435#END_LOCAL; 436#... 437#h1 := LOINDEX(a); -- =-3 (lower bound of array) 438#h2 := LOINDEX(a[-3]); -- = 1 (for set) 439#h3 := LOINDEX(a[-3][1]); -- = 1 (for list) 440def LOINDEX(V): 441 if not isinstance(V,Aggregate): 442 raise TypeError("LOINDEX takes an aggregate of generic") 443 return V.get_loindex() 444 445# EXPRESS definition: 446# =================== 447#15.18 NVL - null value function 448#FUNCTION NVL(V:GENERIC:GEN1; SUBSTITUTE:GENERIC:GEN1):GENERIC:GEN1; 449#The nvl function returns either the input value or an alternate value in the case where the input 450#has a indeterminate (?) value. 451#Parameters : 452#a) V is an expression which is of any type. 453#b) SUBSTITUTE is an expression which shall not evaluate to indeterminate (?). 454#Result : When V is not indeterminate (?) that value is returned. Otherwise, SUBSTITUTE is 455#returned. 456#EXAMPLE 141 { ENTITY unit_vector; 457#x, y : REAL; 458#z : OPTIONAL REAL; 459#WHERE 460#x**2 + y**2 + NVL(z, 0.0)**2 = 1.0; 461#END_ENTITY; 462#The nvl function is used to supply zero (0.0) as the value of Z when Z is indeterminate (?). 463def NVL(V,SUBSTITUTE): 464 if V is not None: 465 return V 466 else: 467 return SUBSTITUTE 468 469# EXPRESS definition: 470# =================== 471#15.19 Odd - arithmetic function 472#FUNCTION ODD ( V:INTEGER ) : LOGICAL; 473#The odd function returns true or false depending on whether a number is odd or even. 474#Parameters : V is an integer number. 475#Result : When V MOD 2 = 1 true is returned; otherwise false is returned. 476#Conditions : Zero is not odd. 477#EXAMPLE 142 { ODD ( 121 ) --> TRUE 478def ODD(V): 479 if not isinstance(V,INTEGER): 480 raise TypeError("ODD takes an INTEGER") 481 if V%2 == 0: 482 return False 483 else: 484 return True 485 486# EXPRESS definition: 487# =================== 488#15.20 RolesOf - general function 489#FUNCTION ROLESOF ( V:GENERIC ) : SET OF STRING; 490#The rolesof function returns a set of strings containing the fully qualied names of the roles 491#played by the specied entity instance. A fully qualied name is dened to be the name of the 492#attribute qualied by the name of the schema and entity in which this attribute is declared (i.e. 493#'SCHEMA.ENTITY.ATTRIBUTE'). 494#Parameters : V is any instance of an entity data type. 495#Result : A set of string values (in upper case) containing the fully qualied names of the 496#attributes of the entity instances which use the instance V. 497#When a named data type is use'd or reference'd, the schema and the name in that schema, 498#if renamed, are also returned. Since use statements may be chained, all the chained schema 499#names and the name in each schema are returned. 500#EXAMPLE 143 { This example shows that a point might be used as the centre of a circle. The 501#rolesof function determines what roles an entity instance actually plays. 502#SCHEMA that_schema; 503#ENTITY point; 504#x, y, z : REAL; 505#END_ENTITY; 506#ENTITY line; 507#start, 508#end : point; 509#END_ENTITY; 510#END_SCHEMA; 511#SCHEMA this_schema; 512#USE FROM that_schema (point,line); 513#CONSTANT 514#origin : point := point(0.0, 0.0, 0.0); 515#END_CONSTANT; 516#ENTITY circle; 517#centre : point; 518#axis : vector; 519#radius : REAL; 520#END_ENTITY; 521#... 522#LOCAL 523#p : point := point(1.0, 0.0, 0.0); 524#c : circle := circle(p, vector(1,1,1), 1.0); 525#l : line := line(p, origin); 526#END_LOCAL; 527#... 528#IF 'THIS_SCHEMA.CIRCLE.CENTRE' IN ROLESOF(p) THEN -- true 529#... 530#IF 'THIS_SCHEMA.LINE.START' IN ROLESOF(p) THEN -- true 531#... 532#IF 'THAT_SCHEMA.LINE.START' IN ROLESOF(p) THEN -- true 533#... 534#IF 'THIS_SCHEMA.LINE.END' IN ROLESOF(p) THEN -- false 535# 536# Python note: 537# @TODO: implement the ROLESOF function 538def ROLESOF(V): 539 raise NotImplemented("Function ROLESOF not implemented") 540 541# EXPRESS definition: 542# =================== 543#15.22 SizeOf - aggregate function 544#FUNCTION SIZEOF ( V:AGGREGATE OF GENERIC ) : INTEGER; 545#The sizeof function returns the number of elements in an aggregate value. 546#Parameters : V is an aggregate value. 547#Result : 548#a) When V is an array the returned value is its declared number of elements in the 549#aggregation data type. 550#b) When V is a bag, list or set, the returned value is the actual number of elements in 551#the aggregate value. 552#EXAMPLE 145 { LOCAL 553#n : NUMBER; 554#y : ARRAY[2:5] OF b; 555#END_LOCAL; 556#... 557#n := SIZEOF (y); -- n is assigned the value 4 558def SIZEOF(V): 559 if not isinstance(V,Aggregate): 560 raise TypeError("SIZEOF takes an aggregate of generic") 561 return V.get_size() 562 563# EXPRESS definition: 564# =================== 565#15.23 Sqrt - arithmetic function 566#FUNCTION SQRT ( V:NUMBER ) : REAL; 567#The sqrt function returns the non-negative square root of a number. 568#Parameters : V is any non-negative number. 569#Result : The non-negative square root of V. 570#Conditions : V 0:0 571#EXAMPLE 146 - SQRT ( 121 ) --> 11.0 572def SQRT(V): 573 if not isinstance(V,NUMBER): 574 raise TypeError("SQRT function takes a NUMBER parameter") 575 if V<0.0: 576 raise ValueError("SQRT takes a non-negative parameter") 577 return REAL(math.sqrt(V)) 578 579# EXPRESS definition: 580# =================== 581#15.24 Tan - arithmetic function 582#FUNCTION TAN ( V:NUMBER ) : REAL; 583#The tan function returns the tangent of of an angle. 584#Parameters : V is a number representing an angle expressed in radians. 585#Result : The tangent of the angle. If the angle is npi/2, where n is an odd integer, indeterminate 586#(?) is returned. 587#EXAMPLE 147 - TAN ( 0.0 ) --> 0.0 588def TAN(V): 589 if not isinstance(V,NUMBER): 590 raise TypeError("TAN function takes a NUMBER parameter") 591 # check if angle is npi/2 where n is an odd integer 592 a = V/(PI/2) 593 if abs(a%2-1.) < SCL_float_epsilon : 594 return None 595 else: 596 return REAL(math.tan(V)) 597 598# EXPRESS definition: 599# =================== 600#15.25 TypeOf - general function 601#FUNCTION TYPEOF ( V:GENERIC ) : SET OF STRING; 602#The typeof function returns a set of strings that contains the names of all the data types 603#of which the parameter is a member. Except for the simple data types (binary, boolean, 604#integer, logical, number, real, and string) and the aggregation data types (array, bag, 605#list, set) these names are qualied by the name of the schema which contains the denition of 606#the type. 607#NOTE 1 { The primary purpose of this function is to check whether a given value (variable, at- 608#tribute value) can be used for a certain purpose, e.g. to ensure assignment compatibility between 609#two values. It may also be used if dierent subtypes or specializations of a given type have to be 610#treated dierently in some context. 611#Parameters : V is a value of any type. 612#Result : The contents of the returned set of string values are the names (in upper case) of all 613#types the value V is a member of. Such names are qualied by the name of the schema which 614#contains the denition of the type ('SCHEMA.TYPE') if it is neither a simple data type nor an 615#aggregation data type. It may be derived by the following algorithm (which is given here for 616#specification purposes rather than to prescribe any particular type of implementation) 617def TYPEOF(V): 618 # Create the set to return 619 v_types = set() 620 # append the type of V to the set 621 try: #it's a class 622 to_add = V.__name__.upper() 623 except AttributeError: #it's an instance, first retrieve the type 624 to_add = type(V).__name__.upper() 625 if not to_add in ['FLOAT','INT','AGGREGATE']: 626 v_types.add(to_add) 627 # recursively adds the base class names 628 for base_type in type(V).__bases__: 629 #print base_type 630 if not base_type == object: 631 v_types = v_types.union(TYPEOF(base_type)) 632 # finally, converts the v_types set to SET 633 return v_types 634 635# EXPRESS definition: 636# =================== 637#15.26 UsedIn - general function 638#FUNCTION USEDIN ( T:GENERIC; R:STRING) : BAG OF GENERIC; 639#The usedin function returns each entity instance that uses a specied entity instance in a 640#specied role. 641def USEDIN(T,R): 642 raise NotImplemented("USEDIN function not yet implemented.") 643 644# EXPRESS definition: 645# =================== 646#15.27 Value - arithmetic function 647#FUNCTION VALUE ( V:STRING ) : NUMBER; 648#The value function returns the numeric representation of a string. 649#Parameters : V is a string containing either a real or integer literal. 650#Result : A number corresponding to the string representation. If it is not possible to interpret 651#the string as either a real or integer literal, indeterminate (?) is returned. 652#EXAMPLE 151 { VALUE ( '1.234' ) --> 1.234 (REAL) 653#VALUE ( '20' ) --> 20 (INTEGER) 654#VALUE ( 'abc' ) --> ? null 655def VALUE(V): 656 if not isinstance(V,STRING): 657 raise TypeError("VALULE function takes a NUMBER parameter") 658 # first try to instanciate an INTEGER from the string: 659 try: 660 return INTEGER(V) 661 except: 662 pass #not possible, try to cast to REAL 663 try: 664 return REAL(V) 665 except: 666 pass 667 # else return None 668 return None 669 670# EXPRESS definition: 671# =================== 672#15.28 Value in - membership function 673#FUNCTION VALUE_IN ( C:AGGREGATE OF GENERIC:GEN; V:GENERIC:GEN ) : LOGICAL; 674#The value in function returns a logical value depending on whether or not a particular value 675#is a member of an aggregation. 676#Parameters : 677#a) C is an aggregation of any type. 678#b) V is an expression which is assignment compatible with the base type of C. 679#Result : 680#a) If either V or C is indeterminate (?), unknown is returned. 681#b) If any element of C has a value equal to the value of V, true is returned. 682#c) If any element of C is indeterminate (?), unknown is returned. 683#d) Otherwise false is returned. 684#EXAMPLE 152 { The following test ensures that there is at least one point which is positioned at 685#the origin. 686#LOCAL 687#points : SET OF point; 688#END_LOCAL; 689#... 690#IF VALUE_IN(points, point(0.0, 0.0, 0.0)) THEN ... 691def VALUE_IN(C,V): 692 if not isinstance(C,Aggregate): 693 raise TypeError("VALUE_IN method takes an aggregate as first parameter") 694 raise NotImplemented("VALUE_IN function not et implemented") 695 696# EXPRESS definition: 697# =================== 698#15.29 Value unique - uniqueness function 699#FUNCTION VALUE UNIQUE ( V:AGGREGATE OF GENERIC) : LOGICAL; 700#The value unique function returns a logical value depending on whether or not the elements 701#of an aggregation are value unique. 702#Parameters : V is an aggregation of any type. 703#Result : 704#a) If V is indeterminate (?), unknown is returned. 705#b) If any any two elements of V are value equal, false is returned. 706#c) If any element of V is indeterminate (?), unknown is returned. 707#d) Otherwise true is returned. 708#EXAMPLE 153 { The following test ensures tht each point is a set is at a dierent position, (by 709#denition they are distinct, i.e., instance unique). 710#IF VALUE_UNIQUE(points) THEN ... 711def VALUE_UNIQUE(V): 712 if not isinstance(V,Aggregate): 713 raise TypeError("VALUE_UNIQUE method takes an aggregate as first parameter") 714 return V.get_value_unique() 715 716