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