summary refs log tree commit diff stats
path: root/compiler/saturate.nim
blob: 065cb512847d2739286645cd27713a4e1dc3950a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#
#
#           The Nim Compiler
#        (c) Copyright 2012 Andreas Rumpf
#
#    See the file "copying.txt", included in this
#    distribution, for details about the copyright.
#

## Saturated arithmetic routines. XXX Make part of the stdlib?

proc `|+|`*(a, b: BiggestInt): BiggestInt =
  ## saturated addition.
  result = a +% b
  if (result xor a) >= 0'i64 or (result xor b) >= 0'i64:
    return result
  if a < 0 or b < 0:
    result = low(result)
  else:
    result = high(result)

proc `|-|`*(a, b: BiggestInt): BiggestInt =
  result = a -% b
  if (result xor a) >= 0'i64 or (result xor not b) >= 0'i64:
    return result
  if b > 0:
    result = low(result)
  else:
    result = high(result)

proc `|abs|`*(a: BiggestInt): BiggestInt =
  if a != low(a):
    if a >= 0: result = a
    else: result = -a
  else:
    result = low(a)

proc `|div|`*(a, b: BiggestInt): BiggestInt =
  # (0..5) div (0..4) == (0..5) div (1..4) == (0 div 4) .. (5 div 1)
  if b == 0'i64:
    # make the same as ``div 1``:
    result = a
  elif a == low(a) and b == -1'i64:
    result = high(result)
  else:
    result = a div b

proc `|mod|`*(a, b: BiggestInt): BiggestInt =
  if b == 0'i64:
    result = a
  else:
    result = a mod b

proc `|*|`*(a, b: BiggestInt): BiggestInt =
  var
    resAsFloat, floatProd: float64
  result = a *% b
  floatProd = toBiggestFloat(a) # conversion
  floatProd = floatProd * toBiggestFloat(b)
  resAsFloat = toBiggestFloat(result)

  # Fast path for normal case: small multiplicands, and no info
  # is lost in either method.
  if resAsFloat == floatProd: return result

  # Somebody somewhere lost info. Close enough, or way off? Note
  # that a != 0 and b != 0 (else resAsFloat == floatProd == 0).
  # The difference either is or isn't significant compared to the
  # true value (of which floatProd is a good approximation).

  # abs(diff)/abs(prod) <= 1/32 iff
  #   32 * abs(diff) <= abs(prod) -- 5 good bits is "close enough"
  if 32.0 * abs(resAsFloat - floatProd) <= abs(floatProd):
    return result

  if floatProd >= 0.0:
    result = high(result)
  else:
    result = low(result)
and use that in place of the existing one. See `terminfo', `infocmp', `tic' etc. man pages if necessary. Alternatively, compiling Lynx with the slang library may avoid problems with these terminals. The Sun console driver (aka wscons(7)) implements "reverse" and "bold" as "reverse", causing confusion where Lynx uses the distinction between the two to convey information. Lynx tries to detect this automatically, but if it fails (for instance, you are running under "screen"), try setting the -noreverse commandline option. --------- On VMS, Lynx, and other TCP-IP software, have been experiencing chronic problems of incompatibilities between DECC and MultiNet headers whenever new versions of either DECC or MultiNet are released. The Lynx build procedure for VMS and a maze of spaghetti #ifdef-ing in tcp.h of the libwww-FM had previously been successful in dealing with this problem across all versions of MultiNet and of DECC, VAXC, and Pat Rankin's VMS port of GNUC, but are now not 100% successful. If you get compiler messages about "struct timeval timeout" having no linkage, add that declaration immediately below the inclusion of ioctl.h for MultiNet in tcp.h (by deleting the "#ifdef NOT_DEFINED" and "#endif /* NOT_DEFINED */" lines): [...] #include "multinet_root:[multinet.include.sys]ioctl.h" struct timeval { long tv_sec; /* seconds since Jan. 1, 1970 */ long tv_usec; /* microseconds */ }; [...] If you get compiler warnings about incompatible multinet_foo() declarations, delete those where indicated in tcp.h. For the most current versions of MultiNet, you can modify tcp.h to use the DECC socket and related headers. On VMS, the ftp function does not work with SOCKETSHR 0.9D and NETLIB 2 (NETLIB 1 may work). This is because the functions getsockname() and getpeername() within SOCKETSHR make incorrect calls to the NETLIB functions. This results in zeroes being returned for part of the local IP address. Since ftp sends this IP address to the remote end, the remote server ends up sending a file back to a non-existent address. Andy Harper (A.HARPER@kcl.ac.uk) has fixed these problems in the SOCKETSHR 0.9D sources and offers the fixes as: http://alder.cc.kcl.ac.uk/fileserv/zip/socketshr_src_09d-2.zip ftp://ftp2.kcl.ac.uk/zip/socketshr_src_09d-2.zip --------- On VMS, to build an SSL-capable version, lynx and the ssl library e.g., OpenSSL, must be built using the same network library. If you build OpenSSL without specifying the network library (the 5th parameter of the makevms.com script), it will guess, possibly not the one you intended. We have tested only the UCX configuration -TD (2002/9/15).