Re: класс Config
От: kov_serg Россия  
Дата: 15.01.19 20:57
Оценка: +4
Здравствуйте, Hard_Club, Вы писали:

H_C>переносим свой Python код на C++. У нас там был в

H_C>Python конфиг в котором константами задавалось (было порядка 30 параметров):

H_C>CPU_NUM = getenv("CPU_NUM", 3) # default


H_C>если ли в C++ какой-то рекомендуемый способ/либа для конфигов?

яд бы не заморачивался. если надо getenv сделайте себе getenv
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>

int getenv(const char* name,int defval) {
    long int val; char *end, *text=getenv(name);
    if (!text) return defval;
    val=strtol(text,&end,10);
    if (val==0 && errno) return defval;
    if (*end) return defval;
    if ((int)val!=val) return defval;
    return val;
}

Либо готовые есть в бусте
https://www.boost.org/doc/libs/1_53_0/doc/html/program_options.html
https://www.boost.org/doc/libs/1_48_0/doc/html/property_tree.html
Если алергия то
куча реализайций есть
например:
https://github.com/benhoyt/inih
на C есть glib и libargp
https://developer.gnome.org/glib/stable/glib-Key-value-file-parser.html
https://github.com/alexreg/libargp
класс Config
От: Hard_Club  
Дата: 15.01.19 17:17
Оценка:
переносим свой Python код на C++. У нас там был в
Python конфиг в котором константами задавалось (было порядка 30 параметров):

CPU_NUM = getenv("CPU_NUM", 3) # default

если ли в C++ какой-то рекомендуемый способ/либа для конфигов?
Re: класс Config
От: niXman Ниоткуда https://github.com/niXman
Дата: 15.01.19 19:16
Оценка:
есть такое: https://github.com/niXman/config-ctor

кстати идея CPU_NUM = getenv("CPU_NUM", 3) мне кажется достойной внимания! реализую-ка.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Отредактировано 15.01.2019 19:17 niXman . Предыдущая версия .
Re[2]: класс Config
От: vadfromnu  
Дата: 21.01.19 16:31
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>яд бы не заморачивался. если надо getenv сделайте себе getenv

_>
_>#include <stdio.h>
_>#include <errno.h>
_>#include <stdlib.h>

_>int getenv(const char* name,int defval) {
_>    long int val; char *end, *text=getenv(name);
_>    if (!text) return defval;
_>    val=strtol(text,&end,10);
_>    if (val==0 && errno) return defval;
_>    if (*end) return defval;
_>    if ((int)val!=val) return defval;
_>    return val;
_>}
_>


В функции прикопан баг, который когда-нибудь бахнет.(Я подрывался) strtol выставит errno при ошибке, но не сбросит его при успехе. Если errno уже выставлен кем-то ранее, то вместо 0 будет возвращаться defval.
Re[3]: класс Config
От: kov_serg Россия  
Дата: 21.01.19 17:20
Оценка:
Здравствуйте, vadfromnu, Вы писали:

V>В функции прикопан баг, который когда-нибудь бахнет.(Я подрывался) strtol выставит errno при ошибке, но не сбросит его при успехе. Если errno уже выставлен кем-то ранее, то вместо 0 будет возвращаться defval.


Действительно https://github.com/gcc-mirror/gcc/blob/master/libiberty/strtol.c
Тогда так:
#include <stdlib.h>

int getint(const char *p,int defval) {
    struct L{
        static int is_space(char c) { return c>0 && c<=32; }
        static int is_digit(char c) { return c>='0' && c<='9'; }
        static int dec(char c) { return (c>='0' && c<='9') ? c-'0' : -1; }
    };    
    int digit,val,t,minus=0;
    while(L::is_space(*p)) p++;
    if (*p=='-') { p++; minus=1; }
    if (!L::is_digit(*p)) return defval;
    for(val=0;(digit=L::dec(*p))>=0;p++){
        t=val*10+digit;
        if (t<val && t!=-t) return defval; // overflow
        val=t;
    }
    if (val && val==-val && !minus) return defval;  // special case
    if (minus) val=-val;
    while(L::is_space(*p)) p++;
    return *p ? defval : val;
}
int getenv(const char* name,int defval) {
    char *text=getenv(name);
    if (!text) return defval;
    return getint(text,defval);
}
Re[2]: класс Config
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 26.01.19 20:05
Оценка:
Здравствуйте, niXman, Вы писали:

