Page 1 of 2

Математические функции

Posted: Wed Feb 28, 2007 6:53 pm
by Serial
Вдохновленный статьей diamond'а, накачал сишных компиляторов и начал экспериментировать. И тут вспомнил, что у меня есть отличная игрушка, написанная мной на c++, которую было бы неплохо портировать в КолибриОС. Взялся за переделку... и тут же столкнулся с проблемой, а именно с отсутствием математических функций в сишных компиляторах, делающих колибри-файлы.
Поэтому прошу помощи в реализации на ассемблере следующих функций: sqrt, cos, acos, sin, round. На сколько мне известно, это довольно-таки легко сделать, используя FPU.
Буду благодарен за любую помощь.

Posted: Wed Feb 28, 2007 7:20 pm
by Heavyiron
Насчет sqrt, cos, acos, sin помогу - стучи в асю или в irc заходи, а про round не слышал - что это вообще?

Posted: Wed Feb 28, 2007 7:20 pm
by andrew_programmer
Ненужно ничего реализовавать - все математические функции уже есть.
Напиши в заголовке твой сишной программы

#include <math.h>

И пользуйся математическими фугкциями.
Я под Linux-ом установил menuetlibc.Написал тестовую программу с использованием математических функций.Скомпилировал и опробовал в Колибри - все отлично работало.

Posted: Wed Feb 28, 2007 7:24 pm
by andrew_programmer
Если надо,то могу выложить скомпилированную библиотеку libc.a для компиляции с использованием GCC или TinyC-compilera.

Posted: Wed Feb 28, 2007 7:25 pm
by k@sTIg@r
Тебе нужно помочь реализовать(я так понял на асме) или просто алгоритмы??? По запросу в гугле на "математические алгоритмы" сразу попал на сайт http://algorithm.narod.ru/
там есть реализация на си алгоритмов тангенса синуса и т.п.

Если именно проблема с реализацией, то конкретно что именно нужно??? Просто написать их? :wink:

Posted: Wed Feb 28, 2007 7:33 pm
by Heavyiron

Posted: Wed Feb 28, 2007 8:22 pm
by Serial
Мдя.. Посмотрел я по-подробнее свой компилятор (cl из VS 2005). Вот на такой код:

Code: Select all

#include "kosSyst.h"
#include "kosFile.h"


void kos_Main()
{
	double id = 10.4;
}
Выдает вот такое:

Code: Select all

LINK : warning LNK4108: /ALIGN specified without /DRIVER; image may not run
game.obj : error LNK2001: unresolved external symbol __fltused
game.exe : fatal error LNK1120: 1 unresolved externals
(естественно все делал как говорилось в вышеупомянутой статье)

Posted: Wed Feb 28, 2007 8:28 pm
by Serial
Тогда какой компилятор необходимо использовать? Мне нужна поддержка ООП и чтобы без проблем подключался math.h с синусами, косинусами...

Posted: Wed Feb 28, 2007 8:53 pm
by diamond
Значит, так.
1. Для компилятора GCC/G++ или Tiny C: библиотека menuetlibc включает в себя математическую библиотеку. Так что можно подключить math.h и спокойно пользоваться математическими функциями.
2. Для компилятора VC++/VS: kosSyst.h не включает реализации математических функций, так что в текущей реализации ими пользоваться нельзя. Проблема не в том, что нет math.h - его как раз-таки подключать можно без проблем, а в отсутствии реализации. Хотя можно попробовать подключить msvcrt.lib (в командной строке - дополнительный аргумент, в GUI есть специальный editbox для подключения объектников и библиотек) в надежде, что линкер не станет страдать фигнёй и подключит только math-библиотеку, которая вроде бы не опирается на WinAPI (зачем бы?). В данный момент сам проверить не могу, так что только советую попробовать.
3. Если строго следовать ANSI C, то реализация sqrt и прочих не может тупо вызывать соответствующие инструкции FPU, а должна иметь кучу обвязочного кода (исходники RTL в VS2005 входят, вроде бы там есть реализация). Всякие там errno, matherr...
NAME
sqrt - square root function

SYNOPSIS
#include <math.h>

double sqrt(double x);

DESCRIPTION
The sqrt() function returns the non-negative square root
of x. It fails and sets errno to EDOM, if x is negative.

ERRORS
EDOM x is negative.
Другой вопрос, что в абсолютном большинстве случаев это не нужно - нормальный программист либо вообще не извлекает корней из отрицательных чисел, либо явным образом проверяет на положительность перед использованием, так что тупой вызов FPU-команды вполне достаточен. Такие реализации можно написать за несколько минут, так что завтра могу выложить.

Да, кстати, для компиляции вышеприведённого текста вполне достаточно объявить

Code: Select all

extern "C" int _fltused;
int _fltused = 0;

Posted: Wed Feb 28, 2007 10:51 pm
by Serial
Вот, что смог написать.. проверил - работает.

Code: Select all

double sin(double x)
{
	__asm	fld	x
	__asm	fsin
}

double cos(double x)
{
	__asm	fld	x
	__asm	fcos
}

double sqrt(double x)
{
	__asm	fld	x
	__asm	fsqrt
}
Остались две функции: арккосинус и округление.

Posted: Wed Feb 28, 2007 11:01 pm
by Serial
Думаю это поможет, тем кто захочет помочь:
ImageImage, при Image
ImageImage, при Image

Posted: Wed Feb 28, 2007 11:21 pm
by Heavyiron
Арксинус:
fld x
fld st0
fmul st,st1
fld1
fsubrp st1,st0
fsqrt
fpatan
Арккосинус:
fld x
fld st0
fmul st,st1
fld1
fsubrp st1,st0
fsqrt
fxch st1
fpatan
Округление до целого:
fld x
frndint
ЗЫ: за формулу респект, поправил калькулятор ;)

Posted: Thu Mar 01, 2007 1:54 am
by Serial
Heavyiron

Code: Select all

double acos(double x)
{
	__asm	fld x
	__asm	fld st0 
	__asm	fmul st,st1 // game.cpp(31) : error C2415: improper operand type
	__asm	fld1 
	__asm	fsubrp st1,st0 // game.cpp(33) : error C2415: improper operand type
	__asm	fsqrt 
	__asm	fstp st2 
	__asm	fpatan
}

Posted: Thu Mar 01, 2007 2:07 am
by Heavyiron
Попробуй вместо st вводить st(0), st1 - st(1)... Просто во всей литературе так, а когда писал функции для фасма он ругался на скобки. Кстати, я заменил fstp st2 в предпоследней строке на fxch st1 - так вроде оптимальней будет

Posted: Thu Mar 01, 2007 12:25 pm
by Serial
Heavyiron wrote:Попробуй вместо st вводить st(0), st1 - st(1)... Просто во всей литературе так, а когда писал функции для фасма он ругался на скобки. Кстати, я заменил fstp st2 в предпоследней строке на fxch st1 - так вроде оптимальней будет
Ура, заработало, спасибо.

И теперь последнее ;)
Функция округления:

Code: Select all

int round(double x)
{
	__asm	fld x
	__asm	frndint
}

...

int fg = round(17.99);
При любом передаваемом параметре, всегда возвращает результат 4. Что к чему пока не могу понять.. может int заменить на double?