17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 23*5d54f3d8Smuffin * Copyright 1988 Sun Microsystems, Inc. All rights reserved. 24*5d54f3d8Smuffin * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 27*5d54f3d8Smuffin #pragma ident "%Z%%M% %I% %E% SMI" 28*5d54f3d8Smuffin 297c478bd9Sstevel@tonic-gate /* Special version adapted from libm for use in libc. */ 307c478bd9Sstevel@tonic-gate 31*5d54f3d8Smuffin static int n0 = 0, n1 = 1; 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate static double two52 = 4.503599627370496000E+15; 347c478bd9Sstevel@tonic-gate static double twom52 = 2.220446049250313081E-16; 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate static double 37*5d54f3d8Smuffin setexception(int n, double x) 387c478bd9Sstevel@tonic-gate { 39*5d54f3d8Smuffin return (0.0); 407c478bd9Sstevel@tonic-gate } 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate double 43*5d54f3d8Smuffin copysign(double x, double y) 447c478bd9Sstevel@tonic-gate { 457c478bd9Sstevel@tonic-gate long *px = (long *) &x; 467c478bd9Sstevel@tonic-gate long *py = (long *) &y; 477c478bd9Sstevel@tonic-gate px[n0] = (px[n0] & 0x7fffffff) | (py[n0] & 0x80000000); 48*5d54f3d8Smuffin return (x); 497c478bd9Sstevel@tonic-gate } 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate static double 52*5d54f3d8Smuffin fabs(double x) 537c478bd9Sstevel@tonic-gate { 547c478bd9Sstevel@tonic-gate long *px = (long *) &x; 557c478bd9Sstevel@tonic-gate px[0] &= 0x7fffffff; 56*5d54f3d8Smuffin 57*5d54f3d8Smuffin return (x); 587c478bd9Sstevel@tonic-gate } 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate static int 61*5d54f3d8Smuffin finite(double x) 627c478bd9Sstevel@tonic-gate { 637c478bd9Sstevel@tonic-gate long *px = (long *) &x; 647c478bd9Sstevel@tonic-gate return ((px[n0] & 0x7ff00000) != 0x7ff00000); 657c478bd9Sstevel@tonic-gate } 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate static int 68*5d54f3d8Smuffin ilogb(double x) 697c478bd9Sstevel@tonic-gate { 707c478bd9Sstevel@tonic-gate long *px = (long *) &x, k; 717c478bd9Sstevel@tonic-gate k = px[n0] & 0x7ff00000; 727c478bd9Sstevel@tonic-gate if (k == 0) { 737c478bd9Sstevel@tonic-gate if ((px[n1] | (px[n0] & 0x7fffffff)) == 0) 74*5d54f3d8Smuffin return (0x80000001); 757c478bd9Sstevel@tonic-gate else { 767c478bd9Sstevel@tonic-gate x *= two52; 777c478bd9Sstevel@tonic-gate return ((px[n0] & 0x7ff00000) >> 20) - 1075; 787c478bd9Sstevel@tonic-gate } 797c478bd9Sstevel@tonic-gate } else if (k != 0x7ff00000) 807c478bd9Sstevel@tonic-gate return (k >> 20) - 1023; 817c478bd9Sstevel@tonic-gate else 82*5d54f3d8Smuffin return (0x7fffffff); 837c478bd9Sstevel@tonic-gate } 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate static double 86*5d54f3d8Smuffin scalbn(double x, int n) 877c478bd9Sstevel@tonic-gate { 887c478bd9Sstevel@tonic-gate long *px = (long *) &x, k; 897c478bd9Sstevel@tonic-gate double twom54 = twom52 * 0.25; 907c478bd9Sstevel@tonic-gate k = (px[n0] & 0x7ff00000) >> 20; 917c478bd9Sstevel@tonic-gate if (k == 0x7ff) 92*5d54f3d8Smuffin return (x + x); 937c478bd9Sstevel@tonic-gate if ((px[n1] | (px[n0] & 0x7fffffff)) == 0) 94*5d54f3d8Smuffin return (x); 957c478bd9Sstevel@tonic-gate if (k == 0) { 967c478bd9Sstevel@tonic-gate x *= two52; 977c478bd9Sstevel@tonic-gate k = ((px[n0] & 0x7ff00000) >> 20) - 52; 987c478bd9Sstevel@tonic-gate } 997c478bd9Sstevel@tonic-gate k = k + n; 1007c478bd9Sstevel@tonic-gate if (n > 5000) 101*5d54f3d8Smuffin return (setexception(2, x)); 1027c478bd9Sstevel@tonic-gate if (n < -5000) 103*5d54f3d8Smuffin return (setexception(1, x)); 1047c478bd9Sstevel@tonic-gate if (k > 0x7fe) 105*5d54f3d8Smuffin return (setexception(2, x)); 1067c478bd9Sstevel@tonic-gate if (k <= -54) 107*5d54f3d8Smuffin return (setexception(1, x)); 1087c478bd9Sstevel@tonic-gate if (k > 0) { 1097c478bd9Sstevel@tonic-gate px[n0] = (px[n0] & 0x800fffff) | (k << 20); 110*5d54f3d8Smuffin return (x); 1117c478bd9Sstevel@tonic-gate } 1127c478bd9Sstevel@tonic-gate k += 54; 1137c478bd9Sstevel@tonic-gate px[n0] = (px[n0] & 0x800fffff) | (k << 20); 114*5d54f3d8Smuffin return (x * twom54); 1157c478bd9Sstevel@tonic-gate } 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate double 118*5d54f3d8Smuffin fmod(double x, double y) 1197c478bd9Sstevel@tonic-gate { 1207c478bd9Sstevel@tonic-gate int ny, nr; 1217c478bd9Sstevel@tonic-gate double r, z, w; 122*5d54f3d8Smuffin 1237c478bd9Sstevel@tonic-gate int finite(), ilogb(); 1247c478bd9Sstevel@tonic-gate double fabs(), scalbn(), copysign(); 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate /* purge off exception values */ 1277c478bd9Sstevel@tonic-gate if (!finite(x) || y != y || y == 0.0) { 128*5d54f3d8Smuffin return ((x * y) / (x * y)); 1297c478bd9Sstevel@tonic-gate } 1307c478bd9Sstevel@tonic-gate /* scale and subtract to get the remainder */ 1317c478bd9Sstevel@tonic-gate r = fabs(x); 1327c478bd9Sstevel@tonic-gate y = fabs(y); 1337c478bd9Sstevel@tonic-gate ny = ilogb(y); 1347c478bd9Sstevel@tonic-gate while (r >= y) { 1357c478bd9Sstevel@tonic-gate nr = ilogb(r); 1367c478bd9Sstevel@tonic-gate if (nr == ny) 1377c478bd9Sstevel@tonic-gate w = y; 1387c478bd9Sstevel@tonic-gate else { 1397c478bd9Sstevel@tonic-gate z = scalbn(y, nr - ny - 1); 1407c478bd9Sstevel@tonic-gate w = z + z; 1417c478bd9Sstevel@tonic-gate } 1427c478bd9Sstevel@tonic-gate if (r >= w) 1437c478bd9Sstevel@tonic-gate r -= w; 1447c478bd9Sstevel@tonic-gate else 1457c478bd9Sstevel@tonic-gate r -= z; 1467c478bd9Sstevel@tonic-gate } 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate /* restore sign */ 149*5d54f3d8Smuffin return (copysign(r, x)); 1507c478bd9Sstevel@tonic-gate } 151