X>есть такое: https://github.com/niXman/config-ctor


X>кстати идея CPU_NUM = getenv("CPU_NUM", 3) мне кажется достойной внимания! реализую-ка.


Плохая идея. Как обеспечить конфигурирование нескольких экземпляров приложения?

Из переменых окружения имхо стоит брать только переопределения зашитых дефолтных значений, не более того
Маньяк Робокряк колесит по городу
Re[4]: класс Config
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 26.01.19 20:11
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>Здравствуйте, vadfromnu, Вы писали:


V>>В функции прикопан баг, который когда-нибудь бахнет.(Я подрывался) strtol выставит errno при ошибке, но не сбросит его при успехе. Если errno уже выставлен кем-то ранее, то вместо 0 будет возвращаться defval.


_>Действительно https://github.com/gcc-mirror/gcc/blob/master/libiberty/strtol.c

_>Тогда так:

Сорян, что не по теме, но это выглядит, как говнокод. Строчки экономишь?


ЗЫ Моя версия, не факт, что рабочая — просто по-человечески переписал даденое. Да, в три раза длиннее получилось, если считать по строчкам
  Скрытый текст
#include <stdlib.h>

struct int_parsing_traits
{
    // Методы не упаковываем в одну строчку (хотя они очень просятся) чтобы можно было
    // остановится в отладчике и посмотреть одновременно на входной параметр, и на условие

    bool is_space(char c) const
    {
        return c>0 && c<=32;
    }

    bool is_digit(char c) const
    {
        return c>='0' && c<='9';
    }

    bool is_sign(char c) const
    {
        return c=='-' || c=='+';
    }

    bool is_negate_sign(char c) const
    {
        return c=='-';
    }

    int to_digit(char c) const
    {
        return (c>='0' && c<='9') ? c-'0' : -1;
    }

    // Решили, что системой счисления управляет ParsingTraits
    unsigned get_base() const
    {
        return 10;
    }

}; // struct int_parsing_traits



template<typename ParsingTraits>
inline
int getint( const char *p, int defval = 0, const ParsingTraits &parsingTraits = int_parsing_traits() )
{
    // skip leading whitespaces
    while( *p && parsingTraits.is_space(*p) )
        p++;

    // check for leading sign
    if (!parsingTraits.is_sign(*p))
        return defval;

    bool neg = false;

    // is negative number?
    if (parsingTraits.is_negate_sign(*p))
        neg = true;

    unsigned resultAbs = 0;

    while(*p && parsingTraits.is_digit(*p))
    {
        int digit = parsingTraits.to_digit();

        // Тут можно вставить проверку на систему счисления,
        // а можно положится, что ParsingTraits сама знает, что делает
        if (digit<0)
            break;

        // А тут мы уже точно решили, что ParsingTraits знает систему счисления
        unsigned newRes = resultAbs * parsingTraits.get_base() + (unsigned)digit;

        if (newRes<resultAbs)
            return defval; // переполнились

        resultAbs = newRes;

        p++;
    }

    // Пробегаем по оставшейся строке, надеясь, что она состоит из пробелов
    while(*p && parsingTraits.is_space(*p))
        ++p; 

    if ( *p && !parsingTraits.is_space(*p) )
        return defval; // стопанули на чём-то, не похожем на цифру или пробел

    int result = (int)resultAbs;

    if (neg)
        result = -result;

    if (unsigned(result)!=resultAbs)
        return defval; // переполнение при смене знака

    return result;
}
Маньяк Робокряк колесит по городу
Отредактировано 26.01.2019 21:06 Marty . Предыдущая версия .
Re[5]: класс Config
От: kov_serg Россия  
Дата: 26.01.19 21:39
Оценка:
Здравствуйте, Marty, Вы писали:

M>Сорян, что не по теме, но это выглядит, как говнокод. Строчки экономишь?

