# Difference between revisions of "Reference:Numeric Expressions"

Jholsenback (talk | contribs) m (version changes) |
Jholsenback (talk | contribs) m (technical correction) |
||

Line 122: | Line 122: | ||

</pre> | </pre> | ||

− | <p>Where <em>IDENTIFIER</em> is | + | <p>Where <em>IDENTIFIER</em> is valid identifier name and <em>EXPRESSION</em> is any valid expression which |

− | + | evaluates to a float value.</p> | |

− | evaluates to a float value. </p> | + | <p class="Note"><strong>Note:</strong> There should be a semi-colon after the expression in a float declaration. If omitted, it generates a warning and some macros may not work properly.</p> |

− | <p class="Note"><strong>Note:</strong> There should be a semi-colon after the | + | <p>See also: <!--<linkto "Identifiers">Identifiers</linkto>--->[[Reference:Identifiers|Identifiers]] and <!--<linkto "#declare vs. #local">#declare vs. #local</linkto>--->[[Reference:Declare and Local Directives#declare vs. local|#declare vs. #local]] for additional information on identifier naming and scope.</p> |

− | expression in a float declaration. If omitted, it generates a warning | ||

− | and some macros may not work properly. See <!--<linkto "#declare vs. #local">#declare vs. #local</linkto>--->[[Reference:Declare and Local Directives#declare vs. local|#declare vs. #local]] for information on identifier scope.</p> | ||

<p>Here are some examples.</p> | <p>Here are some examples.</p> |

## Revision as of 18:00, 10 February 2020

Many parts of the POV-Ray language require you to specify one or more floating point numbers. A floating point number is a number with a decimal point. Floats may be specified using literals, identifiers or functions which return float values. You may also create very complex float expressions from combinations of any of these using various familiar operators.

Where POV-Ray needs an integer value it allows you to specify a float value
and it truncates it to an integer. When POV-Ray needs a logical or boolean
value it interprets any non-zero float as true and zero as false. Because
float comparisons are subject to rounding errors POV-Ray accepts values
extremely close to zero as being false when doing boolean functions.
Typically values whose absolute values are less than a preset value *
epsilon* are considered false for logical expressions. The value of *
epsilon* is system dependent but is generally about 1.0e-10. Two floats
*a* and *b* are considered to be equal if *abs(a-b) <
epsilon.*

The full syntax for float expressions is given below. Detailed explanations are given in the following sub-sections.

