xref: /freebsd-src/contrib/bc/scripts/sqrt_random.bc (revision a970610a3af63b3f4df5b69d91c6b4093a00ed8f)
1f4fbc49dSStefan Eßer#! /usr/bin/bc
2f4fbc49dSStefan Eßer#
3f4fbc49dSStefan Eßer# SPDX-License-Identifier: BSD-2-Clause
4f4fbc49dSStefan Eßer#
5*a970610aSStefan Eßer# Copyright (c) 2018-2024 Gavin D. Howard and contributors.
6f4fbc49dSStefan Eßer#
7f4fbc49dSStefan Eßer# Redistribution and use in source and binary forms, with or without
8f4fbc49dSStefan Eßer# modification, are permitted provided that the following conditions are met:
9f4fbc49dSStefan Eßer#
10f4fbc49dSStefan Eßer# * Redistributions of source code must retain the above copyright notice, this
11f4fbc49dSStefan Eßer#   list of conditions and the following disclaimer.
12f4fbc49dSStefan Eßer#
13f4fbc49dSStefan Eßer# * Redistributions in binary form must reproduce the above copyright notice,
14f4fbc49dSStefan Eßer#   this list of conditions and the following disclaimer in the documentation
15f4fbc49dSStefan Eßer#   and/or other materials provided with the distribution.
16f4fbc49dSStefan Eßer#
17f4fbc49dSStefan Eßer# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18f4fbc49dSStefan Eßer# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19f4fbc49dSStefan Eßer# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20f4fbc49dSStefan Eßer# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21f4fbc49dSStefan Eßer# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22f4fbc49dSStefan Eßer# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23f4fbc49dSStefan Eßer# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24f4fbc49dSStefan Eßer# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25f4fbc49dSStefan Eßer# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26f4fbc49dSStefan Eßer# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27f4fbc49dSStefan Eßer# POSSIBILITY OF SUCH DAMAGE.
28f4fbc49dSStefan Eßer#
29f4fbc49dSStefan Eßer
30f4fbc49dSStefan Eßerscale = 0
31f4fbc49dSStefan Eßer
32f4fbc49dSStefan Eßerbits = rand()
33f4fbc49dSStefan Eßer
34f4fbc49dSStefan Eßer# This extracts a bit and takes it out of the original value.
35f4fbc49dSStefan Eßer#
36f4fbc49dSStefan Eßer# Here, I am getting a bit to say whether we should have a value that is less
37f4fbc49dSStefan Eßer# than 1.
38f4fbc49dSStefan Eßerbits = divmod(bits, 2, negpow[])
39f4fbc49dSStefan Eßer
40f4fbc49dSStefan Eßer# Get a bit that will say whether the value should be an exact square.
41f4fbc49dSStefan Eßerbits = divmod(bits, 2, square[])
42f4fbc49dSStefan Eßer
43f4fbc49dSStefan Eßer# See below. This is to help bias toward small numbers.
44f4fbc49dSStefan Eßerpow = 4
45f4fbc49dSStefan Eßer
46f4fbc49dSStefan Eßer# I want to bias toward small numbers, so let's give a 50 percent chance to
47f4fbc49dSStefan Eßer# values below 16 or so.
48f4fbc49dSStefan Eßerbits = divmod(bits, 2, small[])
49f4fbc49dSStefan Eßer
50f4fbc49dSStefan Eßer# Let's keep raising the power limit by 2^4 when the bit is zero.
51f4fbc49dSStefan Eßerwhile (!small[0])
52f4fbc49dSStefan Eßer{
53f4fbc49dSStefan Eßer	pow += 4
54f4fbc49dSStefan Eßer	bits = divmod(bits, 2, small[])
55f4fbc49dSStefan Eßer}
56f4fbc49dSStefan Eßer
57f4fbc49dSStefan Eßerlimit = 2^pow
58f4fbc49dSStefan Eßer
59f4fbc49dSStefan Eßer# Okay, this is the starting number.
60f4fbc49dSStefan Eßernum = irand(limit) + 1
61f4fbc49dSStefan Eßer
62f4fbc49dSStefan Eßer# Figure out if we should have (more) fractional digits.
63f4fbc49dSStefan Eßerbits = divmod(bits, 2, extra_digits[])
64f4fbc49dSStefan Eßer
65f4fbc49dSStefan Eßerif (square[0])
66f4fbc49dSStefan Eßer{
67f4fbc49dSStefan Eßer	# Okay, I lied. If we need a perfect square, square now.
68f4fbc49dSStefan Eßer	num *= num
69f4fbc49dSStefan Eßer
70f4fbc49dSStefan Eßer	# If we need extra digits, we need to multiply by an even power of 10.
71f4fbc49dSStefan Eßer	if (extra_digits[0])
72f4fbc49dSStefan Eßer	{
73f4fbc49dSStefan Eßer		extra = (irand(8) + 1) * 2
74f4fbc49dSStefan Eßer	}
75f4fbc49dSStefan Eßer	else
76f4fbc49dSStefan Eßer	{
77f4fbc49dSStefan Eßer		extra = 0
78f4fbc49dSStefan Eßer	}
79f4fbc49dSStefan Eßer
80f4fbc49dSStefan Eßer	# If we need a number less than 1, just take the inverse, which will still
81f4fbc49dSStefan Eßer	# be a perfect square.
82f4fbc49dSStefan Eßer	if (negpow[0])
83f4fbc49dSStefan Eßer	{
84f4fbc49dSStefan Eßer		scale = length(num) + 5
85f4fbc49dSStefan Eßer		num = 1/num
86f4fbc49dSStefan Eßer		scale = 0
87f4fbc49dSStefan Eßer
88f4fbc49dSStefan Eßer		num >>= extra
89f4fbc49dSStefan Eßer	}
90f4fbc49dSStefan Eßer	else
91f4fbc49dSStefan Eßer	{
92f4fbc49dSStefan Eßer		num <<= extra
93f4fbc49dSStefan Eßer	}
94f4fbc49dSStefan Eßer}
95f4fbc49dSStefan Eßerelse
96f4fbc49dSStefan Eßer{
97f4fbc49dSStefan Eßer	# Get this for later.
98f4fbc49dSStefan Eßer	l = length(num)
99f4fbc49dSStefan Eßer
100f4fbc49dSStefan Eßer	# If we need extra digits.
101f4fbc49dSStefan Eßer	if (extra_digits[0])
102f4fbc49dSStefan Eßer	{
103f4fbc49dSStefan Eßer		# Add up to 32 decimal places.
104f4fbc49dSStefan Eßer		num += frand(irand(32) + 1)
105f4fbc49dSStefan Eßer	}
106f4fbc49dSStefan Eßer
107f4fbc49dSStefan Eßer	# If we need a value less than 1...
108f4fbc49dSStefan Eßer	if (negpow[0])
109f4fbc49dSStefan Eßer	{
110f4fbc49dSStefan Eßer		# Move right until the number is
111f4fbc49dSStefan Eßer		num >>= l
112f4fbc49dSStefan Eßer	}
113f4fbc49dSStefan Eßer}
114f4fbc49dSStefan Eßer
115f4fbc49dSStefan Eßerbits = divmod(bits, 2, zero_scale[])
116f4fbc49dSStefan Eßer
117f4fbc49dSStefan Eßer# Do we want a zero scale?
118f4fbc49dSStefan Eßerif (zero_scale[0])
119f4fbc49dSStefan Eßer{
120f4fbc49dSStefan Eßer	print "scale = 0\n"
121f4fbc49dSStefan Eßer}
122f4fbc49dSStefan Eßerelse
123f4fbc49dSStefan Eßer{
124f4fbc49dSStefan Eßer	print "scale = 20\n"
125f4fbc49dSStefan Eßer}
126f4fbc49dSStefan Eßer
127f4fbc49dSStefan Eßerprint "sqrt(", num, ")\n"
128f4fbc49dSStefan Eßer
129f4fbc49dSStefan Eßerhalt
130