Если оно крякает как утака, и плавает как утка — возможно это и есть утка.
Я придерживался правила что демонстрационный код, должен умещаться на одном экране, его должно быть легко объяснить на пальцах.
Каждая строчка выполняет какое-то одно осмысленное действие. То что в С++ для отдельных осмысленных операций приходится писать много букв это издержки конкретного языка. Да и использование итератора строки с разными типами символов, экзотических кодировок и чудных систем исчисления типа 36#2QJBZ и другие гибкости в данном конкретном случае были бы излишними.
Re[3]: класс Config
От: kov_serg Россия  
Дата: 26.01.19 21:42
Оценка:
Здравствуйте, Marty, Вы писали:

M>Плохая идея. Как обеспечить конфигурирование нескольких экземпляров приложения?

# CPU_NUM=32 ./app &
# CPU_NUM=16 ./app &

M>Из переменых окружения имхо стоит брать только переопределения зашитых дефолтных значений, не более того

Ситуации бывают разные: зачем сразу ломать обратную совместимость?
Re[6]: класс Config
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 26.01.19 21:49
Оценка:
Здравствуйте, kov_serg, Вы писали:

M>>Сорян, что не по теме, но это выглядит, как говнокод. Строчки экономишь?

_>Если оно крякает как утака, и плавает как утка — возможно это и есть утка.

Ты наверное хотел сказать: "Если оно пачкает как говно, и плавает как говно — возможно это и есть говно"?


_>Я придерживался правила что демонстрационный код, должен умещаться на одном экране, его должно быть легко объяснить на пальцах.


Странное правило. Демонстрационный код должен быть понятен, это основное требование к нему.
Твой код выглядит так, как-будто вытащен из говнопроекта. И да, на пальцах там ничего не объяснить.

_>Каждая строчка выполняет какое-то одно осмысленное действие.


Не одно, а кучу.


_>То что в С++ для отдельных осмысленных операций приходится писать много букв это издержки конкретного языка.


Это не так. Ты просто видимо привык, что какой-то узкий спектр твоих задач хорошо покрывается средствами используемого тобой языка. Тебе повезло, что твой язык хорошо подходит под твои задачи


_>Да и использование итератора строки с разными типами символов, экзотических кодировок и чудных систем исчисления типа 36#2QJBZ и другие гибкости в данном конкретном случае были бы излишними.


Я об этом что-то говорил?
Маньяк Робокряк колесит по городу
Re[4]: класс Config
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 26.01.19 21:53
Оценка:
Здравствуйте, kov_serg, Вы писали:


M>>Плохая идея. Как обеспечить конфигурирование нескольких экземпляров приложения?

_># CPU_NUM=32 ./app &
_># CPU_NUM=16 ./app &

Непортируемо.


M>>Из переменых окружения имхо стоит брать только переопределения зашитых дефолтных значений, не более того

_>Ситуации бывают разные: зачем сразу ломать обратную совместимость?

Я предлагал что-то ломать?
Маньяк Робокряк колесит по городу
Re[7]: класс Config
От: kov_serg Россия  
Дата: 26.01.19 22:11
Оценка:
Здравствуйте, Marty, Вы писали:

M>Ты наверное хотел сказать: "Если оно пачкает как говно, и плавает как говно — возможно это и есть говно"?

Не нравиться не ешь. Я нигде не говорил что я являюсь образцом для подражания.

M>Странное правило. Демонстрационный код должен быть понятен, это основное требование к нему.

M>Твой код выглядит так, как-будто вытащен из говнопроекта. И да, на пальцах там ничего не объяснить.
Ты на свой посмотри "template inline"

_>>Каждая строчка выполняет какое-то одно осмысленное действие.

M>Не одно, а кучу.
И чему это противоречит? Если для осмысленного действия надо сделать кучу элементарных операций.

_>>То что в С++ для отдельных осмысленных операций приходится писать много букв это издержки конкретного языка.

M>Это не так.
Это очень даже так. Посмотри на темы которые обсуждаются в последнее время. Как правильно писать for — дожили

M>Ты просто видимо привык, что какой-то узкий спектр твоих задач хорошо покрывается средствами используемого тобой языка.

Грусть печаль, спектр моих задач не покрывается одними только языками и программированием.

M>Тебе повезло, что твой язык хорошо подходит под твои задачи

Да я везучий
Re[8]: класс Config
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 26.01.19 22:28
Оценка:
Здравствуйте, kov_serg, Вы писали:

M>>Твой код выглядит так, как-будто вытащен из говнопроекта. И да, на пальцах там ничего не объяснить.

_>Ты на свой посмотри "template inline"