FLOAT: NUMERIC_TERM [SIGN NUMERIC_TERM]... SIGN: + | - NUMERIC_TERM: NUMERIC_FACTOR [MULT NUMERIC_FACTOR]... MULT: * | / NUMERIC_FACTOR: FLOAT_LITERAL | FLOAT_IDENTIFIER | SIGN NUMERIC_FACTOR | FLOAT_FUNCTION | FLOAT_BUILT_IN_IDENT | ( FULL_EXPRESSION ) | ! NUMERIC_FACTOR | VECTOR DECIMAL_POINT DOT_ITEM | FLOAT_FUNCTION_INVOCATION FLOAT_LITERAL: MANTISSA [EXP [SIGN] DIGIT...] MANTISSA: DIGIT... [DECIMAL_POINT [DIGIT...]] | DECIMAL_POINT DIGIT... DIGIT: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 DECIMAL_POINT: . EXP: e | E DOT_ITEM: x | y | z | t | u | v | red | green | blue | filter | transmit | gray FLOAT_FUNCTION: abs( FLOAT ) | acos( FLOAT ) | acosh( FLOAT ) | asc( STRING ) | asin( FLOAT ) | asinh( FLOAT ) | atan( FLOAT) | atanh( FLOAT) | atan2( FLOAT , FLOAT ) | bitwise_and( FLOAT, FLOAT, ...) | bitwise_or (FLOAT, FLOAT, ...) | bitwise_xor ( FLOAT, FLOAT, ...) | ceil( FLOAT ) | cos( FLOAT ) | cosh( FLOAT ) | defined(IDENTIFIER ) | degrees( FLOAT ) | dimensions( ARRAY_IDENTIFIER ) | dimension_size( ARRAY_IDENTIFIER , FLOAT ) | div( FLOAT , FLOAT ) | exp( FLOAT ) | file_exists( STRING ) | floor( FLOAT ) | int( FLOAT ) | ln(Float | log( FLOAT ) | max( FLOAT , FLOAT, ... ) | min( FLOAT , FLOAT, ... ) | mod( FLOAT , FLOAT ) | pow( FLOAT , FLOAT ) | radians( FLOAT ) | rand( FLOAT ) | seed( FLOAT ) | select( FLOAT, FLOAT, FLOAT [,FLOAT]) | sin( FLOAT ) | sinh( FLOAT ) | sqrt( FLOAT ) | strcmp( STRING , STRING ) | strlen( STRING ) | tan( FLOAT ) | tanh( FLOAT ) | val( STRING ) | vdot( VECTOR , VECTOR ) | vlength( VECTOR ) | FLOAT_BUILT_IN_IDENT: clock | clock_delta | clock_on | false | final_clock | final_frame | frame_number | image_height | image_width | initial_clock | initial_frame | no | now | off | on | pi | true | version | yes FULL_EXPRESSION: FLOAT | LOGICAL_EXPRESSION [? FULL_EXPRESSION : FULL_EXPRESSION] LOGICAL_EXPRESSION: REL_TERM [LOGICAL_OPERATOR REL_TERM]... LOGICAL_OPERATOR: & | | (note: this means an ampersand or a vertical bar is a logical operator) REL_TERM: FLOAT [REL_OPERATOR FLOAT]... | STRING REL_OPERATOR STRING REL_OPERATOR: < | <= | = | >= | > | != INT: FLOAT (note: any syntax which requires a integer INT will accept a FLOAT and it will be truncated to an integer internally by POV-Ray).

**Note:** *FLOAT_IDENTIFIERS* are identifiers previously declared to
have float values. The *DOT_ITEM* syntax is actually a vector or color operator but it returns a float value. See Vector Operators or Color Operators for details. An * ARRAY_IDENTIFIER* is just the identifier name of a previously declared array, it does not include the `[]`

braces nor the index. The syntax for *STRING* is in the section Strings.

## Literals

Float literals are represented by an optional sign ("+" or "-") digits, an optional decimal point and more digits. If the number is an integer you may omit the decimal point and trailing zero. If it is all fractional you may omit the leading zero. POV-Ray supports scientific notation for very large or very small numbers. The following are all valid float literals:

` -2.0 -4 34 3.4e6 2e-5 .3 0.6`

## Identifiers

Float identifiers may be declared to make scene files more readable and to parameterize scenes so that changing a single declaration changes many values. An identifier is declared as follows.

FLOAT_DECLARATION: #declare IDENTIFIER = EXPRESSION; | #local IDENTIFIER = EXPRESSION;

Where *IDENTIFIER* is valid identifier name and *EXPRESSION* is any valid expression which
evaluates to a float value.

**Note:** There should be a semi-colon after the expression in a float declaration. If omitted, it generates a warning and some macros may not work properly.

See also: Identifiers and #declare vs. #local for additional information on identifier naming and scope.

Here are some examples.

#declare Count = 0; #declare Rows = 5.3; #declare Cols = 6.15; #declare Number = Rows*Cols; #declare Count = Count+1;

As the last example shows, you can re-declare a float identifier and may use previously declared values in that re-declaration. There are several built-in identifiers which POV-Ray declares for you. See Float Expressions: Built-in Variables for details.

## Operators

**Arithmetic expressions:** Basic math expressions can be
created from float literals, identifiers or functions using the following
operators in this order of precedence...

`( )` |
expressions in parentheses first |

`+A -A !A` |
unary minus, unary plus and logical not |

`A*B A/B` |
multiplication and division |

`A+B A-B` |
addition and subtraction |

Relational, logical and conditional expressions may also be created. However there is a restriction that these types of expressions must be enclosed in parentheses first. This restriction, which is not imposed by most computer languages, is necessary because POV-Ray allows mixing of float and vector expressions. Without the parentheses there is an ambiguity problem. Parentheses are not required for the unary logical not operator "!" as shown above. The operators and their precedence are shown here.

** Relational expressions:** The operands are arithmetic
expressions and the result is always boolean with 1 for true and 0 for false.
All relational operators have the same precedence.

`(A < B)` |
A is less than B |

`(A <= B)` |
A is less than or equal to B |

`(A = B)` |
A is equal to B (actually abs(A-B)<EPSILON) |

`(A != B)` |
A is not equal to B (actually abs(A-B)>=EPSILON) |

`(A >= B)` |
A is greater than or equal to B |

`(A > B)` |
A is greater than B |

**Logical expressions:** The operands are converted to
boolean values of 0 for false and 1 for true. The result is always boolean.
All logical operators have the same precedence.

**Note:** These are not
bit-wise operations, they are logical.

`(A & B)` |
true only if both A and B are true, false otherwise |

`(A | B)` |
true if either A or B or both are true |

**Conditional expressions:** The operand C is boolean while
operands A and B are any expressions. The result is of the same type as A and
B.

`(C ? A : B)` |
if C then A else B |

Assuming the various identifiers have been declared, the following are examples of valid expressions...

1+2+3 2*5 1/3 Row*3 Col*5 (Offset-5)/2 This/That+Other*Thing ((This<That) & (Other>=Thing)?Foo:Bar)

Expressions are evaluated left to right with innermost parentheses evaluated first, then unary +, - or !, then multiply or divide, then add or subtract, then relational, then logical, then conditional.

## Functions

POV-Ray defines a variety of built-in functions for manipulating floats, vectors and strings. Function calls consist of a keyword which specifies the name of the function followed by a parameter list enclosed in parentheses. Parameters are separated by commas. For example:

keyword(param1,param2)

The following are the functions which return float values. They take one
or more float, integer, vector, or string parameters. Assume that ```
A
```

and `B`

are any valid expression that evaluates to a
float; `I`

is a float which is truncated to integer internally,
`S`

, `S1`

, `S2`

etc. are strings, and ```
V
```

, `V1`

, `V2`

etc. are any vector
expressions.`O`

is an object identifier to a pre-declared object.

`abs(A)`

Absolute value of `A`

. If `A`

is negative, returns `-A`

otherwise returns `A`

.

`acos(A)`

Arc-cosine of `A`

. Returns the angle, measured in radians, whose cosine is `A`

.

`acosh(A)`

Inverse hyperbolic cosine of `A`

.

`asc(S)`

Returns an integer value in the range 0 to 255 that is the ASCII value of the first character of the string `S`

. For example `asc("ABC")`

is 65 because that is the value of the character "A".

`asin(A)`

Arc-sine of `A`

. Returns the angle, measured in radians, whose sine is `A`

.

`asinh(A)`

Inverse hyperbolic sine of `A`

`atan2(A,B)`

Arc-tangent of `(A/B)`

. Returns the angle, measured in radians, whose tangent is `(A/B)`

. Returns appropriate value even if `B`

is zero. Use `atan2(A,1)`

to compute usual atan(A) function.

`atanh(A)`

Inverse hyperbolic tangent of `A`

`bitwise_and(A,B,...)`

Bitwise *AND* of two or more float values considered as integers.

`bitwise_or(A,B,...)`

Bitwise *OR* of two or more float values considered as integers.

`bitwise_xor(A,B,...)`

Bitwise *XOR* of two or more float values considered as integers.

**Note:** For the three bit-wise functions, each parameter is first converted to integer (so fractional part is ignored), and the computation is performed on a classical int. Do not expect to much precision, as conversion from a double precision number (usually with 52 bits mantissa) to an integer and back to a double precision number is not the best way to keep track of every bit.

`ceil(A)`

Ceiling of `A`

. Returns the smallest integer greater than `A`

. Rounds up to the next higher integer.

`cos(A)`

Cosine of `A`

. Returns the cosine of the angle `A`

, where `A`

is measured in radians.

`cosh(A)`

The hyperbolic cosine of `A`

.

`defined(`

*IDENTIFIER*`)`

Returns `true`

if the identifier is currently defined, `false`

otherwise. This is especially useful for detecting end-of-file after a `#read`

directive because the file identifier is automatically undefined when end-of-file is reached. See The #read Directive for details.

`degrees(A)`

Convert radians to degrees. Returns the angle measured in degrees whose value in radians is `A`

. Formula is *degrees=A/pi*180.0*.

`dimensions(`

*ARRAY_IDENTIFIER* `)`

Returns the number of dimensions of a previously declared array identifier. For example if you do `#declare MyArray=array[6][10]`

then `dimensions(MyArray)`

returns the value `2`

.

`dimension_size(`

* ARRAY_IDENTIFIER, FLOAT* `)`

Returns the size of a given dimension of a previously declared array identifier. Dimensions are numbered left-to-right starting with 1. For example if you do `#declare MyArray=array[6][10]`

then `dimension_size(MyArray,2)`

returns the value `10`

.

`div(A,B)`

Integer division. The integer part of `(A/B)`

.

`exp(A)`

Exponential of `A`

. Returns the value of * e* raised to the power `A`

where *e* is the base of the natural logarithm, i.e. the non-repeating value approximately equal to 2.71828182846.

`file_exists(S)`

Attempts to open the file specified by the string `S`

. The current directory and all library directories specified by the `Library_Path`

or `+L`

options are also searched. See Library Paths for details. Returns `1`

if successful and `0`

if unsuccessful.

`floor(A)`

Floor of `A`

. Returns the largest integer less than `A`

. Rounds down to the next lower integer.

`inside(O,V)`

It returns either 0.0, when the vector `V`

is outside the object, specified by the object-identifier `O`

, or 1.0 if it is inside.

**Note:** The `inside`

keyword does not accept object-identifiers to non-solid objects.

`int(A)`

Integer part of `A`

. Returns the truncated integer part of `A`

. Rounds towards zero.

`log(A)`

Logarithm of `A`

. Returns the logarithm base *10* of the value `A`

.

`ln(A)`

Natural logarithm of `A`

. Returns the natural logarithm base *e* of the value `A`

.

`max(A,B,...)`

Maximum of two or more float values. Returns `A`

if `A`

larger than `B`

. Otherwise returns `B`

.

`min(A,B,...)`

Minimum of two or more float values. Returns `A`

if `A`

smaller than `B`

. Otherwise returns `B`

.

`mod(A,B)`

Value of `A`

modulo `B`

. Returns the remainder after the integer division of `A`

/`B`

. Formula is * mod=((A/B)-int(A/B))*B*.

`pow(A,B)`

Exponentiation. Returns the value of `A`

raised to the power `B`

.

**Note:** For a negative A and a non-integer B the function has no defined return value. The result then may depend on the platform POV-Ray is compiled on.

`radians(A)`

Convert degrees to radians. Returns the angle measured in radians whose value in degrees is `A`

. Formula is *radians=A*pi/180.0*.

`rand(I)`

Returns the next pseudo-random number from the stream specified by the positive integer `I`

. You must call `seed()`

to initialize a random stream before calling `rand()`

. The numbers are uniformly distributed, and have values between `0.0`

and `1.0`

, inclusively. The numbers generated by separate streams are independent random variables.

`seed(I)`

Initializes a new pseudo-random stream with the initial seed value `I`

. The number corresponding to this random stream is returned. Any number of pseudo-random streams may be used as shown in the example below:

#declare R1 = seed(0); #declare R2 = seed(12345); sphere { <rand(R1), rand(R1), rand(R1)>, rand(R2) }

Multiple random generators are very useful in situations where you use `rand()`

to place a group of objects, and then decide to use `rand()`

in another location earlier in the file to set some colors or place another group of objects. Without separate `rand()`

streams, all of your objects would move when you added more calls to `rand()`

. This is very annoying.

`select(A, B, C [,D])`

It can be used with three or four parameters `Select`

compares the first argument with zero, depending on the outcome it will return `B`

, `C`

or `D`

. `A,B,C,D`

can be floats or funtions.

When used with three parameters, if `A < 0`

it will return `B`

, else `C`

(`A >= 0`

).

When used with four parameters, if `A < 0`

it will return B. If `A = 0`

it will return `C`

. Else it will return `D`

(`A > 0`

).

Example:

If `A`

has the consecutive values -2, -1, 0, 1, and 2 :

// A = -2 -1 0 1 2 select (A, -1, 0, 1) //returns -1 -1 0 1 1 select (A, -1, 1) //returns -1 -1 1 1 1

`sin(A)`

Sine of `A`

. Returns the sine of the angle `A`

, where `A`

is measured in radians.

`sinh(A)`

The hyperbolic sine of `A`

.

`strcmp(S1,S2)`

Compare string `S1`

to `S2`

. Returns a float value zero if the strings are equal, a positive number if `S1`

comes after `S2`

in the ASCII collating sequence, else a negative number.

`strlen(S)`

Length of `S`

. Returns an integer value that is the number of characters in the string `S`

.

`sqrt(A)`

Square root of `A`

. Returns the value whose square is `A`

.

`tan(A)`

Tangent of `A`

. Returns the tangent of the angle `A`

, where `A`

is measured in radians.

`tanh(A)`

The hyperbolic tangent of `A`

.

`val(S)`

Convert string `S`

to float. Returns a float value that is represented by the text in string `S`

. For example `val("123.45")`

is 123.45 as a float.

`vdot(V1,V2)`

Dot product of `V1`

and `V2`

. Returns a float value that is the dot product (sometimes called scalar product) of `V1`

with `V2`

. It is directly proportional to the length of the two vectors and the cosine of the angle between them. Formula is *vdot=V1.x*V2.x + V1.y*V2.y + V1.z*V2.z.* See the animated demo scene `VECT2.POV`

for an illustration.

`vlength(V)`

Length of `V`

. Returns a float value that is the length of vector `V`

. Formula is *vlength=sqrt(vdot(A,A))*. Can be used to compute the distance between two points. `Dist=vlength(V2-V1)`

.

See section Vector Functions and section String Functions for other functions which are somewhat float-related but which return vectors and strings. In addition to the above built-in functions, you may also define your own functions using the `function`

keyword. See the section User-Defined Functions for more details.

## Built-in Constants

Constants are:

FLOAT_BUILT_IN_IDENT: false | no | off | on | pi | tau | true | yes

The built-in constants never change value. They are defined as though the following lines were at the start of every scene.

#declare pi = 3.1415926535897932384626; #declare tau = 6.2831853071795864769253; #declare true = 1; #declare yes = 1; #declare on = 1; #declare false = 0; #declare no = 0; #declare off = 0;

The built-in float identifier `pi`

is obviously useful in math
expressions involving circles. The built-in float identifiers ```
on
```

, `off`

, `yes`

, `no`

, ```
true
```

, and `false`

are designed for use as boolean
constants.

New in version 3.8 the `tau`

constant can be used as a more convenient and intuitive alternative to `2*pi`

to express a full (360 degrees) turn in radians.

The built-in float constants `on`

, `off`

, `yes`

, `no`

, `true`

, and `false`

are most often used as boolean values with object modifiers or parameters such as `sturm`

, `hollow`

, `hierarchy`

, `smooth`

, `media_attenuation`

, and `media_interaction`

. Whenever you see syntax of the form `keyword`

* [Bool]*, if you simply specify the keyword without the optional boolean then it assumes

`keyword on`

. You need not use the boolean but for readability it is a good idea. You must use one of the false booleans or an expression which evaluates to zero to turn it off.**Note:** Some of these keywords are `on`

by default, if no keyword is specified.

For example:

object { MyBlob } // sturm defaults off, but // hierarchy defaults on object { MyBlob sturm } // turn sturm on object { MyBlob sturm on } // turn sturm on object { MyBlob sturm off } // turn sturm off object { MyBlob hierarchy } // does nothing, hierarchy was // already on object { MyBlob hierarchy off } // turn hierarchy off

## Built-in Variables

There are several built-in float variables. You can use them to specify values or to create expressions but you cannot re-declare them to change their values.

Clock-related are:

FLOAT_BUILT-IN_IDENT: clock | clock_delta | clock_on | final_clock | final_frame frame_number | initial_clock | initial_frame

These keywords allow to use the values of the clock which have been set in the command line switch options (or INI-file). They represent float or integer values, read from the animation options. You cannot re-declare these identifiers.

`clock`

The built-in float identifier `clock`

is used to control
animations in POV-Ray. Unlike some animation packages, the action in POV-Ray
animated scenes does not depend upon the integer frame numbers. Rather you
should design your scenes based upon the float identifier ```
clock
```

. For non-animated scenes its default value is 0 but you can set
it to any float value using the INI file option `Clock=`

*n.n*
or the command-line switch `+K`

*n.n* to pass a single float
value your scene file.

Other INI options and switches may be used to animate scenes by automatically
looping through the rendering of frames using various values for `clock`

.
By default, the clock value is 0 for the initial frame and 1 for the final frame. All other
frames are interpolated between these values.

For example if your object is supposed to rotate one full turn over the course
of the animation you could specify `rotate 360*clock*y`

. Then as
clock runs from 0 to 1, the object rotates about the y-axis from 0 to 360 degrees.

Although the value of `clock`

will change from frame-to-frame,
it will never change throughout the parsing of a scene.

`clock_delta`

The built-in float identifier `clock_delta`

returns the amount
of time between clock values in animations in POV-Ray. While most animations
only need the clock value itself, some animation calculations are easier if
you know how long since the last frame. Caution must be used when designing
such scenes. If you render a scene with too few frames, the results may be
different than if you render with more frames in a given time period. On
non-animated scenes, `clock_delta`

defaults to 0. See the section
Animation Options for more details.

`clock_on`

With this identifier the status of the clock can be checked: 1 is on, 0 is off.

#if(clock_on=0) //stuff for still image #else //some animation #end

`frame_number`

If you rather want to define the action in POV-Ray animated scenes depending upon the integer frame numbers, this identifier can be used. It reads the number of the frame currently being rendered.

#if(frame_number=1) //stuff for first image or frame #end #if(frame_number=2) //stuff for second image or frame #end #if(frame_number=n) //stuff for n th image or frame #end

`initial_clock`

This identifier reads the value set through the INI file option `Initial_Clock=`

*n.n*
or the command-line switch `+KI`

*n.n*.

`final_clock`

This identifier reads the value set through the INI file option `Final_Clock=`

*n.n*
or the command-line switch `+KF`

*n.n*.

`initial_frame`

This identifier reads the value set through the INI file option `Initial_Frame=`

*n*
or the command-line switch `+KFI`

*n*.

`final_frame`

This identifier reads the value set through the INI file option `Final_Frame=`

*n*
or the command-line switch `+KFF`

*n*.

**Note:** These values are the ones actually used. When the option 'cyclic animation' is set,
they could be different from the ones originally set in the options.

Image-size are:

FLOAT_BUILT-IN_IDENT: image_width | image_height

`image_width`

This identifier reads the value set through the INI file option `Width=`

*n*
or the command-line switch `+W`

*n*.

`image_height`

This identifier reads the value set through the INI file option `Height=`

*n*
or the command-line switch `+H`

*n*.

You could use these keywords to set the camera ratio (up and right vectors) correctly. The viewing angle of the camera covers the full width of the rendered image. The camera ratio will always follow the ratio of the image width to height, regardless of the set image size. Use it like this:

up y*image_height right x*image_width

You could also make some items of the scene dependent on the image size:

#if (image_width < 300) crand 0.1 #else crand 0.5 #end or: image_map { pattern image_width, image_width { //make pattern resolution gradient x //dependent of render width color_map { [ 0.0 ... ] [ 1.0 ... ] } } }

Miscellaneous are:

FLOAT_BUILT-IN_IDENT: now | version

The built-in float variable `now`

returns a value specifying
the current date and time, given in days since 2000-01-01 00:00:00 GMT, at
a precision of seconds or better.

Among other things, this variable is primarily intended to be used in the following constructs:

#local CurrentTime = datetime(now); // current date and time as a string #local Random = seed(now*24*60*60); // get a different random sequence for each render

**Note:** The value of this variable changes over time
as parsing progresses.

The built-in float variable `version`

contains the current
setting of the version compatibility option. Although this value defaults to
the current POV-Ray version number, the initial value of ```
version
```

may be set by the INI file option ```
Version=
```

*n.n* or by the `+MV`

*n.n*
command-line switch. This tells POV-Ray to parse the scene file using syntax
from an earlier version of POV-Ray.

The INI option or switch only affects the initial setting. Unlike other built-in identifiers, you may change the value of `version`

throughout a scene file. You do not use `#declare`

to change it though. The `#version`

language directive is used to change modes. Such changes may occur several times within scene files.

Together with the built-in `version`

identifier the `#version`

directive allows you to save and restore the previous values of this compatibility setting. The new `#local`

identifier option is especially useful here. For example suppose `mystuff.inc`

is in *version 3.5* format. At the top of the file you could put:

#local Temp_Vers = version; // Save previous value #version 3.5; // Change to 3.5 mode ... // Version 3.5 stuff goes here... #version Temp_Vers; // Restore previous version

**Note:** There should be a semi-colon after the
float expression in a `#version`

directive. If omitted, it generates
a warning and some macros may not work properly.

**Note:** As of POV-Ray 3.7, the version compatibility option
defaults to 3.62 rather than the actual software version. However, in POV-Ray 3.7.0,
`version`

defaults to the actual software version. This is a Change in
POV-Ray 3.8 so that `version`

generally reflects the version compatibility option
even in the default case, except when used inside the very first `#version`

statement where it still defaults to the actual software version. Therefore, to identify
POV-Ray version 3.8 or higher, you will need to start your scene file with the following
construct:

#version version;