А что не так?
Маньяк Робокряк колесит по городу
Re[9]: класс Config
От: kov_serg Россия  
Дата: 26.01.19 23:06
Оценка:
Здравствуйте, Marty, Вы писали:

M>>>Твой код выглядит так, как-будто вытащен из говнопроекта. И да, на пальцах там ничего не объяснить.

_>>Ты на свой посмотри "template inline"

M>А что не так?

  да всё зашибись просто на надо было constexpr и __forceinline для шаблона то иначе не айс
Если бы не использовл C с классами, а хотя бы C++11 то написал бы как-то так:
#include <string>
#include <cstdlib>

int getenv(const char* name,int defval) {
  try {
    return std::stoi(std::getenv(name));
  } catch(...) {
    return defval;
  }
}
Re[10]: класс Config
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 26.01.19 23:14
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>Здравствуйте, Marty, Вы писали:


M>>>>Твой код выглядит так, как-будто вытащен из говнопроекта. И да, на пальцах там ничего не объяснить.

_>>>Ты на свой посмотри "template inline"

M>>А что не так?

_>[cut=да всё зашибись просто на надо было constexpr и __forceinline для шаблона то иначе не айс]
_>Если бы не использовл C с классами, а хотя бы C++11 то написал бы как-то так:

Не пойму что ты хочешь сказать. Я просто переписал твой код нормально, не более того.
Маньяк Робокряк колесит по городу
Re[11]: класс Config
От: kov_serg Россия  
Дата: 26.01.19 23:26
Оценка:
Здравствуйте, Marty, Вы писали:

M>Не пойму что ты хочешь сказать. Я просто переписал твой код нормально, не более того.

Зачем?
Re[12]: класс Config
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 26.01.19 23:28
Оценка:
Здравствуйте, kov_serg, Вы писали:

M>>Не пойму что ты хочешь сказать. Я просто переписал твой код нормально, не более того.

_>Зачем?

Чтобы показать, насколько по-разному можно написать одно и то же
Маньяк Робокряк колесит по городу
Re[13]: класс Config
От: kov_serg Россия  
Дата: 26.01.19 23:32
Оценка:
Здравствуйте, Marty, Вы писали:

M>>>Не пойму что ты хочешь сказать. Я просто переписал твой код нормально, не более того.

_>>Зачем?

M>Чтобы показать, насколько по-разному можно написать одно и то же

Я рад за вас. У вас всё получилось.

Другой вопрос: Как бы вы написали функцию расчета объёма тетраидера у которого известны все 6 сторон на С++?
Re[14]: класс Config
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 26.01.19 23:38
Оценка:
Здравствуйте, kov_serg, Вы писали:

M>>Чтобы показать, насколько по-разному можно написать одно и то же

_>Я рад за вас. У вас всё получилось.

_>Другой вопрос: Как бы вы написали функцию расчета объёма тетраидера у которого известны все 6 сторон на С++?


Для начала бы уточнил ТЗ и узнал бы, что подразумевается по термином "тетраидер"
Маньяк Робокряк колесит по городу
Re[15]: класс Config
От: kov_serg Россия  
Дата: 27.01.19 07:56
Оценка:
Здравствуйте, Marty, Вы писали:

M>Для начала бы уточнил ТЗ и узнал бы, что подразумевается по термином "тетраидер"

Одна точка над треугольником соединяется 3 сторонами с вершинами треугольника.
Известные 3 стороны треугольника a,b,c и длины ea,eb,ec (ea напротив a, eb напротив b, ec напротив c)
Re[16]: класс Config
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 27.01.19 13:06
Оценка:
Здравствуйте, kov_serg, Вы писали:

M>>Для начала бы уточнил ТЗ и узнал бы, что подразумевается по термином "тетраидер"

_>Одна точка над треугольником соединяется 3 сторонами с вершинами треугольника.
_>Известные 3 стороны треугольника a,b,c и длины ea,eb,ec (ea напротив a, eb напротив b, ec напротив c)
_>Image: 254px-Tetrahedron.gif

Сколько дашь?
Маньяк Робокряк колесит по городу
Re[17]: класс Config
От: kov_serg Россия  
Дата: 27.01.19 14:55
Оценка:
Здравствуйте, Marty, Вы писали:

M>Сколько дашь?


#include <math.h>

struct tetrahedron {
    double a,b,c,ea,eb,ec;
    double volume() const {
        double A=a*a, B=b*b, C=c*c, X=B+C-ea*ea, Y=A+C-eb*eb, Z=A+B-ec*ec;
        return sqrt(4*A*B*C-A*X*X-B*Y*Y-C*Z*Z+X*Y*Z)/12;
    }
};

#include <stdio.h>

int main(int argc,char** argv) {
    tetrahedron t;
    t.a=1;  t.b=1;  t.c=1;
    t.ea=1; t.eb=1; t.ec=1;
    double V=t.volume(), V0=sqrt(2)/12;
    printf("V=%.5f (%.5f)\n",V,V0);
    return 0;
}
Отредактировано 27.01.2019 16:55 kov_serg . Предыдущая версия .
Re[18]: класс Config
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 27.01.19 21:26
Оценка:
Здравствуйте, kov_serg, Вы писали:

M>>Сколько дашь?


_>
_>#include <math.h>

_>struct tetrahedron {
_>    double a,b,c,ea,eb,ec;
_>    double volume() const {
_>        double A=a*a, B=b*b, C=c*c, X=B+C-ea*ea, Y=A+C-eb*eb, Z=A+B-ec*ec;
_>        return sqrt(4*A*B*C-A*X*X-B*Y*Y-C*Z*Z+X*Y*Z)/12;
_>    }
_>};

_>#include <stdio.h>

_>int main(int argc,char** argv) {
_>    tetrahedron t;
_>    t.a=1;  t.b=1;  t.c=1;
_>    t.ea=1; t.eb=1; t.ec=1;
_>    double V=t.volume(), V0=sqrt(2)/12;
_>    printf("V=%.5f (%.5f)\n",V,V0);
_>    return 0;
_>}
_>



Ок, ты мне что-то доказал. Заодно, похоже, научившись приводить код в читаемый вид
Маньяк Робокряк колесит по городу
Re[19]: класс Config
От: kov_serg Россия  
Дата: 27.01.19 22:12
Оценка:
Здравствуйте, Marty, Вы писали:

_>>for(val=0;(digit=L::dec(*p))>=0;p++){
_>>    t=val*10+digit;
_>>    if (t<val && t!=-t) return defval; // overflow
_>>    val=t;
_>>}

_>>    tetrahedron t;
_>>    t.a=1;  t.b=1;  t.c=1;
_>>    t.ea=1; t.eb=1; t.ec=1;
_>>    double V=t.volume();

M> научившись приводить код в читаемый вид

И чем он лучше, тут также на одной строчке несколько действий, но теперь он вдруг читаемый.

http://format.krzaq.cc
Re[20]: класс Config
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 29.01.19 18:08
Оценка:
Здравствуйте, kov_serg, Вы писали:

M>> научившись приводить код в читаемый вид


_>И чем он лучше,


Ну, это не простыня, которая была до правки


_>тут также на одной строчке несколько действий, но теперь он вдруг читаемый.


Так-то тоже говнецо, но за счет того, гавнецо размазано тонюсенькочто кода совсем чуть чуть — это терпимо
Маньяк Робокряк колесит по городу
Re[21]: класс Config
От: kov_serg Россия  
Дата: 29.01.19 20:33
Оценка:
Здравствуйте, Marty, Вы писали:

M>Так-то тоже говнецо, но за счет того, гавнецо размазано тонюсенькочто кода совсем чуть чуть — это терпимо


  Насладитесь прекрасным:
https://www.youtube.com/watch?v=N9uSr-8FJ2M&amp;t=182

                                            
      subroutine quart(n,c,r4,jj,mm)                                    
c        use the procedure of la-4299 to solve the quartic equation     
c           x**4+b*x**3+c*x**2+d*x+e=0  (c(i),i=1,5)=1,b,c,d,e          
c        the jj real roots are returned in r4.  the roots with odd      
c        multiplicity are listed first, in ascending order.  if mm=0,   
c        the roots with even multiplicity are omitted.                  
      implicit double precision (a-h,o-z)                               
      dimension c(5),r4(4),tp(16)                                       
      parameter (pf=(2.*3.1415926535898d0)/3.,th=1d0/3.)                
c                                                                       
      jj=0                                                              
      if(n.eq.3)go to 90                                                
c                                                                       
c        let y=x+b/4 to reduce the quartic equation to                  
c          y**4+q*y**2+r*y+s=0  (tp(i),i=1,5)=b/2,b/4,q,r,s             
      tp(1)=.5*c(2)                                                     
      tp(2)=.25*c(2)                                                    
      tp(3)=c(3)-1.5*tp(1)**2                                           
      tp(4)=c(4)+tp(1)*(tp(1)**2-c(3))                                  
      tp(5)=c(5)-.0625*tp(1)*(5.*c(4)-c(3)*tp(1)+3.*tp(4))              
c                                                                       
c        steps 2-7 (la-4299) (tp(i),i=6,11)=b/3,c,d,p/3,q/2,w           
      if(abs(tp(4)).le.1.e-10*max(abs(c(4)),tp(1)**2,abs(tp(1)*c(3))))  
     1 go to 40                                                         
      tp(6)=2.*th*tp(3)                                                 
      tp(7)=tp(3)**2-4.*tp(5)                                           
      tp(8)=-tp(4)**2                                                   
      tp(9)=th*tp(7)-tp(6)**2                                           
      tp(10)=.5*(tp(8)-tp(6)*(tp(7)-2.*tp(6)**2))                       
      tp(11)=tp(9)**3+tp(10)**2                                         
      if(abs(tp(11)).le.1.e-10*max(abs(tp(9)**3),tp(10)**2))go to 10    
      if(tp(11).gt.0.)go to 30                                          
      tp(12)=sqrt(-tp(9))                                               
      if(tp(6).ge.0..or.tp(7).le.0.)return                              
      tp(13)=-tp(10)/tp(12)**3                                          
      if(abs(tp(13)).ge.1.)go to 10                                     
      tp(13)=acos(tp(13))                                               
      tp(14)=2.*tp(12)*cos(th*tp(13))-tp(6)                             
      if(tp(14).lt.1.e-10*abs(tp(6)))go to 40                           
      tp(15)=.5*sqrt(tp(14))                                            
      tp(14)=-tp(14)-3.*tp(6)                                           
      tp(16)=tp(4)/tp(15)                                               
      if(abs(tp(16)).ge.tp(14))go to 10                                 
      jj=4                                                              
      tp(13)=.5*sqrt(tp(14)+tp(16))                                     
      r4(1)=-tp(13)-tp(15)-tp(2)                                        
      r4(2)=tp(13)-tp(15)-tp(2)                                         
      tp(13)=.5*sqrt(tp(14)-tp(16))                                     
      r4(3)=tp(15)-tp(13)-tp(2)                                         
      r4(4)=tp(15)+tp(13)-tp(2)                                         
      return                                                            
c                                                                       
c        steps 8-11 (la-4299) double or triple roots.                   
   10 tp(12)=sign(sqrt(abs(tp(9))),tp(10))                              
      tp(13)=-2.*tp(12)-tp(6)                                           
      tp(14)=tp(12)-tp(6)                                               
      tp(15)=sign(.5*sqrt(abs(tp(13))),tp(4))                           
      if(tp(14).le.0.)go to 20                                          
      tp(16)=sqrt(tp(14))                                               
      jj=2                                                              
      r4(1)=-tp(15)-tp(2)-tp(16)                                        
      r4(2)=tp(16)-tp(15)-tp(2)                                         
      if(mm.eq.0)return                                                 
      if(tp(10).eq.0.)return                                            
      jj=3                                                              
      r4(3)=tp(15)-tp(2)                                                
      return                                                            
   20 if(mm.eq.0)return                                                 
      jj=1                                                              
      r4(1)=-tp(15)-tp(2)                                               
      return                                                            
c                                                                       
c        step 12 (la-4299)                                              
   30 tp(12)=-tp(10)-sign(sqrt(tp(11)),tp(10))                          
      tp(12)=sign(abs(tp(12))**th,tp(12))                               
      tp(14)=tp(12)-tp(9)/tp(12)-tp(6)                                  
      if(tp(14).lt.1.e-10*abs(tp(6)))go to 40                           
      tp(15)=.5*sign(sqrt(tp(14)),tp(4))                                
      tp(16)=abs(tp(4)/tp(15))-tp(14)-3.*tp(6)                          
      if(tp(16).le.0.)return                                            
      tp(16)=.5*sqrt(tp(16))                                            
      jj=2                                                              
      r4(1)=-tp(16)-tp(15)-tp(2)                                        
      r4(2)=tp(16)-tp(15)-tp(2)                                         
      return                                                            
c                                                                       
c        steps 13-24 (la-4299) trivial case; r=tp(4)=0                  
   40 tp(6)=.5*tp(3)                                                    
      tp(7)=tp(6)**2-tp(5)                                              
      tp(9)=1.e-8*max(tp(6)**2,abs(tp(5)))                              
      if(tp(7).le.tp(9))go to 60                                        
      tp(8)=sqrt(tp(7))                                                 
      tp(16)=tp(8)-tp(6)                                                
      if(tp(16).le.0.)go to 70                                          
      tp(15)=-tp(6)-tp(8)                                               
      tp(16)=sqrt(tp(16))                                               
      if(tp(15).gt.0.)go to 50                                          
      jj=2                                                              
      r4(1)=-tp(16)-tp(2)                                               
      r4(2)=tp(16)-tp(2)                                                
      if(mm.eq.0)return                                                 
      if(tp(15).ne.0.)return                                            
      jj=3                                                              
      r4(3)=-tp(2)                                                      
      return                                                            
   50 tp(15)=sqrt(tp(15))                                               
      jj=4                                                              
      r4(1)=-tp(16)-tp(2)                                               
      r4(2)=-tp(15)-tp(2)                                               
      r4(3)=tp(15)-tp(2)                                                
      r4(4)=tp(16)-tp(2)                                                
      return                                                            
   60 if(mm.eq.0)return                                                 
      if(tp(7).lt.-tp(9).or.tp(6).gt.0.)return                          
      if(tp(6).eq.0.)go to 80                                           
      jj=2                                                              
      tp(16)=sqrt(-tp(6))                                               
      r4(1)=tp(16)-tp(2)                                                
      r4(2)=-tp(16)-tp(2)                                               
      return                                                            
   70 if(mm.eq.0)return                                                 
      if(tp(16).lt.0.)return                                            
   80 jj=1                                                              
      r4(1)=-tp(2)                                                      
      return                                                            
c                                                                       
c        cubic equation.  x**3+b*x**2+c*x+d=0  (c(i),i=1,4)=1,b,c,d     
c        let y=x+b/3.  then  y**3+p*y+q=0   (tp(i),i=1,4)=b/3,p/3,q/2,w 
   90 tp(1)=th*c(2)                                                     
      tp(2)=th*c(3)-tp(1)**2                                            
      tp(3)=.5*(c(4)-tp(1)*(c(3)-2.*tp(1)**2))                          
      tp(4)=tp(2)**3+tp(3)**2                                           
      if(tp(4).gt.0.)go to 110                                          
      if(tp(4).eq.0.)go to 100                                          
c                                                                       
c        case i (la-4299)  3 distinct roots                             
      tp(5)=2.*sqrt(-tp(2))                                             
      tp(6)=8.*tp(3)/tp(5)**3                                           
      if(abs(tp(6)).ge.1.)go to 100                                     
      tp(7)=th*acos(-tp(6))                                             
      r4(1)=tp(5)*cos(pf+tp(7))-tp(1)                                   
      r4(2)=tp(5)*cos(pf-tp(7))-tp(1)                                   
      r4(3)=tp(5)*cos(tp(7))-tp(1)                                      
      jj=3                                                              
      return                                                            
c                                                                       
c        case ii (la-4299) 1 distinct and 1 double root                 
  100 r4(1)=-2.*sign(sqrt(-tp(2)),tp(3))-tp(1)                          
      jj=1                                                              
      if(mm.eq.0)return                                                 
      if(r4(1).eq.0.)return                                             
      jj=2                                                              
      r4(2)=-.5*r4(1)                                                   
      return                                                            
c                                                                       
c        case iii (la-4299)  1 distinct root                            
  110 tp(5)=-tp(3)-sign(sqrt(tp(4)),tp(3))                              
      tp(5)=sign(abs(tp(5))**th,tp(5))                                  
      r4(1)=tp(5)-tp(2)/tp(5)-tp(1)                                     
      jj=1                                                              
      return                                                            
      end
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.